This properly tells the CFG manipulation of the case where we thread through a loop exit - the duplicated header block will end up in the outer loop and the original loop structure will be preserved.
Bootstrapped on x86_64-unknown-linux-gnu, testing in progress. Richard. 2012-04-10 Richard Guenther <rguent...@suse.de> PR tree-optimization/52912 * tree-ssa-threadupdate.c (thread_block): Tell the cfg manipulation code we are threading through a loop header to an exit destination. * gcc.dg/torture/pr52912.c: New testcase. Index: gcc/tree-ssa-threadupdate.c =================================================================== *** gcc/tree-ssa-threadupdate.c (revision 186274) --- gcc/tree-ssa-threadupdate.c (working copy) *************** thread_block (basic_block bb, bool noloo *** 661,666 **** --- 661,673 ---- /* We do not update dominance info. */ free_dominance_info (CDI_DOMINATORS); + /* We know we only thread through the loop header to loop exits. + Let the basic block duplication hook know we are not creating + a multiple entry loop. */ + if (noloop_only + && bb == bb->loop_father->header) + set_loop_copy (bb->loop_father, loop_outer (bb->loop_father)); + /* Now create duplicates of BB. Note that for a block with a high outgoing degree we can waste *************** thread_block (basic_block bb, bool noloo *** 692,697 **** --- 699,708 ---- htab_delete (redirection_data); redirection_data = NULL; + if (noloop_only + && bb == bb->loop_father->header) + set_loop_copy (bb->loop_father, NULL); + /* Indicate to our caller whether or not any jumps were threaded. */ return local_info.jumps_threaded; } Index: gcc/testsuite/gcc.dg/torture/pr52912.c =================================================================== *** gcc/testsuite/gcc.dg/torture/pr52912.c (revision 0) --- gcc/testsuite/gcc.dg/torture/pr52912.c (revision 0) *************** *** 0 **** --- 1,18 ---- + /* { dg-do compile } */ + + int a, b, c; + static int + fn1 (p1) + { + lbl_549: + if (p1) + goto lbl_549; + return 0; + } + + void + fn2 () + { + b = (c && a) > fn1 (c) >= c; + } +