diff options
author | Jan Hubicka <jh@suse.cz> | 2007-02-04 14:27:23 +0100 |
---|---|---|
committer | Jan Hubicka <hubicka@gcc.gnu.org> | 2007-02-04 13:27:23 +0000 |
commit | 1084e689538f05f1ccf59403f6358e41fd56c5d6 (patch) | |
tree | 61cbec31f848f75cb6f387628ddf79e4de1f3de6 /gcc/tree-inline.c | |
parent | facbf9482df37925486b53a299b35d3f4c504c30 (diff) | |
download | gcc-1084e689538f05f1ccf59403f6358e41fd56c5d6.zip gcc-1084e689538f05f1ccf59403f6358e41fd56c5d6.tar.gz gcc-1084e689538f05f1ccf59403f6358e41fd56c5d6.tar.bz2 |
tree-optimize.c (has_abnormal_outgoing_edge_p): Move to tree-inline.
* tree-optimize.c (has_abnormal_outgoing_edge_p): Move to tree-inline.
(execute_fixup_cfg): Break out the abnormal goto code.
* tree-inline.c (has_abnormal_outgoing_edge_p): Move here from
tree-optimize.c.
(make_nonlocal_label_edges): Move here from execute_fixup_cfg.
(optimize_inline_calls): Call make_nonlocal_label_edges.
Co-Authored-By: Eric Botcazou <ebotcazou@libertysurf.fr>
From-SVN: r121572
Diffstat (limited to 'gcc/tree-inline.c')
-rw-r--r-- | gcc/tree-inline.c | 71 |
1 files changed, 71 insertions, 0 deletions
diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c index def3af4..75a0553 100644 --- a/gcc/tree-inline.c +++ b/gcc/tree-inline.c @@ -2676,6 +2676,75 @@ fold_marked_statements (int first, struct pointer_set_t *statements) } } +/* Return true if BB has at least one abnormal outgoing edge. */ + +static inline bool +has_abnormal_outgoing_edge_p (basic_block bb) +{ + edge e; + edge_iterator ei; + + FOR_EACH_EDGE (e, ei, bb->succs) + if (e->flags & EDGE_ABNORMAL) + return true; + + return false; +} + +/* When a block from the inlined function contains a call with side-effects + in the middle gets inlined in a function with non-locals labels, the call + becomes a potential non-local goto so we need to add appropriate edge. */ + +static void +make_nonlocal_label_edges (void) +{ + block_stmt_iterator bsi; + basic_block bb; + + FOR_EACH_BB (bb) + { + for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi)) + { + tree stmt = bsi_stmt (bsi); + if (tree_can_make_abnormal_goto (stmt)) + { + if (stmt == bsi_stmt (bsi_last (bb))) + { + if (!has_abnormal_outgoing_edge_p (bb)) + make_abnormal_goto_edges (bb, true); + } + else + { + edge e = split_block (bb, stmt); + bb = e->src; + make_abnormal_goto_edges (bb, true); + } + break; + } + + /* Update PHIs on nonlocal goto receivers we (possibly) + just created new edges into. */ + if (TREE_CODE (stmt) == LABEL_EXPR + && gimple_in_ssa_p (cfun)) + { + tree target = LABEL_EXPR_LABEL (stmt); + if (DECL_NONLOCAL (target)) + { + tree phi; + + for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi)) + { + gcc_assert (SSA_NAME_OCCURS_IN_ABNORMAL_PHI + (PHI_RESULT (phi))); + mark_sym_for_renaming + (SSA_NAME_VAR (PHI_RESULT (phi))); + } + } + } + } + } +} + /* Expand calls to inline functions in the body of FN. */ unsigned int @@ -2751,6 +2820,8 @@ optimize_inline_calls (tree fn) fold_marked_statements (last, id.statements_to_fold); pointer_set_destroy (id.statements_to_fold); fold_cond_expr_cond (); + if (current_function_has_nonlocal_label) + make_nonlocal_label_edges (); /* We make no attempts to keep dominance info up-to-date. */ free_dominance_info (CDI_DOMINATORS); free_dominance_info (CDI_POST_DOMINATORS); |