diff --git a/gcc/ChangeLog b/gcc/ChangeLog index b01aa11f41a..751668f29c3 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,13 @@ +2005-08-09 Steven Bosscher + + PR tree-optimization/23234 + * tree-ssa-math-opts.c (place_reciprocal): New enum. + (execute_cse_reciprocals_1): Replace the 'phi' argument with an + argument of the new enum. + (execute_cse_reciprocals): Add reciprocals for function arguments + on the unique successor edge of the entry block. Update other calls + to execute_cse_reciprocals_1. + 2005-08-08 Richard Henderson PR 22439 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index c45105e2134..57681cd9035 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2005-08-09 Stevem Bosscher + + PR tree-optimization/23234 + * gcc.dg/tree-ssa/pr23234.c: New test. + 2005-08-08 Josh Conner PR rtl-optimization/23241 diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr23234.c b/gcc/testsuite/gcc.dg/tree-ssa/pr23234.c new file mode 100644 index 00000000000..bd0b62b558f --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr23234.c @@ -0,0 +1,52 @@ +/* The problem in this PR was mostly finding a suitable place to insert + the reciprocals of the function arguments. This test case tries to + test three possible ways of how this may go wrong. */ +/* { dg-options "-O2 -ffast-math" } */ +/* { dg-do compile } */ + +/* The original test case. */ +double +f1 (double a, double b, double c) +{ + double y0; + + if (a == 0.0) + { + y0 = -c / b; + return y0; + } + y0 = c / b; + return y0; +} + +/* Labels may end up in the middle of a block. Also bad. */ +double +f2 (double a, double b, double c) +{ + double y0; + +a_label: +another_label: + if (a == 0.0) + { + y0 = -c / b; + return y0; + } + y0 = c / b; + return y0; +} + +/* Uses must still be dominated by their defs. */ +double +f3 (double a, double b, double c) +{ + double y0; + + y0 = -c / b; + if (a == 0.0) + { + return y0; + } + y0 = c / b; + return y0; +} diff --git a/gcc/tree-ssa-math-opts.c b/gcc/tree-ssa-math-opts.c index be2d75840fd..456043fc3f4 100644 --- a/gcc/tree-ssa-math-opts.c +++ b/gcc/tree-ssa-math-opts.c @@ -54,16 +54,25 @@ gate_cse_reciprocals (void) return optimize && !optimize_size && flag_unsafe_math_optimizations; } +/* Where to put the statement computing a reciprocal. */ +enum place_reciprocal +{ + PR_BEFORE_BSI, /* Put it using bsi_insert_before. */ + PR_AFTER_BSI, /* Put it using bsi_insert_after. */ + PR_ON_ENTRY_EDGE /* Put it on the edge between the entry + and the first basic block. */ +}; + /* Check if DEF's uses include more than one floating-point division, - and if so replace them by multiplications with the reciprocal. If - PHI is true, insert the reciprocal calculation before BSI, otherwise - insert it after and move BSI to the new statement. + and if so replace them by multiplications with the reciprocal. Add + the statement computing the reciprocal according to WHERE. Does not check the type of DEF, nor that DEF is a GIMPLE register. This is done in the caller for speed, because otherwise this routine would be called for every definition and phi node. */ static void -execute_cse_reciprocals_1 (block_stmt_iterator *bsi, tree def, bool phi) +execute_cse_reciprocals_1 (block_stmt_iterator *bsi, tree def, + enum place_reciprocal where) { use_operand_p use_p; imm_use_iterator use_iter; @@ -99,10 +108,14 @@ execute_cse_reciprocals_1 (block_stmt_iterator *bsi, tree def, bool phi) fold_build2 (RDIV_EXPR, type, build_real (type, dconst1), def)); - if (phi) + if (where == PR_BEFORE_BSI) bsi_insert_before (bsi, new_stmt, BSI_SAME_STMT); - else + else if (where == PR_AFTER_BSI) bsi_insert_after (bsi, new_stmt, BSI_NEW_STMT); + else if (where == PR_ON_ENTRY_EDGE) + bsi_insert_on_edge (single_succ_edge (ENTRY_BLOCK_PTR), new_stmt); + else + gcc_unreachable (); FOR_EACH_IMM_USE_SAFE (use_p, use_iter, def) { @@ -133,7 +146,8 @@ execute_cse_reciprocals (void) { block_stmt_iterator bsi; bsi = bsi_start (single_succ (ENTRY_BLOCK_PTR)); - execute_cse_reciprocals_1 (&bsi, default_def (arg), false); + execute_cse_reciprocals_1 (&bsi, default_def (arg), + PR_ON_ENTRY_EDGE); } FOR_EACH_BB (bb) @@ -150,7 +164,7 @@ execute_cse_reciprocals (void) def = PHI_RESULT (phi); if (FLOAT_TYPE_P (TREE_TYPE (def)) && is_gimple_reg (def)) - execute_cse_reciprocals_1 (&bsi, def, true); + execute_cse_reciprocals_1 (&bsi, def, PR_BEFORE_BSI); } for (; !bsi_end_p (bsi); bsi_next (&bsi)) @@ -160,12 +174,15 @@ execute_cse_reciprocals (void) && (def = SINGLE_SSA_TREE_OPERAND (stmt, SSA_OP_DEF)) != NULL && FLOAT_TYPE_P (TREE_TYPE (def)) && TREE_CODE (def) == SSA_NAME) - execute_cse_reciprocals_1 (&bsi, def, false); + execute_cse_reciprocals_1 (&bsi, def, PR_AFTER_BSI); } } if (flag_trapping_math) free_dominance_info (CDI_POST_DOMINATORS); + + if (single_succ_p (ENTRY_BLOCK_PTR)) + bsi_commit_one_edge_insert (single_succ_edge (ENTRY_BLOCK_PTR), NULL); } struct tree_opt_pass pass_cse_reciprocals =