The following makes loop-header copying stop after the first exit test it copied. The reports rightfully complain about too much peeling. If some cases pop up which show we should peel up to a specific test we need to improve this heuristic which simply errs on the easy side.
Bootstrap & regtest running on x86_64-unknown-linux-gnu. Richard. 2018-04-26 Richard Biener <rguent...@suse.de> PR tree-optimization/28364 PR tree-optimization/85275 * tree-ssa-loop-ch.c (ch_base::copy_headers): Stop after copying first exit test. * gcc.dg/tree-ssa/copy-headers-5.c: New testcase. Index: gcc/tree-ssa-loop-ch.c =================================================================== --- gcc/tree-ssa-loop-ch.c (revision 259669) +++ gcc/tree-ssa-loop-ch.c (working copy) @@ -328,6 +340,11 @@ ch_base::copy_headers (function *fun) bbs[n_bbs++] = header; gcc_assert (bbs_size > n_bbs); header = exit->dest; + /* Make sure to stop copying after we copied the first exit test. + Without further heuristics we do not want to rotate the loop + any further. */ + if (loop_exits_from_bb_p (loop, exit->src)) + break; } if (!exit) Index: gcc/testsuite/gcc.dg/tree-ssa/copy-headers-5.c =================================================================== --- gcc/testsuite/gcc.dg/tree-ssa/copy-headers-5.c (nonexistent) +++ gcc/testsuite/gcc.dg/tree-ssa/copy-headers-5.c (working copy) @@ -0,0 +1,16 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-ch2-details" } */ + +int is_sorted(int *a, int n) +{ + for (int i = 0; i < n - 1; i++) + if (a[i] > a[i + 1]) + return 0; + return 1; +} + +/* Verify we apply loop header copying but only copy the IV test and + not the alternate exit test. */ + +/* { dg-final { scan-tree-dump "is now do-while loop" "ch2" } } */ +/* { dg-final { scan-tree-dump-times " if " 3 "ch2" } } */