diff options
Diffstat (limited to 'gcc/tree-ssa-math-opts.c')
-rw-r--r-- | gcc/tree-ssa-math-opts.c | 71 |
1 files changed, 43 insertions, 28 deletions
diff --git a/gcc/tree-ssa-math-opts.c b/gcc/tree-ssa-math-opts.c index b7bbde4..3e0b238 100644 --- a/gcc/tree-ssa-math-opts.c +++ b/gcc/tree-ssa-math-opts.c @@ -3044,6 +3044,8 @@ last_fma_candidate_feeds_initial_phi (fma_deferring_state *state, /* Combine the multiplication at MUL_STMT with operands MULOP1 and MULOP2 with uses in additions and subtractions to form fused multiply-add operations. Returns true if successful and MUL_STMT should be removed. + If MUL_COND is nonnull, the multiplication in MUL_STMT is conditional + on MUL_COND, otherwise it is unconditional. If STATE indicates that we are deferring FMA transformation, that means that we do not produce FMAs for basic blocks which look like: @@ -3060,7 +3062,7 @@ last_fma_candidate_feeds_initial_phi (fma_deferring_state *state, static bool convert_mult_to_fma (gimple *mul_stmt, tree op1, tree op2, - fma_deferring_state *state) + fma_deferring_state *state, tree mul_cond = NULL_TREE) { tree mul_result = gimple_get_lhs (mul_stmt); tree type = TREE_TYPE (mul_result); @@ -3174,6 +3176,9 @@ convert_mult_to_fma (gimple *mul_stmt, tree op1, tree op2, return false; } + if (mul_cond && cond != mul_cond) + return false; + if (cond) { if (cond == result || else_value == result) @@ -3785,38 +3790,48 @@ math_opts_dom_walker::after_dom_children (basic_block bb) } else if (is_gimple_call (stmt)) { - tree fndecl = gimple_call_fndecl (stmt); - if (fndecl && gimple_call_builtin_p (stmt, BUILT_IN_NORMAL)) + switch (gimple_call_combined_fn (stmt)) { - switch (DECL_FUNCTION_CODE (fndecl)) + CASE_CFN_POW: + if (gimple_call_lhs (stmt) + && TREE_CODE (gimple_call_arg (stmt, 1)) == REAL_CST + && real_equal (&TREE_REAL_CST (gimple_call_arg (stmt, 1)), + &dconst2) + && convert_mult_to_fma (stmt, + gimple_call_arg (stmt, 0), + gimple_call_arg (stmt, 0), + &fma_state)) { - case BUILT_IN_POWF: - case BUILT_IN_POW: - case BUILT_IN_POWL: - if (gimple_call_lhs (stmt) - && TREE_CODE (gimple_call_arg (stmt, 1)) == REAL_CST - && real_equal - (&TREE_REAL_CST (gimple_call_arg (stmt, 1)), - &dconst2) - && convert_mult_to_fma (stmt, - gimple_call_arg (stmt, 0), - gimple_call_arg (stmt, 0), - &fma_state)) - { - unlink_stmt_vdef (stmt); - if (gsi_remove (&gsi, true) - && gimple_purge_dead_eh_edges (bb)) - *m_cfg_changed_p = true; - release_defs (stmt); - continue; - } - break; + unlink_stmt_vdef (stmt); + if (gsi_remove (&gsi, true) + && gimple_purge_dead_eh_edges (bb)) + *m_cfg_changed_p = true; + release_defs (stmt); + continue; + } + break; - default:; + case CFN_COND_MUL: + if (convert_mult_to_fma (stmt, + gimple_call_arg (stmt, 1), + gimple_call_arg (stmt, 2), + &fma_state, + gimple_call_arg (stmt, 0))) + + { + gsi_remove (&gsi, true); + release_defs (stmt); + continue; } + break; + + case CFN_LAST: + cancel_fma_deferring (&fma_state); + break; + + default: + break; } - else - cancel_fma_deferring (&fma_state); } gsi_next (&gsi); } |