This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Refactor a bit of jump thread identification code



This pulls out the code to search for a threading opportunity in a normal block into its own subroutine. No functional changes.

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


diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 065ebf1..cf4a45c 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,10 @@
+2013-10-04  Jeff Law  <law@redhat.com>
+
+	* tree-ssa-threadedge.c: Fix some trailing whitespace problems.
+
+	* tree-ssa-threadedge.c (thread_through_normal_block): Broken out of ...
+	(thread_across_edge): Here.  Call it.
+
 2013-10-04  Cary Coutant  <ccoutant@google.com>
 
 	* dwarf2out.c (dw_sra_loc_expr): Release addr_table entries when
diff --git a/gcc/tree-ssa-threadedge.c b/gcc/tree-ssa-threadedge.c
index 39e921b..c2dd015 100644
--- a/gcc/tree-ssa-threadedge.c
+++ b/gcc/tree-ssa-threadedge.c
@@ -771,7 +771,7 @@ thread_around_empty_blocks (edge taken_edge,
   gsi = gsi_start_nondebug_bb (bb);
 
   /* If the block has no statements, but does have a single successor, then
-     it's just a forwarding block and we can thread through it trivially. 
+     it's just a forwarding block and we can thread through it trivially.
 
      However, note that just threading through empty blocks with single
      successors is not inherently profitable.  For the jump thread to
@@ -779,7 +779,7 @@ thread_around_empty_blocks (edge taken_edge,
 
      By taking the return value from the recursive call, we get the
      desired effect of returning TRUE when we found a profitable jump
-     threading opportunity and FALSE otherwise. 
+     threading opportunity and FALSE otherwise.
 
      This is particularly important when this routine is called after
      processing a joiner block.  Returning TRUE too aggressively in
@@ -844,13 +844,16 @@ thread_around_empty_blocks (edge taken_edge,
 				  path);
       return true;
     }
- 
+
   return false;
 }
-      
+
 /* We are exiting E->src, see if E->dest ends with a conditional
    jump which has a known value when reached via E.
 
+   E->dest can have arbitrary side effects which, if threading is
+   successful, will be maintained.
+
    Special care is necessary if E is a back edge in the CFG as we
    may have already recorded equivalences for E->dest into our
    various tables, including the result of the conditional at
@@ -858,11 +861,6 @@ thread_around_empty_blocks (edge taken_edge,
    limited in that case to avoid short-circuiting the loop
    incorrectly.
 
-   Note it is quite common for the first block inside a loop to
-   end with a conditional which is either always true or always
-   false when reached via the loop backedge.  Thus we do not want
-   to blindly disable threading across a loop backedge.
-
    DUMMY_COND is a shared cond_expr used by condition simplification as scratch,
    to avoid allocating memory.
 
@@ -873,17 +871,19 @@ thread_around_empty_blocks (edge taken_edge,
    STACK is used to undo temporary equivalences created during the walk of
    E->dest.
 
-   SIMPLIFY is a pass-specific function used to simplify statements.  */
+   SIMPLIFY is a pass-specific function used to simplify statements.
 
-void
-thread_across_edge (gimple dummy_cond,
-		    edge e,
-		    bool handle_dominating_asserts,
-		    vec<tree> *stack,
-		    tree (*simplify) (gimple, gimple))
-{
-  gimple stmt;
+   Our caller is responsible for restoring the state of the expression
+   and const_and_copies stacks.  */
 
+static bool
+thread_through_normal_block (edge e,
+			     gimple dummy_cond,
+			     bool handle_dominating_asserts,
+			     vec<tree> *stack,
+			     tree (*simplify) (gimple, gimple),
+			     vec<jump_thread_edge *> *path)
+{
   /* If E is 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
@@ -891,20 +891,19 @@ thread_across_edge (gimple dummy_cond,
   if (e->flags & EDGE_DFS_BACK)
     {
       if (cond_arg_set_in_bb (e, e->dest))
-	goto fail;
+	return false;
     }
 
-  stmt_count = 0;
-
   /* PHIs create temporary equivalences.  */
   if (!record_temporary_equivalences_from_phis (e, stack))
-    goto fail;
+    return false;
 
   /* Now walk each statement recording any context sensitive
      temporary equivalences we can detect.  */
-  stmt = record_temporary_equivalences_from_stmts_at_dest (e, stack, simplify);
+  gimple stmt
+    = record_temporary_equivalences_from_stmts_at_dest (e, stack, simplify);
   if (!stmt)
-    goto fail;
+    return false;
 
   /* If we stopped at a COND_EXPR or SWITCH_EXPR, see if we know which arm
      will be taken.  */
@@ -927,9 +926,8 @@ thread_across_edge (gimple dummy_cond,
 	  /* DEST could be NULL for a computed jump to an absolute
 	     address.  */
 	  if (dest == NULL || dest == e->dest)
-	    goto fail;
+	    return false;
 
-	  vec<jump_thread_edge *> *path = new vec<jump_thread_edge *> ();
           jump_thread_edge *x
 	    = new jump_thread_edge (e, EDGE_START_JUMP_THREAD);
 	  path->safe_push (x);
@@ -956,14 +954,65 @@ thread_across_edge (gimple dummy_cond,
 					  path);
 	      BITMAP_FREE (visited);
 	    }
-
-	  remove_temporary_equivalences (stack);
-	  propagate_threaded_block_debug_into (path->last ()->e->dest,
-					       e->dest);
-	  register_jump_thread (path);
-	  return;
+	  return true;
 	}
     }
+  return false;
+}
+
+/* We are exiting E->src, see if E->dest ends with a conditional
+   jump which has a known value when reached via E.
+
+   Special care is necessary if E is a back edge in the CFG as we
+   may have already recorded equivalences for E->dest into our
+   various tables, including the result of the conditional at
+   the end of E->dest.  Threading opportunities are severely
+   limited in that case to avoid short-circuiting the loop
+   incorrectly.
+
+   Note it is quite common for the first block inside a loop to
+   end with a conditional which is either always true or always
+   false when reached via the loop backedge.  Thus we do not want
+   to blindly disable threading across a loop backedge.
+
+   DUMMY_COND is a shared cond_expr used by condition simplification as scratch,
+   to avoid allocating memory.
+
+   HANDLE_DOMINATING_ASSERTS is true if we should try to replace operands of
+   the simplified condition with left-hand sides of ASSERT_EXPRs they are
+   used in.
+
+   STACK is used to undo temporary equivalences created during the walk of
+   E->dest.
+
+   SIMPLIFY is a pass-specific function used to simplify statements.  */
+
+void
+thread_across_edge (gimple dummy_cond,
+		    edge e,
+		    bool handle_dominating_asserts,
+		    vec<tree> *stack,
+		    tree (*simplify) (gimple, gimple))
+{
+  stmt_count = 0;
+
+  vec<jump_thread_edge *> *path = new vec<jump_thread_edge *> ();
+  if (thread_through_normal_block (e, dummy_cond, handle_dominating_asserts,
+				   stack, simplify, path))
+    {
+      propagate_threaded_block_debug_into (path->last ()->e->dest,
+					   e->dest);
+      remove_temporary_equivalences (stack);
+      register_jump_thread (path);
+      return;
+    }
+  else
+    {
+      /* There should be no edges on the path, so no need to walk through
+	 the vector entries.  */
+      gcc_assert (path->length () == 0);
+      path->release ();
+    }
 
  /* We were unable to determine what out edge from E->dest is taken.  However,
     we might still be able to thread through successors of E->dest.  This
@@ -1026,6 +1075,5 @@ thread_across_edge (gimple dummy_cond,
     BITMAP_FREE (visited);
   }
 
- fail:
   remove_temporary_equivalences (stack);
 }

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]