tree-vrp.c (value_range_nonnegative_p): Fix anti-range case.
authorRichard Guenther <rguenther@suse.de>
Mon, 15 Aug 2011 14:32:12 +0000 (14:32 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Mon, 15 Aug 2011 14:32:12 +0000 (14:32 +0000)
2011-08-15  Richard Guenther  <rguenther@suse.de>

* tree-vrp.c (value_range_nonnegative_p): Fix anti-range case.
(extract_range_from_unary_expr_1): Restructure.

From-SVN: r177761

gcc/ChangeLog
gcc/tree-vrp.c

index 58e2216..de1298c 100644 (file)
@@ -1,5 +1,10 @@
 2011-08-15  Richard Guenther  <rguenther@suse.de>
 
+       * tree-vrp.c (value_range_nonnegative_p): Fix anti-range case.
+       (extract_range_from_unary_expr_1): Restructure.
+
+2011-08-15  Richard Guenther  <rguenther@suse.de>
+
        PR tree-optimization/50058
        * tree-ssa-sccvn.c (vn_reference_lookup_3): Relax aggregate
        copy matching.
index df7a9a2..adf5a53 100644 (file)
@@ -1398,16 +1398,14 @@ range_includes_zero_p (value_range_t *vr)
 static inline bool
 value_range_nonnegative_p (value_range_t *vr)
 {
+  /* Testing for VR_ANTI_RANGE is not useful here as any anti-range
+     which would return a useful value should be encoded as a 
+     VR_RANGE.  */
   if (vr->type == VR_RANGE)
     {
       int result = compare_values (vr->min, integer_zero_node);
       return (result == 0 || result == 1);
     }
-  else if (vr->type == VR_ANTI_RANGE)
-    {
-      int result = compare_values (vr->max, integer_zero_node);
-      return result == -1;
-    }
 
   return false;
 }
@@ -2826,61 +2824,51 @@ extract_range_from_unary_expr_1 (value_range_t *vr,
                                 value_range_t *vr0_, tree op0_type)
 {
   value_range_t vr0 = *vr0_;
-  tree min, max;
-  int cmp;
-
-  /* If VR0 is UNDEFINED, so is the result.  */
-  if (vr0.type == VR_UNDEFINED)
-    {
-      set_value_range_to_undefined (vr);
-      return;
-    }
 
-  /* Refuse to operate on certain unary expressions for which we
-     cannot easily determine a resulting range.  */
-  if (code == FIX_TRUNC_EXPR
-      || code == FLOAT_EXPR
-      || code == CONJ_EXPR)
+  /* VRP only operates on integral and pointer types.  */
+  if (!(INTEGRAL_TYPE_P (op0_type)
+       || POINTER_TYPE_P (op0_type))
+      || !(INTEGRAL_TYPE_P (type)
+          || POINTER_TYPE_P (type)))
     {
       set_value_range_to_varying (vr);
       return;
     }
 
-  /* Refuse to operate on symbolic ranges, or if neither operand is
-     a pointer or integral type.  */
-  if ((!INTEGRAL_TYPE_P (op0_type)
-       && !POINTER_TYPE_P (op0_type))
-      || (vr0.type != VR_VARYING
-         && symbolic_range_p (&vr0)))
-    {
-      set_value_range_to_varying (vr);
-      return;
-    }
-
-  /* If the expression involves pointers, we are only interested in
-     determining if it evaluates to NULL [0, 0] or non-NULL (~[0, 0]).  */
-  if (POINTER_TYPE_P (type) || POINTER_TYPE_P (op0_type))
+  /* If VR0 is UNDEFINED, so is the result.  */
+  if (vr0.type == VR_UNDEFINED)
     {
-      if (range_is_nonnull (&vr0))
-       set_value_range_to_nonnull (vr, type);
-      else if (range_is_null (&vr0))
-       set_value_range_to_null (vr, type);
-      else
-       set_value_range_to_varying (vr);
+      set_value_range_to_undefined (vr);
       return;
     }
 
-  /* Handle unary expressions on integer ranges.  */
-  if (CONVERT_EXPR_CODE_P (code)
-      && INTEGRAL_TYPE_P (type)
-      && INTEGRAL_TYPE_P (op0_type))
+  if (CONVERT_EXPR_CODE_P (code))
     {
       tree inner_type = op0_type;
       tree outer_type = type;
 
+      /* If the expression evaluates to a pointer, we are only interested in
+        determining if it evaluates to NULL [0, 0] or non-NULL (~[0, 0]).  */
+      if (POINTER_TYPE_P (type))
+       {
+         if (CONVERT_EXPR_CODE_P (code))
+           {
+             if (range_is_nonnull (&vr0))
+               set_value_range_to_nonnull (vr, type);
+             else if (range_is_null (&vr0))
+               set_value_range_to_null (vr, type);
+             else
+               set_value_range_to_varying (vr);
+           }
+         else
+           set_value_range_to_varying (vr);
+         return;
+       }
+
       /* If VR0 is varying and we increase the type precision, assume
         a full range for the following transformation.  */
       if (vr0.type == VR_VARYING
+         && INTEGRAL_TYPE_P (inner_type)
          && TYPE_PRECISION (inner_type) < TYPE_PRECISION (outer_type))
        {
          vr0.type = VR_RANGE;
@@ -2933,20 +2921,7 @@ extract_range_from_unary_expr_1 (value_range_t *vr,
       set_value_range_to_varying (vr);
       return;
     }
-
-  /* Conversion of a VR_VARYING value to a wider type can result
-     in a usable range.  So wait until after we've handled conversions
-     before dropping the result to VR_VARYING if we had a source
-     operand that is VR_VARYING.  */
-  if (vr0.type == VR_VARYING)
-    {
-      set_value_range_to_varying (vr);
-      return;
-    }
-
-  /* Apply the operation to each end of the range and see what we end
-     up with.  */
-  if (code == NEGATE_EXPR)
+  else if (code == NEGATE_EXPR)
     {
       /* -X is simply 0 - X, so re-use existing code that also handles
          anti-ranges fine.  */
@@ -2955,17 +2930,35 @@ extract_range_from_unary_expr_1 (value_range_t *vr,
       extract_range_from_binary_expr_1 (vr, MINUS_EXPR, type, &zero, &vr0);
       return;
     }
-  else if (code == ABS_EXPR
-           && !TYPE_UNSIGNED (type))
+  else if (code == ABS_EXPR)
     {
+      tree min, max;
+      int cmp;
+
+      /* Pass through vr0 in the easy cases.  */
+      if (TYPE_UNSIGNED (type)
+         || value_range_nonnegative_p (&vr0))
+       {
+         copy_value_range (vr, &vr0);
+         return;
+       }
+
+      /* For the remaining varying or symbolic ranges we can't do anything
+        useful.  */
+      if (vr0.type == VR_VARYING
+         || symbolic_range_p (&vr0))
+       {
+         set_value_range_to_varying (vr);
+         return;
+       }
+
       /* -TYPE_MIN_VALUE = TYPE_MIN_VALUE with flag_wrapv so we can't get a
          useful range.  */
       if (!TYPE_OVERFLOW_UNDEFINED (type)
          && ((vr0.type == VR_RANGE
               && vrp_val_is_min (vr0.min))
              || (vr0.type == VR_ANTI_RANGE
-                 && !vrp_val_is_min (vr0.min)
-                 && !range_includes_zero_p (&vr0))))
+                 && !vrp_val_is_min (vr0.min))))
        {
          set_value_range_to_varying (vr);
          return;
@@ -3077,6 +3070,18 @@ extract_range_from_unary_expr_1 (value_range_t *vr,
              max = t;
            }
        }
+
+      cmp = compare_values (min, max);
+      if (cmp == -2 || cmp == 1)
+       {
+         /* If the new range has its limits swapped around (MIN > MAX),
+            then the operation caused one of them to wrap around, mark
+            the new range VARYING.  */
+         set_value_range_to_varying (vr);
+       }
+      else
+       set_value_range (vr, vr0.type, min, max, NULL);
+      return;
     }
   else if (code == BIT_NOT_EXPR)
     {
@@ -3088,69 +3093,15 @@ extract_range_from_unary_expr_1 (value_range_t *vr,
                                        type, &minusone, &vr0);
       return;
     }
-  else
+  else if (code == PAREN_EXPR)
     {
-      /* Otherwise, operate on each end of the range.  */
-      min = fold_unary_to_constant (code, type, vr0.min);
-      max = fold_unary_to_constant (code, type, vr0.max);
-
-      if (needs_overflow_infinity (type))
-       {
-         gcc_assert (code != NEGATE_EXPR && code != ABS_EXPR);
-
-         /* If both sides have overflowed, we don't know
-            anything.  */
-         if ((is_overflow_infinity (vr0.min)
-              || TREE_OVERFLOW (min))
-             && (is_overflow_infinity (vr0.max)
-                 || TREE_OVERFLOW (max)))
-           {
-             set_value_range_to_varying (vr);
-             return;
-           }
-
-         if (is_overflow_infinity (vr0.min))
-           min = vr0.min;
-         else if (TREE_OVERFLOW (min))
-           {
-             if (supports_overflow_infinity (type))
-               min = (tree_int_cst_sgn (min) >= 0
-                      ? positive_overflow_infinity (TREE_TYPE (min))
-                      : negative_overflow_infinity (TREE_TYPE (min)));
-             else
-               {
-                 set_value_range_to_varying (vr);
-                 return;
-               }
-           }
-
-         if (is_overflow_infinity (vr0.max))
-           max = vr0.max;
-         else if (TREE_OVERFLOW (max))
-           {
-             if (supports_overflow_infinity (type))
-               max = (tree_int_cst_sgn (max) >= 0
-                      ? positive_overflow_infinity (TREE_TYPE (max))
-                      : negative_overflow_infinity (TREE_TYPE (max)));
-             else
-               {
-                 set_value_range_to_varying (vr);
-                 return;
-               }
-           }
-       }
+      copy_value_range (vr, &vr0);
+      return;
     }
 
-  cmp = compare_values (min, max);
-  if (cmp == -2 || cmp == 1)
-    {
-      /* If the new range has its limits swapped around (MIN > MAX),
-        then the operation caused one of them to wrap around, mark
-        the new range VARYING.  */
-      set_value_range_to_varying (vr);
-    }
-  else
-    set_value_range (vr, vr0.type, min, max, NULL);
+  /* For unhandled operations fall back to varying.  */
+  set_value_range_to_varying (vr);
+  return;
 }