]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
Merge branch 'trunk-at-merge' into ranger-merge
authorAldy Hernandez <aldyh@gcc.gnu.org>
Sun, 18 Aug 2019 17:21:23 +0000 (17:21 +0000)
committerAldy Hernandez <aldyh@gcc.gnu.org>
Sun, 18 Aug 2019 17:21:23 +0000 (17:21 +0000)
From-SVN: r274621

24 files changed:
1  2 
gcc/ChangeLog
gcc/Makefile.in
gcc/calls.c
gcc/common.opt
gcc/coretypes.h
gcc/dbgcnt.def
gcc/gimple-ssa-evrp.c
gcc/gimple-ssa-sprintf.c
gcc/gimple-ssa-warn-alloca.c
gcc/gimple-ssa-warn-restrict.c
gcc/opts.c
gcc/params.def
gcc/passes.def
gcc/selftest.h
gcc/timevar.def
gcc/tree-pass.h
gcc/tree-ssa-dce.c
gcc/tree-ssa-dom.c
gcc/tree-ssa-propagate.c
gcc/tree-ssa-sccvn.c
gcc/tree-vrp.c
gcc/tree-vrp.h
gcc/vr-values.c
gcc/vr-values.h

diff --cc gcc/ChangeLog
Simple merge
diff --cc gcc/Makefile.in
Simple merge
diff --cc gcc/calls.c
Simple merge
diff --cc gcc/common.opt
Simple merge
diff --cc gcc/coretypes.h
Simple merge
diff --cc gcc/dbgcnt.def
Simple merge
Simple merge
Simple merge
index 469b0990bce989f223dca767d7b55c56d8f8fbf5,af39ff415e1b45e86255dc62835c2f47faafe804..58df6b1d0a0a14d7afb07c0ccd04deb3655cf26e
@@@ -177,12 -294,48 +178,12 @@@ alloca_call_type_by_arg (unsigned HOST_
  // Analyze the alloca call in STMT and return the alloca type with its
  // corresponding limit (if applicable).  IS_VLA is set if the alloca
  // call was created by the gimplifier for a VLA.
 -//
 -// If the alloca call may be too large because of a cast from a signed
 -// type to an unsigned type, set *INVALID_CASTED_TYPE to the
 -// problematic signed type.
  
- static struct alloca_type_and_limit
+ static class alloca_type_and_limit
 -alloca_call_type (gimple *stmt, bool is_vla, tree *invalid_casted_type)
 +alloca_call_type (global_ranger &ranger, gimple *stmt, bool is_vla)
  {
    gcc_assert (gimple_alloca_call_p (stmt));
 -  bool tentative_cast_from_signed = false;
    tree len = gimple_call_arg (stmt, 0);
 -  tree len_casted = NULL;
 -  wide_int min, max;
 -  edge_iterator ei;
 -  edge e;
  
    gcc_assert (!is_vla || warn_vla_limit >= 0);
    gcc_assert (is_vla || warn_alloca_limit >= 0);
@@@ -294,8 -535,9 +295,8 @@@ pass_walloca::execute (function *fun
          else if (warn_alloca_limit < 0)
            continue;
  
-         struct alloca_type_and_limit t
 -        tree invalid_casted_type = NULL;
+         class alloca_type_and_limit t
 -          = alloca_call_type (stmt, is_vla, &invalid_casted_type);
 +          = alloca_call_type (ranger, stmt, is_vla);
  
          unsigned HOST_WIDE_INT adjusted_alloca_limit
            = adjusted_warn_limit (false);
Simple merge
diff --cc gcc/opts.c
Simple merge
diff --cc gcc/params.def
Simple merge
diff --cc gcc/passes.def
index 8f12acf67189335b9ffaf19ed1255799b1720ef3,1a7fd144f87d366f6bb3f63fae7f588628f9fce4..39410ba05f62d56f2fd28864bfaa470ef475534c
@@@ -83,8 -83,7 +83,8 @@@ along with GCC; see the file COPYING3
          /* pass_build_ealias is a dummy pass that ensures that we
             execute TODO_rebuild_alias at this point.  */
          NEXT_PASS (pass_build_ealias);
-         NEXT_PASS (pass_fre);
+         NEXT_PASS (pass_fre, true /* may_iterate */);
 +        NEXT_PASS (pass_ranger_vrp);
          NEXT_PASS (pass_early_vrp);
          NEXT_PASS (pass_merge_phi);
            NEXT_PASS (pass_dse);
diff --cc gcc/selftest.h
Simple merge
diff --cc gcc/timevar.def
Simple merge
diff --cc gcc/tree-pass.h
Simple merge
Simple merge
Simple merge
Simple merge
index fc8d6bc07ea75c8bc6ea4da5d8e41bc3a59e2de3,eb7e4be09e699783173f37b0504dbc733a05ea9c..f06f57269cbd19c817b87b4b4637db6a19758dfe
@@@ -69,8 -70,8 +70,9 @@@ along with GCC; see the file COPYING3
  #include "tree-ssa-loop.h"
  #include "tree-scalar-evolution.h"
  #include "tree-ssa-loop-niter.h"
+ #include "builtins.h"
  #include "tree-ssa-sccvn.h"
 +#include "tree-ssa-propagate.h"
  
  /* This algorithm is based on the SCC algorithm presented by Keith
     Cooper and L. Taylor Simpson in "SCC-Based Value numbering"
@@@ -1904,8 -2136,8 +2136,8 @@@ class rpo_elim : public eliminate_dom_w
  {
  public:
    rpo_elim(basic_block entry_)
-     : eliminate_dom_walker (CDI_DOMINATORS, NULL, NULL), entry (entry_) {}
-   ~rpo_elim();
 -    : eliminate_dom_walker (CDI_DOMINATORS, NULL), entry (entry_),
++    : eliminate_dom_walker (CDI_DOMINATORS, NULL, NULL), entry (entry_),
+       m_avail_freelist (NULL) {}
  
    virtual tree eliminate_avail (basic_block, tree op);
  
diff --cc gcc/tree-vrp.c
index d56fad9dfc3eae3347a195391b503d99269d4632,8067f8560cd1854af7c9efc89e41586b97394532..01bffa0e8585365044ad5d70047aa98197c74ea3
@@@ -1507,196 -1448,112 +1514,49 @@@ combine_bound (enum tree_code code, wid
      wi = wi::shwi (0, prec);
  }
  
 -/* Given a range in [WMIN, WMAX], adjust it for possible overflow and
 -   put the result in VR.
 -
 -   TYPE is the type of the range.
 -
 -   MIN_OVF and MAX_OVF indicate what type of overflow, if any,
 -   occurred while originally calculating WMIN or WMAX.  -1 indicates
 -   underflow.  +1 indicates overflow.  0 indicates neither.  */
 +/* Fold two value range's of a POINTER_PLUS_EXPR into VR.  Return TRUE
 +   if successful.  */
  
 -static void
 -set_value_range_with_overflow (value_range_kind &kind, tree &min, tree &max,
 -                             tree type,
 -                             const wide_int &wmin, const wide_int &wmax,
 -                             wi::overflow_type min_ovf,
 -                             wi::overflow_type max_ovf)
 +static bool
- handle_symbolics_in_pointer_plus_expr (value_range_base *vr,
-                                      enum tree_code code,
-                                      tree expr_type,
-                                      const value_range_base *vr0,
-                                      const value_range_base *vr1)
++extract_range_from_pointer_plus_expr (value_range_base *vr,
++                                    enum tree_code code,
++                                    tree expr_type,
++                                    const value_range_base *vr0,
++                                    const value_range_base *vr1)
  {
 -  const signop sgn = TYPE_SIGN (type);
 -  const unsigned int prec = TYPE_PRECISION (type);
 -
 -  /* For one bit precision if max < min, then the swapped
 -     range covers all values.  */
 -  if (prec == 1 && wi::lt_p (wmax, wmin, sgn))
 -    {
 -      kind = VR_VARYING;
 -      return;
 -    }
 -
 -  if (TYPE_OVERFLOW_WRAPS (type))
 -    {
 -      /* If overflow wraps, truncate the values and adjust the
 -       range kind and bounds appropriately.  */
 -      wide_int tmin = wide_int::from (wmin, prec, sgn);
 -      wide_int tmax = wide_int::from (wmax, prec, sgn);
 -      if ((min_ovf != wi::OVF_NONE) == (max_ovf != wi::OVF_NONE))
 -      {
 -        /* If the limits are swapped, we wrapped around and cover
 -           the entire range.  We have a similar check at the end of
 -           extract_range_from_binary_expr.  */
 -        if (wi::gt_p (tmin, tmax, sgn))
 -          kind = VR_VARYING;
 -        else
 -          {
 -            kind = VR_RANGE;
 -            /* No overflow or both overflow or underflow.  The
 -               range kind stays VR_RANGE.  */
 -            min = wide_int_to_tree (type, tmin);
 -            max = wide_int_to_tree (type, tmax);
 -          }
 -        return;
 -      }
 -      else if ((min_ovf == wi::OVF_UNDERFLOW && max_ovf == wi::OVF_NONE)
 -             || (max_ovf == wi::OVF_OVERFLOW && min_ovf == wi::OVF_NONE))
 -      {
 -        /* Min underflow or max overflow.  The range kind
 -           changes to VR_ANTI_RANGE.  */
 -        bool covers = false;
 -        wide_int tem = tmin;
 -        tmin = tmax + 1;
 -        if (wi::cmp (tmin, tmax, sgn) < 0)
 -          covers = true;
 -        tmax = tem - 1;
 -        if (wi::cmp (tmax, tem, sgn) > 0)
 -          covers = true;
 -        /* If the anti-range would cover nothing, drop to varying.
 -           Likewise if the anti-range bounds are outside of the
 -           types values.  */
 -        if (covers || wi::cmp (tmin, tmax, sgn) > 0)
 -          {
 -            kind = VR_VARYING;
 -            return;
 -          }
 -        kind = VR_ANTI_RANGE;
 -        min = wide_int_to_tree (type, tmin);
 -        max = wide_int_to_tree (type, tmax);
 -        return;
 -      }
 +  if (POINTER_TYPE_P (expr_type) && code == POINTER_PLUS_EXPR)
 +    {
 +      /* For pointer types, we are really only interested in asserting
 +       whether the expression evaluates to non-NULL.
 +       With -fno-delete-null-pointer-checks we need to be more
 +       conservative.  As some object might reside at address 0,
 +       then some offset could be added to it and the same offset
 +       subtracted again and the result would be NULL.
 +       E.g.
 +       static int a[12]; where &a[0] is NULL and
 +       ptr = &a[6];
 +       ptr -= 6;
 +       ptr will be NULL here, even when there is POINTER_PLUS_EXPR
 +       where the first range doesn't include zero and the second one
 +       doesn't either.  As the second operand is sizetype (unsigned),
 +       consider all ranges where the MSB could be set as possible
 +       subtractions where the result might be NULL.  */
 +      if ((!range_includes_zero_p (vr0)
 +         || !range_includes_zero_p (vr1))
 +        && !TYPE_OVERFLOW_WRAPS (expr_type)
 +        && (flag_delete_null_pointer_checks
 +            || (range_int_cst_p (vr1)
 +                && !tree_int_cst_sign_bit (vr1->max ()))))
 +      vr->set_nonzero (expr_type);
 +      else if (vr0->zero_p () && vr1->zero_p ())
 +      vr->set_zero (expr_type);
        else
 -      {
 -        /* Other underflow and/or overflow, drop to VR_VARYING.  */
 -        kind = VR_VARYING;
 -        return;
 -      }
 -    }
 -  else
 -    {
 -      /* If overflow does not wrap, saturate to the types min/max
 -       value.  */
 -      wide_int type_min = wi::min_value (prec, sgn);
 -      wide_int type_max = wi::max_value (prec, sgn);
 -      kind = VR_RANGE;
 -      if (min_ovf == wi::OVF_UNDERFLOW)
 -      min = wide_int_to_tree (type, type_min);
 -      else if (min_ovf == wi::OVF_OVERFLOW)
 -      min = wide_int_to_tree (type, type_max);
 -      else
 -      min = wide_int_to_tree (type, wmin);
 -
 -      if (max_ovf == wi::OVF_UNDERFLOW)
 -      max = wide_int_to_tree (type, type_min);
 -      else if (max_ovf == wi::OVF_OVERFLOW)
 -      max = wide_int_to_tree (type, type_max);
 -      else
 -      max = wide_int_to_tree (type, wmax);
 +      vr->set_varying (expr_type);
 +      return true;
      }
 +  return false;
  }
  
- /* Extract range information from a PLUS_EXPR or MINUS_EXPR based on
-    the ranges of each of its operands *VR0 and *VR1 with resulting
-    type EXPR_TYPE.  The resulting range is stored in *VR.  */
- static void
- extract_range_from_plus_expr (value_range_base *vr,
-                             enum tree_code code, tree expr_type,
-                             const value_range_base *vr0,
-                             const value_range_base *vr1)
- {
-   gcc_assert (code == PLUS_EXPR || code == MINUS_EXPR);
-   enum value_range_kind type;
-   tree min = NULL, max = NULL;
-   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_kind = VR_RANGE;
-       vr0_min = vrp_val_min (expr_type);
-       vr0_max = vrp_val_max (expr_type);
-     }
-   if (vr1->varying_p ())
-     {
-       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 sym_min_op0 = NULL_TREE;
-   tree sym_min_op1 = NULL_TREE;
-   tree sym_max_op0 = NULL_TREE;
-   tree sym_max_op1 = NULL_TREE;
-   bool neg_min_op0, neg_min_op1, neg_max_op0, neg_max_op1;
-   neg_min_op0 = neg_min_op1 = neg_max_op0 = neg_max_op1 = false;
-   /* If we have a PLUS or MINUS with two VR_RANGEs, either constant or
-      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
-       && (TREE_CODE (min_op0) == INTEGER_CST
-         || (sym_min_op0
-             = get_single_symbol (min_op0, &neg_min_op0, &min_op0)))
-       && (TREE_CODE (min_op1) == INTEGER_CST
-         || (sym_min_op1
-             = get_single_symbol (min_op1, &neg_min_op1, &min_op1)))
-       && (!(sym_min_op0 && sym_min_op1)
-         || (sym_min_op0 == sym_min_op1
-             && neg_min_op0 == (minus_p ? neg_min_op1 : !neg_min_op1)))
-       && (TREE_CODE (max_op0) == INTEGER_CST
-         || (sym_max_op0
-             = get_single_symbol (max_op0, &neg_max_op0, &max_op0)))
-       && (TREE_CODE (max_op1) == INTEGER_CST
-         || (sym_max_op1
-             = get_single_symbol (max_op1, &neg_max_op1, &max_op1)))
-       && (!(sym_max_op0 && sym_max_op1)
-         || (sym_max_op0 == sym_max_op1
-             && neg_max_op0 == (minus_p ? neg_max_op1 : !neg_max_op1))))
-     {
-       wide_int wmin, wmax;
-       wi::overflow_type min_ovf = wi::OVF_NONE;
-       wi::overflow_type max_ovf = wi::OVF_NONE;
-       /* Build the bounds.  */
-       combine_bound (code, wmin, min_ovf, expr_type, min_op0, min_op1);
-       combine_bound (code, wmax, max_ovf, expr_type, max_op0, max_op1);
-       /* If we have overflow for the constant part and the resulting
-        range will be symbolic, drop to VR_VARYING.  */
-       if (((bool)min_ovf && sym_min_op0 != sym_min_op1)
-         || ((bool)max_ovf && sym_max_op0 != sym_max_op1))
-       {
-         vr->set_varying (expr_type);
-         return;
-       }
-       adjust_range_for_overflow (type, wmin, wmax, expr_type,
-                                min_ovf, max_ovf,
-                                TYPE_OVERFLOW_WRAPS (expr_type));
-       if (type == VR_VARYING)
-       {
-         vr->set_varying (expr_type);
-         return;
-       }
-       gcc_assert (type != VR_UNDEFINED);
-       min = wide_int_to_tree (expr_type, wmin);
-       max = wide_int_to_tree (expr_type, wmax);
-       /* Build the symbolic bounds if needed.  */
-       adjust_symbolic_bound (min, code, expr_type,
-                            sym_min_op0, sym_min_op1,
-                            neg_min_op0, neg_min_op1);
-       adjust_symbolic_bound (max, code, expr_type,
-                            sym_max_op0, sym_max_op1,
-                            neg_max_op0, neg_max_op1);
-       /* If either MIN or MAX overflowed, then set the resulting range to
-        VARYING.  */
-       if (min == NULL_TREE
-         || TREE_OVERFLOW_P (min)
-         || max == NULL_TREE
-         || TREE_OVERFLOW_P (max))
-       {
-         vr->set_varying (expr_type);
-         return;
-       }
-       int 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.  */
-         vr->set_varying (expr_type);
-       }
-       else
-       vr->set (type, min, max);
-       return;
-     }
-   else
-     {
-       /* For other cases, for example if we have a PLUS_EXPR with two
-        VR_ANTI_RANGEs, drop to VR_VARYING.  It would take more effort
-        to compute a precise range for such a case.
-        ???  General even mixed range kind operations can be expressed
-        by for example transforming ~[3, 5] + [1, 2] to range-only
-        operations and a union primitive:
-        [-INF, 2] + [1, 2]  U  [5, +INF] + [1, 2]
-        [-INF+1, 4]     U    [6, +INF(OVF)]
-        though usually the union is not exactly representable with
-        a single range or anti-range as the above is
-        [-INF+1, +INF(OVF)] intersected with ~[5, 5]
-        but one could use a scheme similar to equivalences for this. */
-       vr->set_varying (expr_type);
-     }
- }
  /* Extract range information from a binary operation CODE based on
     the ranges of each of its operands *VR0 and *VR1 with resulting
     type EXPR_TYPE.  The resulting range is stored in *VR.  */
@@@ -1867,7 -1709,34 +1727,7 @@@ extract_range_from_binary_expr (value_r
            vr->set_varying (expr_type);
        }
        else if (code == POINTER_PLUS_EXPR)
-       handle_symbolics_in_pointer_plus_expr (vr, code, expr_type, &vr0, &vr1);
 -      {
 -        /* For pointer types, we are really only interested in asserting
 -           whether the expression evaluates to non-NULL.
 -           With -fno-delete-null-pointer-checks we need to be more
 -           conservative.  As some object might reside at address 0,
 -           then some offset could be added to it and the same offset
 -           subtracted again and the result would be NULL.
 -           E.g.
 -           static int a[12]; where &a[0] is NULL and
 -           ptr = &a[6];
 -           ptr -= 6;
 -           ptr will be NULL here, even when there is POINTER_PLUS_EXPR
 -           where the first range doesn't include zero and the second one
 -           doesn't either.  As the second operand is sizetype (unsigned),
 -           consider all ranges where the MSB could be set as possible
 -           subtractions where the result might be NULL.  */
 -        if ((!range_includes_zero_p (&vr0)
 -             || !range_includes_zero_p (&vr1))
 -            && !TYPE_OVERFLOW_WRAPS (expr_type)
 -            && (flag_delete_null_pointer_checks
 -                || (range_int_cst_p (&vr1)
 -                    && !tree_int_cst_sign_bit (vr1.max ()))))
 -          vr->set_nonzero (expr_type);
 -        else if (vr0.zero_p () && vr1.zero_p ())
 -          vr->set_zero (expr_type);
 -        else
 -          vr->set_varying (expr_type);
 -      }
++      extract_range_from_pointer_plus_expr (vr, code, expr_type, &vr0, &vr1);
        else if (code == BIT_AND_EXPR)
        {
          /* For pointer types, we are really only interested in asserting
       range and see what we end up with.  */
    if (code == PLUS_EXPR || code == MINUS_EXPR)
      {
-       extract_range_from_plus_expr (vr, code, expr_type, &vr0, &vr1);
-       return;
+       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_kind = VR_RANGE;
+         vr0_min = vrp_val_min (expr_type);
+         vr0_max = vrp_val_max (expr_type);
+       }
+       if (vr1.varying_p ())
+       {
+         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 sym_min_op0 = NULL_TREE;
+       tree sym_min_op1 = NULL_TREE;
+       tree sym_max_op0 = NULL_TREE;
+       tree sym_max_op1 = NULL_TREE;
+       bool neg_min_op0, neg_min_op1, neg_max_op0, neg_max_op1;
+       neg_min_op0 = neg_min_op1 = neg_max_op0 = neg_max_op1 = false;
+       /* If we have a PLUS or MINUS with two VR_RANGEs, either constant or
+        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
+         && (TREE_CODE (min_op0) == INTEGER_CST
+             || (sym_min_op0
+                 = get_single_symbol (min_op0, &neg_min_op0, &min_op0)))
+         && (TREE_CODE (min_op1) == INTEGER_CST
+             || (sym_min_op1
+                 = get_single_symbol (min_op1, &neg_min_op1, &min_op1)))
+         && (!(sym_min_op0 && sym_min_op1)
+             || (sym_min_op0 == sym_min_op1
+                 && neg_min_op0 == (minus_p ? neg_min_op1 : !neg_min_op1)))
+         && (TREE_CODE (max_op0) == INTEGER_CST
+             || (sym_max_op0
+                 = get_single_symbol (max_op0, &neg_max_op0, &max_op0)))
+         && (TREE_CODE (max_op1) == INTEGER_CST
+             || (sym_max_op1
+                 = get_single_symbol (max_op1, &neg_max_op1, &max_op1)))
+         && (!(sym_max_op0 && sym_max_op1)
+             || (sym_max_op0 == sym_max_op1
+                 && neg_max_op0 == (minus_p ? neg_max_op1 : !neg_max_op1))))
+       {
+         wide_int wmin, wmax;
+         wi::overflow_type min_ovf = wi::OVF_NONE;
+         wi::overflow_type max_ovf = wi::OVF_NONE;
+         /* Build the bounds.  */
+         combine_bound (code, wmin, min_ovf, expr_type, min_op0, min_op1);
+         combine_bound (code, wmax, max_ovf, expr_type, max_op0, max_op1);
+         /* If we have overflow for the constant part and the resulting
+            range will be symbolic, drop to VR_VARYING.  */
+         if (((bool)min_ovf && sym_min_op0 != sym_min_op1)
+             || ((bool)max_ovf && sym_max_op0 != sym_max_op1))
+           {
+             vr->set_varying (expr_type);
+             return;
+           }
 -        /* Adjust the range for possible overflow.  */
 -        min = NULL_TREE;
 -        max = NULL_TREE;
 -        set_value_range_with_overflow (type, min, max, expr_type,
 -                                       wmin, wmax, min_ovf, max_ovf);
++        adjust_range_for_overflow (type, wmin, wmax, expr_type,
++                                   min_ovf, max_ovf,
++                                   TYPE_OVERFLOW_WRAPS (expr_type));
+         if (type == VR_VARYING)
+           {
+             vr->set_varying (expr_type);
+             return;
+           }
++        gcc_assert (type != VR_UNDEFINED);
++        min = wide_int_to_tree (expr_type, wmin);
++        max = wide_int_to_tree (expr_type, wmax);
+         /* Build the symbolic bounds if needed.  */
+         adjust_symbolic_bound (min, code, expr_type,
+                                sym_min_op0, sym_min_op1,
+                                neg_min_op0, neg_min_op1);
+         adjust_symbolic_bound (max, code, expr_type,
+                                sym_max_op0, sym_max_op1,
+                                neg_max_op0, neg_max_op1);
+       }
+       else
+       {
+         /* For other cases, for example if we have a PLUS_EXPR with two
+            VR_ANTI_RANGEs, drop to VR_VARYING.  It would take more effort
+            to compute a precise range for such a case.
+            ???  General even mixed range kind operations can be expressed
+            by for example transforming ~[3, 5] + [1, 2] to range-only
+            operations and a union primitive:
+              [-INF, 2] + [1, 2]  U  [5, +INF] + [1, 2]
+                  [-INF+1, 4]     U    [6, +INF(OVF)]
+            though usually the union is not exactly representable with
+            a single range or anti-range as the above is
+                [-INF+1, +INF(OVF)] intersected with ~[5, 5]
+            but one could use a scheme similar to equivalences for this. */
+         vr->set_varying (expr_type);
+         return;
+       }
      }
    else if (code == MIN_EXPR
           || code == MAX_EXPR)
@@@ -2281,353 -2257,6 +2249,353 @@@ extract_range_from_unary_expr (value_ra
    return;
  }
  
-   if (handle_symbolics_in_pointer_plus_expr (vr, code, expr_type, &vr0, &vr1))
 +/* Given two ranges (OLD_VR and NEW_VR) that are the result of
 +   VR0 .OPCODE. VR1, abort if they are not equivalent.  */
 +
 +void
 +assert_compare_value_ranges (const value_range_base *old_vr,
 +                           const value_range_base *new_vr,
 +                           tree_code code,
 +                           const value_range_base *vr0,
 +                           const value_range_base *vr1)
 +{
 +  if (old_vr->equal_p (*new_vr))
 +    return;
 +
 +  /* Now account for any known differences between range-ops and
 +     extract_range_from_*expr.  If we can't account for the difference
 +     between the ranges, fail vewwy woughly.  */
 +
 +  /* Ideally, unsigned [1, MAX] should've been canonicalized as
 +     ~[0, 0], but this causes issues with ranges_from_anti_range.
 +     Special case this for now, and avoid batting the beehive.  */
 +  if (TYPE_UNSIGNED (old_vr->type ())
 +      && integer_onep (old_vr->min ())
 +      && vrp_val_is_max (old_vr->max ())
 +      && new_vr->nonzero_p ())
 +    return;
 +
 +  /* extract_range_from_binary_expr special cases this scenario, and
 +     gives up.  Since range-ops can do better, avoid a false
 +     positive.  */
 +  if (code == EXACT_DIV_EXPR && vr0->nonzero_p ())
 +    return;
 +
 +  /* The ordering in which range-ops and
 +     extract_range_from_binary_expr split up and handle sub-ranges
 +     matters, and this can yield slightly worse results for VRP at
 +     times.  This is because the union of intermediate ranges,
 +     depending on which order they are done in, can yield
 +     unrepresentable ranges that ultimately generate a VARYING.
 +
 +     This is imprecise at best, so avoid comparing pairs of
 +     VR_ANTI_RANGES inputs, for which VRP produces VARYING and
 +     range-ops does better.
 +
 +     For example, extract_range_from_binary_expr, with its recursive
 +     ranges_from_anti_range approach, will handle ~[5,10] OP [20,30]
 +     in this order:
 +
 +      [0,4][11,MAX] OP [0,19][31,MAX]
 +
 +              t1 = [0,4] OP [0,19]
 +              t2 = [0,4] OP [31,MAX]
 +              t3 = union(t1, t2)
 +
 +              t4 = [11,MAX] OP [0,19]
 +              t5 = [11,MAX] OP [31,MAX]
 +              t6 = union(t4, t5)
 +
 +              t = union(t3, t6)
 +
 +     Whereas, range-ops will do:
 +
 +              t = union([0,4] OP [0,19])
 +              t = union(t, union([0,4] OP [31,MAX]))
 +              t = union(t, union([11,MAX] OP [0,19]))
 +              t = union(t, union([11,MAX] OP [31,MAX]))
 +
 +     Ugh.  In the amount of time it took to explain this, I could've
 +     rewritten VRP to match range-ops, but let's avoid touching too
 +     much of existing code.
 +
 +     Triggered by: gcc.target/i386/sse4_2-crc32b.c.  */
 +  if (vr0->kind () == VR_ANTI_RANGE && vr1->kind () == VR_ANTI_RANGE
 +      && old_vr->varying_p ())
 +    return;
 +
 +  /* MAX/MIN of pointers in VRP dumbs everything down to
 +     NULL/NON_NULL/VARYING.  When running range-ops with multiple
 +     sub-ranges, we may get slightly better ranges.  In this case,
 +     pretend we're varying and see if we matched VRP.  */
 +  if ((code == MAX_EXPR || code == MIN_EXPR)
 +      && POINTER_TYPE_P (new_vr->type ())
 +      && !new_vr->zero_p ()
 +      && !new_vr->nonzero_p ()
 +      && old_vr->varying_p ())
 +    return;
 +
 +  /* Sigh.  extract_range_from_binary_expr may refuse to work on
 +     varying ranges for some codes, but range-ops can sometimes derive
 +     useful information.  This is the same check we have in
 +     extract_range_from_binary_expr.  */
 +  if (code != BIT_AND_EXPR
 +      && code != BIT_IOR_EXPR
 +      && code != TRUNC_DIV_EXPR
 +      && code != FLOOR_DIV_EXPR
 +      && code != CEIL_DIV_EXPR
 +      && code != EXACT_DIV_EXPR
 +      && code != ROUND_DIV_EXPR
 +      && code != TRUNC_MOD_EXPR
 +      && code != MIN_EXPR
 +      && code != MAX_EXPR
 +      && code != PLUS_EXPR
 +      && code != MINUS_EXPR
 +      && code != RSHIFT_EXPR
 +      && code != POINTER_PLUS_EXPR
 +      && (vr0->varying_p ()
 +        || vr1->varying_p ()
 +        || vr0->symbolic_p ()
 +        || vr1->symbolic_p ()))
 +    {
 +      /* If VRP was varying, we know we did better.  */
 +      if (old_vr->varying_p ())
 +      return;
 +    }
 +
 +  /* There's an unaccounted difference.  This may be a real bug.  */
 +
 +  tree expr_type = old_vr->type ();
 +  fprintf (stderr, "------------\n");
 +  fprintf (stderr, "Ranges from VRP and range-ops do not agree!\n");
 +  fprintf (stderr, "CODE: %s\n", get_tree_code_name (code));
 +  fprintf (stderr, "TYPE = ");
 +  debug_generic_stmt (expr_type);
 +  if (CONVERT_EXPR_CODE_P (code))
 +    {
 +      fprintf (stderr, "\tFROM TYPE = ");
 +      debug_generic_stmt (vr0->type ());
 +    }
 +  fprintf (stderr, "vr0: ");
 +  vr0->dump (stderr);
 +  fputc ('\n', stderr);
 +  if (TREE_CODE_CLASS (code) != tcc_unary)
 +    {
 +      fprintf (stderr, "vr1: ");
 +      vr1->dump (stderr);
 +      fputc ('\n', stderr);
 +    }
 +  fprintf (stderr, "VRP returned: ");
 +  old_vr->dump (stderr);
 +  fprintf (stderr, "\nrange-ops returned: ");
 +  new_vr->dump (stderr);
 +  fputc ('\n', stderr);
 +  gcc_unreachable();
 +}
 +
 +/* Normalize a value_range for use in range_ops and return it.
 +   Eventually, range-ops should do this for us.  */
 +
 +static value_range_base
 +normalize_for_range_ops (const value_range_base &vr)
 +{
 +  tree type = vr.type ();
 +
 +  /* This will return ~[0,0] for [&var, &var].  */
 +  if (POINTER_TYPE_P (type) && !range_includes_zero_p (&vr))
 +    {
 +      value_range_base temp;
 +      temp.set_nonzero (type);
 +      return temp;
 +    }
 +  if (vr.symbolic_p ())
 +    return normalize_for_range_ops (vr.normalize_symbolics ());
 +  if (TREE_CODE (vr.min ()) == INTEGER_CST
 +      && TREE_CODE (vr.max ()) == INTEGER_CST)
 +    return vr;
 +  /* Anything not strictly numeric at this point becomes varying.  */
 +  return value_range_base (vr.type ());
 +}
 +
 +/* Fold a binary expression of two value_range's with range-ops.  */
 +
 +static void
 +range_ops_fold_binary_expr (value_range_base *vr,
 +                          enum tree_code code,
 +                          tree expr_type,
 +                          const value_range_base *vr0_,
 +                          const value_range_base *vr1_)
 +{
 +  /* Mimic any behavior users of extract_range_from_unary_expr may
 +     expect.  */
 +  range_operator *op = range_op_handler (code);
 +  if (!op)
 +    {
 +      vr->set_varying (expr_type);
 +      return;
 +    }
 +  value_range_base vr0 = *vr0_, vr1 = *vr1_;
 +  if (vr0.undefined_p () && vr1.undefined_p ())
 +    {
 +      vr->set_undefined (expr_type);
 +      return;
 +    }
 +  if (vr0.undefined_p ())
 +    vr0.set_varying (expr_type);
 +  else if (vr1.undefined_p ())
 +    vr1.set_varying (expr_type);
 +
 +  /* Handle symbolics.  Worth moving into range-ops?? */
 +  if ((code == PLUS_EXPR || code == MINUS_EXPR)
 +      && (vr0.symbolic_p () || vr1.symbolic_p ()))
 +    {
 +      /* Pass on down until we handle anti-ranges in
 +       extract_range_from_plus_expr.  */
 +      extract_range_from_binary_expr (vr, code, expr_type, &vr0, &vr1);
 +      return;
 +    }
++  if (extract_range_from_pointer_plus_expr (vr, code, expr_type, &vr0, &vr1))
 +    return;
 +
 +  /* Do the range-ops dance.  */
 +  value_range_base n0 = normalize_for_range_ops (vr0);
 +  value_range_base n1 = normalize_for_range_ops (vr1);
 +#if USE_IRANGE
 +  irange ir;
 +  op->fold_range (ir, n0, n1);
 +  *vr = ir;
 +#else
 +  op->fold_range (*vr, n0, n1);
 +#endif
 +}
 +
 +/* Fold a unary expression of a value_range with range-ops.  */
 +
 +static void
 +range_ops_fold_unary_expr (value_range_base *vr,
 +                         enum tree_code code, tree expr_type,
 +                         const value_range_base *vr0)
 +{
 +  /* Mimic any behavior users of extract_range_from_unary_expr may
 +     expect.  */
 +  range_operator *op = range_op_handler (code);
 +  if (!op)
 +    {
 +      vr->set_varying (expr_type);
 +      return;
 +    }
 +  if (vr0->undefined_p ())
 +    {
 +      vr->set_undefined (expr_type);
 +      return;
 +    }
 +
 +  /* Handle symbolics.  Worth moving into range-ops?? */
 +  if (code == NEGATE_EXPR && vr0->symbolic_p ())
 +    {
 +      /* -X is simply 0 - X.  */
 +      value_range_base zero;
 +      zero.set_zero (vr0->type ());
 +      range_ops_fold_binary_expr (vr, MINUS_EXPR, expr_type, &zero, vr0);
 +      return;
 +    }
 +  if (code == BIT_NOT_EXPR && vr0->symbolic_p ())
 +    {
 +      /* ~X is simply -1 - X.  */
 +      value_range_base minusone;
 +      minusone.set (build_int_cst (vr0->type (), -1));
 +      range_ops_fold_binary_expr (vr, MINUS_EXPR, expr_type, &minusone, vr0);
 +      return;
 +    }
 +  if (CONVERT_EXPR_CODE_P (code) && (POINTER_TYPE_P (expr_type)
 +                                   || POINTER_TYPE_P (vr0->type ())))
 +    {
 +      /* This handles symbolic conversions such such as [25, x_4].  */
 +      if (!range_includes_zero_p (vr0))
 +      vr->set_nonzero (expr_type);
 +      else if (vr0->zero_p ())
 +      vr->set_zero (expr_type);
 +      else
 +      vr->set_varying (expr_type);
 +      return;
 +    }
 +
 +
 +  /* Do the range-ops dance.  */
 +  value_range_base n0 = normalize_for_range_ops (*vr0);
 +  value_range_base n1 (expr_type);
 +#if USE_IRANGE
 +  irange ir;
 +  op->fold_range (ir, n0, n1);
 +  *vr = ir;
 +#else
 +  op->fold_range (*vr, n0, n1);
 +#endif
 +}
 +
 +/* Generic folding of a binary expression between two value_ranges.
 +   Uses range-ops and extract_range_from_binary_expr, and verifies
 +   that the results match.  */
 +
 +void
 +range_fold_binary_expr (value_range_base *vr,
 +                      enum tree_code code,
 +                      tree expr_type,
 +                      const value_range_base *vr0,
 +                      const value_range_base *vr1)
 +{
 +  if (!value_range_base::supports_type_p (expr_type)
 +      || !value_range_base::supports_type_p (vr0->type ())
 +      || !value_range_base::supports_type_p (vr1->type ()))
 +    {
 +      *vr = value_range (expr_type);
 +      return;
 +    }
 +  if (flag_ranges_mode & RANGES_RANGE_OPS)
 +    range_ops_fold_binary_expr (vr, code, expr_type, vr0, vr1);
 +  if (flag_ranges_mode & RANGES_VRP)
 +    {
 +      value_range_base old;
 +      extract_range_from_binary_expr (&old, code, expr_type, vr0, vr1);
 +      if (flag_ranges_mode & RANGES_CHECKING)
 +      assert_compare_value_ranges (&old, vr, code, vr0, vr1);
 +      else
 +      *vr = old;
 +    }
 +}
 +
 +/* Generic folding of a unary expression of a value_range.  Uses
 +   range-ops and extract_range_from_unary_expr, and verifies that the
 +   results match.  */
 +
 +void
 +range_fold_unary_expr (value_range_base *vr,
 +                     enum tree_code code,
 +                     tree expr_type,
 +                     const value_range_base *vr0)
 +{
 +  if (!value_range_base::supports_type_p (expr_type)
 +      || !value_range_base::supports_type_p (vr0->type ()))
 +    {
 +      *vr = value_range (expr_type);
 +      return;
 +    }
 +  if (flag_ranges_mode & RANGES_RANGE_OPS)
 +    range_ops_fold_unary_expr (vr, code, expr_type, vr0);
 +  if (flag_ranges_mode & RANGES_VRP)
 +    {
 +      value_range_base old;
 +      extract_range_from_unary_expr (&old, code, expr_type, vr0, vr0->type ());
 +      if (flag_ranges_mode & RANGES_CHECKING)
 +      {
 +        value_range_base vr1 (expr_type);
 +        assert_compare_value_ranges (&old, vr, code, vr0, &vr1);
 +      }
 +      else
 +      *vr = old;
 +    }
 +}
 +
  /* Given a COND_EXPR COND of the form 'V OP W', and an SSA name V,
     create a new SSA name N and return the assertion assignment
     'N = ASSERT_EXPR <V, V OP W>'.  */
@@@ -6614,9 -6245,9 +6584,9 @@@ value_range_base::union_helper (const v
    /* Work on a temporary so we can still use vr0 when union returns varying.  */
    value_range_base tem;
    if (vr0type == VR_UNDEFINED)
 -    tem.set_undefined ();
 +    tem.set_undefined (TREE_TYPE (vr0->min ()));
    else if (vr0type == VR_VARYING)
-     tem.set_varying (TREE_TYPE (vr0->min ()));
+     tem.set_varying (vr0->type ());
    else
      tem.set (vr0type, vr0min, vr0max);
  
diff --cc gcc/tree-vrp.h
index 32eb856e7faacbd777b1a9b4fa33ed6b1aa62d18,c879a8c6df87fbd8c0914129778c201b71097586..ba60f47ef0a8b955520462a18ddb854e4b6d7ff7
@@@ -56,8 -58,8 +56,8 @@@ public
    bool constant_p () const;
    bool undefined_p () const;
    bool varying_p () const;
-   void set_varying (tree);
+   void set_varying (tree type);
 -  void set_undefined ();
 +  void set_undefined (tree = NULL);
  
    void union_ (const value_range_base *);
    void intersect (const value_range_base *);
    bool nonzero_p () const;
    bool singleton_p (tree *result = NULL) const;
    void dump (FILE *) const;
+   void dump () const;
+   static bool supports_type_p (tree);
+   value_range_base normalize_symbolics () const;
  
-   static bool supports_type_p (tree type);
 +  /* Support machinery for irange.  */
 +  static const unsigned int m_max_pairs = 2;
-   void dump () const;
-   value_range_base normalize_symbolics () const;
 +  static bool supports_ssa_p (tree ssa);
 +  static bool supports_p (tree expr);
 +  void cast (tree);
 +  bool contains_p (tree) const;
 +  unsigned num_pairs () const;
 +  wide_int lower_bound (unsigned = 0) const;
 +  wide_int upper_bound (unsigned) const;
 +  wide_int upper_bound () const;
 +  void invert ();
 +  void union_ (const value_range_base &);
 +  void intersect (const value_range_base &);
 +
  protected:
    void check ();
    static value_range_base union_helper (const value_range_base *,
diff --cc gcc/vr-values.c
index 21c1f930c33c839cb8f09f82140b6148f2f8dd54,6f9a3612931cbff15612b6266844295ea7ef1184..7a9639f476ec924a03aac8a3cae9bee6a47a1ea0
@@@ -46,96 -46,8 +46,96 @@@ along with GCC; see the file COPYING3
  #include "case-cfn-macros.h"
  #include "alloc-pool.h"
  #include "attribs.h"
 +#include "range.h"
  #include "vr-values.h"
  #include "cfghooks.h"
-   value_range *vr = get_value_range (op);
 +#include "range-op.h"
 +#include "wide-int-range.h"
 +
 +
 +/* Cache VARYING value_ranges indexed by type.  */
 +class type_range_cache
 +{
 +public:
 +  type_range_cache ();
 +  ~type_range_cache ();
 +  value_range *varying_range (tree type);
 +private:
 +  value_range *new_varying (tree type);
 +  hash_map<tree, value_range *> *m_type_table;
 +  obstack m_range_obj;
 +};
 +
 +/* Delete type cache.  */
 +type_range_cache::~type_range_cache ()
 +{
 +  delete m_type_table;
 +  obstack_free (&m_range_obj, NULL);
 +}
 +
 +/* Create a new type cache.  */
 +type_range_cache::type_range_cache ()
 +{
 +  /* Allocate a map and a local obstack.  */
 +  m_type_table = new hash_map<tree, value_range *>;
 +  gcc_obstack_init (&m_range_obj);
 +}
 +
 +/* Allocate a new range from the obstack and set it to VARYING for TYPE.  */
 +inline value_range *
 +type_range_cache::new_varying (tree type)
 +{
 +  /* Allocate memory.  */
 +  void *p = XOBNEW (&m_range_obj, value_range);
 +  /* Invoke the constructors on the memory using placement new.  */
 +  value_range *new_p = new (p) value_range ();
 +  /* Initialize it to varying.  */
 +  new_p->set_varying (type);
 +  return new_p;
 +}
 +
 +/* Return a varying object for TYPE.  If it already exists, return it.
 +   Otherwise allocate a new one and register it in the table.  */
 +value_range *
 +type_range_cache::varying_range (tree type)
 +{
 +  bool existed;
 +  value_range *&slot = m_type_table->get_or_insert (type, &existed);
 +  if (!existed)
 +    slot = new_varying (type);
 +  else
 +    {
 +      /* Sanity check to ensure this varying hasn't been modified.  */
 +      value_range v;
 +      v.set_varying (type);
 +      gcc_checking_assert (v.equal_p (*slot, true));
 +    }
 +  return slot;
 +}
 +
 +/* Convert the value_range in this object to an irange.  This function
 +   will normalize non-constant ranges into constant ranges by
 +   degrading them to VARYING.  */
 +
 +irange
 +vr_values::get_irange (tree op, gimple *stmt ATTRIBUTE_UNUSED)
 +{
 +  if (TREE_CODE (op) == INTEGER_CST)
 +    return irange (op, op);
 +
 +  if (TREE_CODE (op) != SSA_NAME)
 +    return irange (TREE_TYPE (op));
 +
++  const value_range *vr = get_value_range (op);
 +  /* Degrade all symbolics and non-constants into VARYING.  This will
 +     downgrade things like [0, "a"], etc.  */
 +  if (vr->symbolic_p ()
 +      || ((vr->kind () == VR_RANGE || vr->kind () == VR_ANTI_RANGE)
 +        && !vr->constant_p ()))
 +    return irange (TREE_TYPE (op));
 +
 +  return *vr;
 +}
  
  /* Set value range VR to a non-negative range of type TYPE.  */
  
@@@ -1799,8 -1743,8 +1827,8 @@@ compare_range_with_value (enum tree_cod
     for VAR.  If so, update VR with the new limits.  */
  
  void
- range_misc::adjust_range_with_loop (irange &ir, struct loop *loop,
 -vr_values::adjust_range_with_scev (value_range *vr, class loop *loop,
--                                 gimple *stmt, tree var)
++range_misc::adjust_range_with_loop (irange &ir, class loop *loop,
++                                  gimple *stmt, tree var)
  {
    tree init, step, chrec, tmin, tmax, min, max, type, tem;
    enum ev_direction dir;
@@@ -2718,7 -2638,7 +2747,8 @@@ vr_values::vrp_visit_cond_stmt (gcond *
     Returns true if the default label is not needed.  */
  
  static bool
- find_case_label_ranges (gswitch *stmt, value_range_base *vr, size_t *min_idx1,
 -find_case_label_ranges (gswitch *stmt, const value_range *vr, size_t *min_idx1,
++find_case_label_ranges (gswitch *stmt, const value_range_base *vr,
++                      size_t *min_idx1,
                        size_t *max_idx1, size_t *min_idx2,
                        size_t *max_idx2)
  {
@@@ -3683,14 -3660,10 +3713,14 @@@ vr_values::simplify_cond_using_ranges_
          && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (innerop)
          && desired_pro_or_demotion_p (TREE_TYPE (innerop), TREE_TYPE (op0)))
        {
-         value_range *vr = get_value_range (innerop);
+         const value_range *vr = get_value_range (innerop);
 +        irange ir;
 +
 +        if (range_int_cst_p (vr))
 +          ir = *vr;
  
 -        if (range_int_cst_p (vr)
 -            && range_fits_type_p (vr,
 +        if (!ir.undefined_p ()
 +            && range_fits_type_p (ir,
                                    TYPE_PRECISION (TREE_TYPE (op0)),
                                    TYPE_SIGN (TREE_TYPE (op0)))
              && int_fits_type_p (op1, TREE_TYPE (innerop)))
@@@ -3717,8 -3690,7 +3747,8 @@@ boo
  vr_values::simplify_switch_using_ranges (gswitch *stmt)
  {
    tree op = gimple_switch_index (stmt);
 -  const value_range *vr = NULL;
 +  value_range_base vr_obj;
-   value_range_base *vr = NULL;
++  const value_range_base *vr = NULL;
    bool take_default;
    edge e;
    edge_iterator ei;
diff --cc gcc/vr-values.h
index 29b35d0f2ea7a614f620ed764e019f4f35c72d31,ec65de3dab73912119941a3a14fe8a8c23f0d3bb..ea4c6b6e3baa36e45870b4cabe96b14be07a1e52
@@@ -76,14 -40,15 +76,16 @@@ class vr_values : public range_mis
    vr_values (void);
    ~vr_values (void);
  
-   value_range *get_value_range (const_tree);
+   const value_range *get_value_range (const_tree);
    void set_vr_value (tree, value_range *);
+   value_range *swap_vr_value (tree, value_range *);
+   void set_def_to_varying (const_tree);
    void set_defs_to_varying (gimple *);
    bool update_value_range (const_tree, value_range *);
 -  tree op_with_constant_singleton_value_range (tree);
 -  void adjust_range_with_scev (value_range *, class loop *, gimple *, tree);
 +  tree singleton (tree, gimple *);
-   void adjust_range_with_scev (value_range_base *, struct loop *, gimple *,
++  void adjust_range_with_scev (value_range_base *, class loop *, gimple *,
 +                             tree);
    tree vrp_evaluate_conditional (tree_code, tree, tree, gimple *);
    void dump_all_value_ranges (FILE *);
  
    void cleanup_edges_and_switches (void);
  
   private:
 +  irange get_irange (tree, gimple *);
+   value_range *get_lattice_entry (const_tree);
    bool vrp_stmt_computes_nonzero (gimple *);
    bool op_with_boolean_value_range_p (tree);
-   value_range *get_vr_for_comparison (int, value_range *);
 -  bool check_for_binary_op_overflow (enum tree_code, tree, tree, tree, bool *);
+   const value_range *get_vr_for_comparison (int, value_range *);
    tree compare_name_with_value (enum tree_code, tree, tree, bool *, bool);
    tree compare_names (enum tree_code, tree, tree, bool *);
 -  bool two_valued_val_range_p (tree, tree *, tree *);
 -  tree vrp_evaluate_conditional_warnv_with_ops_using_ranges (enum tree_code,
 -                                                           tree, tree,
 -                                                           bool *);
    tree vrp_evaluate_conditional_warnv_with_ops (enum tree_code,
                                                tree, tree, bool,
                                                bool *, bool *);