This is the mail archive of the gcc-bugs@gcc.gnu.org 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]

[Bug tree-optimization/42728] "-fcompare-debug failure (length)" at -O1



------- Comment #2 from jakub at gcc dot gnu dot org  2010-01-18 13:03 -------
This is a fwprop.c bug.  In particular, that the
797  /* If target_insn comes right after def_insn, which is very common
798     for addresses, we can use a quicker test.  */
799  if (NEXT_INSN (def_insn) == target_insn
800      && REG_P (SET_DEST (def_set)))
shortcut in all_uses_available_at has different behavior depending from the
following code.  We have def_insn:
(insn 15 14 18 4 pr42728.c:6 (parallel [
            (set (reg/v/f:DI 60 [ b ])
                (plus:DI (reg/v/f:DI 60 [ b ])
                    (const_int 1 [0x1])))
            (clobber (reg:CC 17 flags))
        ]) 252 {*adddi_1} (expr_list:REG_UNUSED (reg:CC 17 flags)
        (nil)))
(as b is uninitialized, this is the only definition of b) and target_insn is
(insn 21 19 22 4 pr42728.c:5 (set (reg:CCZ 17 flags)
        (compare:CCZ (mem:QI (reg/v/f:DI 60 [ b ]) [0 S1 A8])
            (const_int 0 [0x0]))) 0 {*cmpqi_ccno_1} (nil))
(the only use of it besides debug_insns with -g).
If def_insn and target_insn are adjacent (-g0), then this returns false, as
one of the uses (the only one actually) in def_insn is the target of that insn.
If there are any debug insns in between (or any other), it returns true, as
  /* Check if the reg in USE has only one definition.  We already
     know that this definition reaches use, or we wouldn't be here.
     However, this is invalid for hard registers because if they are
     live at the beginning of the function it does not mean that we
     have an uninitialized access.  */
  regno = DF_REF_REGNO (use);
  def = DF_REG_DEF_CHAIN (regno);
  if (def
      && DF_REF_NEXT_REG (def) == NULL
      && regno >= FIRST_PSEUDO_REGISTER)
    return false;
shortcut applies and thus local_ref_killed_between_p is not allowed to return
true (because of the def in def_insn).

To fix this, we could either ensure the shortcut is run regardless of any debug
insns in between (next_nondebug_insn isn't probably usable, as target_insn may
be a debug_insn):
--- fwprop.c.jj 2009-12-10 19:19:08.000000000 +0100
+++ fwprop.c 2010-01-18 13:55:57.000000000 +0100
@@ -791,13 +791,16 @@ all_uses_available_at (rtx def_insn, rtx
   df_ref *use_rec;
   struct df_insn_info *insn_info = DF_INSN_INFO_GET (def_insn);
   rtx def_set = single_set (def_insn);
+  rtx next;

   gcc_assert (def_set);

   /* If target_insn comes right after def_insn, which is very common
      for addresses, we can use a quicker test.  */
-  if (NEXT_INSN (def_insn) == target_insn
-      && REG_P (SET_DEST (def_set)))
+  next = NEXT_INSN (def_insn);
+  while (next && next != target_insn && DEBUG_INSN_P (next))
+    next = NEXT_INSN (next);
+  if (next == target_insn && REG_P (SET_DEST (def_set)))
     {
       rtx def_reg = SET_DEST (def_set);

or we could do something like:
--- fwprop.c.xx        2009-12-10 19:19:08.000000000 +0100
+++ fwprop.c        2010-01-18 14:02:32.000000000 +0100
@@ -818,17 +818,23 @@ all_uses_available_at (rtx def_insn, rtx
     }
   else
     {
+      rtx def_reg = REG_P (SET_DEST (def_set)) ? SET_DEST (def_set) :
NULL_RTX;
+
       /* Look at all the uses of DEF_INSN, and see if they are not
          killed between DEF_INSN and TARGET_INSN.  */
       for (use_rec = DF_INSN_INFO_USES (insn_info); *use_rec; use_rec++)
         {
           df_ref use = *use_rec;
+          if (def_reg && rtx_equal_p (DF_REF_REG (use), def_reg))
+            return false;
           if (use_killed_between (use, def_insn, target_insn))
             return false;
         }
       for (use_rec = DF_INSN_INFO_EQ_USES (insn_info); *use_rec; use_rec++)
         {
           df_ref use = *use_rec;
+          if (def_reg && rtx_equal_p (DF_REF_REG (use), def_reg))
+            return false;
           if (use_killed_between (use, def_insn, target_insn))
             return false;
         }


-- 

jakub at gcc dot gnu dot org changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |bonzini at gnu dot org
             Status|UNCONFIRMED                 |NEW
     Ever Confirmed|0                           |1
   Last reconfirmed|0000-00-00 00:00:00         |2010-01-18 13:03:43
               date|                            |


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=42728


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