From 6e0b633f6c2b88355a66d77c956367730e67f783 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Tue, 14 Nov 2006 08:46:26 +0000 Subject: [PATCH] re PR rtl-optimization/29798 (-O2 gives wrong results) 2006-11-14 Paolo Bonzini PR rtl-optimization/29798 * fwprop.c (use_killed_between): Check that DEF_INSN dominates TARGET_INSN before any other check. (fwprop_init): Always calculate dominators. (fwprop_done): Always free them. 2006-11-14 Paolo Bonzini PR rtl-optimization/29798 * gcc.c-torture/execute/pr29798.c: New. From-SVN: r118808 --- gcc/ChangeLog | 9 +++++ gcc/fwprop.c | 39 +++++++++---------- gcc/testsuite/ChangeLog | 6 +++ gcc/testsuite/gcc.c-torture/execute/pr29798.c | 26 +++++++++++++ 4 files changed, 59 insertions(+), 21 deletions(-) create mode 100644 gcc/testsuite/gcc.c-torture/execute/pr29798.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 69f6627cf68..d1f36dfa6b7 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2006-11-14 Paolo Bonzini + + PR rtl-optimization/29798 + + * fwprop.c (use_killed_between): Check that DEF_INSN dominates + TARGET_INSN before any other check. + (fwprop_init): Always calculate dominators. + (fwprop_done): Always free them. + 2006-11-14 Kaveh R. Ghazi * fold-const.c (fold_strip_sign_ops): Handle COMPOUND_EXPR and diff --git a/gcc/fwprop.c b/gcc/fwprop.c index 1e4f749eb12..fb601e1a4f0 100644 --- a/gcc/fwprop.c +++ b/gcc/fwprop.c @@ -466,10 +466,22 @@ local_ref_killed_between_p (struct df_ref * ref, rtx from, rtx to) static bool use_killed_between (struct df_ref *use, rtx def_insn, rtx target_insn) { - basic_block def_bb, target_bb; + basic_block def_bb = BLOCK_FOR_INSN (def_insn); + basic_block target_bb = BLOCK_FOR_INSN (target_insn); int regno; struct df_ref * def; + /* In some obscure situations we can have a def reaching a use + that is _before_ the def. In other words the def does not + dominate the use even though the use and def are in the same + basic block. This can happen when a register may be used + uninitialized in a loop. In such cases, we must assume that + DEF is not available. */ + if (def_bb == target_bb + ? DF_INSN_LUID (df, def_insn) >= DF_INSN_LUID (df, target_insn) + : !dominated_by_p (CDI_DOMINATORS, target_bb, def_bb)) + return true; + /* Check if the reg in USE has only one definition. We already know that this definition reaches use, or we wouldn't be here. */ regno = DF_REF_REGNO (use); @@ -477,22 +489,9 @@ use_killed_between (struct df_ref *use, rtx def_insn, rtx target_insn) if (def && (def->next_reg == NULL)) return false; - /* Check if we are in the same basic block. */ - def_bb = BLOCK_FOR_INSN (def_insn); - target_bb = BLOCK_FOR_INSN (target_insn); + /* Check locally if we are in the same basic block. */ if (def_bb == target_bb) - { - /* In some obscure situations we can have a def reaching a use - that is _before_ the def. In other words the def does not - dominate the use even though the use and def are in the same - basic block. This can happen when a register may be used - uninitialized in a loop. In such cases, we must assume that - DEF is not available. */ - if (DF_INSN_LUID (df, def_insn) >= DF_INSN_LUID (df, target_insn)) - return true; - - return local_ref_killed_between_p (use, def_insn, target_insn); - } + return local_ref_killed_between_p (use, def_insn, target_insn); /* Finally, if DEF_BB is the sole predecessor of TARGET_BB. */ if (single_pred_p (target_bb) @@ -890,16 +889,14 @@ static void fwprop_init (void) { num_changes = 0; + calculate_dominance_info (CDI_DOMINATORS); /* We do not always want to propagate into loops, so we have to find loops and be careful about them. But we have to call flow_loops_find before df_analyze, because flow_loops_find may introduce new jump insns (sadly) if we are not working in cfglayout mode. */ if (flag_rerun_cse_after_loop && (flag_unroll_loops || flag_peel_loops)) - { - calculate_dominance_info (CDI_DOMINATORS); - flow_loops_find (&loops); - } + flow_loops_find (&loops); /* Now set up the dataflow problem (we only want use-def chains) and put the dataflow solver to work. */ @@ -917,10 +914,10 @@ fwprop_done (void) if (flag_rerun_cse_after_loop && (flag_unroll_loops || flag_peel_loops)) { flow_loops_free (&loops); - free_dominance_info (CDI_DOMINATORS); loops.num = 0; } + free_dominance_info (CDI_DOMINATORS); cleanup_cfg (0); delete_trivially_dead_insns (get_insns (), max_reg_num ()); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 370620b3cbb..9693e4da1aa 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2006-11-14 Paolo Bonzini + + PR rtl-optimization/29798 + + * gcc.c-torture/execute/pr29798.c: New. + 2006-11-14 Kaveh R. Ghazi * gcc.dg/builtins-20.c: Add more cases. diff --git a/gcc/testsuite/gcc.c-torture/execute/pr29798.c b/gcc/testsuite/gcc.c-torture/execute/pr29798.c new file mode 100644 index 00000000000..f7b90da0200 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/pr29798.c @@ -0,0 +1,26 @@ +extern void abort (); + +int +main () +{ + int i; + double oldrho; + double beta = 0.0; + double work = 1.0; + for (i = 1; i <= 2; i++) + { + double rho = work * work; + if (i != 1) + beta = rho / oldrho; + if (beta == 1.0) + abort (); + + /* All targets even remotely likely to ever get supported + use at least an even base, so there will never be any + floating-point rounding. All computation in this test + case is exact for even bases. */ + work /= 2.0; + oldrho = rho; + } + return 0; +}