re PR tree-optimization/22493 (with -fwrapv -INT_MIN is still not positive)
authorJames A. Morrison <phython@gcc.gnu.org>
Thu, 28 Jul 2005 04:35:01 +0000 (04:35 +0000)
committerJames A. Morrison <phython@gcc.gnu.org>
Thu, 28 Jul 2005 04:35:01 +0000 (04:35 +0000)
2005-07-27  James A. Morrison  <phython@gcc.gnu.org>

        PR tree-optimization/22493
        * tree-vrp.c (extract_range_from_unary_expr): Deal with -fwrapv and
        VR_ANTI_RANGEs properly for NEGATE_EXPRs and ABS_EXPRs.

From-SVN: r102458

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.c-torture/execute/pr22493-1.c [new file with mode: 0644]
gcc/testsuite/gcc.c-torture/execute/pr22493-1.x [new file with mode: 0644]
gcc/testsuite/gcc.c-torture/execute/vrp-1.c [new file with mode: 0644]
gcc/testsuite/gcc.c-torture/execute/vrp-2.c [new file with mode: 0644]
gcc/testsuite/gcc.c-torture/execute/vrp-3.c [new file with mode: 0644]
gcc/tree-vrp.c

index 299d206..b0d7bff 100644 (file)
@@ -1,3 +1,9 @@
+2005-07-27  James A. Morrison  <phython@gcc.gnu.org>
+
+       PR tree-optimization/22493
+       * tree-vrp.c (extract_range_from_unary_expr): Deal with -fwrapv and
+       VR_ANTI_RANGEs properly for NEGATE_EXPRs and ABS_EXPRs.
+
 2005-07-27  Aldy Hernandez  <aldyh@redhat.com>
 
        * config/frv/frv.opt (moptimize-membar): New.
index a98dd06..d2861aa 100644 (file)
@@ -1,3 +1,12 @@
+2005-07-27  James A. Morrison  <phython@gcc.gnu.org>
+
+       PR rtl-optimization/22493
+       * gcc.c-torture/execute/pr22493-1.c: New test.
+       * gcc.c-torture/execute/pr22493-1.x: New.
+       * gcc.c-torture/execute/vrp-1.c: New test.
+       * gcc.c-torture/execute/vrp-2.c: New test.
+       * gcc.c-torture/execute/vrp-2.c: New test.
+
 2005-07-27  Aldy Hernandez  <aldyh@redhat.com>
 
        * gcc.target/frv/all-builtin-read8.c: Delete.
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr22493-1.c b/gcc/testsuite/gcc.c-torture/execute/pr22493-1.c
new file mode 100644 (file)
index 0000000..bc0ff78
--- /dev/null
@@ -0,0 +1,18 @@
+#include <limits.h>
+extern void abort ();
+extern void exit (int);
+void f(int i)
+{
+  if (i>0)
+    abort();
+  i = -i;
+  if (i<0)
+    return;
+  abort ();
+}
+
+int main(int argc, char *argv[])
+{
+  f(INT_MIN);
+  exit (0);
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr22493-1.x b/gcc/testsuite/gcc.c-torture/execute/pr22493-1.x
new file mode 100644 (file)
index 0000000..36a5839
--- /dev/null
@@ -0,0 +1,2 @@
+set additional_flags "-fwrapv"
+return 0
diff --git a/gcc/testsuite/gcc.c-torture/execute/vrp-1.c b/gcc/testsuite/gcc.c-torture/execute/vrp-1.c
new file mode 100644 (file)
index 0000000..ac42e6c
--- /dev/null
@@ -0,0 +1,20 @@
+
+extern void abort ();
+extern void exit (int);
+
+int f (int a) {
+       if (a != 2) {
+               a = -a;
+               if (a == 2)
+                 return 0;
+               return 1;
+       }
+       return 1;
+}
+
+int main (int argc, char *argv[]) {
+       if (f (-2))
+               abort ();
+       exit (0);
+}
+
diff --git a/gcc/testsuite/gcc.c-torture/execute/vrp-2.c b/gcc/testsuite/gcc.c-torture/execute/vrp-2.c
new file mode 100644 (file)
index 0000000..69ed3e7
--- /dev/null
@@ -0,0 +1,19 @@
+extern void abort ();
+extern void exit (int);
+
+int f (int a) {
+       if (a != 2) {
+               a = a > 0 ? a : -a;
+               if (a == 2)
+                 return 0;
+               return 1;
+       }
+       return 1;
+}
+
+int main (int argc, char *argv[]) {
+       if (f (-2))
+               abort ();
+       exit (0);
+}
+
diff --git a/gcc/testsuite/gcc.c-torture/execute/vrp-3.c b/gcc/testsuite/gcc.c-torture/execute/vrp-3.c
new file mode 100644 (file)
index 0000000..bc0e490
--- /dev/null
@@ -0,0 +1,21 @@
+extern void abort ();
+extern void exit (int);
+
+int f (int a) {
+       if (a < 12) {
+         if (a > -15) {
+               a = a > 0 ? a : -a;
+               if (a == 2)
+                 return 0;
+               return 1;
+         }
+       }
+       return 1;
+}
+
+int main (int argc, char *argv[]) {
+       if (f (-2))
+               abort ();
+       exit (0);
+}
+
index 58fb7ef..af79ba4 100644 (file)
@@ -1353,27 +1353,31 @@ extract_range_from_unary_expr (value_range_t *vr, tree expr)
   if (code == NEGATE_EXPR
       && !TYPE_UNSIGNED (TREE_TYPE (expr)))
     {
-      /* Negating an anti-range doesn't really do anything to it.  The
-        new range will also not take on the same range of values
-        excluded by the original anti-range.  */
-      if (vr0.type == VR_ANTI_RANGE)
-       {
-         copy_value_range (vr, &vr0);
-         return;
-       }
-
       /* NEGATE_EXPR flips the range around.  */
-      min = (vr0.max == TYPE_MAX_VALUE (TREE_TYPE (expr)))
-           ? TYPE_MIN_VALUE (TREE_TYPE (expr))
-           : fold_unary_to_constant (code, TREE_TYPE (expr), vr0.max);
+      min = (vr0.max == TYPE_MAX_VALUE (TREE_TYPE (expr)) && !flag_wrapv)
+            ? TYPE_MIN_VALUE (TREE_TYPE (expr))
+            : fold_unary_to_constant (code, TREE_TYPE (expr), vr0.max);
 
-      max = (vr0.min == TYPE_MIN_VALUE (TREE_TYPE (expr)))
-           ? TYPE_MAX_VALUE (TREE_TYPE (expr))
-           : fold_unary_to_constant (code, TREE_TYPE (expr), vr0.min);
+      max = (vr0.min == TYPE_MIN_VALUE (TREE_TYPE (expr)) && !flag_wrapv)
+            ? TYPE_MAX_VALUE (TREE_TYPE (expr))
+            : fold_unary_to_constant (code, TREE_TYPE (expr), vr0.min);
     }
   else if (code == ABS_EXPR
            && !TYPE_UNSIGNED (TREE_TYPE (expr)))
     {
+      /* -TYPE_MIN_VALUE = TYPE_MIN_VALUE with flag_wrapv so we can't get a
+         useful range.  */
+      if (flag_wrapv
+         && ((vr0.type == VR_RANGE
+              && vr0.min == TYPE_MIN_VALUE (TREE_TYPE (expr)))
+             || (vr0.type == VR_ANTI_RANGE
+                 && vr0.min != TYPE_MIN_VALUE (TREE_TYPE (expr))
+                 && !range_includes_zero_p (&vr0))))
+       {
+         set_value_range_to_varying (vr);
+         return;
+       }
+       
       /* ABS_EXPR may flip the range around, if the original range
         included negative values.  */
       min = (vr0.min == TYPE_MIN_VALUE (TREE_TYPE (expr)))
@@ -1382,12 +1386,58 @@ extract_range_from_unary_expr (value_range_t *vr, tree expr)
 
       max = fold_unary_to_constant (code, TREE_TYPE (expr), vr0.max);
 
-      /* If the range was reversed, swap MIN and MAX.  */
-      if (compare_values (min, max) == 1)
+      cmp = compare_values (min, max);
+
+      /* If a VR_ANTI_RANGEs contains zero, then we have
+        ~[-INF, min(MIN, MAX)].  */
+      if (vr0.type == VR_ANTI_RANGE)
+       { 
+         if (range_includes_zero_p (&vr0))
+           {
+             tree type_min_value = TYPE_MIN_VALUE (TREE_TYPE (expr));
+
+             /* Take the lower of the two values.  */
+             if (cmp != 1)
+               max = min;
+
+             /* Create ~[-INF, min (abs(MIN), abs(MAX))]
+                or ~[-INF + 1, min (abs(MIN), abs(MAX))] when
+                flag_wrapv is set and the original anti-range doesn't include
+                TYPE_MIN_VALUE, remember -TYPE_MIN_VALUE = TYPE_MIN_VALUE.  */
+             min = (flag_wrapv && vr0.min != type_min_value
+                    ? int_const_binop (PLUS_EXPR,
+                                       type_min_value,
+                                       integer_one_node, 0)
+                    : type_min_value);
+           }
+         else
+           {
+             /* All else has failed, so create the range [0, INF], even for
+                flag_wrapv since TYPE_MIN_VALUE is in the original
+                anti-range.  */
+             vr0.type = VR_RANGE;
+             min = build_int_cst (TREE_TYPE (expr), 0);
+             max = TYPE_MAX_VALUE (TREE_TYPE (expr));
+           }
+       }
+
+      /* If the range contains zero then we know that the minimum value in the
+         range will be zero.  */
+      else if (range_includes_zero_p (&vr0))
+       {
+         if (cmp == 1)
+           max = min;
+         min = build_int_cst (TREE_TYPE (expr), 0);
+       }
+      else
        {
-         tree t = min;
-         min = max;
-         max = t;
+          /* If the range was reversed, swap MIN and MAX.  */
+         if (cmp == 1)
+           {
+             tree t = min;
+             min = max;
+             max = t;
+           }
        }
     }
   else