]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
combine: Count auto_inc properly (PR89794)
authorsegher <segher@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 15 Apr 2019 11:33:29 +0000 (11:33 +0000)
committersegher <segher@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 15 Apr 2019 11:33:29 +0000 (11:33 +0000)
The code that checks if an auto-increment from i0 or i1 is not lost is
a bit shaky.  The code to check the same for i2 is non-existent, and
cannot be implemented in a similar way at all.  So, this patch counts
all auto-increments, and makes sure we end up with the same number as
we started with.  This works because we still have a check that we
will not duplicate any.

We should do this some better way, but not while we are in stage 4.

PR rtl-optimization/89794
* combine.c (count_auto_inc): New function.
(try_combine): Count how many auto_inc expressions there were in the
original instructions.  Ensure we have the same number in the new
instructions.  Remove the code that tried to ensure auto_inc side
effects on i1 and i0 are not lost.

gcc/testsuite/
PR rtl-optimization/89794
* gcc.dg/torture/pr89794.c: New testcase.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@270368 138bc75d-0d04-0410-961f-82ee72b054a4

ChangeLog
gcc/combine.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/torture/pr89794.c [new file with mode: 0644]

index 10ea6676726e5977b6102ad1787304b85cbac4d7..2605beb5e96f348b8e6b496a18c044ee801d4da7 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2019-04-15  Segher Boessenkool  <segher@kernel.crashing.org>
+
+       PR rtl-optimization/89794
+       * combine.c (count_auto_inc): New function.
+       (try_combine): Count how many auto_inc expressions there were in the
+       original instructions.  Ensure we have the same number in the new
+       instructions.  Remove the code that tried to ensure auto_inc side
+       effects on i1 and i0 are not lost.
+
 2019-04-14  Johannes Pfau  <johannespfau@gmail.com>
 
        * configure.ac: Remove d from unsupported languages on mingw and cygwin.
index 91e32c88c8898781a884cb3b263855b88206cac7..5616e6b1bacb2a53fa006c121e0a4aaf853aadc3 100644 (file)
@@ -2641,6 +2641,16 @@ is_just_move (rtx x)
   return (GET_CODE (x) == SET && general_operand (SET_SRC (x), VOIDmode));
 }
 
+/* Callback function to count autoincs.  */
+
+static int
+count_auto_inc (rtx, rtx, rtx, rtx, rtx, void *arg)
+{
+  (*((int *) arg))++;
+
+  return 0;
+}
+
 /* Try to combine the insns I0, I1 and I2 into I3.
    Here I0, I1 and I2 appear earlier than I3.
    I0 and I1 can be zero; then we combine just I2 into I3, or I1 and I2 into
@@ -2706,6 +2716,7 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0,
   int split_i2i3 = 0;
   int changed_i3_dest = 0;
   bool i2_was_move = false, i3_was_move = false;
+  int n_auto_inc = 0;
 
   int maxreg;
   rtx_insn *temp_insn;
@@ -3210,6 +3221,16 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0,
       return 0;
     }
 
+  /* Count how many auto_inc expressions there were in the original insns;
+     we need to have the same number in the resulting patterns.  */
+
+  if (i0)
+    for_each_inc_dec (PATTERN (i0), count_auto_inc, &n_auto_inc);
+  if (i1)
+    for_each_inc_dec (PATTERN (i1), count_auto_inc, &n_auto_inc);
+  for_each_inc_dec (PATTERN (i2), count_auto_inc, &n_auto_inc);
+  for_each_inc_dec (PATTERN (i3), count_auto_inc, &n_auto_inc);
+
   /* If the set in I2 needs to be kept around, we must make a copy of
      PATTERN (I2), so that when we substitute I1SRC for I1DEST in
      PATTERN (I2), we are only substituting for the original I1DEST, not into
@@ -3411,18 +3432,11 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0,
 
   if (i1 && GET_CODE (newpat) != CLOBBER)
     {
-      /* Check that an autoincrement side-effect on I1 has not been lost.
-        This happens if I1DEST is mentioned in I2 and dies there, and
-        has disappeared from the new pattern.  */
-      if ((FIND_REG_INC_NOTE (i1, NULL_RTX) != 0
-          && i1_feeds_i2_n
-          && dead_or_set_p (i2, i1dest)
-          && !reg_overlap_mentioned_p (i1dest, newpat))
-          /* Before we can do this substitution, we must redo the test done
-             above (see detailed comments there) that ensures I1DEST isn't
-             mentioned in any SETs in NEWPAT that are field assignments.  */
-         || !combinable_i3pat (NULL, &newpat, i1dest, NULL_RTX, NULL_RTX,
-                               0, 0, 0))
+      /* Before we can do this substitution, we must redo the test done
+        above (see detailed comments there) that ensures I1DEST isn't
+        mentioned in any SETs in NEWPAT that are field assignments.  */
+      if (!combinable_i3pat (NULL, &newpat, i1dest, NULL_RTX, NULL_RTX,
+                            0, 0, 0))
        {
          undo_all ();
          return 0;
@@ -3452,12 +3466,8 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0,
 
   if (i0 && GET_CODE (newpat) != CLOBBER)
     {
-      if ((FIND_REG_INC_NOTE (i0, NULL_RTX) != 0
-          && ((i0_feeds_i2_n && dead_or_set_p (i2, i0dest))
-              || (i0_feeds_i1_n && dead_or_set_p (i1, i0dest)))
-          && !reg_overlap_mentioned_p (i0dest, newpat))
-         || !combinable_i3pat (NULL, &newpat, i0dest, NULL_RTX, NULL_RTX,
-                               0, 0, 0))
+      if (!combinable_i3pat (NULL, &newpat, i0dest, NULL_RTX, NULL_RTX,
+                            0, 0, 0))
        {
          undo_all ();
          return 0;
@@ -3478,6 +3488,20 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0,
       substed_i0 = 1;
     }
 
+  if (n_auto_inc)
+    {
+      int new_n_auto_inc = 0;
+      for_each_inc_dec (newpat, count_auto_inc, &new_n_auto_inc);
+
+      if (n_auto_inc != new_n_auto_inc)
+       {
+         if (dump_file && (dump_flags & TDF_DETAILS))
+           fprintf (dump_file, "Number of auto_inc expressions changed\n");
+         undo_all ();
+         return 0;
+       }
+    }
+
   /* Fail if an autoincrement side-effect has been duplicated.  Be careful
      to count all the ways that I2SRC and I1SRC can be used.  */
   if ((FIND_REG_INC_NOTE (i2, NULL_RTX) != 0
index 5513a934f738162e9711219c22f368a7d47bc300..be91be7c11bc76428eba3ccb1abe487e5d667fd2 100644 (file)
@@ -1,3 +1,8 @@
+2019-04-15  Segher Boessenkool  <segher@kernel.crashing.org>
+
+       PR rtl-optimization/89794
+       * gcc.dg/torture/pr89794.c: New testcase.
+
 2019-04-15  Richard Biener  <rguenther@suse.de>
 
        PR ipa/88936
diff --git a/gcc/testsuite/gcc.dg/torture/pr89794.c b/gcc/testsuite/gcc.dg/torture/pr89794.c
new file mode 100644 (file)
index 0000000..91bb0c4
--- /dev/null
@@ -0,0 +1,24 @@
+/* { dg-do run } */
+
+typedef unsigned short u16;
+typedef unsigned int u32;
+typedef unsigned long long u64;
+
+u32 a, b, c, d;
+
+u32 foo (u32 f, u32 g, u32 g2, u32 g3, u16 h, u16 i)
+{
+  (void)g, (void)g2, (void)g3, (void)h;
+  d = __builtin_bswap64 (i);
+  __builtin_sub_overflow (0, d, &b);
+  __builtin_memset (&i, c, 2);
+  a = 0;
+  return b + f + i + c;
+}
+
+int main (void)
+{
+  u32 x = foo (0, 0, 0, 0, 0, 0);
+  asm ("" :: "r" (x));
+  return 0;
+}