aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSebastian Pop <s.pop@samsung.com>2015-02-06 21:08:13 +0000
committerSebastian Pop <spop@gcc.gnu.org>2015-02-06 21:08:13 +0000
commit45beb02eb0ab4714349e56e854c96cf2910a1f1b (patch)
tree08d97221c46417aa09ef53738c958a0a4940782d
parentf3ab4eedf1fdaa2f52c587a9e2b91255df32fcc1 (diff)
downloadgcc-45beb02eb0ab4714349e56e854c96cf2910a1f1b.zip
gcc-45beb02eb0ab4714349e56e854c96cf2910a1f1b.tar.gz
gcc-45beb02eb0ab4714349e56e854c96cf2910a1f1b.tar.bz2
PR 64878: do not jump thread across more than one back-edge
2015-02-04 Sebastian Pop <s.pop@samsung.com> Brian Rzycki <b.rzycki@samsung.com> PR tree-optimization/64878 * tree-ssa-threadedge.c: Include tree-ssa-loop.h. (fsm_find_control_statement_thread_paths): Add parameter seen_loop_phi. Stop recursion at loop phi nodes after having visited a loop phi node. * testsuite/gcc.dg/tree-ssa/ssa-dom-thread-8.c: New. Co-Authored-By: Brian Rzycki <b.rzycki@samsung.com> From-SVN: r220491
-rw-r--r--gcc/ChangeLog8
-rw-r--r--gcc/testsuite/ChangeLog6
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-8.c440
-rw-r--r--gcc/tree-ssa-threadedge.c19
4 files changed, 470 insertions, 3 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 531ffa0..fb90851 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,11 @@
+2015-02-06 Sebastian Pop <s.pop@samsung.com>
+ Brian Rzycki <b.rzycki@samsung.com>
+
+ PR tree-optimization/64878
+ * tree-ssa-threadedge.c: Include tree-ssa-loop.h.
+ (fsm_find_control_statement_thread_paths): Add parameter seen_loop_phi.
+ Stop recursion at loop phi nodes after having visited a loop phi node.
+
2015-02-06 Jakub Jelinek <jakub@redhat.com>
* toplev.c (process_options): Change flag_ipa_ra before creating
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 8855d27..e10f778 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,9 @@
+2015-02-06 Sebastian Pop <s.pop@samsung.com>
+ Brian Rzycki <b.rzycki@samsung.com>
+
+ PR tree-optimization/64878
+ * testsuite/gcc.dg/tree-ssa/ssa-dom-thread-8.c: New.
+
2015-02-06 Jakub Jelinek <jakub@redhat.com>
PR ipa/64896
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-8.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-8.c
new file mode 100644
index 0000000..9be75aa
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-8.c
@@ -0,0 +1,440 @@
+/* PR 64878 */
+/* { dg-options "-O2" } */
+/* { dg-do run } */
+
+struct A { int a1; };
+struct B { char *b1; int b2; int b3; };
+struct C { char *c1; int c2; struct B *c3; };
+extern struct A *f1 (char *s);
+static struct A *f2 (struct C *x);
+__attribute__ ((noinline, noclone)) int f3 (struct A *x, struct A *z) { asm volatile ("" : : "g" (x), "g" (z) : "memory"); return 0; }
+__attribute__ ((noinline, noclone)) void f4 (struct A *x, char *y, struct A *z) { asm volatile ("" : : "g" (x), "g" (z), "g" (y) : "memory"); }
+__attribute__ ((noinline, noclone)) struct B *f5 (void) { static char b[32]; static struct B f3 = { b, 0, 32 }; return &f3; }
+__attribute__ ((noinline, noclone)) int f6 (struct B *p, char *w, int z) { asm volatile ("" : : "g" (p), "g" (w), "g" (z) : "memory"); return 0; }
+__attribute__ ((noinline, noclone)) void f7 (struct B *p) { asm volatile ("" : : "g" (p) : "memory"); }
+__attribute__ ((noinline, noclone)) void f8 (struct B *p) { asm volatile ("" : : "g" (p) : "memory"); }
+__attribute__ ((noinline, noclone)) void f9 (struct A *x) { asm volatile ("" : : "g" (x) : "memory"); }
+__attribute__ ((noinline, noclone)) struct A *f10 (void) { static struct A j; asm volatile ("" : : : "memory"); return &j; }
+__attribute__ ((noinline, noclone)) struct A *f11 (void) { static struct A j; asm volatile ("" : : : "memory"); return &j; }
+__attribute__ ((noinline, noclone)) struct A *f12 (int b) { static struct A j; asm volatile ("" : : "g" (b) : "memory"); return &j; }
+__attribute__ ((noinline, noclone)) struct A *f13 (int i) { static struct A j; asm volatile ("" : : "g" (i) : "memory"); return &j; }
+__attribute__ ((noinline, noclone)) struct A *f14 (double d) { static struct A j; asm volatile ("" : : "g" (&d) : "memory"); return &j; }
+__attribute__ ((noinline, noclone)) struct A *f15 (char *s) { static struct A j; asm volatile ("" : : "g" (s) : "memory"); return &j; }
+char *t = "0123456789abcdef";
+char *u = "0123456789.+-e";
+
+__attribute__ ((noinline, noclone)) struct A *
+f1 (char *s)
+{
+ struct C f;
+ struct A *o;
+ f.c1 = s;
+ f.c2 = 0;
+ f.c3 = f5 ();
+ o = f2 (&f);
+ f8 (f.c3);
+ return o;
+}
+
+static struct A *
+f2 (struct C *x)
+{
+ int a, b, e = 0;
+ struct A *f = 0, *o;
+ char *g = 0;
+ char h = '\0';
+ int i = 0, j = 0;
+ a = 0;
+ b = 1;
+ char c;
+ do
+ {
+ c = x->c1[x->c2];
+ switch (a)
+ {
+ case 0:
+ if (c == ' ')
+ x->c2++;
+ else if (c == '/')
+ {
+ a = 4;
+ j = x->c2++;
+ }
+ else
+ a = b;
+ break;
+ case 1:
+ switch (c)
+ {
+ case '{':
+ a = 0;
+ b = 15;
+ f = f10 ();
+ x->c2++;
+ break;
+ case '[':
+ a = 0;
+ b = 13;
+ f = f11 ();
+ x->c2++;
+ break;
+ case 'N':
+ case 'n':
+ a = 3;
+ j = x->c2++;
+ break;
+ case '"':
+ case '\'':
+ h = c;
+ f7 (x->c3);
+ a = 8;
+ j = ++x->c2;
+ break;
+ case 'T':
+ case 't':
+ case 'F':
+ case 'f':
+ a = 11;
+ j = x->c2++;
+ break;
+ case '0' ... '9':
+ case '-':
+ i = 0;
+ a = 12;
+ j = x->c2++;
+ break;
+ default:
+ e = 1;
+ goto out;
+ }
+ break;
+ case 2:
+ goto out;
+ case 3:
+ if (__builtin_strncmp ("null", x->c1 + j, x->c2 - j))
+ {
+ e = 2;
+ goto out;
+ }
+ if (x->c2 - j == 4)
+ {
+ f = 0;
+ b = 2;
+ a = 0;
+ }
+ else
+ x->c2++;
+ break;
+ case 4:
+ if (c == '*')
+ a = 5;
+ else if (c == '/')
+ a = 6;
+ else
+ {
+ e = 8;
+ goto out;
+ }
+ x->c2++;
+ break;
+ case 5:
+ if (c == '*')
+ a = 7;
+ x->c2++;
+ break;
+ case 6:
+ if (c == '\n')
+ a = 0;
+ x->c2++;
+ break;
+ case 7:
+ if (c == '/')
+ a = 0;
+ else
+ a = 5;
+ x->c2++;
+ break;
+ case 8:
+ if (c == h)
+ {
+ f6 (x->c3, x->c1 + j, x->c2 - j);
+ f = f15 (x->c3->b1);
+ b = 2;
+ a = 0;
+ }
+ else if (c == '\\')
+ {
+ b = 8;
+ a = 9;
+ }
+ x->c2++;
+ break;
+ case 9:
+ switch (c)
+ {
+ case '"':
+ case '\\':
+ f6 (x->c3, x->c1 + j, x->c2 - j - 1);
+ j = x->c2++;
+ a = b;
+ break;
+ case 'b':
+ case 'n':
+ case 'r':
+ case 't':
+ f6 (x->c3, x->c1 + j, x->c2 - j - 1);
+ if (c == 'b')
+ f6 (x->c3, "\b", 1);
+ else if (c == 'n')
+ f6 (x->c3, "\n", 1);
+ else if (c == 'r')
+ f6 (x->c3, "\r", 1);
+ else if (c == 't')
+ f6 (x->c3, "\t", 1);
+ j = ++x->c2;
+ a = b;
+ break;
+ case 'u':
+ f6 (x->c3, x->c1 + j, x->c2 - j - 1);
+ j = ++x->c2;
+ a = 10;
+ break;
+ default:
+ e = 7;
+ goto out;
+ }
+ break;
+ case 10:
+ if (__builtin_strchr (t, c))
+ {
+ x->c2++;
+ if (x->c2 - j == 4)
+ {
+ unsigned char w[3];
+ unsigned int s =
+ (((x->c1[j] <= '9') ? x->c1[j] - '0' : (x->c1[j] & 7) + 9) << 12)
+ + (((x->c1[j + 1] <= '9') ? x->c1[j + 1] - '0' : (x->c1[j + 1] & 7) + 9) << 8)
+ + (((x->c1[j + 2] <= '9') ? x->c1[j + 2] - '0' : (x->c1[j + 2] & 7) + 9) << 4)
+ + ((x->c1[j + 3] <= '9') ? x->c1[j + 3] - '0' : (x->c1[j + 3] & 7) + 9);
+ if (s < 0x80)
+ {
+ w[0] = s;
+ f6 (x->c3, (char *) w, 1);
+ }
+ else if (s < 0x800)
+ {
+ w[0] = 0xc0 | (s >> 6);
+ w[1] = 0x80 | (s & 0x3f);
+ f6 (x->c3, (char *) w, 2);
+ }
+ else
+ {
+ w[0] = 0x0 | (s >> 12);
+ w[1] = 0x80 | ((s >> 6) & 0x3f);
+ w[2] = 0x80 | (s & 0x3f);
+ f6 (x->c3, (char *) w, 3);
+ }
+ j = x->c2;
+ a = b;
+ }
+ }
+ else
+ {
+ e = 7;
+ goto out;
+ }
+ break;
+ case 11:
+ if (__builtin_strncmp ("true", x->c1 + j, x->c2 - j) == 0)
+ {
+ if (x->c2 - j == 4)
+ {
+ f = f12 (1);
+ b = 2;
+ a = 0;
+ }
+ else
+ x->c2++;
+ }
+ else if (__builtin_strncmp ("false", x->c1 + j, x->c2 - j) == 0)
+ {
+ if (x->c2 - j == 5)
+ {
+ f = f12 (0);
+ b = 2;
+ a = 0;
+ }
+ else
+ x->c2++;
+ }
+ else
+ {
+ e = 3;
+ goto out;
+ }
+ break;
+ case 12:
+ if (!c || !__builtin_strchr (u, c))
+ {
+ if (!i)
+ f = f13 (0);
+ else
+ f = f14 (0.0);
+ b = 2;
+ a = 0;
+ }
+ else
+ {
+ if (c == '.' || c == 'e')
+ i = 1;
+ x->c2++;
+ }
+ break;
+ case 13:
+ if (c == ']')
+ {
+ x->c2++;
+ b = 2;
+ a = 0;
+ }
+ else
+ {
+ o = f2 (x);
+ if (((unsigned long) o > (unsigned long) -4000L))
+ {
+ e = 5;
+ goto out;
+ }
+ f3 (f, o);
+ b = 14;
+ a = 0;
+ }
+ break;
+ case 14:
+ if (c == ']')
+ {
+ x->c2++;
+ b = 2;
+ a = 0;
+ }
+ else if (c == ',')
+ {
+ x->c2++;
+ b = 13;
+ a = 0;
+ }
+ else
+ {
+ f9 (f);
+ e = 5;
+ goto out;
+ }
+ break;
+ case 15:
+ a = 16;
+ j = x->c2;
+ break;
+ case 16:
+ if (c == '}')
+ {
+ x->c2++;
+ b = 2;
+ a = 0;
+ }
+ else if (c == '"' || c == '\'')
+ {
+ h = c;
+ f7 (x->c3);
+ a = 17;
+ j = ++x->c2;
+ }
+ else
+ {
+ e = 6;
+ goto out;
+ }
+ break;
+ case 17:
+ if (c == h)
+ {
+ f6 (x->c3, x->c1 + j, x->c2 - j);
+ g = __builtin_strdup (x->c3->b1);
+ b = 18;
+ a = 0;
+ }
+ else if (c == '\\')
+ {
+ b = 17;
+ a = 9;
+ }
+ x->c2++;
+ break;
+ case 18:
+ if (c == ':')
+ {
+ x->c2++;
+ b = 19;
+ a = 0;
+ }
+ else
+ {
+ e = -6;
+ goto out;
+ }
+ break;
+ case 19:
+ o = f2 (x);
+ if (((unsigned long) o > (unsigned long) -4000L))
+ {
+ e = 6;
+ goto out;
+ }
+ f4 (f, g, o);
+ __builtin_free (g);
+ g = 0;
+ b = 20;
+ a = 0;
+ break;
+ case 20:
+ if (c == '}')
+ {
+ x->c2++;
+ b = 2;
+ a = 0;
+ }
+ else if (c == ',')
+ {
+ x->c2++;
+ b = 15;
+ a = 0;
+ }
+ else
+ {
+ e = 6;
+ goto out;
+ }
+ break;
+ }
+ }
+ while (c);
+ if (a != 2 && b != 2)
+ e = 9;
+out:
+ __builtin_free (g);
+ if (e == 0)
+ return f;
+ f9 (f);
+ return 0;
+}
+
+int
+main ()
+{
+ asm volatile ("" : : : "memory");
+ struct A *r = f1 ("{ \"id\": null, \"blahah\": \"foobarbazbar\", \"barbar\": { \"barbarbarba\":"
+ "\"abcdefgh\", \"ijklmnopqr\": \"stuvwxyzabcdefghijklmnopqrstuv\", \"xyzxyz\":"
+ " [ \"1\" ] } }");
+ if (!r)
+ __builtin_abort ();
+ return 0;
+}
diff --git a/gcc/tree-ssa-threadedge.c b/gcc/tree-ssa-threadedge.c
index 9e10e44..4f83991 100644
--- a/gcc/tree-ssa-threadedge.c
+++ b/gcc/tree-ssa-threadedge.c
@@ -61,6 +61,7 @@ along with GCC; see the file COPYING3. If not see
#include "langhooks.h"
#include "params.h"
#include "tree-ssa-threadedge.h"
+#include "tree-ssa-loop.h"
#include "builtins.h"
#include "cfg.h"
#include "cfganal.h"
@@ -1006,7 +1007,8 @@ static int max_threaded_paths;
static void
fsm_find_control_statement_thread_paths (tree expr,
hash_set<gimple> *visited_phis,
- vec<basic_block, va_gc> *&path)
+ vec<basic_block, va_gc> *&path,
+ bool seen_loop_phi)
{
tree var = SSA_NAME_VAR (expr);
gimple def_stmt = SSA_NAME_DEF_STMT (expr);
@@ -1030,6 +1032,14 @@ fsm_find_control_statement_thread_paths (tree expr,
int next_path_length = 0;
basic_block last_bb_in_path = path->last ();
+ if (loop_containing_stmt (phi)->header == gimple_bb (phi))
+ {
+ /* Do not walk through more than one loop PHI node. */
+ if (seen_loop_phi)
+ return;
+ seen_loop_phi = true;
+ }
+
/* Following the chain of SSA_NAME definitions, we jumped from a definition in
LAST_BB_IN_PATH to a definition in VAR_BB. When these basic blocks are
different, append to PATH the blocks from LAST_BB_IN_PATH to VAR_BB. */
@@ -1090,7 +1100,9 @@ fsm_find_control_statement_thread_paths (tree expr,
{
vec_safe_push (path, bbi);
/* Recursively follow SSA_NAMEs looking for a constant definition. */
- fsm_find_control_statement_thread_paths (arg, visited_phis, path);
+ fsm_find_control_statement_thread_paths (arg, visited_phis, path,
+ seen_loop_phi);
+
path->pop ();
continue;
}
@@ -1357,7 +1369,8 @@ thread_through_normal_block (edge e,
hash_set<gimple> *visited_phis = new hash_set<gimple>;
max_threaded_paths = PARAM_VALUE (PARAM_MAX_FSM_THREAD_PATHS);
- fsm_find_control_statement_thread_paths (cond, visited_phis, bb_path);
+ fsm_find_control_statement_thread_paths (cond, visited_phis, bb_path,
+ false);
delete visited_phis;
vec_free (bb_path);