From 4dbed5f6d4fd0e9ffa797e3b1b5d0ae479e7e6c5 Mon Sep 17 00:00:00 2001 From: Richard Guenther Date: Tue, 30 Nov 2010 16:55:35 +0000 Subject: re PR tree-optimization/46722 (Missed fma for x*x + y) 2010-11-30 Richard Guenther 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. From-SVN: r167304 --- gcc/tree-ssa-math-opts.c | 54 ++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 43 insertions(+), 11 deletions(-) (limited to 'gcc/tree-ssa-math-opts.c') diff --git a/gcc/tree-ssa-math-opts.c b/gcc/tree-ssa-math-opts.c index 7837161..435c014 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 -- cgit v1.1