VRP: x+1 and -x cannot be INT_MIN
authorMarc Glisse <marc.glisse@inria.fr>
Mon, 20 Nov 2017 13:26:39 +0000 (14:26 +0100)
committerMarc Glisse <glisse@gcc.gnu.org>
Mon, 20 Nov 2017 13:26:39 +0000 (13:26 +0000)
2017-11-20  Marc Glisse  <marc.glisse@inria.fr>

gcc/
* vr-values.c (extract_range_from_binary_expr): Use a full range
for VR_VARYING.

gcc/testsuite/
PR testsuite/82951
* gcc.c-torture/execute/20040409-1.c: Move invalid tests...
* gcc.c-torture/execute/20040409-1w.c: ... here with -fwrapv.
* gcc.c-torture/execute/20040409-2.c: Move invalid tests...
* gcc.c-torture/execute/20040409-2w.c: ... here with -fwrapv.
* gcc.c-torture/execute/20040409-3.c: Move invalid tests...
* gcc.c-torture/execute/20040409-3w.c: ... here with -fwrapv.
* gcc.dg/tree-ssa/cmpmul-1.c: Tweak condition.
* gcc.dg/tree-ssa/vrp118.c: New file.

From-SVN: r254954

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.c-torture/execute/20040409-1.c
gcc/testsuite/gcc.c-torture/execute/20040409-1w.c [new file with mode: 0644]
gcc/testsuite/gcc.c-torture/execute/20040409-2.c
gcc/testsuite/gcc.c-torture/execute/20040409-2w.c [new file with mode: 0644]
gcc/testsuite/gcc.c-torture/execute/20040409-3.c
gcc/testsuite/gcc.c-torture/execute/20040409-3w.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tree-ssa/cmpmul-1.c
gcc/testsuite/gcc.dg/tree-ssa/vrp118.c [new file with mode: 0644]
gcc/vr-values.c

index 4df4d801854b70c54ead21a33eb1861fa18c14e4..11e515ef84df907cd37eaf2dfaf580a9979a7e83 100644 (file)
@@ -1,3 +1,8 @@
+2017-11-20  Marc Glisse  <marc.glisse@inria.fr>
+
+       * vr-values.c (extract_range_from_binary_expr): Use a full range
+       for VR_VARYING.
+
 2017-11-20  Thomas Preud'homme  <thomas.preudhomme@arm.com>
 
        * config/arm/arm.md (R4_REGNUM): Define constant.
index 70dc99260094249ec51ddad7e2c2eed221a13171..35fd8dfe0a9b4d4be03300aa91d4aa71ffefd1d6 100644 (file)
@@ -1,3 +1,15 @@
+2017-11-20  Marc Glisse  <marc.glisse@inria.fr>
+
+       PR testsuite/82951
+       * gcc.c-torture/execute/20040409-1.c: Move invalid tests...
+       * gcc.c-torture/execute/20040409-1w.c: ... here with -fwrapv.
+       * gcc.c-torture/execute/20040409-2.c: Move invalid tests...
+       * gcc.c-torture/execute/20040409-2w.c: ... here with -fwrapv.
+       * gcc.c-torture/execute/20040409-3.c: Move invalid tests...
+       * gcc.c-torture/execute/20040409-3w.c: ... here with -fwrapv.
+       * gcc.dg/tree-ssa/cmpmul-1.c: Tweak condition.
+       * gcc.dg/tree-ssa/vrp118.c: New file.
+
 2017-11-20  Rainer Orth  <ro@CeBiTec.Uni-Bielefeld.DE>
 
        * g++.dg/pr82836.C: Require int128, __float128 support.
index 1e81edb365f24e8bbb80150e85ef7d6e3c74a9e1..d9649ab5a19f6713a24691ceb01fefca3d66ae2f 100644 (file)
@@ -12,21 +12,11 @@ unsigned int test1u(unsigned int x)
   return x ^ (unsigned int)INT_MIN;
 }
 
-int test2(int x)
-{
-  return x + INT_MIN;
-}
-
 unsigned int test2u(unsigned int x)
 {
   return x + (unsigned int)INT_MIN;
 }
 
-int test3(int x)
-{
-  return x - INT_MIN;
-}
-
 unsigned int test3u(unsigned int x)
 {
   return x - (unsigned int)INT_MIN;
@@ -44,24 +34,12 @@ unsigned int test4u(unsigned int x)
   return x ^ y;
 }
 
-int test5(int x)
-{
-  int y = INT_MIN;
-  return x + y;
-}
-
 unsigned int test5u(unsigned int x)
 {
   unsigned int y = (unsigned int)INT_MIN;
   return x + y;
 }
 
-int test6(int x)
-{
-  int y = INT_MIN;
-  return x - y;
-}
-
 unsigned int test6u(unsigned int x)
 {
   unsigned int y = (unsigned int)INT_MIN;
@@ -74,16 +52,8 @@ void test(int a, int b)
 {
   if (test1(a) != b)
     abort();
-  if (test2(a) != b)
-    abort();
-  if (test3(a) != b)
-    abort();
   if (test4(a) != b)
     abort();
-  if (test5(a) != b)
-    abort();
-  if (test6(a) != b)
-    abort();
 }
 
 void testu(unsigned int a, unsigned int b)
diff --git a/gcc/testsuite/gcc.c-torture/execute/20040409-1w.c b/gcc/testsuite/gcc.c-torture/execute/20040409-1w.c
new file mode 100644 (file)
index 0000000..bd0157d
--- /dev/null
@@ -0,0 +1,65 @@
+/* { dg-additional-options "-fwrapv" } */
+
+#include <limits.h>
+
+extern void abort ();
+
+int test2(int x)
+{
+  return x + INT_MIN;
+}
+
+int test3(int x)
+{
+  return x - INT_MIN;
+}
+
+int test5(int x)
+{
+  int y = INT_MIN;
+  return x + y;
+}
+
+int test6(int x)
+{
+  int y = INT_MIN;
+  return x - y;
+}
+
+
+
+void test(int a, int b)
+{
+  if (test2(a) != b)
+    abort();
+  if (test3(a) != b)
+    abort();
+  if (test5(a) != b)
+    abort();
+  if (test6(a) != b)
+    abort();
+}
+
+
+int main()
+{
+#if INT_MAX == 2147483647
+  test(0x00000000,0x80000000);
+  test(0x80000000,0x00000000);
+  test(0x12345678,0x92345678);
+  test(0x92345678,0x12345678);
+  test(0x7fffffff,0xffffffff);
+  test(0xffffffff,0x7fffffff);
+#endif
+
+#if INT_MAX == 32767
+  test(0x0000,0x8000);
+  test(0x8000,0x0000);
+  test(0x1234,0x9234);
+  test(0x9234,0x1234);
+  test(0x7fff,0xffff);
+  test(0xffff,0x7fff);
+#endif
+
+  return 0;
+}
index c83ff1adf5ea05ddb5640c1db3b3a43176257ad6..c04c7be373963b96d548497d9244a727c67cc19a 100644 (file)
@@ -22,41 +22,21 @@ unsigned int test2u(unsigned int x)
   return (x ^ 0x1234) ^ (unsigned int)INT_MIN;
 }
 
-int test3(int x)
-{
-  return (x + INT_MIN) ^ 0x1234;
-}
-
 unsigned int test3u(unsigned int x)
 {
   return (x + (unsigned int)INT_MIN) ^ 0x1234;
 }
 
-int test4(int x)
-{
-  return (x ^ 0x1234) + INT_MIN;
-}
-
 unsigned int test4u(unsigned int x)
 {
   return (x ^ 0x1234) + (unsigned int)INT_MIN;
 }
 
-int test5(int x)
-{
-  return (x - INT_MIN) ^ 0x1234;
-}
-
 unsigned int test5u(unsigned int x)
 {
   return (x - (unsigned int)INT_MIN) ^ 0x1234;
 }
 
-int test6(int x)
-{
-  return (x ^ 0x1234) - INT_MIN;
-}
-
 unsigned int test6u(unsigned int x)
 {
   return (x ^ 0x1234) - (unsigned int)INT_MIN;
@@ -90,13 +70,6 @@ unsigned int test8u(unsigned int x)
   return (x ^ y) ^ z;
 }
 
-int test9(int x)
-{
-  int y = INT_MIN;
-  int z = 0x1234;
-  return (x + y) ^ z;
-}
-
 unsigned int test9u(unsigned int x)
 {
   unsigned int y = (unsigned int)INT_MIN;
@@ -104,13 +77,6 @@ unsigned int test9u(unsigned int x)
   return (x + y) ^ z;
 }
 
-int test10(int x)
-{
-  int y = 0x1234;
-  int z = INT_MIN;
-  return (x ^ y) + z;
-}
-
 unsigned int test10u(unsigned int x)
 {
   unsigned int y = 0x1234;
@@ -118,13 +84,6 @@ unsigned int test10u(unsigned int x)
   return (x ^ y) + z;
 }
 
-int test11(int x)
-{
-  int y = INT_MIN;
-  int z = 0x1234;
-  return (x - y) ^ z;
-}
-
 unsigned int test11u(unsigned int x)
 {
   unsigned int y = (unsigned int)INT_MIN;
@@ -132,13 +91,6 @@ unsigned int test11u(unsigned int x)
   return (x - y) ^ z;
 }
 
-int test12(int x)
-{
-  int y = 0x1234;
-  int z = INT_MIN;
-  return (x ^ y) - z;
-}
-
 unsigned int test12u(unsigned int x)
 {
   unsigned int y = 0x1234;
@@ -153,26 +105,10 @@ void test(int a, int b)
     abort();
   if (test2(a) != b)
     abort();
-  if (test3(a) != b)
-    abort();
-  if (test4(a) != b)
-    abort();
-  if (test5(a) != b)
-    abort();
-  if (test6(a) != b)
-    abort();
   if (test7(a) != b)
     abort();
   if (test8(a) != b)
     abort();
-  if (test9(a) != b)
-    abort();
-  if (test10(a) != b)
-    abort();
-  if (test11(a) != b)
-    abort();
-  if (test12(a) != b)
-    abort();
 }
 
 void testu(unsigned int a, unsigned int b)
diff --git a/gcc/testsuite/gcc.c-torture/execute/20040409-2w.c b/gcc/testsuite/gcc.c-torture/execute/20040409-2w.c
new file mode 100644 (file)
index 0000000..f6c5f2c
--- /dev/null
@@ -0,0 +1,99 @@
+/* { dg-additional-options "-fwrapv" } */
+
+#include <limits.h>
+
+extern void abort ();
+
+int test3(int x)
+{
+  return (x + INT_MIN) ^ 0x1234;
+}
+
+int test4(int x)
+{
+  return (x ^ 0x1234) + INT_MIN;
+}
+
+int test5(int x)
+{
+  return (x - INT_MIN) ^ 0x1234;
+}
+
+int test6(int x)
+{
+  return (x ^ 0x1234) - INT_MIN;
+}
+
+int test9(int x)
+{
+  int y = INT_MIN;
+  int z = 0x1234;
+  return (x + y) ^ z;
+}
+
+int test10(int x)
+{
+  int y = 0x1234;
+  int z = INT_MIN;
+  return (x ^ y) + z;
+}
+
+int test11(int x)
+{
+  int y = INT_MIN;
+  int z = 0x1234;
+  return (x - y) ^ z;
+}
+
+int test12(int x)
+{
+  int y = 0x1234;
+  int z = INT_MIN;
+  return (x ^ y) - z;
+}
+
+
+void test(int a, int b)
+{
+  if (test3(a) != b)
+    abort();
+  if (test4(a) != b)
+    abort();
+  if (test5(a) != b)
+    abort();
+  if (test6(a) != b)
+    abort();
+  if (test9(a) != b)
+    abort();
+  if (test10(a) != b)
+    abort();
+  if (test11(a) != b)
+    abort();
+  if (test12(a) != b)
+    abort();
+}
+
+
+int main()
+{
+#if INT_MAX == 2147483647
+  test(0x00000000,0x80001234);
+  test(0x00001234,0x80000000);
+  test(0x80000000,0x00001234);
+  test(0x80001234,0x00000000);
+  test(0x7fffffff,0xffffedcb);
+  test(0xffffffff,0x7fffedcb);
+#endif
+
+#if INT_MAX == 32767
+  test(0x0000,0x9234);
+  test(0x1234,0x8000);
+  test(0x8000,0x1234);
+  test(0x9234,0x0000);
+  test(0x7fff,0xedcb);
+  test(0xffff,0x6dcb);
+#endif
+
+  return 0;
+}
+
index 07aa99cee1f29658c8c23e466b743274d4b7b0a7..279cab1803b65ffb8bab282869c0d289f422add2 100644 (file)
@@ -12,21 +12,11 @@ unsigned int test1u(unsigned int x)
   return ~(x ^ (unsigned int)INT_MIN);
 }
 
-int test2(int x)
-{
-  return ~(x + INT_MIN);
-}
-
 unsigned int test2u(unsigned int x)
 {
   return ~(x + (unsigned int)INT_MIN);
 }
 
-int test3(int x)
-{
-  return ~(x - INT_MIN);
-}
-
 unsigned int test3u(unsigned int x)
 {
   return ~(x - (unsigned int)INT_MIN);
@@ -44,24 +34,12 @@ unsigned int test4u(unsigned int x)
   return ~(x ^ y);
 }
 
-int test5(int x)
-{
-  int y = INT_MIN;
-  return ~(x + y);
-}
-
 unsigned int test5u(unsigned int x)
 {
   unsigned int y = (unsigned int)INT_MIN;
   return ~(x + y);
 }
 
-int test6(int x)
-{
-  int y = INT_MIN;
-  return ~(x - y);
-}
-
 unsigned int test6u(unsigned int x)
 {
   unsigned int y = (unsigned int)INT_MIN;
@@ -74,16 +52,8 @@ void test(int a, int b)
 {
   if (test1(a) != b)
     abort();
-  if (test2(a) != b)
-    abort();
-  if (test3(a) != b)
-    abort();
   if (test4(a) != b)
     abort();
-  if (test5(a) != b)
-    abort();
-  if (test6(a) != b)
-    abort();
 }
 
 void testu(unsigned int a, unsigned int b)
diff --git a/gcc/testsuite/gcc.c-torture/execute/20040409-3w.c b/gcc/testsuite/gcc.c-torture/execute/20040409-3w.c
new file mode 100644 (file)
index 0000000..3a1883d
--- /dev/null
@@ -0,0 +1,65 @@
+/* { dg-additional-options "-fwrapv" } */
+
+#include <limits.h>
+
+extern void abort ();
+
+int test2(int x)
+{
+  return ~(x + INT_MIN);
+}
+
+int test3(int x)
+{
+  return ~(x - INT_MIN);
+}
+
+int test5(int x)
+{
+  int y = INT_MIN;
+  return ~(x + y);
+}
+
+int test6(int x)
+{
+  int y = INT_MIN;
+  return ~(x - y);
+}
+
+
+void test(int a, int b)
+{
+  if (test2(a) != b)
+    abort();
+  if (test3(a) != b)
+    abort();
+  if (test5(a) != b)
+    abort();
+  if (test6(a) != b)
+    abort();
+}
+
+
+int main()
+{
+#if INT_MAX == 2147483647
+  test(0x00000000,0x7fffffff);
+  test(0x80000000,0xffffffff);
+  test(0x12345678,0x6dcba987);
+  test(0x92345678,0xedcba987);
+  test(0x7fffffff,0x00000000);
+  test(0xffffffff,0x80000000);
+#endif
+
+#if INT_MAX == 32767
+  test(0x0000,0x7fff);
+  test(0x8000,0xffff);
+  test(0x1234,0x6dcb);
+  test(0x9234,0xedcb);
+  test(0x7fff,0x0000);
+  test(0xffff,0x8000);
+#endif
+
+  return 0;
+}
+
index 1e303b19690f335305e3479be8c2279f8474f1fa..1fa7f3ee15e3a33f8184f792317242b2ebcf94a0 100644 (file)
@@ -2,7 +2,7 @@
 /* { dg-options "-O2 -fdump-tree-optimized-raw" } */
 
 int f(int a, int b, int c){
-  c |= 1; // c cannot be 0
+  if (c == 0) __builtin_unreachable();
   a *= c;
   b *= c;
   return a == b;
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp118.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp118.c
new file mode 100644 (file)
index 0000000..8c4cc36
--- /dev/null
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+void eliminate_me();
+void f(int x,int y){
+    if (y <= 0)
+      __builtin_unreachable();
+    x += y;
+    if (x == -__INT_MAX__ - 1)
+      eliminate_me ();
+}
+
+/* { dg-final { scan-tree-dump-not "eliminate_me" "optimized" } } */
index 3e760a378fcd77676e9fa75e0682c0e63bc4ac1e..2d1186198f7f1d1d7a8af017208a4426d32a7aa8 100644 (file)
@@ -771,6 +771,25 @@ vr_values::extract_range_from_binary_expr (value_range *vr,
   else
     set_value_range_to_varying (&vr1);
 
+  /* If one argument is varying, we can sometimes still deduce a
+     range for the output: any + [3, +INF] is in [MIN+3, +INF].  */
+  if (INTEGRAL_TYPE_P (TREE_TYPE (op0))
+      && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (op0)))
+    {
+      if (vr0.type == VR_VARYING && vr1.type != VR_VARYING)
+       {
+         vr0.type = VR_RANGE;
+         vr0.min = vrp_val_min (expr_type);
+         vr0.max = vrp_val_max (expr_type);
+       }
+      else if (vr1.type == VR_VARYING && vr0.type != VR_VARYING)
+       {
+         vr1.type = VR_RANGE;
+         vr1.min = vrp_val_min (expr_type);
+         vr1.max = vrp_val_max (expr_type);
+       }
+    }
+
   extract_range_from_binary_expr_1 (vr, code, expr_type, &vr0, &vr1);
 
   /* Try harder for PLUS and MINUS if the range of one operand is symbolic