We're threading into a loop across an inner exit. Bootstrapped and tested on x86_64-unknown-linux-gnu, applied.
Richard. 2018-05-03 Richard Biener <rguent...@suse.de> PR tree-optimization/85615 * tree-ssa-threadupdate.c (thread_block_1): Only allow exits to loops not nested in BBs loop father to avoid creating multi-entry loops. * gcc.dg/torture/pr85615.c: New testcase. Index: gcc/tree-ssa-threadupdate.c =================================================================== --- gcc/tree-ssa-threadupdate.c (revision 259879) +++ gcc/tree-ssa-threadupdate.c (working copy) @@ -1309,7 +1309,9 @@ thread_block_1 (basic_block bb, bool nol and thread this elsewhere, so just cancel the jump threading request by clearing the AUX field now. */ if (bb->loop_father != e2->src->loop_father - && !loop_exit_edge_p (e2->src->loop_father, e2)) + && (!loop_exit_edge_p (e2->src->loop_father, e2) + || flow_loop_nested_p (bb->loop_father, + e2->dest->loop_father))) { /* Since this case is not handled by our special code to thread through a loop header, we must explicitly Index: gcc/testsuite/gcc.dg/torture/pr85615.c =================================================================== --- gcc/testsuite/gcc.dg/torture/pr85615.c (nonexistent) +++ gcc/testsuite/gcc.dg/torture/pr85615.c (working copy) @@ -0,0 +1,28 @@ +/* { dg-do compile } */ + +long a, d; +int b, c; +void fn1() +{ + int e = -1L, f = 2, g = 8; + for (;;) + { + for (; b; g++) + ; + int i; + for (; c;) + { + i = 5; + for (; e >= 1; i--) + ; + } + d = f ?: a; + if (d) + { + e = 0; + for (; i;) + for (; g < 3; f++) + ; + } + } +}