diff --git a/gcc/range-op.cc b/gcc/range-op.cc
index fc0eef998e4..3ab2c665901 100644
--- a/gcc/range-op.cc
+++ b/gcc/range-op.cc
@@ -89,7 +89,8 @@ update_known_bitmask (irange &r, tree_code code,
   bit_value_binop (code, sign, prec, &value, &mask,
 		   lh_sign, lh_prec, lh_value, lh_mask,
 		   rh_sign, rh_prec, rh_value, rh_mask);
-  r.set_nonzero_bits (value | mask);
+  wide_int tmp = wide_int::from (value | mask, prec, sign);
+  r.set_nonzero_bits (tmp);
 }
 
 // Return the upper limit for a type.
diff --git a/gcc/tree-ssanames.cc b/gcc/tree-ssanames.cc
index a510dfa031a..5fdb6a37e9f 100644
--- a/gcc/tree-ssanames.cc
+++ b/gcc/tree-ssanames.cc
@@ -456,7 +456,7 @@ set_ptr_nonnull (tree name)
 /* Update the non-zero bits bitmask of NAME.  */
 
 void
-set_nonzero_bits (tree name, const wide_int_ref &mask)
+set_nonzero_bits (tree name, const wide_int &mask)
 {
   gcc_assert (!POINTER_TYPE_P (TREE_TYPE (name)));
 
diff --git a/gcc/tree-ssanames.h b/gcc/tree-ssanames.h
index b09e71bf779..f3fa609208a 100644
--- a/gcc/tree-ssanames.h
+++ b/gcc/tree-ssanames.h
@@ -58,7 +58,7 @@ struct GTY(()) ptr_info_def
 
 /* Sets the value range to SSA.  */
 extern bool set_range_info (tree, const vrange &);
-extern void set_nonzero_bits (tree, const wide_int_ref &);
+extern void set_nonzero_bits (tree, const wide_int &);
 extern wide_int get_nonzero_bits (const_tree);
 extern bool ssa_name_has_boolean_range (tree);
 extern void init_ssanames (struct function *, int);
diff --git a/gcc/value-range-storage.cc b/gcc/value-range-storage.cc
index 98a6d99af78..7d2de5e8384 100644
--- a/gcc/value-range-storage.cc
+++ b/gcc/value-range-storage.cc
@@ -300,10 +300,7 @@ irange_storage::set_irange (const irange &r)
       write_wide_int (val, len, r.lower_bound (i));
       write_wide_int (val, len, r.upper_bound (i));
     }
-  if (r.m_nonzero_mask)
-    write_wide_int (val, len, wi::to_wide (r.m_nonzero_mask));
-  else
-    write_wide_int (val, len, wi::minus_one (m_precision));
+  write_wide_int (val, len, r.m_nonzero_mask);
 
   if (flag_checking)
     {
@@ -341,17 +338,16 @@ irange_storage::get_irange (irange &r, tree type) const
   gcc_checking_assert (TYPE_PRECISION (type) == m_precision);
   const HOST_WIDE_INT *val = &m_val[0];
   const unsigned char *len = lengths_address ();
-  wide_int w;
 
   // Handle the common case where R can fit the new range.
   if (r.m_max_ranges >= m_num_ranges)
     {
       r.m_kind = VR_RANGE;
       r.m_num_ranges = m_num_ranges;
+      r.m_type = type;
       for (unsigned i = 0; i < m_num_ranges * 2; ++i)
 	{
-	  read_wide_int (w, val, *len, m_precision);
-	  r.m_base[i] = wide_int_to_tree (type, w);
+	  read_wide_int (r.m_base[i], val, *len, m_precision);
 	  val += *len++;
 	}
     }
@@ -370,15 +366,9 @@ irange_storage::get_irange (irange &r, tree type) const
 	  r.union_ (tmp);
 	}
     }
-  read_wide_int (w, val, *len, m_precision);
-  if (w == -1)
-    r.m_nonzero_mask = NULL;
-  else
-    {
-      r.m_nonzero_mask = wide_int_to_tree (type, w);
-      if (r.m_kind == VR_VARYING)
-	r.m_kind = VR_RANGE;
-    }
+  read_wide_int (r.m_nonzero_mask, val, *len, m_precision);
+  if (r.m_kind == VR_VARYING)
+    r.m_kind = VR_RANGE;
 
   if (flag_checking)
     r.verify_range ();
diff --git a/gcc/value-range.cc b/gcc/value-range.cc
index cf694ccaa28..2dc6b98bc63 100644
--- a/gcc/value-range.cc
+++ b/gcc/value-range.cc
@@ -914,6 +914,7 @@ irange::operator= (const irange &src)
     m_base[x - 1] = src.m_base[src.m_num_ranges * 2 - 1];
 
   m_num_ranges = lim;
+  m_type = src.m_type;
   m_kind = src.m_kind;
   m_nonzero_mask = src.m_nonzero_mask;
   if (m_max_ranges == 1)
@@ -963,11 +964,12 @@ get_legacy_range (const irange &r, tree &min, tree &max)
 void
 irange::irange_set (tree type, const wide_int &min, const wide_int &max)
 {
-  m_base[0] = wide_int_to_tree (type, min);
-  m_base[1] = wide_int_to_tree (type, max);
+  m_type = type;
+  m_base[0] = min;
+  m_base[1] = max;
   m_num_ranges = 1;
   m_kind = VR_RANGE;
-  m_nonzero_mask = NULL;
+  m_nonzero_mask = wi::minus_one (TYPE_PRECISION (type));
   normalize_kind ();
 
   if (flag_checking)
@@ -978,28 +980,26 @@ void
 irange::irange_set_1bit_anti_range (tree type,
 				    const wide_int &min, const wide_int &max)
 {
-  gcc_checking_assert (TYPE_PRECISION (type) == 1);
+  unsigned prec = TYPE_PRECISION (type);
+  signop sign = TYPE_SIGN (type);
+  gcc_checking_assert (prec == 1);
 
   if (min == max)
     {
+      wide_int tmp;
       // Since these are 1-bit quantities, they can only be [MIN,MIN]
       // or [MAX,MAX].
-      if (min == wi::to_wide (TYPE_MIN_VALUE (type)))
-	{
-	  wide_int tmp = wi::to_wide (TYPE_MAX_VALUE (type));
-	  set (type, tmp, tmp);
-	}
+      if (min == wi::min_value (prec, sign))
+	tmp = wi::max_value (prec, sign);
       else
-	{
-	  wide_int tmp = wi::to_wide (TYPE_MIN_VALUE (type));
-	  set (type, tmp, tmp);
-	}
+	tmp = wi::min_value (prec, sign);
+      set (type, tmp, tmp);
     }
   else
     {
       // The only alternative is [MIN,MAX], which is the empty range.
-      gcc_checking_assert (min == wi::to_wide (TYPE_MIN_VALUE (type)));
-      gcc_checking_assert (max == wi::to_wide (TYPE_MAX_VALUE (type)));
+      gcc_checking_assert (min == wi::min_value (prec, sign));
+      gcc_checking_assert (max == wi::max_value (prec, sign));
       set_undefined ();
     }
   if (flag_checking)
@@ -1027,8 +1027,8 @@ irange::irange_set_anti_range (tree type,
     {
       wide_int lim1 = wi::sub (min, 1, sign, &ovf);
       gcc_checking_assert (ovf != wi::OVF_OVERFLOW);
-      m_base[0] = wide_int_to_tree (type, type_range.lower_bound (0));
-      m_base[1] = wide_int_to_tree (type, lim1);
+      m_base[0] = type_range.lower_bound (0);
+      m_base[1] = lim1;
       m_num_ranges = 1;
     }
   if (wi::ne_p (max, type_range.upper_bound ()))
@@ -1040,14 +1040,13 @@ irange::irange_set_anti_range (tree type,
 	}
       wide_int lim2 = wi::add (max, 1, sign, &ovf);
       gcc_checking_assert (ovf != wi::OVF_OVERFLOW);
-      m_base[m_num_ranges * 2] = wide_int_to_tree (type, lim2);
-      m_base[m_num_ranges * 2 + 1]
-	= wide_int_to_tree (type, type_range.upper_bound (0));
+      m_base[m_num_ranges * 2] = lim2;
+      m_base[m_num_ranges * 2 + 1] = type_range.upper_bound (0);
       ++m_num_ranges;
     }
 
   m_kind = VR_RANGE;
-  m_nonzero_mask = NULL;
+  m_nonzero_mask = wi::minus_one (TYPE_PRECISION (type));
   normalize_kind ();
 
   if (flag_checking)
@@ -1079,6 +1078,7 @@ irange::set (tree type, const wide_int &rmin, const wide_int &rmax,
       return;
     }
 
+  m_type = type;
   signop sign = TYPE_SIGN (type);
   unsigned prec = TYPE_PRECISION (type);
   wide_int min = wide_int::from (rmin, prec, sign);
@@ -1134,12 +1134,14 @@ irange::verify_range ()
       return;
     }
   gcc_checking_assert (m_num_ranges <= m_max_ranges);
+  unsigned prec = TYPE_PRECISION (m_type);
   if (m_kind == VR_VARYING)
     {
-      gcc_checking_assert (!m_nonzero_mask
-			   || wi::to_wide (m_nonzero_mask) == -1);
+      gcc_checking_assert (m_nonzero_mask == -1);
       gcc_checking_assert (m_num_ranges == 1);
       gcc_checking_assert (varying_compatible_p ());
+      gcc_checking_assert (lower_bound ().get_precision () == prec);
+      gcc_checking_assert (upper_bound ().get_precision () == prec);
       return;
     }
   gcc_checking_assert (m_num_ranges != 0);
@@ -1148,9 +1150,12 @@ irange::verify_range ()
     {
       wide_int lb = lower_bound (i);
       wide_int ub = upper_bound (i);
-      int c = wi::cmp (lb, ub, TYPE_SIGN (type ()));
+      gcc_checking_assert (lb.get_precision () == prec);
+      gcc_checking_assert (ub.get_precision () == prec);
+      int c = wi::cmp (lb, ub, TYPE_SIGN (m_type));
       gcc_checking_assert (c == 0 || c == -1);
     }
+  gcc_checking_assert (m_nonzero_mask.get_precision () == prec);
 }
 
 bool
@@ -1217,9 +1222,9 @@ irange::contains_p (const wide_int &cst) const
     return false;
 
   // See if we can exclude CST based on the nonzero bits.
-  if (m_nonzero_mask
+  if (m_nonzero_mask != -1
       && cst != 0
-      && wi::bit_and (wi::to_wide (m_nonzero_mask), cst) == 0)
+      && wi::bit_and (m_nonzero_mask, cst) == 0)
     return false;
 
   signop sign = TYPE_SIGN (type ());
@@ -1243,17 +1248,18 @@ irange::irange_single_pair_union (const irange &r)
   gcc_checking_assert (!undefined_p () && !varying_p ());
   gcc_checking_assert (!r.undefined_p () && !varying_p ());
 
-  signop sign = TYPE_SIGN (TREE_TYPE (m_base[0]));
+  signop sign = TYPE_SIGN (m_type);
   // Check if current lower bound is also the new lower bound.
-  if (wi::le_p (wi::to_wide (m_base[0]), wi::to_wide (r.m_base[0]), sign))
+  if (wi::le_p (m_base[0], r.m_base[0], sign))
     {
       // If current upper bound is new upper bound, we're done.
-      if (wi::le_p (wi::to_wide (r.m_base[1]), wi::to_wide (m_base[1]), sign))
+      if (wi::le_p (r.m_base[1], m_base[1], sign))
 	return union_nonzero_bits (r);
       // Otherwise R has the new upper bound.
       // Check for overlap/touching ranges, or single target range.
       if (m_max_ranges == 1
-	  || wi::to_widest (m_base[1]) + 1 >= wi::to_widest (r.m_base[0]))
+	  || (widest_int::from (m_base[1], sign) + 1
+	      >= widest_int::from (r.m_base[0], TYPE_SIGN (r.m_type))))
 	m_base[1] = r.m_base[1];
       else
 	{
@@ -1267,15 +1273,16 @@ irange::irange_single_pair_union (const irange &r)
     }
 
   // Set the new lower bound to R's lower bound.
-  tree lb = m_base[0];
+  wide_int lb = m_base[0];
   m_base[0] = r.m_base[0];
 
   // If R fully contains THIS range, just set the upper bound.
-  if (wi::ge_p (wi::to_wide (r.m_base[1]), wi::to_wide (m_base[1]), sign))
+  if (wi::ge_p (r.m_base[1], m_base[1], sign))
     m_base[1] = r.m_base[1];
   // Check for overlapping ranges, or target limited to a single range.
   else if (m_max_ranges == 1
-	   || wi::to_widest (r.m_base[1]) + 1 >= wi::to_widest (lb))
+	   || (widest_int::from (r.m_base[1], TYPE_SIGN (r.m_type)) + 1
+	       >= widest_int::from (lb, sign)))
     ;
   else
     {
@@ -1336,13 +1343,15 @@ irange::union_ (const vrange &v)
   // the merge is performed.
   //
   // [Xi,Yi]..[Xn,Yn]  U  [Xj,Yj]..[Xm,Ym]   -->  [Xk,Yk]..[Xp,Yp]
-  auto_vec<tree, 20> res (m_num_ranges * 2 + r.m_num_ranges * 2);
+  auto_vec<wide_int, 20> res (m_num_ranges * 2 + r.m_num_ranges * 2);
   unsigned i = 0, j = 0, k = 0;
+  signop sign = TYPE_SIGN (m_type);
 
   while (i < m_num_ranges * 2 && j < r.m_num_ranges * 2)
     {
       // lower of Xi and Xj is the lowest point.
-      if (wi::to_widest (m_base[i]) <= wi::to_widest (r.m_base[j]))
+      if (widest_int::from (m_base[i], sign)
+	  <= widest_int::from (r.m_base[j], sign))
 	{
 	  res.quick_push (m_base[i]);
 	  res.quick_push (m_base[i + 1]);
@@ -1375,10 +1384,12 @@ irange::union_ (const vrange &v)
   for (j = 2; j < k ; j += 2)
     {
       // Current upper+1 is >= lower bound next pair, then we merge ranges.
-      if (wi::to_widest (res[i - 1]) + 1 >= wi::to_widest (res[j]))
+      if (widest_int::from (res[i - 1], sign) + 1
+	  >= widest_int::from (res[j], sign))
 	{
 	  // New upper bounds is greater of current or the next one.
-	  if (wi::to_widest (res[j + 1]) > wi::to_widest (res[i - 1]))
+	  if (widest_int::from (res[j + 1], sign)
+	      > widest_int::from (res[i - 1], sign))
 	    res[i - 1] = res[j + 1];
 	}
       else
@@ -1424,18 +1435,18 @@ irange::irange_contains_p (const irange &r) const
 
   // In order for THIS to fully contain R, all of the pairs within R must
   // be fully contained by the pairs in this object.
-  signop sign = TYPE_SIGN (TREE_TYPE(m_base[0]));
+  signop sign = TYPE_SIGN (m_type);
   unsigned ri = 0;
   unsigned i = 0;
-  tree rl = r.m_base[0];
-  tree ru = r.m_base[1];
-  tree l = m_base[0];
-  tree u = m_base[1];
+  wide_int rl = r.m_base[0];
+  wide_int ru = r.m_base[1];
+  wide_int l = m_base[0];
+  wide_int u = m_base[1];
   while (1)
     {
       // If r is contained within this range, move to the next R
-      if (wi::ge_p (wi::to_wide (rl), wi::to_wide (l), sign)
-	  && wi::le_p (wi::to_wide (ru), wi::to_wide (u), sign))
+      if (wi::ge_p (rl, l, sign)
+	  && wi::le_p (ru, u, sign))
 	{
 	  // This pair is OK, Either done, or bump to the next.
 	  if (++ri >= r.num_pairs ())
@@ -1445,7 +1456,7 @@ irange::irange_contains_p (const irange &r) const
 	  continue;
 	}
       // Otherwise, check if this's pair occurs before R's.
-      if (wi::lt_p (wi::to_wide (u), wi::to_wide (rl), sign))
+      if (wi::lt_p (u, rl, sign))
 	{
 	  // There's still at least one pair of R left.
 	  if (++i >= num_pairs ())
@@ -1498,7 +1509,7 @@ irange::intersect (const vrange &v)
   if (r.irange_contains_p (*this))
     return intersect_nonzero_bits (r);
 
-  signop sign = TYPE_SIGN (TREE_TYPE(m_base[0]));
+  signop sign = TYPE_SIGN (m_type);
   unsigned bld_pair = 0;
   unsigned bld_lim = m_max_ranges;
   int_range_max r2 (*this);
@@ -1507,17 +1518,17 @@ irange::intersect (const vrange &v)
   for (unsigned i = 0; i < r.num_pairs (); )
     {
       // If r1's upper is < r2's lower, we can skip r1's pair.
-      tree ru = r.m_base[i * 2 + 1];
-      tree r2l = r2.m_base[i2 * 2];
-      if (wi::lt_p (wi::to_wide (ru), wi::to_wide (r2l), sign))
+      wide_int ru = r.m_base[i * 2 + 1];
+      wide_int r2l = r2.m_base[i2 * 2];
+      if (wi::lt_p (ru, r2l, sign))
 	{
 	  i++;
 	  continue;
 	}
       // Likewise, skip r2's pair if its excluded.
-      tree r2u = r2.m_base[i2 * 2 + 1];
-      tree rl = r.m_base[i * 2];
-      if (wi::lt_p (wi::to_wide (r2u), wi::to_wide (rl), sign))
+      wide_int r2u = r2.m_base[i2 * 2 + 1];
+      wide_int rl = r.m_base[i * 2];
+      if (wi::lt_p (r2u, rl, sign))
 	{
 	  i2++;
 	  if (i2 < r2_lim)
@@ -1531,7 +1542,7 @@ irange::intersect (const vrange &v)
       // set.
       if (bld_pair < bld_lim)
 	{
-	  if (wi::ge_p (wi::to_wide (rl), wi::to_wide (r2l), sign))
+	  if (wi::ge_p (rl, r2l, sign))
 	    m_base[bld_pair * 2] = rl;
 	  else
 	    m_base[bld_pair * 2] = r2l;
@@ -1541,7 +1552,7 @@ irange::intersect (const vrange &v)
 	bld_pair--;
 
       // ...and choose the lower of the upper bounds.
-      if (wi::le_p (wi::to_wide (ru), wi::to_wide (r2u), sign))
+      if (wi::le_p (ru, r2u, sign))
 	{
 	  m_base[bld_pair * 2 + 1] = ru;
 	  bld_pair++;
@@ -1604,27 +1615,27 @@ irange::intersect (const wide_int& lb, const wide_int& ub)
   unsigned pair_lim = num_pairs ();
   for (unsigned i = 0; i < pair_lim; i++)
     {
-      tree pairl = m_base[i * 2];
-      tree pairu = m_base[i * 2 + 1];
+      wide_int pairl = m_base[i * 2];
+      wide_int pairu = m_base[i * 2 + 1];
       // Once UB is less than a pairs lower bound, we're done.
-      if (wi::lt_p (ub, wi::to_wide (pairl), sign))
+      if (wi::lt_p (ub, pairl, sign))
 	break;
       // if LB is greater than this pairs upper, this pair is excluded.
-      if (wi::lt_p (wi::to_wide (pairu), lb, sign))
+      if (wi::lt_p (pairu, lb, sign))
 	continue;
 
       // Must be some overlap.  Find the highest of the lower bounds,
       // and set it
-      if (wi::gt_p (lb, wi::to_wide (pairl), sign))
-	m_base[bld_index * 2] = wide_int_to_tree (range_type, lb);
+      if (wi::gt_p (lb, pairl, sign))
+	m_base[bld_index * 2] = lb;
       else
 	m_base[bld_index * 2] = pairl;
 
       // ...and choose the lower of the upper bounds and if the base pair
       // has the lower upper bound, need to check next pair too.
-      if (wi::lt_p (ub, wi::to_wide (pairu), sign))
+      if (wi::lt_p (ub, pairu, sign))
 	{
-	  m_base[bld_index++ * 2 + 1] = wide_int_to_tree (range_type, ub);
+	  m_base[bld_index++ * 2 + 1] = ub;
 	  break;
 	}
       else
@@ -1696,12 +1707,12 @@ irange::invert ()
   signop sign = TYPE_SIGN (ttype);
   wide_int type_min = wi::min_value (prec, sign);
   wide_int type_max = wi::max_value (prec, sign);
-  m_nonzero_mask = NULL;
+  m_nonzero_mask = wi::minus_one (prec);
   if (m_num_ranges == m_max_ranges
       && lower_bound () != type_min
       && upper_bound () != type_max)
     {
-      m_base[1] = wide_int_to_tree (ttype, type_max);
+      m_base[1] = type_max;
       m_num_ranges = 1;
       return;
     }
@@ -1723,9 +1734,9 @@ irange::invert ()
   // which doesn't set the underflow bit.
   if (type_min != orig_range.lower_bound ())
     {
-      m_base[nitems++] = wide_int_to_tree (ttype, type_min);
+      m_base[nitems++] = type_min;
       tmp = subtract_one (orig_range.lower_bound (), ttype, ovf);
-      m_base[nitems++] = wide_int_to_tree (ttype, tmp);
+      m_base[nitems++] = tmp;
       if (ovf)
 	nitems = 0;
     }
@@ -1738,11 +1749,10 @@ irange::invert ()
 	{
 	  // The middle ranges cannot have MAX/MIN, so there's no need
 	  // to check for unsigned overflow on the +1 and -1 here.
-	  tmp = wi::add (wi::to_wide (orig_range.m_base[j]), 1, sign, &ovf);
-	  m_base[nitems++] = wide_int_to_tree (ttype, tmp);
-	  tmp = subtract_one (wi::to_wide (orig_range.m_base[j + 1]),
-			      ttype, ovf);
-	  m_base[nitems++] = wide_int_to_tree (ttype, tmp);
+	  tmp = wi::add (orig_range.m_base[j], 1, sign, &ovf);
+	  m_base[nitems++] = tmp;
+	  tmp = subtract_one (orig_range.m_base[j + 1], ttype, ovf);
+	  m_base[nitems++] = tmp;
 	  if (ovf)
 	    nitems -= 2;
 	}
@@ -1753,11 +1763,11 @@ irange::invert ()
   // However, if this will overflow on the PLUS 1, don't even bother.
   // This also handles adding one to an unsigned MAX, which doesn't
   // set the overflow bit.
-  if (type_max != wi::to_wide (orig_range.m_base[i]))
+  if (type_max != orig_range.m_base[i])
     {
-      tmp = add_one (wi::to_wide (orig_range.m_base[i]), ttype, ovf);
-      m_base[nitems++] = wide_int_to_tree (ttype, tmp);
-      m_base[nitems++] = wide_int_to_tree (ttype, type_max);
+      tmp = add_one (orig_range.m_base[i], ttype, ovf);
+      m_base[nitems++] = tmp;
+      m_base[nitems++] = type_max;
       if (ovf)
 	nitems -= 2;
     }
@@ -1794,21 +1804,21 @@ bool
 irange::set_range_from_nonzero_bits ()
 {
   gcc_checking_assert (!undefined_p ());
-  if (!m_nonzero_mask)
+  if (m_nonzero_mask == -1)
     return false;
-  unsigned popcount = wi::popcount (wi::to_wide (m_nonzero_mask));
+  unsigned popcount = wi::popcount (m_nonzero_mask);
 
   // If we have only one bit set in the mask, we can figure out the
   // range immediately.
   if (popcount == 1)
     {
       // Make sure we don't pessimize the range.
-      if (!contains_p (wi::to_wide (m_nonzero_mask)))
+      if (!contains_p (m_nonzero_mask))
 	return false;
 
       bool has_zero = contains_zero_p (*this);
-      tree nz = m_nonzero_mask;
-      set (nz, nz);
+      wide_int nz = m_nonzero_mask;
+      set (m_type, nz, nz);
       m_nonzero_mask = nz;
       if (has_zero)
 	{
@@ -1827,26 +1837,15 @@ irange::set_range_from_nonzero_bits ()
 }
 
 void
-irange::set_nonzero_bits (const wide_int_ref &bits)
+irange::set_nonzero_bits (const wide_int &bits)
 {
   gcc_checking_assert (!undefined_p ());
-  unsigned prec = TYPE_PRECISION (type ());
-
-  if (bits == -1)
-    {
-      m_nonzero_mask = NULL;
-      normalize_kind ();
-      if (flag_checking)
-	verify_range ();
-      return;
-    }
 
   // Drop VARYINGs with a nonzero mask to a plain range.
   if (m_kind == VR_VARYING && bits != -1)
     m_kind = VR_RANGE;
 
-  wide_int nz = wide_int::from (bits, prec, TYPE_SIGN (type ()));
-  m_nonzero_mask = wide_int_to_tree (type (), nz);
+  m_nonzero_mask = bits;
   if (set_range_from_nonzero_bits ())
     return;
 
@@ -1870,21 +1869,10 @@ irange::get_nonzero_bits () const
   // the mask precisely up to date at all times.  Instead, we default
   // to -1 and set it when explicitly requested.  However, this
   // function will always return the correct mask.
-  if (m_nonzero_mask)
-    return wi::to_wide (m_nonzero_mask) & get_nonzero_bits_from_range ();
-  else
+  if (m_nonzero_mask == -1)
     return get_nonzero_bits_from_range ();
-}
-
-// Convert tree mask to wide_int.  Returns -1 for NULL masks.
-
-inline wide_int
-mask_to_wi (tree mask, tree type)
-{
-  if (mask)
-    return wi::to_wide (mask);
   else
-    return wi::shwi (-1, TYPE_PRECISION (type));
+    return m_nonzero_mask & get_nonzero_bits_from_range ();
 }
 
 // Intersect the nonzero bits in R into THIS and normalize the range.
@@ -1895,7 +1883,7 @@ irange::intersect_nonzero_bits (const irange &r)
 {
   gcc_checking_assert (!undefined_p () && !r.undefined_p ());
 
-  if (!m_nonzero_mask && !r.m_nonzero_mask)
+  if (m_nonzero_mask == -1 && r.m_nonzero_mask == -1)
     {
       normalize_kind ();
       if (flag_checking)
@@ -1904,15 +1892,14 @@ irange::intersect_nonzero_bits (const irange &r)
     }
 
   bool changed = false;
-  tree t = type ();
-  if (mask_to_wi (m_nonzero_mask, t) != mask_to_wi (r.m_nonzero_mask, t))
+  if (m_nonzero_mask != r.m_nonzero_mask)
     {
       wide_int nz = get_nonzero_bits () & r.get_nonzero_bits ();
       // If the nonzero bits did not change, return false.
       if (nz == get_nonzero_bits ())
 	return false;
 
-      m_nonzero_mask = wide_int_to_tree (t, nz);
+      m_nonzero_mask = nz;
       if (set_range_from_nonzero_bits ())
 	return true;
       changed = true;
@@ -1931,7 +1918,7 @@ irange::union_nonzero_bits (const irange &r)
 {
   gcc_checking_assert (!undefined_p () && !r.undefined_p ());
 
-  if (!m_nonzero_mask && !r.m_nonzero_mask)
+  if (m_nonzero_mask == -1 && r.m_nonzero_mask == -1)
     {
       normalize_kind ();
       if (flag_checking)
@@ -1940,11 +1927,9 @@ irange::union_nonzero_bits (const irange &r)
     }
 
   bool changed = false;
-  tree t = type ();
-  if (mask_to_wi (m_nonzero_mask, t) != mask_to_wi (r.m_nonzero_mask, t))
+  if (m_nonzero_mask != r.m_nonzero_mask)
     {
-      wide_int nz = get_nonzero_bits () | r.get_nonzero_bits ();
-      m_nonzero_mask = wide_int_to_tree (t, nz);
+      m_nonzero_mask = get_nonzero_bits () | r.get_nonzero_bits ();
       // No need to call set_range_from_nonzero_bits, because we'll
       // never narrow the range.  Besides, it would cause endless
       // recursion because of the union_ in
@@ -2005,25 +1990,15 @@ vrp_operand_equal_p (const_tree val1, const_tree val2)
 void
 gt_ggc_mx (irange *x)
 {
-  for (unsigned i = 0; i < x->m_num_ranges; ++i)
-    {
-      gt_ggc_mx (x->m_base[i * 2]);
-      gt_ggc_mx (x->m_base[i * 2 + 1]);
-    }
-  if (x->m_nonzero_mask)
-    gt_ggc_mx (x->m_nonzero_mask);
+  if (!x->undefined_p ())
+    gt_ggc_mx (x->m_type);
 }
 
 void
 gt_pch_nx (irange *x)
 {
-  for (unsigned i = 0; i < x->m_num_ranges; ++i)
-    {
-      gt_pch_nx (x->m_base[i * 2]);
-      gt_pch_nx (x->m_base[i * 2 + 1]);
-    }
-  if (x->m_nonzero_mask)
-    gt_pch_nx (x->m_nonzero_mask);
+  if (!x->undefined_p ())
+    gt_pch_nx (x->m_type);
 }
 
 void
@@ -2034,8 +2009,6 @@ gt_pch_nx (irange *x, gt_pointer_operator op, void *cookie)
       op (&x->m_base[i * 2], NULL, cookie);
       op (&x->m_base[i * 2 + 1], NULL, cookie);
     }
-  if (x->m_nonzero_mask)
-    op (&x->m_nonzero_mask, NULL, cookie);
 }
 
 void
@@ -2144,12 +2117,6 @@ range (tree type, int a, int b, value_range_kind kind = VR_RANGE)
   return int_range<2> (type, w1, w2, kind);
 }
 
-static int_range<2>
-tree_range (tree a, tree b, value_range_kind kind = VR_RANGE)
-{
-  return int_range<2> (TREE_TYPE (a), wi::to_wide (a), wi::to_wide (b), kind);
-}
-
 static int_range<2>
 range_int (int a, int b, value_range_kind kind = VR_RANGE)
 {
@@ -2328,7 +2295,9 @@ range_tests_strict_enum ()
   ASSERT_FALSE (ir1.varying_p ());
 
   // The same test as above, but using TYPE_{MIN,MAX}_VALUE instead of [0,3].
-  vr1 = tree_range (TYPE_MIN_VALUE (rtype), TYPE_MAX_VALUE (rtype));
+  vr1 = int_range<2> (rtype,
+		      wi::to_wide (TYPE_MIN_VALUE (rtype)),
+		      wi::to_wide (TYPE_MAX_VALUE (rtype)));
   ir1 = vr1;
   ASSERT_TRUE (ir1 == vr1);
   ASSERT_FALSE (ir1.varying_p ());
@@ -2522,11 +2491,11 @@ range_tests_misc ()
   ASSERT_TRUE (vv.contains_p (UINT (2)));
   ASSERT_TRUE (vv.num_pairs () == 3);
 
-  r0 = range_uint (1, 1);
+  r0 = range_int (1, 1);
   // And union it with  [0,0][2,2][4,MAX] multi range
   r0.union_ (vv);
   // The result should be [0,2][4,MAX], or ~[3,3]  but it must contain 2
-  ASSERT_TRUE (r0.contains_p (UINT (2)));
+  ASSERT_TRUE (r0.contains_p (INT (2)));
 }
 
 static void
@@ -2536,33 +2505,33 @@ range_tests_nonzero_bits ()
 
   // Adding nonzero bits to a varying drops the varying.
   r0.set_varying (integer_type_node);
-  r0.set_nonzero_bits (255);
+  r0.set_nonzero_bits (INT (255));
   ASSERT_TRUE (!r0.varying_p ());
   // Dropping the nonzero bits brings us back to varying.
-  r0.set_nonzero_bits (-1);
+  r0.set_nonzero_bits (INT (-1));
   ASSERT_TRUE (r0.varying_p ());
 
   // Test contains_p with nonzero bits.
   r0.set_zero (integer_type_node);
   ASSERT_TRUE (r0.contains_p (INT (0)));
   ASSERT_FALSE (r0.contains_p (INT (1)));
-  r0.set_nonzero_bits (0xfe);
+  r0.set_nonzero_bits (INT (0xfe));
   ASSERT_FALSE (r0.contains_p (INT (0x100)));
   ASSERT_FALSE (r0.contains_p (INT (0x3)));
 
   // Union of nonzero bits.
   r0.set_varying (integer_type_node);
-  r0.set_nonzero_bits (0xf0);
+  r0.set_nonzero_bits (INT (0xf0));
   r1.set_varying (integer_type_node);
-  r1.set_nonzero_bits (0xf);
+  r1.set_nonzero_bits (INT (0xf));
   r0.union_ (r1);
   ASSERT_TRUE (r0.get_nonzero_bits () == 0xff);
 
   // Intersect of nonzero bits.
   r0 = range_int (0, 255);
-  r0.set_nonzero_bits (0xfe);
+  r0.set_nonzero_bits (INT (0xfe));
   r1.set_varying (integer_type_node);
-  r1.set_nonzero_bits (0xf0);
+  r1.set_nonzero_bits (INT (0xf0));
   r0.intersect (r1);
   ASSERT_TRUE (r0.get_nonzero_bits () == 0xf0);
 
@@ -2579,13 +2548,13 @@ range_tests_nonzero_bits ()
   x = wi::bit_not (x);
   r0.set_nonzero_bits (x); 	// 0xff..ff00
   r1.set_varying (integer_type_node);
-  r1.set_nonzero_bits (0xff);
+  r1.set_nonzero_bits (INT (0xff));
   r0.union_ (r1);
   ASSERT_TRUE (r0.varying_p ());
 
   // Test that setting a nonzero bit of 1 does not pessimize the range.
   r0.set_zero (integer_type_node);
-  r0.set_nonzero_bits (1);
+  r0.set_nonzero_bits (INT (1));
   ASSERT_TRUE (r0.zero_p ());
 }
 
diff --git a/gcc/value-range.h b/gcc/value-range.h
index b040e2f254f..9f82b0011c7 100644
--- a/gcc/value-range.h
+++ b/gcc/value-range.h
@@ -164,12 +164,12 @@ public:
 
   // Nonzero masks.
   wide_int get_nonzero_bits () const;
-  void set_nonzero_bits (const wide_int_ref &bits);
+  void set_nonzero_bits (const wide_int &bits);
 
 protected:
   virtual void set (tree, tree, value_range_kind = VR_RANGE) override;
   virtual bool contains_p (tree cst) const override;
-  irange (tree *, unsigned);
+  irange (wide_int *, unsigned);
 
    // In-place operators.
   void irange_set (tree type, const wide_int &, const wide_int &);
@@ -197,8 +197,9 @@ private:
   bool intersect (const wide_int& lb, const wide_int& ub);
   unsigned char m_num_ranges;
   const unsigned char m_max_ranges;
-  tree m_nonzero_mask;
-  tree *m_base;
+  tree m_type;
+  wide_int m_nonzero_mask;
+  wide_int *m_base;
 };
 
 // Here we describe an irange with N pairs of ranges.  The storage for
@@ -224,7 +225,7 @@ private:
   template <unsigned X> friend void gt_pch_nx (int_range<X> *,
 					       gt_pointer_operator, void *);
 
-  tree m_ranges[N*2];
+  wide_int m_ranges[N*2];
 };
 
 // Unsupported temporaries may be created by ranger before it's known
@@ -651,7 +652,7 @@ inline tree
 irange::type () const
 {
   gcc_checking_assert (m_num_ranges > 0);
-  return TREE_TYPE (m_base[0]);
+  return m_type;
 }
 
 inline bool
@@ -660,23 +661,19 @@ irange::varying_compatible_p () const
   if (m_num_ranges != 1)
     return false;
 
-  tree l = m_base[0];
-  tree u = m_base[1];
-  tree t = TREE_TYPE (l);
+  const wide_int &l = m_base[0];
+  const wide_int &u = m_base[1];
+  tree t = m_type;
 
   if (m_kind == VR_VARYING && t == error_mark_node)
     return true;
 
   unsigned prec = TYPE_PRECISION (t);
   signop sign = TYPE_SIGN (t);
-  if (INTEGRAL_TYPE_P (t))
-    return (wi::to_wide (l) == wi::min_value (prec, sign)
-	    && wi::to_wide (u) == wi::max_value (prec, sign)
-	    && (!m_nonzero_mask || wi::to_wide (m_nonzero_mask) == -1));
-  if (POINTER_TYPE_P (t))
-    return (wi::to_wide (l) == 0
-	    && wi::to_wide (u) == wi::max_value (prec, sign)
-	    && (!m_nonzero_mask || wi::to_wide (m_nonzero_mask) == -1));
+  if (INTEGRAL_TYPE_P (t) || POINTER_TYPE_P (t))
+    return (l == wi::min_value (prec, sign)
+	    && u == wi::max_value (prec, sign)
+	    && m_nonzero_mask == -1);
   return true;
 }
 
@@ -769,7 +766,7 @@ gt_pch_nx (int_range<N> *x, gt_pointer_operator op, void *cookie)
 // Constructors for irange
 
 inline
-irange::irange (tree *base, unsigned nranges)
+irange::irange (wide_int *base, unsigned nranges)
   : vrange (VR_IRANGE),
     m_max_ranges (nranges)
 {
@@ -812,9 +809,7 @@ int_range<N>::int_range (tree type, const wide_int &wmin, const wide_int &wmax,
 			 value_range_kind kind)
   : irange (m_ranges, N)
 {
-  tree min = wide_int_to_tree (type, wmin);
-  tree max = wide_int_to_tree (type, wmax);
-  set (min, max, kind);
+  set (type, wmin, wmax, kind);
 }
 
 template<unsigned N>
@@ -836,8 +831,8 @@ inline void
 irange::set_undefined ()
 {
   m_kind = VR_UNDEFINED;
+  m_type = NULL;
   m_num_ranges = 0;
-  m_nonzero_mask = NULL;
 }
 
 inline void
@@ -845,33 +840,18 @@ irange::set_varying (tree type)
 {
   m_kind = VR_VARYING;
   m_num_ranges = 1;
-  m_nonzero_mask = NULL;
+  m_nonzero_mask = wi::minus_one (TYPE_PRECISION (type));
 
-  if (INTEGRAL_TYPE_P (type))
+  if (INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type))
     {
+      m_type = type;
       // Strict enum's require varying to be not TYPE_MIN/MAX, but rather
       // min_value and max_value.
-      wide_int min = wi::min_value (TYPE_PRECISION (type), TYPE_SIGN (type));
-      wide_int max = wi::max_value (TYPE_PRECISION (type), TYPE_SIGN (type));
-      if (wi::eq_p (max, wi::to_wide (TYPE_MAX_VALUE (type)))
-	  && wi::eq_p (min, wi::to_wide (TYPE_MIN_VALUE (type))))
-	{
-	  m_base[0] = TYPE_MIN_VALUE (type);
-	  m_base[1] = TYPE_MAX_VALUE (type);
-	}
-      else
-	{
-	  m_base[0] = wide_int_to_tree (type, min);
-	  m_base[1] = wide_int_to_tree (type, max);
-	}
-    }
-  else if (POINTER_TYPE_P (type))
-    {
-      m_base[0] = build_int_cst (type, 0);
-      m_base[1] = build_int_cst (type, -1);
+      m_base[0] = wi::min_value (TYPE_PRECISION (type), TYPE_SIGN (type));
+      m_base[1] = wi::max_value (TYPE_PRECISION (type), TYPE_SIGN (type));
     }
   else
-    m_base[0] = m_base[1] = error_mark_node;
+    m_type = error_mark_node;
 }
 
 // Return the lower bound of a sub-range.  PAIR is the sub-range in
@@ -882,7 +862,7 @@ irange::lower_bound (unsigned pair) const
 {
   gcc_checking_assert (m_num_ranges > 0);
   gcc_checking_assert (pair + 1 <= num_pairs ());
-  return wi::to_wide (m_base[pair * 2]);
+  return m_base[pair * 2];
 }
 
 // Return the upper bound of a sub-range.  PAIR is the sub-range in
@@ -893,7 +873,7 @@ irange::upper_bound (unsigned pair) const
 {
   gcc_checking_assert (m_num_ranges > 0);
   gcc_checking_assert (pair + 1 <= num_pairs ());
-  return wi::to_wide (m_base[pair * 2 + 1]);
+  return m_base[pair * 2 + 1];
 }
 
 // Return the highest bound of a range.
