diff options
author | rguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4> | 2010-11-30 16:55:35 +0000 |
---|---|---|
committer | rguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4> | 2010-11-30 16:55:35 +0000 |
commit | 15dbdc8f645ffd08ce1ac17fedf27556a0b70260 (patch) | |
tree | e61a7127cbad42be966353a6abec621a1e9d38ed /gcc/tree-ssa-math-opts.c | |
parent | 5930a293fc0b3e48968f142ff03d2deb6dfd4cea (diff) | |
download | gcc-15dbdc8f645ffd08ce1ac17fedf27556a0b70260.tar.gz |
2010-11-30 Richard Guenther <rguenther@suse.de>
PR tree-optimization/46722
* tree-ssa-math-opts.c (convert_mult_to_fma): Get multiplication
operands as arguments.
(execute_optimize_widening_mul): Also handle power of two as
multiplication.
* gcc.target/i386/fma4-fma-2.c: New testcase.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@167304 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/tree-ssa-math-opts.c')
-rw-r--r-- | gcc/tree-ssa-math-opts.c | 54 |
1 files changed, 43 insertions, 11 deletions
diff --git a/gcc/tree-ssa-math-opts.c b/gcc/tree-ssa-math-opts.c index 7837161e440..435c014ea7c 100644 --- a/gcc/tree-ssa-math-opts.c +++ b/gcc/tree-ssa-math-opts.c @@ -1494,14 +1494,14 @@ convert_plusminus_to_widen (gimple_stmt_iterator *gsi, gimple stmt, return true; } -/* Combine the multiplication at MUL_STMT with uses in additions and - subtractions to form fused multiply-add operations. Returns true - if successful and MUL_STMT should be removed. */ +/* 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. */ static bool -convert_mult_to_fma (gimple mul_stmt) +convert_mult_to_fma (gimple mul_stmt, tree op1, tree op2) { - tree mul_result = gimple_assign_lhs (mul_stmt); + tree mul_result = gimple_get_lhs (mul_stmt); tree type = TREE_TYPE (mul_result); gimple use_stmt, neguse_stmt, fma_stmt; use_operand_p use_p; @@ -1607,7 +1607,7 @@ convert_mult_to_fma (gimple mul_stmt) { gimple_stmt_iterator gsi = gsi_for_stmt (use_stmt); enum tree_code use_code; - tree addop, mulop1, result = mul_result; + tree addop, mulop1 = op1, result = mul_result; bool negate_p = false; if (is_gimple_debug (use_stmt)) @@ -1646,7 +1646,6 @@ convert_mult_to_fma (gimple mul_stmt) negate_p = !negate_p; } - mulop1 = gimple_assign_rhs1 (mul_stmt); if (negate_p) mulop1 = force_gimple_operand_gsi (&gsi, build1 (NEGATE_EXPR, @@ -1656,8 +1655,7 @@ convert_mult_to_fma (gimple mul_stmt) fma_stmt = gimple_build_assign_with_ops3 (FMA_EXPR, gimple_assign_lhs (use_stmt), - mulop1, - gimple_assign_rhs2 (mul_stmt), + mulop1, op2, addop); gsi_replace (&gsi, fma_stmt, true); } @@ -1673,6 +1671,7 @@ static unsigned int execute_optimize_widening_mul (void) { basic_block bb; + bool cfg_changed = false; FOR_EACH_BB (bb) { @@ -1690,7 +1689,9 @@ execute_optimize_widening_mul (void) { case MULT_EXPR: if (!convert_mult_to_widen (stmt) - && convert_mult_to_fma (stmt)) + && convert_mult_to_fma (stmt, + gimple_assign_rhs1 (stmt), + gimple_assign_rhs2 (stmt))) { gsi_remove (&gsi, true); release_defs (stmt); @@ -1706,11 +1707,42 @@ execute_optimize_widening_mul (void) default:; } } + else if (is_gimple_call (stmt)) + { + tree fndecl = gimple_call_fndecl (stmt); + if (fndecl + && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL) + { + switch (DECL_FUNCTION_CODE (fndecl)) + { + case BUILT_IN_POWF: + case BUILT_IN_POW: + case BUILT_IN_POWL: + if (TREE_CODE (gimple_call_arg (stmt, 1)) == REAL_CST + && REAL_VALUES_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))) + { + gsi_remove (&gsi, true); + release_defs (stmt); + if (gimple_purge_dead_eh_edges (bb)) + cfg_changed = true; + continue; + } + break; + + default:; + } + } + } gsi_next (&gsi); } } - return 0; + return cfg_changed ? TODO_cleanup_cfg : 0; } static bool |