Commit 5f51d006 by Jeff Law Committed by Jeff Law

tree-ssa-threadedge.c (thread_across_edge): After threading through a joiner...

	* tree-ssa-threadedge.c (thread_across_edge): After threading
	through a joiner, allow threading a normal block requiring
	duplication.

	* tree-ssa-threadupdate.c (thread_block_1): Improve code to detect
	jump threading requests that would muck up the loop structures.

From-SVN: r205074
parent 2ed4d7ee
2013-11-19 Jeff Law <law@redhat.com>
* tree-ssa-threadedge.c (thread_across_edge): After threading
through a joiner, allow threading a normal block requiring
duplication.
* tree-ssa-threadupdate.c (thread_block_1): Improve code to detect
jump threading requests that would muck up the loop structures.
* tree-ssa-threadupdate.c: Fix trailing whitespace.
* tree-ssa-threadupdate.h: Likewise.
......@@ -1098,6 +1098,14 @@ thread_across_edge (gimple dummy_cond,
path,
&backedge_seen);
if (!found
&& (!backedge_seen
|| ! cond_arg_set_in_bb (path->last ()->e, e->dest)))
found = thread_through_normal_block (path->last ()->e, dummy_cond,
handle_dominating_asserts,
stack, simplify, path, visited,
&backedge_seen);
/* If we were able to thread through a successor of E->dest, then
record the jump threading opportunity. */
if (found)
......
......@@ -328,7 +328,7 @@ lookup_redirection_data (edge e, enum insert_option insert)
to the list of incoming edges associated with E. */
if (insert)
{
struct el *el = XNEW (struct el);
struct el *el = XNEW (struct el);
el->next = elt->incoming_edges;
el->e = e;
elt->incoming_edges = el;
......@@ -496,11 +496,11 @@ ssa_fix_duplicate_block_edges (struct redirection_data *rd,
e2 = redirect_edge_and_branch (victim, path->last ()->e->dest);
e2->count = path->last ()->e->count;
/* If we redirected the edge, then we need to copy PHI arguments
at the target. If the edge already existed (e2 != victim
at the target. If the edge already existed (e2 != victim
case), then the PHIs in the target already have the correct
arguments. */
if (e2 == victim)
copy_phi_args (e2->dest, path->last ()->e, e2);
copy_phi_args (e2->dest, path->last ()->e, e2);
}
else
{
......@@ -550,7 +550,7 @@ ssa_create_duplicates (struct redirection_data **slot,
/* The second duplicated block in a jump threading path is specific
to the path. So it gets stored in RD rather than in LOCAL_DATA.
Each time we're called, we have to look through the path and see
if a second block needs to be duplicated.
......@@ -672,7 +672,7 @@ ssa_redirect_edges (struct redirection_data **slot,
}
/* Go ahead and clear E->aux. It's not needed anymore and failure
to clear it will cause all kinds of unpleasant problems later. */
to clear it will cause all kinds of unpleasant problems later. */
delete_jump_thread_path (path);
e->aux = NULL;
......@@ -697,9 +697,9 @@ redirection_block_p (basic_block bb)
/* Advance to the first executable statement. */
gsi = gsi_start_bb (bb);
while (!gsi_end_p (gsi)
&& (gimple_code (gsi_stmt (gsi)) == GIMPLE_LABEL
&& (gimple_code (gsi_stmt (gsi)) == GIMPLE_LABEL
|| is_gimple_debug (gsi_stmt (gsi))
|| gimple_nop_p (gsi_stmt (gsi))))
|| gimple_nop_p (gsi_stmt (gsi))))
gsi_next (&gsi);
/* Check if this is an empty block. */
......@@ -708,9 +708,9 @@ redirection_block_p (basic_block bb)
/* Test that we've reached the terminating control statement. */
return gsi_stmt (gsi)
&& (gimple_code (gsi_stmt (gsi)) == GIMPLE_COND
|| gimple_code (gsi_stmt (gsi)) == GIMPLE_GOTO
|| gimple_code (gsi_stmt (gsi)) == GIMPLE_SWITCH);
&& (gimple_code (gsi_stmt (gsi)) == GIMPLE_COND
|| gimple_code (gsi_stmt (gsi)) == GIMPLE_GOTO
|| gimple_code (gsi_stmt (gsi)) == GIMPLE_SWITCH);
}
/* BB is a block which ends with a COND_EXPR or SWITCH_EXPR and when BB
......@@ -795,22 +795,12 @@ thread_block_1 (basic_block bb, bool noloop_only, bool joiners)
if (!e2 || noloop_only)
{
/* If NOLOOP_ONLY is true, we only allow threading through the
header of a loop to exit edges.
There are two cases to consider. The first when BB is the
loop header. We will attempt to thread this elsewhere, so
we can just continue here. */
if (bb == bb->loop_father->header
&& (!loop_exit_edge_p (bb->loop_father, e2)
|| (*path)[1]->type == EDGE_COPY_SRC_JOINER_BLOCK))
continue;
header of a loop to exit edges. */
/* The second occurs when there was loop header buried in a jump
threading path. We do not try and thread this elsewhere, so
just cancel the jump threading request by clearing the AUX
field now. */
/* One case occurs when there was loop header buried in a jump
threading path that crosses loop boundaries. We do not try
and thread this elsewhere, so just cancel the jump threading
request by clearing the AUX field now. */
if ((bb->loop_father != e2->src->loop_father
&& !loop_exit_edge_p (e2->src->loop_father, e2))
|| (e2->src->loop_father != e2->dest->loop_father
......@@ -823,11 +813,40 @@ thread_block_1 (basic_block bb, bool noloop_only, bool joiners)
e->aux = NULL;
continue;
}
/* Another case occurs when trying to thread through our
own loop header, possibly from inside the loop.
If our loop header is buried in the path, then go ahead
and cancel the jump threading request here. This likely
will need updating for the FSA/FSM coremark case.
Other cases (BB is the loop header) are handled elsewhere. */
unsigned int i;
for (i = 1; i < path->length (); i++)
{
if ((*path)[i]->e->src == bb->loop_father->header
&& (!loop_exit_edge_p (bb->loop_father, e2)
|| (*path)[1]->type == EDGE_COPY_SRC_JOINER_BLOCK))
{
/* If i != 1, then it's a buried header that will not
be handled elsehwere. */
if (i != 1)
{
delete_jump_thread_path (path);
e->aux = NULL;
}
break;
}
}
if (i != path->length ())
continue;
}
if (e->dest == e2->src)
update_bb_profile_for_threading (e->dest, EDGE_FREQUENCY (e),
e->count, (*THREAD_PATH (e))[1]->e);
e->count, (*THREAD_PATH (e))[1]->e);
/* Insert the outgoing edge into the hash table if it is not
already in the hash table. */
......@@ -1242,7 +1261,7 @@ thread_through_loop_header (struct loop *loop, bool may_peel_loop_headers)
unsigned nblocks, i;
/* First handle the case latch edge is redirected. We are copying
the loop header but not creating a multiple entry loop. Make the
the loop header but not creating a multiple entry loop. Make the
cfg manipulation code aware of that fact. */
set_loop_copy (loop, loop);
loop->latch = thread_single_edge (latch);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment