* combine.c (distribute_links): Handle multiple SETs.
authorSegher Boessenkool <segher@kernel.crashing.org>
Mon, 1 Dec 2014 18:28:07 +0000 (19:28 +0100)
committerSegher Boessenkool <segher@gcc.gnu.org>
Mon, 1 Dec 2014 18:28:07 +0000 (19:28 +0100)
From-SVN: r218242

gcc/ChangeLog
gcc/combine.c

index bd31731cac5f67bdb593693d7eea72744dd75483..f1e029e9d5d349cb1d07cf4d4a43fba146a9f080 100644 (file)
@@ -1,3 +1,7 @@
+2014-12-01  Segher Boessenkool  <segher@kernel.crashing.org>
+
+       * combine.c (distribute_links): Handle multiple SETs.
+
 2014-12-01  Segher Boessenkool  <segher@kernel.crashing.org>
 
        * combine.c (struct insn_link): New field `regno'.
index f94d8770a347aaa099bc1763dbfba153088671fb..afcb91eedd03ec60f5e261b4567938ed06740c30 100644 (file)
@@ -13817,24 +13817,46 @@ distribute_links (struct insn_link *links)
 
       next_link = link->next;
 
-      /* If the insn that this link points to is a NOTE or isn't a single
-        set, ignore it.  In the latter case, it isn't clear what we
-        can do other than ignore the link, since we can't tell which
-        register it was for.  Such links wouldn't be used by combine
-        anyway.
-
-        It is not possible for the destination of the target of the link to
-        have been changed by combine.  The only potential of this is if we
-        replace I3, I2, and I1 by I3 and I2.  But in that case the
-        destination of I2 also remains unchanged.  */
-
-      if (NOTE_P (link->insn)
-         || (set = single_set (link->insn)) == 0)
+      /* If the insn that this link points to is a NOTE, ignore it.  */
+      if (NOTE_P (link->insn))
+       continue;
+
+      set = 0;
+      rtx pat = PATTERN (link->insn);
+      if (GET_CODE (pat) == SET)
+       set = pat;
+      else if (GET_CODE (pat) == PARALLEL)
+       {
+         int i;
+         for (i = 0; i < XVECLEN (pat, 0); i++)
+           {
+             set = XVECEXP (pat, 0, i);
+             if (GET_CODE (set) != SET)
+               continue;
+
+             reg = SET_DEST (set);
+             while (GET_CODE (reg) == ZERO_EXTRACT
+                    || GET_CODE (reg) == STRICT_LOW_PART
+                    || GET_CODE (reg) == SUBREG)
+               reg = XEXP (reg, 0);
+
+             if (!REG_P (reg))
+               continue;
+
+             if (REGNO (reg) == link->regno)
+               break;
+           }
+         if (i == XVECLEN (pat, 0))
+           continue;
+       }
+      else
        continue;
 
       reg = SET_DEST (set);
-      while (GET_CODE (reg) == SUBREG || GET_CODE (reg) == ZERO_EXTRACT
-            || GET_CODE (reg) == STRICT_LOW_PART)
+
+      while (GET_CODE (reg) == ZERO_EXTRACT
+            || GET_CODE (reg) == STRICT_LOW_PART
+            || GET_CODE (reg) == SUBREG)
        reg = XEXP (reg, 0);
 
       /* A LOG_LINK is defined as being placed on the first insn that uses