This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [RFT] fwprop merge
- From: Steven Bosscher <stevenb dot gcc at gmail dot com>
- To: gcc-patches at gcc dot gnu dot org
- Cc: Ian Lance Taylor <ian at airs dot com>, "Paolo Bonzini" <paolo dot bonzini at lu dot unisi dot ch>, "Mark Mitchell" <mark at codesourcery dot com>, "David Edelsohn" <dje at gcc dot gnu dot org>, "Richard Guenther" <rguenther at suse dot de>, "Mike Stein" <mstein at phenix dot rootshell dot be>, Serge Belyshev <belyshev at depni dot sinp dot msu dot ru>
- Date: Sat, 20 May 2006 00:32:11 +0200
- Subject: Re: [RFT] fwprop merge
- References: <200605071148.21066.steven@gcc.gnu.org> <200605141837.44084.steven.bosscher@gmail.com> <200605190036.00912.steven@gcc.gnu.org>
On Friday 19 May 2006 00:36, Steven Bosscher wrote:
> * 20 are testsuite/gcc.c-torture/compile/20020927-1.c at -O2 or higher,
> so they are probably all the same problem (amr:4, m32r:4, mips:4,
> mn10300:4, v850:4).
This failure turned out to be a problem where we have a DEF that
reaches some USE in the same basic block that the DEF is in, but
the DEF does not dominate the USE. Think e.g. using a register
that is initialized in a loop, but it is used in the same loop
before it is initialized.
The fix has two parts:
1) Don't look at notes in local_ref_killed_between_p. This was
causing the ICE for this test case because from was after to,
so we'd run into the basic block note of the next basic block.
2) Don't call local_ref_killed_between_p from use_killed_between
when def_insn comes after target_insn.
This patch is incremental wrt. the patches I posted last night.
They still need to go through the full cycle of testing that I
can do myself.
Gr.
Steven
--- fwprop.c.jj 2006-05-18 20:44:07.000000000 +0200
+++ fwprop.c 2006-05-20 00:26:38.000000000 +0200
@@ -433,21 +433,24 @@ propagate_rtx (rtx x, enum machine_mode
between FROM to (but not including) TO. */
static bool
local_ref_killed_between_p (struct df_ref * ref, rtx from, rtx to)
{
- while (from != to)
+ rtx insn;
+
+ for (insn = from; insn != to; insn = NEXT_INSN (insn))
{
- struct df_ref * def = DF_INSN_DEFS (df, from);
+ if (!INSN_P (insn))
+ continue;
+
+ struct df_ref * def = DF_INSN_DEFS (df, insn);
while (def)
{
if (DF_REF_REGNO (ref) == DF_REF_REGNO (def))
return true;
def = def->next_ref;
}
-
- from = NEXT_INSN (from);
}
return false;
}
@@ -475,11 +478,22 @@ use_killed_between (struct df_ref *use,
/* Check if we are in the same basic block. */
def_bb = BLOCK_FOR_INSN (def_insn);
target_bb = BLOCK_FOR_INSN (target_insn);
if (def_bb == target_bb)
- return local_ref_killed_between_p (use, def_insn, target_insn);
+ {
+ /* 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);
+ }
/* Finally, if DEF_BB is the sole predecessor of TARGET_BB. */
if (single_pred_p (target_bb)
&& single_pred (target_bb) == def_bb)
{