From f9bf4777c1f93f733b4e99e44dd176417ed0afca Mon Sep 17 00:00:00 2001 From: Jan Hubicka <jh@suse.cz> Date: Sun, 14 Oct 2012 18:18:26 +0200 Subject: [PATCH] tree-ssa-loop-niter.c (estimate_numbers_of_iterations_loop): Do not predict loops with multiple exits realistically. * 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. From-SVN: r192433 --- gcc/ChangeLog | 6 ++++++ gcc/cfgloopanal.c | 37 +++++++++++++++++++++++++++++++++ gcc/testsuite/ChangeLog | 4 ++++ gcc/testsuite/gcc.dg/unroll_5.c | 25 ++++++++++++++++++++++ gcc/tree-ssa-loop-niter.c | 4 +++- 5 files changed, 75 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/gcc.dg/unroll_5.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index b74a547aa9c0..a50d9d305c01 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2012-10-14 Jan Hubicka <jh@suse.cz> + + * 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. + 2012-10-14 Uros Bizjak <ubizjak@gmail.com> * config/alpha/alpha.md: Remove empty predicates and/or constraints. diff --git a/gcc/cfgloopanal.c b/gcc/cfgloopanal.c index cec33fbb97e3..c3cf3edf9b9f 100644 --- a/gcc/cfgloopanal.c +++ b/gcc/cfgloopanal.c @@ -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; +} diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 3a7dd939a844..79aee2f3d6e3 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2012-10-14 Jan Hubicka <jh@suse.cz> + + * gcc.dg/unroll_5.c: New testcase. + 2012-10-14 Paolo Carlini <paolo.carlini@oracle.com> PR c++/52643 diff --git a/gcc/testsuite/gcc.dg/unroll_5.c b/gcc/testsuite/gcc.dg/unroll_5.c new file mode 100644 index 000000000000..48259eb84473 --- /dev/null +++ b/gcc/testsuite/gcc.dg/unroll_5.c @@ -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" } } */ diff --git a/gcc/tree-ssa-loop-niter.c b/gcc/tree-ssa-loop-niter.c index cdcdb5c5ad8e..3c39413ee1bd 100644 --- a/gcc/tree-ssa-loop-niter.c +++ b/gcc/tree-ssa-loop-niter.c @@ -2965,6 +2965,7 @@ estimate_numbers_of_iterations_loop (struct loop *loop) 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 (struct loop *loop) 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 (struct loop *loop) 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); -- GitLab