This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Assuage ICE in VRP with [1, X] + UINT_MAX (PR tree-optimization/71031)


Since Bin's changes to the niter analysis in r231097, we find ourselves in
a situation where extract_range_from_binary_expr is given [1, od_5] + UINT_MAX
on type unsigned.  We combine the lower bounds, which is 1 + UINT_MAX = 0(OVF).
We then combine the upper bounds, because the max_op0 is not a constant, the
result of that is UINT_MAX.  That results in min overflow -- and an assert is
unhappy about that.  As suggested in the PR, a safe thing would be to change
the assert to dropping to varying.

Bootstrapped/regtested on x86_64-linux, ok for trunk and 6?

2016-05-19  Marek Polacek  <polacek@redhat.com>

	PR tree-optimization/71031
	* tree-vrp.c (extract_range_from_binary_expr_1): Drop to varying for
	min overflow or max underflow and remove an assert.

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

diff --git gcc/testsuite/gcc.dg/tree-ssa/vrp100.c gcc/testsuite/gcc.dg/tree-ssa/vrp100.c
index e69de29..c0fe4b5 100644
--- gcc/testsuite/gcc.dg/tree-ssa/vrp100.c
+++ gcc/testsuite/gcc.dg/tree-ssa/vrp100.c
@@ -0,0 +1,32 @@
+/* PR tree-optimization/71031 */
+/* { dg-do compile } */
+/* { dg-options "-Os" } */
+
+int zj;
+int **yr;
+
+void
+nn (void)
+{
+  unsigned int od = 4;
+
+  for (;;)
+    {
+      int lk;
+
+      for (lk = 0; lk < 2; ++lk)
+        {
+          static int cm;
+
+          zj = 0;
+          if (od == 0)
+            return;
+          ++od;
+          for (cm = 0; cm < 2; ++cm)
+            {
+              --od;
+              **yr = 0;
+            }
+        }
+    }
+}
diff --git gcc/tree-vrp.c gcc/tree-vrp.c
index 69e6248..791d738 100644
--- gcc/tree-vrp.c
+++ gcc/tree-vrp.c
@@ -2525,14 +2525,19 @@ extract_range_from_binary_expr_1 (value_range *vr,
 		  set_value_range_to_varying (vr);
 		  return;
 		}
+	      else if ((min_ovf == 1 && max_ovf == 0)
+		       || (min_ovf == 0 && max_ovf == -1))
+		{
+		  /* Min overflow or max underflow, drop to VR_VARYING.  */
+		  set_value_range_to_varying (vr);
+		  return;
+		}
 	      else
 		{
 		  /* Min underflow or max overflow.  The range kind
 		     changes to VR_ANTI_RANGE.  */
 		  bool covers = false;
 		  wide_int tem = tmin;
-		  gcc_assert ((min_ovf == -1 && max_ovf == 0)
-			      || (max_ovf == 1 && min_ovf == 0));
 		  type = VR_ANTI_RANGE;
 		  tmin = tmax + 1;
 		  if (wi::cmp (tmin, tmax, sgn) < 0)

	Marek


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]