Enforce canonicalization in value_range.
authorAldy Hernandez <aldyh@redhat.com>
Thu, 15 Aug 2019 10:45:41 +0000 (10:45 +0000)
committerAldy Hernandez <aldyh@gcc.gnu.org>
Thu, 15 Aug 2019 10:45:41 +0000 (10:45 +0000)
From-SVN: r274525

gcc/ChangeLog
gcc/tree-vrp.c
gcc/tree-vrp.h
gcc/vr-values.c

index ae7d49ca5c80236de372006ed24fd2ad365679aa..4f9f044aea6684207e8ab9ae3a62cb22eb12e3f6 100644 (file)
@@ -1,3 +1,37 @@
+2019-08-15  Aldy Hernandez  <aldyh@redhat.com>
+
+       * tree-vrp.c (value_range_base::set): Merge in code from
+       value_range_base::set_and_canonicalize.
+       Enforce canonicalization at set time.
+       Normalize [MIN, MAX] into VARYING and ~[MIN, MAX] into UNDEFINED.
+       (value_range_base::set_undefined): Inline call to set().
+       (value_range_base::set_varying): Same.
+       (value_range_base::singleton_p): Handle VR_ANTI_RANGEs.
+       (vrp_val_max): New argument handle_pointers.
+       (vrp_val_min): Same.
+       (ranges_from_anti_range): Same.
+       (extract_range_into_wide_ints): Use tree argument instead of sign
+       and precision.
+       (extract_range_from_multiplicative_op): Take in tree type instead
+       of precision and sign.  Adapt function for canonicalized ranges.
+       (extract_range_from_binary_expr): Pass type to
+       extract_range_from_multiplicative_op.
+       Adapt for canonicalized ranges.
+       (extract_range_from_unary_expr): Same.
+       (value_range_base::intersect_helper): Adjust for canonicalized
+       ranges.
+       (value_range_base::union_helper): Same.
+       (value_range_base::normalize_symbolics): New.
+       * tree-vrp.h (class value_range_base): Remove
+       set_and_canonicalize.
+       New prototype for normalize_symbolics.
+       (class value_range): Remove set_and_canonicalize.
+       (vrp_val_min): Adjust prototype.
+       (vrp_val_max): Same.
+       * vr-values.c
+       (vr_values::extract_range_for_var_from_comparison_expr):  Call set
+       instead of set_and_canonicalize.
+
 2019-08-15  Richard Sandiford  <richard.sandiford@arm.com>
 
        PR middle-end/91444
index e2850682da2072e0561846ee80103801884bcdfb..77e7594eee51654f333a96a2b3efca05f5c6d643 100644 (file)
@@ -69,23 +69,20 @@ along with GCC; see the file COPYING3.  If not see
 #include "builtins.h"
 #include "wide-int-range.h"
 
+static bool
+ranges_from_anti_range (const value_range_base *ar,
+                       value_range_base *vr0, value_range_base *vr1,
+                       bool handle_pointers = false);
+
 /* Set of SSA names found live during the RPO traversal of the function
    for still active basic-blocks.  */
 static sbitmap *live;
 
-void
-value_range_base::set (enum value_range_kind kind, tree min, tree max)
-{
-  m_kind = kind;
-  m_min = min;
-  m_max = max;
-  if (flag_checking)
-    check ();
-}
-
 void
 value_range::set_equiv (bitmap equiv)
 {
+  if (undefined_p () || varying_p ())
+    equiv = NULL;
   /* Since updating the equivalence set involves deep copying the
      bitmaps, only do it if absolutely necessary.
 
@@ -261,7 +258,8 @@ value_range_base::constant_p () const
 void
 value_range_base::set_undefined ()
 {
-  set (VR_UNDEFINED, NULL, NULL);
+  m_kind = VR_UNDEFINED;
+  m_min = m_max = NULL;
 }
 
 void
@@ -273,7 +271,8 @@ value_range::set_undefined ()
 void
 value_range_base::set_varying ()
 {
-  set (VR_VARYING, NULL, NULL);
+  m_kind = VR_VARYING;
+  m_min = m_max = NULL;
 }
 
 void
@@ -324,6 +323,24 @@ value_range::equiv_add (const_tree var,
 bool
 value_range_base::singleton_p (tree *result) const
 {
+  if (m_kind == VR_ANTI_RANGE)
+    {
+      if (nonzero_p ())
+       {
+         if (TYPE_PRECISION (type ()) == 1)
+           {
+             if (result)
+               *result = m_max;
+             return true;
+           }
+         return false;
+       }
+
+      value_range_base vr0, vr1;
+      return (ranges_from_anti_range (this, &vr0, &vr1, true)
+             && vr1.undefined_p ()
+             && vr0.singleton_p (result));
+    }
   if (m_kind == VR_RANGE
       && vrp_operand_equal_p (min (), max ())
       && is_gimple_min_invariant (min ()))
@@ -499,23 +516,28 @@ static assert_locus **asserts_for;
 /* Return the maximum value for TYPE.  */
 
 tree
-vrp_val_max (const_tree type)
+vrp_val_max (const_tree type, bool handle_pointers)
 {
-  if (!INTEGRAL_TYPE_P (type))
-    return NULL_TREE;
-
-  return TYPE_MAX_VALUE (type);
+  if (INTEGRAL_TYPE_P (type))
+    return TYPE_MAX_VALUE (type);
+  if (POINTER_TYPE_P (type) && handle_pointers)
+    {
+      wide_int max = wi::max_value (TYPE_PRECISION (type), TYPE_SIGN (type));
+      return wide_int_to_tree (const_cast<tree> (type), max);
+    }
+  return NULL_TREE;
 }
 
 /* Return the minimum value for TYPE.  */
 
 tree
-vrp_val_min (const_tree type)
+vrp_val_min (const_tree type, bool handle_pointers)
 {
-  if (!INTEGRAL_TYPE_P (type))
-    return NULL_TREE;
-
-  return TYPE_MIN_VALUE (type);
+  if (INTEGRAL_TYPE_P (type))
+    return TYPE_MIN_VALUE (type);
+  if (POINTER_TYPE_P (type) && handle_pointers)
+    return build_zero_cst (const_cast<tree> (type));
+  return NULL_TREE;
 }
 
 /* Return whether VAL is equal to the maximum value of its type.
@@ -626,8 +648,7 @@ intersect_range_with_nonzero_bits (enum value_range_kind vr_type,
    extract ranges from var + CST op limit.  */
 
 void
-value_range_base::set_and_canonicalize (enum value_range_kind kind,
-                                       tree min, tree max)
+value_range_base::set (enum value_range_kind kind, tree min, tree max)
 {
   /* Use the canonical setters for VR_UNDEFINED and VR_VARYING.  */
   if (kind == VR_UNDEFINED)
@@ -645,7 +666,9 @@ value_range_base::set_and_canonicalize (enum value_range_kind kind,
   if (TREE_CODE (min) != INTEGER_CST
       || TREE_CODE (max) != INTEGER_CST)
     {
-      set (kind, min, max);
+      m_kind = kind;
+      m_min = min;
+      m_max = max;
       return;
     }
 
@@ -681,12 +704,13 @@ value_range_base::set_and_canonicalize (enum value_range_kind kind,
       kind = kind == VR_RANGE ? VR_ANTI_RANGE : VR_RANGE;
     }
 
+  tree type = TREE_TYPE (min);
+
   /* Anti-ranges that can be represented as ranges should be so.  */
   if (kind == VR_ANTI_RANGE)
     {
       /* For -fstrict-enums we may receive out-of-range ranges so consider
          values < -INF and values > INF as -INF/INF as well.  */
-      tree type = TREE_TYPE (min);
       bool is_min = (INTEGRAL_TYPE_P (type)
                     && tree_int_cst_compare (min, TYPE_MIN_VALUE (type)) <= 0);
       bool is_max = (INTEGRAL_TYPE_P (type)
@@ -729,22 +753,37 @@ value_range_base::set_and_canonicalize (enum value_range_kind kind,
         }
     }
 
+  /* Normalize [MIN, MAX] into VARYING and ~[MIN, MAX] into UNDEFINED.
+
+     Avoid using TYPE_{MIN,MAX}_VALUE because -fstrict-enums can
+     restrict those to a subset of what actually fits in the type.
+     Instead use the extremes of the type precision which will allow
+     compare_range_with_value() to check if a value is inside a range,
+     whereas if we used TYPE_*_VAL, said function would just punt
+     upon seeing a VARYING.  */
+  unsigned prec = TYPE_PRECISION (type);
+  signop sign = TYPE_SIGN (type);
+  if (wi::eq_p (wi::to_wide (min), wi::min_value (prec, sign))
+      && wi::eq_p (wi::to_wide (max), wi::max_value (prec, sign)))
+    {
+      if (kind == VR_RANGE)
+       set_varying ();
+      else if (kind == VR_ANTI_RANGE)
+       set_undefined ();
+      else
+       gcc_unreachable ();
+      return;
+    }
+
   /* Do not drop [-INF(OVF), +INF(OVF)] to varying.  (OVF) has to be sticky
      to make sure VRP iteration terminates, otherwise we can get into
      oscillations.  */
 
-  set (kind, min, max);
-}
-
-void
-value_range::set_and_canonicalize (enum value_range_kind kind,
-                                  tree min, tree max, bitmap equiv)
-{
-  value_range_base::set_and_canonicalize (kind, min, max);
-  if (this->kind () == VR_RANGE || this->kind () == VR_ANTI_RANGE)
-    set_equiv (equiv);
-  else
-    equiv_clear ();
+  m_kind = kind;
+  m_min = min;
+  m_max = max;
+  if (flag_checking)
+    check ();
 }
 
 void
@@ -1180,7 +1219,8 @@ vrp_set_zero_nonzero_bits (const tree expr_type,
 
 static bool
 ranges_from_anti_range (const value_range_base *ar,
-                       value_range_base *vr0, value_range_base *vr1)
+                       value_range_base *vr0, value_range_base *vr1,
+                       bool handle_pointers)
 {
   tree type = ar->type ();
 
@@ -1193,18 +1233,18 @@ ranges_from_anti_range (const value_range_base *ar,
   if (ar->kind () != VR_ANTI_RANGE
       || TREE_CODE (ar->min ()) != INTEGER_CST
       || TREE_CODE (ar->max ()) != INTEGER_CST
-      || !vrp_val_min (type)
-      || !vrp_val_max (type))
+      || !vrp_val_min (type, handle_pointers)
+      || !vrp_val_max (type, handle_pointers))
     return false;
 
-  if (tree_int_cst_lt (vrp_val_min (type), ar->min ()))
+  if (tree_int_cst_lt (vrp_val_min (type, handle_pointers), ar->min ()))
     vr0->set (VR_RANGE,
-             vrp_val_min (type),
+             vrp_val_min (type, handle_pointers),
              wide_int_to_tree (type, wi::to_wide (ar->min ()) - 1));
-  if (tree_int_cst_lt (ar->max (), vrp_val_max (type)))
+  if (tree_int_cst_lt (ar->max (), vrp_val_max (type, handle_pointers)))
     vr1->set (VR_RANGE,
              wide_int_to_tree (type, wi::to_wide (ar->max ()) + 1),
-             vrp_val_max (type));
+             vrp_val_max (type, handle_pointers));
   if (vr0->undefined_p ())
     {
       *vr0 = *vr1;
@@ -1215,21 +1255,20 @@ ranges_from_anti_range (const value_range_base *ar,
 }
 
 /* Extract the components of a value range into a pair of wide ints in
-   [WMIN, WMAX].
-
-   If the value range is anything but a VR_*RANGE of constants, the
-   resulting wide ints are set to [-MIN, +MAX] for the type.  */
+   [WMIN, WMAX], after having normalized any symbolics from the input.  */
 
 static void inline
-extract_range_into_wide_ints (const value_range_base *vr,
-                             signop sign, unsigned prec,
-                             wide_int &wmin, wide_int &wmax)
+extract_range_into_wide_ints (const value_range_base *vr_,
+                             tree type, wide_int &wmin, wide_int &wmax)
 {
-  gcc_assert (vr->kind () != VR_ANTI_RANGE || vr->symbolic_p ());
-  if (range_int_cst_p (vr))
+  signop sign = TYPE_SIGN (type);
+  unsigned int prec = TYPE_PRECISION (type);
+  gcc_assert (vr_->kind () != VR_ANTI_RANGE || vr_->symbolic_p ());
+  value_range vr = vr_->normalize_symbolics ();
+  if (range_int_cst_p (&vr))
     {
-      wmin = wi::to_wide (vr->min ());
-      wmax = wi::to_wide (vr->max ());
+      wmin = wi::to_wide (vr.min ());
+      wmax = wi::to_wide (vr.max ());
     }
   else
     {
@@ -1256,12 +1295,31 @@ extract_range_from_multiplicative_op (value_range_base *vr,
              || code == ROUND_DIV_EXPR
              || code == RSHIFT_EXPR
              || code == LSHIFT_EXPR);
-  gcc_assert (vr0->kind () == VR_RANGE
-             && vr0->kind () == vr1->kind ());
+  if (!range_int_cst_p (vr1))
+    {
+      vr->set_varying ();
+      return;
+    }
+
+  /* Even if vr0 is VARYING or otherwise not usable, we can derive
+     useful ranges just from the shift count.  E.g.
+     x >> 63 for signed 64-bit x is always [-1, 0].  */
+  value_range_base tem = vr0->normalize_symbolics ();
+  tree vr0_min, vr0_max;
+  if (tem.kind () == VR_RANGE)
+    {
+      vr0_min = tem.min ();
+      vr0_max = tem.max ();
+    }
+  else
+    {
+      vr0_min = vrp_val_min (type);
+      vr0_max = vrp_val_max (type);
+    }
 
   wide_int res_lb, res_ub;
-  wide_int vr0_lb = wi::to_wide (vr0->min ());
-  wide_int vr0_ub = wi::to_wide (vr0->max ());
+  wide_int vr0_lb = wi::to_wide (vr0_min);
+  wide_int vr0_ub = wi::to_wide (vr0_max);
   wide_int vr1_lb = wi::to_wide (vr1->min ());
   wide_int vr1_ub = wi::to_wide (vr1->max ());
   bool overflow_undefined = TYPE_OVERFLOW_UNDEFINED (type);
@@ -1271,9 +1329,8 @@ extract_range_from_multiplicative_op (value_range_base *vr,
                                        code, TYPE_SIGN (type), prec,
                                        vr0_lb, vr0_ub, vr1_lb, vr1_ub,
                                        overflow_undefined))
-    vr->set_and_canonicalize (VR_RANGE,
-                             wide_int_to_tree (type, res_lb),
-                             wide_int_to_tree (type, res_ub));
+    vr->set (VR_RANGE, wide_int_to_tree (type, res_lb),
+            wide_int_to_tree (type, res_ub));
   else
     vr->set_varying ();
 }
@@ -1667,19 +1724,30 @@ extract_range_from_binary_expr (value_range_base *vr,
      range and see what we end up with.  */
   if (code == PLUS_EXPR || code == MINUS_EXPR)
     {
+      value_range_kind vr0_kind = vr0.kind (), vr1_kind = vr1.kind ();
+      tree vr0_min = vr0.min (), vr0_max = vr0.max ();
+      tree vr1_min = vr1.min (), vr1_max = vr1.max ();
       /* This will normalize things such that calculating
         [0,0] - VR_VARYING is not dropped to varying, but is
         calculated as [MIN+1, MAX].  */
       if (vr0.varying_p ())
-       vr0.set (VR_RANGE, vrp_val_min (expr_type), vrp_val_max (expr_type));
+       {
+         vr0_kind = VR_RANGE;
+         vr0_min = vrp_val_min (expr_type);
+         vr0_max = vrp_val_max (expr_type);
+       }
       if (vr1.varying_p ())
-       vr1.set (VR_RANGE, vrp_val_min (expr_type), vrp_val_max (expr_type));
+       {
+         vr1_kind = VR_RANGE;
+         vr1_min = vrp_val_min (expr_type);
+         vr1_max = vrp_val_max (expr_type);
+       }
 
       const bool minus_p = (code == MINUS_EXPR);
-      tree min_op0 = vr0.min ();
-      tree min_op1 = minus_p ? vr1.max () : vr1.min ();
-      tree max_op0 = vr0.max ();
-      tree max_op1 = minus_p ? vr1.min () : vr1.max ();
+      tree min_op0 = vr0_min;
+      tree min_op1 = minus_p ? vr1_max : vr1_min;
+      tree max_op0 = vr0_max;
+      tree max_op1 = minus_p ? vr1_min : vr1_max;
       tree sym_min_op0 = NULL_TREE;
       tree sym_min_op1 = NULL_TREE;
       tree sym_max_op0 = NULL_TREE;
@@ -1692,7 +1760,7 @@ extract_range_from_binary_expr (value_range_base *vr,
         single-symbolic ranges, try to compute the precise resulting range,
         but only if we know that this resulting range will also be constant
         or single-symbolic.  */
-      if (vr0.kind () == VR_RANGE && vr1.kind () == VR_RANGE
+      if (vr0_kind == VR_RANGE && vr1_kind == VR_RANGE
          && (TREE_CODE (min_op0) == INTEGER_CST
              || (sym_min_op0
                  = get_single_symbol (min_op0, &neg_min_op0, &min_op0)))
@@ -1772,8 +1840,8 @@ extract_range_from_binary_expr (value_range_base *vr,
       wide_int wmin, wmax;
       wide_int vr0_min, vr0_max;
       wide_int vr1_min, vr1_max;
-      extract_range_into_wide_ints (&vr0, sign, prec, vr0_min, vr0_max);
-      extract_range_into_wide_ints (&vr1, sign, prec, vr1_min, vr1_max);
+      extract_range_into_wide_ints (&vr0, expr_type, vr0_min, vr0_max);
+      extract_range_into_wide_ints (&vr1, expr_type, vr1_min, vr1_max);
       if (wide_int_range_min_max (wmin, wmax, code, sign, prec,
                                  vr0_min, vr0_max, vr1_min, vr1_max))
        vr->set (VR_RANGE, wide_int_to_tree (expr_type, wmin),
@@ -1805,12 +1873,6 @@ extract_range_from_binary_expr (value_range_base *vr,
        {
          if (code == RSHIFT_EXPR)
            {
-             /* Even if vr0 is VARYING or otherwise not usable, we can derive
-                useful ranges just from the shift count.  E.g.
-                x >> 63 for signed 64-bit x is always [-1, 0].  */
-             if (vr0.kind () != VR_RANGE || vr0.symbolic_p ())
-               vr0.set (VR_RANGE, vrp_val_min (expr_type),
-                        vrp_val_max (expr_type));
              extract_range_from_multiplicative_op (vr, code, expr_type,
                                                    &vr0, &vr1);
              return;
@@ -1828,7 +1890,7 @@ extract_range_from_binary_expr (value_range_base *vr,
                {
                  min = wide_int_to_tree (expr_type, res_lb);
                  max = wide_int_to_tree (expr_type, res_ub);
-                 vr->set_and_canonicalize (VR_RANGE, min, max);
+                 vr->set (VR_RANGE, min, max);
                  return;
                }
            }
@@ -1860,9 +1922,9 @@ extract_range_from_binary_expr (value_range_base *vr,
         NOTE: As a future improvement, we may be able to do better
         with mixed symbolic (anti-)ranges like [0, A].  See note in
         ranges_from_anti_range.  */
-      extract_range_into_wide_ints (&vr0, sign, prec,
+      extract_range_into_wide_ints (&vr0, expr_type,
                                    dividend_min, dividend_max);
-      extract_range_into_wide_ints (&vr1, sign, prec,
+      extract_range_into_wide_ints (&vr1, expr_type,
                                    divisor_min, divisor_max);
       if (!wide_int_range_div (wmin, wmax, code, sign, prec,
                               dividend_min, dividend_max,
@@ -1893,8 +1955,8 @@ extract_range_from_binary_expr (value_range_base *vr,
        }
       wide_int wmin, wmax, tmp;
       wide_int vr0_min, vr0_max, vr1_min, vr1_max;
-      extract_range_into_wide_ints (&vr0, sign, prec, vr0_min, vr0_max);
-      extract_range_into_wide_ints (&vr1, sign, prec, vr1_min, vr1_max);
+      extract_range_into_wide_ints (&vr0, expr_type, vr0_min, vr0_max);
+      extract_range_into_wide_ints (&vr1, expr_type, vr1_min, vr1_max);
       wide_int_range_trunc_mod (wmin, wmax, sign, prec,
                                vr0_min, vr0_max, vr1_min, vr1_max);
       min = wide_int_to_tree (expr_type, wmin);
@@ -1912,8 +1974,8 @@ extract_range_from_binary_expr (value_range_base *vr,
                                 &may_be_nonzero0, &must_be_nonzero0);
       vrp_set_zero_nonzero_bits (expr_type, &vr1,
                                 &may_be_nonzero1, &must_be_nonzero1);
-      extract_range_into_wide_ints (&vr0, sign, prec, vr0_min, vr0_max);
-      extract_range_into_wide_ints (&vr1, sign, prec, vr1_min, vr1_max);
+      extract_range_into_wide_ints (&vr0, expr_type, vr0_min, vr0_max);
+      extract_range_into_wide_ints (&vr1, expr_type, vr1_min, vr1_max);
       if (code == BIT_AND_EXPR)
        {
          if (wide_int_range_bit_and (wmin, wmax, sign, prec,
@@ -2117,8 +2179,7 @@ extract_range_from_unary_expr (value_range_base *vr,
       signop outer_sign = TYPE_SIGN (outer_type);
       unsigned inner_prec = TYPE_PRECISION (inner_type);
       unsigned outer_prec = TYPE_PRECISION (outer_type);
-      extract_range_into_wide_ints (&vr0, inner_sign, inner_prec,
-                                   vr0_min, vr0_max);
+      extract_range_into_wide_ints (&vr0, inner_type, vr0_min, vr0_max);
       if (wide_int_range_convert (wmin, wmax,
                                  inner_sign, inner_prec,
                                  outer_sign, outer_prec,
@@ -2126,7 +2187,7 @@ extract_range_from_unary_expr (value_range_base *vr,
        {
          tree min = wide_int_to_tree (outer_type, wmin);
          tree max = wide_int_to_tree (outer_type, wmax);
-         vr->set_and_canonicalize (VR_RANGE, min, max);
+         vr->set (VR_RANGE, min, max);
        }
       else
        vr->set_varying ();
@@ -2136,7 +2197,7 @@ extract_range_from_unary_expr (value_range_base *vr,
     {
       wide_int wmin, wmax;
       wide_int vr0_min, vr0_max;
-      extract_range_into_wide_ints (&vr0, sign, prec, vr0_min, vr0_max);
+      extract_range_into_wide_ints (&vr0, type, vr0_min, vr0_max);
       if (wide_int_range_abs (wmin, wmax, sign, prec, vr0_min, vr0_max,
                              TYPE_OVERFLOW_UNDEFINED (type)))
        vr->set (VR_RANGE, wide_int_to_tree (type, wmin),
@@ -2149,7 +2210,8 @@ extract_range_from_unary_expr (value_range_base *vr,
     {
       wide_int wmin, wmax;
       wide_int vr0_min, vr0_max;
-      extract_range_into_wide_ints (&vr0, SIGNED, prec, vr0_min, vr0_max);
+      tree signed_type = make_signed_type (TYPE_PRECISION (type));
+      extract_range_into_wide_ints (&vr0, signed_type, vr0_min, vr0_max);
       wide_int_range_absu (wmin, wmax, prec, vr0_min, vr0_max);
       vr->set (VR_RANGE, wide_int_to_tree (type, wmin),
               wide_int_to_tree (type, wmax));
@@ -6038,7 +6100,7 @@ value_range_base::intersect_helper (const value_range_base *vr0,
      VR_RANGE can still be a VR_RANGE.  Work on a temporary so we can
      fall back to vr0 when this turns things to varying.  */
   value_range_base tem;
-  tem.set_and_canonicalize (vr0type, vr0min, vr0max);
+  tem.set (vr0type, vr0min, vr0max);
   /* If that failed, use the saved original VR0.  */
   if (tem.varying_p ())
     return *vr0;
@@ -6143,7 +6205,7 @@ value_range_base::union_helper (const value_range_base *vr0,
 
   /* Work on a temporary so we can still use vr0 when union returns varying.  */
   value_range_base tem;
-  tem.set_and_canonicalize (vr0type, vr0min, vr0max);
+  tem.set (vr0type, vr0min, vr0max);
 
   /* Failed to find an efficient meet.  Before giving up and setting
      the result to VARYING, see if we can at least derive a useful
@@ -6223,6 +6285,58 @@ value_range::union_ (const value_range *other)
     }
 }
 
+/* Normalize symbolics into constants.  */
+
+value_range_base
+value_range_base::normalize_symbolics () const
+{
+  if (varying_p () || undefined_p ())
+    return *this;
+  tree ttype = type ();
+  bool min_symbolic = !is_gimple_min_invariant (min ());
+  bool max_symbolic = !is_gimple_min_invariant (max ());
+  if (!min_symbolic && !max_symbolic)
+    return *this;
+
+  // [SYM, SYM] -> VARYING
+  if (min_symbolic && max_symbolic)
+    {
+      value_range_base var;
+      var.set_varying ();
+      return var;
+    }
+  if (kind () == VR_RANGE)
+    {
+      // [SYM, NUM] -> [-MIN, NUM]
+      if (min_symbolic)
+       return value_range_base (VR_RANGE, vrp_val_min (ttype), max ());
+      // [NUM, SYM] -> [NUM, +MAX]
+      return value_range_base (VR_RANGE, min (), vrp_val_max (ttype));
+    }
+  gcc_assert (kind () == VR_ANTI_RANGE);
+  // ~[SYM, NUM] -> [NUM + 1, +MAX]
+  if (min_symbolic)
+    {
+      if (!vrp_val_is_max (max ()))
+       {
+         tree n = wide_int_to_tree (ttype, wi::to_wide (max ()) + 1);
+         return value_range_base (VR_RANGE, n, vrp_val_max (ttype));
+       }
+      value_range_base var;
+      var.set_varying ();
+      return var;
+    }
+  // ~[NUM, SYM] -> [-MIN, NUM - 1]
+  if (!vrp_val_is_min (min ()))
+    {
+      tree n = wide_int_to_tree (ttype, wi::to_wide (min ()) - 1);
+      return value_range_base (VR_RANGE, vrp_val_min (ttype), n);
+    }
+  value_range_base var;
+  var.set_varying ();
+  return var;
+}
+
 /* Visit all arguments for PHI node PHI that flow through executable
    edges.  If a valid value range can be derived from all the incoming
    value ranges, set a new range for the LHS of PHI.  */
index 4ec974f5fdb1b6dbd57e8e3a7aae687e31f0a338..b5830851fcb8ee3ccf77dbf0fc3cf4ca6f4689b5 100644 (file)
@@ -71,12 +71,13 @@ public:
   /* Misc methods.  */
   tree type () const;
   bool may_contain_p (tree) const;
-  void set_and_canonicalize (enum value_range_kind, tree, tree);
   bool zero_p () const;
   bool nonzero_p () const;
   bool singleton_p (tree *result = NULL) const;
   void dump (FILE *) const;
 
+  value_range_base normalize_symbolics () const;
+
 protected:
   void check ();
   static value_range_base union_helper (const value_range_base *,
@@ -143,7 +144,6 @@ class GTY((user)) value_range : public value_range_base
 
   /* Misc methods.  */
   void deep_copy (const value_range *);
-  void set_and_canonicalize (enum value_range_kind, tree, tree, bitmap = NULL);
   void dump (FILE *) const;
 
  private:
@@ -270,8 +270,8 @@ extern int operand_less_p (tree, tree);
 extern bool vrp_val_is_min (const_tree);
 extern bool vrp_val_is_max (const_tree);
 
-extern tree vrp_val_min (const_tree);
-extern tree vrp_val_max (const_tree);
+extern tree vrp_val_min (const_tree, bool handle_pointers = false);
+extern tree vrp_val_max (const_tree, bool handle_pointers = false);
 
 extern void extract_range_from_unary_expr (value_range_base *vr,
                                           enum tree_code code,
index 3acbdf62a561cbc173e77ecaa7a4db407ea7e874..a87cb672e36f43dd4a4494f75f27aed33592d489 100644 (file)
@@ -522,9 +522,9 @@ vr_values::extract_range_for_var_from_comparison_expr (tree var,
          vice-versa.  Use set_and_canonicalize which does this for
          us.  */
       if (cond_code == LE_EXPR)
-        vr_p->set_and_canonicalize (VR_RANGE, min, max, vr_p->equiv ());
+        vr_p->set (VR_RANGE, min, max, vr_p->equiv ());
       else if (cond_code == GT_EXPR)
-        vr_p->set_and_canonicalize (VR_ANTI_RANGE, min, max, vr_p->equiv ());
+        vr_p->set (VR_ANTI_RANGE, min, max, vr_p->equiv ());
       else
        gcc_unreachable ();
     }
@@ -596,7 +596,7 @@ vr_values::extract_range_for_var_from_comparison_expr (tree var,
          && vrp_val_is_max (max))
        min = max = limit;
 
-      vr_p->set_and_canonicalize (VR_ANTI_RANGE, min, max, vr_p->equiv ());
+      vr_p->set (VR_ANTI_RANGE, min, max, vr_p->equiv ());
     }
   else if (cond_code == LE_EXPR || cond_code == LT_EXPR)
     {