re PR tree-optimization/84321 (ice in intersect_range_with_nonzero_bits, at tree...
authorRichard Sandiford <richard.sandiford@linaro.org>
Tue, 13 Feb 2018 15:48:38 +0000 (15:48 +0000)
committerJeff Law <law@gcc.gnu.org>
Tue, 13 Feb 2018 15:48:38 +0000 (08:48 -0700)
2018-02-12  Richard Sandiford  <richard.sandiford@linaro.org>

gcc/
PR tree-optimization/84321
* tree-vrp.c (intersect_range_with_nonzero_bits): Fix VR_ANTI_RANGE
handling.  Also check whether the anti-range contains any values
that satisfy the mask; switch to a VR_RANGE if not.

gcc/testsuite/
PR tree-optimization/84321
* gcc.dg/pr84321.c: New test.

From-SVN: r257629

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/pr84321.c [new file with mode: 0644]
gcc/tree-vrp.c

index 6c1e5e38d63751a580098e483f6dac0e49bf2bba..c582ae17c1cc84a45591bcb8d0f679a11e63fb52 100644 (file)
@@ -1,3 +1,10 @@
+2018-02-13  Richard Sandiford  <richard.sandiford@linaro.org>
+
+       PR tree-optimization/84321
+       * tree-vrp.c (intersect_range_with_nonzero_bits): Fix VR_ANTI_RANGE
+       handling.  Also check whether the anti-range contains any values
+       that satisfy the mask; switch to a VR_RANGE if not.
+
 2018-02-13  Paolo Bonzini <bonzini@gnu.org>
 
        PR sanitizer/84340
index 0a1a4f924a2f682189658978dbe6263955b0ed42..b11f10a6179e3c4facbcc8e35c690adc5c14a2d2 100644 (file)
@@ -1,3 +1,8 @@
+2018-02-12  Richard Sandiford  <richard.sandiford@linaro.org>
+
+       PR tree-optimization/84321
+       * gcc.dg/pr84321.c: New test.
+
 2018-02-13  Vladimir Makarov  <vmakarov@redhat.com>
 
        PR target/84359
diff --git a/gcc/testsuite/gcc.dg/pr84321.c b/gcc/testsuite/gcc.dg/pr84321.c
new file mode 100644 (file)
index 0000000..8f8186b
--- /dev/null
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -fwrapv" } */
+
+int c;
+
+void
+foo (int *a, int b)
+{
+  int e;
+  if (b == 1)
+    return;
+  for (e = 0; e < (b & ~7); e += 8)
+    ;
+  for (++e; e < b;)
+    c = a[e];
+}
index cba58e0279108293a2e8b923941512ded35bdac3..625e65b1184c86963f36f0c66a9e56311c99e101 100644 (file)
@@ -184,37 +184,61 @@ intersect_range_with_nonzero_bits (enum value_range_type vr_type,
                                   const wide_int &nonzero_bits,
                                   signop sgn)
 {
-  if (vr_type == VR_RANGE)
-    {
-      *max = wi::round_down_for_mask (*max, nonzero_bits);
-
-      /* Check that the range contains at least one valid value.  */
-      if (wi::gt_p (*min, *max, sgn))
-       return VR_UNDEFINED;
-
-      *min = wi::round_up_for_mask (*min, nonzero_bits);
-      gcc_checking_assert (wi::le_p (*min, *max, sgn));
-    }
   if (vr_type == VR_ANTI_RANGE)
     {
-      *max = wi::round_up_for_mask (*max, nonzero_bits);
+      /* The VR_ANTI_RANGE is equivalent to the union of the ranges
+        A: [-INF, *MIN) and B: (*MAX, +INF].  First use NONZERO_BITS
+        to create an inclusive upper bound for A and an inclusive lower
+        bound for B.  */
+      wide_int a_max = wi::round_down_for_mask (*min - 1, nonzero_bits);
+      wide_int b_min = wi::round_up_for_mask (*max + 1, nonzero_bits);
+
+      /* If the calculation of A_MAX wrapped, A is effectively empty
+        and A_MAX is the highest value that satisfies NONZERO_BITS.
+        Likewise if the calculation of B_MIN wrapped, B is effectively
+        empty and B_MIN is the lowest value that satisfies NONZERO_BITS.  */
+      bool a_empty = wi::ge_p (a_max, *min, sgn);
+      bool b_empty = wi::le_p (b_min, *max, sgn);
+
+      /* If both A and B are empty, there are no valid values.  */
+      if (a_empty && b_empty)
+       return VR_UNDEFINED;
 
-      /* If the calculation wrapped, we now have a VR_RANGE whose
-        lower bound is *MAX and whose upper bound is *MIN.  */
-      if (wi::gt_p (*min, *max, sgn))
+      /* If exactly one of A or B is empty, return a VR_RANGE for the
+        other one.  */
+      if (a_empty || b_empty)
        {
-         std::swap (*min, *max);
-         *max = wi::round_down_for_mask (*max, nonzero_bits);
+         *min = b_min;
+         *max = a_max;
          gcc_checking_assert (wi::le_p (*min, *max, sgn));
          return VR_RANGE;
        }
 
-      *min = wi::round_down_for_mask (*min, nonzero_bits);
+      /* Update the VR_ANTI_RANGE bounds.  */
+      *min = a_max + 1;
+      *max = b_min - 1;
       gcc_checking_assert (wi::le_p (*min, *max, sgn));
 
-      /* Check whether we now have an empty set of values.  */
-      if (*min - 1 == *max)
+      /* Now check whether the excluded range includes any values that
+        satisfy NONZERO_BITS.  If not, switch to a full VR_RANGE.  */
+      if (wi::round_up_for_mask (*min, nonzero_bits) == b_min)
+       {
+         unsigned int precision = min->get_precision ();
+         *min = wi::min_value (precision, sgn);
+         *max = wi::max_value (precision, sgn);
+         vr_type = VR_RANGE;
+       }
+    }
+  if (vr_type == VR_RANGE)
+    {
+      *max = wi::round_down_for_mask (*max, nonzero_bits);
+
+      /* Check that the range contains at least one valid value.  */
+      if (wi::gt_p (*min, *max, sgn))
        return VR_UNDEFINED;
+
+      *min = wi::round_up_for_mask (*min, nonzero_bits);
+      gcc_checking_assert (wi::le_p (*min, *max, sgn));
     }
   return vr_type;
 }