/* 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.
/* 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);
/* 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;
+
+ 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;
- /* Edges for statements that sometimes alter flow control. */
- if (is_ctrl_altering_stmt (last))
- make_exit_edges (bb);
+ 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 ();
{
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);
}
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. */
{
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);
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))
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);
}