aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree-cfg.c
diff options
context:
space:
mode:
authorRichard Sandiford <rsandifo@redhat.com>2005-02-02 20:58:39 +0000
committerRichard Sandiford <rsandifo@gcc.gnu.org>2005-02-02 20:58:39 +0000
commit7ded35b4c2c8ebf53faa42987703616e2a813421 (patch)
tree8186ca6684edf68798355acd2929c8c432d3b55b /gcc/tree-cfg.c
parentd01da8bd5ea37af2e5b6d382e489de7a73579a01 (diff)
downloadgcc-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.c24
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;