On Thu, 25 Oct 2012, Richard Biener wrote: > On Thu, 25 Oct 2012, Jakub Jelinek wrote: > > > On Thu, Oct 25, 2012 at 12:58:26PM +0200, Richard Biener wrote: > > > So the bug here is really in find_many_sub_basic_blocks then > > > and your patch would certainly avoid triggering its bug > > > (or its wrong expectations). I'll give it testing. > > > > I'd say we should insert the __builtin_unreachable already far earlier than > > that, either when inlining the noreturn function and figuring out > > it might return (perhaps conditionally on something that never happens), > > or if LTO does something similar with it even without inlining. > > That would be fixup_cfg which is supposed to deal with this kind of > "fallout", like in my original patch (just using __builtin_unreachable () > instead of an infinite loop edge) > > Honza?
Like the following, bootstrap & regtest pending on x86_64-unknown-linux-gnu. Richard. 2012-10-15 Richard Biener <rguent...@suse.de> PR middle-end/54824 * tree-optimize.c (execute_fixup_cfg): Insert __builtin_unreachable at the end of blocks with no successors. * gcc.dg/torture/pr54824.c: New testcase. Index: gcc/tree-optimize.c =================================================================== *** gcc/tree-optimize.c (revision 192803) --- gcc/tree-optimize.c (working copy) *************** execute_fixup_cfg (void) *** 180,185 **** --- 180,204 ---- FOR_EACH_EDGE (e, ei, bb->succs) e->count = (e->count * count_scale + REG_BR_PROB_BASE / 2) / REG_BR_PROB_BASE; + + /* If we have a basic-block with no successors that does not + end with a control statement or a noreturn call connect it + to itself. This situation can occur when inlining a noreturn + call that does in fact return. */ + if (EDGE_COUNT (bb->succs) == 0) + { + gimple stmt = last_stmt (bb); + if (!stmt + || (!is_ctrl_stmt (stmt) + && (!is_gimple_call (stmt) + || (gimple_call_flags (stmt) & ECF_NORETURN) == 0))) + { + stmt = gimple_build_call + (builtin_decl_implicit (BUILT_IN_UNREACHABLE), 0); + gimple_stmt_iterator gsi = gsi_last_bb (bb); + gsi_insert_after (&gsi, stmt, GSI_NEW_STMT); + } + } } if (count_scale != REG_BR_PROB_BASE) compute_function_frequency (); Index: gcc/testsuite/gcc.dg/torture/pr54824.c =================================================================== *** gcc/testsuite/gcc.dg/torture/pr54824.c (revision 0) --- gcc/testsuite/gcc.dg/torture/pr54824.c (working copy) *************** *** 0 **** --- 1,16 ---- + /* { dg-do compile } */ + /* { dg-options "-w" } */ + + void __attribute__((noreturn)) bar(void) + { + } + + void foo(int i, char *p, char *q) + { + while (*p++) { + if (i) + p++; + if (!*q++) + bar(); + } + }