aboutsummaryrefslogtreecommitdiff
path: root/gcc/fwprop.c
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 /gcc/fwprop.c
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
Diffstat (limited to 'gcc/fwprop.c')
-rw-r--r--gcc/fwprop.c39
1 files changed, 18 insertions, 21 deletions
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 ());