From 45beb02eb0ab4714349e56e854c96cf2910a1f1b Mon Sep 17 00:00:00 2001 From: Sebastian Pop Date: Fri, 6 Feb 2015 21:08:13 +0000 Subject: [PATCH] PR 64878: do not jump thread across more than one back-edge 2015-02-04 Sebastian Pop Brian Rzycki 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 From-SVN: r220491 --- gcc/ChangeLog | 8 + gcc/testsuite/ChangeLog | 6 + .../gcc.dg/tree-ssa/ssa-dom-thread-8.c | 440 ++++++++++++++++++ gcc/tree-ssa-threadedge.c | 19 +- 4 files changed, 470 insertions(+), 3 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-8.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 531ffa0b30d..fb908510615 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2015-02-06 Sebastian Pop + Brian Rzycki + + 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 * toplev.c (process_options): Change flag_ipa_ra before creating diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 8855d27ff38..e10f7782b44 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2015-02-06 Sebastian Pop + Brian Rzycki + + PR tree-optimization/64878 + * testsuite/gcc.dg/tree-ssa/ssa-dom-thread-8.c: New. + 2015-02-06 Jakub Jelinek 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 00000000000..9be75aaf21d --- /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 9e10e446bc9..4f839910a84 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 *visited_phis, - vec *&path) + vec *&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 *visited_phis = new hash_set; 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); -- 2.30.2