diff options
author | bonzini <bonzini@138bc75d-0d04-0410-961f-82ee72b054a4> | 2006-11-14 08:46:26 +0000 |
---|---|---|
committer | bonzini <bonzini@138bc75d-0d04-0410-961f-82ee72b054a4> | 2006-11-14 08:46:26 +0000 |
commit | a39fe6879370cf141c97292a496d7dae7705778b (patch) | |
tree | c55d31f7d81769bc6d0eda9eb0cb9aac25e6818f /gcc/fwprop.c | |
parent | 2c26730b9caf78019c2b713d82d895cb7fec3963 (diff) | |
download | gcc-a39fe6879370cf141c97292a496d7dae7705778b.tar.gz |
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.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@118808 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/fwprop.c')
-rw-r--r-- | gcc/fwprop.c | 39 |
1 files changed, 18 insertions, 21 deletions
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 ()); |