OSDN Git Service

* tree-ssa-loop-niter.c (number_of_iterations_cond): Split into several
authorrakdver <rakdver@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 14 Jan 2006 12:29:06 +0000 (12:29 +0000)
committerrakdver <rakdver@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 14 Jan 2006 12:29:06 +0000 (12:29 +0000)
functions.
(number_of_iterations_ne, number_of_iterations_lt_to_ne,
assert_no_overflow_lt, assert_loop_rolls_lt, number_of_iterations_lt,
number_of_iterations_le): New functions.
(number_of_iterations_special): Removed.
(number_of_iterations_exit): Do not use number_of_iterations_special.
* tree.c (unsigned_type_for): Always return integer type.

* gcc.dg/tree-ssa/pr19210-1.c: Update outcome.  Add new test loop.
* gcc.dg/tree-ssa/pr19210-2.c: Ditto.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@109702 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/tree-ssa/pr19210-1.c
gcc/testsuite/gcc.dg/tree-ssa/pr19210-2.c
gcc/tree-ssa-loop-niter.c
gcc/tree.c

index e7961fe..2422704 100644 (file)
@@ -1,3 +1,14 @@
+2006-01-14  Zdenek Dvorak <dvorakz@suse.cz>
+
+       * tree-ssa-loop-niter.c (number_of_iterations_cond): Split into several
+       functions.
+       (number_of_iterations_ne, number_of_iterations_lt_to_ne,
+       assert_no_overflow_lt, assert_loop_rolls_lt, number_of_iterations_lt,
+       number_of_iterations_le): New functions.
+       (number_of_iterations_special): Removed.
+       (number_of_iterations_exit): Do not use number_of_iterations_special.
+       * tree.c (unsigned_type_for): Always return integer type.
+
 2006-01-14  Steven Bosscher  <stevenb.gcc@gmail.com>
        Richard Guenther  <rguenther@suse.de>
 
index 66a7b7f..ffe0dc9 100644 (file)
@@ -1,3 +1,8 @@
+2005-01-14  Zdenek Dvorak <dvorakz@suse.cz>
+
+       * gcc.dg/tree-ssa/pr19210-1.c: Update outcome.  Add new test loop.
+       * gcc.dg/tree-ssa/pr19210-2.c: Ditto.
+
 2006-01-14  Steven Bosscher  <stevenb.gcc@gmail.com>
        Richard Guenther  <rguenther@suse.de>
 
index 4d6100a..906132c 100644 (file)
@@ -12,9 +12,18 @@ f (unsigned n)
   for(k = 0;k <= n;k += 4) /* { dg-warning "cannot optimize.*overflow" } */
     g();
 
-  for(k = 5;k <= n;k += 5) /* { dg-warning "cannot optimize.*overflow" } */
+  /* We used to get warning for this loop.  However, since then # of iterations
+     analysis improved, and we can now prove that this loop does not verflow.
+     This is because the only case when it would overflow is if n = ~0 (since
+     ~0 is divisible by 5), and this cannot be the case, since when we got
+     here, the previous loop exited, thus there exists k > n.  */
+  for(k = 5;k <= n;k += 5)
     g();
 
+  /* So we need the following loop, instead.  */
+  for(k = 4;k <= n;k += 5) /* { dg-warning "cannot optimize.*overflow" } */
+    g();
+  
   for(k = 15;k >= n;k--) /* { dg-warning "cannot optimize.*infinite" } */
     g();
 }
index 498c658..9116e97 100644 (file)
@@ -12,7 +12,15 @@ f (unsigned n)
   for(k = 5;k <= n;k += 4) /* { dg-warning "assuming.*not overflow" } */
     g();
 
-  for(k = 5;k <= n;k += 5) /* { dg-warning "assuming.*not overflow" } */
+  /* We used to get warning for this loop.  However, since then # of iterations
+     analysis improved, and we can now prove that this loop does not verflow.
+     This is because the only case when it would overflow is if n = ~0 (since
+     ~0 is divisible by 5), and this cannot be the case, since when we got
+     here, the previous loop exited, thus there exists k > n.  */
+  for(k = 5;k <= n;k += 5)
+    g();
+
+  for(k = 4;k <= n;k += 5) /* { dg-warning "assuming.*not overflow" } */
     g();
 
   for(k = 15;k >= n;k--) /* { dg-warning "assuming.*not infinite" } */
index bd3667b..7566e7c 100644 (file)
@@ -126,490 +126,504 @@ inverse (tree x, tree mask)
   return rslt;
 }
 
-/* Determine the number of iterations according to condition (for staying
-   inside loop) which compares two induction variables using comparison
-   operator CODE.  The induction variable on left side of the comparison
-   is IV0, the right-hand side is IV1.  Both induction variables must have
-   type TYPE, which must be an integer or pointer type.  The steps of the
-   ivs must be constants (or NULL_TREE, which is interpreted as constant zero).
-   
-   The results (number of iterations and assumptions as described in
-   comments at struct tree_niter_desc in tree-flow.h) are stored to NITER.
-   In case we are unable to determine number of iterations, contents of
-   this structure is unchanged.  */
+/* Determines number of iterations of loop whose ending condition
+   is IV <> FINAL.  TYPE is the type of the iv.  The number of
+   iterations is stored to NITER.  NEVER_INFINITE is true if
+   we know that the loop cannot be infinite (we derived this
+   earlier, and possibly set NITER->assumptions to make sure this
+   is the case.  */
 
-static void
-number_of_iterations_cond (tree type, affine_iv *iv0, enum tree_code code,
-                          affine_iv *iv1, struct tree_niter_desc *niter)
+static bool
+number_of_iterations_ne (tree type, affine_iv *iv, tree final,
+                        struct tree_niter_desc *niter, bool never_infinite)
 {
-  tree step, delta, mmin, mmax;
-  tree may_xform, bound, s, d, tmp;
-  bool was_sharp = false, never_infinite;
-  tree assumption;
-  tree assumptions = boolean_true_node;
-  tree noloop_assumptions = boolean_false_node;
-  tree niter_type, signed_niter_type;
-  tree bits;
+  tree niter_type = unsigned_type_for (type);
+  tree s, c, d, bits, assumption, tmp, bound;
 
-  /* The meaning of these assumptions is this:
-     if !assumptions
-       then the rest of information does not have to be valid
-     if noloop_assumptions then the loop does not have to roll
-       (but it is only conservative approximation, i.e. it only says that
-       if !noloop_assumptions, then the loop does not end before the computed
-       number of iterations)  */
-
-  /* Make < comparison from > ones.  */
-  if (code == GE_EXPR
-      || code == GT_EXPR)
+  /* Rearrange the terms so that we get inequality s * i <> c, with s
+     positive.  Also cast everything to the unsigned type.  */
+  if (tree_int_cst_sign_bit (iv->step))
     {
-      SWAP (iv0, iv1);
-      code = swap_tree_comparison (code);
+      s = fold_convert (niter_type,
+                       fold_build1 (NEGATE_EXPR, type, iv->step));
+      c = fold_build2 (MINUS_EXPR, niter_type,
+                      fold_convert (niter_type, iv->base),
+                      fold_convert (niter_type, final));
     }
-
-  /* If the control induction variable does not overflow, the loop obviously
-     cannot be infinite.  */
-  if (!zero_p (iv0->step) && iv0->no_overflow)
-    never_infinite = true;
-  else if (!zero_p (iv1->step) && iv1->no_overflow)
-    never_infinite = true;
   else
-    never_infinite = false;
-
-  /* We can handle the case when neither of the sides of the comparison is
-     invariant, provided that the test is NE_EXPR.  This rarely occurs in
-     practice, but it is simple enough to manage.  */
-  if (!zero_p (iv0->step) && !zero_p (iv1->step))
     {
-      if (code != NE_EXPR)
-       return;
+      s = fold_convert (niter_type, iv->step);
+      c = fold_build2 (MINUS_EXPR, niter_type,
+                      fold_convert (niter_type, final),
+                      fold_convert (niter_type, iv->base));
+    }
 
-      iv0->step = fold_binary_to_constant (MINUS_EXPR, type,
-                                          iv0->step, iv1->step);
-      iv0->no_overflow = false;
-      iv1->step = NULL_TREE;
-      iv1->no_overflow = true;
+  /* First the trivial cases -- when the step is 1.  */
+  if (integer_onep (s))
+    {
+      niter->niter = c;
+      return true;
     }
 
-  /* If the result is a constant,  the loop is weird.  More precise handling
-     would be possible, but the situation is not common enough to waste time
-     on it.  */
-  if (zero_p (iv0->step) && zero_p (iv1->step))
-    return;
+  /* Let nsd (step, size of mode) = d.  If d does not divide c, the loop
+     is infinite.  Otherwise, the number of iterations is
+     (inverse(s/d) * (c/d)) mod (size of mode/d).  */
+  bits = num_ending_zeros (s);
+  bound = build_low_bits_mask (niter_type,
+                              (TYPE_PRECISION (niter_type)
+                               - tree_low_cst (bits, 1)));
 
-  /* Ignore loops of while (i-- < 10) type.  */
-  if (code != NE_EXPR)
-    {
-      if (iv0->step && tree_int_cst_sign_bit (iv0->step))
-       return;
+  d = fold_binary_to_constant (LSHIFT_EXPR, niter_type,
+                              build_int_cst_type (niter_type, 1), bits);
+  s = fold_binary_to_constant (RSHIFT_EXPR, niter_type, s, bits);
 
-      if (!zero_p (iv1->step) && !tree_int_cst_sign_bit (iv1->step))
-       return;
+  if (!never_infinite)
+    {
+      /* If we cannot assume that the loop is not infinite, record the
+        assumptions for divisibility of c.  */
+      assumption = fold_build2 (FLOOR_MOD_EXPR, niter_type, c, d);
+      assumption = fold_build2 (EQ_EXPR, boolean_type_node,
+                               assumption, build_int_cst (niter_type, 0));
+      if (!nonzero_p (assumption))
+       niter->assumptions = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
+                                         niter->assumptions, assumption);
     }
+      
+  c = fold_build2 (EXACT_DIV_EXPR, niter_type, c, d);
+  tmp = fold_build2 (MULT_EXPR, niter_type, c, inverse (s, bound));
+  niter->niter = fold_build2 (BIT_AND_EXPR, niter_type, tmp, bound);
+  return true;
+}
 
-  if (POINTER_TYPE_P (type))
+/* Checks whether we can determine the final value of the control variable
+   of the loop with ending condition IV0 < IV1 (computed in TYPE).
+   DELTA is the difference IV1->base - IV0->base, STEP is the absolute value
+   of the step.  The assumptions necessary to ensure that the computation
+   of the final value does not overflow are recorded in NITER.  If we
+   find the final value, we adjust DELTA and return TRUE.  Otherwise
+   we return false.  */
+
+static bool
+number_of_iterations_lt_to_ne (tree type, affine_iv *iv0, affine_iv *iv1,
+                              struct tree_niter_desc *niter,
+                              tree *delta, tree step)
+{
+  tree niter_type = TREE_TYPE (step);
+  tree mod = fold_build2 (FLOOR_MOD_EXPR, niter_type, *delta, step);
+  tree tmod;
+  tree assumption = boolean_true_node, bound, noloop;
+
+  if (TREE_CODE (mod) != INTEGER_CST)
+    return false;
+  if (nonzero_p (mod))
+    mod = fold_build2 (MINUS_EXPR, niter_type, step, mod);
+  tmod = fold_convert (type, mod);
+
+  if (nonzero_p (iv0->step))
     {
-      /* We assume pointer arithmetic never overflows.  */
-      mmin = mmax = NULL_TREE;
+      /* The final value of the iv is iv1->base + MOD, assuming that this
+        computation does not overflow, and that
+        iv0->base <= iv1->base + MOD.  */
+      if (!iv1->no_overflow && !zero_p (mod))
+       {
+         bound = fold_build2 (MINUS_EXPR, type,
+                              TYPE_MAX_VALUE (type), tmod);
+         assumption = fold_build2 (LE_EXPR, boolean_type_node,
+                                   iv1->base, bound);
+         if (zero_p (assumption))
+           return false;
+       }
+      noloop = fold_build2 (GT_EXPR, boolean_type_node,
+                           iv0->base,
+                           fold_build2 (PLUS_EXPR, type,
+                                        iv1->base, tmod));
     }
   else
     {
-      mmin = TYPE_MIN_VALUE (type);
-      mmax = TYPE_MAX_VALUE (type);
+      /* The final value of the iv is iv0->base - MOD, assuming that this
+        computation does not overflow, and that
+        iv0->base - MOD <= iv1->base. */
+      if (!iv0->no_overflow && !zero_p (mod))
+       {
+         bound = fold_build2 (PLUS_EXPR, type,
+                              TYPE_MIN_VALUE (type), tmod);
+         assumption = fold_build2 (GE_EXPR, boolean_type_node,
+                                   iv0->base, bound);
+         if (zero_p (assumption))
+           return false;
+       }
+      noloop = fold_build2 (GT_EXPR, boolean_type_node,
+                           fold_build2 (MINUS_EXPR, type,
+                                        iv0->base, tmod),
+                           iv1->base);
     }
 
-  /* Some more condition normalization.  We must record some assumptions
-     due to overflows.  */
+  if (!nonzero_p (assumption))
+    niter->assumptions = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
+                                     niter->assumptions,
+                                     assumption);
+  if (!zero_p (noloop))
+    niter->may_be_zero = fold_build2 (TRUTH_OR_EXPR, boolean_type_node,
+                                     niter->may_be_zero,
+                                     noloop);
+  *delta = fold_build2 (PLUS_EXPR, niter_type, *delta, mod);
+  return true;
+}
+
+/* Add assertions to NITER that ensure that the control variable of the loop
+   with ending condition IV0 < IV1 does not overflow.  Types of IV0 and IV1
+   are TYPE.  Returns false if we can prove that there is an overflow, true
+   otherwise.  STEP is the absolute value of the step.  */
+
+static bool
+assert_no_overflow_lt (tree type, affine_iv *iv0, affine_iv *iv1,
+                      struct tree_niter_desc *niter, tree step)
+{
+  tree bound, d, assumption, diff;
+  tree niter_type = TREE_TYPE (step);
 
-  if (code == LT_EXPR)
+  if (nonzero_p (iv0->step))
     {
-      /* We want to take care only of <=; this is easy,
-        as in cases the overflow would make the transformation unsafe the loop
-        does not roll.  Seemingly it would make more sense to want to take
-        care of <, as NE is more similar to it, but the problem is that here
-        the transformation would be more difficult due to possibly infinite
-        loops.  */
-      if (zero_p (iv0->step))
+      /* for (i = iv0->base; i < iv1->base; i += iv0->step) */
+      if (iv0->no_overflow)
+       return true;
+
+      /* If iv0->base is a constant, we can determine the last value before
+        overflow precisely; otherwise we conservatively assume
+        MAX - STEP + 1.  */
+
+      if (TREE_CODE (iv0->base) == INTEGER_CST)
        {
-         if (mmax)
-           assumption = fold_build2 (EQ_EXPR, boolean_type_node,
-                                     iv0->base, mmax);
-         else
-           assumption = boolean_false_node;
-         if (nonzero_p (assumption))
-           goto zero_iter;
-         iv0->base = fold_build2 (PLUS_EXPR, type, iv0->base,
-                                  build_int_cst_type (type, 1));
+         d = fold_build2 (MINUS_EXPR, niter_type,
+                          fold_convert (niter_type, TYPE_MAX_VALUE (type)),
+                          fold_convert (niter_type, iv0->base));
+         diff = fold_build2 (FLOOR_MOD_EXPR, niter_type, d, step);
        }
       else
+       diff = fold_build2 (MINUS_EXPR, niter_type, step,
+                           build_int_cst_type (niter_type, 1));
+      bound = fold_build2 (MINUS_EXPR, type,
+                          TYPE_MAX_VALUE (type), fold_convert (type, diff));
+      assumption = fold_build2 (LE_EXPR, boolean_type_node,
+                               iv1->base, bound);
+    }
+  else
+    {
+      /* for (i = iv1->base; i > iv0->base; i += iv1->step) */
+      if (iv1->no_overflow)
+       return true;
+
+      if (TREE_CODE (iv1->base) == INTEGER_CST)
        {
-         if (mmin)
-           assumption = fold_build2 (EQ_EXPR, boolean_type_node,
-                                     iv1->base, mmin);
-         else
-           assumption = boolean_false_node;
-         if (nonzero_p (assumption))
-           goto zero_iter;
-         iv1->base = fold_build2 (MINUS_EXPR, type, iv1->base,
-                                  build_int_cst_type (type, 1));
+         d = fold_build2 (MINUS_EXPR, niter_type,
+                          fold_convert (niter_type, iv1->base),
+                          fold_convert (niter_type, TYPE_MIN_VALUE (type)));
+         diff = fold_build2 (FLOOR_MOD_EXPR, niter_type, d, step);
        }
-      noloop_assumptions = assumption;
-      code = LE_EXPR;
-
-      /* It will be useful to be able to tell the difference once more in
-        <= -> != reduction.  */
-      was_sharp = true;
+      else
+       diff = fold_build2 (MINUS_EXPR, niter_type, step,
+                           build_int_cst_type (niter_type, 1));
+      bound = fold_build2 (PLUS_EXPR, type,
+                          TYPE_MIN_VALUE (type), fold_convert (type, diff));
+      assumption = fold_build2 (GE_EXPR, boolean_type_node,
+                               iv0->base, bound);
     }
 
-  /* Take care of trivially infinite loops.  */
-  if (code != NE_EXPR)
-    {
-      if (zero_p (iv0->step)
-         && mmin
-         && operand_equal_p (iv0->base, mmin, 0))
-       return;
-      if (zero_p (iv1->step)
-         && mmax
-         && operand_equal_p (iv1->base, mmax, 0))
-       return;
-    }
+  if (zero_p (assumption))
+    return false;
+  if (!nonzero_p (assumption))
+    niter->assumptions = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
+                                     niter->assumptions, assumption);
+    
+  iv0->no_overflow = true;
+  iv1->no_overflow = true;
+  return true;
+}
 
-  /* If we can we want to take care of NE conditions instead of size
-     comparisons, as they are much more friendly (most importantly
-     this takes care of special handling of loops with step 1).  We can
-     do it if we first check that upper bound is greater or equal to
-     lower bound, their difference is constant c modulo step and that
-     there is not an overflow.  */
-  if (code != NE_EXPR)
+/* Add an assumption to NITER that a loop whose ending condition
+   is IV0 < IV1 rolls.  TYPE is the type of the control iv.  */
+
+static void
+assert_loop_rolls_lt (tree type, affine_iv *iv0, affine_iv *iv1,
+                     struct tree_niter_desc *niter)
+{
+  tree assumption = boolean_true_node, bound, diff;
+  tree mbz, mbzl, mbzr;
+
+  if (nonzero_p (iv0->step))
     {
-      if (zero_p (iv0->step))
-       step = fold_unary_to_constant (NEGATE_EXPR, type, iv1->step);
-      else
-       step = iv0->step;
-      delta = fold_build2 (MINUS_EXPR, type, iv1->base, iv0->base);
-      delta = fold_build2 (FLOOR_MOD_EXPR, type, delta, step);
-      may_xform = boolean_false_node;
+      diff = fold_build2 (MINUS_EXPR, type,
+                         iv0->step, build_int_cst_type (type, 1));
 
-      if (TREE_CODE (delta) == INTEGER_CST)
+      /* We need to know that iv0->base >= MIN + iv0->step - 1.  Since
+        0 address never belongs to any object, we can assume this for
+        pointers.  */
+      if (!POINTER_TYPE_P (type))
        {
-         tmp = fold_binary_to_constant (MINUS_EXPR, type, step,
-                                        build_int_cst_type (type, 1));
-         if (was_sharp
-             && operand_equal_p (delta, tmp, 0))
-           {
-             /* A special case.  We have transformed condition of type
-                for (i = 0; i < 4; i += 4)
-                into
-                for (i = 0; i <= 3; i += 4)
-                obviously if the test for overflow during that transformation
-                passed, we cannot overflow here.  Most importantly any
-                loop with sharp end condition and step 1 falls into this
-                category, so handling this case specially is definitely
-                worth the troubles.  */
-             may_xform = boolean_true_node;
-           }
-         else if (zero_p (iv0->step))
-           {
-             if (!mmin || iv1->no_overflow)
-               may_xform = boolean_true_node;
-             else
-               {
-                 bound = fold_binary_to_constant (PLUS_EXPR, type,
-                                                  mmin, step);
-                 bound = fold_binary_to_constant (MINUS_EXPR, type,
-                                                  bound, delta);
-                 may_xform = fold_build2 (LE_EXPR, boolean_type_node,
-                                          bound, iv0->base);
-               }
-           }
-         else
-           {
-             if (!mmax || iv0->no_overflow)
-               may_xform = boolean_true_node;
-             else
-               {
-                 bound = fold_binary_to_constant (MINUS_EXPR, type,
-                                                  mmax, step);
-                 bound = fold_binary_to_constant (PLUS_EXPR, type,
-                                                  bound, delta);
-                 may_xform = fold_build2 (LE_EXPR, boolean_type_node,
-                                          iv1->base, bound);
-               }
-           }
+         bound = fold_build2 (PLUS_EXPR, type,
+                              TYPE_MIN_VALUE (type), diff);
+         assumption = fold_build2 (GE_EXPR, boolean_type_node,
+                                   iv0->base, bound);
        }
 
-      if (!zero_p (may_xform))
-       {
-         /* We perform the transformation always provided that it is not
-            completely senseless.  This is OK, as we would need this assumption
-            to determine the number of iterations anyway.  */
-         if (!nonzero_p (may_xform))
-           assumptions = may_xform;
-
-         if (zero_p (iv0->step))
-           {
-             iv0->base = fold_build2 (PLUS_EXPR, type, iv0->base, delta);
-             iv0->base = fold_build2 (MINUS_EXPR, type, iv0->base, step);
-           }
-         else
-           {
-             iv1->base = fold_build2 (MINUS_EXPR, type, iv1->base, delta);
-             iv1->base = fold_build2 (PLUS_EXPR, type, iv1->base, step);
-           }
-
-         assumption = fold_build2 (GT_EXPR, boolean_type_node,
-                                   iv0->base, iv1->base);
-         noloop_assumptions = fold_build2 (TRUTH_OR_EXPR, boolean_type_node,
-                                           noloop_assumptions, assumption);
-         code = NE_EXPR;
-       }
+      /* And then we can compute iv0->base - diff, and compare it with
+        iv1->base.  */      
+      mbzl = fold_build2 (MINUS_EXPR, type, iv0->base, diff);
+      mbzr = iv1->base;
     }
-
-  /* Count the number of iterations.  */
-  niter_type = unsigned_type_for (type);
-  signed_niter_type = signed_type_for (type);
-
-  if (code == NE_EXPR)
+  else
     {
-      /* Everything we do here is just arithmetics modulo size of mode.  This
-        makes us able to do more involved computations of number of iterations
-        than in other cases.  First transform the condition into shape
-        s * i <> c, with s positive.  */
-      iv1->base = fold_build2 (MINUS_EXPR, type, iv1->base, iv0->base);
-      iv0->base = NULL_TREE;
-      if (!zero_p (iv1->step))
-       iv0->step = fold_unary_to_constant (NEGATE_EXPR, type, iv1->step);
-      iv1->step = NULL_TREE;
-      if (tree_int_cst_sign_bit (fold_convert (signed_niter_type, iv0->step)))
+      diff = fold_build2 (PLUS_EXPR, type,
+                         iv1->step, build_int_cst_type (type, 1));
+
+      if (!POINTER_TYPE_P (type))
        {
-         iv0->step = fold_unary_to_constant (NEGATE_EXPR, type, iv0->step);
-         iv1->base = fold_build1 (NEGATE_EXPR, type, iv1->base);
+         bound = fold_build2 (PLUS_EXPR, type,
+                              TYPE_MAX_VALUE (type), diff);
+         assumption = fold_build2 (LE_EXPR, boolean_type_node,
+                                   iv1->base, bound);
        }
 
-      iv1->base = fold_convert (niter_type, iv1->base);
-      iv0->step = fold_convert (niter_type, iv0->step);
+      mbzl = iv0->base;
+      mbzr = fold_build2 (MINUS_EXPR, type, iv1->base, diff);
+    }
+
+  mbz = fold_build2 (GT_EXPR, boolean_type_node, mbzl, mbzr);
 
-      /* Let nsd (step, size of mode) = d.  If d does not divide c, the loop
-        is infinite.  Otherwise, the number of iterations is
-        (inverse(s/d) * (c/d)) mod (size of mode/d).  */
-      bits = num_ending_zeros (iv0->step);
-      d = fold_binary_to_constant (LSHIFT_EXPR, niter_type,
-                                  build_int_cst_type (niter_type, 1), bits);
-      s = fold_binary_to_constant (RSHIFT_EXPR, niter_type, iv0->step, bits);
+  if (!nonzero_p (assumption))
+    niter->assumptions = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
+                                     niter->assumptions, assumption);
+  if (!zero_p (mbz))
+    niter->may_be_zero = fold_build2 (TRUTH_OR_EXPR, boolean_type_node,
+                                     niter->may_be_zero, mbz);
+}
 
-      bound = build_low_bits_mask (niter_type,
-                                  (TYPE_PRECISION (niter_type)
-                                   - tree_low_cst (bits, 1)));
+/* Determines number of iterations of loop whose ending condition
+   is IV0 < IV1.  TYPE is the type of the iv.  The number of
+   iterations is stored to NITER.  */
 
-      if (!never_infinite)
-       {
-         /* If we cannot assume that the loop is not infinite, record the
-            assumptions for divisibility of c.  */
-         assumption = fold_build2 (FLOOR_MOD_EXPR, niter_type, iv1->base, d);
-         assumption = fold_build2 (EQ_EXPR, boolean_type_node,
-                                   assumption,
-                                   build_int_cst (niter_type, 0));
-         assumptions = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
-                                    assumptions, assumption);
-       }
+static bool
+number_of_iterations_lt (tree type, affine_iv *iv0, affine_iv *iv1,
+                        struct tree_niter_desc *niter,
+                        bool never_infinite ATTRIBUTE_UNUSED)
+{
+  tree niter_type = unsigned_type_for (type);
+  tree delta, step, s;
+
+  delta = fold_build2 (MINUS_EXPR, niter_type,
+                      fold_convert (niter_type, iv1->base),
+                      fold_convert (niter_type, iv0->base));
+
+  /* First handle the special case that the step is +-1.  */
+  if ((iv0->step && integer_onep (iv0->step)
+       && zero_p (iv1->step))
+      || (iv1->step && integer_all_onesp (iv1->step)
+         && zero_p (iv0->step)))
+    {
+      /* for (i = iv0->base; i < iv1->base; i++)
+
+        or
 
-      tmp = fold_build2 (EXACT_DIV_EXPR, niter_type, iv1->base, d);
-      tmp = fold_build2 (MULT_EXPR, niter_type, tmp, inverse (s, bound));
-      niter->niter = fold_build2 (BIT_AND_EXPR, niter_type, tmp, bound);
+        for (i = iv1->base; i > iv0->base; i--).
+            
+        In both cases # of iterations is iv1->base - iv0->base, assuming that
+        iv1->base >= iv0->base.  */
+      niter->may_be_zero = fold_build2 (LT_EXPR, boolean_type_node,
+                                       iv1->base, iv0->base);
+      niter->niter = delta;
+      return true;
     }
+
+  if (nonzero_p (iv0->step))
+    step = fold_convert (niter_type, iv0->step);
   else
+    step = fold_convert (niter_type,
+                        fold_build1 (NEGATE_EXPR, type, iv1->step));
+
+  /* If we can determine the final value of the control iv exactly, we can
+     transform the condition to != comparison.  In particular, this will be
+     the case if DELTA is constant.  */
+  if (number_of_iterations_lt_to_ne (type, iv0, iv1, niter, &delta, step))
     {
-      if (zero_p (iv1->step))
-       /* Condition in shape a + s * i <= b
-          We must know that b + s does not overflow and a <= b + s and then we
-          can compute number of iterations as (b + s - a) / s.  (It might
-          seem that we in fact could be more clever about testing the b + s
-          overflow condition using some information about b - a mod s,
-          but it was already taken into account during LE -> NE transform).  */
-       {
-         if (mmax && !iv0->no_overflow)
-           {
-             bound = fold_binary_to_constant (MINUS_EXPR, type,
-                                              mmax, iv0->step);
-             assumption = fold_build2 (LE_EXPR, boolean_type_node,
-                                       iv1->base, bound);
-             assumptions = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
-                                        assumptions, assumption);
-           }
+      affine_iv zps;
 
-         step = iv0->step;
-         tmp = fold_build2 (PLUS_EXPR, type, iv1->base, iv0->step);
-         assumption = fold_build2 (GT_EXPR, boolean_type_node,
-                                   iv0->base, tmp);
-         delta = fold_build2 (PLUS_EXPR, type, iv1->base, step);
-         delta = fold_build2 (MINUS_EXPR, type, delta, iv0->base);
-         delta = fold_convert (niter_type, delta);
-       }
-      else
-       {
-         /* Condition in shape a <= b - s * i
-            We must know that a - s does not overflow and a - s <= b and then
-            we can again compute number of iterations as (b - (a - s)) / s.  */
-         if (mmin && !iv1->no_overflow)
-           {
-             bound = fold_binary_to_constant (MINUS_EXPR, type,
-                                              mmin, iv1->step);
-             assumption = fold_build2 (LE_EXPR, boolean_type_node,
-                                       bound, iv0->base);
-             assumptions = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
-                                        assumptions, assumption);
-           }
-         step = fold_build1 (NEGATE_EXPR, type, iv1->step);
-         tmp = fold_build2 (PLUS_EXPR, type, iv0->base, iv1->step);
-         assumption = fold_build2 (GT_EXPR, boolean_type_node, tmp, iv1->base);
-         delta = fold_build2 (MINUS_EXPR, type, iv0->base, step);
-         delta = fold_build2 (MINUS_EXPR, type, iv1->base, delta);
-         delta = fold_convert (niter_type, delta);
-       }
-      noloop_assumptions = fold_build2 (TRUTH_OR_EXPR, boolean_type_node,
-                                       noloop_assumptions, assumption);
-      delta = fold_build2 (FLOOR_DIV_EXPR, niter_type, delta,
-                          fold_convert (niter_type, step));
-      niter->niter = delta;
+      zps.base = build_int_cst_type (niter_type, 0);
+      zps.step = step;
+      /* number_of_iterations_lt_to_ne will add assumptions that ensure that
+        zps does not overflow.  */
+      zps.no_overflow = true;
+
+      return number_of_iterations_ne (type, &zps, delta, niter, true);
     }
 
-  niter->assumptions = assumptions;
-  niter->may_be_zero = noloop_assumptions;
-  return;
+  /* Make sure that the control iv does not overflow.  */
+  if (!assert_no_overflow_lt (type, iv0, iv1, niter, step))
+    return false;
 
-zero_iter:
-  niter->assumptions = boolean_true_node;
-  niter->may_be_zero = boolean_true_node;
-  niter->niter = build_int_cst_type (type, 0);
-  return;
+  /* We determine the number of iterations as (delta + step - 1) / step.  For
+     this to work, we must know that iv1->base >= iv0->base - step + 1,
+     otherwise the loop does not roll.  */
+  assert_loop_rolls_lt (type, iv0, iv1, niter);
+
+  s = fold_build2 (MINUS_EXPR, niter_type,
+                  step, build_int_cst_type (niter_type, 1));
+  delta = fold_build2 (PLUS_EXPR, niter_type, delta, s);
+  niter->niter = fold_build2 (FLOOR_DIV_EXPR, niter_type, delta, step);
+  return true;
 }
 
+/* Determines number of iterations of loop whose ending condition
+   is IV0 <= IV1.  TYPE is the type of the iv.  The number of
+   iterations is stored to NITER.  NEVER_INFINITE is true if
+   we know that the loop cannot be infinite (we derived this
+   earlier, and possibly set NITER->assumptions to make sure this
+   is the case.  */
+
+static bool
+number_of_iterations_le (tree type, affine_iv *iv0, affine_iv *iv1,
+                        struct tree_niter_desc *niter, bool never_infinite)
+{
+  tree assumption;
 
-/* Similar to number_of_iterations_cond, but only handles the special
-   case of loops with step 1 or -1.  The meaning of the arguments
-   is the same as in number_of_iterations_cond.  The function
-   returns true if the special case was recognized, false otherwise.  */
+  /* Say that IV0 is the control variable.  Then IV0 <= IV1 iff
+     IV0 < IV1 + 1, assuming that IV1 is not equal to the greatest
+     value of the type.  This we must know anyway, since if it is
+     equal to this value, the loop rolls forever.  */
+
+  if (!never_infinite)
+    {
+      if (nonzero_p (iv0->step))
+       assumption = fold_build2 (NE_EXPR, boolean_type_node,
+                                 iv1->base, TYPE_MAX_VALUE (type));
+      else
+       assumption = fold_build2 (NE_EXPR, boolean_type_node,
+                                 iv0->base, TYPE_MIN_VALUE (type));
+
+      if (zero_p (assumption))
+       return false;
+      if (!nonzero_p (assumption))
+       niter->assumptions = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
+                                         niter->assumptions, assumption);
+    }
+
+  if (nonzero_p (iv0->step))
+    iv1->base = fold_build2 (PLUS_EXPR, type,
+                            iv1->base, build_int_cst_type (type, 1));
+  else
+    iv0->base = fold_build2 (MINUS_EXPR, type,
+                            iv0->base, build_int_cst_type (type, 1));
+  return number_of_iterations_lt (type, iv0, iv1, niter, never_infinite);
+}
+
+/* Determine the number of iterations according to condition (for staying
+   inside loop) which compares two induction variables using comparison
+   operator CODE.  The induction variable on left side of the comparison
+   is IV0, the right-hand side is IV1.  Both induction variables must have
+   type TYPE, which must be an integer or pointer type.  The steps of the
+   ivs must be constants (or NULL_TREE, which is interpreted as constant zero).
+   
+   The results (number of iterations and assumptions as described in
+   comments at struct tree_niter_desc in tree-flow.h) are stored to NITER.
+   Returns false if it fails to determine number of iterations, true if it
+   was determined (possibly with some assumptions).  */
 
 static bool
-number_of_iterations_special (tree type, affine_iv *iv0, enum tree_code code,
-                             affine_iv *iv1, struct tree_niter_desc *niter)
+number_of_iterations_cond (tree type, affine_iv *iv0, enum tree_code code,
+                          affine_iv *iv1, struct tree_niter_desc *niter)
 {
-  tree niter_type = unsigned_type_for (type), mmax, mmin;
+  bool never_infinite;
+
+  /* The meaning of these assumptions is this:
+     if !assumptions
+       then the rest of information does not have to be valid
+     if may_be_zero then the loop does not roll, even if
+       niter != 0.  */
+  niter->assumptions = boolean_true_node;
+  niter->may_be_zero = boolean_false_node;
+  niter->niter = NULL_TREE;
+  niter->additional_info = boolean_true_node;
 
-  /* Make < comparison from > ones.  */
-  if (code == GE_EXPR
-      || code == GT_EXPR)
+  /* Make < comparison from > ones, and for NE_EXPR comparisons, ensure that
+     the control variable is on lhs.  */
+  if (code == GE_EXPR || code == GT_EXPR
+      || (code == NE_EXPR && zero_p (iv0->step)))
     {
       SWAP (iv0, iv1);
       code = swap_tree_comparison (code);
     }
 
-  switch (code)
+  if (POINTER_TYPE_P (type))
     {
-    case NE_EXPR:
-      if (zero_p (iv0->step))
-       {
-         if (zero_p (iv1->step))
-           return false;
-         SWAP (iv0, iv1);
-       }
-      else if (!zero_p (iv1->step))
-       return false;
+      /* Comparison of pointers is undefined unless both iv0 and iv1 point
+        to the same object.  If they do, the control variable cannot wrap
+        (as wrap around the bounds of memory will never return a pointer
+        that would be guaranteed to point to the same object, even if we
+        avoid undefined behavior by casting to size_t and back).  */
+      iv0->no_overflow = true;
+      iv1->no_overflow = true;
+    }
 
-      if (integer_onep (iv0->step))
-       {
-         /* for (i = iv0->base; i != iv1->base; i++)  */
-         niter->assumptions = boolean_true_node;
-         niter->may_be_zero = boolean_false_node;
-         niter->niter = fold_build2 (MINUS_EXPR, type, iv1->base, iv0->base);
-         niter->additional_info = boolean_true_node;
-       }
-      else if (integer_all_onesp (iv0->step))
-       {
-         /* for (i = iv0->base; i != iv1->base; i--)  */
-         niter->assumptions = boolean_true_node;
-         niter->may_be_zero = boolean_false_node;
-         niter->niter = fold_build2 (MINUS_EXPR, type, iv0->base, iv1->base);
-       }
-      else
-       return false;
+  /* If the control induction variable does not overflow, the loop obviously
+     cannot be infinite.  */
+  if (!zero_p (iv0->step) && iv0->no_overflow)
+    never_infinite = true;
+  else if (!zero_p (iv1->step) && iv1->no_overflow)
+    never_infinite = true;
+  else
+    never_infinite = false;
 
-      break;
+  /* We can handle the case when neither of the sides of the comparison is
+     invariant, provided that the test is NE_EXPR.  This rarely occurs in
+     practice, but it is simple enough to manage.  */
+  if (!zero_p (iv0->step) && !zero_p (iv1->step))
+    {
+      if (code != NE_EXPR)
+       return false;
 
-    case LT_EXPR:
-      if ((iv0->step && integer_onep (iv0->step)
-          && zero_p (iv1->step))
-         || (iv1->step && integer_all_onesp (iv1->step)
-             && zero_p (iv0->step)))
-       {
-         /* for (i = iv0->base; i < iv1->base; i++)
-            
-            or
+      iv0->step = fold_binary_to_constant (MINUS_EXPR, type,
+                                          iv0->step, iv1->step);
+      iv0->no_overflow = false;
+      iv1->step = NULL_TREE;
+      iv1->no_overflow = true;
+    }
 
-            for (i = iv1->base; i > iv0->base; i--).
-            
-            In both cases # of iterations is iv1->base - iv0->base.  */
+  /* If the result of the comparison is a constant,  the loop is weird.  More
+     precise handling would be possible, but the situation is not common enough
+     to waste time on it.  */
+  if (zero_p (iv0->step) && zero_p (iv1->step))
+    return false;
 
-         niter->assumptions = boolean_true_node;
-         niter->may_be_zero = fold_build2 (GT_EXPR, boolean_type_node,
-                                           iv0->base, iv1->base);
-         niter->niter = fold_build2 (MINUS_EXPR, type, iv1->base, iv0->base);
-       }
-      else
+  /* Ignore loops of while (i-- < 10) type.  */
+  if (code != NE_EXPR)
+    {
+      if (iv0->step && tree_int_cst_sign_bit (iv0->step))
        return false;
-      break;
 
-    case LE_EXPR:
-      if (POINTER_TYPE_P (type))
-       {
-         /* We assume pointer arithmetic never overflows.  */
-         mmin = mmax = NULL_TREE;
-       }
-      else
-       {
-         mmin = TYPE_MIN_VALUE (type);
-         mmax = TYPE_MAX_VALUE (type);
-       }
-
-      if (iv0->step && integer_onep (iv0->step)
-         && zero_p (iv1->step))
-       {
-         /* for (i = iv0->base; i <= iv1->base; i++)  */
-         if (mmax && !iv0->no_overflow)
-           niter->assumptions = fold_build2 (NE_EXPR, boolean_type_node,
-                                             iv1->base, mmax);
-         else
-           niter->assumptions = boolean_true_node;
-         iv1->base = fold_build2 (PLUS_EXPR, type, iv1->base,
-                                  build_int_cst_type (type, 1));
-       }
-      else if (iv1->step && integer_all_onesp (iv1->step)
-              && zero_p (iv0->step))
-       {
-         /* for (i = iv1->base; i >= iv0->base; i--)  */
-         if (mmin && !iv1->no_overflow)
-           niter->assumptions = fold_build2 (NE_EXPR, boolean_type_node,
-                                             iv0->base, mmin);
-         else
-           niter->assumptions = boolean_true_node;
-         iv0->base = fold_build2 (MINUS_EXPR, type, iv0->base,
-                                  build_int_cst_type (type, 1));
-       }
-      else
+      if (!zero_p (iv1->step) && !tree_int_cst_sign_bit (iv1->step))
        return false;
+    }
 
-      niter->may_be_zero = fold_build2 (GT_EXPR, boolean_type_node,
-                                       iv0->base, iv1->base);
-      niter->niter = fold_build2 (MINUS_EXPR, type, iv1->base, iv0->base);
-      break;
+  /* If the loop exits immediatelly, there is nothing to do.  */
+  if (zero_p (fold_build2 (code, boolean_type_node, iv0->base, iv1->base)))
+    {
+      niter->niter = build_int_cst_type (unsigned_type_for (type), 0);
+      return true;
+    }
 
+  /* OK, now we know we have a senseful loop.  Handle several cases, depending
+     on what comparison operator is used.  */
+  switch (code)
+    {
+    case NE_EXPR:
+      gcc_assert (zero_p (iv1->step));
+      return number_of_iterations_ne (type, iv0, iv1->base, niter, never_infinite);
+    case LT_EXPR:
+      return number_of_iterations_lt (type, iv0, iv1, niter, never_infinite);
+    case LE_EXPR:
+      return number_of_iterations_le (type, iv0, iv1, niter, never_infinite);
     default:
       gcc_unreachable ();
     }
-
-  niter->niter = fold_convert (niter_type, niter->niter);
-  niter->additional_info = boolean_true_node;
-  return true;
 }
 
 /* Substitute NEW for OLD in EXPR and fold the result.  */
@@ -987,18 +1001,10 @@ number_of_iterations_exit (struct loop *loop, edge exit,
   if (!simple_iv (loop, stmt, op1, &iv1, false))
     return false;
 
-  niter->niter = NULL_TREE;
-
-  /* Handle common special cases first, so that we do not need to use
-     generic (and slow) analysis very often.  */
-  if (!number_of_iterations_special (type, &iv0, code, &iv1, niter))
-    {
-
-      number_of_iterations_cond (type, &iv0, code, &iv1, niter);
-
-      if (!niter->niter)
-       return false;
-    }
+  iv0.base = expand_simple_operations (iv0.base);
+  iv1.base = expand_simple_operations (iv1.base);
+  if (!number_of_iterations_cond (type, &iv0, code, &iv1, niter))
+    return false;
 
   if (optimize >= 3)
     {
index 4bda846..0cca757 100644 (file)
@@ -6809,6 +6809,8 @@ tree_fold_gcd (tree a, tree b)
 tree
 unsigned_type_for (tree type)
 {
+  if (POINTER_TYPE_P (type))
+    return size_type_node;
   return lang_hooks.types.unsigned_type (type);
 }