Hi, the update of RTL optimizers to use SCEV's loop bounds make them to be inexpectedly active. One of reasons is invalid. For loop
int *a; int t() { int i; for (i=0;i<1000000;i++) if (a[i]) return 1; return 0; } We get realistic number of iteration estimate to be 9999999. This is quite wrong. We could however still predict loop: int t2() { int i; for (i=0;i<3000000;i++) if (a[i]) abort (); return 0; } This patch implements that by making estimate_numbers_of_iterations_loop to save the realistic estimate only when all other exits out of the loop are unlikely (i.e. EH or predicted by NORETURN or similarly strong heuristic). Bootstrapped/regtested x86_64-linux, comitted. Honza * tree-ssa-loop-niter.c (estimate_numbers_of_iterations_loop): Do not predict loops with multiple exits realistically. * cfgloopanal.c (single_likely_exit): New function. * gcc.dg/unroll_5.c: New testcase. Index: tree-ssa-loop-niter.c =================================================================== --- tree-ssa-loop-niter.c (revision 192432) +++ tree-ssa-loop-niter.c (working copy) @@ -2965,6 +2965,7 @@ estimate_numbers_of_iterations_loop (str struct tree_niter_desc niter_desc; edge ex; double_int bound; + edge likely_exit; /* Give up if we already have tried to compute an estimation. */ if (loop->estimate_state != EST_NOT_COMPUTED) @@ -2975,6 +2976,7 @@ estimate_numbers_of_iterations_loop (str loop->any_estimate = false; exits = get_loop_exit_edges (loop); + likely_exit = single_likely_exit (loop); FOR_EACH_VEC_ELT (edge, exits, i, ex) { if (!number_of_iterations_exit (loop, ex, &niter_desc, false)) @@ -2988,7 +2990,7 @@ estimate_numbers_of_iterations_loop (str niter); record_estimate (loop, niter, niter_desc.max, last_stmt (ex->src), - true, true, true); + true, ex == likely_exit, true); } VEC_free (edge, heap, exits); Index: cfgloopanal.c =================================================================== --- cfgloopanal.c (revision 192432) +++ cfgloopanal.c (working copy) @@ -446,3 +446,40 @@ mark_loop_exit_edges (void) } } +/* Return exit edge if loop has only one exit that is likely + to be executed on runtime (i.e. it is not EH or leading + to noreturn call. */ + +edge +single_likely_exit (struct loop *loop) +{ + edge found = single_exit (loop); + VEC (edge, heap) *exits; + unsigned i; + edge ex; + + if (found) + return found; + exits = get_loop_exit_edges (loop); + FOR_EACH_VEC_ELT (edge, exits, i, ex) + { + if (ex->flags & (EDGE_EH | EDGE_ABNORMAL_CALL)) + continue; + /* The constant of 5 is set in a way so noreturn calls are + ruled out by this test. The static branch prediction algorithm + will not assign such a low probability to conditionals for usual + reasons. */ + if (profile_status != PROFILE_ABSENT + && ex->probability < 5 && !ex->count) + continue; + if (!found) + found = ex; + else + { + VEC_free (edge, heap, exits); + return NULL; + } + } + VEC_free (edge, heap, exits); + return found; +} Index: testsuite/gcc.dg/unroll_5.c =================================================================== --- testsuite/gcc.dg/unroll_5.c (revision 0) +++ testsuite/gcc.dg/unroll_5.c (revision 0) @@ -0,0 +1,25 @@ +/* { dg-do compile } */ +/* { dg-options "-O3 -fdump-rtl-loop2_unroll -funroll-loops" } */ +void abort (void); +int *a; +int t() +{ + int i; + for (i=0;i<1000000;i++) + if (a[i]) + return 1; + return 0; +} +int t2() +{ + int i; + for (i=0;i<3000000;i++) + if (a[i]) + abort (); + return 0; +} +/* { dg-final { scan-rtl-dump-times "upper bound: 999999" 1 "loop2_unroll" } } */ +/* { dg-final { scan-rtl-dump-not "realistic bound: 999999" "loop2_unroll" } } */ +/* { dg-final { scan-rtl-dump-times "upper bound: 2999999" 1 "loop2_unroll" } } */ +/* { dg-final { scan-rtl-dump-times "realistic bound: 2999999" 1 "loop2_unroll" } } */ +/* { dg-final { cleanup-rtl-dump "loop2_unroll" } } */