re PR rtl-optimization/67443 (DSE removes required store instruction)
authorRichard Biener <rguenther@suse.de>
Mon, 26 Oct 2015 15:24:45 +0000 (15:24 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Mon, 26 Oct 2015 15:24:45 +0000 (15:24 +0000)
2015-10-26  Richard Biener  <rguenther@suse.de>
Dominik Vogt  <vogt@linux.vnet.ibm.com>

PR middle-end/67443
* alias.c (ao_ref_from_mem): Remove promoted subreg handling.
Properly prune ref->ref for accesses outside of ref.

* gcc.target/s390/pr67443.c: New testcase.

Co-Authored-By: Dominik Vogt <vogt@linux.vnet.ibm.com>
From-SVN: r229372

gcc/ChangeLog
gcc/alias.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/s390/pr67443.c [new file with mode: 0644]

index b35b201b0f7749dc8d1f221a55730e4b473a7cd6..95479f3793a46318e32962ca0f925d98712133e4 100644 (file)
@@ -1,3 +1,10 @@
+2015-10-26  Richard Biener  <rguenther@suse.de>
+       Dominik Vogt  <vogt@linux.vnet.ibm.com>
+
+       PR middle-end/67443
+       * alias.c (ao_ref_from_mem): Remove promoted subreg handling.
+       Properly prune ref->ref for accesses outside of ref.
+
 2015-10-26  Richard Sandiford  <richard.sandiford@arm.com>
 
        * gimple-fold.c (replace_stmt_with_simplification): Don't allow
index 1c58547df72372caa3f69b46f21367aff7a20c31..5c1ad34e088140606b74db74a80a58eefb84911f 100644 (file)
@@ -339,15 +339,16 @@ ao_ref_from_mem (ao_ref *ref, const_rtx mem)
       || !MEM_SIZE_KNOWN_P (mem))
     return true;
 
-  /* If the base decl is a parameter we can have negative MEM_OFFSET in
-     case of promoted subregs on bigendian targets.  Trust the MEM_EXPR
-     here.  */
+  /* If MEM_OFFSET/MEM_SIZE get us outside of ref->offset/ref->max_size
+     drop ref->ref.  */
   if (MEM_OFFSET (mem) < 0
-      && (MEM_SIZE (mem) + MEM_OFFSET (mem)) * BITS_PER_UNIT == ref->size)
-    return true;
+      || (ref->max_size != -1
+         && ((MEM_OFFSET (mem) + MEM_SIZE (mem)) * BITS_PER_UNIT
+             > ref->max_size)))
+    ref->ref = NULL_TREE;
 
-  /* Otherwise continue and refine size and offset we got from analyzing
-     MEM_EXPR by using MEM_SIZE and MEM_OFFSET.  */
+  /* Refine size and offset we got from analyzing MEM_EXPR by using
+     MEM_SIZE and MEM_OFFSET.  */
 
   ref->offset += MEM_OFFSET (mem) * BITS_PER_UNIT;
   ref->size = MEM_SIZE (mem) * BITS_PER_UNIT;
index 73e0a39434a7f635e48931a4d69e66d22bcd2d7b..fd5ade4ac889d2dda906638221dc3c308530d57d 100644 (file)
@@ -1,3 +1,9 @@
+2015-10-26  Richard Biener  <rguenther@suse.de>
+       Dominik Vogt  <vogt@linux.vnet.ibm.com>
+
+       PR middle-end/67443
+       * gcc.target/s390/pr67443.c: New testcase.
+
 2015-10-26  Christophe Lyon  <christophe.lyon@linaro.org>
 
        * gfortran.dg/chmod_1.f90: Add suffix to the temporary filename to
diff --git a/gcc/testsuite/gcc.target/s390/pr67443.c b/gcc/testsuite/gcc.target/s390/pr67443.c
new file mode 100644 (file)
index 0000000..e011a11
--- /dev/null
@@ -0,0 +1,49 @@
+/* Test case for PR/67443.  */
+
+/* { dg-do run { target s390*-*-* } } */
+/* { dg-prune-output "call-clobbered register used for global register variable" } */
+/* { dg-options "-march=z900 -fPIC -fomit-frame-pointer -O3" } */
+
+#include <assert.h>
+
+/* Block all registers except the first three argument registers.  */
+register long r0 asm ("r0");
+register long r1 asm ("r1");
+register long r5 asm ("r5");
+register long r6 asm ("r6");
+register long r7 asm ("r7");
+register long r8 asm ("r8");
+register long r9 asm ("r9");
+register long r10 asm ("r10");
+register long r11 asm ("r11");
+
+struct s_t
+{
+  unsigned f1 : 8;
+  unsigned f2 : 24;
+};
+
+__attribute__ ((noinline))
+void foo (struct s_t *ps, int c, int i)
+{
+  /* Uses r2 as address register.  */
+  ps->f1 = c;
+  /* The calculation of the value is so expensive that it's cheaper to spill ps
+     to the stack and reload it later (into a different register).
+     ==> Uses r4 as address register.*/
+  ps->f2 = i + i % 3;
+  /* If dead store elimination fails to detect that the address in r2 during
+     the first assignment is an alias of the address in r4 during the second
+     assignment, it eliminates the first assignment and the f1 field is not
+     written (bug).  */
+}
+
+int main (void)
+{
+  struct s_t s = { 0x01u, 0x020304u };
+
+  foo (&s, 0, 0);
+  assert (s.f1 == 0&& s.f2 == 0);
+
+  return 0;
+}