tree-scalar-evolution.c (iv_can_overflow_p): New function.
authorJan Hubicka <jh@suse.cz>
Tue, 5 Jul 2016 16:17:12 +0000 (18:17 +0200)
committerJan Hubicka <hubicka@gcc.gnu.org>
Tue, 5 Jul 2016 16:17:12 +0000 (16:17 +0000)
* tree-scalar-evolution.c (iv_can_overflow_p): New function.
(simple_iv): Use it.

* gcc.dg/tree-ssa/scev-14.c: new testcase.

From-SVN: r238012

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/tree-ssa/scev-14.c [new file with mode: 0644]
gcc/tree-scalar-evolution.c

index bc4b4db894436bb0fb93b97c1ba66e0cfa35c80a..c7468666273061bf1ae4356b476e3558ee37ba73 100644 (file)
@@ -1,3 +1,8 @@
+2016-07-05  Jan Hubicka  <jh@suse.cz>
+
+       * tree-scalar-evolution.c (iv_can_overflow_p): New function.
+       (simple_iv): Use it.
+
 2016-07-05  Jan Hubicka  <jh@suse.cz>
 
        * tree-ssa-loop-niter.c (nowrap_type_p): Use ANY_INTEGRAL_TYPE_P.
index f86ee90ec5e0dc4c0134e45f1c1dad3312f2e7ce..d57f9c3eede534aa8ce40af5dcff4ee07b4eac2b 100644 (file)
@@ -1,3 +1,7 @@
+2016-07-05  Jan Hubicka  <jh@suse.cz>
+
+       * gcc.dg/tree-ssa/scev-14.c: new testcase.
+
 2016-07-05  David Malcolm  <dmalcolm@redhat.com>
 
        PR c++/62314
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/scev-14.c b/gcc/testsuite/gcc.dg/tree-ssa/scev-14.c
new file mode 100644 (file)
index 0000000..43af7d3
--- /dev/null
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-ivopts-details" } */
+int a[100];
+void t(unsigned int n)
+{
+  unsigned int i;
+  for (i=0; i<n; i++)
+     a[i]++;
+}
+/* { dg-final { scan-tree-dump "Overflowness wrto loop niter:  No-overflow"  "ivopts" } } */
+/* { dg-final { scan-tree-dump-not "Overflowness wrto loop niter:      Overflow" "ivopts" } } */
index 7c4c433672826da676d3abc54b62d0fff8a51e7f..e51f0aaedc199291273d4e2734ce167117a46bd6 100644 (file)
@@ -3309,6 +3309,91 @@ scev_reset (void)
     }
 }
 
+/* Return true if the IV calculation in TYPE can overflow based on the knowledge
+   of the upper bound on the number of iterations of LOOP, the BASE and STEP
+   of IV.
+
+   We do not use information whether TYPE can overflow so it is safe to
+   use this test even for derived IVs not computed every iteration or
+   hypotetical IVs to be inserted into code.  */
+
+static bool
+iv_can_overflow_p (struct loop *loop, tree type, tree base, tree step)
+{
+  widest_int nit;
+  wide_int base_min, base_max, step_min, step_max, type_min, type_max;
+  signop sgn = TYPE_SIGN (type);
+
+  if (integer_zerop (step))
+    return false;
+
+  if (TREE_CODE (base) == INTEGER_CST)
+    base_min = base_max = base;
+  else if (TREE_CODE (base) == SSA_NAME
+          && INTEGRAL_TYPE_P (TREE_TYPE (base))
+          && get_range_info (base, &base_min, &base_max) == VR_RANGE)
+    ;
+  else
+    return true;
+
+  if (TREE_CODE (step) == INTEGER_CST)
+    step_min = step_max = step;
+  else if (TREE_CODE (step) == SSA_NAME
+          && INTEGRAL_TYPE_P (TREE_TYPE (step))
+          && get_range_info (step, &step_min, &step_max) == VR_RANGE)
+    ;
+  else
+    return true;
+
+  if (!get_max_loop_iterations (loop, &nit))
+    return true;
+
+  type_min = wi::min_value (type);
+  type_max = wi::max_value (type);
+
+  /* Just sanity check that we don't see values out of the range of the type.
+     In this case the arithmetics bellow would overflow.  */
+  gcc_checking_assert (wi::ge_p (base_min, type_min, sgn)
+                      && wi::le_p (base_max, type_max, sgn));
+
+  /* Account the possible increment in the last ieration.  */
+  bool overflow = false;
+  nit = wi::add (nit, 1, SIGNED, &overflow);
+  if (overflow)
+    return true;
+
+  /* NIT is typeless and can exceed the precision of the type.  In this case
+     overflow is always possible, because we know STEP is non-zero.  */
+  if (wi::min_precision (nit, UNSIGNED) > TYPE_PRECISION (type))
+    return true;
+  wide_int nit2 = wide_int::from (nit, TYPE_PRECISION (type), UNSIGNED);
+
+  /* If step can be positive, check that nit*step <= type_max-base.
+     This can be done by unsigned arithmetic and we only need to watch overflow
+     in the multiplication. The right hand side can always be represented in
+     the type.  */
+  if (sgn == UNSIGNED || !wi::neg_p (step_max))
+    {
+      bool overflow = false;
+      if (wi::gtu_p (wi::mul (step_max, nit2, UNSIGNED, &overflow),
+                    type_max - base_max)
+         || overflow)
+       return true;
+    }
+  /* If step can be negative, check that nit*(-step) <= base_min-type_min.  */
+  if (sgn == SIGNED && wi::neg_p (step_min))
+    {
+      bool overflow = false, overflow2 = false;
+      if (wi::gtu_p (wi::mul (wi::neg (step_min, &overflow2),
+                    nit2, UNSIGNED, &overflow),
+                    base_min - type_min)
+         || overflow || overflow2)
+        return true;
+    }
+
+  return false;
+}
+
 /* Checks whether use of OP in USE_LOOP behaves as a simple affine iv with
    respect to WRTO_LOOP and returns its base and step in IV if possible
    (see analyze_scalar_evolution_in_loop for more details on USE_LOOP
@@ -3377,6 +3462,10 @@ simple_iv (struct loop *wrto_loop, struct loop *use_loop, tree op,
 
   iv->no_overflow = !folded_casts && nowrap_type_p (type);
 
+  if (!iv->no_overflow
+      && !iv_can_overflow_p (wrto_loop, type, iv->base, iv->step))
+    iv->no_overflow = true;
+
   /* Try to simplify iv base:
 
        (signed T) ((unsigned T)base + step) ;; TREE_TYPE (base) == signed T