diff --git a/gcc/builtins.c b/gcc/builtins.c
index c1722ab..f5c9418 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -378,7 +378,7 @@ get_object_alignment_2 (tree exp, unsigned int *alignp,
 	  bitpos += ptr_bitpos;
 	  if (TREE_CODE (exp) == MEM_REF
 	      || TREE_CODE (exp) == TARGET_MEM_REF)
-	    bitpos += mem_ref_offset (exp).low * BITS_PER_UNIT;
+	    bitpos += mem_ref_offset_as_double (exp).low * BITS_PER_UNIT;
 	}
     }
   else if (TREE_CODE (exp) == STRING_CST)
@@ -8784,12 +8784,12 @@ fold_builtin_memory_op (location_t loc, tree dest, tree src,
 		  if (! operand_equal_p (TREE_OPERAND (src_base, 0),
 					 TREE_OPERAND (dest_base, 0), 0))
 		    return NULL_TREE;
-		  off = mem_ref_offset (src_base) +
+		  off = mem_ref_offset_as_double (src_base) +
 					double_int::from_shwi (src_offset);
 		  if (!off.fits_shwi ())
 		    return NULL_TREE;
 		  src_offset = off.low;
-		  off = mem_ref_offset (dest_base) +
+		  off = mem_ref_offset_as_double (dest_base) +
 					double_int::from_shwi (dest_offset);
 		  if (!off.fits_shwi ())
 		    return NULL_TREE;
diff --git a/gcc/cfgloop.h b/gcc/cfgloop.h
index e0a370f..dd3748a 100644
--- a/gcc/cfgloop.h
+++ b/gcc/cfgloop.h
@@ -24,6 +24,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "basic-block.h"
 #include "vecprim.h"
 #include "double-int.h"
+#include "wide-int.h"
 
 #include "bitmap.h"
 #include "sbitmap.h"
@@ -288,6 +289,7 @@ void estimate_numbers_of_iterations_loop (struct loop *);
 void record_niter_bound (struct loop *, double_int, bool, bool);
 bool estimated_loop_iterations (struct loop *, double_int *);
 bool max_loop_iterations (struct loop *, double_int *);
+bool max_loop_iterations (struct loop *, wide_int *, int, int);
 HOST_WIDE_INT estimated_loop_iterations_int (struct loop *);
 HOST_WIDE_INT max_loop_iterations_int (struct loop *);
 bool max_stmt_executions (struct loop *, double_int *);
diff --git a/gcc/expr.c b/gcc/expr.c
index fe27819..31adc26 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -6678,7 +6678,7 @@ get_inner_reference (tree exp, HOST_WIDE_INT *pbitsize,
 	      tree off = TREE_OPERAND (exp, 1);
 	      if (!integer_zerop (off))
 		{
-		  double_int boff, coff = mem_ref_offset (exp);
+		  double_int boff, coff = mem_ref_offset_as_double (exp);
 		  boff = coff.alshift (BITS_PER_UNIT == 8
 				       ? 3 : exact_log2 (BITS_PER_UNIT),
 				       HOST_BITS_PER_DOUBLE_INT);
@@ -9533,7 +9533,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
 	   might end up in a register.  */
 	if (mem_ref_refers_to_non_mem_p (exp))
 	  {
-	    HOST_WIDE_INT offset = mem_ref_offset (exp).low;
+	    HOST_WIDE_INT offset = mem_ref_offset_as_double (exp).low;
 	    tree bit_offset;
 	    tree bftype;
 	    base = TREE_OPERAND (base, 0);
@@ -9577,8 +9577,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
 	op0 = memory_address_addr_space (address_mode, op0, as);
 	if (!integer_zerop (TREE_OPERAND (exp, 1)))
 	  {
-	    wide_int wi = wide_int::from_double_int
-	      (mem_ref_offset (exp), address_mode);
+	    wide_int wi = mem_ref_offset (exp);
 	    rtx off = immed_wide_int_const (wi, address_mode);
 	    op0 = simplify_gen_binary (PLUS, address_mode, op0, off);
 	  }
diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c
index 5ff70a2..57f3914 100644
--- a/gcc/gimple-fold.c
+++ b/gcc/gimple-fold.c
@@ -2688,7 +2688,7 @@ get_base_constructor (tree base, HOST_WIDE_INT *bit_offset,
 	{
 	  if (!tree_fits_shwi_p (TREE_OPERAND (base, 1)))
 	    return NULL_TREE;
-	  *bit_offset += (mem_ref_offset (base).low
+	  *bit_offset += (mem_ref_offset_as_double (base).low
 			  * BITS_PER_UNIT);
 	}
 
diff --git a/gcc/gimple-ssa-strength-reduction.c b/gcc/gimple-ssa-strength-reduction.c
index 6ee5c7a..eb141c0 100644
--- a/gcc/gimple-ssa-strength-reduction.c
+++ b/gcc/gimple-ssa-strength-reduction.c
@@ -557,7 +557,7 @@ restructure_reference (tree *pbase, tree *poffset, double_int *pindex,
     return false;
 
   t1 = TREE_OPERAND (base, 0);
-  c1 = mem_ref_offset (base);
+  c1 = mem_ref_offset_as_double (base);
   type = TREE_TYPE (TREE_OPERAND (base, 1));
 
   mult_op0 = TREE_OPERAND (offset, 0);
diff --git a/gcc/ipa-prop.c b/gcc/ipa-prop.c
index 633cbc4..243847e 100644
--- a/gcc/ipa-prop.c
+++ b/gcc/ipa-prop.c
@@ -933,7 +933,7 @@ compute_complex_assign_jump_func (struct ipa_node_params *info,
       || max_size == -1
       || max_size != size)
     return;
-  offset += mem_ref_offset (base).low * BITS_PER_UNIT;
+  offset += mem_ref_offset_as_double (base).low * BITS_PER_UNIT;
   ssa = TREE_OPERAND (base, 0);
   if (TREE_CODE (ssa) != SSA_NAME
       || !SSA_NAME_IS_DEFAULT_DEF (ssa)
@@ -988,7 +988,7 @@ get_ancestor_addr_info (gimple assign, tree *obj_p, HOST_WIDE_INT *offset)
       || TREE_CODE (SSA_NAME_VAR (parm)) != PARM_DECL)
     return NULL_TREE;
 
-  *offset += mem_ref_offset (expr).low * BITS_PER_UNIT;
+  *offset += mem_ref_offset_as_double (expr).low * BITS_PER_UNIT;
   *obj_p = obj;
   return expr;
 }
diff --git a/gcc/tree-data-ref.c b/gcc/tree-data-ref.c
index b606210..42ad127 100644
--- a/gcc/tree-data-ref.c
+++ b/gcc/tree-data-ref.c
@@ -720,7 +720,7 @@ dr_analyze_innermost (struct data_reference *dr, struct loop *nest)
     {
       if (!integer_zerop (TREE_OPERAND (base, 1)))
 	{
-	  double_int moff = mem_ref_offset (base);
+	  double_int moff = mem_ref_offset_as_double (base);
 	  tree mofft = double_int_to_tree (sizetype, moff);
 	  if (!poffset)
 	    poffset = mofft;
diff --git a/gcc/tree-dfa.c b/gcc/tree-dfa.c
index 9be06aa..03814bc 100644
--- a/gcc/tree-dfa.c
+++ b/gcc/tree-dfa.c
@@ -552,7 +552,7 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset,
 		exp = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
 	      else
 		{
-		  double_int off = mem_ref_offset (exp);
+		  double_int off = mem_ref_offset_as_double (exp);
 		  off = off.alshift (BITS_PER_UNIT == 8
 				     ? 3 : exact_log2 (BITS_PER_UNIT),
 				     HOST_BITS_PER_DOUBLE_INT);
@@ -583,7 +583,7 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset,
 		exp = TREE_OPERAND (TMR_BASE (exp), 0);
 	      else
 		{
-		  double_int off = mem_ref_offset (exp);
+		  double_int off = mem_ref_offset_as_double (exp);
 		  off = off.alshift (BITS_PER_UNIT == 8
 				     ? 3 : exact_log2 (BITS_PER_UNIT),
 				     HOST_BITS_PER_DOUBLE_INT);
diff --git a/gcc/tree-flow-inline.h b/gcc/tree-flow-inline.h
index a433223..1e59aa1 100644
--- a/gcc/tree-flow-inline.h
+++ b/gcc/tree-flow-inline.h
@@ -1269,7 +1269,7 @@ get_addr_base_and_unit_offset_1 (tree exp, HOST_WIDE_INT *poffset,
 	      {
 		if (!integer_zerop (TREE_OPERAND (exp, 1)))
 		  {
-		    double_int off = mem_ref_offset (exp);
+		    double_int off = mem_ref_offset_as_double (exp);
 		    gcc_assert (off.high == -1 || off.high == 0);
 		    byte_offset += off.to_shwi ();
 		  }
@@ -1292,7 +1292,7 @@ get_addr_base_and_unit_offset_1 (tree exp, HOST_WIDE_INT *poffset,
 		  return NULL_TREE;
 		if (!integer_zerop (TMR_OFFSET (exp)))
 		  {
-		    double_int off = mem_ref_offset (exp);
+		    double_int off = mem_ref_offset_as_double (exp);
 		    gcc_assert (off.high == -1 || off.high == 0);
 		    byte_offset += off.to_shwi ();
 		  }
diff --git a/gcc/tree-object-size.c b/gcc/tree-object-size.c
index c9e30f7..1a4a4d9 100644
--- a/gcc/tree-object-size.c
+++ b/gcc/tree-object-size.c
@@ -142,7 +142,7 @@ compute_object_offset (const_tree expr, const_tree var)
 
     case MEM_REF:
       gcc_assert (TREE_CODE (TREE_OPERAND (expr, 0)) == ADDR_EXPR);
-      return double_int_to_tree (sizetype, mem_ref_offset (expr));
+      return double_int_to_tree (sizetype, mem_ref_offset_as_double (expr));
 
     default:
       return error_mark_node;
@@ -192,7 +192,7 @@ addr_object_size (struct object_size_info *osi, const_tree ptr,
 	}
       if (sz != unknown[object_size_type])
 	{
-	  double_int dsz = double_int::from_uhwi (sz) - mem_ref_offset (pt_var);
+	  double_int dsz = double_int::from_uhwi (sz) - mem_ref_offset_as_double (pt_var);
 	  if (dsz.is_negative ())
 	    sz = 0;
 	  else if (dsz.fits_uhwi ())
diff --git a/gcc/tree-sra.c b/gcc/tree-sra.c
index a172d91..5ccecbc 100644
--- a/gcc/tree-sra.c
+++ b/gcc/tree-sra.c
@@ -4304,7 +4304,7 @@ sra_ipa_modify_expr (tree *expr, bool convert,
 
   if (TREE_CODE (base) == MEM_REF)
     {
-      offset += mem_ref_offset (base).low * BITS_PER_UNIT;
+      offset += mem_ref_offset_as_double (base).low * BITS_PER_UNIT;
       base = TREE_OPERAND (base, 0);
     }
 
diff --git a/gcc/tree-ssa-address.c b/gcc/tree-ssa-address.c
index 932c1e1..c7875ee 100644
--- a/gcc/tree-ssa-address.c
+++ b/gcc/tree-ssa-address.c
@@ -869,8 +869,8 @@ copy_ref_info (tree new_ref, tree old_ref)
 			   && (tree_to_shwi (TMR_STEP (new_ref))
 			       < align)))))
 	    {
-	      unsigned int inc = (mem_ref_offset (old_ref)
-				  - mem_ref_offset (new_ref)).low;
+	      unsigned int inc = (mem_ref_offset_as_double (old_ref)
+				  - mem_ref_offset_as_double (new_ref)).low;
 	      adjust_ptr_info_misalignment (new_pi, inc);
 	    }
 	  else
diff --git a/gcc/tree-ssa-alias.c b/gcc/tree-ssa-alias.c
index 6eabb70..8624ce2 100644
--- a/gcc/tree-ssa-alias.c
+++ b/gcc/tree-ssa-alias.c
@@ -755,7 +755,7 @@ indirect_ref_may_alias_decl_p (tree ref1 ATTRIBUTE_UNUSED, tree base1,
 
   /* The offset embedded in MEM_REFs can be negative.  Bias them
      so that the resulting offset adjustment is positive.  */
-  moff = mem_ref_offset (base1);
+  moff = mem_ref_offset_as_double (base1);
   moff = moff.alshift (BITS_PER_UNIT == 8
 		       ? 3 : exact_log2 (BITS_PER_UNIT),
 		       HOST_BITS_PER_DOUBLE_INT);
@@ -833,7 +833,7 @@ indirect_ref_may_alias_decl_p (tree ref1 ATTRIBUTE_UNUSED, tree base1,
   if (TREE_CODE (dbase2) == MEM_REF
       || TREE_CODE (dbase2) == TARGET_MEM_REF)
     {
-      double_int moff = mem_ref_offset (dbase2);
+      double_int moff = mem_ref_offset_as_double (dbase2);
       moff = moff.alshift (BITS_PER_UNIT == 8
 			   ? 3 : exact_log2 (BITS_PER_UNIT),
 			   HOST_BITS_PER_DOUBLE_INT);
@@ -929,7 +929,7 @@ indirect_refs_may_alias_p (tree ref1 ATTRIBUTE_UNUSED, tree base1,
       double_int moff;
       /* The offset embedded in MEM_REFs can be negative.  Bias them
 	 so that the resulting offset adjustment is positive.  */
-      moff = mem_ref_offset (base1);
+      moff = mem_ref_offset_as_double (base1);
       moff = moff.alshift (BITS_PER_UNIT == 8
 			   ? 3 : exact_log2 (BITS_PER_UNIT),
 			   HOST_BITS_PER_DOUBLE_INT);
@@ -937,7 +937,7 @@ indirect_refs_may_alias_p (tree ref1 ATTRIBUTE_UNUSED, tree base1,
 	offset2 += (-moff).low;
       else
 	offset1 += moff.low;
-      moff = mem_ref_offset (base2);
+      moff = mem_ref_offset_as_double (base2);
       moff = moff.alshift (BITS_PER_UNIT == 8
 			   ? 3 : exact_log2 (BITS_PER_UNIT),
 			   HOST_BITS_PER_DOUBLE_INT);
diff --git a/gcc/tree-ssa-forwprop.c b/gcc/tree-ssa-forwprop.c
index 703325a..601641e 100644
--- a/gcc/tree-ssa-forwprop.c
+++ b/gcc/tree-ssa-forwprop.c
@@ -799,12 +799,12 @@ forward_propagate_addr_expr_1 (tree name, tree def_rhs,
       if ((def_rhs_base = get_addr_base_and_unit_offset (TREE_OPERAND (def_rhs, 0),
 							 &def_rhs_offset)))
 	{
-	  double_int off = mem_ref_offset (lhs);
+	  double_int off = mem_ref_offset_as_double (lhs);
 	  tree new_ptr;
 	  off += double_int::from_shwi (def_rhs_offset);
 	  if (TREE_CODE (def_rhs_base) == MEM_REF)
 	    {
-	      off += mem_ref_offset (def_rhs_base);
+	      off += mem_ref_offset_as_double (def_rhs_base);
 	      new_ptr = TREE_OPERAND (def_rhs_base, 0);
 	    }
 	  else
@@ -883,12 +883,12 @@ forward_propagate_addr_expr_1 (tree name, tree def_rhs,
       if ((def_rhs_base = get_addr_base_and_unit_offset (TREE_OPERAND (def_rhs, 0),
 							 &def_rhs_offset)))
 	{
-	  double_int off = mem_ref_offset (rhs);
+	  double_int off = mem_ref_offset_as_double (rhs);
 	  tree new_ptr;
 	  off += double_int::from_shwi (def_rhs_offset);
 	  if (TREE_CODE (def_rhs_base) == MEM_REF)
 	    {
-	      off += mem_ref_offset (def_rhs_base);
+	      off += mem_ref_offset_as_double (def_rhs_base);
 	      new_ptr = TREE_OPERAND (def_rhs_base, 0);
 	    }
 	  else
@@ -1352,7 +1352,7 @@ constant_pointer_difference (tree p1, tree p2)
 		  p = TREE_OPERAND (q, 0);
 		  off = size_binop (PLUS_EXPR, off,
 				    double_int_to_tree (sizetype,
-							mem_ref_offset (q)));
+							mem_ref_offset_as_double (q)));
 		}
 	      else
 		{
diff --git a/gcc/tree-ssa-loop-niter.c b/gcc/tree-ssa-loop-niter.c
index fe4db37..27e2d71 100644
--- a/gcc/tree-ssa-loop-niter.c
+++ b/gcc/tree-ssa-loop-niter.c
@@ -3035,6 +3035,23 @@ max_loop_iterations (struct loop *loop, double_int *nit)
   return true;
 }
 
+/* Sets NIT to an upper bound for the maximum number of executions of the
+   latch of the LOOP.  If we have no reliable estimate, the function returns
+   false, otherwise returns true.  */
+
+bool
+max_loop_iterations (struct loop *loop, wide_int *nit,
+		     int bitsize, int precision)
+{
+  estimate_numbers_of_iterations_loop (loop);
+  if (!loop->any_upper_bound)
+    return false;
+
+  *nit = wide_int::from_double_int (loop->nb_iterations_upper_bound,
+				    bitsize, precision);
+  return true;
+}
+
 /* Similar to estimated_loop_iterations, but returns the estimate only
    if it fits to HOST_WIDE_INT.  If this is not the case, or the estimate
    on the number of iterations of LOOP could not be derived, returns -1.  */
diff --git a/gcc/tree-ssa-phiopt.c b/gcc/tree-ssa-phiopt.c
index e3e90d5..3055b1e 100644
--- a/gcc/tree-ssa-phiopt.c
+++ b/gcc/tree-ssa-phiopt.c
@@ -702,7 +702,7 @@ jump_function_from_stmt (tree *arg, gimple stmt)
 						&offset);
       if (tem
 	  && TREE_CODE (tem) == MEM_REF
-	  && (mem_ref_offset (tem) + double_int::from_shwi (offset)).is_zero ())
+	  && (mem_ref_offset_as_double (tem) + double_int::from_shwi (offset)).is_zero ())
 	{
 	  *arg = TREE_OPERAND (tem, 0);
 	  return true;
diff --git a/gcc/tree-ssa-sccvn.c b/gcc/tree-ssa-sccvn.c
index 837fe6d..91fc76b 100644
--- a/gcc/tree-ssa-sccvn.c
+++ b/gcc/tree-ssa-sccvn.c
@@ -1124,7 +1124,7 @@ vn_reference_maybe_forwprop_address (VEC (vn_reference_op_s, heap) **ops,
 	return;
 
       off += double_int::from_shwi (addr_offset);
-      off += mem_ref_offset (addr_base);
+      off += mem_ref_offset_as_double (addr_base);
       op->op0 = TREE_OPERAND (addr_base, 0);
     }
   else
diff --git a/gcc/tree-ssa.c b/gcc/tree-ssa.c
index 7ba11e1..1fee91e 100644
--- a/gcc/tree-ssa.c
+++ b/gcc/tree-ssa.c
@@ -1833,9 +1833,9 @@ non_rewritable_mem_ref_base (tree ref)
 	   || TREE_CODE (TREE_TYPE (decl)) == COMPLEX_TYPE)
 	  && useless_type_conversion_p (TREE_TYPE (base),
 					TREE_TYPE (TREE_TYPE (decl)))
-	  && mem_ref_offset (base).fits_uhwi ()
+	  && mem_ref_offset_as_double (base).fits_uhwi ()
 	  && tree_to_double_int (TYPE_SIZE_UNIT (TREE_TYPE (decl)))
-	     .ugt (mem_ref_offset (base))
+	     .ugt (mem_ref_offset_as_double (base))
 	  && multiple_of_p (sizetype, TREE_OPERAND (base, 1),
 			    TYPE_SIZE_UNIT (TREE_TYPE (base))))
 	return NULL_TREE;
diff --git a/gcc/tree-vect-data-refs.c b/gcc/tree-vect-data-refs.c
index d93c5b7..d16e345 100644
--- a/gcc/tree-vect-data-refs.c
+++ b/gcc/tree-vect-data-refs.c
@@ -2730,7 +2730,7 @@ vect_check_gather (gimple stmt, loop_vec_info loop_vinfo, tree *basep,
 	{
 	  if (off == NULL_TREE)
 	    {
-	      double_int moff = mem_ref_offset (base);
+	      double_int moff = mem_ref_offset_as_double (base);
 	      off = double_int_to_tree (sizetype, moff);
 	    }
 	  else
diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c
index 9003ac5..85d6f6d 100644
--- a/gcc/tree-vrp.c
+++ b/gcc/tree-vrp.c
@@ -80,6 +80,12 @@ typedef struct value_range_d value_range_t;
    for still active basic-blocks.  */
 static sbitmap *live;
 
+/* The largest precision and bitsize used in any code in this
+   function.  We use these to determine the value of infinity for
+   doing infinite precision math.  */
+static int largest_precision;
+static int largest_bitsize;
+
 /* Return true if the SSA name NAME is live on the edge E.  */
 
 static bool
@@ -387,6 +393,15 @@ nonnull_arg_p (const_tree arg)
   return false;
 }
 
+/* Convert a cst to an infinitely sized wide_interger.  Infinite is
+   defined to be that largest type seen in this function.  */
+static wide_int
+tree_to_infinite_wide_int (const_tree cst)
+{
+  wide_int result = wide_int::from_tree_as_infinite_precision
+    (cst, largest_bitsize, largest_precision);
+  return result;
+}
 
 /* Set value range VR to VR_UNDEFINED.  */
 
@@ -967,7 +982,7 @@ gimple_assign_nonnegative_warnv_p (gimple stmt, bool *strict_overflow_p)
     }
 }
 
-/* Return true if return value of call STMT is know to be non-negative.
+/* Return true if return value of call STMT is known to be non-negative.
    If the return value is based on the assumption that signed overflow is
    undefined, set *STRICT_OVERFLOW_P to true; otherwise, don't change
    *STRICT_OVERFLOW_P.*/
@@ -987,7 +1002,7 @@ gimple_call_nonnegative_warnv_p (gimple stmt, bool *strict_overflow_p)
 					strict_overflow_p);
 }
 
-/* Return true if STMT is know to to compute a non-negative value.
+/* Return true if STMT is known to to compute a non-negative value.
    If the return value is based on the assumption that signed overflow is
    undefined, set *STRICT_OVERFLOW_P to true; otherwise, don't change
    *STRICT_OVERFLOW_P.*/
@@ -1006,7 +1021,7 @@ gimple_stmt_nonnegative_warnv_p (gimple stmt, bool *strict_overflow_p)
     }
 }
 
-/* Return true if the result of assignment STMT is know to be non-zero.
+/* Return true if the result of assignment STMT is known to be non-zero.
    If the return value is based on the assumption that signed overflow is
    undefined, set *STRICT_OVERFLOW_P to true; otherwise, don't change
    *STRICT_OVERFLOW_P.*/
@@ -1040,7 +1055,7 @@ gimple_assign_nonzero_warnv_p (gimple stmt, bool *strict_overflow_p)
     }
 }
 
-/* Return true if STMT is know to to compute a non-zero value.
+/* Return true if STMT is known to to compute a non-zero value.
    If the return value is based on the assumption that signed overflow is
    undefined, set *STRICT_OVERFLOW_P to true; otherwise, don't change
    *STRICT_OVERFLOW_P.*/
@@ -1613,10 +1628,12 @@ extract_range_from_assert (value_range_t *vr_p, tree expr)
       /* Make sure to not set TREE_OVERFLOW on the final type
 	 conversion.  We are willingly interpreting large positive
 	 unsigned values as negative singed values here.  */
-      min = force_fit_type_double (TREE_TYPE (var), tree_to_double_int (min),
-				   0, false);
-      max = force_fit_type_double (TREE_TYPE (var), tree_to_double_int (max),
-				   0, false);
+      min = wide_int_to_infinite_tree (TREE_TYPE (var), 
+				       tree_to_infinite_wide_int (min),
+				       largest_precision);
+      max = wide_int_to_infinite_tree (TREE_TYPE (var), 
+				       tree_to_infinite_wide_int (max),
+				       largest_precision);
 
       /* We can transform a max, min range to an anti-range or
          vice-versa.  Use set_and_canonicalize_value_range which does
@@ -1962,7 +1979,7 @@ vrp_int_const_binop (enum tree_code code, tree val1, tree val2)
 }
 
 
-/* For range VR compute two double_int bitmasks.  In *MAY_BE_NONZERO
+/* For range VR compute two wide_int bitmasks.  In *MAY_BE_NONZERO
    bitmask if some bit is unset, it means for all numbers in the range
    the bit is 0, otherwise it might be 0 or 1.  In *MUST_BE_NONZERO
    bitmask if some bit is set, it means for all numbers in the range
@@ -1970,11 +1987,11 @@ vrp_int_const_binop (enum tree_code code, tree val1, tree val2)
 
 static bool
 zero_nonzero_bits_from_vr (value_range_t *vr,
-			   double_int *may_be_nonzero,
-			   double_int *must_be_nonzero)
+			   wide_int *may_be_nonzero,
+			   wide_int *must_be_nonzero)
 {
-  *may_be_nonzero = double_int_minus_one;
-  *must_be_nonzero = double_int_zero;
+  *may_be_nonzero = wide_int::minus_one (largest_bitsize, largest_precision);
+  *must_be_nonzero = wide_int::zero (largest_bitsize, largest_precision);
   if (!range_int_cst_p (vr)
       || TREE_OVERFLOW (vr->min)
       || TREE_OVERFLOW (vr->max))
@@ -1982,34 +1999,24 @@ zero_nonzero_bits_from_vr (value_range_t *vr,
 
   if (range_int_cst_singleton_p (vr))
     {
-      *may_be_nonzero = tree_to_double_int (vr->min);
+      *may_be_nonzero = tree_to_infinite_wide_int (vr->min);
       *must_be_nonzero = *may_be_nonzero;
     }
   else if (tree_int_cst_sgn (vr->min) >= 0
 	   || tree_int_cst_sgn (vr->max) < 0)
     {
-      double_int dmin = tree_to_double_int (vr->min);
-      double_int dmax = tree_to_double_int (vr->max);
-      double_int xor_mask = dmin ^ dmax;
+      wide_int dmin = tree_to_infinite_wide_int (vr->min);
+      wide_int dmax = tree_to_infinite_wide_int (vr->max);
+      wide_int xor_mask = dmin ^ dmax;
       *may_be_nonzero = dmin | dmax;
       *must_be_nonzero = dmin & dmax;
-      if (xor_mask.high != 0)
+      if (!xor_mask.zero_p ())
 	{
-	  unsigned HOST_WIDE_INT mask
-	      = ((unsigned HOST_WIDE_INT) 1
-		 << floor_log2 (xor_mask.high)) - 1;
-	  may_be_nonzero->low = ALL_ONES;
-	  may_be_nonzero->high |= mask;
-	  must_be_nonzero->low = 0;
-	  must_be_nonzero->high &= ~mask;
-	}
-      else if (xor_mask.low != 0)
-	{
-	  unsigned HOST_WIDE_INT mask
-	      = ((unsigned HOST_WIDE_INT) 1
-		 << floor_log2 (xor_mask.low)) - 1;
-	  may_be_nonzero->low |= mask;
-	  must_be_nonzero->low &= ~mask;
+	  wide_int mask = wide_int::mask (xor_mask.floor_log2 (), 
+					  false, largest_bitsize, 
+					  largest_precision);
+	  *may_be_nonzero = (*may_be_nonzero) | mask;
+	  *must_be_nonzero = (*must_be_nonzero).and_not (mask);
 	}
     }
 
@@ -2042,15 +2049,21 @@ ranges_from_anti_range (value_range_t *ar,
       vr0->type = VR_RANGE;
       vr0->min = vrp_val_min (type);
       vr0->max
-	= double_int_to_tree (type,
-			      tree_to_double_int (ar->min) - double_int_one);
+	= wide_int_to_infinite_tree (type,
+				     tree_to_infinite_wide_int (ar->min) 
+				     - wide_int::one (largest_bitsize, 
+						      largest_precision),
+				     largest_precision);
     }
   if (!vrp_val_is_max (ar->max))
     {
       vr1->type = VR_RANGE;
       vr1->min
-	= double_int_to_tree (type,
-			      tree_to_double_int (ar->max) + double_int_one);
+	= wide_int_to_infinite_tree (type,
+				     tree_to_infinite_wide_int (ar->max) 
+				     + wide_int::one (largest_bitsize, 
+						      largest_precision),
+				     largest_precision);
       vr1->max = vrp_val_max (type);
     }
   if (vr0->type == VR_UNDEFINED)
@@ -2216,28 +2229,6 @@ extract_range_from_multiplicative_op_1 (value_range_t *vr,
     set_value_range (vr, type, min, max, NULL);
 }
 
-/* Some quadruple precision helpers.  */
-static int
-quad_int_cmp (double_int l0, double_int h0,
-	      double_int l1, double_int h1, bool uns)
-{
-  int c = h0.cmp (h1, uns);
-  if (c != 0) return c;
-  return l0.ucmp (l1);
-}
-
-static void
-quad_int_pair_sort (double_int *l0, double_int *h0,
-		    double_int *l1, double_int *h1, bool uns)
-{
-  if (quad_int_cmp (*l0, *h0, *l1, *h1, uns) > 0)
-    {
-      double_int tmp;
-      tmp = *l0; *l0 = *l1; *l1 = tmp;
-      tmp = *h0; *h0 = *h1; *h1 = tmp;
-    }
-}
-
 /* 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.  */
@@ -2252,6 +2243,8 @@ extract_range_from_binary_expr_1 (value_range_t *vr,
   enum value_range_type type;
   tree min = NULL_TREE, max = NULL_TREE;
   int cmp;
+  wide_int::SignOp sgn = TYPE_UNSIGNED (expr_type) 
+    ? wide_int::UNSIGNED : wide_int::UNSIGNED;
 
   if (!INTEGRAL_TYPE_P (expr_type)
       && !POINTER_TYPE_P (expr_type))
@@ -2407,32 +2400,34 @@ extract_range_from_binary_expr_1 (value_range_t *vr,
       /* If we have a PLUS_EXPR with two VR_RANGE integer constant
          ranges compute the precise range for such case if possible.  */
       if (range_int_cst_p (&vr0)
-	  && range_int_cst_p (&vr1)
-	  /* We need as many bits as the possibly unsigned inputs.  */
-	  && TYPE_PRECISION (expr_type) <= HOST_BITS_PER_DOUBLE_INT)
-	{
-	  double_int min0 = tree_to_double_int (vr0.min);
-	  double_int max0 = tree_to_double_int (vr0.max);
-	  double_int min1 = tree_to_double_int (vr1.min);
-	  double_int max1 = tree_to_double_int (vr1.max);
-	  bool uns = TYPE_UNSIGNED (expr_type);
-	  double_int type_min
-	    = double_int::min_value (TYPE_PRECISION (expr_type), uns);
-	  double_int type_max
-	    = double_int::max_value (TYPE_PRECISION (expr_type), uns);
-	  double_int dmin, dmax;
+	  && range_int_cst_p (&vr1))
+	{
+	  wide_int min0 = tree_to_infinite_wide_int (vr0.min);
+	  wide_int max0 = tree_to_infinite_wide_int (vr0.max);
+	  wide_int min1 = tree_to_infinite_wide_int (vr1.min);
+	  wide_int max1 = tree_to_infinite_wide_int (vr1.max);
+	  wide_int::SignOp uns = TYPE_UNSIGNED (expr_type) 
+	    ? wide_int::UNSIGNED : wide_int::SIGNED;
+	  wide_int type_min = wide_int::min_value (expr_type)
+	    .force_to_size (largest_bitsize, largest_precision, uns)
+	    .ext (TYPE_PRECISION (expr_type), uns);
+	  wide_int type_max = wide_int::max_value (expr_type)
+	    .force_to_size (largest_bitsize, largest_precision, uns)
+	    .ext (TYPE_PRECISION (expr_type), wide_int::UNSIGNED);
+	  wide_int dmin, dmax;
 	  int min_ovf = 0;
 	  int max_ovf = 0;
+	  wide_int zero = wide_int::zero (largest_bitsize, largest_precision);
 
 	  if (code == PLUS_EXPR)
 	    {
 	      dmin = min0 + min1;
 	      dmax = max0 + max1;
 
-	      /* Check for overflow in double_int.  */
-	      if (min1.cmp (double_int_zero, uns) != dmin.cmp (min0, uns))
+	      /* Check for overflow in wide_int.  */
+	      if (min1.cmp (zero, uns) != dmin.cmp (min0, uns))
 		min_ovf = min0.cmp (dmin, uns);
-	      if (max1.cmp (double_int_zero, uns) != dmax.cmp (max0, uns))
+	      if (max1.cmp (zero, uns) != dmax.cmp (max0, uns))
 		max_ovf = max0.cmp (dmax, uns);
 	    }
 	  else /* if (code == MINUS_EXPR) */
@@ -2440,9 +2435,9 @@ extract_range_from_binary_expr_1 (value_range_t *vr,
 	      dmin = min0 - max1;
 	      dmax = max0 - min1;
 
-	      if (double_int_zero.cmp (max1, uns) != dmin.cmp (min0, uns))
+	      if (zero.cmp (max1, uns) != dmin.cmp (min0, uns))
 		min_ovf = min0.cmp (max1, uns);
-	      if (double_int_zero.cmp (min1, uns) != dmax.cmp (max0, uns))
+	      if (zero.cmp (min1, uns) != dmax.cmp (max0, uns))
 		max_ovf = max0.cmp (min1, uns);
 	    }
 
@@ -2451,9 +2446,9 @@ extract_range_from_binary_expr_1 (value_range_t *vr,
 	  if (!TYPE_OVERFLOW_WRAPS (expr_type))
 	    {
 	      if (vrp_val_min (expr_type))
-		type_min = tree_to_double_int (vrp_val_min (expr_type));
+		type_min = tree_to_infinite_wide_int (vrp_val_min (expr_type));
 	      if (vrp_val_max (expr_type))
-		type_max = tree_to_double_int (vrp_val_max (expr_type));
+		type_max = tree_to_infinite_wide_int (vrp_val_max (expr_type));
 	    }
 
 	  /* Check for type overflow.  */
@@ -2476,19 +2471,16 @@ extract_range_from_binary_expr_1 (value_range_t *vr,
 	    {
 	      /* If overflow wraps, truncate the values and adjust the
 		 range kind and bounds appropriately.  */
-	      double_int tmin
-		= dmin.ext (TYPE_PRECISION (expr_type), uns);
-	      double_int tmax
-		= dmax.ext (TYPE_PRECISION (expr_type), uns);
+	      wide_int tmin = dmin.ext (TYPE_PRECISION (expr_type), uns);
+	      wide_int tmax = dmax.ext (TYPE_PRECISION (expr_type), uns);
 	      if (min_ovf == max_ovf)
 		{
 		  /* No overflow or both overflow or underflow.  The
 		     range kind stays VR_RANGE.  */
-		  min = double_int_to_tree (expr_type, tmin);
-		  max = double_int_to_tree (expr_type, tmax);
+		  min = wide_int_to_infinite_tree (expr_type, tmin, largest_precision);
+		  max = wide_int_to_infinite_tree (expr_type, tmax, largest_precision);
 		}
-	      else if (min_ovf == -1
-		       && max_ovf == 1)
+	      else if (min_ovf == -1 && max_ovf == 1)
 		{
 		  /* Underflow and overflow, drop to VR_VARYING.  */
 		  set_value_range_to_varying (vr);
@@ -2499,26 +2491,30 @@ extract_range_from_binary_expr_1 (value_range_t *vr,
 		  /* Min underflow or max overflow.  The range kind
 		     changes to VR_ANTI_RANGE.  */
 		  bool covers = false;
-		  double_int tem = tmin;
+		  wide_int tem = tmin;
 		  gcc_assert ((min_ovf == -1 && max_ovf == 0)
 			      || (max_ovf == 1 && min_ovf == 0));
 		  type = VR_ANTI_RANGE;
-		  tmin = tmax + double_int_one;
-		  if (tmin.cmp (tmax, uns) < 0)
+		  tmin = tmax + wide_int::one (largest_bitsize, 
+					       largest_precision);
+		  if (tmin.lt_p (tmax, uns))
 		    covers = true;
-		  tmax = tem + double_int_minus_one;
-		  if (tmax.cmp (tem, uns) > 0)
+		  tmax = tem + wide_int::minus_one (largest_bitsize, 
+						    largest_precision);
+		  if (tmax.gt_p (tem, uns))
 		    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 || tmin.cmp (tmax, uns) > 0)
+		  if (covers || tmin.gt_p (tmax, uns))
 		    {
 		      set_value_range_to_varying (vr);
 		      return;
 		    }
-		  min = double_int_to_tree (expr_type, tmin);
-		  max = double_int_to_tree (expr_type, tmax);
+		  min = wide_int_to_infinite_tree (expr_type, tmin,
+						   largest_precision);
+		  max = wide_int_to_infinite_tree (expr_type, tmax, 
+						   largest_precision);
 		}
 	    }
 	  else
@@ -2531,7 +2527,8 @@ extract_range_from_binary_expr_1 (value_range_t *vr,
 		      && supports_overflow_infinity (expr_type))
 		    min = negative_overflow_infinity (expr_type);
 		  else
-		    min = double_int_to_tree (expr_type, type_min);
+		    min = wide_int_to_infinite_tree (expr_type, type_min, 
+						     largest_precision);
 		}
 	      else if (min_ovf == 1)
 		{
@@ -2539,10 +2536,12 @@ extract_range_from_binary_expr_1 (value_range_t *vr,
 		      && supports_overflow_infinity (expr_type))
 		    min = positive_overflow_infinity (expr_type);
 		  else
-		    min = double_int_to_tree (expr_type, type_max);
+		    min = wide_int_to_infinite_tree (expr_type, type_max,
+						     largest_precision);
 		}
 	      else
-		min = double_int_to_tree (expr_type, dmin);
+		min = wide_int_to_infinite_tree (expr_type, dmin,
+						 largest_precision);
 
 	      if (max_ovf == -1)
 		{
@@ -2550,7 +2549,8 @@ extract_range_from_binary_expr_1 (value_range_t *vr,
 		      && supports_overflow_infinity (expr_type))
 		    max = negative_overflow_infinity (expr_type);
 		  else
-		    max = double_int_to_tree (expr_type, type_min);
+		    max = wide_int_to_infinite_tree (expr_type, type_min,
+						     largest_precision);
 		}
 	      else if (max_ovf == 1)
 		{
@@ -2558,10 +2558,12 @@ extract_range_from_binary_expr_1 (value_range_t *vr,
 		      && supports_overflow_infinity (expr_type))
 		    max = positive_overflow_infinity (expr_type);
 		  else
-		    max = double_int_to_tree (expr_type, type_max);
+		    max = wide_int_to_infinite_tree (expr_type, type_max,
+						     largest_precision);
 		}
 	      else
-		max = double_int_to_tree (expr_type, dmax);
+		max = wide_int_to_infinite_tree (expr_type, dmax,
+						 largest_precision);
 	    }
 	  if (needs_overflow_infinity (expr_type)
 	      && supports_overflow_infinity (expr_type))
@@ -2624,92 +2626,133 @@ extract_range_from_binary_expr_1 (value_range_t *vr,
 	  && range_int_cst_p (&vr1)
 	  && TYPE_OVERFLOW_WRAPS (expr_type))
 	{
-	  double_int min0, max0, min1, max1, sizem1, size;
-	  double_int prod0l, prod0h, prod1l, prod1h,
-		     prod2l, prod2h, prod3l, prod3h;
-	  bool uns0, uns1, uns;
-
-	  sizem1 = double_int::max_value (TYPE_PRECISION (expr_type), true);
-	  size = sizem1 + double_int_one;
+	  wide_int min0, max0, min1, max1, sizem1, size;
+	  wide_int prod0, prod1, prod2, prod3;
+	  wide_int::SignOp uns0, uns1, uns;
+
+	  /* The largest_precision and the largest_bitsize are already
+	     twice the size of the largest type that has been seen in
+	     this function.  We do not need to multiply them by a
+	     factor of two again to do this analysis.  So we trim them
+	     down to the size of the largest types seen and then we
+	     will fix things up at the end.  */
+
+	  int bs2 = largest_bitsize*2;
+	  int prec2 = largest_precision*2;
+
+	  /* Use the mode here to force the unsigned max value.  */
+	  sizem1 = wide_int::max_value (TYPE_MODE (expr_type), wide_int::UNSIGNED)
+	    .force_to_size (largest_bitsize, largest_precision, wide_int::UNSIGNED)
+	    .zext (TYPE_PRECISION (expr_type));
+	  size = sizem1 + wide_int::one (largest_bitsize, largest_precision);
+
+	  uns0 = TYPE_UNSIGNED (expr_type) 
+	    ? wide_int::UNSIGNED : wide_int::SIGNED;
+
+	  min0 = tree_to_infinite_wide_int (vr0.min)
+	    .force_to_size (largest_bitsize, largest_precision, uns0);
+	  max0 = tree_to_infinite_wide_int (vr0.max)
+	    .force_to_size (largest_bitsize, largest_precision, uns0);
+	  min1 = tree_to_infinite_wide_int (vr1.min)
+	    .force_to_size (largest_bitsize, largest_precision, uns0);
+	  max1 = tree_to_infinite_wide_int (vr1.max)
+	    .force_to_size (largest_bitsize, largest_precision, uns0);
 
-	  min0 = tree_to_double_int (vr0.min);
-	  max0 = tree_to_double_int (vr0.max);
-	  min1 = tree_to_double_int (vr1.min);
-	  max1 = tree_to_double_int (vr1.max);
-
-	  uns0 = TYPE_UNSIGNED (expr_type);
 	  uns1 = uns0;
 
 	  /* Canonicalize the intervals.  */
 	  if (TYPE_UNSIGNED (expr_type))
 	    {
-	      double_int min2 = size - min0;
-	      if (min2.cmp (max0, true) < 0)
+	      wide_int min2 = size - min0;
+	      if (min2.ltu_p (max0))
 		{
-		  min0 = -min2;
-		  max0 -= size;
-		  uns0 = false;
+		  min0 = min2.neg ();
+		  max0 = max0 - size;
+		  uns0 = wide_int::SIGNED;
 		}
 
 	      min2 = size - min1;
-	      if (min2.cmp (max1, true) < 0)
+	      if (min2.ltu_p (max1))
 		{
-		  min1 = -min2;
-		  max1 -= size;
-		  uns1 = false;
+		  min1 = min2.neg();
+		  max1 = max1 - size;
+		  uns1 = wide_int::SIGNED;
 		}
 	    }
-	  uns = uns0 & uns1;
-
-	  bool overflow;
-	  prod0l = min0.wide_mul_with_sign (min1, true, &prod0h, &overflow);
-	  if (!uns0 && min0.is_negative ())
-	    prod0h -= min1;
-	  if (!uns1 && min1.is_negative ())
-	    prod0h -= min0;
-
-	  prod1l = min0.wide_mul_with_sign (max1, true, &prod1h, &overflow);
-	  if (!uns0 && min0.is_negative ())
-	    prod1h -= max1;
-	  if (!uns1 && max1.is_negative ())
-	    prod1h -= min0;
-
-	  prod2l = max0.wide_mul_with_sign (min1, true, &prod2h, &overflow);
-	  if (!uns0 && max0.is_negative ())
-	    prod2h -= min1;
-	  if (!uns1 && min1.is_negative ())
-	    prod2h -= max0;
-
-	  prod3l = max0.wide_mul_with_sign (max1, true, &prod3h, &overflow);
-	  if (!uns0 && max0.is_negative ())
-	    prod3h -= max1;
-	  if (!uns1 && max1.is_negative ())
-	    prod3h -= max0;
-
-	  /* Sort the 4 products.  */
-	  quad_int_pair_sort (&prod0l, &prod0h, &prod3l, &prod3h, uns);
-	  quad_int_pair_sort (&prod1l, &prod1h, &prod2l, &prod2h, uns);
-	  quad_int_pair_sort (&prod0l, &prod0h, &prod1l, &prod1h, uns);
-	  quad_int_pair_sort (&prod2l, &prod2h, &prod3l, &prod3h, uns);
 
-	  /* Max - min.  */
-	  if (prod0l.is_zero ())
+	  uns = ((uns0 == wide_int::UNSIGNED) & (uns1 == wide_int::UNSIGNED))
+	    ? wide_int::UNSIGNED : wide_int::SIGNED;
+
+	  prod0 = min0.umul_full (min1);
+	  if (uns0 == wide_int::SIGNED && min0.neg_p ())
+	    prod0 = prod0 - min1.lshift (largest_precision, wide_int::NONE, 
+					 bs2, prec2);
+	  if (uns1 == wide_int::SIGNED && min1.neg_p ())
+	    prod0 = prod0 - min0.lshift (largest_precision, wide_int::NONE, 
+					 bs2, prec2);
+
+	  prod1 = min0.umul_full (max1);
+	  if (uns0 == wide_int::SIGNED && min0.neg_p ())
+	    prod1 = prod1 - max1.lshift (largest_precision, wide_int::NONE, 
+					 bs2, prec2);
+	  if (uns1 == wide_int::SIGNED && max1.neg_p ())
+	    prod1 = prod1 - min0.lshift (largest_precision, wide_int::NONE, 
+					 bs2, prec2);
+
+	  prod2 = max0.umul_full (min1);
+	  if (uns0 == wide_int::SIGNED && max0.neg_p ())
+	    prod2 = prod2 - min1.lshift (largest_precision, wide_int::NONE, 
+					 bs2, prec2);
+	  if (uns1 == wide_int::SIGNED && min1.neg_p ())
+	    prod2 = prod2 - max0.lshift (largest_precision, wide_int::NONE, 
+					 bs2, prec2);
+
+	  prod3 = max0.umul_full (max1);
+	  if (uns0 == wide_int::SIGNED && max0.neg_p ())
+	    prod3 = prod3 - max1.lshift (largest_precision, wide_int::NONE, 
+					 bs2, prec2);
+	  if (uns1 == wide_int::SIGNED && max1.neg_p ())
+	    prod3 = prod3 - max0.lshift (largest_precision, wide_int::NONE, 
+					 bs2, prec2);
+
+	  /* Sort the 4 products so that min is in prod0 and max is in
+	     prod3.  */
+
+	  /* min0min1 > max0max1 */
+	  if (!prod0.lt_p (prod3, uns))
 	    {
-	      prod1l = double_int_zero;
-	      prod1h = -prod0h;
+	      wide_int tmp = prod0;
+	      prod0 = prod3;
+	      prod3 = tmp;
 	    }
-	  else
+	  
+	  /* min0max1 > max0min1 */
+	  if (!prod1.lt_p (prod2, uns))
 	    {
-	      prod1l = -prod0l;
-	      prod1h = ~prod0h;
+	      wide_int tmp = prod1;
+	      prod1 = prod2;
+	      prod2 = tmp;
 	    }
-	  prod2l = prod3l + prod1l;
-	  prod2h = prod3h + prod1h;
-	  if (prod2l.ult (prod3l))
-	    prod2h += double_int_one; /* carry */
 
-	  if (!prod2h.is_zero ()
-	      || prod2l.cmp (sizem1, true) >= 0)
+	  if (!prod0.lt_p (prod1, uns))
+	    {
+	      wide_int tmp = prod0;
+	      prod0 = prod1;
+	      prod1 = tmp;
+	    }
+
+	  if (!prod2.lt_p (prod3, uns))
+	    {
+	      wide_int tmp = prod2;
+	      prod2 = prod3;
+	      prod3 = tmp;
+	    }
+
+	  /* Max - min.  */
+	  prod2 = prod3 - prod0;
+	  if (sizem1.force_to_size (bs2, prec2, 
+				    wide_int::UNSIGNED)
+	      .ltu_p (prod2))
 	    {
 	      /* the range covers all values.  */
 	      set_value_range_to_varying (vr);
@@ -2718,8 +2761,10 @@ extract_range_from_binary_expr_1 (value_range_t *vr,
 
 	  /* The following should handle the wrapping and selecting
 	     VR_ANTI_RANGE for us.  */
-	  min = double_int_to_tree (expr_type, prod0l);
-	  max = double_int_to_tree (expr_type, prod3l);
+	  min = wide_int_to_infinite_tree (expr_type, prod0,
+					   prec2);
+	  max = wide_int_to_infinite_tree (expr_type, prod3,
+					   prec2);
 	  set_and_canonicalize_value_range (vr, VR_RANGE, min, max, NULL);
 	  return;
 	}
@@ -2766,11 +2811,11 @@ extract_range_from_binary_expr_1 (value_range_t *vr,
 	      bool saved_flag_wrapv;
 	      value_range_t vr1p = VR_INITIALIZER;
 	      vr1p.type = VR_RANGE;
-	      vr1p.min
-		= double_int_to_tree (expr_type,
-				      double_int_one
-				      .llshift (tree_to_shwi (vr1.min),
-					        TYPE_PRECISION (expr_type)));
+	      vr1p.min = wide_int_to_infinite_tree 
+		(expr_type,
+		 wide_int::set_bit_in_zero (tree_to_uhwi (vr1.min),
+					    largest_bitsize, largest_precision),
+		 largest_precision);
 	      vr1p.max = vr1p.min;
 	      /* We have to use a wrapping multiply though as signed overflow
 		 on lshifts is implementation defined in C89.  */
@@ -2787,7 +2832,7 @@ extract_range_from_binary_expr_1 (value_range_t *vr,
 	      int prec = TYPE_PRECISION (expr_type);
 	      int overflow_pos = prec;
 	      int bound_shift;
-	      double_int bound, complement, low_bound, high_bound;
+	      wide_int bound, complement, low_bound, high_bound;
 	      bool uns = TYPE_UNSIGNED (expr_type);
 	      bool in_bounds = false;
 
@@ -2800,21 +2845,23 @@ extract_range_from_binary_expr_1 (value_range_t *vr,
 		 zero, which means vr1 is a singleton range of zero, which
 		 means it should be handled by the previous LSHIFT_EXPR
 		 if-clause.  */
-	      bound = double_int_one.llshift (bound_shift, prec);
-	      complement = ~(bound - double_int_one);
+	      bound = wide_int::set_bit_in_zero (bound_shift, 
+						 largest_bitsize, 
+						 largest_precision);
+	      complement = bound.neg ();
 
 	      if (uns)
 		{
 		  low_bound = bound;
 		  high_bound = complement.zext (prec);
-		  if (tree_to_double_int (vr0.max).ult (low_bound))
+		  if (tree_to_infinite_wide_int (vr0.max).ltu_p (low_bound))
 		    {
 		      /* [5, 6] << [1, 2] == [10, 24].  */
 		      /* We're shifting out only zeroes, the value increases
 			 monotonically.  */
 		      in_bounds = true;
 		    }
-		  else if (high_bound.ult (tree_to_double_int (vr0.min)))
+		  else if (high_bound.ltu_p (tree_to_infinite_wide_int (vr0.min)))
 		    {
 		      /* [0xffffff00, 0xffffffff] << [1, 2]
 		         == [0xfffffc00, 0xfffffffe].  */
@@ -2828,8 +2875,8 @@ extract_range_from_binary_expr_1 (value_range_t *vr,
 		  /* [-1, 1] << [1, 2] == [-4, 4].  */
 		  low_bound = complement.sext (prec);
 		  high_bound = bound;
-		  if (tree_to_double_int (vr0.max).slt (high_bound)
-		      && low_bound.slt (tree_to_double_int (vr0.min)))
+		  if (tree_to_infinite_wide_int (vr0.max).lts_p (high_bound)
+		      && low_bound.lts_p (tree_to_infinite_wide_int (vr0.min)))
 		    {
 		      /* For non-negative numbers, we're shifting out only
 			 zeroes, the value increases monotonically.
@@ -2965,8 +3012,8 @@ extract_range_from_binary_expr_1 (value_range_t *vr,
   else if (code == BIT_AND_EXPR || code == BIT_IOR_EXPR || code == BIT_XOR_EXPR)
     {
       bool int_cst_range0, int_cst_range1;
-      double_int may_be_nonzero0, may_be_nonzero1;
-      double_int must_be_nonzero0, must_be_nonzero1;
+      wide_int may_be_nonzero0, may_be_nonzero1;
+      wide_int must_be_nonzero0, must_be_nonzero1;
 
       int_cst_range0 = zero_nonzero_bits_from_vr (&vr0, &may_be_nonzero0,
 						  &must_be_nonzero0);
@@ -2976,10 +3023,13 @@ extract_range_from_binary_expr_1 (value_range_t *vr,
       type = VR_RANGE;
       if (code == BIT_AND_EXPR)
 	{
-	  double_int dmax;
-	  min = double_int_to_tree (expr_type,
-				    must_be_nonzero0 & must_be_nonzero1);
+	  wide_int dmax;
+	    
+	  min = wide_int_to_infinite_tree (expr_type,
+					   must_be_nonzero0 & must_be_nonzero1,
+					   largest_precision);
 	  dmax = may_be_nonzero0 & may_be_nonzero1;
+
 	  /* If both input ranges contain only negative values we can
 	     truncate the result range maximum to the minimum of the
 	     input range maxima.  */
@@ -2987,27 +3037,26 @@ extract_range_from_binary_expr_1 (value_range_t *vr,
 	      && tree_int_cst_sgn (vr0.max) < 0
 	      && tree_int_cst_sgn (vr1.max) < 0)
 	    {
-	      dmax = dmax.min (tree_to_double_int (vr0.max),
-				     TYPE_UNSIGNED (expr_type));
-	      dmax = dmax.min (tree_to_double_int (vr1.max),
-				     TYPE_UNSIGNED (expr_type));
+	      dmax = dmax.min (tree_to_infinite_wide_int (vr0.max), sgn);
+	      dmax = dmax.min (tree_to_infinite_wide_int (vr1.max), sgn);
 	    }
 	  /* If either input range contains only non-negative values
 	     we can truncate the result range maximum to the respective
 	     maximum of the input range.  */
 	  if (int_cst_range0 && tree_int_cst_sgn (vr0.min) >= 0)
-	    dmax = dmax.min (tree_to_double_int (vr0.max),
-				   TYPE_UNSIGNED (expr_type));
+	    dmax = dmax.min (tree_to_infinite_wide_int (vr0.max), sgn);
+
 	  if (int_cst_range1 && tree_int_cst_sgn (vr1.min) >= 0)
-	    dmax = dmax.min (tree_to_double_int (vr1.max),
-				   TYPE_UNSIGNED (expr_type));
-	  max = double_int_to_tree (expr_type, dmax);
+	    dmax = dmax.min (tree_to_infinite_wide_int (vr1.max), sgn);
+	  max = wide_int_to_infinite_tree (expr_type, dmax,
+					   largest_precision);
 	}
       else if (code == BIT_IOR_EXPR)
 	{
-	  double_int dmin;
-	  max = double_int_to_tree (expr_type,
-				    may_be_nonzero0 | may_be_nonzero1);
+	  wide_int dmin;
+	  max = wide_int_to_infinite_tree (expr_type, 
+					   may_be_nonzero0 | may_be_nonzero1,
+					   largest_precision);
 	  dmin = must_be_nonzero0 | must_be_nonzero1;
 	  /* If the input ranges contain only positive values we can
 	     truncate the minimum of the result range to the maximum
@@ -3016,35 +3065,35 @@ extract_range_from_binary_expr_1 (value_range_t *vr,
 	      && tree_int_cst_sgn (vr0.min) >= 0
 	      && tree_int_cst_sgn (vr1.min) >= 0)
 	    {
-	      dmin = dmin.max (tree_to_double_int (vr0.min),
-			       TYPE_UNSIGNED (expr_type));
-	      dmin = dmin.max (tree_to_double_int (vr1.min),
-			       TYPE_UNSIGNED (expr_type));
+	      dmin = dmin.max (tree_to_infinite_wide_int (vr0.min), sgn);
+	      dmin = dmin.max (tree_to_infinite_wide_int (vr1.min), sgn);
 	    }
 	  /* If either input range contains only negative values
 	     we can truncate the minimum of the result range to the
 	     respective minimum range.  */
 	  if (int_cst_range0 && tree_int_cst_sgn (vr0.max) < 0)
-	    dmin = dmin.max (tree_to_double_int (vr0.min),
-			     TYPE_UNSIGNED (expr_type));
+	    dmin = dmin.max (tree_to_infinite_wide_int (vr0.min), sgn);
 	  if (int_cst_range1 && tree_int_cst_sgn (vr1.max) < 0)
-	    dmin = dmin.max (tree_to_double_int (vr1.min),
-			     TYPE_UNSIGNED (expr_type));
-	  min = double_int_to_tree (expr_type, dmin);
+	    dmin = dmin.max (tree_to_infinite_wide_int (vr1.min), sgn);
+	  min = wide_int_to_infinite_tree (expr_type, dmin,
+					   largest_precision);
 	}
       else if (code == BIT_XOR_EXPR)
 	{
-	  double_int result_zero_bits, result_one_bits;
-	  result_zero_bits = (must_be_nonzero0 & must_be_nonzero1)
-			     | ~(may_be_nonzero0 | may_be_nonzero1);
-	  result_one_bits = must_be_nonzero0.and_not (may_be_nonzero1)
-			    | must_be_nonzero1.and_not (may_be_nonzero0);
-	  max = double_int_to_tree (expr_type, ~result_zero_bits);
-	  min = double_int_to_tree (expr_type, result_one_bits);
+	  wide_int result_zero_bits, result_one_bits;
+	  result_zero_bits
+	    = (must_be_nonzero0 & must_be_nonzero1).or_not
+	    (may_be_nonzero0 | may_be_nonzero1);
+	  result_one_bits
+	    = must_be_nonzero0.and_not (may_be_nonzero1)
+	    | must_be_nonzero1.and_not (may_be_nonzero0);
+	  max = wide_int_to_infinite_tree (expr_type, ~result_zero_bits,
+					   largest_precision);
+	  min = wide_int_to_infinite_tree (expr_type, result_one_bits,
+					   largest_precision);
 	  /* If the range has all positive or all negative values the
 	     result is better than VARYING.  */
-	  if (tree_int_cst_sgn (min) < 0
-	      || tree_int_cst_sgn (max) >= 0)
+	  if (tree_int_cst_sgn (min) < 0 || tree_int_cst_sgn (max) >= 0)
 	    ;
 	  else
 	    max = min = NULL_TREE;
@@ -3252,18 +3301,27 @@ extract_range_from_unary_expr_1 (value_range_t *vr,
 		         size_int (TYPE_PRECISION (outer_type)))))))
 	{
 	  tree new_min, new_max;
+	  wide_int::SignOp inner_type_sgn = 
+	    TYPE_UNSIGNED (inner_type) ? wide_int::UNSIGNED : wide_int::SIGNED;
+	  /* We want to extend these from the inner type to the outer
+	     type using the signedness of the inner type but the
+	     precision of the outer type.  */
 	  if (is_overflow_infinity (vr0.min))
 	    new_min = negative_overflow_infinity (outer_type);
 	  else
-	    new_min = force_fit_type_double (outer_type,
-					     tree_to_double_int (vr0.min),
-					     0, false);
+	    new_min = wide_int_to_infinite_tree 
+	      (outer_type,
+	       tree_to_infinite_wide_int (vr0.min)
+	       .ext (TYPE_PRECISION (outer_type), inner_type_sgn),
+	       largest_precision);
 	  if (is_overflow_infinity (vr0.max))
 	    new_max = positive_overflow_infinity (outer_type);
 	  else
-	    new_max = force_fit_type_double (outer_type,
-					     tree_to_double_int (vr0.max),
-					     0, false);
+	    new_max = wide_int_to_infinite_tree
+	      (outer_type,
+	       tree_to_infinite_wide_int (vr0.max)
+	       .ext (TYPE_PRECISION (outer_type), inner_type_sgn),
+	       largest_precision);
 	  set_and_canonicalize_value_range (vr, vr0.type,
 					    new_min, new_max, NULL);
 	  return;
@@ -3660,30 +3718,33 @@ adjust_range_with_scev (value_range_t *vr, struct loop *loop,
       && (TREE_CODE (init) != SSA_NAME
 	  || get_value_range (init)->type == VR_RANGE))
     {
-      double_int nit;
+      wide_int nit;
+      wide_int wstep = tree_to_infinite_wide_int (step); 
 
       /* We are only entering here for loop header PHI nodes, so using
 	 the number of latch executions is the correct thing to use.  */
-      if (max_loop_iterations (loop, &nit))
+      if (max_loop_iterations (loop, &nit,
+			       wstep.get_bitsize (), wstep.get_precision()))
 	{
 	  value_range_t maxvr = VR_INITIALIZER;
-	  double_int dtmp;
-	  bool unsigned_p = TYPE_UNSIGNED (TREE_TYPE (step));
+	  wide_int dtmp;
+	  wide_int::SignOp uns = TYPE_UNSIGNED (TREE_TYPE (step)) 
+	    ? wide_int::UNSIGNED : wide_int::SIGNED;
 	  bool overflow = false;
 
-	  dtmp = tree_to_double_int (step)
-		 .mul_with_sign (nit, unsigned_p, &overflow);
+	  dtmp = wstep.mul (nit, uns, &overflow);
 	  /* If the multiplication overflowed we can't do a meaningful
 	     adjustment.  Likewise if the result doesn't fit in the type
 	     of the induction variable.  For a signed type we have to
 	     check whether the result has the expected signedness which
 	     is that of the step as number of iterations is unsigned.  */
 	  if (!overflow
-	      && double_int_fits_to_tree_p (TREE_TYPE (init), dtmp)
-	      && (unsigned_p
-		  || ((dtmp.high ^ TREE_INT_CST_HIGH (step)) >= 0)))
+	      && dtmp.fits_to_tree_p (TREE_TYPE (init))
+	      && (TYPE_UNSIGNED (TREE_TYPE (step))
+		  || (dtmp.neg_p () == tree_int_cst_sign_bit (step))))
 	    {
-	      tem = double_int_to_tree (TREE_TYPE (init), dtmp);
+	      tem = wide_int_to_infinite_tree (TREE_TYPE (init), dtmp,
+					       largest_precision);
 	      extract_range_from_binary_expr (&maxvr, PLUS_EXPR,
 					      TREE_TYPE (init), init, tem);
 	      /* Likewise if the addition did.  */
@@ -4404,9 +4465,9 @@ register_new_assert_for (tree name, tree expr,
      machinery.  */
   if (TREE_CODE (val) == INTEGER_CST
       && TREE_OVERFLOW (val))
-    val = build_int_cst_wide (TREE_TYPE (val),
-			      TREE_INT_CST_LOW (val), TREE_INT_CST_HIGH (val));
-
+    val = wide_int_to_infinite_tree
+      (TREE_TYPE (val), tree_to_infinite_wide_int (val), largest_precision);
+  
   /* The new assertion A will be inserted at BB or E.  We need to
      determine if the new location is dominated by a previously
      registered location for A.  If we are doing an edge insertion,
@@ -4558,23 +4619,27 @@ extract_code_and_val_from_cond_with_ops (tree name, enum tree_code cond_code,
    (to transform signed values into unsigned) and at the end xor
    SGNBIT back.  */
 
-static double_int
-masked_increment (double_int val, double_int mask, double_int sgnbit,
-		  unsigned int prec)
+static wide_int
+masked_increment (const wide_int &val_in, const wide_int &mask_in, 
+		  const wide_int &sgnbit, const_tree type)
 {
-  double_int bit = double_int_one, res;
+  wide_int val = val_in.zext (TYPE_PRECISION (type));
+  wide_int mask = mask_in.zext (TYPE_PRECISION (type));
+  wide_int one = wide_int::one (largest_bitsize, largest_precision);
+  wide_int bit = one, res;
+  unsigned int prec = TYPE_PRECISION (type);
   unsigned int i;
 
-  val ^= sgnbit;
-  for (i = 0; i < prec; i++, bit += bit)
+  val = val ^ sgnbit;
+  for (i = 0; i < prec; i++, bit = bit + bit)
     {
       res = mask;
-      if ((res & bit).is_zero ())
+      if ((res & bit).zero_p())
 	continue;
-      res = bit - double_int_one;
+      res = bit - one;
       res = (val + bit).and_not (res);
-      res &= mask;
-      if (res.ugt (val))
+      res = res & mask;
+      if (res.gtu_p (val))
 	return res ^ sgnbit;
     }
   return val ^ sgnbit;
@@ -4710,8 +4775,12 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi,
       gimple def_stmt = SSA_NAME_DEF_STMT (name);
       tree name2 = NULL_TREE, names[2], cst2 = NULL_TREE;
       tree val2 = NULL_TREE;
-      double_int mask = double_int_zero;
-      unsigned int prec = TYPE_PRECISION (TREE_TYPE (val));
+      tree ntype = TREE_TYPE (val);
+      unsigned int prec = TYPE_PRECISION (ntype);
+      wide_int mask = wide_int::zero (largest_bitsize, largest_precision);
+
+      /* Add asserts for NAME cmp CST and NAME being defined
+	 as NAME = (int) NAME2.  */
       unsigned int nprec = prec;
       enum tree_code rhs_code = ERROR_MARK;
 
@@ -4780,12 +4849,12 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi,
 	      && tree_fits_uhwi_p (cst2)
 	      && INTEGRAL_TYPE_P (TREE_TYPE (name2))
 	      && IN_RANGE (tree_to_uhwi (cst2), 1, prec - 1)
-	      && prec <= HOST_BITS_PER_DOUBLE_INT
 	      && prec == GET_MODE_PRECISION (TYPE_MODE (TREE_TYPE (val)))
 	      && live_on_edge (e, name2)
 	      && !has_single_use (name2))
 	    {
-	      mask = double_int::mask (tree_to_uhwi (cst2));
+	      mask = wide_int::mask (tree_to_uhwi (cst2), false, 
+				     largest_bitsize, largest_precision);
 	      val2 = fold_binary (LSHIFT_EXPR, TREE_TYPE (val), val, cst2);
 	    }
 	}
@@ -4808,20 +4877,26 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi,
 		  val2 = fold_convert (type, val2);
 		}
 	      tmp = fold_build2 (MINUS_EXPR, TREE_TYPE (tmp), tmp, val2);
-	      new_val = double_int_to_tree (TREE_TYPE (tmp), mask);
+	      new_val = wide_int_to_infinite_tree (TREE_TYPE (tmp), mask,
+						   largest_precision);
 	      new_comp_code = comp_code == EQ_EXPR ? LE_EXPR : GT_EXPR;
 	    }
 	  else if (comp_code == LT_EXPR || comp_code == GE_EXPR)
 	    new_val = val2;
 	  else
 	    {
-	      double_int maxval
-		= double_int::max_value (prec, TYPE_UNSIGNED (TREE_TYPE (val)));
-	      mask |= tree_to_double_int (val2);
+	      wide_int::SignOp uns = TYPE_UNSIGNED (TREE_TYPE (val))
+		? wide_int::UNSIGNED : wide_int::SIGNED;
+		
+	      wide_int maxval = wide_int::max_value (TREE_TYPE (val))
+		.force_to_size (largest_bitsize, largest_precision, uns)
+		.ext (TYPE_PRECISION (TREE_TYPE (val)), wide_int::UNSIGNED);
+	      mask = tree_to_infinite_wide_int (val2) | mask;
 	      if (mask == maxval)
 		new_val = NULL_TREE;
 	      else
-		new_val = double_int_to_tree (TREE_TYPE (val2), mask);
+		new_val = wide_int_to_infinite_tree (TREE_TYPE (val2), mask,
+						     largest_precision);
 	    }
 
 	  if (new_val)
@@ -4867,13 +4942,13 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi,
 	  else
 	    {
 	      cst2 = TYPE_MAX_VALUE (TREE_TYPE (val));
-	      nprec = TYPE_PRECISION (TREE_TYPE (name2));
+	      ntype = TREE_TYPE (name2);
+	      nprec = TYPE_PRECISION (ntype);
 	    }
 	  if (TREE_CODE (name2) == SSA_NAME
 	      && INTEGRAL_TYPE_P (TREE_TYPE (name2))
 	      && TREE_CODE (cst2) == INTEGER_CST
 	      && !integer_zerop (cst2)
-	      && nprec <= HOST_BITS_PER_DOUBLE_INT
 	      && (nprec > 1
 		  || TYPE_UNSIGNED (TREE_TYPE (val))))
 	    {
@@ -4896,17 +4971,19 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi,
 	}
       if (names[0] || names[1])
 	{
-	  double_int minv, maxv = double_int_zero, valv, cst2v;
-	  double_int tem, sgnbit;
+	  wide_int minv, valv, cst2v;
+	  wide_int zero = wide_int::zero (largest_bitsize, largest_precision);
+	  wide_int maxv = zero;
+	  wide_int tem, sgnbit;
 	  bool valid_p = false, valn = false, cst2n = false;
 	  enum tree_code ccode = comp_code;
 
-	  valv = tree_to_double_int (val).zext (nprec);
-	  cst2v = tree_to_double_int (cst2).zext (nprec);
+	  valv = tree_to_infinite_wide_int (val).zext (nprec);
+	  cst2v = tree_to_infinite_wide_int (cst2).zext (nprec);
 	  if (!TYPE_UNSIGNED (TREE_TYPE (val)))
 	    {
-	      valn = valv.sext (nprec).is_negative ();
-	      cst2n = cst2v.sext (nprec).is_negative ();
+	      valn = valv.sext (nprec).neg_p ();
+	      cst2n = cst2v.sext (nprec).neg_p ();
 	    }
 	  /* If CST2 doesn't have most significant bit set,
 	     but VAL is negative, we have comparison like
@@ -4914,9 +4991,11 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi,
 	  if (!cst2n && valn)
 	    ccode = ERROR_MARK;
 	  if (cst2n)
-	    sgnbit = double_int_one.llshift (nprec - 1, nprec).zext (nprec);
+	    sgnbit = wide_int::set_bit_in_zero (nprec - 1, 
+						largest_bitsize, 
+						largest_precision);
 	  else
-	    sgnbit = double_int_zero;
+	    sgnbit = zero;
 	  minv = valv & cst2v;
 	  switch (ccode)
 	    {
@@ -4925,34 +5004,35 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi,
 		 (should be equal to VAL, otherwise we probably should
 		 have folded the comparison into false) and
 		 maximum unsigned value is VAL | ~CST2.  */
-	      maxv = valv | ~cst2v;
+	      maxv = valv.or_not (cst2v);
 	      maxv = maxv.zext (nprec);
 	      valid_p = true;
 	      break;
 	    case NE_EXPR:
-	      tem = valv | ~cst2v;
+	      tem = valv.or_not (cst2v);
 	      tem = tem.zext (nprec);
 	      /* If VAL is 0, handle (X & CST2) != 0 as (X & CST2) > 0U.  */
-	      if (valv.is_zero ())
+	      if (valv.zero_p ())
 		{
 		  cst2n = false;
-		  sgnbit = double_int_zero;
+		  sgnbit = zero;
 		  goto gt_expr;
 		}
 	      /* If (VAL | ~CST2) is all ones, handle it as
 		 (X & CST2) < VAL.  */
-	      if (tem == double_int::mask (nprec))
+	      if (tem == wide_int::mask (nprec, false, 
+					 largest_bitsize, largest_precision))
 		{
 		  cst2n = false;
 		  valn = false;
-		  sgnbit = double_int_zero;
+		  sgnbit = zero;
 		  goto lt_expr;
 		}
-	      if (!cst2n
-		  && cst2v.sext (nprec).is_negative ())
-		sgnbit
-		  = double_int_one.llshift (nprec - 1, nprec).zext (nprec);
-	      if (!sgnbit.is_zero ())
+	      if (!cst2n && cst2v.sext (nprec).neg_p ())
+		sgnbit = wide_int::set_bit_in_zero (nprec - 1, 
+						    largest_bitsize, 
+						    largest_precision);
+	      if (!sgnbit.zero_p ())
 		{
 		  if (valv == sgnbit)
 		    {
@@ -4960,13 +5040,15 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi,
 		      valn = true;
 		      goto gt_expr;
 		    }
-		  if (tem == double_int::mask (nprec - 1))
+		  if (tem == wide_int::mask (nprec - 1, false, 
+					     largest_bitsize, 
+					     largest_precision))
 		    {
 		      cst2n = true;
 		      goto lt_expr;
 		    }
 		  if (!cst2n)
-		    sgnbit = double_int_zero;
+		    sgnbit = zero;
 		}
 	      break;
 	    case GE_EXPR:
@@ -4979,11 +5061,12 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi,
 		{
 		  /* If (VAL & CST2) != VAL, X & CST2 can't be equal to
 		     VAL.  */
-		  minv = masked_increment (valv, cst2v, sgnbit, nprec);
+		  minv = masked_increment (valv, cst2v, sgnbit, ntype);
 		  if (minv == valv)
 		    break;
 		}
-	      maxv = double_int::mask (nprec - (cst2n ? 1 : 0));
+	      maxv = wide_int::mask (nprec - (cst2n ? 1 : 0), false,
+				     largest_bitsize, largest_precision);
 	      valid_p = true;
 	      break;
 	    case GT_EXPR:
@@ -4991,10 +5074,11 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi,
 	      /* Find out smallest MINV where MINV > VAL
 		 && (MINV & CST2) == MINV, if any.  If VAL is signed and
 		 CST2 has MSB set, compute it biased by 1 << (nprec - 1).  */
-	      minv = masked_increment (valv, cst2v, sgnbit, nprec);
+	      minv = masked_increment (valv, cst2v, sgnbit, ntype);
 	      if (minv == valv)
 		break;
-	      maxv = double_int::mask (nprec - (cst2n ? 1 : 0));
+	      maxv = wide_int::mask (nprec - (cst2n ? 1 : 0), false,
+				     largest_bitsize, largest_precision);
 	      valid_p = true;
 	      break;
 	    case LE_EXPR:
@@ -5010,12 +5094,13 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi,
 		maxv = valv;
 	      else
 		{
-		  maxv = masked_increment (valv, cst2v, sgnbit, nprec);
+		  maxv = masked_increment (valv, cst2v, sgnbit, ntype);
 		  if (maxv == valv)
 		    break;
-		  maxv -= double_int_one;
+		  maxv = maxv - wide_int::one (largest_bitsize, 
+					       largest_precision);
 		}
-	      maxv |= ~cst2v;
+	      maxv = maxv.or_not (cst2v);
 	      maxv = maxv.zext (nprec);
 	      minv = sgnbit;
 	      valid_p = true;
@@ -5038,12 +5123,13 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi,
 		}
 	      else
 		{
-		  maxv = masked_increment (valv, cst2v, sgnbit, nprec);
+		  maxv = masked_increment (valv, cst2v, sgnbit, ntype);
 		  if (maxv == valv)
 		    break;
 		}
-	      maxv -= double_int_one;
-	      maxv |= ~cst2v;
+	      maxv = maxv - wide_int::one (largest_bitsize, 
+					   largest_precision);
+	      maxv = maxv.or_not (cst2v);
 	      maxv = maxv.zext (nprec);
 	      minv = sgnbit;
 	      valid_p = true;
@@ -5052,7 +5138,9 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi,
 	      break;
 	    }
 	  if (valid_p
-	      && (maxv - minv).zext (nprec) != double_int::mask (nprec))
+	      && (maxv - minv).zext (nprec) 
+	        != wide_int::mask (nprec, false, 
+				   largest_bitsize, largest_precision))
 	    {
 	      tree tmp, new_val, type;
 	      int i;
@@ -5060,7 +5148,7 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi,
 	      for (i = 0; i < 2; i++)
 		if (names[i])
 		  {
-		    double_int maxv2 = maxv;
+		    wide_int maxv2 = maxv;
 		    tmp = names[i];
 		    type = TREE_TYPE (names[i]);
 		    if (!TYPE_UNSIGNED (type))
@@ -5068,13 +5156,15 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi,
 			type = build_nonstandard_integer_type (nprec, 1);
 			tmp = build1 (NOP_EXPR, type, names[i]);
 		      }
-		    if (!minv.is_zero ())
+		    if (!minv.zero_p ())
 		      {
 			tmp = build2 (PLUS_EXPR, type, tmp,
-				      double_int_to_tree (type, -minv));
+				      wide_int_to_infinite_tree 
+				      (type, minv.neg (), largest_precision));
 			maxv2 = maxv - minv;
 		      }
-		    new_val = double_int_to_tree (type, maxv2);
+		    new_val = wide_int_to_infinite_tree (type, maxv2,
+							 largest_precision);
 
 		    if (dump_file)
 		      {
@@ -5994,7 +6084,7 @@ search_for_addr_array (tree t, location_t location)
     {
       tree tem = TREE_OPERAND (TREE_OPERAND (t, 0), 0);
       tree low_bound, up_bound, el_sz;
-      double_int idx;
+      wide_int idx;
       if (TREE_CODE (TREE_TYPE (tem)) != ARRAY_TYPE
 	  || TREE_CODE (TREE_TYPE (TREE_TYPE (tem))) == ARRAY_TYPE
 	  || !TYPE_DOMAIN (TREE_TYPE (tem)))
@@ -6011,17 +6101,19 @@ search_for_addr_array (tree t, location_t location)
 	  || TREE_CODE (el_sz) != INTEGER_CST)
 	return;
 
-      idx = mem_ref_offset (t);
-      idx = idx.sdiv (tree_to_double_int (el_sz), TRUNC_DIV_EXPR);
-      if (idx.slt (double_int_zero))
+      idx = mem_ref_offset (t).force_to_size (largest_bitsize, 
+					      largest_precision,
+					      wide_int::SIGNED);
+      idx = idx.sdiv_trunc (tree_to_infinite_wide_int (el_sz));
+      if (idx.lts_p (0))
 	{
 	  warning_at (location, OPT_Warray_bounds,
 		      "array subscript is below array bounds");
 	  TREE_NO_WARNING (t) = 1;
 	}
-      else if (idx.sgt (tree_to_double_int (up_bound)
-			- tree_to_double_int (low_bound)
-			+ double_int_one))
+      else if (idx.gts_p (tree_to_infinite_wide_int (up_bound)
+			  - tree_to_infinite_wide_int (low_bound)
+			  + wide_int::one (largest_bitsize, largest_precision)))
 	{
 	  warning_at (location, OPT_Warray_bounds,
 		      "array subscript is above array bounds");
@@ -6188,6 +6280,78 @@ remove_range_assertions (void)
 }
 
 
+/* Return true if STMT is interesting for VRP and initialize
+   largest_bitsize and largest_precision.  */
+
+static void
+look_for_largest (gimple stmt)
+{
+  if (gimple_code (stmt) == GIMPLE_PHI)
+    {
+      tree res = gimple_phi_result (stmt);
+      tree type = TREE_TYPE (res);
+
+      if (!virtual_operand_p (res)
+	  && (INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type)))
+      {
+	largest_bitsize = MAX (largest_bitsize, 
+			       GET_MODE_BITSIZE (TYPE_MODE (type)));
+	largest_precision = MAX (largest_precision, TYPE_PRECISION (type));
+      }
+    }
+  else if (is_gimple_assign (stmt) || is_gimple_call (stmt))
+    {
+      tree lhs = gimple_get_lhs (stmt);
+
+      /* In general, assignments with virtual operands are not useful
+	 for deriving ranges, with the obvious exception of calls to
+	 builtin functions.  */
+      if (lhs && TREE_CODE (lhs) == SSA_NAME
+	  && (INTEGRAL_TYPE_P (TREE_TYPE (lhs))
+	      || POINTER_TYPE_P (TREE_TYPE (lhs)))
+	  && ((is_gimple_call (stmt)
+	       && gimple_call_fndecl (stmt) != NULL_TREE
+	       && DECL_BUILT_IN (gimple_call_fndecl (stmt)))
+	      || !gimple_vuse (stmt)))
+	{
+	  tree type = TREE_TYPE (lhs);
+	  largest_bitsize = MAX (largest_bitsize, 
+				 GET_MODE_BITSIZE (TYPE_MODE (type)));
+	  largest_precision = MAX (largest_precision, TYPE_PRECISION (type));
+	}
+    }
+}
+
+
+/* Find the largest integer types.  */
+
+static void
+largest_initialize (void)
+{
+  basic_block bb;
+
+  largest_bitsize = GET_MODE_BITSIZE (word_mode);
+  largest_precision = GET_MODE_PRECISION (word_mode);
+
+  FOR_EACH_BB (bb)
+    {
+      gimple_stmt_iterator si;
+
+      for (si = gsi_start_phis (bb); !gsi_end_p (si); gsi_next (&si))
+        look_for_largest (gsi_stmt (si));
+
+      for (si = gsi_start_bb (bb); !gsi_end_p (si); gsi_next (&si))
+        look_for_largest (gsi_stmt (si));
+    }
+
+  /* We need to leave enough space so that we can see some bits above
+     the largest precision.  */
+  largest_bitsize *= 2;
+  largest_bitsize = MIN (largest_bitsize, MAX_BITSIZE_MODE_ANY_INT);
+  largest_precision *= 2;
+  largest_precision = MIN (largest_precision, MAX_BITSIZE_MODE_ANY_INT);
+}
+
 /* Return true if STMT is interesting for VRP.  */
 
 static bool
@@ -8256,9 +8420,9 @@ simplify_bit_ops_using_ranges (gimple_stmt_iterator *gsi, gimple stmt)
   tree op = NULL_TREE;
   value_range_t vr0 = VR_INITIALIZER;
   value_range_t vr1 = VR_INITIALIZER;
-  double_int may_be_nonzero0, may_be_nonzero1;
-  double_int must_be_nonzero0, must_be_nonzero1;
-  double_int mask;
+  wide_int may_be_nonzero0, may_be_nonzero1;
+  wide_int must_be_nonzero0, must_be_nonzero1;
+  wide_int mask;
 
   if (TREE_CODE (op0) == SSA_NAME)
     vr0 = *(get_value_range (op0));
@@ -8283,13 +8447,13 @@ simplify_bit_ops_using_ranges (gimple_stmt_iterator *gsi, gimple stmt)
     {
     case BIT_AND_EXPR:
       mask = may_be_nonzero0.and_not (must_be_nonzero1);
-      if (mask.is_zero ())
+      if (mask.zero_p ())
 	{
 	  op = op0;
 	  break;
 	}
       mask = may_be_nonzero1.and_not (must_be_nonzero0);
-      if (mask.is_zero ())
+      if (mask.zero_p ())
 	{
 	  op = op1;
 	  break;
@@ -8297,13 +8461,13 @@ simplify_bit_ops_using_ranges (gimple_stmt_iterator *gsi, gimple stmt)
       break;
     case BIT_IOR_EXPR:
       mask = may_be_nonzero0.and_not (must_be_nonzero1);
-      if (mask.is_zero ())
+      if (mask.zero_p ())
 	{
 	  op = op1;
 	  break;
 	}
       mask = may_be_nonzero1.and_not (must_be_nonzero0);
-      if (mask.is_zero ())
+      if (mask.zero_p ())
 	{
 	  op = op0;
 	  break;
@@ -8573,15 +8737,18 @@ simplify_switch_using_ranges (gimple stmt)
 static bool
 simplify_conversion_using_ranges (gimple stmt)
 {
-  tree innerop, middleop, finaltype;
+  tree innerop, middleop;
+  tree middle_type, final_type;
   gimple def_stmt;
   value_range_t *innervr;
-  bool inner_unsigned_p, middle_unsigned_p, final_unsigned_p;
+  bool inner_unsigned_p;
   unsigned inner_prec, middle_prec, final_prec;
-  double_int innermin, innermed, innermax, middlemin, middlemed, middlemax;
+  wide_int innermin, innermed, innermax, middlemin, middlemed, middlemax;
+  tree inner_type;
+  wide_int::SignOp inner_uns;
 
-  finaltype = TREE_TYPE (gimple_assign_lhs (stmt));
-  if (!INTEGRAL_TYPE_P (finaltype))
+  final_type = TREE_TYPE (gimple_assign_lhs (stmt));
+  if (!INTEGRAL_TYPE_P (final_type))
     return false;
   middleop = gimple_assign_rhs1 (stmt);
   def_stmt = SSA_NAME_DEF_STMT (middleop);
@@ -8601,43 +8768,48 @@ simplify_conversion_using_ranges (gimple stmt)
 
   /* Simulate the conversion chain to check if the result is equal if
      the middle conversion is removed.  */
-  innermin = tree_to_double_int (innervr->min);
-  innermax = tree_to_double_int (innervr->max);
-
-  inner_prec = TYPE_PRECISION (TREE_TYPE (innerop));
-  middle_prec = TYPE_PRECISION (TREE_TYPE (middleop));
-  final_prec = TYPE_PRECISION (finaltype);
-
+  innermin = tree_to_infinite_wide_int (innervr->min);
+  innermax = tree_to_infinite_wide_int (innervr->max);
+
+  inner_type = TREE_TYPE (innerop);
+  inner_prec = TYPE_PRECISION (inner_type);
+  middle_type = TREE_TYPE (middleop);
+  middle_prec = TYPE_PRECISION (middle_type);
+  final_prec = TYPE_PRECISION (final_type);
+  
   /* If the first conversion is not injective, the second must not
      be widening.  */
-  if ((innermax - innermin).ugt (double_int::mask (middle_prec))
+  if ((innermax - innermin).gtu_p (wide_int::mask (middle_prec, false, 
+						   largest_bitsize,
+						   largest_precision))
       && middle_prec < final_prec)
     return false;
   /* We also want a medium value so that we can track the effect that
      narrowing conversions with sign change have.  */
   inner_unsigned_p = TYPE_UNSIGNED (TREE_TYPE (innerop));
+  inner_uns = inner_unsigned_p ? wide_int::UNSIGNED : wide_int::SIGNED;
   if (inner_unsigned_p)
-    innermed = double_int::mask (inner_prec).lrshift (1, inner_prec);
+    innermed = wide_int::mask (inner_prec - 1, false, 
+			       largest_bitsize, largest_precision);
   else
-    innermed = double_int_zero;
-  if (innermin.cmp (innermed, inner_unsigned_p) >= 0
-      || innermed.cmp (innermax, inner_unsigned_p) >= 0)
+    innermed = wide_int::zero (largest_bitsize, largest_precision);
+
+  if ((!innermin.lt_p (innermed, inner_uns))
+      || !innermed.lt_p (innermax, inner_uns))
     innermed = innermin;
 
-  middle_unsigned_p = TYPE_UNSIGNED (TREE_TYPE (middleop));
-  middlemin = innermin.ext (middle_prec, middle_unsigned_p);
-  middlemed = innermed.ext (middle_prec, middle_unsigned_p);
-  middlemax = innermax.ext (middle_prec, middle_unsigned_p);
+  middlemin = innermin.ext (middle_type);
+  middlemed = innermed.ext (middle_type);
+  middlemax = innermax.ext (middle_type);
 
   /* Require that the final conversion applied to both the original
      and the intermediate range produces the same result.  */
-  final_unsigned_p = TYPE_UNSIGNED (finaltype);
-  if (middlemin.ext (final_prec, final_unsigned_p)
-	 != innermin.ext (final_prec, final_unsigned_p)
-      || middlemed.ext (final_prec, final_unsigned_p)
-	 != innermed.ext (final_prec, final_unsigned_p)
-      || middlemax.ext (final_prec, final_unsigned_p)
-	 != innermax.ext (final_prec, final_unsigned_p))
+  if (middlemin.ext (final_type)
+      != innermin.ext (final_type)
+      || middlemed.ext (final_type)
+      != innermed.ext (final_type)
+      || middlemax.ext (final_type)
+      != innermax.ext (final_type))
     return false;
 
   gimple_assign_set_rhs1 (stmt, innerop);
@@ -8646,14 +8818,14 @@ simplify_conversion_using_ranges (gimple stmt)
 }
 
 /* Return whether the value range *VR fits in an integer type specified
-   by PRECISION and UNSIGNED_P.  */
+   by PRECISION.  The operand is assumed to be signed.  */
 
 static bool
-range_fits_type_p (value_range_t *vr, unsigned precision, bool unsigned_p)
+range_fits_type_p (value_range_t *vr, unsigned precision)
 {
   tree src_type;
   unsigned src_precision;
-  double_int tem;
+  wide_int tem;
 
   /* We can only handle integral and pointer types.  */
   src_type = TREE_TYPE (vr->min);
@@ -8665,7 +8837,7 @@ range_fits_type_p (value_range_t *vr, unsigned precision, bool unsigned_p)
   src_precision = TYPE_PRECISION (TREE_TYPE (vr->min));
   if (src_precision < precision
       || (src_precision == precision
-	  && TYPE_UNSIGNED (src_type) == unsigned_p))
+	  && !TYPE_UNSIGNED (src_type)))
     return true;
 
   /* Now we can only handle ranges with constant bounds.  */
@@ -8674,19 +8846,13 @@ range_fits_type_p (value_range_t *vr, unsigned precision, bool unsigned_p)
       || TREE_CODE (vr->max) != INTEGER_CST)
     return false;
 
-  /* For precision-preserving sign-changes the MSB of the double-int
-     has to be clear.  */
-  if (src_precision == precision
-      && (TREE_INT_CST_HIGH (vr->min) | TREE_INT_CST_HIGH (vr->max)) < 0)
-    return false;
-
   /* Then we can perform the conversion on both ends and compare
      the result for equality.  */
-  tem = tree_to_double_int (vr->min).ext (precision, unsigned_p);
-  if (tree_to_double_int (vr->min) != tem)
+  tem = tree_to_infinite_wide_int (vr->min).sext (precision);
+  if (tree_to_infinite_wide_int (vr->min) != tem)
     return false;
-  tem = tree_to_double_int (vr->max).ext (precision, unsigned_p);
-  if (tree_to_double_int (vr->max) != tem)
+  tem = tree_to_infinite_wide_int (vr->max).sext (precision);
+  if (tree_to_infinite_wide_int (vr->max) != tem)
     return false;
 
   return true;
@@ -8715,7 +8881,7 @@ simplify_float_conversion_using_ranges (gimple_stmt_iterator *gsi, gimple stmt)
       && (can_float_p (fltmode, TYPE_MODE (TREE_TYPE (rhs1)), 0)
 	  != CODE_FOR_nothing)
       && range_fits_type_p (vr, GET_MODE_PRECISION
-			          (TYPE_MODE (TREE_TYPE (rhs1))), 0))
+			    (TYPE_MODE (TREE_TYPE (rhs1)))))
     mode = TYPE_MODE (TREE_TYPE (rhs1));
   /* If we can do the conversion in the current input mode do nothing.  */
   else if (can_float_p (fltmode, TYPE_MODE (TREE_TYPE (rhs1)),
@@ -8732,7 +8898,7 @@ simplify_float_conversion_using_ranges (gimple_stmt_iterator *gsi, gimple stmt)
 	     or if the value-range does not fit in the signed type
 	     try with a wider mode.  */
 	  if (can_float_p (fltmode, mode, 0) != CODE_FOR_nothing
-	      && range_fits_type_p (vr, GET_MODE_PRECISION (mode), 0))
+	      && range_fits_type_p (vr, GET_MODE_PRECISION (mode)))
 	    break;
 
 	  mode = GET_MODE_WIDER_MODE (mode);
@@ -9152,6 +9318,7 @@ execute_vrp (void)
   loop_optimizer_init (LOOPS_NORMAL | LOOPS_HAVE_RECORDED_EXITS);
   rewrite_into_loop_closed_ssa (NULL, TODO_update_ssa);
   scev_initialize ();
+  largest_initialize ();
 
   insert_range_assertions ();
 
diff --git a/gcc/tree.c b/gcc/tree.c
index 84f2cbc..1b11044 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -1074,15 +1074,27 @@ double_int_to_tree (tree type, double_int cst)
 tree
 wide_int_to_tree (tree type, const wide_int &cst)
 {
-  wide_int v;
+  wide_int v = cst.force_to_size ((const_tree)type);
+ 
+  return build_int_cst_wide (type, v.elt (0), v.elt (1));
+}
 
-  gcc_assert (cst.get_len () <= 2);
-  if (TYPE_UNSIGNED (type))
-    v = cst.zext (TYPE_PRECISION (type));
-  else
-    v = cst.sext (TYPE_PRECISION (type));
+/* Constructs tree in type TYPE from with value given by CST.
+   Signedness of CST is assumed to be the same as the signedness of
+   TYPE.  The number is represented in an infinite filed of PREC bits.
+   This number should be twice the sized of the largest integer mode
+   in the function being compiled.  */
 
-  return build_int_cst_wide (type, v.elt (0), v.elt (1));
+tree
+wide_int_to_infinite_tree (tree type, const wide_int &cst, unsigned int prec)
+{
+  wide_int::SignOp sgn = TYPE_UNSIGNED (type) 
+    ? wide_int::UNSIGNED : wide_int::SIGNED;
+  wide_int v = cst.ext (TYPE_PRECISION (type), sgn);
+  HOST_WIDE_INT e1 = (prec <= HOST_BITS_PER_WIDE_INT) 
+    ? v.elt (0) >> (HOST_BITS_PER_WIDE_INT - 1) : v.elt (1);
+
+  return build_int_cst_wide (type, v.elt (0), e1);
 }
 
 /* Return 0 or -1 depending on the sign of the cst.  */ 
@@ -1265,6 +1277,61 @@ force_fit_type_double (tree type, double_int cst, int overflowable,
   return double_int_to_tree (type, cst);
 }
 
+/* We force the wide_int CST to the range of the type TYPE by sign or
+   zero extending it.  OVERFLOWABLE indicates if we are interested in
+   overflow of the value, when >0 we are only interested in signed
+   overflow, for <0 we are interested in any overflow.  OVERFLOWED
+   indicates whether overflow has already occurred.  CONST_OVERFLOWED
+   indicates whether constant overflow has already occurred.  We force
+   T's value to be within range of T's type (by setting to 0 or 1 all
+   the bits outside the type's range).  We set TREE_OVERFLOWED if,
+        OVERFLOWED is nonzero,
+        or OVERFLOWABLE is >0 and signed overflow occurs
+        or OVERFLOWABLE is <0 and any overflow occurs
+   We return a new tree node for the extended wide_int.  The node
+   is shared if no overflow flags are set.  */
+
+
+tree
+force_fit_type_wide (tree type, const wide_int &cst, int overflowable,
+		     bool overflowed)
+{
+  /* Size types *are* sign extended.  */
+  bool sign_extended_type = !TYPE_UNSIGNED (type);
+
+  /* If we need to set overflow flags, return a new unshared node.  */
+  if (overflowed || !cst.fits_to_tree_p (type))
+    {
+      if (overflowed
+	  || overflowable < 0
+	  || (overflowable > 0 && sign_extended_type))
+	{
+#ifdef NEW_REP_FOR_INT_CST
+	  wide_int::SignOp uns = TYPE_UNSIGNED (type) 
+	    ? wide_int::UNSIGNED : wide_int::SIGNED;
+	  const wide_int &r = cst.ext (TYPE_PRECISION (type), uns);
+	  tree t = make_int_cst (r.get_len ());
+	  int i;
+
+	  for (i = 0; i < r.get_len (); ++i)
+	    TREE_INT_CST_ELT (t, i) = r.elt (i);
+#else
+	  tree t = make_node (INTEGER_CST);
+	  double_int d = double_int::from_pair (cst.elt (1), cst.elt(0));
+
+	  TREE_INT_CST (t) = d.ext (TYPE_PRECISION (type),
+					     !sign_extended_type);
+#endif
+	  TREE_TYPE (t) = type;
+	  TREE_OVERFLOW (t) = 1;
+	  return t;
+	}
+    }
+
+  /* Else build a shared node.  */
+  return wide_int_to_tree (type, cst);
+}
+
 /* These are the hash table functions for the hash table of INTEGER_CST
    nodes of a sizetype.  */
 
@@ -1293,6 +1360,7 @@ int_cst_hash_eq (const void *x, const void *y)
 	  && TREE_INT_CST_LOW (xt) == TREE_INT_CST_LOW (yt));
 }
 
+
 /* Create an INT_CST node of TYPE and value HI:LOW.
    The returned node is always shared.  For small integers we use a
    per-type vector cache, for larger ones we use a single hash table.  */
@@ -4130,12 +4198,21 @@ build_simple_mem_ref_loc (location_t loc, tree ptr)
 /* Return the constant offset of a MEM_REF or TARGET_MEM_REF tree T.  */
 
 double_int
-mem_ref_offset (const_tree t)
+mem_ref_offset_as_double (const_tree t)
 {
   tree toff = TREE_OPERAND (t, 1);
   return tree_to_double_int (toff).sext (TYPE_PRECISION (TREE_TYPE (toff)));
 }
 
+/* Return the constant offset of a MEM_REF or TARGET_MEM_REF tree T.  */
+
+wide_int
+mem_ref_offset (const_tree t)
+{
+  tree toff = TREE_OPERAND (t, 1);
+  return wide_int::from_tree (toff);
+}
+
 /* Return the pointer-type relevant for TBAA purposes from the
    gimple memory reference tree T.  This is the type to be used for
    the offset operand of MEM_REF or TARGET_MEM_REF replacements of T.  */
diff --git a/gcc/tree.h b/gcc/tree.h
index f5497cd..74348d1 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -5835,7 +5835,7 @@ extern tree fold_indirect_ref_loc (location_t, tree);
 extern tree build_simple_mem_ref_loc (location_t, tree);
 #define build_simple_mem_ref(T)\
 	build_simple_mem_ref_loc (UNKNOWN_LOCATION, T)
-extern double_int mem_ref_offset (const_tree);
+extern double_int mem_ref_offset_as_double (const_tree);
 extern tree reference_alias_ptr_type (const_tree);
 extern tree build_invariant_address (tree, tree, HOST_WIDE_INT);
 extern tree constant_boolean_node (bool, tree);
diff --git a/gcc/varasm.c b/gcc/varasm.c
index 0666fcb..ee477f0 100644
--- a/gcc/varasm.c
+++ b/gcc/varasm.c
@@ -2583,7 +2583,7 @@ decode_addr_const (tree exp, struct addr_const *value)
       else if (TREE_CODE (target) == MEM_REF
 	       && TREE_CODE (TREE_OPERAND (target, 0)) == ADDR_EXPR)
 	{
-	  offset += mem_ref_offset (target).low;
+	  offset += mem_ref_offset_as_double (target).low;
 	  target = TREE_OPERAND (TREE_OPERAND (target, 0), 0);
 	}
       else if (TREE_CODE (target) == INDIRECT_REF
