Patchwork [committed] Fix VRP range meet (PR tree-optimization/59358)

login
register
mail settings
Submitter Jakub Jelinek
Date Dec. 2, 2013, 10:47 p.m.
Message ID <20131202224702.GR892@tucnak.redhat.com>
Download mbox | patch
Permalink /patch/296027/
State New
Headers show

Comments

Jakub Jelinek - Dec. 2, 2013, 10:47 p.m.
Hi!

The following testcase is miscompiled (to endless loop), because
union_ranges didn't count with the possibility that *vr0max and vr1max
are uncomparable (one of them is symbolic).

Fixed thusly, bootstrapped/regtested on x86_64-linux and i686-linux,
preapproved by richi on IRC, committed to trunk/4.8.

2013-12-02  Jakub Jelinek  <jakub@redhat.com>

	PR tree-optimization/59358
	* tree-vrp.c (union_ranges): To check for the partially
	overlapping ranges or adjacent ranges, also compare *vr0max
	with vr1max.

	* gcc.c-torture/execute/pr59358.c: New test.


	Jakub

Patch

--- gcc/tree-vrp.c.jj	2013-11-28 23:51:58.000000000 +0100
+++ gcc/tree-vrp.c	2013-12-02 13:24:10.750956769 +0100
@@ -7758,7 +7758,8 @@  union_ranges (enum value_range_type *vr0
     }
   else if ((operand_less_p (vr1min, *vr0max) == 1
 	    || operand_equal_p (vr1min, *vr0max, 0))
-	   && operand_less_p (*vr0min, vr1min) == 1)
+	   && operand_less_p (*vr0min, vr1min) == 1
+	   && operand_less_p (*vr0max, vr1max) == 1)
     {
       /* [  (  ]  ) or [   ](   ) */
       if (*vr0type == VR_RANGE
@@ -7792,7 +7793,8 @@  union_ranges (enum value_range_type *vr0
     }
   else if ((operand_less_p (*vr0min, vr1max) == 1
 	    || operand_equal_p (*vr0min, vr1max, 0))
-	   && operand_less_p (vr1min, *vr0min) == 1)
+	   && operand_less_p (vr1min, *vr0min) == 1
+	   && operand_less_p (vr1max, *vr0max) == 1)
     {
       /* (  [  )  ] or (   )[   ] */
       if (*vr0type == VR_RANGE
--- gcc/testsuite/gcc.c-torture/execute/pr59358.c.jj	2013-12-02 13:26:33.984198815 +0100
+++ gcc/testsuite/gcc.c-torture/execute/pr59358.c	2013-12-02 13:26:17.000000000 +0100
@@ -0,0 +1,44 @@ 
+/* PR tree-optimization/59358 */
+
+__attribute__((noinline, noclone)) int
+foo (int *x, int y)
+{
+  int z = *x;
+  if (y > z && y <= 16)
+    while (y > z)
+      z *= 2;
+  return z;
+}
+
+int
+main ()
+{
+  int i;
+  for (i = 1; i < 17; i++)
+    {
+      int j = foo (&i, 16);
+      int k;
+      if (i >= 8 && i <= 15)
+	k = 16 + (i - 8) * 2;
+      else if (i >= 4 && i <= 7)
+	k = 16 + (i - 4) * 4;
+      else if (i == 3)
+	k = 24;
+      else
+	k = 16;
+      if (j != k)
+	__builtin_abort ();
+      j = foo (&i, 7);
+      if (i >= 7)
+	k = i;
+      else if (i >= 4)
+	k = 8 + (i - 4) * 2;
+      else if (i == 3)
+	k = 12;
+      else
+	k = 8;
+      if (j != k)
+	__builtin_abort ();
+    }
+  return 0;
+}