PR 64878: do not jump thread across more than one back-edge
authorSebastian Pop <s.pop@samsung.com>
Fri, 6 Feb 2015 21:08:13 +0000 (21:08 +0000)
committerSebastian Pop <spop@gcc.gnu.org>
Fri, 6 Feb 2015 21:08:13 +0000 (21:08 +0000)
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

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-8.c [new file with mode: 0644]
gcc/tree-ssa-threadedge.c

index 531ffa0b30d8fc5a7539b5977b0b8d3b73b1c46c..fb908510615d7c2f58e78eb8f1b8d1ffaf7f259d 100644 (file)
@@ -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
index 8855d27ff3898921fd85c3c7a690d450eb35d1e2..e10f7782b44846f04c8a76c76f42d4a837f26610 100644 (file)
@@ -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 (file)
index 0000000..9be75aa
--- /dev/null
@@ -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;
+}
index 9e10e446bc9e41e6d706d4dc3cc3e2fc1c360934..4f839910a84c686644c59daf3c2b63e74250eeb1 100644 (file)
@@ -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);