(try_combine): New variable i3_subst_into_i2.
authorJim Wilson <wilson@gcc.gnu.org>
Wed, 6 Oct 1993 17:46:02 +0000 (10:46 -0700)
committerJim Wilson <wilson@gcc.gnu.org>
Wed, 6 Oct 1993 17:46:02 +0000 (10:46 -0700)
Set it for special case of substituting i3 into i2.  Use it near
end to detect when special case succeeded.  Move i2notes to
i3notes for this special case.
(distribute_notes, REG_UNUSED case): Ignore all REG_UNUSED notes
except those from I3.

From-SVN: r5639

gcc/combine.c

index c50265681b0c40456d108e7a54ed5ff6cc20e664..8f9efb86caacd1558be6b15071cc31c44140b0d8 100644 (file)
@@ -1152,6 +1152,8 @@ try_combine (i3, i2, i1)
   int i1_feeds_i3 = 0;
   /* Notes that must be added to REG_NOTES in I3 and I2.  */
   rtx new_i3_notes, new_i2_notes;
+  /* Notes that we substituted I3 into I2 instead of the normal case.  */
+  int i3_subst_into_i2 = 0;
 
   int maxreg;
   rtx temp;
@@ -1254,6 +1256,7 @@ try_combine (i3, i2, i1)
                     SET_DEST (PATTERN (i3)));
 
              newpat = p2;
+             i3_subst_into_i2 = 1;
              goto validate_replacement;
            }
     }
@@ -2040,22 +2043,39 @@ try_combine (i3, i2, i1)
     /* We had one special case above where I2 had more than one set and
        we replaced a destination of one of those sets with the destination
        of I3.  In that case, we have to update LOG_LINKS of insns later
-       in this basic block.  Note that this (expensive) case is rare.  */
-
-    if (GET_CODE (PATTERN (i2)) == PARALLEL)
-      for (i = 0; i < XVECLEN (PATTERN (i2), 0); i++)
-       if (GET_CODE (SET_DEST (XVECEXP (PATTERN (i2), 0, i))) == REG
-           && SET_DEST (XVECEXP (PATTERN (i2), 0, i)) != i2dest
-           && ! find_reg_note (i2, REG_UNUSED,
-                               SET_DEST (XVECEXP (PATTERN (i2), 0, i))))
-         for (temp = NEXT_INSN (i2);
-              temp && (this_basic_block == n_basic_blocks - 1
-                       || basic_block_head[this_basic_block] != temp);
-              temp = NEXT_INSN (temp))
-           if (temp != i3 && GET_RTX_CLASS (GET_CODE (temp)) == 'i')
-             for (link = LOG_LINKS (temp); link; link = XEXP (link, 1))
-               if (XEXP (link, 0) == i2)
-                 XEXP (link, 0) = i3;
+       in this basic block.  Note that this (expensive) case is rare.
+
+       Also, in this case, we must pretend that all REG_NOTEs for I2
+       actually came from I3, so that REG_UNUSED notes from I2 will be
+       properly handled.  */
+
+    if (i3_subst_into_i2)
+      {
+       for (i = 0; i < XVECLEN (PATTERN (i2), 0); i++)
+         if (GET_CODE (SET_DEST (XVECEXP (PATTERN (i2), 0, i))) == REG
+             && SET_DEST (XVECEXP (PATTERN (i2), 0, i)) != i2dest
+             && ! find_reg_note (i2, REG_UNUSED,
+                                 SET_DEST (XVECEXP (PATTERN (i2), 0, i))))
+           for (temp = NEXT_INSN (i2);
+                temp && (this_basic_block == n_basic_blocks - 1
+                         || basic_block_head[this_basic_block] != temp);
+                temp = NEXT_INSN (temp))
+             if (temp != i3 && GET_RTX_CLASS (GET_CODE (temp)) == 'i')
+               for (link = LOG_LINKS (temp); link; link = XEXP (link, 1))
+                 if (XEXP (link, 0) == i2)
+                   XEXP (link, 0) = i3;
+
+       if (i3notes)
+         {
+           rtx link = i3notes;
+           while (XEXP (link, 1))
+             link = XEXP (link, 1);
+           XEXP (link, 1) = i2notes;
+         }
+       else
+         i3notes = i2notes;
+       i2notes = 0;
+      }
 
     LOG_LINKS (i3) = 0;
     REG_NOTES (i3) = 0;
@@ -9857,9 +9877,26 @@ distribute_notes (notes, from_insn, i3, i2, elim_i2, elim_i1)
       switch (REG_NOTE_KIND (note))
        {
        case REG_UNUSED:
+         /* If this note is from any insn other than i3, then we have no
+            use for it, and must ignore it.
+
+            Any clobbers for i3 may still exist, and so we must process
+            REG_UNUSED notes from that insn.
+
+            Any clobbers from i2 or i1 can only exist if they were added by
+            recog_for_combine.  In that case, recog_for_combine created the
+            necessary REG_UNUSED notes.  Trying to keep any original
+            REG_UNUSED notes from these insns can cause incorrect output
+            if it is for the same register as the original i3 dest.
+            In that case, we will notice that the register is set in i3,
+            and then add a REG_UNUSED note for the destination of i3, which
+            is wrong.  */
+         if (from_insn != i3)
+           break;
+
          /* If this register is set or clobbered in I3, put the note there
             unless there is one already.  */
-         if (reg_set_p (XEXP (note, 0), PATTERN (i3)))
+         else if (reg_set_p (XEXP (note, 0), PATTERN (i3)))
            {
              if (! (GET_CODE (XEXP (note, 0)) == REG
                     ? find_regno_note (i3, REG_UNUSED, REGNO (XEXP (note, 0)))