]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR tree-optimization/58640 (wrong code (segfaults) at -O3 on x86_64-linux-gnu)
authorJeff Law <law@redhat.com>
Fri, 11 Oct 2013 20:31:25 +0000 (14:31 -0600)
committerJeff Law <law@gcc.gnu.org>
Fri, 11 Oct 2013 20:31:25 +0000 (14:31 -0600)
PR tree-optimization/58640
* tree-ssa-threadupdate.c (mark_threaded_blocks): Truncate jump threading
paths that cross over two loop entry points.

* gcc.c-torture/execute/pr58640.c: New test.

From-SVN: r203463

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.c-torture/execute/pr58640.c [new file with mode: 0644]
gcc/tree-ssa-threadupdate.c

index 41e29dc534d1988ada7bb8b76dce1875c59a15f0..9f4e2975ae0105900de2615bb877e137ef2c0eb1 100644 (file)
@@ -1,3 +1,9 @@
+2013-10-11  Jeff Law  <law@redhat.com>
+
+       PR tree-optimization/58640
+       * tree-ssa-threadupdate.c (mark_threaded_blocks): Truncate jump threading
+       paths that cross over two loop entry points.
+
 2013-10-11  Bill Schmidt  <wschmidt@linux.vnet.ibm.com>
 
        * config/rs6000/vsx.md (*vsx_le_perm_load_v2di): Generalize to
index 87ff2a7dacaf3a857afe3701cc51a0e598d96412..bb2ede41cb5e5474949205f7b595de0307bbb721 100644 (file)
@@ -1,3 +1,7 @@
+2013-10-11  Jeff Law  <law@redhat.com>
+
+       * gcc.c-torture/execute/pr58640.c: New test.
+
 2013-10-11  Paolo Carlini  <paolo.carlini@oracle.com>
 
        PR c++/58633
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr58640.c b/gcc/testsuite/gcc.c-torture/execute/pr58640.c
new file mode 100644 (file)
index 0000000..7786b8d
--- /dev/null
@@ -0,0 +1,32 @@
+int a, b, c, d = 1, e;
+
+static signed char
+foo ()
+{
+  int f, g = a;
+
+  for (f = 1; f < 3; f++)
+    for (; b < 1; b++)
+      {
+        if (d)
+          for (c = 0; c < 4; c++)
+            for (f = 0; f < 3; f++)
+              {
+                for (e = 0; e < 1; e++)
+                  a = g;
+                if (f)
+                  break;
+              }
+        else if (f)
+          continue;
+        return 0;
+      }
+  return 0;
+}
+
+int
+main ()
+{
+  foo ();
+  exit (0);
+}
index 2adea1b5119e2e229f23b50a596a30f6e7dfc9f2..3e34567d8c128bb66b8378aa196015939751b0c0 100644 (file)
@@ -1354,6 +1354,68 @@ mark_threaded_blocks (bitmap threaded_blocks)
   else
     bitmap_copy (threaded_blocks, tmp);
 
+  /* Look for jump threading paths which cross multiple loop headers.
+
+     The code to thread through loop headers will change the CFG in ways
+     that break assumptions made by the loop optimization code.
+
+     We don't want to blindly cancel the requests.  We can instead do better
+     by trimming off the end of the jump thread path.  */
+  EXECUTE_IF_SET_IN_BITMAP (tmp, 0, i, bi)
+    {
+      basic_block bb = BASIC_BLOCK (i);
+      FOR_EACH_EDGE (e, ei, bb->preds)
+       {
+         if (e->aux)
+           {
+             vec<jump_thread_edge *> *path = THREAD_PATH (e);
+
+             /* Basically we're looking for a situation where we can see
+                3 or more loop structures on a jump threading path.  */
+
+             struct loop *first_father = (*path)[0]->e->src->loop_father;
+             struct loop *second_father = NULL;
+             for (unsigned int i = 0; i < path->length (); i++)
+               {
+                 /* See if this is a loop father we have not seen before.  */
+                 if ((*path)[i]->e->dest->loop_father != first_father
+                     && (*path)[i]->e->dest->loop_father != second_father)
+                   {
+                     /* We've already seen two loop fathers, so we
+                        need to trim this jump threading path.  */
+                     if (second_father != NULL)
+                       {
+                         /* Trim from entry I onwards.  */
+                         for (unsigned int j = i; j < path->length (); j++)
+                           delete (*path)[j];
+                         path->truncate (i);
+
+                         /* Now that we've truncated the path, make sure
+                            what's left is still valid.   We need at least
+                            two edges on the path and the last edge can not
+                            be a joiner.  This should never happen, but let's
+                            be safe.  */
+                         if (path->length () < 2
+                             || (path->last ()->type
+                                 == EDGE_COPY_SRC_JOINER_BLOCK))
+                           {
+                             for (unsigned int i = 0; i < path->length (); i++)
+                               delete (*path)[i];
+                             path->release ();
+                             e->aux = NULL;
+                           }
+                         break;
+                       }
+                     else
+                       {
+                         second_father = (*path)[i]->e->dest->loop_father;
+                       }
+                   }
+               }
+           }
+       }
+    }
+
   BITMAP_FREE (tmp);
 }