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:
parent
58261bc246
commit
be47740604
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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.
|
||||
|
|
Loading…
Reference in New Issue