re PR rtl-optimization/89965 (wrong code with -O -mtune=nano-x2 -fcaller-saves -fexpe...
authorJakub Jelinek <jakub@redhat.com>
Fri, 12 Apr 2019 16:20:21 +0000 (18:20 +0200)
committerJakub Jelinek <jakub@gcc.gnu.org>
Fri, 12 Apr 2019 16:20:21 +0000 (18:20 +0200)
PR rtl-optimization/89965
* dce.c: Include rtl-iter.h.
(struct check_argument_load_data): New type.
(check_argument_load): New function.
(find_call_stack_args): Check for loads from stack slots still tracked
in sp_bytes and punt if any is found.

* gcc.target/i386/pr89965.c: New test.

From-SVN: r270323

gcc/ChangeLog
gcc/dce.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/i386/pr89965.c [new file with mode: 0644]

index 26b76ee3493caec73b0c91fd1ad618fefbabc587..02d3d07d0e4cb88ee93fbd7d096bab90a8f895b4 100644 (file)
@@ -1,4 +1,11 @@
 2019-04-12  Jakub Jelinek  <jakub@redhat.com>
+       
+       PR rtl-optimization/89965
+       * dce.c: Include rtl-iter.h.
+       (struct check_argument_load_data): New type.
+       (check_argument_load): New function.
+       (find_call_stack_args): Check for loads from stack slots still tracked
+       in sp_bytes and punt if any is found.
 
        * config/mips/loongson-mmiintrin.h: Fix up #error message.
 
index 98063dc44ac925de75c9762a48bf311855240f61..e6822fed7911f4938282db32d2ec2cf1b3495014 100644 (file)
--- a/gcc/dce.c
+++ b/gcc/dce.c
@@ -35,6 +35,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "valtrack.h"
 #include "tree-pass.h"
 #include "dbgcnt.h"
+#include "rtl-iter.h"
 
 
 /* -------------------------------------------------------------------------
@@ -325,6 +326,48 @@ sp_based_mem_offset (rtx_call_insn *call_insn, const_rtx mem, bool fast)
   return off;
 }
 
+/* Data for check_argument_load called via note_uses.  */
+struct check_argument_load_data {
+  bitmap sp_bytes;
+  HOST_WIDE_INT min_sp_off, max_sp_off;
+  rtx_call_insn *call_insn;
+  bool fast;
+  bool load_found;
+};
+
+/* Helper function for find_call_stack_args.  Check if there are
+   any loads from the argument slots in between the const/pure call
+   and store to the argument slot, set LOAD_FOUND if any is found.  */
+
+static void
+check_argument_load (rtx *loc, void *data)
+{
+  struct check_argument_load_data *d
+    = (struct check_argument_load_data *) data;
+  subrtx_iterator::array_type array;
+  FOR_EACH_SUBRTX (iter, array, *loc, NONCONST)
+    {
+      const_rtx mem = *iter;
+      HOST_WIDE_INT size;
+      if (MEM_P (mem)
+         && MEM_SIZE_KNOWN_P (mem)
+         && MEM_SIZE (mem).is_constant (&size))
+       {
+         HOST_WIDE_INT off = sp_based_mem_offset (d->call_insn, mem, d->fast);
+         if (off != INTTYPE_MINIMUM (HOST_WIDE_INT)
+             && off < d->max_sp_off
+             && off + size > d->min_sp_off)
+           for (HOST_WIDE_INT byte = MAX (off, d->min_sp_off);
+                byte < MIN (off + size, d->max_sp_off); byte++)
+             if (bitmap_bit_p (d->sp_bytes, byte - d->min_sp_off))
+               {
+                 d->load_found = true;
+                 return;
+               }
+       }
+    }
+}
+
 /* Try to find all stack stores of CALL_INSN arguments if
    ACCUMULATE_OUTGOING_ARGS.  If all stack stores have been found
    and it is therefore safe to eliminate the call, return true,
@@ -394,8 +437,10 @@ find_call_stack_args (rtx_call_insn *call_insn, bool do_mark, bool fast,
       }
 
   /* Walk backwards, looking for argument stores.  The search stops
-     when seeing another call, sp adjustment or memory store other than
-     argument store.  */
+     when seeing another call, sp adjustment, memory store other than
+     argument store or a read from an argument stack slot.  */
+  struct check_argument_load_data data
+    = { sp_bytes, min_sp_off, max_sp_off, call_insn, fast, false };
   ret = false;
   for (insn = PREV_INSN (call_insn); insn; insn = prev_insn)
     {
@@ -414,6 +459,10 @@ find_call_stack_args (rtx_call_insn *call_insn, bool do_mark, bool fast,
       if (!set || SET_DEST (set) == stack_pointer_rtx)
        break;
 
+      note_uses (&PATTERN (insn), check_argument_load, &data);
+      if (data.load_found)
+       break;
+
       if (!MEM_P (SET_DEST (set)))
        continue;
 
index fe8373e30603e8177b1c0d2d63ee8dc8578a5655..e3f1bf12049a379e1398eecd6310064deffab6cd 100644 (file)
@@ -1,3 +1,8 @@
+2019-04-12  Jakub Jelinek  <jakub@redhat.com>
+       
+       PR rtl-optimization/89965
+       * gcc.target/i386/pr89965.c: New test.
+
 2019-04-12  Marek Polacek  <polacek@redhat.com>
 
        PR c++/87603 - constexpr functions are no longer noexcept.
diff --git a/gcc/testsuite/gcc.target/i386/pr89965.c b/gcc/testsuite/gcc.target/i386/pr89965.c
new file mode 100644 (file)
index 0000000..db6382c
--- /dev/null
@@ -0,0 +1,39 @@
+/* PR rtl-optimization/89965 */
+/* { dg-do run } */
+/* { dg-options "-O -mtune=nano-x2 -fcaller-saves -fexpensive-optimizations -fno-tree-dce -fno-tree-ter" } */
+/* { dg-additional-options "-march=i386" { target ia32 } } */
+
+int a;
+
+__attribute__ ((noipa)) unsigned long long
+foo (unsigned char c, unsigned d, unsigned e, unsigned long long f,
+     unsigned char g, unsigned h, unsigned long long i)
+{
+  (void) d;
+  unsigned short j = __builtin_mul_overflow_p (~0, h, c);
+  e <<= e;
+  i >>= 7;
+  c *= i;
+  i /= 12;
+  a = __builtin_popcount (c);
+  __builtin_add_overflow (e, a, &f);
+  return c + f + g + j + h;
+}
+
+__attribute__ ((noipa)) void
+bar (void)
+{
+  char buf[64];
+  __builtin_memset (buf, 0x55, sizeof buf);
+  asm volatile ("" : : "r" (&buf[0]) : "memory");
+}
+
+int
+main (void)
+{
+  bar ();
+  unsigned long long x = foo (2, 0, 0, 0, 0, 0, 0);
+  if (x != 0)
+    __builtin_abort ();
+  return 0;
+}