]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR tree-optimization/45427 (Number of iteration analysis bogus)
authorZdenek Dvorak <ook@ucw.cz>
Mon, 30 Aug 2010 19:50:05 +0000 (21:50 +0200)
committerZdenek Dvorak <rakdver@gcc.gnu.org>
Mon, 30 Aug 2010 19:50:05 +0000 (19:50 +0000)
PR tree-optimization/45427
* tree-ssa-loop-niter.c (number_of_iterations_ne_max): Rewritten.
Handle the case that the exit is never taken correctly.
(number_of_iterations_ne): Pass exit_must_be_taken to
number_of_iterations_ne_max.

* gcc.dg/tree-ssa/pr45427.c: New test.

From-SVN: r163659

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/tree-ssa/pr45427.c [new file with mode: 0644]
gcc/tree-ssa-loop-niter.c

index 71dc958e5a067356f6fcb3ad03cc73fd90fe3ac2..fe16d48fae50a21801487a4e0832dbe6b3442d9e 100644 (file)
@@ -1,3 +1,11 @@
+2010-08-30  Zdenek Dvorak  <ook@ucw.cz>
+
+       PR tree-optimization/45427
+       * tree-ssa-loop-niter.c (number_of_iterations_ne_max): Rewritten.
+       Handle the case that the exit is never taken correctly.
+       (number_of_iterations_ne): Pass exit_must_be_taken to
+       number_of_iterations_ne_max.
+
 2010-08-31  Catherine Moore  <clm@codesourcery.com>
 
        * config/mips/mips.h (BASE_DRIVER_SELF_SPECS):
index 9bbb54bbf38bb30fc3aea3c48505ec43747a3120..fd8fecbd9e88e90066662307a869ece49682ad6b 100644 (file)
@@ -1,3 +1,8 @@
+2010-08-30  Zdenek Dvorak  <ook@ucw.cz>
+
+       PR tree-optimization/45427
+       * gcc.dg/tree-ssa/pr45427.c: New test.
+
 2010-08-30  Paolo Carlini  <paolo.carlini@oracle.com>
 
        PR c++/45043
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr45427.c b/gcc/testsuite/gcc.dg/tree-ssa/pr45427.c
new file mode 100644 (file)
index 0000000..0952b5a
--- /dev/null
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-cunrolli-details" } */
+
+extern void abort (void);
+int __attribute__((noinline,noclone))
+foo (char *p)
+{
+  int h = 0;
+  do
+    {
+      if (*p == '\0')
+        break;
+      ++h;
+      if (p == 0)
+        abort ();
+      ++p;
+    }
+  while (1);
+  return h;
+}
+int main()
+{
+  if (foo("a") != 1)
+    abort ();
+  return 0;
+}
+
+/* { dg-final { scan-tree-dump-times "bounded by 0" 0 "cunrolli"} } */
+/* { dg-final { cleanup-tree-dump "cunrolli" } } */
index d23592dfa53175ee1b2e99655120d58e855796f4..2118b973a63ef5bc06d334b28e108468a2f2c6bb 100644 (file)
@@ -536,22 +536,46 @@ inverse (tree x, tree mask)
 }
 
 /* Derives the upper bound BND on the number of executions of loop with exit
-   condition S * i <> C, assuming that this exit is taken.  If
-   NO_OVERFLOW is true, then the control variable of the loop does not
-   overflow.  If NO_OVERFLOW is true or BNDS.below >= 0, then BNDS.up
-   contains the upper bound on the value of C.  */
+   condition S * i <> C.  If NO_OVERFLOW is true, then the control variable of
+   the loop does not overflow.  EXIT_MUST_BE_TAKEN is true if we are guaranteed
+   that the loop ends through this exit, i.e., the induction variable ever
+   reaches the value of C.  
+   
+   The value C is equal to final - base, where final and base are the final and
+   initial value of the actual induction variable in the analysed loop.  BNDS
+   bounds the value of this difference when computed in signed type with
+   unbounded range, while the computation of C is performed in an unsigned
+   type with the range matching the range of the type of the induction variable.
+   In particular, BNDS.up contains an upper bound on C in the following cases:
+   -- if the iv must reach its final value without overflow, i.e., if
+      NO_OVERFLOW && EXIT_MUST_BE_TAKEN is true, or
+   -- if final >= base, which we know to hold when BNDS.below >= 0.  */
 
 static void
 number_of_iterations_ne_max (mpz_t bnd, bool no_overflow, tree c, tree s,
-                            bounds *bnds)
+                            bounds *bnds, bool exit_must_be_taken)
 {
   double_int max;
   mpz_t d;
+  bool bnds_u_valid = ((no_overflow && exit_must_be_taken)
+                      || mpz_sgn (bnds->below) >= 0);
 
-  /* If the control variable does not overflow, the number of iterations is
-     at most c / s.  Otherwise it is at most the period of the control
-     variable.  */
-  if (!no_overflow && !multiple_of_p (TREE_TYPE (c), c, s))
+  if (multiple_of_p (TREE_TYPE (c), c, s))
+    {
+      /* If C is an exact multiple of S, then its value will be reached before
+        the induction variable overflows (unless the loop is exited in some
+        other way before).  Note that the actual induction variable in the
+        loop (which ranges from base to final instead of from 0 to C) may
+        overflow, in which case BNDS.up will not be giving a correct upper
+        bound on C; thus, BNDS_U_VALID had to be computed in advance.  */
+      no_overflow = true;
+      exit_must_be_taken = true;
+    }
+
+  /* If the induction variable can overflow, the number of iterations is at
+     most the period of the control variable (or infinite, but in that case
+     the whole # of iterations analysis will fail).  */
+  if (!no_overflow)
     {
       max = double_int_mask (TYPE_PRECISION (TREE_TYPE (c))
                             - tree_low_cst (num_ending_zeros (s), 1));
@@ -559,14 +583,22 @@ number_of_iterations_ne_max (mpz_t bnd, bool no_overflow, tree c, tree s,
       return;
     }
 
-  /* Determine the upper bound on C.  */
-  if (no_overflow || mpz_sgn (bnds->below) >= 0)
-    mpz_set (bnd, bnds->up);
-  else if (TREE_CODE (c) == INTEGER_CST)
-    mpz_set_double_int (bnd, tree_to_double_int (c), true);
-  else
-    mpz_set_double_int (bnd, double_int_mask (TYPE_PRECISION (TREE_TYPE (c))),
-                       true);
+  /* Now we know that the induction variable does not overflow, so the loop
+     iterates at most (range of type / S) times.  */
+  mpz_set_double_int (bnd, double_int_mask (TYPE_PRECISION (TREE_TYPE (c))),
+                     true);
+
+  /* If the induction variable is guaranteed to reach the value of C before
+     overflow, ... */
+  if (exit_must_be_taken)
+    {
+      /* ... then we can strenghten this to C / S, and possibly we can use
+        the upper bound on C given by BNDS.  */
+      if (TREE_CODE (c) == INTEGER_CST)
+       mpz_set_double_int (bnd, tree_to_double_int (c), true);
+      else if (bnds_u_valid)
+       mpz_set (bnd, bnds->up);
+    }
 
   mpz_init (d);
   mpz_set_double_int (d, tree_to_double_int (s), true);
@@ -618,7 +650,8 @@ number_of_iterations_ne (tree type, affine_iv *iv, tree final,
     }
 
   mpz_init (max);
-  number_of_iterations_ne_max (max, iv->no_overflow, c, s, bnds);
+  number_of_iterations_ne_max (max, iv->no_overflow, c, s, bnds,
+                              exit_must_be_taken);
   niter->max = mpz_get_double_int (niter_type, max, false);
   mpz_clear (max);