]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
[PR80693] drop value of parallel SETs dropped by combine
authorAlexandre Oliva <aoliva@redhat.com>
Mon, 11 Dec 2017 22:36:07 +0000 (22:36 +0000)
committerAlexandre Oliva <aoliva@gcc.gnu.org>
Mon, 11 Dec 2017 22:36:07 +0000 (22:36 +0000)
When combine drops a REG_UNUSED SET in a parallel, we have to clear
cached values, so that, even if the REGs remain used (e.g. because
they were referenced in the used SET_SRC), we will not use properties
of the dropped modified value as if they applied to the preserved
original one.

We fail to adjust REG_N_SETS.

for  gcc/ChangeLog

PR rtl-optimization/80693
PR rtl-optimization/81019
PR rtl-optimization/81020
* combine.c (distribute_notes): Reset any REG_UNUSED REGs that
are not mentioned in i3.  Place the REG_UNUSED note on i2,
possibly modified to REG_DEAD, if it did not originate in i3.

for  gcc/testsuite/ChangeLog

PR rtl-optimization/80693
PR rtl-optimization/81019
PR rtl-optimization/81020
* gcc.dg/pr80693.c: New.
* gcc.dg/pr81019.c: New.

From-SVN: r255554

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

index bd41af866365912a2f4ca828ec163426eada38ce..04fbd66e292b31513ce67d1de2611383c392c469 100644 (file)
@@ -1,3 +1,12 @@
+2017-12-11  Alexandre Oliva <aoliva@redhat.com>
+
+       PR rtl-optimization/80693
+       PR rtl-optimization/81019
+       PR rtl-optimization/81020
+       * combine.c (distribute_notes): Reset any REG_UNUSED REGs that
+       are not mentioned in i3.  Place the REG_UNUSED note on i2,
+       possibly modified to REG_DEAD, if it did not originate in i3.
+
 2017-12-11  Jakub Jelinek  <jakub@redhat.com>
 
        * recog.c (store_data_bypass_p_1): New function.
index 786a84010d8e0eb8feef3c28fa025892f64411eb..7f10c67bf0f615b39f097605543f6c884c84552e 100644 (file)
@@ -14219,6 +14219,46 @@ distribute_notes (rtx notes, rtx_insn *from_insn, rtx_insn *i3, rtx_insn *i2,
              PUT_REG_NOTE_KIND (note, REG_DEAD);
              place = i3;
            }
+
+         /* A SET or CLOBBER of the REG_UNUSED reg has been removed,
+            but we can't tell which at this point.  We must reset any
+            expectations we had about the value that was previously
+            stored in the reg.  ??? Ideally, we'd adjust REG_N_SETS
+            and, if appropriate, restore its previous value, but we
+            don't have enough information for that at this point.  */
+         else
+           {
+             record_value_for_reg (XEXP (note, 0), NULL, NULL_RTX);
+
+             /* Otherwise, if this register is now referenced in i2
+                then the register used to be modified in one of the
+                original insns.  If it was i3 (say, in an unused
+                parallel), it's now completely gone, so the note can
+                be discarded.  But if it was modified in i2, i1 or i0
+                and we still reference it in i2, then we're
+                referencing the previous value, and since the
+                register was modified and REG_UNUSED, we know that
+                the previous value is now dead.  So, if we only
+                reference the register in i2, we change the note to
+                REG_DEAD, to reflect the previous value.  However, if
+                we're also setting or clobbering the register as
+                scratch, we know (because the register was not
+                referenced in i3) that it's unused, just as it was
+                unused before, and we place the note in i2.  */
+             if (from_insn != i3 && i2 && INSN_P (i2)
+                 && reg_referenced_p (XEXP (note, 0), PATTERN (i2)))
+               {
+                 if (!reg_set_p (XEXP (note, 0), PATTERN (i2)))
+                   PUT_REG_NOTE_KIND (note, REG_DEAD);
+                 if (! (REG_P (XEXP (note, 0))
+                        ? find_regno_note (i2, REG_NOTE_KIND (note),
+                                           REGNO (XEXP (note, 0)))
+                        : find_reg_note (i2, REG_NOTE_KIND (note),
+                                         XEXP (note, 0))))
+                   place = i2;
+               }
+           }
+
          break;
 
        case REG_EQUAL:
index 3c2f0d2bd83cbc9ad804a2369515b508b5caaeb3..5cdd4930812038a316dac9324fafdee2ba031635 100644 (file)
@@ -1,3 +1,11 @@
+2017-12-11  Alexandre Oliva <aoliva@redhat.com>
+
+       PR rtl-optimization/80693
+       PR rtl-optimization/81019
+       PR rtl-optimization/81020
+       * gcc.dg/pr80693.c: New.
+       * gcc.dg/pr81019.c: New.
+
 2017-12-11  Segher Boessenkool  <segher@kernel.crashing.org>
 
        PR rtl-optimization/83361
diff --git a/gcc/testsuite/gcc.dg/pr80693.c b/gcc/testsuite/gcc.dg/pr80693.c
new file mode 100644 (file)
index 0000000..5071771
--- /dev/null
@@ -0,0 +1,26 @@
+/* { dg-do run } */
+/* { dg-options "-O -fno-tree-coalesce-vars" } */
+typedef unsigned char u8;
+typedef unsigned short u16;
+typedef unsigned u32;
+typedef unsigned long long u64;
+
+static u64 __attribute__((noinline, noclone))
+foo(u8 u8_0, u16 u16_0, u32 u32_0, u64 u64_0,  u16 u16_1)
+{
+  u16_1 += 0x1051;
+  u16_1 &= 1;
+  u8_0 <<= u32_0 & 7;
+  u16_0 -= !u16_1;
+  u16_1 >>= ((u16)-u8_0 != 0xff);
+  return u8_0 + u16_0 + u64_0 + u16_1;
+}
+
+int
+main (void)
+{
+  u64 x = foo(1, 1, 0xffff, 0, 1);
+  if (x != 0x80)
+    __builtin_abort();
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/pr81019.c b/gcc/testsuite/gcc.dg/pr81019.c
new file mode 100644 (file)
index 0000000..cf13bfa
--- /dev/null
@@ -0,0 +1,27 @@
+/* PR rtl-optimization/81019 */
+/* { dg-do run } */
+/* { dg-options "-O -fno-tree-ccp" } */
+
+unsigned long long __attribute__((noinline, noclone))
+foo (unsigned char a, unsigned short b, unsigned c, unsigned long long d,
+     unsigned char e, unsigned short f, unsigned g, unsigned long long h)
+{
+  g = e;
+  c &= 0 < d;
+  b *= d;
+  g ^= -1;
+  g &= 1;
+  c |= 1;
+  a -= 0 < g;
+  g >>= 1;
+  f = b | (f >> b);
+  return a + c + d + f + g + h;
+}
+
+int
+main (void)
+{
+  if (foo (0, 0, 0, 0, 0, 0, 0, 0) != 0x100)
+    __builtin_abort ();
+  return 0;
+}