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:
parent
0c33762a47
commit
56e8401921
2 changed files with 102 additions and 152 deletions
|
@ -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.
|
||||
|
|
245
gcc/tree-cfg.c
245
gcc/tree-cfg.c
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue