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