diff gcc/vr-values.c @ 145:1830386684a0

gcc-9.2.0
author anatofuz
date Thu, 13 Feb 2020 11:34:05 +0900
parents 84e7813d76e9
children
line wrap: on
line diff
--- a/gcc/vr-values.c	Thu Oct 25 07:37:49 2018 +0900
+++ b/gcc/vr-values.c	Thu Feb 13 11:34:05 2020 +0900
@@ -1,5 +1,5 @@
 /* Support routines for Value Range Propagation (VRP).
-   Copyright (C) 2005-2018 Free Software Foundation, Inc.
+   Copyright (C) 2005-2020 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -46,63 +46,61 @@
 #include "case-cfn-macros.h"
 #include "alloc-pool.h"
 #include "attribs.h"
+#include "range.h"
 #include "vr-values.h"
 #include "cfghooks.h"
+#include "range-op.h"
 
 /* Set value range VR to a non-negative range of type TYPE.  */
 
 static inline void
-set_value_range_to_nonnegative (value_range *vr, tree type)
+set_value_range_to_nonnegative (value_range_equiv *vr, tree type)
 {
   tree zero = build_int_cst (type, 0);
-  vr->update (VR_RANGE, zero, vrp_val_max (type));
+  vr->update (zero, vrp_val_max (type));
 }
 
 /* Set value range VR to a range of a truthvalue of type TYPE.  */
 
 static inline void
-set_value_range_to_truthvalue (value_range *vr, tree type)
+set_value_range_to_truthvalue (value_range_equiv *vr, tree type)
 {
   if (TYPE_PRECISION (type) == 1)
-    set_value_range_to_varying (vr);
+    vr->set_varying (type);
   else
-    vr->update (VR_RANGE, build_int_cst (type, 0), build_int_cst (type, 1));
+    vr->update (build_int_cst (type, 0), build_int_cst (type, 1));
 }
 
-
-/* Return value range information for VAR.
-
-   If we have no values ranges recorded (ie, VRP is not running), then
-   return NULL.  Otherwise create an empty range if none existed for VAR.  */
-
-value_range *
-vr_values::get_value_range (const_tree var)
+/* Return the lattice entry for VAR or NULL if it doesn't exist or cannot
+   be initialized.  */
+
+value_range_equiv *
+vr_values::get_lattice_entry (const_tree var)
 {
-  static const value_range vr_const_varying (VR_VARYING, NULL, NULL);
-  value_range *vr;
+  value_range_equiv *vr;
   tree sym;
   unsigned ver = SSA_NAME_VERSION (var);
 
-  /* If we have no recorded ranges, then return NULL.  */
-  if (! vr_value)
-    return NULL;
-
-  /* If we query the range for a new SSA name return an unmodifiable VARYING.
-     We should get here at most from the substitute-and-fold stage which
+  /* If we query the entry for a new SSA name avoid reallocating the lattice
+     since we should get here at most from the substitute-and-fold stage which
      will never try to change values.  */
   if (ver >= num_vr_values)
-    return CONST_CAST (value_range *, &vr_const_varying);
+    return NULL;
 
   vr = vr_value[ver];
   if (vr)
     return vr;
 
-  /* After propagation finished do not allocate new value-ranges.  */
-  if (values_propagated)
-    return CONST_CAST (value_range *, &vr_const_varying);
-
   /* Create a default value range.  */
   vr_value[ver] = vr = vrp_value_range_pool.allocate ();
+
+  /* After propagation finished return varying.  */
+  if (values_propagated)
+    {
+      vr->set_varying (TREE_TYPE (var));
+      return vr;
+    }
+
   vr->set_undefined ();
 
   /* If VAR is a default definition of a parameter, the variable can
@@ -118,30 +116,71 @@
 	  if (POINTER_TYPE_P (TREE_TYPE (sym))
 	      && (nonnull_arg_p (sym)
 		  || get_ptr_nonnull (var)))
-	    set_value_range_to_nonnull (vr, TREE_TYPE (sym));
+	    {
+	      vr->set_nonzero (TREE_TYPE (sym));
+	      vr->equiv_clear ();
+	    }
 	  else if (INTEGRAL_TYPE_P (TREE_TYPE (sym)))
 	    {
-	      wide_int min, max;
-	      value_range_kind rtype = get_range_info (var, &min, &max);
-	      if (rtype == VR_RANGE || rtype == VR_ANTI_RANGE)
-		set_value_range (vr, rtype,
-				 wide_int_to_tree (TREE_TYPE (var), min),
-				 wide_int_to_tree (TREE_TYPE (var), max),
-				 NULL);
-	      else
-		set_value_range_to_varying (vr);
+	      get_range_info (var, *vr);
+	      if (vr->undefined_p ())
+		vr->set_varying (TREE_TYPE (sym));
 	    }
 	  else
-	    set_value_range_to_varying (vr);
+	    vr->set_varying (TREE_TYPE (sym));
 	}
       else if (TREE_CODE (sym) == RESULT_DECL
 	       && DECL_BY_REFERENCE (sym))
-	set_value_range_to_nonnull (vr, TREE_TYPE (sym));
+	{
+	  vr->set_nonzero (TREE_TYPE (sym));
+	  vr->equiv_clear ();
+	}
     }
 
   return vr;
 }
 
+/* Return value range information for VAR.
+
+   If we have no values ranges recorded (ie, VRP is not running), then
+   return NULL.  Otherwise create an empty range if none existed for VAR.  */
+
+const value_range_equiv *
+vr_values::get_value_range (const_tree var)
+{
+  /* If we have no recorded ranges, then return NULL.  */
+  if (!vr_value)
+    return NULL;
+
+  value_range_equiv *vr = get_lattice_entry (var);
+
+  /* Reallocate the lattice if needed.  */
+  if (!vr)
+    {
+      unsigned int old_sz = num_vr_values;
+      num_vr_values = num_ssa_names + num_ssa_names / 10;
+      vr_value = XRESIZEVEC (value_range_equiv *, vr_value, num_vr_values);
+      for ( ; old_sz < num_vr_values; old_sz++)
+        vr_value [old_sz] = NULL;
+
+      /* Now that the lattice has been resized, we should never fail.  */
+      vr = get_lattice_entry (var);
+      gcc_assert (vr);
+    }
+
+  return vr;
+}
+
+/* Set the lattice entry for DEF to VARYING.  */
+
+void
+vr_values::set_def_to_varying (const_tree def)
+{
+  value_range_equiv *vr = get_lattice_entry (def);
+  if (vr)
+    vr->set_varying (TREE_TYPE (def));
+}
+
 /* Set value-ranges of all SSA names defined by STMT to varying.  */
 
 void
@@ -150,12 +189,7 @@
   ssa_op_iter i;
   tree def;
   FOR_EACH_SSA_TREE_OPERAND (def, stmt, i, SSA_OP_DEF)
-    {
-      value_range *vr = get_value_range (def);
-      /* Avoid writing to vr_const_varying get_value_range may return.  */
-      if (!vr->varying_p ())
-	set_value_range_to_varying (vr);
-    }
+    set_def_to_varying (def);
 }
 
 /* Update the value range and equivalence set for variable VAR to
@@ -169,31 +203,28 @@
    is the range object associated with another SSA name.  */
 
 bool
-vr_values::update_value_range (const_tree var, value_range *new_vr)
+vr_values::update_value_range (const_tree var, value_range_equiv *new_vr)
 {
-  value_range *old_vr;
+  value_range_equiv *old_vr;
   bool is_new;
 
   /* If there is a value-range on the SSA name from earlier analysis
      factor that in.  */
   if (INTEGRAL_TYPE_P (TREE_TYPE (var)))
     {
-      wide_int min, max;
-      value_range_kind rtype = get_range_info (var, &min, &max);
-      if (rtype == VR_RANGE || rtype == VR_ANTI_RANGE)
-	{
-	  tree nr_min, nr_max;
-	  nr_min = wide_int_to_tree (TREE_TYPE (var), min);
-	  nr_max = wide_int_to_tree (TREE_TYPE (var), max);
-	  value_range nr;
-	  nr.set_and_canonicalize (rtype, nr_min, nr_max, NULL);
-	  new_vr->intersect (&nr);
-	}
+      value_range_equiv nr;
+      get_range_info (var, nr);
+      if (!nr.undefined_p ())
+	new_vr->intersect (&nr);
     }
 
-  /* Update the value range, if necessary.  */
-  old_vr = get_value_range (var);
-  is_new = *old_vr != *new_vr;
+  /* Update the value range, if necessary.  If we cannot allocate a lattice
+     entry for VAR keep it at VARYING.  This happens when DOM feeds us stmts
+     with SSA names allocated after setting up the lattice.  */
+  old_vr = get_lattice_entry (var);
+  if (!old_vr)
+    return false;
+  is_new = !old_vr->equal_p (*new_vr, /*ignore_equivs=*/false);
 
   if (is_new)
     {
@@ -202,16 +233,21 @@
 	 because VR_RANGE and VR_ANTI_RANGE need to be considered
 	 the same.  We may not have is_new when transitioning to
 	 UNDEFINED.  If old_vr->type is VARYING, we shouldn't be
-	 called.  */
-      if (new_vr->undefined_p ())
+	 called, if we are anyway, keep it VARYING.  */
+      if (old_vr->varying_p ())
 	{
-	  set_value_range_to_varying (old_vr);
-	  set_value_range_to_varying (new_vr);
+	  new_vr->set_varying (TREE_TYPE (var));
+	  is_new = false;
+	}
+      else if (new_vr->undefined_p ())
+	{
+	  old_vr->set_varying (TREE_TYPE (var));
+	  new_vr->set_varying (TREE_TYPE (var));
 	  return true;
 	}
       else
-	set_value_range (old_vr, new_vr->kind (),
-			 new_vr->min (), new_vr->max (), new_vr->equiv ());
+	old_vr->set (new_vr->min (), new_vr->max (), new_vr->equiv (),
+		     new_vr->kind ());
     }
 
   new_vr->equiv_clear ();
@@ -310,14 +346,49 @@
       && gimple_assign_rhs_code (stmt) == ADDR_EXPR)
     {
       tree expr = gimple_assign_rhs1 (stmt);
-      tree base = get_base_address (TREE_OPERAND (expr, 0));
+      poly_int64 bitsize, bitpos;
+      tree offset;
+      machine_mode mode;
+      int unsignedp, reversep, volatilep;
+      tree base = get_inner_reference (TREE_OPERAND (expr, 0), &bitsize,
+				       &bitpos, &offset, &mode, &unsignedp,
+				       &reversep, &volatilep);
 
       if (base != NULL_TREE
 	  && TREE_CODE (base) == MEM_REF
 	  && TREE_CODE (TREE_OPERAND (base, 0)) == SSA_NAME)
 	{
-	  value_range *vr = get_value_range (TREE_OPERAND (base, 0));
-	  if (!range_includes_zero_p (vr))
+	  poly_offset_int off = 0;
+	  bool off_cst = false;
+	  if (offset == NULL_TREE || TREE_CODE (offset) == INTEGER_CST)
+	    {
+	      off = mem_ref_offset (base);
+	      if (offset)
+		off += poly_offset_int::from (wi::to_poly_wide (offset),
+					      SIGNED);
+	      off <<= LOG2_BITS_PER_UNIT;
+	      off += bitpos;
+	      off_cst = true;
+	    }
+	  /* If &X->a is equal to X and X is ~[0, 0], the result is too.
+	     For -fdelete-null-pointer-checks -fno-wrapv-pointer we don't
+	     allow going from non-NULL pointer to NULL.  */
+	  if ((off_cst && known_eq (off, 0))
+	      || (flag_delete_null_pointer_checks
+		  && !TYPE_OVERFLOW_WRAPS (TREE_TYPE (expr))))
+	    {
+	      const value_range_equiv *vr
+		= get_value_range (TREE_OPERAND (base, 0));
+	      if (!range_includes_zero_p (vr))
+		return true;
+	    }
+	  /* If MEM_REF has a "positive" offset, consider it non-NULL
+	     always, for -fdelete-null-pointer-checks also "negative"
+	     ones.  Punt for unknown offsets (e.g. variable ones).  */
+	  if (!TYPE_OVERFLOW_WRAPS (TREE_TYPE (expr))
+	      && off_cst
+	      && known_ne (off, 0)
+	      && (flag_delete_null_pointer_checks || known_gt (off, 0)))
 	    return true;
 	}
     }
@@ -355,7 +426,10 @@
   if (TREE_CODE (op) != SSA_NAME)
     return NULL_TREE;
 
-  return value_range_constant_singleton (get_value_range (op));
+  tree t;
+  if (get_value_range (op)->singleton_p (&t))
+    return t;
+  return NULL;
 }
 
 /* Return true if op is in a boolean [0, 1] value-range.  */
@@ -363,7 +437,7 @@
 bool
 vr_values::op_with_boolean_value_range_p (tree op)
 {
-  value_range *vr;
+  const value_range_equiv *vr;
 
   if (TYPE_PRECISION (TREE_TYPE (op)) == 1)
     return true;
@@ -388,10 +462,10 @@
 vr_values::extract_range_for_var_from_comparison_expr (tree var,
 						       enum tree_code cond_code,
 						       tree op, tree limit,
-						       value_range *vr_p)
+						       value_range_equiv *vr_p)
 {
   tree  min, max, type;
-  value_range *limit_vr;
+  const value_range_equiv *limit_vr;
   type = TREE_TYPE (var);
 
   /* For pointer arithmetic, we only keep track of pointer equality
@@ -400,7 +474,7 @@
   if ((POINTER_TYPE_P (type) && cond_code != NE_EXPR && cond_code != EQ_EXPR)
       || limit == var)
     {
-      set_value_range_to_varying (vr_p);
+      vr_p->set_varying (type);
       return;
     }
 
@@ -465,30 +539,30 @@
          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 (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 (min, max, vr_p->equiv (), VR_ANTI_RANGE);
       else
 	gcc_unreachable ();
     }
   else if (cond_code == EQ_EXPR)
     {
-      enum value_range_kind range_type;
+      enum value_range_kind range_kind;
 
       if (limit_vr)
 	{
-	  range_type = limit_vr->kind ();
+	  range_kind = limit_vr->kind ();
 	  min = limit_vr->min ();
 	  max = limit_vr->max ();
 	}
       else
 	{
-	  range_type = VR_RANGE;
+	  range_kind = VR_RANGE;
 	  min = limit;
 	  max = limit;
 	}
 
-      vr_p->update (range_type, min, max);
+      vr_p->update (min, max, range_kind);
 
       /* When asserting the equality VAR == LIMIT and LIMIT is another
 	 SSA name, the new range will also inherit the equivalence set
@@ -539,7 +613,7 @@
 	  && vrp_val_is_max (max))
 	min = max = limit;
 
-      vr_p->set_and_canonicalize (VR_ANTI_RANGE, min, max, vr_p->equiv ());
+      vr_p->set (min, max, vr_p->equiv (), VR_ANTI_RANGE);
     }
   else if (cond_code == LE_EXPR || cond_code == LT_EXPR)
     {
@@ -560,7 +634,7 @@
 	 all should be optimized away above us.  */
       if (cond_code == LT_EXPR
 	  && compare_values (max, min) == 0)
-	set_value_range_to_varying (vr_p);
+	vr_p->set_varying (TREE_TYPE (min));
       else
 	{
 	  /* For LT_EXPR, we create the range [MIN, MAX - 1].  */
@@ -578,7 +652,7 @@
 		TREE_NO_WARNING (max) = 1;
 	    }
 
-	  vr_p->update (VR_RANGE, min, max);
+	  vr_p->update (min, max);
 	}
     }
   else if (cond_code == GE_EXPR || cond_code == GT_EXPR)
@@ -600,7 +674,7 @@
 	 all should be optimized away above us.  */
       if (cond_code == GT_EXPR
 	  && compare_values (min, max) == 0)
-	set_value_range_to_varying (vr_p);
+	vr_p->set_varying (TREE_TYPE (min));
       else
 	{
 	  /* For GT_EXPR, we create the range [MIN + 1, MAX].  */
@@ -618,7 +692,7 @@
 		TREE_NO_WARNING (min) = 1;
 	    }
 
-	  vr_p->update (VR_RANGE, min, max);
+	  vr_p->update (min, max);
 	}
     }
   else
@@ -632,7 +706,7 @@
    it in *VR_P.  */
 
 void
-vr_values::extract_range_from_assert (value_range *vr_p, tree expr)
+vr_values::extract_range_from_assert (value_range_equiv *vr_p, tree expr)
 {
   tree var = ASSERT_EXPR_VAR (expr);
   tree cond = ASSERT_EXPR_COND (expr);
@@ -678,16 +752,17 @@
     always false.  */
 
 void
-vr_values::extract_range_from_ssa_name (value_range *vr, tree var)
+vr_values::extract_range_from_ssa_name (value_range_equiv *vr, tree var)
 {
-  value_range *var_vr = get_value_range (var);
+  const value_range_equiv *var_vr = get_value_range (var);
 
   if (!var_vr->varying_p ())
     vr->deep_copy (var_vr);
   else
-    set_value_range (vr, VR_RANGE, var, var, NULL);
-
-  vr->equiv_add (var, get_value_range (var), &vrp_equiv_obstack);
+    vr->set (var);
+
+  if (!vr->undefined_p ())
+    vr->equiv_add (var, get_value_range (var), &vrp_equiv_obstack);
 }
 
 /* Extract range information from a binary expression OP0 CODE OP1 based on
@@ -695,7 +770,7 @@
    The resulting range is stored in *VR.  */
 
 void
-vr_values::extract_range_from_binary_expr (value_range *vr,
+vr_values::extract_range_from_binary_expr (value_range_equiv *vr,
 					   enum tree_code code,
 					   tree expr_type, tree op0, tree op1)
 {
@@ -705,16 +780,16 @@
   if (TREE_CODE (op0) == SSA_NAME)
     vr0 = *(get_value_range (op0));
   else if (is_gimple_min_invariant (op0))
-    set_value_range_to_value (&vr0, op0, NULL);
+    vr0.set (op0);
   else
-    set_value_range_to_varying (&vr0);
+    vr0.set_varying (TREE_TYPE (op0));
 
   if (TREE_CODE (op1) == SSA_NAME)
     vr1 = *(get_value_range (op1));
   else if (is_gimple_min_invariant (op1))
-    set_value_range_to_value (&vr1, op1, NULL);
+    vr1.set (op1);
   else
-    set_value_range_to_varying (&vr1);
+    vr1.set_varying (TREE_TYPE (op1));
 
   /* If one argument is varying, we can sometimes still deduce a
      range for the output: any + [3, +INF] is in [MIN+3, +INF].  */
@@ -722,16 +797,12 @@
       && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (op0)))
     {
       if (vr0.varying_p () && !vr1.varying_p ())
-	vr0 = value_range (VR_RANGE,
-			   vrp_val_min (expr_type),
-			   vrp_val_max (expr_type));
+	vr0 = value_range (vrp_val_min (expr_type), vrp_val_max (expr_type));
       else if (vr1.varying_p () && !vr0.varying_p ())
-	vr1 = value_range (VR_RANGE,
-			   vrp_val_min (expr_type),
-			   vrp_val_max (expr_type));
+	vr1 = value_range (vrp_val_min (expr_type), vrp_val_max (expr_type));
     }
 
-  extract_range_from_binary_expr_1 (vr, code, expr_type, &vr0, &vr1);
+  range_fold_binary_expr (vr, code, expr_type, &vr0, &vr1);
 
   /* Set value_range for n in following sequence:
      def = __builtin_memchr (arg, 0, sz)
@@ -761,7 +832,7 @@
 	      wide_int wmax = wi::to_wide (max, TYPE_PRECISION (TREE_TYPE (max)));
 	      tree range_min = build_zero_cst (expr_type);
 	      tree range_max = wide_int_to_tree (expr_type, wmax - 1);
-	      set_value_range (vr, VR_RANGE, range_min, range_max, NULL);
+	      vr->set (range_min, range_max);
 	      return;
 	    }
      }
@@ -782,17 +853,17 @@
 
       /* Try with VR0 and [-INF, OP1].  */
       if (is_gimple_min_invariant (minus_p ? vr0.max () : vr0.min ()))
-	set_value_range (&n_vr1, VR_RANGE, vrp_val_min (expr_type), op1, NULL);
+	n_vr1.set (vrp_val_min (expr_type), op1);
 
       /* Try with VR0 and [OP1, +INF].  */
       else if (is_gimple_min_invariant (minus_p ? vr0.min () : vr0.max ()))
-	set_value_range (&n_vr1, VR_RANGE, op1, vrp_val_max (expr_type), NULL);
+	n_vr1.set (op1, vrp_val_max (expr_type));
 
       /* Try with VR0 and [OP1, OP1].  */
       else
-	set_value_range (&n_vr1, VR_RANGE, op1, op1, NULL);
-
-      extract_range_from_binary_expr_1 (vr, code, expr_type, &vr0, &n_vr1);
+	n_vr1.set (op1, op1);
+
+      range_fold_binary_expr (vr, code, expr_type, &vr0, &n_vr1);
     }
 
   if (vr->varying_p ()
@@ -806,17 +877,17 @@
 
       /* Try with [-INF, OP0] and VR1.  */
       if (is_gimple_min_invariant (minus_p ? vr1.max () : vr1.min ()))
-	set_value_range (&n_vr0, VR_RANGE, vrp_val_min (expr_type), op0, NULL);
+	n_vr0.set (vrp_val_min (expr_type), op0);
 
       /* Try with [OP0, +INF] and VR1.  */
       else if (is_gimple_min_invariant (minus_p ? vr1.min (): vr1.max ()))
-	set_value_range (&n_vr0, VR_RANGE, op0, vrp_val_max (expr_type), NULL);
+	n_vr0.set (op0, vrp_val_max (expr_type));
 
       /* Try with [OP0, OP0] and VR1.  */
       else
-	set_value_range (&n_vr0, VR_RANGE, op0, op0, NULL);
-
-      extract_range_from_binary_expr_1 (vr, code, expr_type, &n_vr0, &vr1);
+	n_vr0.set (op0);
+
+      range_fold_binary_expr (vr, code, expr_type, &n_vr0, &vr1);
     }
 
   /* If we didn't derive a range for MINUS_EXPR, and
@@ -832,7 +903,10 @@
 	  || (vr1.kind () == VR_ANTI_RANGE
 	      && vr1.min () == op0
 	      && vr1.min () == vr1.max ())))
-      set_value_range_to_nonnull (vr, expr_type);
+    {
+      vr->set_nonzero (expr_type);
+      vr->equiv_clear ();
+    }
 }
 
 /* Extract range information from a unary expression CODE OP0 based on
@@ -840,7 +914,8 @@
    The resulting range is stored in *VR.  */
 
 void
-vr_values::extract_range_from_unary_expr (value_range *vr, enum tree_code code,
+vr_values::extract_range_from_unary_expr (value_range_equiv *vr,
+					  enum tree_code code,
 					  tree type, tree op0)
 {
   value_range vr0;
@@ -850,11 +925,11 @@
   if (TREE_CODE (op0) == SSA_NAME)
     vr0 = *(get_value_range (op0));
   else if (is_gimple_min_invariant (op0))
-    set_value_range_to_value (&vr0, op0, NULL);
+    vr0.set (op0);
   else
-    set_value_range_to_varying (&vr0);
-
-  ::extract_range_from_unary_expr (vr, code, type, &vr0, TREE_TYPE (op0));
+    vr0.set_varying (type);
+
+  range_fold_unary_expr (vr, code, type, &vr0, TREE_TYPE (op0));
 }
 
 
@@ -862,31 +937,33 @@
    the ranges of each of its operands and the expression code.  */
 
 void
-vr_values::extract_range_from_cond_expr (value_range *vr, gassign *stmt)
+vr_values::extract_range_from_cond_expr (value_range_equiv *vr, gassign *stmt)
 {
   /* Get value ranges for each operand.  For constant operands, create
      a new value range with the operand to simplify processing.  */
   tree op0 = gimple_assign_rhs2 (stmt);
-  value_range vr0;
+  value_range_equiv tem0;
+  const value_range_equiv *vr0 = &tem0;
   if (TREE_CODE (op0) == SSA_NAME)
-    vr0 = *(get_value_range (op0));
+    vr0 = get_value_range (op0);
   else if (is_gimple_min_invariant (op0))
-    set_value_range_to_value (&vr0, op0, NULL);
+    tem0.set (op0);
   else
-    set_value_range_to_varying (&vr0);
+    tem0.set_varying (TREE_TYPE (op0));
 
   tree op1 = gimple_assign_rhs3 (stmt);
-  value_range vr1;
+  value_range_equiv tem1;
+  const value_range_equiv *vr1 = &tem1;
   if (TREE_CODE (op1) == SSA_NAME)
-    vr1 = *(get_value_range (op1));
+    vr1 = get_value_range (op1);
   else if (is_gimple_min_invariant (op1))
-    set_value_range_to_value (&vr1, op1, NULL);
+    tem1.set (op1);
   else
-    set_value_range_to_varying (&vr1);
+    tem1.set_varying (TREE_TYPE (op1));
 
   /* The resulting value range is the union of the operand ranges */
-  vr->deep_copy (&vr0);
-  vr->union_ (&vr1);
+  vr->deep_copy (vr0);
+  vr->union_ (vr1);
 }
 
 
@@ -894,7 +971,8 @@
    on the range of its operand and the expression code.  */
 
 void
-vr_values::extract_range_from_comparison (value_range *vr, enum tree_code code,
+vr_values::extract_range_from_comparison (value_range_equiv *vr,
+					  enum tree_code code,
 					  tree type, tree op0, tree op1)
 {
   bool sop;
@@ -909,9 +987,9 @@
 	 type.  */
       val = fold_convert (type, val);
       if (is_gimple_min_invariant (val))
-	set_value_range_to_value (vr, val, vr->equiv ());
+	vr->set (val);
       else
-	vr->update (VR_RANGE, val, val);
+	vr->update (val, val);
     }
   else
     /* The result of a comparison is always true or false.  */
@@ -932,16 +1010,16 @@
   if (TREE_CODE (op0) == SSA_NAME)
     vr0 = *get_value_range (op0);
   else if (TREE_CODE (op0) == INTEGER_CST)
-    set_value_range_to_value (&vr0, op0, NULL);
+    vr0.set (op0);
   else
-    set_value_range_to_varying (&vr0);
+    vr0.set_varying (TREE_TYPE (op0));
 
   if (TREE_CODE (op1) == SSA_NAME)
     vr1 = *get_value_range (op1);
   else if (TREE_CODE (op1) == INTEGER_CST)
-    set_value_range_to_value (&vr1, op1, NULL);
+    vr1.set (op1);
   else
-    set_value_range_to_varying (&vr1);
+    vr1.set_varying (TREE_TYPE (op1));
 
   tree vr0min = vr0.min (), vr0max = vr0.max ();
   tree vr1min = vr1.min (), vr1max = vr1.max ();
@@ -1031,7 +1109,7 @@
    Store the result in *VR */
 
 void
-vr_values::extract_range_basic (value_range *vr, gimple *stmt)
+vr_values::extract_range_basic (value_range_equiv *vr, gimple *stmt)
 {
   bool sop;
   tree type = gimple_expr_type (stmt);
@@ -1047,17 +1125,11 @@
       switch (cfn)
 	{
 	case CFN_BUILT_IN_CONSTANT_P:
-	  /* If the call is __builtin_constant_p and the argument is a
-	     function parameter resolve it to false.  This avoids bogus
-	     array bound warnings.
-	     ???  We could do this as early as inlining is finished.  */
-	  arg = gimple_call_arg (stmt, 0);
-	  if (TREE_CODE (arg) == SSA_NAME
-	      && SSA_NAME_IS_DEFAULT_DEF (arg)
-	      && TREE_CODE (SSA_NAME_VAR (arg)) == PARM_DECL
-	      && cfun->after_inlining)
+	  /* Resolve calls to __builtin_constant_p after inlining.  */
+	  if (cfun->after_inlining)
 	    {
-	      set_value_range_to_null (vr, type);
+	      vr->set_zero (type);
+	      vr->equiv_clear ();
 	      return;
 	    }
 	  break;
@@ -1071,7 +1143,7 @@
 	  maxi = prec;
 	  if (TREE_CODE (arg) == SSA_NAME)
 	    {
-	      value_range *vr0 = get_value_range (arg);
+	      const value_range_equiv *vr0 = get_value_range (arg);
 	      /* If arg is non-zero, then ffs or popcount are non-zero.  */
 	      if (range_includes_zero_p (vr0) == 0)
 		mini = 1;
@@ -1109,7 +1181,7 @@
 	    mini = -2;
 	  if (TREE_CODE (arg) == SSA_NAME)
 	    {
-	      value_range *vr0 = get_value_range (arg);
+	      const value_range_equiv *vr0 = get_value_range (arg);
 	      /* From clz of VR_RANGE minimum we can compute
 		 result maximum.  */
 	      if (vr0->kind () == VR_RANGE
@@ -1166,7 +1238,7 @@
 	    }
 	  if (TREE_CODE (arg) == SSA_NAME)
 	    {
-	      value_range *vr0 = get_value_range (arg);
+	      const value_range_equiv *vr0 = get_value_range (arg);
 	      /* If arg is non-zero, then use [0, prec - 1].  */
 	      if ((vr0->kind () == VR_RANGE
 		   && integer_nonzerop (vr0->min ()))
@@ -1198,8 +1270,7 @@
 	  maxi = prec - 1;
 	  goto bitop_builtin;
 	bitop_builtin:
-	  set_value_range (vr, VR_RANGE, build_int_cst (type, mini),
-			   build_int_cst (type, maxi), NULL);
+	  vr->set (build_int_cst (type, mini), build_int_cst (type, maxi));
 	  return;
 	case CFN_UBSAN_CHECK_ADD:
 	  subcode = PLUS_EXPR;
@@ -1226,10 +1297,9 @@
 	      size = targetm.goacc.dim_limit (axis);
 
 	    tree type = TREE_TYPE (gimple_call_lhs (stmt));
-	    set_value_range (vr, VR_RANGE,
-			     build_int_cst (type, is_pos ? 0 : 1),
-			     size ? build_int_cst (type, size - is_pos)
-			          : vrp_val_max (type), NULL);
+	    vr->set(build_int_cst (type, is_pos ? 0 : 1),
+		    size
+		    ? build_int_cst (type, size - is_pos) : vrp_val_max (type));
 	  }
 	  return;
 	case CFN_BUILT_IN_STRLEN:
@@ -1242,8 +1312,13 @@
 		tree max = vrp_val_max (ptrdiff_type_node);
 		wide_int wmax = wi::to_wide (max, TYPE_PRECISION (TREE_TYPE (max)));
 		tree range_min = build_zero_cst (type);
-		tree range_max = wide_int_to_tree (type, wmax - 1);
-		set_value_range (vr, VR_RANGE, range_min, range_max, NULL);
+		/* To account for the terminating NUL, the maximum length
+		   is one less than the maximum array size, which in turn
+		   is one  less than PTRDIFF_MAX (or SIZE_MAX where it's
+		   smaller than the former type).
+		   FIXME: Use max_object_size() - 1 here.  */
+		tree range_max = wide_int_to_tree (type, wmax - 2);
+		vr->set (range_min, range_max);
 		return;
 	      }
 	  break;
@@ -1269,7 +1344,7 @@
 	  if (vr->kind () == VR_RANGE
 	      && (vr->min () == vr->max ()
 		  || operand_equal_p (vr->min (), vr->max (), 0)))
-	    set_value_range_to_varying (vr);
+	    vr->set_varying (vr->type ());
 	  return;
 	}
     }
@@ -1305,8 +1380,8 @@
 		    {
 		      /* This is the boolean return value whether compare and
 			 exchange changed anything or not.  */
-		      set_value_range (vr, VR_RANGE, build_int_cst (type, 0),
-				       build_int_cst (type, 1), NULL);
+		      vr->set (build_int_cst (type, 0),
+			       build_int_cst (type, 1));
 		      return;
 		    }
 		  break;
@@ -1322,15 +1397,13 @@
 		      bool ovf = false;
 		      if (check_for_binary_op_overflow (subcode, type,
 							op0, op1, &ovf))
-			set_value_range_to_value (vr,
-						  build_int_cst (type, ovf),
-						  NULL);
+			vr->set (build_int_cst (type, ovf));
 		      else if (TYPE_PRECISION (type) == 1
 			       && !TYPE_UNSIGNED (type))
-			set_value_range_to_varying (vr);
+			vr->set_varying (type);
 		      else
-			set_value_range (vr, VR_RANGE, build_int_cst (type, 0),
-					 build_int_cst (type, 1), NULL);
+			vr->set (build_int_cst (type, 0),
+				 build_int_cst (type, 1));
 		    }
 		  else if (types_compatible_p (type, TREE_TYPE (op0))
 			   && types_compatible_p (type, TREE_TYPE (op1)))
@@ -1345,7 +1418,7 @@
 		    }
 		  else
 		    {
-		      value_range vr0, vr1;
+		      value_range_equiv vr0, vr1;
 		      bool saved_flag_wrapv = flag_wrapv;
 		      /* Pretend the arithmetics is wrapping.  If there is
 			 any overflow, IMAGPART_EXPR will be set.  */
@@ -1354,8 +1427,7 @@
 						     type, op0);
 		      extract_range_from_unary_expr (&vr1, NOP_EXPR,
 						     type, op1);
-		      extract_range_from_binary_expr_1 (vr, subcode, type,
-							&vr0, &vr1);
+		      range_fold_binary_expr (vr, subcode, type, &vr0, &vr1);
 		      flag_wrapv = saved_flag_wrapv;
 		    }
 		  return;
@@ -1367,9 +1439,12 @@
       && gimple_stmt_nonnegative_warnv_p (stmt, &sop))
     set_value_range_to_nonnegative (vr, type);
   else if (vrp_stmt_computes_nonzero (stmt))
-    set_value_range_to_nonnull (vr, type);
+    {
+      vr->set_nonzero (type);
+      vr->equiv_clear ();
+    }
   else
-    set_value_range_to_varying (vr);
+    vr->set_varying (type);
 }
 
 
@@ -1377,7 +1452,7 @@
    in *VR.  */
 
 void
-vr_values::extract_range_from_assignment (value_range *vr, gassign *stmt)
+vr_values::extract_range_from_assignment (value_range_equiv *vr, gassign *stmt)
 {
   enum tree_code code = gimple_assign_rhs_code (stmt);
 
@@ -1403,9 +1478,9 @@
 				   gimple_assign_rhs2 (stmt));
   else if (get_gimple_rhs_class (code) == GIMPLE_SINGLE_RHS
 	   && is_gimple_min_invariant (gimple_assign_rhs1 (stmt)))
-    set_value_range_to_value (vr, gimple_assign_rhs1 (stmt), NULL);
+    vr->set (gimple_assign_rhs1 (stmt));
   else
-    set_value_range_to_varying (vr);
+    vr->set_varying (TREE_TYPE (gimple_assign_lhs (stmt)));
 
   if (vr->varying_p ())
     extract_range_basic (vr, stmt);
@@ -1426,8 +1501,8 @@
 
 
 static tree
-compare_ranges (enum tree_code comp, value_range *vr0, value_range *vr1,
-		bool *strict_overflow_p)
+compare_ranges (enum tree_code comp, const value_range_equiv *vr0,
+		const value_range_equiv *vr1, bool *strict_overflow_p)
 {
   /* VARYING or UNDEFINED ranges cannot be compared.  */
   if (vr0->varying_p ()
@@ -1454,12 +1529,8 @@
       /* Equality can be computed only between a range and an
 	 anti-range.  ~[VAL1, VAL2] == [VAL1, VAL2] is always false.  */
       if (vr0->kind () == VR_RANGE)
-	{
-	  /* To simplify processing, make VR0 the anti-range.  */
-	  value_range *tmp = vr0;
-	  vr0 = vr1;
-	  vr1 = tmp;
-	}
+	/* To simplify processing, make VR0 the anti-range.  */
+	std::swap (vr0, vr1);
 
       gcc_assert (comp == NE_EXPR || comp == EQ_EXPR);
 
@@ -1565,8 +1636,8 @@
    assumed signed overflow is undefined.  */
 
 static tree
-compare_range_with_value (enum tree_code comp, value_range *vr, tree val,
-			  bool *strict_overflow_p)
+compare_range_with_value (enum tree_code comp, const value_range_equiv *vr,
+			  tree val, bool *strict_overflow_p)
 {
   if (vr->varying_p () || vr->undefined_p ())
     return NULL_TREE;
@@ -1583,7 +1654,7 @@
 	return NULL_TREE;
 
       /* ~[VAL_1, VAL_2] OP VAL is known if VAL_1 <= VAL <= VAL_2.  */
-      if (value_inside_range (val, vr->min (), vr->max ()) == 1)
+      if (!vr->may_contain_p (val))
 	return (comp == NE_EXPR) ? boolean_true_node : boolean_false_node;
 
       return NULL_TREE;
@@ -1669,7 +1740,7 @@
    for VAR.  If so, update VR with the new limits.  */
 
 void
-vr_values::adjust_range_with_scev (value_range *vr, struct loop *loop,
+vr_values::adjust_range_with_scev (value_range_equiv *vr, class loop *loop,
 				   gimple *stmt, tree var)
 {
   tree init, step, chrec, tmin, tmax, min, max, type, tem;
@@ -1685,7 +1756,7 @@
   /* Like in PR19590, scev can return a constant function.  */
   if (is_gimple_min_invariant (chrec))
     {
-      set_value_range_to_value (vr, chrec, vr->equiv ());
+      vr->set (chrec);
       return;
     }
 
@@ -1742,7 +1813,6 @@
 	 the number of latch executions is the correct thing to use.  */
       if (max_loop_iterations (loop, &nit))
 	{
-	  value_range maxvr;
 	  signop sgn = TYPE_SIGN (TREE_TYPE (step));
 	  wi::overflow_type overflow;
 
@@ -1758,6 +1828,7 @@
 	      && (sgn == UNSIGNED
 		  || wi::gts_p (wtmp, 0) == wi::gts_p (wi::to_wide (step), 0)))
 	    {
+	      value_range_equiv maxvr;
 	      tem = wide_int_to_tree (TREE_TYPE (init), wtmp);
 	      extract_range_from_binary_expr (&maxvr, PLUS_EXPR,
 					      TREE_TYPE (init), init, tem);
@@ -1769,7 +1840,7 @@
 		  if (TREE_CODE (init) == SSA_NAME)
 		    initvr = *(get_value_range (init));
 		  else if (is_gimple_min_invariant (init))
-		    set_value_range_to_value (&initvr, init, NULL);
+		    initvr.set (init);
 		  else
 		    return;
 
@@ -1849,7 +1920,7 @@
   if (TREE_OVERFLOW_P (max))
     max = drop_tree_overflow (max);
 
-  vr->update (VR_RANGE, min, max);
+  vr->update (min, max);
 }
 
 /* Dump value ranges of all SSA_NAMEs to FILE.  */
@@ -1878,8 +1949,8 @@
 vr_values::vr_values () : vrp_value_range_pool ("Tree VRP value ranges")
 {
   values_propagated = false;
-  num_vr_values = num_ssa_names;
-  vr_value = XCNEWVEC (value_range *, num_vr_values);
+  num_vr_values = num_ssa_names * 2;
+  vr_value = XCNEWVEC (value_range_equiv *, num_vr_values);
   vr_phi_edge_counts = XCNEWVEC (int, num_ssa_names);
   bitmap_obstack_initialize (&vrp_equiv_obstack);
   to_remove_edges = vNULL;
@@ -1919,7 +1990,7 @@
 {
   if (TREE_CODE (name) == SSA_NAME)
     {
-      value_range *vr = x_vr_values->get_value_range (name);
+      const value_range_equiv *vr = x_vr_values->get_value_range (name);
       if (vr->kind () == VR_RANGE
 	  && (TREE_CODE (vr->min ()) == SSA_NAME
 	      || is_gimple_min_invariant (vr->min ()))
@@ -1944,7 +2015,7 @@
       if (!gimple_nop_p (def_stmt)
 	  && prop_simulate_again_p (def_stmt))
 	return NULL_TREE;
-      value_range *vr = x_vr_values->get_value_range (name);
+      const value_range_equiv *vr = x_vr_values->get_value_range (name);
       tree singleton;
       if (vr->singleton_p (&singleton))
 	return singleton;
@@ -1980,7 +2051,7 @@
 
 void
 vr_values::vrp_visit_assignment_or_call (gimple *stmt, tree *output_p,
-					 value_range *vr)
+					 value_range_equiv *vr)
 {
   tree lhs = get_output_for_vrp (stmt);
   *output_p = lhs;
@@ -2006,7 +2077,7 @@
 	    }
 	  else if (is_gimple_min_invariant (tem))
 	    {
-	      set_value_range_to_value (vr, tem, NULL);
+	      vr->set (tem);
 	      return;
 	    }
 	}
@@ -2020,18 +2091,22 @@
 
 /* Helper that gets the value range of the SSA_NAME with version I
    or a symbolic range containing the SSA_NAME only if the value range
-   is varying or undefined.  */
-
-value_range
-vr_values::get_vr_for_comparison (int i)
+   is varying or undefined.  Uses TEM as storage for the alternate range.  */
+
+const value_range_equiv *
+vr_values::get_vr_for_comparison (int i, value_range_equiv *tem)
 {
-  value_range vr = *get_value_range (ssa_name (i));
+  /* Shallow-copy equiv bitmap.  */
+  const value_range_equiv *vr = get_value_range (ssa_name (i));
 
   /* If name N_i does not have a valid range, use N_i as its own
      range.  This allows us to compare against names that may
      have N_i in their ranges.  */
-  if (vr.varying_p () || vr.undefined_p ())
-    vr = value_range (VR_RANGE, ssa_name (i), ssa_name (i), NULL);
+  if (vr->varying_p () || vr->undefined_p ())
+    {
+      tem->set (ssa_name (i));
+      return tem;
+    }
 
   return vr;
 }
@@ -2045,51 +2120,46 @@
 vr_values::compare_name_with_value (enum tree_code comp, tree var, tree val,
 				    bool *strict_overflow_p, bool use_equiv_p)
 {
-  bitmap_iterator bi;
-  unsigned i;
-  bitmap e;
-  tree retval, t;
-  int used_strict_overflow;
-  bool sop;
-  value_range equiv_vr;
-
   /* Get the set of equivalences for VAR.  */
-  e = get_value_range (var)->equiv ();
+  bitmap e = get_value_range (var)->equiv ();
 
   /* Start at -1.  Set it to 0 if we do a comparison without relying
      on overflow, or 1 if all comparisons rely on overflow.  */
-  used_strict_overflow = -1;
+  int used_strict_overflow = -1;
 
   /* Compare vars' value range with val.  */
-  equiv_vr = get_vr_for_comparison (SSA_NAME_VERSION (var));
-  sop = false;
-  retval = compare_range_with_value (comp, &equiv_vr, val, &sop);
+  value_range_equiv tem_vr;
+  const value_range_equiv *equiv_vr
+    = get_vr_for_comparison (SSA_NAME_VERSION (var), &tem_vr);
+  bool sop = false;
+  tree retval = compare_range_with_value (comp, equiv_vr, val, &sop);
   if (retval)
     used_strict_overflow = sop ? 1 : 0;
 
   /* If the equiv set is empty we have done all work we need to do.  */
   if (e == NULL)
     {
-      if (retval
-	  && used_strict_overflow > 0)
+      if (retval && used_strict_overflow > 0)
 	*strict_overflow_p = true;
       return retval;
     }
 
+  unsigned i;
+  bitmap_iterator bi;
   EXECUTE_IF_SET_IN_BITMAP (e, 0, i, bi)
     {
       tree name = ssa_name (i);
-      if (! name)
+      if (!name)
 	continue;
 
-      if (! use_equiv_p
-	  && ! SSA_NAME_IS_DEFAULT_DEF (name)
+      if (!use_equiv_p
+	  && !SSA_NAME_IS_DEFAULT_DEF (name)
 	  && prop_simulate_again_p (SSA_NAME_DEF_STMT (name)))
 	continue;
 
-      equiv_vr = get_vr_for_comparison (i);
+      equiv_vr = get_vr_for_comparison (i, &tem_vr);
       sop = false;
-      t = compare_range_with_value (comp, &equiv_vr, val, &sop);
+      tree t = compare_range_with_value (comp, equiv_vr, val, &sop);
       if (t)
 	{
 	  /* If we get different answers from different members
@@ -2111,8 +2181,7 @@
 	}
     }
 
-  if (retval
-      && used_strict_overflow > 0)
+  if (retval && used_strict_overflow > 0)
     *strict_overflow_p = true;
 
   return retval;
@@ -2130,20 +2199,14 @@
 vr_values::compare_names (enum tree_code comp, tree n1, tree n2,
 			  bool *strict_overflow_p)
 {
-  tree t, retval;
-  bitmap e1, e2;
-  bitmap_iterator bi1, bi2;
-  unsigned i1, i2;
-  int used_strict_overflow;
-  static bitmap_obstack *s_obstack = NULL;
-  static bitmap s_e1 = NULL, s_e2 = NULL;
-
   /* Compare the ranges of every name equivalent to N1 against the
      ranges of every name equivalent to N2.  */
-  e1 = get_value_range (n1)->equiv ();
-  e2 = get_value_range (n2)->equiv ();
+  bitmap e1 = get_value_range (n1)->equiv ();
+  bitmap e2 = get_value_range (n2)->equiv ();
 
   /* Use the fake bitmaps if e1 or e2 are not available.  */
+  static bitmap s_e1 = NULL, s_e2 = NULL;
+  static bitmap_obstack *s_obstack = NULL;
   if (s_obstack == NULL)
     {
       s_obstack = XNEW (bitmap_obstack);
@@ -2176,37 +2239,42 @@
 
   /* Start at -1.  Set it to 0 if we do a comparison without relying
      on overflow, or 1 if all comparisons rely on overflow.  */
-  used_strict_overflow = -1;
+  int used_strict_overflow = -1;
 
   /* Otherwise, compare all the equivalent ranges.  First, add N1 and
      N2 to their own set of equivalences to avoid duplicating the body
      of the loop just to check N1 and N2 ranges.  */
+  bitmap_iterator bi1;
+  unsigned i1;
   EXECUTE_IF_SET_IN_BITMAP (e1, 0, i1, bi1)
     {
-      if (! ssa_name (i1))
+      if (!ssa_name (i1))
 	continue;
 
-      value_range vr1 = get_vr_for_comparison (i1);
-
-      t = retval = NULL_TREE;
+      value_range_equiv tem_vr1;
+      const value_range_equiv *vr1 = get_vr_for_comparison (i1, &tem_vr1);
+
+      tree t = NULL_TREE, retval = NULL_TREE;
+      bitmap_iterator bi2;
+      unsigned i2;
       EXECUTE_IF_SET_IN_BITMAP (e2, 0, i2, bi2)
 	{
-	  if (! ssa_name (i2))
+	  if (!ssa_name (i2))
 	    continue;
 
 	  bool sop = false;
 
-	  value_range vr2 = get_vr_for_comparison (i2);
-
-	  t = compare_ranges (comp, &vr1, &vr2, &sop);
+	  value_range_equiv tem_vr2;
+	  const value_range_equiv *vr2 = get_vr_for_comparison (i2, &tem_vr2);
+
+	  t = compare_ranges (comp, vr1, vr2, &sop);
 	  if (t)
 	    {
 	      /* If we get different answers from different members
 		 of the equivalence set this check must be in a dead
 		 code region.  Folding it to a trap representation
 		 would be correct here.  For now just return don't-know.  */
-	      if (retval != NULL
-		  && t != retval)
+	      if (retval != NULL && t != retval)
 		{
 		  bitmap_clear_bit (e1, SSA_NAME_VERSION (n1));
 		  bitmap_clear_bit (e2, SSA_NAME_VERSION (n2));
@@ -2245,8 +2313,7 @@
 vr_values::vrp_evaluate_conditional_warnv_with_ops_using_ranges
     (enum tree_code code, tree op0, tree op1, bool * strict_overflow_p)
 {
-  value_range *vr0, *vr1;
-
+  const value_range_equiv *vr0, *vr1;
   vr0 = (TREE_CODE (op0) == SSA_NAME) ? get_value_range (op0) : NULL;
   vr1 = (TREE_CODE (op1) == SSA_NAME) ? get_value_range (op1) : NULL;
 
@@ -2310,6 +2377,39 @@
 	  op1 = wide_int_to_tree (TREE_TYPE (op0), 0);
 	  code = (code == GT_EXPR || code == GE_EXPR) ? EQ_EXPR : NE_EXPR;
 	}
+      else
+	{
+	  value_range vro, vri;
+	  if (code == GT_EXPR || code == GE_EXPR)
+	    {
+	      vro.set (TYPE_MIN_VALUE (TREE_TYPE (op0)), x, VR_ANTI_RANGE);
+	      vri.set (TYPE_MIN_VALUE (TREE_TYPE (op0)), x);
+	    }
+	  else if (code == LT_EXPR || code == LE_EXPR)
+	    {
+	      vro.set (TYPE_MIN_VALUE (TREE_TYPE (op0)), x);
+	      vri.set (TYPE_MIN_VALUE (TREE_TYPE (op0)), x, VR_ANTI_RANGE);
+	    }
+	  else
+	    gcc_unreachable ();
+	  const value_range_equiv *vr0 = get_value_range (op0);
+	  /* If vro, the range for OP0 to pass the overflow test, has
+	     no intersection with *vr0, OP0's known range, then the
+	     overflow test can't pass, so return the node for false.
+	     If it is the inverted range, vri, that has no
+	     intersection, then the overflow test must pass, so return
+	     the node for true.  In other cases, we could proceed with
+	     a simplified condition comparing OP0 and X, with LE_EXPR
+	     for previously LE_ or LT_EXPR and GT_EXPR otherwise, but
+	     the comments next to the enclosing if suggest it's not
+	     generally profitable to do so.  */
+	  vro.intersect (vr0);
+	  if (vro.undefined_p ())
+	    return boolean_false_node;
+	  vri.intersect (vr0);
+	  if (vri.undefined_p ())
+	    return boolean_true_node;
+	}
     }
 
   if ((ret = vrp_evaluate_conditional_warnv_with_ops_using_ranges
@@ -2331,7 +2431,7 @@
 }
 
 /* Given (CODE OP0 OP1) within STMT, try to simplify it based on value range
-   information.  Return NULL if the conditional can not be evaluated.
+   information.  Return NULL if the conditional cannot be evaluated.
    The ranges of all the names equivalent with the operands in COND
    will be used when trying to compute the value.  If the result is
    based on undefined signed overflow, issue a warning if
@@ -2398,7 +2498,7 @@
 	 always fold regardless of the value of OP0.  If -Wtype-limits
 	 was specified, emit a warning.  */
       tree type = TREE_TYPE (op0);
-      value_range *vr0 = get_value_range (op0);
+      const value_range_equiv *vr0 = get_value_range (op0);
 
       if (vr0->kind () == VR_RANGE
 	  && INTEGRAL_TYPE_P (type)
@@ -2524,9 +2624,9 @@
    Returns true if the default label is not needed.  */
 
 static bool
-find_case_label_ranges (gswitch *stmt, value_range *vr, size_t *min_idx1,
-			size_t *max_idx1, size_t *min_idx2,
-			size_t *max_idx2)
+find_case_label_ranges (gswitch *stmt, const value_range_equiv *vr,
+			size_t *min_idx1, size_t *max_idx1,
+			size_t *min_idx2, size_t *max_idx2)
 {
   size_t i, j, k, l;
   unsigned int n = gimple_switch_num_labels (stmt);
@@ -2538,7 +2638,7 @@
 
   take_default = !find_case_label_range (stmt, min, max, &i, &j);
 
-  /* Set second range to emtpy.  */
+  /* Set second range to empty.  */
   *min_idx2 = 1;
   *max_idx2 = 0;
 
@@ -2604,7 +2704,7 @@
 vr_values::vrp_visit_switch_stmt (gswitch *stmt, edge *taken_edge_p)
 {
   tree op, val;
-  value_range *vr;
+  const value_range_equiv *vr;
   size_t i = 0, j = 0, k, l;
   bool take_default;
 
@@ -2694,7 +2794,7 @@
 
 void
 vr_values::extract_range_from_stmt (gimple *stmt, edge *taken_edge_p,
-				    tree *output_p, value_range *vr)
+				    tree *output_p, value_range_equiv *vr)
 {
 
   if (dump_file && (dump_flags & TDF_DETAILS))
@@ -2718,14 +2818,14 @@
    value ranges, set a new range in VR_RESULT.  */
 
 void
-vr_values::extract_range_from_phi_node (gphi *phi, value_range *vr_result)
+vr_values::extract_range_from_phi_node (gphi *phi,
+					value_range_equiv *vr_result)
 {
-  size_t i;
   tree lhs = PHI_RESULT (phi);
-  value_range *lhs_vr = get_value_range (lhs);
+  const value_range_equiv *lhs_vr = get_value_range (lhs);
   bool first = true;
-  int edges, old_edges;
-  struct loop *l;
+  int old_edges;
+  class loop *l;
 
   if (dump_file && (dump_flags & TDF_DETAILS))
     {
@@ -2734,8 +2834,8 @@
     }
 
   bool may_simulate_backedge_again = false;
-  edges = 0;
-  for (i = 0; i < gimple_phi_num_args (phi); i++)
+  int edges = 0;
+  for (size_t i = 0; i < gimple_phi_num_args (phi); i++)
     {
       edge e = gimple_phi_arg_edge (phi, i);
 
@@ -2749,11 +2849,12 @@
 
       if (e->flags & EDGE_EXECUTABLE)
 	{
-	  tree arg = PHI_ARG_DEF (phi, i);
-	  value_range vr_arg;
+	  value_range_equiv vr_arg_tem;
+	  const value_range_equiv *vr_arg = &vr_arg_tem;
 
 	  ++edges;
 
+	  tree arg = PHI_ARG_DEF (phi, i);
 	  if (TREE_CODE (arg) == SSA_NAME)
 	    {
 	      /* See if we are eventually going to change one of the args.  */
@@ -2763,30 +2864,35 @@
 		  && e->flags & EDGE_DFS_BACK)
 		may_simulate_backedge_again = true;
 
-	      vr_arg = *(get_value_range (arg));
+	      const value_range_equiv *vr_arg_ = get_value_range (arg);
 	      /* Do not allow equivalences or symbolic ranges to leak in from
 		 backedges.  That creates invalid equivalencies.
 		 See PR53465 and PR54767.  */
 	      if (e->flags & EDGE_DFS_BACK)
 		{
-		  if (!vr_arg.varying_p () && !vr_arg.undefined_p ())
+		  if (!vr_arg_->varying_p () && !vr_arg_->undefined_p ())
 		    {
-		      vr_arg.equiv_clear ();
-		      if (vr_arg.symbolic_p ())
-			vr_arg.set_varying ();
+		      vr_arg_tem.set (vr_arg_->min (), vr_arg_->max (), NULL,
+				      vr_arg_->kind ());
+		      if (vr_arg_tem.symbolic_p ())
+			vr_arg_tem.set_varying (TREE_TYPE (arg));
 		    }
+		  else
+		    vr_arg = vr_arg_;
 		}
 	      /* If the non-backedge arguments range is VR_VARYING then
 		 we can still try recording a simple equivalence.  */
-	      else if (vr_arg.varying_p ())
-		vr_arg = value_range (VR_RANGE, arg, arg, NULL);
+	      else if (vr_arg_->varying_p ())
+		vr_arg_tem.set (arg);
+	      else
+		vr_arg = vr_arg_;
 	    }
 	  else
 	    {
 	      if (TREE_OVERFLOW_P (arg))
 		arg = drop_tree_overflow (arg);
 
-	      vr_arg = value_range (VR_RANGE, arg, arg);
+	      vr_arg_tem.set (arg);
 	    }
 
 	  if (dump_file && (dump_flags & TDF_DETAILS))
@@ -2794,14 +2900,14 @@
 	      fprintf (dump_file, "\t");
 	      print_generic_expr (dump_file, arg, dump_flags);
 	      fprintf (dump_file, ": ");
-	      dump_value_range (dump_file, &vr_arg);
+	      dump_value_range (dump_file, vr_arg);
 	      fprintf (dump_file, "\n");
 	    }
 
 	  if (first)
-	    vr_result->deep_copy (&vr_arg);
+	    vr_result->deep_copy (vr_arg);
 	  else
-	    vr_result->union_ (&vr_arg);
+	    vr_result->union_ (vr_arg);
 	  first = false;
 
 	  if (vr_result->varying_p ())
@@ -2859,7 +2965,9 @@
       if (cmp_min < 0)
 	new_min = lhs_vr->min ();
       else if (cmp_min > 0
-	       && !vrp_val_is_min (vr_result->min ()))
+	       && (TREE_CODE (vr_result->min ()) != INTEGER_CST
+		   || tree_int_cst_lt (vrp_val_min (vr_result->type ()),
+				       vr_result->min ())))
 	new_min = int_const_binop (PLUS_EXPR,
 				   vrp_val_min (vr_result->type ()),
 				   build_int_cst (vr_result->type (), 1));
@@ -2868,13 +2976,14 @@
       if (cmp_max > 0)
 	new_max = lhs_vr->max ();
       else if (cmp_max < 0
-	       && !vrp_val_is_max (vr_result->max ()))
+	       && (TREE_CODE (vr_result->max ()) != INTEGER_CST
+		   || tree_int_cst_lt (vr_result->max (),
+				       vrp_val_max (vr_result->type ()))))
 	new_max = int_const_binop (MINUS_EXPR,
 				   vrp_val_max (vr_result->type ()),
 				   build_int_cst (vr_result->type (), 1));
 
-      *vr_result = value_range (vr_result->kind (), new_min, new_max,
-				vr_result->equiv ());
+      vr_result->update (new_min, new_max, vr_result->kind ());
 
       /* If we dropped either bound to +-INF then if this is a loop
 	 PHI node SCEV may known more about its value-range.  */
@@ -2888,7 +2997,7 @@
   goto update_range;
 
 varying:
-  set_value_range_to_varying (vr_result);
+  vr_result->set_varying (TREE_TYPE (lhs));
 
 scev_check:
   /* If this is a loop PHI node SCEV may known more about its value-range.
@@ -2909,7 +3018,7 @@
 	   || compare_values (vr_result->min (), vr_result->max ()) > 0))
     ;
   else
-    set_value_range_to_varying (vr_result);
+    vr_result->set_varying (TREE_TYPE (lhs));
 
   /* If the new range is different than the previous value, keep
      iterating.  */
@@ -3006,7 +3115,7 @@
   tree op1 = gimple_assign_rhs2 (stmt);
   tree op0min = NULL_TREE, op0max = NULL_TREE;
   tree op1min = op1;
-  value_range *vr = NULL;
+  const value_range_equiv *vr = NULL;
 
   if (TREE_CODE (op0) == INTEGER_CST)
     {
@@ -3026,7 +3135,7 @@
   if (rhs_code == TRUNC_MOD_EXPR
       && TREE_CODE (op1) == SSA_NAME)
     {
-      value_range *vr1 = get_value_range (op1);
+      const value_range_equiv *vr1 = get_value_range (op1);
       if (range_int_cst_p (vr1))
 	op1min = vr1->min ();
     }
@@ -3173,7 +3282,7 @@
 vr_values::simplify_abs_using_ranges (gimple_stmt_iterator *gsi, gimple *stmt)
 {
   tree op = gimple_assign_rhs1 (stmt);
-  value_range *vr = get_value_range (op);
+  const value_range_equiv *vr = get_value_range (op);
 
   if (vr)
     {
@@ -3219,6 +3328,30 @@
   return false;
 }
 
+/* value_range wrapper for wi_set_zero_nonzero_bits.
+
+   Return TRUE if VR was a constant range and we were able to compute
+   the bit masks.  */
+
+static bool
+vr_set_zero_nonzero_bits (const tree expr_type,
+			  const value_range *vr,
+			  wide_int *may_be_nonzero,
+			  wide_int *must_be_nonzero)
+{
+  if (range_int_cst_p (vr))
+    {
+      wi_set_zero_nonzero_bits (expr_type,
+				wi::to_wide (vr->min ()),
+				wi::to_wide (vr->max ()),
+				*may_be_nonzero, *must_be_nonzero);
+      return true;
+    }
+  *may_be_nonzero = wi::minus_one (TYPE_PRECISION (expr_type));
+  *must_be_nonzero = wi::zero (TYPE_PRECISION (expr_type));
+  return false;
+}
+
 /* Optimize away redundant BIT_AND_EXPR and BIT_IOR_EXPR.
    If all the bits that are being cleared by & are already
    known to be zero from VR, or all the bits that are being
@@ -3240,22 +3373,22 @@
   if (TREE_CODE (op0) == SSA_NAME)
     vr0 = *(get_value_range (op0));
   else if (is_gimple_min_invariant (op0))
-    set_value_range_to_value (&vr0, op0, NULL);
+    vr0.set (op0);
   else
     return false;
 
   if (TREE_CODE (op1) == SSA_NAME)
     vr1 = *(get_value_range (op1));
   else if (is_gimple_min_invariant (op1))
-    set_value_range_to_value (&vr1, op1, NULL);
+    vr1.set (op1);
   else
     return false;
 
-  if (!vrp_set_zero_nonzero_bits (TREE_TYPE (op0), &vr0, &may_be_nonzero0,
-				  &must_be_nonzero0))
+  if (!vr_set_zero_nonzero_bits (TREE_TYPE (op0), &vr0, &may_be_nonzero0,
+				 &must_be_nonzero0))
     return false;
-  if (!vrp_set_zero_nonzero_bits (TREE_TYPE (op1), &vr1, &may_be_nonzero1,
-				  &must_be_nonzero1))
+  if (!vr_set_zero_nonzero_bits (TREE_TYPE (op1), &vr1, &may_be_nonzero1,
+				 &must_be_nonzero1))
     return false;
 
   switch (gimple_assign_rhs_code (stmt))
@@ -3311,7 +3444,7 @@
 
 static tree
 test_for_singularity (enum tree_code cond_code, tree op0,
-		      tree op1, value_range *vr)
+		      tree op1, const value_range_equiv *vr)
 {
   tree min = NULL;
   tree max = NULL;
@@ -3369,7 +3502,8 @@
    by PRECISION and UNSIGNED_P.  */
 
 static bool
-range_fits_type_p (value_range *vr, unsigned dest_precision, signop dest_sgn)
+range_fits_type_p (const value_range_equiv *vr,
+		   unsigned dest_precision, signop dest_sgn)
 {
   tree src_type;
   unsigned src_precision;
@@ -3433,7 +3567,7 @@
       && INTEGRAL_TYPE_P (TREE_TYPE (op0))
       && is_gimple_min_invariant (op1))
     {
-      value_range *vr = get_value_range (op0);
+      const value_range_equiv *vr = get_value_range (op0);
 
       /* If we have range information for OP0, then we might be
 	 able to simplify this conditional. */
@@ -3536,7 +3670,7 @@
 	  && !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_equiv *vr = get_value_range (innerop);
 
 	  if (range_int_cst_p (vr)
 	      && range_fits_type_p (vr,
@@ -3566,7 +3700,7 @@
 vr_values::simplify_switch_using_ranges (gswitch *stmt)
 {
   tree op = gimple_switch_index (stmt);
-  value_range *vr = NULL;
+  const value_range_equiv *vr = NULL;
   bool take_default;
   edge e;
   edge_iterator ei;
@@ -3866,7 +4000,7 @@
 						   gimple *stmt)
 {
   tree rhs1 = gimple_assign_rhs1 (stmt);
-  value_range *vr = get_value_range (rhs1);
+  const value_range_equiv *vr = get_value_range (rhs1);
   scalar_float_mode fltmode
     = SCALAR_FLOAT_TYPE_MODE (TREE_TYPE (gimple_assign_lhs (stmt)));
   scalar_int_mode mode;
@@ -4029,7 +4163,7 @@
 bool
 vr_values::two_valued_val_range_p (tree var, tree *a, tree *b)
 {
-  value_range *vr = get_value_range (var);
+  const value_range_equiv *vr = get_value_range (var);
   if (vr->varying_p ()
       || vr->undefined_p ()
       || TREE_CODE (vr->min ()) != INTEGER_CST
@@ -4205,11 +4339,23 @@
   return false;
 }
 
+/* Set the lattice entry for VAR to VR.  */
+
 void
-vr_values::set_vr_value (tree var, value_range *vr)
+vr_values::set_vr_value (tree var, value_range_equiv *vr)
 {
   if (SSA_NAME_VERSION (var) >= num_vr_values)
     return;
   vr_value[SSA_NAME_VERSION (var)] = vr;
 }
 
+/* Swap the lattice entry for VAR with VR and return the old entry.  */
+
+value_range_equiv *
+vr_values::swap_vr_value (tree var, value_range_equiv *vr)
+{
+  if (SSA_NAME_VERSION (var) >= num_vr_values)
+    return NULL;
+  std::swap (vr_value[SSA_NAME_VERSION (var)], vr);
+  return vr;
+}