diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 2266b33b3b12aa4d34ec30615a0c23bc965cb1e1..7f383beea2543262e9e611363cf07675ec99ac9a 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -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. diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c index 6f0e947f9432d5e1957bd0aae934c2c0cbb7908d..a62331b56d8ef1761c1c3d9460a6b9cfafc9c000 100644 --- a/gcc/tree-cfg.c +++ b/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; + + 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 (); @@ -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); }