aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaolo Bonzini <bonzini@gnu.org>2006-11-14 08:46:26 +0000
committerPaolo Bonzini <bonzini@gcc.gnu.org>2006-11-14 08:46:26 +0000
commit6e0b633f6c2b88355a66d77c956367730e67f783 (patch)
treec55d31f7d81769bc6d0eda9eb0cb9aac25e6818f
parentb7e85170cf309a3a6e9f3049c61632f7c9284547 (diff)
downloadgcc-6e0b633f6c2b88355a66d77c956367730e67f783.zip
gcc-6e0b633f6c2b88355a66d77c956367730e67f783.tar.gz
gcc-6e0b633f6c2b88355a66d77c956367730e67f783.tar.bz2
re PR rtl-optimization/29798 (-O2 gives wrong results)
2006-11-14 Paolo Bonzini <bonzini@gnu.org> 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 <bonzini@gnu.org> PR rtl-optimization/29798 * gcc.c-torture/execute/pr29798.c: New. From-SVN: r118808
-rw-r--r--gcc/ChangeLog9
-rw-r--r--gcc/fwprop.c39
-rw-r--r--gcc/testsuite/ChangeLog6
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/pr29798.c26
4 files changed, 59 insertions, 21 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 69f6627..d1f36df 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,12 @@
+2006-11-14 Paolo Bonzini <bonzini@gnu.org>
+
+ 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 <ghazi@caip.rutgers.edu>
* fold-const.c (fold_strip_sign_ops): Handle COMPOUND_EXPR and
diff --git a/gcc/fwprop.c b/gcc/fwprop.c
index 1e4f749..fb601e1 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 370620b..9693e4d 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,9 @@
+2006-11-14 Paolo Bonzini <bonzini@gnu.org>
+
+ PR rtl-optimization/29798
+
+ * gcc.c-torture/execute/pr29798.c: New.
+
2006-11-14 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
* 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 0000000..f7b90da
--- /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;
+}