[PATCH][PR tree-optimization/68198] Avoid CFG explosion due to threading
authorlaw <law@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 19 Nov 2015 00:33:27 +0000 (00:33 +0000)
committerlaw <law@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 19 Nov 2015 00:33:27 +0000 (00:33 +0000)
PR tree-optimization/68198
* tree-ssa-threadupdate.c (valid_jump_thread_path): Distinguish
between threading a multi-way branch and a thread path that contains
a multi-way branch.  Disallow the case where a path contains a
multi-way branch and does not thread a multi-way branch.
(thread_through_all_blocks): Update comment.

        PR tree-optimization/68198
* gcc.dg/tree-ssa/pr66752-3.c: Update expected output for VRP1.
* gcc.dg/tree-ssa/pr68198.c: New test.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@230586 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/tree-ssa/pr66752-3.c
gcc/testsuite/gcc.dg/tree-ssa/pr68198.c [new file with mode: 0644]
gcc/tree-ssa-threadupdate.c

index 4b788d3..26ddccc 100644 (file)
@@ -1,3 +1,12 @@
+2015-11-18  Jeff Law  <law@redhat.com>
+
+       PR tree-optimization/68198
+       * tree-ssa-threadupdate.c (valid_jump_thread_path): Distinguish
+       between threading a multi-way branch and a thread path that contains
+       a multi-way branch.  Disallow the case where a path contains a
+       multi-way branch and does not thread a multi-way branch.
+       (thread_through_all_blocks): Update comment.
+
 2015-11-18  Joseph Myers  <joseph@codesourcery.com>
 
        PR c/65083
index 8109c33..48f536f 100644 (file)
@@ -1,3 +1,9 @@
+2015-11-18  Jeff Law  <law@redhat.com>
+
+        PR tree-optimization/68198
+       * gcc.dg/tree-ssa/pr66752-3.c: Update expected output for VRP1.
+       * gcc.dg/tree-ssa/pr68198.c: New test.
+
 2015-11-18  Steven G. Kargl  <kargl@gcc.gnu.org>
 
        PR fortran/59910
index 577a489..1f27b1a 100644 (file)
@@ -32,8 +32,10 @@ foo (int N, int c, int b, int *a)
    pt--;
 }
 
-/* There are 3 FSM jump threading opportunities.  */
-/* { dg-final { scan-tree-dump-times "FSM" 3 "vrp1"} } */
+/* There are 3 FSM jump threading opportunities, one of which will
+   get cancelled.  */
+/* { dg-final { scan-tree-dump-times "Registering FSM" 3 "vrp1"} } */
+/* { dg-final { scan-tree-dump-times "Cancelling FSM" 1 "vrp1"} } */
 
 /* There should be no assignments or references to FLAG.  */
 /* { dg-final { scan-tree-dump-not "flag" "optimized"} } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr68198.c b/gcc/testsuite/gcc.dg/tree-ssa/pr68198.c
new file mode 100644 (file)
index 0000000..ddd3c76
--- /dev/null
@@ -0,0 +1,43 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-vrp1-details" } */
+
+extern void abort (void);
+
+typedef union tree_node *tree;
+union tree_node
+{
+  int code;
+  tree chain;
+  int omp_code;
+}
+bitmap_head;
+
+extern int c_omp_predetermined_sharing (tree);
+
+tree
+c_finish_omp_clauses (tree clauses)
+{
+  tree c, t, *pc = &clauses;
+  for (pc = &clauses, c = clauses; c; c = *pc)
+    {
+      unsigned char remove = 0;
+      switch (((c->omp_code)))
+       {
+       case 1:
+         if (t->code != 42)
+           remove = 1;
+         switch (c_omp_predetermined_sharing (t))
+           {
+           case 2:
+             abort ();
+           }
+       }
+      if (remove)
+       *pc = c->chain;
+    }
+}
+
+/* There are 3 FSM jump threading opportunities, two of which will
+  get cancelled.  */
+/* { dg-final { scan-tree-dump-times "Registering FSM" 3 "vrp1"} } */
+/* { dg-final { scan-tree-dump-times "Cancelling FSM" 2 "vrp1"} } */
index c527206..3dd0e4f 100644 (file)
@@ -2370,11 +2370,13 @@ static bool
 valid_jump_thread_path (vec<jump_thread_edge *> *path)
 {
   unsigned len = path->length ();
-  bool multiway_branch = false;
+  bool threaded_multiway_branch = false;
+  bool multiway_branch_in_path = false;
   bool threaded_through_latch = false;
 
   /* Check that the path is connected and see if there's a multi-way
-     branch on the path.  */
+     branch on the path and whether or not a multi-way branch
+     is threaded.  */
   for (unsigned int j = 0; j < len - 1; j++)
     {
       edge e = (*path)[j]->e;
@@ -2394,7 +2396,12 @@ valid_jump_thread_path (vec<jump_thread_edge *> *path)
        threaded_through_latch = true;
 
       gimple *last = last_stmt (e->dest);
-      multiway_branch |= (last && gimple_code (last) == GIMPLE_SWITCH);
+      if (j == len - 2)
+       threaded_multiway_branch
+         |= (last && gimple_code (last) == GIMPLE_SWITCH);
+      else
+       multiway_branch_in_path
+         |= (last && gimple_code (last) == GIMPLE_SWITCH);
     }
 
   /* If we are trying to thread through the loop latch to a block in the
@@ -2402,8 +2409,33 @@ valid_jump_thread_path (vec<jump_thread_edge *> *path)
      irreducible loop.  We avoid that unless the jump thread has a multi-way
      branch, in which case we have deemed it worth losing other
      loop optimizations later if we can eliminate the multi-way branch.  */
-  if (!multiway_branch && threaded_through_latch)
-    return false;
+  if (!threaded_multiway_branch && threaded_through_latch)
+    {
+      if (dump_file && (dump_flags & TDF_DETAILS))
+       {
+         fprintf (dump_file,
+                  "Thread through latch without threading a multiway "
+                  "branch.\n");
+         dump_jump_thread_path (dump_file, *path, false);
+       }
+      return false;
+    }
+
+  /* When there is a multi-way branch on the path, then threading can
+     explode the CFG due to duplicating the edges for that multi-way
+     branch.  So like above, only allow a multi-way branch on the path
+     if we actually thread a multi-way branch.  */
+  if (!threaded_multiway_branch && multiway_branch_in_path)
+    {
+      if (dump_file && (dump_flags & TDF_DETAILS))
+       {
+         fprintf (dump_file,
+                  "Thread through multiway branch without threading "
+                  "a multiway branch.\n");
+         dump_jump_thread_path (dump_file, *path, false);
+       }
+      return false;
+    }
 
   return true;
 }
@@ -2494,11 +2526,8 @@ thread_through_all_blocks (bool may_peel_loop_headers)
 
       /* Do not jump-thread twice from the same block.  */
       if (bitmap_bit_p (threaded_blocks, entry->src->index)
-         /* Verify that the jump thread path is still valid: a
-            previous jump-thread may have changed the CFG, and
-            invalidated the current path or the requested jump
-            thread might create irreducible loops which should
-            generally be avoided.  */
+         /* We may not want to realize this jump thread path
+            for various reasons.  So check it first.  */
          || !valid_jump_thread_path (path))
        {
          /* Remove invalid FSM jump-thread paths.  */