Commit 56e84019 by Richard Henderson Committed by Richard Henderson

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
parent 0c33762a
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> 2006-04-01 Joseph S. Myers <joseph@codesourcery.com>
* dwarf2.h (DW64_CIE_ID): Define. * dwarf2.h (DW64_CIE_ID): Define.
......
/* Control flow functions for trees. /* 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> Contributed by Diego Novillo <dnovillo@redhat.com>
This file is part of GCC. This file is part of GCC.
...@@ -99,11 +100,10 @@ static void factor_computed_gotos (void); ...@@ -99,11 +100,10 @@ static void factor_computed_gotos (void);
/* Edges. */ /* Edges. */
static void make_edges (void); 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_cond_expr_edges (basic_block);
static void make_switch_expr_edges (basic_block); static void make_switch_expr_edges (basic_block);
static void make_goto_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_redirect_edge_and_branch (edge, basic_block);
static edge tree_try_redirect_by_replacing_jump (edge, basic_block); static edge tree_try_redirect_by_replacing_jump (edge, basic_block);
static unsigned int split_critical_edges (void); static unsigned int split_critical_edges (void);
...@@ -455,122 +455,34 @@ make_edges (void) ...@@ -455,122 +455,34 @@ make_edges (void)
/* Traverse the basic block array placing edges. */ /* Traverse the basic block array placing edges. */
FOR_EACH_BB (bb) FOR_EACH_BB (bb)
{ {
tree first = first_stmt (bb);
tree last = last_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);
/* Edges for statements that sometimes alter flow control. */
if (is_ctrl_altering_stmt (last))
make_exit_edges (bb);
}
/* 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)
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 ();
/* Clean up the graph and warn for unreachable code. */
cleanup_tree_cfg ();
}
/* Link an OMP_SECTIONS block to all the OMP_SECTION blocks in its body. */
static void
make_omp_sections_edges (basic_block bb)
{
basic_block exit_bb;
size_t i, n;
tree vec, stmt;
stmt = last_stmt (bb);
vec = OMP_SECTIONS_SECTIONS (stmt);
n = TREE_VEC_LENGTH (vec);
exit_bb = bb_for_stmt (TREE_VEC_ELT (vec, n - 1));
for (i = 0; i < n - 1; i += 2)
{ {
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 (end_bb, exit_bb, EDGE_FALLTHRU);
}
/* Once the CFG has been built, the vector of sections is no longer
useful. The region can be easily obtained with build_omp_regions.
Furthermore, this sharing of tree expressions is not allowed by the
statement verifier. */
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)) switch (TREE_CODE (last))
{ {
case GOTO_EXPR: case GOTO_EXPR:
make_goto_expr_edges (bb); make_goto_expr_edges (bb);
fallthru = false;
break; break;
case RETURN_EXPR: case RETURN_EXPR:
make_edge (bb, EXIT_BLOCK_PTR, 0); make_edge (bb, EXIT_BLOCK_PTR, 0);
fallthru = false;
break; break;
case COND_EXPR: case COND_EXPR:
make_cond_expr_edges (bb); make_cond_expr_edges (bb);
fallthru = false;
break; break;
case SWITCH_EXPR: case SWITCH_EXPR:
make_switch_expr_edges (bb); make_switch_expr_edges (bb);
fallthru = false;
break; break;
case RESX_EXPR: case RESX_EXPR:
make_eh_edges (last); make_eh_edges (last);
/* Yet another NORETURN hack. */ fallthru = false;
if (EDGE_COUNT (bb->succs) == 0)
make_edge (bb, EXIT_BLOCK_PTR, EDGE_FAKE);
break; 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: case CALL_EXPR:
/* If this function receives a nonlocal goto, then we need to /* If this function receives a nonlocal goto, then we need to
make edges from this call site to all the nonlocal goto make edges from this call site to all the nonlocal goto
...@@ -583,34 +495,24 @@ make_exit_edges (basic_block bb) ...@@ -583,34 +495,24 @@ make_exit_edges (basic_block bb)
create abnormal edges to them. */ create abnormal edges to them. */
make_eh_edges (last); make_eh_edges (last);
/* Some calls are known not to return. For such calls we create /* Some calls are known not to return. */
a fake edge. fallthru = !(call_expr_flags (last) & ECF_NORETURN);
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; break;
case MODIFY_EXPR: case MODIFY_EXPR:
/* A MODIFY_EXPR may have a CALL_EXPR on its RHS and the CALL_EXPR if (is_ctrl_altering_stmt (last))
may have an abnormal edge. Search the RHS for this case and {
create any required edges. */ /* A MODIFY_EXPR may have a CALL_EXPR on its RHS and the
op = get_call_expr_in (last); 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) if (op && TREE_SIDE_EFFECTS (op)
&& current_function_has_nonlocal_label) && current_function_has_nonlocal_label)
make_goto_expr_edges (bb); make_goto_expr_edges (bb);
make_eh_edges (last); make_eh_edges (last);
make_edge (bb, bb->next_bb, EDGE_FALLTHRU); }
fallthru = true;
break; break;
case OMP_PARALLEL: case OMP_PARALLEL:
...@@ -619,27 +521,70 @@ make_exit_edges (basic_block bb) ...@@ -619,27 +521,70 @@ make_exit_edges (basic_block bb)
case OMP_MASTER: case OMP_MASTER:
case OMP_ORDERED: case OMP_ORDERED:
case OMP_CRITICAL: case OMP_CRITICAL:
make_edge (bb, bb->next_bb, EDGE_ABNORMAL); case OMP_SECTION:
fallthru = true;
break;
case OMP_RETURN_EXPR: case OMP_RETURN_EXPR:
if (EDGE_COUNT (bb->succs) == 0) /* In the case of an OMP_SECTION, we may have already made
make_edge (bb, bb->next_bb, EDGE_FALLTHRU); an edge in make_omp_sections_edges. */
fallthru = EDGE_COUNT (bb->succs) == 0;
break; break;
case OMP_SECTIONS: case OMP_SECTIONS:
make_omp_sections_edges (bb); make_omp_sections_edges (bb);
break; fallthru = false;
case OMP_SECTION:
make_edge (bb, bb->next_bb, EDGE_FALLTHRU);
break; break;
default: default:
gcc_unreachable (); gcc_assert (!stmt_ends_bb_p (last));
fallthru = true;
} }
}
else
fallthru = true;
if (fallthru)
make_edge (bb, bb->next_bb, EDGE_FALLTHRU);
}
/* Fold COND_EXPR_COND of each COND_EXPR. */
fold_cond_expr_cond ();
/* Clean up the graph and warn for unreachable code. */
cleanup_tree_cfg ();
} }
/* Link an OMP_SECTIONS block to all the OMP_SECTION blocks in its body. */
static void
make_omp_sections_edges (basic_block bb)
{
basic_block exit_bb;
size_t i, n;
tree vec, stmt;
stmt = last_stmt (bb);
vec = OMP_SECTIONS_SECTIONS (stmt);
n = TREE_VEC_LENGTH (vec);
exit_bb = bb_for_stmt (TREE_VEC_ELT (vec, n - 1));
for (i = 0; i < n - 1; i += 2)
{
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, 0);
make_edge (end_bb, exit_bb, EDGE_FALLTHRU);
}
/* Once the CFG has been built, the vector of sections is no longer
useful. The region can be easily obtained with build_omp_regions.
Furthermore, this sharing of tree expressions is not allowed by the
statement verifier. */
OMP_SECTIONS_SECTIONS (stmt) = NULL_TREE;
}
/* Create the edges for a COND_EXPR starting at block BB. /* Create the edges for a COND_EXPR starting at block BB.
At this point, both clauses must contain only simple gotos. */ At this point, both clauses must contain only simple gotos. */
...@@ -887,7 +832,7 @@ make_goto_expr_edges (basic_block bb) ...@@ -887,7 +832,7 @@ make_goto_expr_edges (basic_block bb)
{ {
tree goto_t; tree goto_t;
basic_block target_bb; basic_block target_bb;
int for_call; bool for_call;
block_stmt_iterator last = bsi_last (bb); block_stmt_iterator last = bsi_last (bb);
goto_t = bsi_stmt (last); goto_t = bsi_stmt (last);
...@@ -896,11 +841,11 @@ make_goto_expr_edges (basic_block bb) ...@@ -896,11 +841,11 @@ make_goto_expr_edges (basic_block bb)
CALL_EXPR or MODIFY_EXPR), then the edge is an abnormal edge resulting CALL_EXPR or MODIFY_EXPR), then the edge is an abnormal edge resulting
from a nonlocal goto. */ from a nonlocal goto. */
if (TREE_CODE (goto_t) != GOTO_EXPR) if (TREE_CODE (goto_t) != GOTO_EXPR)
for_call = 1; for_call = true;
else else
{ {
tree dest = GOTO_DESTINATION (goto_t); tree dest = GOTO_DESTINATION (goto_t);
for_call = 0; for_call = false;
/* A GOTO to a local label creates normal edges. */ /* A GOTO to a local label creates normal edges. */
if (simple_goto_p (goto_t)) if (simple_goto_p (goto_t))
...@@ -939,21 +884,17 @@ make_goto_expr_edges (basic_block bb) ...@@ -939,21 +884,17 @@ make_goto_expr_edges (basic_block bb)
if ( if (
/* Computed GOTOs. Make an edge to every label block that has /* Computed GOTOs. Make an edge to every label block that has
been marked as a potential target for a computed goto. */ 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 /* Nonlocal GOTO target. Make an edge to every label block
that has been marked as a potential target for a nonlocal that has been marked as a potential target for a nonlocal
goto. */ 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); make_edge (bb, target_bb, EDGE_ABNORMAL);
break; 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);
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment