[PATCH] Avoid more irreducible loops in FSM threader
authorJeff Law <law@gcc.gnu.org>
Mon, 2 Nov 2015 23:25:06 +0000 (16:25 -0700)
committerJeff Law <law@gcc.gnu.org>
Mon, 2 Nov 2015 23:25:06 +0000 (16:25 -0700)
* tree-ssa-threadupdate.c (valid_jump_thread_path): Also detect
cases where the loop latch edge is in the middle of an FSM
path.

* gcc.dg/tree-ssa/ssa-thread-11.c: Verify that we do not have
irreducible loops in the CFG.

From-SVN: r229685

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/tree-ssa/ssa-thread-11.c
gcc/tree-ssa-threadupdate.c

index 3613a68543e7141f920a698d947457803ba458f6..6a7d988c626d4aff8b8e92a28a6bab7b54bb0a69 100644 (file)
@@ -1,3 +1,9 @@
+2015-11-02  Jeff Law <jeff@redhat.com>
+
+       * tree-ssa-threadupdate.c (valid_jump_thread_path): Also detect
+       cases where the loop latch edge is in the middle of an FSM
+       path.
+
 2015-11-03  Tom de Vries  <tom@codesourcery.com>
 
        * tree-ssa-structalias.c (make_restrict_var_constraints): Rename to ...
index a86920a02ecb41927849eb82d8b6ae11706e8c05..3dc4edcfd971d4fcf6d5e3fbff2a978a790610e1 100644 (file)
@@ -1,3 +1,8 @@
+2015-11-02  Jeff Law  <law@redhat.com>
+
+       * gcc.dg/tree-ssa/ssa-thread-11.c: Verify that we do not have
+       irreducible loops in the CFG.
+
 2015-11-02  Alan Lawrence  <alan.lawrence@arm.com>
 
        Revert:
index 6a076e105af4c3020d780a0dd29a69fb88990062..a729f5637a53238b33ed1ddbb6ded2de81486919 100644 (file)
@@ -1,5 +1,6 @@
 /* { dg-do compile { target { ! { logical_op_short_circuit || { m68k*-*-* mep*-*-* bfin*-*-* v850*-*-* moxie*-*-* m32c*-*-* fr30*-*-* mcore*-*-* frv-*-* h8300-*-* m32r-*-* mn10300-*-* msp430-*-* pdp11-*-* rl78-*-* rx-*-* vax-*-*} } } } } */
 /* { dg-options "-O2 -fdump-tree-vrp2-details" } */
+/* { dg-final { scan-tree-dump-not "IRREDUCIBLE_LOOP" "vrp2" } } */
 /* { dg-final { scan-tree-dump "FSM" "vrp2" } } */
 
 void abort (void);
index 511433aa76a50890471fe4639dea368334703418..68650e598fe8f3440cc14ef6e828ac573c9dfade 100644 (file)
@@ -2547,29 +2547,38 @@ valid_jump_thread_path (vec<jump_thread_edge *> *path)
 {
   unsigned len = path->length ();
   bool multiway_branch = false;
+  bool threaded_through_latch = false;
 
   /* 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)
+      edge e = (*path)[j]->e;
+      struct loop *loop = e->dest->loop_father;
+
+      if (e->dest != (*path)[j+1]->e->src)
         return false;
-      gimple *last = last_stmt ((*path)[j]->e->dest);
+
+      /* If we're threading through the loop latch back into the
+        same loop and the destination does not dominate the loop
+        latch, then this thread would create an irreducible loop.  */
+      if (loop->latch
+         && loop_latch_edge (loop) == e
+         && loop == path->last()->e->dest->loop_father
+         && (determine_bb_domination_status (loop, path->last ()->e->dest)
+              == DOMST_NONDOMINATING))
+       threaded_through_latch = true;
+
+      gimple *last = last_stmt (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
+  /* If we are trying to thread through the loop latch to a block in the
+     loop 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))
+  if (!multiway_branch && threaded_through_latch)
     return false;
 
   return true;