tree-cfg.c (find_taken_edge_computed_goto): New function.

* tree-cfg.c (find_taken_edge_computed_goto): New function.
        (find_taken_edge): Call find_taken_edge_computed_goto as
        appropriate.  Allow any gimple invariant rather than just
        INTEGER_CST for VAL.
        (cleanup_control_flow): Cleanup a computed goto which has turned
        into a simple goto.
        (tree_merge_blocks): If block B has any forced labels, move
        them to the start of block A.
        * tree-ssa-dom.c (thread_across_edge): Allow threading across
        computed gotos as well.
        * tree-ssa-threadupdate.c (remove_ctrl_stmt_and_useless_edges): Handle
        removal of unnecessary computed gotos too.
        (lookup_redirection_data): Fix type of INSERT argument.  Callers
        updated.

From-SVN: r96084
This commit is contained in:
Jeff Law 2005-03-07 20:39:19 -07:00 committed by Jeff Law
parent 58261bc246
commit be47740604
4 changed files with 114 additions and 6 deletions

View File

@ -1,3 +1,20 @@
2005-03-07 Jeff Law <law@redhat.com>
* tree-cfg.c (find_taken_edge_computed_goto): New function.
(find_taken_edge): Call find_taken_edge_computed_goto as
appropriate. Allow any gimple invariant rather than just
INTEGER_CST for VAL.
(cleanup_control_flow): Cleanup a computed goto which has turned
into a simple goto.
(tree_merge_blocks): If block B has any forced labels, move
them to the start of block A.
* tree-ssa-dom.c (thread_across_edge): Allow threading across
computed gotos as well.
* tree-ssa-threadupdate.c (remove_ctrl_stmt_and_useless_edges): Handle
removal of unnecessary computed gotos too.
(lookup_redirection_data): Fix type of INSERT argument. Callers
updated.
2005-03-08 Kazu Hirata <kazu@cs.umass.edu>
* tree-ssa-phiopt.c: Update copyright. Fix indentations.

View File

@ -129,6 +129,7 @@ static bool tree_can_merge_blocks_p (basic_block, basic_block);
static void remove_bb (basic_block);
static bool cleanup_control_flow (void);
static bool cleanup_control_expr_graph (basic_block, block_stmt_iterator);
static edge find_taken_edge_computed_goto (basic_block, tree);
static edge find_taken_edge_cond_expr (basic_block, tree);
static edge find_taken_edge_switch_expr (basic_block, tree);
static tree find_case_label_for_value (tree, tree);
@ -1301,7 +1302,22 @@ tree_merge_blocks (basic_block a, basic_block b)
for (bsi = bsi_start (b); !bsi_end_p (bsi);)
{
if (TREE_CODE (bsi_stmt (bsi)) == LABEL_EXPR)
bsi_remove (&bsi);
{
tree label = bsi_stmt (bsi);
bsi_remove (&bsi);
/* Now that we can thread computed gotos, we might have
a situation where we have a forced label in block B
However, the label at the start of block B might still be
used in other ways (think about the runtime checking for
Fortran assigned gotos). So we can not just delete the
label. Instead we move the label to the start of block A. */
if (FORCED_LABEL (LABEL_EXPR_LABEL (label)))
{
block_stmt_iterator dest_bsi = bsi_start (a);
bsi_insert_before (&dest_bsi, label, BSI_NEW_STMT);
}
}
else
{
set_bb_for_stmt (bsi_stmt (bsi), a);
@ -2122,6 +2138,43 @@ cleanup_control_flow (void)
|| TREE_CODE (stmt) == SWITCH_EXPR)
retval |= cleanup_control_expr_graph (bb, bsi);
/* If we had a computed goto which has a compile-time determinable
destination, then we can eliminate the goto. */
if (TREE_CODE (stmt) == GOTO_EXPR
&& TREE_CODE (GOTO_DESTINATION (stmt)) == ADDR_EXPR
&& TREE_CODE (TREE_OPERAND (GOTO_DESTINATION (stmt), 0)) == LABEL_DECL)
{
edge e;
tree label;
edge_iterator ei;
basic_block target_block;
/* First look at all the outgoing edges. Delete any outgoing
edges which do not go to the right block. For the one
edge which goes to the right block, fix up its flags. */
label = TREE_OPERAND (GOTO_DESTINATION (stmt), 0);
target_block = label_to_block (label);
for (ei = ei_start (bb->succs); (e = ei_safe_edge (ei)); )
{
if (e->dest != target_block)
remove_edge (e);
else
{
/* Turn off the EDGE_ABNORMAL flag. */
EDGE_SUCC (bb, 0)->flags &= ~EDGE_ABNORMAL;
/* And set EDGE_FALLTHRU. */
EDGE_SUCC (bb, 0)->flags |= EDGE_FALLTHRU;
ei_next (&ei);
}
}
/* Remove the GOTO_EXPR as it is not needed. The CFG has all the
relevant information we need. */
bsi_remove (&bsi);
retval = true;
}
/* Check for indirect calls that have been turned into
noreturn calls. */
if (noreturn_call_p (stmt) && remove_fallthru_edge (bb->succs))
@ -2229,7 +2282,7 @@ find_taken_edge (basic_block bb, tree val)
gcc_assert (is_ctrl_stmt (stmt));
gcc_assert (val);
if (TREE_CODE (val) != INTEGER_CST)
if (! is_gimple_min_invariant (val))
return NULL;
if (TREE_CODE (stmt) == COND_EXPR)
@ -2238,9 +2291,31 @@ find_taken_edge (basic_block bb, tree val)
if (TREE_CODE (stmt) == SWITCH_EXPR)
return find_taken_edge_switch_expr (bb, val);
if (computed_goto_p (stmt))
return find_taken_edge_computed_goto (bb, TREE_OPERAND( val, 0));
gcc_unreachable ();
}
/* Given a constant value VAL and the entry block BB to a GOTO_EXPR
statement, determine which of the outgoing edges will be taken out of the
block. Return NULL if either edge may be taken. */
static edge
find_taken_edge_computed_goto (basic_block bb, tree val)
{
basic_block dest;
edge e = NULL;
dest = label_to_block (val);
if (dest)
{
e = find_edge (bb, dest);
gcc_assert (e != NULL);
}
return e;
}
/* Given a constant value VAL and the entry block BB to a COND_EXPR
statement, determine which of the two edges will be taken out of the

View File

@ -715,7 +715,8 @@ thread_across_edge (struct dom_walk_data *walk_data, edge e)
arm will be taken. */
if (stmt
&& (TREE_CODE (stmt) == COND_EXPR
|| TREE_CODE (stmt) == SWITCH_EXPR))
|| TREE_CODE (stmt) == SWITCH_EXPR
|| TREE_CODE (stmt) == GOTO_EXPR))
{
tree cond, cached_lhs;
@ -723,6 +724,8 @@ thread_across_edge (struct dom_walk_data *walk_data, edge e)
expression in the hash tables. */
if (TREE_CODE (stmt) == COND_EXPR)
cond = COND_EXPR_COND (stmt);
else if (TREE_CODE (stmt) == GOTO_EXPR)
cond = GOTO_DESTINATION (stmt);
else
cond = SWITCH_COND (stmt);
@ -1000,6 +1003,18 @@ dom_opt_finalize_block (struct dom_walk_data *walk_data, basic_block bb)
{
thread_across_edge (walk_data, EDGE_SUCC (bb, 0));
}
else if ((last = last_stmt (bb))
&& TREE_CODE (last) == GOTO_EXPR
&& TREE_CODE (TREE_OPERAND (last, 0)) == SSA_NAME)
{
edge_iterator ei;
edge e;
FOR_EACH_EDGE (e, ei, bb->succs)
{
thread_across_edge (walk_data, e);
}
}
else if ((last = last_stmt (bb))
&& TREE_CODE (last) == COND_EXPR
&& (COMPARISON_CLASS_P (COND_EXPR_COND (last))

View File

@ -169,6 +169,7 @@ remove_ctrl_stmt_and_useless_edges (basic_block bb, basic_block dest_bb)
if (!bsi_end_p (bsi)
&& bsi_stmt (bsi)
&& (TREE_CODE (bsi_stmt (bsi)) == COND_EXPR
|| TREE_CODE (bsi_stmt (bsi)) == GOTO_EXPR
|| TREE_CODE (bsi_stmt (bsi)) == SWITCH_EXPR))
bsi_remove (&bsi);
@ -228,7 +229,7 @@ redirection_data_eq (const void *p1, const void *p2)
edges associated with E in the hash table. */
static struct redirection_data *
lookup_redirection_data (edge e, edge incoming_edge, bool insert)
lookup_redirection_data (edge e, edge incoming_edge, enum insert_option insert)
{
void **slot;
struct redirection_data *elt;
@ -733,7 +734,7 @@ thread_block (basic_block bb)
/* Insert the outgoing edge into the hash table if it is not
already in the hash table. */
lookup_redirection_data (e2, e, true);
lookup_redirection_data (e2, e, INSERT);
}
}
@ -744,7 +745,7 @@ thread_block (basic_block bb)
if (all)
{
edge e = EDGE_PRED (bb, 0)->aux;
lookup_redirection_data (e, NULL, false)->do_not_duplicate = true;
lookup_redirection_data (e, NULL, NO_INSERT)->do_not_duplicate = true;
}
/* Now create duplicates of BB.