tree-cfg.c (make_ctrl_stmt_edges, [...]): Merge into...

* tree-cfg.c (make_ctrl_stmt_edges, make_exit_edges): Merge into...
        (make_edges): ... here.  Control fallthru creation with a local
        variable.  Do not play with fake edges.
        (make_omp_sections_edges): Don't set EDGE_ABNORMAL.
        (make_goto_expr_edges): Don't play with fake edges.  Make for_call
        a boolean.

From-SVN: r112603
This commit is contained in:
Richard Henderson 2006-03-31 16:37:13 -08:00 committed by Richard Henderson
parent 0c33762a47
commit 56e8401921
2 changed files with 102 additions and 152 deletions

View file

@ -1,3 +1,12 @@
2004-03-31 Richard Henderson <rth@redhat.com>
* tree-cfg.c (make_ctrl_stmt_edges, make_exit_edges): Merge into...
(make_edges): ... here. Control fallthru creation with a local
variable. Do not play with fake edges.
(make_omp_sections_edges): Don't set EDGE_ABNORMAL.
(make_goto_expr_edges): Don't play with fake edges. Make for_call
a boolean.
2006-04-01 Joseph S. Myers <joseph@codesourcery.com>
* dwarf2.h (DW64_CIE_ID): Define.

View file

@ -1,5 +1,6 @@
/* Control flow functions for trees.
Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006
Free Software Foundation, Inc.
Contributed by Diego Novillo <dnovillo@redhat.com>
This file is part of GCC.
@ -99,11 +100,10 @@ static void factor_computed_gotos (void);
/* Edges. */
static void make_edges (void);
static void make_ctrl_stmt_edges (basic_block);
static void make_exit_edges (basic_block);
static void make_cond_expr_edges (basic_block);
static void make_switch_expr_edges (basic_block);
static void make_goto_expr_edges (basic_block);
static void make_omp_sections_edges (basic_block);
static edge tree_redirect_edge_and_branch (edge, basic_block);
static edge tree_try_redirect_by_replacing_jump (edge, basic_block);
static unsigned int split_critical_edges (void);
@ -455,30 +455,99 @@ make_edges (void)
/* Traverse the basic block array placing edges. */
FOR_EACH_BB (bb)
{
tree first = first_stmt (bb);
tree last = last_stmt (bb);
bool fallthru;
if (first)
if (last)
{
/* Edges for statements that always alter flow control. */
if (is_ctrl_stmt (last))
make_ctrl_stmt_edges (bb);
switch (TREE_CODE (last))
{
case GOTO_EXPR:
make_goto_expr_edges (bb);
fallthru = false;
break;
case RETURN_EXPR:
make_edge (bb, EXIT_BLOCK_PTR, 0);
fallthru = false;
break;
case COND_EXPR:
make_cond_expr_edges (bb);
fallthru = false;
break;
case SWITCH_EXPR:
make_switch_expr_edges (bb);
fallthru = false;
break;
case RESX_EXPR:
make_eh_edges (last);
fallthru = false;
break;
/* Edges for statements that sometimes alter flow control. */
if (is_ctrl_altering_stmt (last))
make_exit_edges (bb);
case CALL_EXPR:
/* If this function receives a nonlocal goto, then we need to
make edges from this call site to all the nonlocal goto
handlers. */
if (TREE_SIDE_EFFECTS (last)
&& current_function_has_nonlocal_label)
make_goto_expr_edges (bb);
/* If this statement has reachable exception handlers, then
create abnormal edges to them. */
make_eh_edges (last);
/* Some calls are known not to return. */
fallthru = !(call_expr_flags (last) & ECF_NORETURN);
break;
case MODIFY_EXPR:
if (is_ctrl_altering_stmt (last))
{
/* A MODIFY_EXPR may have a CALL_EXPR on its RHS and the
CALL_EXPR may have an abnormal edge. Search the RHS for
this case and create any required edges. */
tree op = get_call_expr_in (last);
if (op && TREE_SIDE_EFFECTS (op)
&& current_function_has_nonlocal_label)
make_goto_expr_edges (bb);
make_eh_edges (last);
}
fallthru = true;
break;
case OMP_PARALLEL:
case OMP_FOR:
case OMP_SINGLE:
case OMP_MASTER:
case OMP_ORDERED:
case OMP_CRITICAL:
case OMP_SECTION:
fallthru = true;
break;
case OMP_RETURN_EXPR:
/* In the case of an OMP_SECTION, we may have already made
an edge in make_omp_sections_edges. */
fallthru = EDGE_COUNT (bb->succs) == 0;
break;
case OMP_SECTIONS:
make_omp_sections_edges (bb);
fallthru = false;
break;
default:
gcc_assert (!stmt_ends_bb_p (last));
fallthru = true;
}
}
else
fallthru = true;
/* Finally, if no edges were created above, this is a regular
basic block that only needs a fallthru edge. */
if (EDGE_COUNT (bb->succs) == 0)
if (fallthru)
make_edge (bb, bb->next_bb, EDGE_FALLTHRU);
}
/* We do not care about fake edges, so remove any that the CFG
builder inserted for completeness. */
remove_fake_exit_edges ();
/* Fold COND_EXPR_COND of each COND_EXPR. */
fold_cond_expr_cond ();
@ -505,7 +574,7 @@ make_omp_sections_edges (basic_block bb)
{
basic_block start_bb = bb_for_stmt (TREE_VEC_ELT (vec, i));
basic_block end_bb = bb_for_stmt (TREE_VEC_ELT (vec, i + 1));
make_edge (bb, start_bb, EDGE_ABNORMAL);
make_edge (bb, start_bb, 0);
make_edge (end_bb, exit_bb, EDGE_FALLTHRU);
}
@ -516,130 +585,6 @@ make_omp_sections_edges (basic_block bb)
OMP_SECTIONS_SECTIONS (stmt) = NULL_TREE;
}
/* Create edges for control statement at basic block BB. */
static void
make_ctrl_stmt_edges (basic_block bb)
{
tree last = last_stmt (bb);
gcc_assert (last);
switch (TREE_CODE (last))
{
case GOTO_EXPR:
make_goto_expr_edges (bb);
break;
case RETURN_EXPR:
make_edge (bb, EXIT_BLOCK_PTR, 0);
break;
case COND_EXPR:
make_cond_expr_edges (bb);
break;
case SWITCH_EXPR:
make_switch_expr_edges (bb);
break;
case RESX_EXPR:
make_eh_edges (last);
/* Yet another NORETURN hack. */
if (EDGE_COUNT (bb->succs) == 0)
make_edge (bb, EXIT_BLOCK_PTR, EDGE_FAKE);
break;
default:
gcc_unreachable ();
}
}
/* Create exit edges for statements in block BB that alter the flow of
control. Statements that alter the control flow are 'goto', 'return'
and calls to non-returning functions. */
static void
make_exit_edges (basic_block bb)
{
tree last = last_stmt (bb), op;
gcc_assert (last);
switch (TREE_CODE (last))
{
case RESX_EXPR:
break;
case CALL_EXPR:
/* If this function receives a nonlocal goto, then we need to
make edges from this call site to all the nonlocal goto
handlers. */
if (TREE_SIDE_EFFECTS (last)
&& current_function_has_nonlocal_label)
make_goto_expr_edges (bb);
/* If this statement has reachable exception handlers, then
create abnormal edges to them. */
make_eh_edges (last);
/* Some calls are known not to return. For such calls we create
a fake edge.
We really need to revamp how we build edges so that it's not
such a bloody pain to avoid creating edges for this case since
all we do is remove these edges when we're done building the
CFG. */
if (call_expr_flags (last) & ECF_NORETURN)
{
make_edge (bb, EXIT_BLOCK_PTR, EDGE_FAKE);
return;
}
/* Don't forget the fall-thru edge. */
make_edge (bb, bb->next_bb, EDGE_FALLTHRU);
break;
case MODIFY_EXPR:
/* A MODIFY_EXPR may have a CALL_EXPR on its RHS and the CALL_EXPR
may have an abnormal edge. Search the RHS for this case and
create any required edges. */
op = get_call_expr_in (last);
if (op && TREE_SIDE_EFFECTS (op)
&& current_function_has_nonlocal_label)
make_goto_expr_edges (bb);
make_eh_edges (last);
make_edge (bb, bb->next_bb, EDGE_FALLTHRU);
break;
case OMP_PARALLEL:
case OMP_FOR:
case OMP_SINGLE:
case OMP_MASTER:
case OMP_ORDERED:
case OMP_CRITICAL:
make_edge (bb, bb->next_bb, EDGE_ABNORMAL);
case OMP_RETURN_EXPR:
if (EDGE_COUNT (bb->succs) == 0)
make_edge (bb, bb->next_bb, EDGE_FALLTHRU);
break;
case OMP_SECTIONS:
make_omp_sections_edges (bb);
break;
case OMP_SECTION:
make_edge (bb, bb->next_bb, EDGE_FALLTHRU);
break;
default:
gcc_unreachable ();
}
}
/* Create the edges for a COND_EXPR starting at block BB.
At this point, both clauses must contain only simple gotos. */
@ -887,7 +832,7 @@ make_goto_expr_edges (basic_block bb)
{
tree goto_t;
basic_block target_bb;
int for_call;
bool for_call;
block_stmt_iterator last = bsi_last (bb);
goto_t = bsi_stmt (last);
@ -896,11 +841,11 @@ make_goto_expr_edges (basic_block bb)
CALL_EXPR or MODIFY_EXPR), then the edge is an abnormal edge resulting
from a nonlocal goto. */
if (TREE_CODE (goto_t) != GOTO_EXPR)
for_call = 1;
for_call = true;
else
{
tree dest = GOTO_DESTINATION (goto_t);
for_call = 0;
for_call = false;
/* A GOTO to a local label creates normal edges. */
if (simple_goto_p (goto_t))
@ -939,21 +884,17 @@ make_goto_expr_edges (basic_block bb)
if (
/* Computed GOTOs. Make an edge to every label block that has
been marked as a potential target for a computed goto. */
(FORCED_LABEL (LABEL_EXPR_LABEL (target)) && for_call == 0)
(FORCED_LABEL (LABEL_EXPR_LABEL (target)) && !for_call)
/* Nonlocal GOTO target. Make an edge to every label block
that has been marked as a potential target for a nonlocal
goto. */
|| (DECL_NONLOCAL (LABEL_EXPR_LABEL (target)) && for_call == 1))
|| (DECL_NONLOCAL (LABEL_EXPR_LABEL (target)) && for_call))
{
make_edge (bb, target_bb, EDGE_ABNORMAL);
break;
}
}
}
/* Degenerate case of computed goto with no labels. */
if (!for_call && EDGE_COUNT (bb->succs) == 0)
make_edge (bb, EXIT_BLOCK_PTR, EDGE_FAKE);
}