CFG cleanup currently searches for calls that became noreturn and fixes them up (splitting block and removing the fallthru). Previously that was technically necessary as propagation may have turned an indirect call into a direct noreturn call and the CFG verifier would have barfed. Today we guard that with GF_CALL_CTRL_ALTERING and thus we "remember" the previous call analysis.
The following patch removes the CFG cleanup code (which is expensive because gimple_call_flags () is quite expensive, not to talk about walking all stmts). This leaves the fixup_cfg passes to perform the very same optimization (relevant propagators can also be teached to call fixup_noreturn_call, but I don't think that's very important). Bootstrapped on x86_64-unknown-linux-gnu, testing in progress. I'm somewhat undecided whether this is ok at this stage and if we _do_ want to make propagators fix those (previously indirect) calls up earlier at the same time. Honza - I think we performed this in CFG cleanup for the sake of CFG checking, not for the sake of prompt optimization, no? This would make PR44563 a pure IPA pass issue. Thanks, Richard. 2015-03-10 Richard Biener <rguent...@suse.de> PR middle-end/44563 * tree-cfgcleanup.c (split_bb_on_noreturn_calls): Remove. (cleanup_tree_cfg_1): Do not call it. Index: gcc/tree-cfgcleanup.c =================================================================== *** gcc/tree-cfgcleanup.c (revision 221308) --- gcc/tree-cfgcleanup.c (working copy) *************** fixup_noreturn_call (gimple stmt) *** 629,659 **** } - /* Split basic blocks on calls in the middle of a basic block that are now - known not to return, and remove the unreachable code. */ - - static bool - split_bb_on_noreturn_calls (basic_block bb) - { - bool changed = false; - gimple_stmt_iterator gsi; - - for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) - { - gimple stmt = gsi_stmt (gsi); - - if (!is_gimple_call (stmt)) - continue; - - if (gimple_call_noreturn_p (stmt)) - changed |= fixup_noreturn_call (stmt); - } - - if (changed) - bitmap_set_bit (cfgcleanup_altered_bbs, bb->index); - return changed; - } - /* Tries to cleanup cfg in basic block BB. Returns true if anything changes. */ --- 629,634 ---- *************** cleanup_tree_cfg_1 (void) *** 703,712 **** { bb = BASIC_BLOCK_FOR_FN (cfun, i); if (bb) ! { ! retval |= cleanup_tree_cfg_bb (bb); ! retval |= split_bb_on_noreturn_calls (bb); ! } } /* Now process the altered blocks, as long as any are available. */ --- 678,684 ---- { bb = BASIC_BLOCK_FOR_FN (cfun, i); if (bb) ! retval |= cleanup_tree_cfg_bb (bb); } /* Now process the altered blocks, as long as any are available. */ *************** cleanup_tree_cfg_1 (void) *** 722,731 **** continue; retval |= cleanup_tree_cfg_bb (bb); - - /* Rerun split_bb_on_noreturn_calls, in case we have altered any noreturn - calls. */ - retval |= split_bb_on_noreturn_calls (bb); } end_recording_case_labels (); --- 694,699 ----