diff options
author | Richard Sandiford <rsandifo@redhat.com> | 2005-02-02 20:58:39 +0000 |
---|---|---|
committer | Richard Sandiford <rsandifo@gcc.gnu.org> | 2005-02-02 20:58:39 +0000 |
commit | 7ded35b4c2c8ebf53faa42987703616e2a813421 (patch) | |
tree | 8186ca6684edf68798355acd2929c8c432d3b55b /gcc/tree-cfg.c | |
parent | d01da8bd5ea37af2e5b6d382e489de7a73579a01 (diff) | |
download | gcc-7ded35b4c2c8ebf53faa42987703616e2a813421.zip gcc-7ded35b4c2c8ebf53faa42987703616e2a813421.tar.gz gcc-7ded35b4c2c8ebf53faa42987703616e2a813421.tar.bz2 |
re PR tree-optimization/19578 (function pointer propagation fails for noreturn functions (part 2))
PR tree-optimization/19578
* tree-flow.h (modified_noreturn_calls): Declare.
(noreturn_call_p): Declare.
* tree-flow-inline.h (noreturn_call_p): New function.
(modify_stmt): Add modified noreturn calls to modified_noreturn_calls.
* tree-cfg.c (modified_noreturn_calls): New variable.
(cleanup_control_flow): Use noreturn_call_p. Split basic blocks
that contain a mid-block noreturn call.
* tree-ssa.c (delete_tree_ssa): Clear modified_noreturn_calls.
From-SVN: r94610
Diffstat (limited to 'gcc/tree-cfg.c')
-rw-r--r-- | gcc/tree-cfg.c | 24 |
1 files changed, 19 insertions, 5 deletions
diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c index ba4fbdc..cade864 100644 --- a/gcc/tree-cfg.c +++ b/gcc/tree-cfg.c @@ -2052,6 +2052,14 @@ remove_bb (basic_block bb) remove_phi_nodes_and_edges_for_unreachable_block (bb); } +/* A list of all the noreturn calls passed to modify_stmt. + cleanup_control_flow uses it to detect cases where a mid-block + indirect call has been turned into a noreturn call. When this + happens, all the instructions after the call are no longer + reachable and must be deleted as dead. */ + +VEC(tree) *modified_noreturn_calls; + /* Try to remove superfluous control structures. */ static bool @@ -2060,7 +2068,16 @@ cleanup_control_flow (void) basic_block bb; block_stmt_iterator bsi; bool retval = false; - tree stmt, call; + tree stmt; + + /* Detect cases where a mid-block call is now known not to return. */ + while (VEC_length (tree, modified_noreturn_calls)) + { + stmt = VEC_pop (tree, modified_noreturn_calls); + bb = bb_for_stmt (stmt); + if (bb != NULL && last_stmt (bb) != stmt && noreturn_call_p (stmt)) + split_block (bb, stmt); + } FOR_EACH_BB (bb) { @@ -2076,10 +2093,7 @@ cleanup_control_flow (void) /* Check for indirect calls that have been turned into noreturn calls. */ - call = get_call_expr_in (stmt); - if (call != 0 - && (call_expr_flags (call) & ECF_NORETURN) != 0 - && remove_fallthru_edge (bb->succs)) + if (noreturn_call_p (stmt) && remove_fallthru_edge (bb->succs)) { free_dominance_info (CDI_DOMINATORS); retval = true; |