[PATCH] Don't allow FSM threader to create irreducible loops unless it eliminates...
authorJeff Law <law@redhat.com>
Mon, 19 Oct 2015 16:24:00 +0000 (10:24 -0600)
committerJeff Law <law@gcc.gnu.org>
Mon, 19 Oct 2015 16:24:00 +0000 (10:24 -0600)
* tree-ssa-threadupdate.c (valid_jump_thread_path): Reject paths
that create irreducible loops unless the path elimiantes a multiway
branch.

From-SVN: r228974

gcc/ChangeLog
gcc/tree-ssa-threadupdate.c

index 89a42c141be64bbd6483493aa505e0876af5ad9a..ff3d3fc6efc88b777a8d766fd88b3ad7b4516554 100644 (file)
@@ -1,3 +1,9 @@
+2015-10-19  Jeff Law  <law@redhat.com>
+
+       * tree-ssa-threadupdate.c (valid_jump_thread_path): Reject paths
+       that create irreducible loops unless the path elimiantes a multiway
+       branch.
+
 2015-10-19  Richard Biener  <rguenther@suse.de>
 
        PR tree-optimization/67975
index 5632a888e46141b077a9966bb835335617fbfa29..8e3437a8ff58771e2235eb7899f47fc78e372135 100644 (file)
@@ -2553,11 +2553,31 @@ static bool
 valid_jump_thread_path (vec<jump_thread_edge *> *path)
 {
   unsigned len = path->length ();
+  bool multiway_branch = false;
 
-  /* Check that the path is connected.  */
+  /* Check that the path is connected and see if there's a multi-way
+     branch on the path.  */
   for (unsigned int j = 0; j < len - 1; j++)
-    if ((*path)[j]->e->dest != (*path)[j+1]->e->src)
-      return false;
+    {
+      if ((*path)[j]->e->dest != (*path)[j+1]->e->src)
+        return false;
+      gimple *last = last_stmt ((*path)[j]->e->dest);
+      multiway_branch |= (last && gimple_code (last) == GIMPLE_SWITCH);
+    }
+
+  /* If we are trying to thread the loop latch to a block that does
+     not dominate the loop latch, then that will create an 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.  */
+  edge e = (*path)[0]->e;
+  struct loop *loop = e->dest->loop_father;
+  if (!multiway_branch
+      && loop->latch
+      && loop_latch_edge (loop) == e
+      && (determine_bb_domination_status (loop, path->last ()->e->dest)
+         == DOMST_NONDOMINATING))
+    return false;
 
   return true;
 }
@@ -2650,7 +2670,9 @@ thread_through_all_blocks (bool may_peel_loop_headers)
       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.  */
+            invalidated the current path or the requested jump
+            thread might create irreducible loops which should
+            generally be avoided.  */
          || !valid_jump_thread_path (path))
        {
          /* Remove invalid FSM jump-thread paths.  */