If I2 is a PARALLEL of two SETs, split it into two instructions, I1
and I2.  If there already was an I1, rename it to I0.  If there
already was an I0, don't do anything.

This surprisingly simple patch is enough to let combine handle such
PARALLELs properly.


2014-11-14  Segher Boessenkool  <seg...@kernel.crashing.org>

gcc/
        * combine.c (try_combine): If I2 is a PARALLEL of two SETs,
        split it into two insns.

---
 gcc/combine.c | 31 +++++++++++++++++++++++++++++++
 1 file changed, 31 insertions(+)

diff --git a/gcc/combine.c b/gcc/combine.c
index f7797e7..c4d23e3 100644
--- a/gcc/combine.c
+++ b/gcc/combine.c
@@ -2780,6 +2780,37 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, 
rtx_insn *i0,
          SUBST_LINK (LOG_LINKS (i2), alloc_insn_link (i1, LOG_LINKS (i2)));
        }
     }
+
+  /* If I2 is a PARALLEL of two SETs of REGs (and perhaps some CLOBBERs),
+     make those two SETs separate I1 and I2 insns, and make an I0 that is
+     the original I1.  */
+  if (i0 == 0
+      && GET_CODE (PATTERN (i2)) == PARALLEL
+      && XVECLEN (PATTERN (i2), 0) >= 2
+      && GET_CODE (XVECEXP (PATTERN (i2), 0, 0)) == SET
+      && GET_CODE (XVECEXP (PATTERN (i2), 0, 1)) == SET
+      && REG_P (SET_DEST (XVECEXP (PATTERN (i2), 0, 0)))
+      && REG_P (SET_DEST (XVECEXP (PATTERN (i2), 0, 1)))
+      && !reg_used_between_p (SET_DEST (XVECEXP (PATTERN (i2), 0, 0)), i2, i3)
+      && !reg_used_between_p (SET_DEST (XVECEXP (PATTERN (i2), 0, 1)), i2, i3)
+      && (XVECLEN (PATTERN (i2), 0) == 2
+         || GET_CODE (XVECEXP (PATTERN (i2), 0, 2)) == CLOBBER))
+    {
+      /* If there is no I1, there is no I0 either.  */
+      i0 = i1;
+
+      /* We make I1 with the same INSN_UID as I2.  This gives it
+        the same DF_INSN_LUID for value tracking.  Our fake I1 will
+        never appear in the insn stream so giving it the same INSN_UID
+        as I2 will not cause a problem.  */
+
+      i1 = gen_rtx_INSN (VOIDmode, NULL, i2, BLOCK_FOR_INSN (i2),
+                        XVECEXP (PATTERN (i2), 0, 0), INSN_LOCATION (i2),
+                        -1, NULL_RTX);
+      INSN_UID (i1) = INSN_UID (i2);
+
+      SUBST (PATTERN (i2), XVECEXP (PATTERN (i2), 0, 1));
+    }
 #endif
 
   /* Verify that I2 and I1 are valid for combining.  */
-- 
1.8.1.4

Reply via email to