summaryrefslogtreecommitdiff
path: root/gcc/tree-ssa-threadedge.c
diff options
context:
space:
mode:
authorJeff Law <law@redhat.com>2013-10-04 14:36:27 -0600
committerJeff Law <law@gcc.gnu.org>2013-10-04 14:36:27 -0600
commit45d992343314089c4c66b9013dbe62b24a3e5285 (patch)
tree5ffa74103db939eef2677c4a3e07c78c23239f87 /gcc/tree-ssa-threadedge.c
parent8a2cb59f1c4a4822f727a5cd8fdfc7d87636508e (diff)
tree-ssa-threadedge.c: Fix some trailing whitespace problems.
* 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. From-SVN: r203217
Diffstat (limited to 'gcc/tree-ssa-threadedge.c')
-rw-r--r--gcc/tree-ssa-threadedge.c114
1 files changed, 81 insertions, 33 deletions
diff --git a/gcc/tree-ssa-threadedge.c b/gcc/tree-ssa-threadedge.c
index 39e921b270c..c2dd0155697 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);
}