This is the mail archive of the mailing list for the GCC project.

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [RFT] fwprop merge

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.


--- 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)

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]