tree-ssa-threadupdate.c (create_block_for_threading): Request that no outgoing edges be left in the duplicate block.

* tree-ssa-threadupdate.c (create_block_for_threading):  Request
	that no outgoing edges be left in the duplicate block.  Do no
	update information on outgoing edges or PHI nodes in target
	blocks here.
	(remove_ctrl_stmt_and_useless_edges): Renamed from
	remove_last_stmt_and_useless_edges.  Handle case where the
	block is empty or has no control statements.  Do not update edge
	flags here.
	(thread_block): Create a template block rather than copying the
	original block every time.  Create outgoing edges from the
	duplicate blocks and update PHIs at the target of the outgoing
	edges here.  Fix edge flags for the original block if necessary.
	* cfghooks (duplicate_block): No longer assert that the original
	block has incoming edges.

From-SVN: r88267
This commit is contained in:
Jeff Law 2004-09-28 20:15:00 -06:00 committed by Jeff Law
parent 805c33df13
commit e376fe5842
3 changed files with 82 additions and 42 deletions

View File

@ -1,3 +1,20 @@
2004-09-28 Jeff Law <law@redhat.com>
* tree-ssa-threadupdate.c (create_block_for_threading): Request
that no outgoing edges be left in the duplicate block. Do no
update information on outgoing edges or PHI nodes in target
blocks here.
(remove_ctrl_stmt_and_useless_edges): Renamed from
remove_last_stmt_and_useless_edges. Handle case where the
block is empty or has no control statements. Do not update edge
flags here.
(thread_block): Create a template block rather than copying the
original block every time. Create outgoing edges from the
duplicate blocks and update PHIs at the target of the outgoing
edges here. Fix edge flags for the original block if necessary.
* cfghooks (duplicate_block): No longer assert that the original
block has incoming edges.
2004-09-29 Hans-Peter Nilsson <hp@bitrange.com>
* doc/extend.texi (Extended Asm): Add blurb about using Explicit

View File

@ -691,7 +691,7 @@ duplicate_block (basic_block bb, edge e)
if (bb->count < new_count)
new_count = bb->count;
gcc_assert (EDGE_COUNT (bb->preds) > 0);
#ifdef ENABLE_CHECKING
gcc_assert (can_duplicate_block_p (bb));
#endif

View File

@ -129,16 +129,12 @@ copy_phis_to_block (basic_block new_bb, basic_block bb, edge e)
}
}
/* Remove the last statement in block BB which must be a COND_EXPR or
SWITCH_EXPR. Also remove all outgoing edges except the edge which
reaches DEST_BB.
This is only used by jump threading which knows the last statement in
BB should be a COND_EXPR or SWITCH_EXPR. If the block ends with any other
statement, then we abort. */
/* Remove the last statement in block BB if it is a control statement
Also remove all outgoing edges except the edge which reaches DEST_BB.
If DEST_BB is NULL, then remove all outgoing edges. */
static void
remove_last_stmt_and_useless_edges (basic_block bb, basic_block dest_bb)
remove_ctrl_stmt_and_useless_edges (basic_block bb, basic_block dest_bb)
{
block_stmt_iterator bsi;
edge e;
@ -146,10 +142,16 @@ remove_last_stmt_and_useless_edges (basic_block bb, basic_block dest_bb)
bsi = bsi_last (bb);
gcc_assert (TREE_CODE (bsi_stmt (bsi)) == COND_EXPR
|| TREE_CODE (bsi_stmt (bsi)) == SWITCH_EXPR);
/* If the duplicate ends with a control statement, then remove it.
bsi_remove (&bsi);
Note that if we are duplicating the template block rather than the
original basic block, then the duplicate might not have any real
statements in it. */
if (!bsi_end_p (bsi)
&& bsi_stmt (bsi)
&& (TREE_CODE (bsi_stmt (bsi)) == COND_EXPR
|| TREE_CODE (bsi_stmt (bsi)) == SWITCH_EXPR))
bsi_remove (&bsi);
for (ei = ei_start (bb->succs); (e = ei_safe_edge (ei)); )
{
@ -158,11 +160,6 @@ remove_last_stmt_and_useless_edges (basic_block bb, basic_block dest_bb)
else
ei_next (&ei);
}
/* BB now has a single outgoing edge. We need to update the flags for
that single outgoing edge. */
EDGE_SUCC (bb, 0)->flags &= ~(EDGE_TRUE_VALUE | EDGE_FALSE_VALUE);
EDGE_SUCC (bb, 0)->flags |= EDGE_FALLTHRU;
}
/* Create a duplicate of BB which only reaches the destination of the edge
@ -171,10 +168,6 @@ remove_last_stmt_and_useless_edges (basic_block bb, basic_block dest_bb)
static void
create_block_for_threading (basic_block bb, struct redirection_data *rd)
{
tree phi;
edge e;
edge_iterator ei;
/* We can use the generic block duplication code and simply remove
the stuff we do not need. */
rd->dup_block = duplicate_block (bb, NULL);
@ -184,25 +177,12 @@ create_block_for_threading (basic_block bb, struct redirection_data *rd)
rd->dup_block->count = 0;
/* The call to duplicate_block will copy everything, including the
useless COND_EXPR or SWITCH_EXPR at the end of the block. We just remove
useless COND_EXPR or SWITCH_EXPR at the end of BB. We just remove
the useless COND_EXPR or SWITCH_EXPR here rather than having a
specialized block copier. */
remove_last_stmt_and_useless_edges (rd->dup_block, rd->outgoing_edge->dest);
FOR_EACH_EDGE (e, ei, rd->dup_block->succs)
e->count = 0;
/* If there are any PHI nodes at the destination of the outgoing edge
from the duplicate block, then we will need to add a new argument
to them. The argument should have the same value as the argument
associated with the outgoing edge stored in RD. */
for (phi = phi_nodes (EDGE_SUCC (rd->dup_block, 0)->dest); phi;
phi = PHI_CHAIN (phi))
{
int indx = phi_arg_from_edge (phi, rd->outgoing_edge);
add_phi_arg (&phi, PHI_ARG_DEF_TREE (phi, indx),
EDGE_SUCC (rd->dup_block, 0));
}
specialized block copier. We also remove all outgoing edges
from the duplicate block. The appropriate edge will be created
later. */
remove_ctrl_stmt_and_useless_edges (rd->dup_block, NULL);
}
/* BB is a block which ends with a COND_EXPR or SWITCH_EXPR and when BB
@ -241,6 +221,7 @@ thread_block (basic_block bb)
redirect to a duplicate of BB. */
edge e;
edge_iterator ei;
basic_block template_block;
/* ALL indicates whether or not all incoming edges into BB should
be threaded to a duplicate of BB. */
@ -293,11 +274,51 @@ thread_block (basic_block bb)
/* Now create duplicates of BB. Note that if all incoming edges are
threaded, then BB is going to become unreachable. In that case
we use BB for one of the duplicates rather than wasting memory
duplicating BB. Thus the odd starting condition for the loop. */
duplicating BB. Thus the odd starting condition for the loop.
Note that for a block with a high outgoing degree we can waste
a lot of time and memory creating and destroying useless edges.
So we first duplicate BB and remove the control structure at the
tail of the duplicate as well as all outgoing edges from the
duplicate. We then use that duplicate block as a template for
the rest of the duplicates. */
template_block = NULL;
for (i = (all ? 1 : 0); i < VARRAY_ACTIVE_SIZE (redirection_data); i++)
{
struct redirection_data *rd = VARRAY_GENERIC_PTR (redirection_data, i);
create_block_for_threading (bb, rd);
if (template_block == NULL)
{
create_block_for_threading (bb, rd);
template_block = rd->dup_block;
}
else
{
create_block_for_threading (template_block, rd);
}
}
/* Now created up edges from the duplicate blocks to their new
destinations. Doing this as a separate loop after block creation
allows us to avoid creating lots of useless edges. */
for (i = (all ? 1 : 0); i < VARRAY_ACTIVE_SIZE (redirection_data); i++)
{
struct redirection_data *rd = VARRAY_GENERIC_PTR (redirection_data, i);
tree phi;
edge e;
e = make_edge (rd->dup_block, rd->outgoing_edge->dest, EDGE_FALLTHRU);
/* If there are any PHI nodes at the destination of the outgoing edge
from the duplicate block, then we will need to add a new argument
to them. The argument should have the same value as the argument
associated with the outgoing edge stored in RD. */
for (phi = phi_nodes (e->dest); phi; phi = PHI_CHAIN (phi))
{
int indx = phi_arg_from_edge (phi, rd->outgoing_edge);
add_phi_arg (&phi, PHI_ARG_DEF_TREE (phi, indx), e);
}
}
/* The loop above created the duplicate blocks (and the statements
@ -375,7 +396,9 @@ thread_block (basic_block bb)
EDGE_PRED (bb, 0)->src->index, bb->index,
EDGE_SUCC (bb, 0)->dest->index);
remove_last_stmt_and_useless_edges (bb, rd->outgoing_edge->dest);
remove_ctrl_stmt_and_useless_edges (bb, rd->outgoing_edge->dest);
EDGE_SUCC (bb, 0)->flags &= ~(EDGE_TRUE_VALUE | EDGE_FALSE_VALUE);
EDGE_SUCC (bb, 0)->flags |= EDGE_FALLTHRU;
}
/* Done with this block. Clear REDIRECTION_DATA. */