re PR middle-end/70245 (Miscompilation of ICU on i386 with atom tuning starting with...
authorJakub Jelinek <jakub@redhat.com>
Wed, 16 Mar 2016 17:52:20 +0000 (18:52 +0100)
committerJakub Jelinek <jakub@gcc.gnu.org>
Wed, 16 Mar 2016 17:52:20 +0000 (18:52 +0100)
PR target/70245
* rtlanal.c (replace_rtx): For REG, if from is a REG,
return to even if only REGNO is equal, and assert
mode is the same.

* g++.dg/opt/pr70245.C: New test.
* g++.dg/opt/pr70245.h: New file.
* g++.dg/opt/pr70245-aux.cc: New file.

Co-Authored-By: Richard Biener <rguenther@suse.de>
From-SVN: r234265

gcc/ChangeLog
gcc/rtlanal.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/opt/pr70245-aux.cc [new file with mode: 0644]
gcc/testsuite/g++.dg/opt/pr70245.C [new file with mode: 0644]
gcc/testsuite/g++.dg/opt/pr70245.h [new file with mode: 0644]

index 48941e22bf3655f488ddff6eceec288a867df380..ab80ce4120a8d98c529570c215e452a756c0dbdf 100644 (file)
@@ -1,3 +1,11 @@
+2016-03-16  Jakub Jelinek  <jakub@redhat.com>
+           Richard Biener  <rguenth@suse.de>
+
+       PR target/70245
+       * rtlanal.c (replace_rtx): For REG, if from is a REG,
+       return to even if only REGNO is equal, and assert
+       mode is the same.
+
 2016-03-11  Jeff Law  <law@redhat.com>
 
        PR rtl-optimization/70224
index bacc5f25f4af20ed5dd0b7118cccea8ce57d0a13..74b593d6935fca944704842efb210ddb3440dfeb 100644 (file)
@@ -2961,7 +2961,16 @@ replace_rtx (rtx x, rtx from, rtx to)
   if (x == 0)
     return 0;
 
-  if (GET_CODE (x) == SUBREG)
+  if (GET_CODE (x) == REG)
+    {
+      if (GET_CODE (from) == REG
+         && REGNO (x) == REGNO (from))
+       {
+         gcc_assert (GET_MODE (x) == GET_MODE (from));
+         return to;
+       }
+    }
+  else if (GET_CODE (x) == SUBREG)
     {
       rtx new_rtx = replace_rtx (SUBREG_REG (x), from, to);
 
index 76b57ea488054dd6b263e4357419984b8d35c73a..a215b0ca51958a8740ce83421dc0c9db118e7abf 100644 (file)
@@ -1,3 +1,10 @@
+2016-03-16  Jakub Jelinek  <jakub@redhat.com>
+
+       PR target/70245
+       * g++.dg/opt/pr70245.C: New test.
+       * g++.dg/opt/pr70245.h: New file.
+       * g++.dg/opt/pr70245-aux.cc: New file.
+
 2016-03-16  Martin Sebor  <msebor@redhat.com>
 
        * g++.dg/cpp1y/constexpr-instantiate.C: Correct DejaGnu directives.
diff --git a/gcc/testsuite/g++.dg/opt/pr70245-aux.cc b/gcc/testsuite/g++.dg/opt/pr70245-aux.cc
new file mode 100644 (file)
index 0000000..7f65f20
--- /dev/null
@@ -0,0 +1,56 @@
+// PR target/70245
+// { dg-do compile }
+// { dg-options "" }
+
+#include "pr70245.h"
+
+D m;
+A n, o;
+int p, q;
+
+int *
+fn1 (char *x, int *y)
+{
+  *y = 0;
+  return &p;
+}
+
+void
+fn2 ()
+{
+  __builtin_abort ();
+}
+
+void *
+fn3 (int *x)
+{
+  *x = 0;
+  return (void *) &m;
+}
+
+void *
+fn4 ()
+{
+  a = &o;
+  o.a1.d = 9;
+  m.d = sizeof (D);
+  __builtin_memcpy (o.a2.c, "abcdefghijklmnop", 16);
+  return (void *) &n;
+}
+
+void
+fn5 (A *x, B *y, unsigned char *z, int *w)
+{
+  if (x != &n || y != &k || z != (unsigned char *) (&m + 1))
+    __builtin_abort ();
+  q++;
+}
+
+int
+main ()
+{
+  d = fn5;
+  baz (0);
+  if (q != 1)
+    __builtin_abort ();
+}
diff --git a/gcc/testsuite/g++.dg/opt/pr70245.C b/gcc/testsuite/g++.dg/opt/pr70245.C
new file mode 100644 (file)
index 0000000..21280b7
--- /dev/null
@@ -0,0 +1,52 @@
+// PR target/70245
+// { dg-do run }
+// { dg-additional-sources "pr70245-aux.cc" }
+// { dg-options "-O2" }
+// { dg-additional-options "-fPIC" { target fpic } }
+// { dg-additional-options "-march=i386 -mtune=atom" { target ia32 } }
+
+#include "pr70245.h"
+
+struct A *a, *i;
+int b, c, e, l;
+F d;
+
+static A *
+foo (B *x, int *y, int *z)
+{
+  unsigned char *f = (unsigned char *) fn3 (y);
+  D *g = (D *) f;
+  A *h;
+  if (e || a || c || b || g->d)
+    return 0;
+  h = (A *) fn4 ();
+  __builtin_memcpy (h, a, sizeof (A));
+  h->a1 = *(D *) f;
+  if (d)
+    {
+      d (h, x, f + g->d, z);
+      if (*z)
+       fn2 ();
+    }
+  return h;
+}
+
+static A *
+bar (B *x, int *y)
+{
+  int *j = fn1 (x->b, y);
+  if (*y > 0)
+    return 0;
+  i = foo (x, j, y);
+  return i;
+}
+
+B k;
+
+void
+baz (int x)
+{
+  if (x)
+    bar (0, 0);
+  bar (&k, &l);
+}
diff --git a/gcc/testsuite/g++.dg/opt/pr70245.h b/gcc/testsuite/g++.dg/opt/pr70245.h
new file mode 100644 (file)
index 0000000..b0c5406
--- /dev/null
@@ -0,0 +1,14 @@
+extern struct A *a, *i;
+extern int b, c, e, l;
+int *fn1 (char *, int *);
+void fn2 ();
+void *fn3 (int *);
+struct B { char *b; };
+typedef void (*F) (A *, B *, unsigned char *, int *);
+struct C { int c[16]; };
+struct D { int d; };
+struct A { D a1; C a2; };
+void *fn4 ();
+extern F d;
+extern B k;
+extern void baz (int);