summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>2016-03-16 17:52:20 +0000
committerjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>2016-03-16 17:52:20 +0000
commit867c9e995539beefa594475f2bd831438e36a077 (patch)
tree0708e09e5edd3bef4be596c6056156cb9c994023
parent8ced6ab75a3a0fcdf1a50ee4d8b0bb57e517ff7b (diff)
downloadgcc-867c9e995539beefa594475f2bd831438e36a077.tar.gz
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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@234265 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog8
-rw-r--r--gcc/rtlanal.c11
-rw-r--r--gcc/testsuite/ChangeLog7
-rw-r--r--gcc/testsuite/g++.dg/opt/pr70245-aux.cc56
-rw-r--r--gcc/testsuite/g++.dg/opt/pr70245.C52
-rw-r--r--gcc/testsuite/g++.dg/opt/pr70245.h14
6 files changed, 147 insertions, 1 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 48941e22bf3..ab80ce4120a 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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
diff --git a/gcc/rtlanal.c b/gcc/rtlanal.c
index bacc5f25f4a..74b593d6935 100644
--- a/gcc/rtlanal.c
+++ b/gcc/rtlanal.c
@@ -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);
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 76b57ea4880..a215b0ca519 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
index 00000000000..7f65f20174f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/opt/pr70245-aux.cc
@@ -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
index 00000000000..21280b7aaf5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/opt/pr70245.C
@@ -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
index 00000000000..b0c54064725
--- /dev/null
+++ b/gcc/testsuite/g++.dg/opt/pr70245.h
@@ -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);