diff mbox

Consistently detect traversing back edges in threader

Message ID 5282B68A.9000509@redhat.com
State New
Headers show

Commit Message

Jeff Law Nov. 12, 2013, 11:15 p.m. UTC
I expect there'll be a follow-up or two with the code that checks 
EDGE_DFS_BACK when discovering jump thread opportunities, but I already 
know I need a way to track if *any* edge on a path is a back edge.  This 
patch adds that capability by accumulating state for each edge into a 
boolean as the edges are added to the path.

Bootstrapped and regression tested on x86_64-unknown-linux-gnu. 
Installed on the trunk.

Jeff
* tree-ssa-threadedge.c (thread_around_empty_blocks): New
	argument backedge_seen_p.  Set, use and pass it to children
	appropriately.
	(thread_through_normal_block): Similarly.
	(thread_across_edge): Similarly.
diff mbox

Patch

diff --git a/gcc/tree-ssa-threadedge.c b/gcc/tree-ssa-threadedge.c
index cd2b34a..0c9dcda 100644
--- a/gcc/tree-ssa-threadedge.c
+++ b/gcc/tree-ssa-threadedge.c
@@ -760,7 +760,8 @@  thread_around_empty_blocks (edge taken_edge,
 			    bool handle_dominating_asserts,
 			    tree (*simplify) (gimple, gimple),
 			    bitmap visited,
-			    vec<jump_thread_edge *> *path)
+			    vec<jump_thread_edge *> *path,
+			    bool *backedge_seen_p)
 {
   basic_block bb = taken_edge->dest;
   gimple_stmt_iterator gsi;
@@ -795,19 +796,20 @@  thread_around_empty_blocks (edge taken_edge,
       if (single_succ_p (bb))
 	{
 	  taken_edge = single_succ_edge (bb);
-	  if ((taken_edge->flags & EDGE_DFS_BACK) == 0
-	      && !bitmap_bit_p (visited, taken_edge->dest->index))
+	  if (!bitmap_bit_p (visited, taken_edge->dest->index))
 	    {
 	      jump_thread_edge *x
 		= new jump_thread_edge (taken_edge, EDGE_NO_COPY_SRC_BLOCK);
 	      path->safe_push (x);
 	      bitmap_set_bit (visited, taken_edge->dest->index);
+	      *backedge_seen_p |= ((taken_edge->flags & EDGE_DFS_BACK) != 0);
 	      return thread_around_empty_blocks (taken_edge,
 						 dummy_cond,
 						 handle_dominating_asserts,
 						 simplify,
 						 visited,
-						 path);
+						 path,
+						 backedge_seen_p);
 	    }
 	}
 
@@ -841,13 +843,15 @@  thread_around_empty_blocks (edge taken_edge,
       jump_thread_edge *x
 	= new jump_thread_edge (taken_edge, EDGE_NO_COPY_SRC_BLOCK);
       path->safe_push (x);
+      *backedge_seen_p |= ((taken_edge->flags & EDGE_DFS_BACK) != 0);
 
       thread_around_empty_blocks (taken_edge,
 				  dummy_cond,
 				  handle_dominating_asserts,
 				  simplify,
 				  visited,
-				  path);
+				  path,
+				  backedge_seen_p);
       return true;
     }
 
@@ -889,17 +893,16 @@  thread_through_normal_block (edge e,
 			     vec<tree> *stack,
 			     tree (*simplify) (gimple, gimple),
 			     vec<jump_thread_edge *> *path,
-			     bitmap visited)
+			     bitmap visited,
+			     bool *backedge_seen_p)
 {
-  /* If E is a backedge, then we want to verify that the COND_EXPR,
+  /* If we have crossed a backedge, then we want to verify that the COND_EXPR,
      SWITCH_EXPR or GOTO_EXPR at the end of e->dest is not affected
      by any statements in e->dest.  If it is affected, then it is not
      safe to thread this edge.  */
-  if (e->flags & EDGE_DFS_BACK)
-    {
-      if (cond_arg_set_in_bb (e, e->dest))
-	return false;
-    }
+  if (*backedge_seen_p
+      && cond_arg_set_in_bb (e, e->dest))
+    return false;
 
   /* PHIs create temporary equivalences.  */
   if (!record_temporary_equivalences_from_phis (e, stack))
@@ -931,20 +934,24 @@  thread_through_normal_block (edge e,
 
 	  /* DEST could be NULL for a computed jump to an absolute
 	     address.  */
-	  if (dest == NULL || dest == e->dest || bitmap_bit_p (visited, dest->index))
+	  if (dest == NULL
+	      || dest == e->dest
+	      || bitmap_bit_p (visited, dest->index))
 	    return false;
 
           jump_thread_edge *x
 	    = new jump_thread_edge (e, EDGE_START_JUMP_THREAD);
 	  path->safe_push (x);
+	  *backedge_seen_p |= ((e->flags & EDGE_DFS_BACK) != 0);
 
 	  x = new jump_thread_edge (taken_edge, EDGE_COPY_SRC_BLOCK);
 	  path->safe_push (x);
+	  *backedge_seen_p |= ((taken_edge->flags & EDGE_DFS_BACK) != 0);
 
 	  /* See if we can thread through DEST as well, this helps capture
 	     secondary effects of threading without having to re-run DOM or
 	     VRP.  */
-	  if ((e->flags & EDGE_DFS_BACK) == 0
+	  if (!*backedge_seen_p
 	       || ! cond_arg_set_in_bb (taken_edge, e->dest))
 	    {
 	      /* We don't want to thread back to a block we have already
@@ -956,7 +963,8 @@  thread_through_normal_block (edge e,
 					  handle_dominating_asserts,
 					  simplify,
 					  visited,
-					  path);
+					  path,
+					  backedge_seen_p);
 	    }
 	  return true;
 	}
@@ -999,6 +1007,7 @@  thread_across_edge (gimple dummy_cond,
 		    tree (*simplify) (gimple, gimple))
 {
   bitmap visited = BITMAP_ALLOC (NULL);
+  bool backedge_seen;
 
   stmt_count = 0;
 
@@ -1006,8 +1015,10 @@  thread_across_edge (gimple dummy_cond,
   bitmap_clear (visited);
   bitmap_set_bit (visited, e->src->index);
   bitmap_set_bit (visited, e->dest->index);
+  backedge_seen = ((e->flags & EDGE_DFS_BACK) != 0);
   if (thread_through_normal_block (e, dummy_cond, handle_dominating_asserts,
-				   stack, simplify, path, visited))
+				   stack, simplify, path, visited,
+				   &backedge_seen))
     {
       propagate_threaded_block_debug_into (path->last ()->e->dest,
 					   e->dest);
@@ -1067,14 +1078,17 @@  thread_across_edge (gimple dummy_cond,
         x = new jump_thread_edge (taken_edge, EDGE_COPY_SRC_JOINER_BLOCK);
 	path->safe_push (x);
 	found = false;
-	if ((e->flags & EDGE_DFS_BACK) == 0
+	backedge_seen = ((e->flags & EDGE_DFS_BACK) != 0);
+	backedge_seen |= ((taken_edge->flags & EDGE_DFS_BACK) != 0);
+	if (!backedge_seen
 	    || ! cond_arg_set_in_bb (path->last ()->e, e->dest))
 	  found = thread_around_empty_blocks (taken_edge,
 					      dummy_cond,
 					      handle_dominating_asserts,
 					      simplify,
 					      visited,
-					      path);
+					      path,
+					      &backedge_seen);
 
 	/* If we were able to thread through a successor of E->dest, then
 	   record the jump threading opportunity.  */