From 566d09eff650c4722dad479494213ecf29372da7 Mon Sep 17 00:00:00 2001 From: Jan Hubicka Date: Tue, 1 Jun 2010 22:35:08 +0200 Subject: tree-cfgcleanup.c (fixup_noreturn_call): Break out from ...; remove return value. * tree-cfgcleanup.c (fixup_noreturn_call): Break out from ...; remove return value. (split_bbs_on_noreturn_calls) .... here. * tree-optimize.c (execute_fixup_cfg): Fixup noreturn calls too. * tree-flow.h (fixup_noreturn_call): New. * testsuite/gcc.dg/lto/noreturn-1_1.c: New testcase. * testsuite/gcc.dg/lto/noreturn-1_0.c: New testcase. From-SVN: r160122 --- gcc/ChangeLog | 8 ++++++ gcc/testsuite/ChangeLog | 5 ++++ gcc/testsuite/gcc.dg/lto/noreturn-1_0.c | 14 ---------- gcc/testsuite/gcc.dg/lto/noreturn-1_1.c | 18 ------------- gcc/tree-cfgcleanup.c | 48 ++++++++++++++++++++++++++++++--- gcc/tree-flow.h | 1 + gcc/tree-optimize.c | 34 +++++++++++++++-------- 7 files changed, 81 insertions(+), 47 deletions(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index df5d3c6..513b318 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,13 @@ 2010-06-01 Jan Hubicka + * tree-cfgcleanup.c (fixup_noreturn_call): Break out from ...; + remove return value. + (split_bbs_on_noreturn_calls) .... here. + * tree-optimize.c (execute_fixup_cfg): Fixup noreturn calls too. + * tree-flow.h (fixup_noreturn_call): New. + +2010-06-01 Jan Hubicka + * emit-rtl.c (remove_insn): Fix thinko in prevoius patch. 2010-06-01 Nathan Froyd diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 4011291..464f02a 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2010-05-31 Jan Hubicka + + * testsuite/gcc.dg/lto/noreturn-1_1.c: New testcase. + * testsuite/gcc.dg/lto/noreturn-1_0.c: New testcase. + 2010-05-31 Thomas Koenig PR fortran/36928 diff --git a/gcc/testsuite/gcc.dg/lto/noreturn-1_0.c b/gcc/testsuite/gcc.dg/lto/noreturn-1_0.c index eb71c64..daac35d 100644 --- a/gcc/testsuite/gcc.dg/lto/noreturn-1_0.c +++ b/gcc/testsuite/gcc.dg/lto/noreturn-1_0.c @@ -5,17 +5,3 @@ call_me (void) { exit (0); } -void exit (int); -__attribute__ ((noreturn)) -int -call_me (void) -{ - exit (0); -} -void exit (int); -__attribute__ ((noreturn)) -int -call_me (void) -{ - exit (0); -} diff --git a/gcc/testsuite/gcc.dg/lto/noreturn-1_1.c b/gcc/testsuite/gcc.dg/lto/noreturn-1_1.c index 8e8b060..6dbded7 100644 --- a/gcc/testsuite/gcc.dg/lto/noreturn-1_1.c +++ b/gcc/testsuite/gcc.dg/lto/noreturn-1_1.c @@ -7,21 +7,3 @@ main(void) { return call_me (); } -/* { dg-lto-do run } */ -/* { dg-lto-options {{-O2 -fwhopr} } } */ - -int call_me (void); -int -main(void) -{ - return call_me (); -} -/* { dg-lto-do run } */ -/* { dg-lto-options {{-O2 -fwhopr} } } */ - -int call_me (void); -int -main(void) -{ - return call_me (); -} diff --git a/gcc/tree-cfgcleanup.c b/gcc/tree-cfgcleanup.c index b8f5a54..10fc7ac 100644 --- a/gcc/tree-cfgcleanup.c +++ b/gcc/tree-cfgcleanup.c @@ -538,6 +538,49 @@ remove_forwarder_block (basic_block bb) return true; } +/* STMT is a call that has been discovered noreturn. Fixup the CFG + and remove LHS. Return true if something changed. */ + +bool +fixup_noreturn_call (gimple stmt) +{ + basic_block bb = gimple_bb (stmt); + bool changed = false; + + if (gimple_call_builtin_p (stmt, BUILT_IN_RETURN)) + return false; + + /* First split basic block if stmt is not last. */ + if (stmt != gsi_stmt (gsi_last_bb (bb))) + split_block (bb, stmt); + + changed |= remove_fallthru_edge (bb->succs); + + /* If there is LHS, remove it. */ + if (gimple_call_lhs (stmt)) + { + tree op = gimple_call_lhs (stmt); + gimple_call_set_lhs (stmt, NULL_TREE); + /* We need to remove SSA name to avoid checking. + All uses are dominated by the noreturn and thus will + be removed afterwards. */ + if (TREE_CODE (op) == SSA_NAME) + { + use_operand_p use_p; + imm_use_iterator iter; + gimple use_stmt; + + FOR_EACH_IMM_USE_STMT (use_stmt, iter, op) + FOR_EACH_IMM_USE_ON_STMT (use_p, iter) + SET_USE (use_p, error_mark_node); + } + update_stmt (stmt); + changed = true; + } + return changed; +} + + /* Split basic blocks on calls in the middle of a basic block that are now known not to return, and remove the unreachable code. */ @@ -560,13 +603,10 @@ split_bbs_on_noreturn_calls (void) || bb->index < NUM_FIXED_BLOCKS || bb->index >= n_basic_blocks || BASIC_BLOCK (bb->index) != bb - || last_stmt (bb) == stmt || !gimple_call_noreturn_p (stmt)) continue; - changed = true; - split_block (bb, stmt); - remove_fallthru_edge (bb->succs); + changed |= fixup_noreturn_call (stmt); } return changed; diff --git a/gcc/tree-flow.h b/gcc/tree-flow.h index bcbd7fb..f28ef31 100644 --- a/gcc/tree-flow.h +++ b/gcc/tree-flow.h @@ -870,6 +870,7 @@ tree maybe_fold_tmr (tree); unsigned int execute_free_datastructures (void); unsigned int execute_fixup_cfg (void); +bool fixup_noreturn_call (gimple stmt); #include "tree-flow-inline.h" diff --git a/gcc/tree-optimize.c b/gcc/tree-optimize.c index ed46769..2631e14 100644 --- a/gcc/tree-optimize.c +++ b/gcc/tree-optimize.c @@ -231,7 +231,8 @@ execute_free_datastructures (void) } /* Pass: fixup_cfg. IPA passes, compilation of earlier functions or inlining - might have changed some properties, such as marked functions nothrow. + might have changed some properties, such as marked functions nothrow, + pure, const or noreturn. Remove redundant edges and basic blocks, and create new ones if necessary. This pass can't be executed as stand alone pass from pass manager, because @@ -267,19 +268,23 @@ execute_fixup_cfg (void) tree decl = is_gimple_call (stmt) ? gimple_call_fndecl (stmt) : NULL; - - if (decl - && gimple_call_flags (stmt) & (ECF_CONST - | ECF_PURE - | ECF_LOOPING_CONST_OR_PURE)) + if (decl) { - if (gimple_in_ssa_p (cfun)) + int flags = gimple_call_flags (stmt); + if (flags & (ECF_CONST | ECF_PURE | ECF_LOOPING_CONST_OR_PURE)) { - todo |= TODO_update_ssa | TODO_cleanup_cfg; - mark_symbols_for_renaming (stmt); - update_stmt (stmt); + if (gimple_in_ssa_p (cfun)) + { + todo |= TODO_update_ssa | TODO_cleanup_cfg; + mark_symbols_for_renaming (stmt); + update_stmt (stmt); + } } - } + + if (flags & ECF_NORETURN + && fixup_noreturn_call (stmt)) + todo |= TODO_cleanup_cfg; + } maybe_clean_eh_stmt (stmt); } @@ -293,6 +298,13 @@ execute_fixup_cfg (void) if (count_scale != REG_BR_PROB_BASE) compute_function_frequency (); + /* We just processed all calls. */ + if (cfun->gimple_df) + { + VEC_free (gimple, gc, MODIFIED_NORETURN_CALLS (cfun)); + MODIFIED_NORETURN_CALLS (cfun) = NULL; + } + /* Dump a textual representation of the flowgraph. */ if (dump_file) gimple_dump_cfg (dump_file, dump_flags); -- cgit v1.1