combine: Update links correctly for new I2 (PR84169)
authorSegher Boessenkool <segher@kernel.crashing.org>
Tue, 13 Feb 2018 22:12:55 +0000 (23:12 +0100)
committerSegher Boessenkool <segher@gcc.gnu.org>
Tue, 13 Feb 2018 22:12:55 +0000 (23:12 +0100)
If there is a LOG_LINK between two insns, this means those two insns
can be combined, as far as dataflow is concerned.  There never should
be a LOG_LINK between two unrelated insns.  If there is one, combine
will try to combine the insns without doing all the needed checks if
the earlier destination is used before the later insn, etc.

Unfortunately we do not update the LOG_LINKs correctly in some cases.
This patch fixes at least some of those cases.

PR rtl-optimization/84169
* combine.c (try_combine): New variable split_i2i3.  Set it to true if
we generated a parallel as new i3 and we split that to new i2 and i3
instructions.  Handle split_i2i3 similar to swap_i2i3: scan the
LOG_LINKs of i3 to see which of those need to link to i2 now.  Link
those to i2, not i1.  Partially rewrite this scan code.

gcc/testsuite/
PR rtl-optimization/84169
* gcc.c-torture/execute/pr84169.c: New.

From-SVN: r257644

gcc/ChangeLog
gcc/combine.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.c-torture/execute/pr84169.c [new file with mode: 0644]

index c58d419556baf04198e8cb14830555ce62b12f8a..ac283a63a9ebcc83b9673039e9a29dfc3a9cb0aa 100644 (file)
@@ -1,3 +1,12 @@
+2018-02-13  Segher Boessenkool  <segher@kernel.crashing.org>
+
+       PR rtl-optimization/84169
+       * combine.c (try_combine): New variable split_i2i3.  Set it to true if
+       we generated a parallel as new i3 and we split that to new i2 and i3
+       instructions.  Handle split_i2i3 similar to swap_i2i3: scan the
+       LOG_LINKs of i3 to see which of those need to link to i2 now.  Link
+       those to i2, not i1.  Partially rewrite this scan code.
+
 2018-02-13  Jakub Jelinek  <jakub@redhat.com>
 
        PR c/82210
index a9929f2a3e2d988d1388213bc932eb1d6a4b4184..c4d55eb85a4fc638b760ecd441681223650ec079 100644 (file)
@@ -2665,6 +2665,7 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0,
   /* Notes that I1, I2 or I3 is a MULT operation.  */
   int have_mult = 0;
   int swap_i2i3 = 0;
+  int split_i2i3 = 0;
   int changed_i3_dest = 0;
 
   int maxreg;
@@ -4091,6 +4092,9 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0,
            }
 
          insn_code_number = recog_for_combine (&newpat, i3, &new_i3_notes);
+
+         if (insn_code_number >= 0)
+           split_i2i3 = 1;
        }
     }
 
@@ -4258,44 +4262,45 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0,
 
   if (swap_i2i3)
     {
-      rtx_insn *insn;
-      struct insn_link *link;
-      rtx ni2dest;
-
       /* I3 now uses what used to be its destination and which is now
         I2's destination.  This requires us to do a few adjustments.  */
       PATTERN (i3) = newpat;
       adjust_for_new_dest (i3);
+    }
 
-      /* We need a LOG_LINK from I3 to I2.  But we used to have one,
-        so we still will.
+  if (swap_i2i3 || split_i2i3)
+    {
+      /* We might need a LOG_LINK from I3 to I2.  But then we used to
+        have one, so we still will.
 
         However, some later insn might be using I2's dest and have
-        a LOG_LINK pointing at I3.  We must remove this link.
-        The simplest way to remove the link is to point it at I1,
-        which we know will be a NOTE.  */
+        a LOG_LINK pointing at I3.  We should change it to point at
+        I2 instead.  */
 
       /* newi2pat is usually a SET here; however, recog_for_combine might
         have added some clobbers.  */
-      if (GET_CODE (newi2pat) == PARALLEL)
-       ni2dest = SET_DEST (XVECEXP (newi2pat, 0, 0));
-      else
-       ni2dest = SET_DEST (newi2pat);
-
-      for (insn = NEXT_INSN (i3);
-          insn && (this_basic_block->next_bb == EXIT_BLOCK_PTR_FOR_FN (cfun)
-                   || insn != BB_HEAD (this_basic_block->next_bb));
+      rtx x = newi2pat;
+      if (GET_CODE (x) == PARALLEL)
+       x = XVECEXP (newi2pat, 0, 0);
+
+      unsigned int regno = REGNO (SET_DEST (x));
+
+      bool done = false;
+      for (rtx_insn *insn = NEXT_INSN (i3);
+          !done
+          && insn
+          && NONDEBUG_INSN_P (insn)
+          && BLOCK_FOR_INSN (insn) == this_basic_block;
           insn = NEXT_INSN (insn))
        {
-         if (NONDEBUG_INSN_P (insn)
-             && reg_referenced_p (ni2dest, PATTERN (insn)))
-           {
-             FOR_EACH_LOG_LINK (link, insn)
-               if (link->insn == i3)
-                 link->insn = i1;
-
-             break;
-           }
+         struct insn_link *link;
+         FOR_EACH_LOG_LINK (link, insn)
+           if (link->insn == i3 && link->regno == regno)
+             {
+               link->insn = i2;
+               done = true;
+               break;
+             }
        }
     }
 
index e14dd7d7a1774a68b13fc2da3e588a7ae3c9d8ab..034931bad9b40c71f6df9437fe9941cb11087998 100644 (file)
@@ -1,3 +1,8 @@
+2018-02-13  Segher Boessenkool  <segher@kernel.crashing.org>
+
+       PR rtl-optimization/84169
+       * gcc.c-torture/execute/pr84169.c: New.
+
 2018-02-13  Peter Bergner  <bergner@vnet.ibm.com>
 
        PR target/84370
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr84169.c b/gcc/testsuite/gcc.c-torture/execute/pr84169.c
new file mode 100644 (file)
index 0000000..ba8f8fc
--- /dev/null
@@ -0,0 +1,25 @@
+/* PR rtl-optimization/84169 */
+
+#ifdef __SIZEOF_INT128__
+typedef unsigned __int128 T;
+#else
+typedef unsigned long long T;
+#endif
+
+T b;
+
+static __attribute__ ((noipa)) T
+foo (T c, T d, T e, T f, T g, T h)
+{
+  __builtin_mul_overflow ((unsigned char) h, -16, &h);
+  return b + h;
+}
+
+int
+main ()
+{
+  T x = foo (0, 0, 0, 0, 0, 4);
+  if (x != -64)
+    __builtin_abort ();
+  return 0;
+}