Patchwork [wide-int] Treat order comparisons like other binary ops

login
register
mail settings
Submitter Richard Sandiford
Date Oct. 27, 2013, 2:22 p.m.
Message ID <878uxerdxq.fsf@talisman.default>
Download mbox | patch
Permalink /patch/286339/
State New
Headers show

Comments

Richard Sandiford - Oct. 27, 2013, 2:22 p.m.
Until now, eq_p and ne_p have enforced the same argument rules as things
like addition, while order comparisons like lts_p have treated the two
arguments as independent and signed.  Richard, I think you said on IRC
that you thought lts_p should behave like the others.  E.g. lts_p on two
trees or two rtxes should make sure that the precisions are the same.

This patch does that.  I think all uses of INT_CST_LT and INT_CST_LT_UNSIGNED
are really comparing to "infinite" precision, and the UNSIGNED distinction is
only there because double_int isn't wide enough to be effectively infinite.
Is that right?  Since that isn't a problem with widest_int, the patch gets
rid of INT_CST_LT_UNSIGNED and only uses INT_CST_LT.

The c-lex.c change includes a generic change that I justed posted for trunk.

I rejigged the order in tree.h slightly so that it matches trunk.

Tested on powerpc64-linux-gnu and x86_64-linux-gnu.  OK for wide-int?

Thanks,
Richard
Richard Guenther - Oct. 29, 2013, 12:18 p.m.
On Sun, 27 Oct 2013, Richard Sandiford wrote:

> Until now, eq_p and ne_p have enforced the same argument rules as things
> like addition, while order comparisons like lts_p have treated the two
> arguments as independent and signed.  Richard, I think you said on IRC
> that you thought lts_p should behave like the others.  E.g. lts_p on two
> trees or two rtxes should make sure that the precisions are the same.

Yes.

> This patch does that.  I think all uses of INT_CST_LT and INT_CST_LT_UNSIGNED
> are really comparing to "infinite" precision, and the UNSIGNED distinction is
> only there because double_int isn't wide enough to be effectively infinite.
> Is that right? 

Yes, it's only because of the case of set MSB on the double-int.

> Since that isn't a problem with widest_int, the patch gets
> rid of INT_CST_LT_UNSIGNED and only uses INT_CST_LT.
>
> 
> The c-lex.c change includes a generic change that I justed posted for trunk.
> 
> I rejigged the order in tree.h slightly so that it matches trunk.
> 
> Tested on powerpc64-linux-gnu and x86_64-linux-gnu.  OK for wide-int?

Ok.

Thanks,
Richard.

> Thanks,
> Richard
> 
> 
> Index: gcc/c-family/c-common.c
> ===================================================================
> --- gcc/c-family/c-common.c	2013-10-27 14:11:53.006510519 +0000
> +++ gcc/c-family/c-common.c	2013-10-27 14:19:27.667578745 +0000
> @@ -4101,20 +4101,10 @@ shorten_compare (tree *op0_ptr, tree *op
>  	  maxval = convert (*restype_ptr, maxval);
>  	}
>  
> -      if (unsignedp && unsignedp0)
> -	{
> -	  min_gt = INT_CST_LT_UNSIGNED (primop1, minval);
> -	  max_gt = INT_CST_LT_UNSIGNED (primop1, maxval);
> -	  min_lt = INT_CST_LT_UNSIGNED (minval, primop1);
> -	  max_lt = INT_CST_LT_UNSIGNED (maxval, primop1);
> -	}
> -      else
> -	{
> -	  min_gt = INT_CST_LT (primop1, minval);
> -	  max_gt = INT_CST_LT (primop1, maxval);
> -	  min_lt = INT_CST_LT (minval, primop1);
> -	  max_lt = INT_CST_LT (maxval, primop1);
> -	}
> +      min_gt = INT_CST_LT (primop1, minval);
> +      max_gt = INT_CST_LT (primop1, maxval);
> +      min_lt = INT_CST_LT (minval, primop1);
> +      max_lt = INT_CST_LT (maxval, primop1);
>  
>        val = 0;
>        /* This used to be a switch, but Genix compiler can't handle that.  */
> Index: gcc/c-family/c-lex.c
> ===================================================================
> --- gcc/c-family/c-lex.c	2013-10-27 14:11:53.006510519 +0000
> +++ gcc/c-family/c-lex.c	2013-10-27 14:19:27.664578718 +0000
> @@ -48,9 +48,9 @@ static tree interpret_float (const cpp_t
>  			     enum overflow_type *);
>  static tree interpret_fixed (const cpp_token *, unsigned int);
>  static enum integer_type_kind narrowest_unsigned_type
> -	(const wide_int &, unsigned int);
> +	(const widest_int &, unsigned int);
>  static enum integer_type_kind narrowest_signed_type
> -	(const wide_int &, unsigned int);
> +	(const widest_int &, unsigned int);
>  static enum cpp_ttype lex_string (const cpp_token *, tree *, bool, bool);
>  static tree lex_charconst (const cpp_token *);
>  static void update_header_times (const char *);
> @@ -526,7 +526,7 @@ c_lex_with_flags (tree *value, location_
>     there isn't one.  */
>  
>  static enum integer_type_kind
> -narrowest_unsigned_type (const wide_int &val, unsigned int flags)
> +narrowest_unsigned_type (const widest_int &val, unsigned int flags)
>  {
>    int itk;
>  
> @@ -545,7 +545,7 @@ narrowest_unsigned_type (const wide_int
>  	continue;
>        upper = TYPE_MAX_VALUE (integer_types[itk]);
>  
> -      if (wi::geu_p (upper, val))
> +      if (wi::geu_p (wi::to_widest (upper), val))
>  	return (enum integer_type_kind) itk;
>      }
>  
> @@ -554,7 +554,7 @@ narrowest_unsigned_type (const wide_int
>  
>  /* Ditto, but narrowest signed type.  */
>  static enum integer_type_kind
> -narrowest_signed_type (const wide_int &val, unsigned int flags)
> +narrowest_signed_type (const widest_int &val, unsigned int flags)
>  {
>    int itk;
>  
> @@ -573,7 +573,7 @@ narrowest_signed_type (const wide_int &v
>  	continue;
>        upper = TYPE_MAX_VALUE (integer_types[itk]);
>  
> -      if (wi::geu_p (upper, val))
> +      if (wi::geu_p (wi::to_widest (upper), val))
>  	return (enum integer_type_kind) itk;
>      }
>  
> @@ -588,20 +588,18 @@ interpret_integer (const cpp_token *toke
>    tree value, type;
>    enum integer_type_kind itk;
>    cpp_num integer;
> -  cpp_options *options = cpp_get_options (parse_in);
> -  HOST_WIDE_INT ival[2];
> -  wide_int wval;
> +  HOST_WIDE_INT ival[3];
>  
>    *overflow = OT_NONE;
>  
>    integer = cpp_interpret_integer (parse_in, token, flags);
> -  integer = cpp_num_sign_extend (integer, options->precision);
>    if (integer.overflow)
>      *overflow = OT_OVERFLOW;
>  
>    ival[0] = integer.low;
>    ival[1] = integer.high;
> -  wval = wide_int::from_array (ival, 2, HOST_BITS_PER_WIDE_INT * 2);
> +  ival[2] = 0;
> +  widest_int wval = widest_int::from_array (ival, 3);
>  
>    /* The type of a constant with a U suffix is straightforward.  */
>    if (flags & CPP_N_UNSIGNED)
> Index: gcc/cp/call.c
> ===================================================================
> --- gcc/cp/call.c	2013-10-27 14:11:53.006510519 +0000
> +++ gcc/cp/call.c	2013-10-27 14:19:27.673578799 +0000
> @@ -6493,8 +6493,7 @@ type_passed_as (tree type)
>    else if (targetm.calls.promote_prototypes (type)
>  	   && INTEGRAL_TYPE_P (type)
>  	   && COMPLETE_TYPE_P (type)
> -	   && INT_CST_LT_UNSIGNED (TYPE_SIZE (type),
> -				   TYPE_SIZE (integer_type_node)))
> +	   && INT_CST_LT (TYPE_SIZE (type), TYPE_SIZE (integer_type_node)))
>      type = integer_type_node;
>  
>    return type;
> @@ -6534,8 +6533,7 @@ convert_for_arg_passing (tree type, tree
>    else if (targetm.calls.promote_prototypes (type)
>  	   && INTEGRAL_TYPE_P (type)
>  	   && COMPLETE_TYPE_P (type)
> -	   && INT_CST_LT_UNSIGNED (TYPE_SIZE (type),
> -				   TYPE_SIZE (integer_type_node)))
> +	   && INT_CST_LT (TYPE_SIZE (type), TYPE_SIZE (integer_type_node)))
>      val = cp_perform_integral_promotions (val, complain);
>    if ((complain & tf_warning)
>        && warn_suggest_attribute_format)
> Index: gcc/cp/class.c
> ===================================================================
> --- gcc/cp/class.c	2013-10-27 14:11:53.006510519 +0000
> +++ gcc/cp/class.c	2013-10-27 14:19:27.675578817 +0000
> @@ -5790,7 +5790,7 @@ end_of_class (tree t, int include_virtua
>  	continue;
>  
>        offset = end_of_base (base_binfo);
> -      if (INT_CST_LT_UNSIGNED (result, offset))
> +      if (INT_CST_LT (result, offset))
>  	result = offset;
>      }
>  
> @@ -5800,7 +5800,7 @@ end_of_class (tree t, int include_virtua
>  	 vec_safe_iterate (vbases, i, &base_binfo); i++)
>        {
>  	offset = end_of_base (base_binfo);
> -	if (INT_CST_LT_UNSIGNED (result, offset))
> +	if (INT_CST_LT (result, offset))
>  	  result = offset;
>        }
>  
> @@ -5880,7 +5880,7 @@ include_empty_classes (record_layout_inf
>  		      CLASSTYPE_AS_BASE (rli->t) != NULL_TREE);
>    rli_size = rli_size_unit_so_far (rli);
>    if (TREE_CODE (rli_size) == INTEGER_CST
> -      && INT_CST_LT_UNSIGNED (rli_size, eoc))
> +      && INT_CST_LT (rli_size, eoc))
>      {
>        if (!abi_version_at_least (2))
>  	/* In version 1 of the ABI, the size of a class that ends with
> Index: gcc/cp/init.c
> ===================================================================
> --- gcc/cp/init.c	2013-10-27 14:11:53.006510519 +0000
> +++ gcc/cp/init.c	2013-10-27 14:19:27.661578691 +0000
> @@ -2412,7 +2412,7 @@ build_new_1 (vec<tree, va_gc> **placemen
>        gcc_assert (TREE_CODE (size) == INTEGER_CST);
>        cookie_size = targetm.cxx.get_cookie_size (elt_type);
>        gcc_assert (TREE_CODE (cookie_size) == INTEGER_CST);
> -      gcc_checking_assert (wi::ltu_p (cookie_size, max_size));
> +      gcc_checking_assert (wi::ltu_p (wi::to_offset (cookie_size), max_size));
>        /* Unconditionally subtract the cookie size.  This decreases the
>  	 maximum object size and is safe even if we choose not to use
>  	 a cookie after all.  */
> Index: gcc/fold-const.c
> ===================================================================
> --- gcc/fold-const.c	2013-10-27 14:11:53.006510519 +0000
> +++ gcc/fold-const.c	2013-10-27 14:19:27.669578763 +0000
> @@ -16448,8 +16448,6 @@ fold_relational_const (enum tree_code co
>      {
>        if (code == EQ_EXPR)
>  	result = tree_int_cst_equal (op0, op1);
> -      else if (TYPE_UNSIGNED (TREE_TYPE (op0)))
> -	result = INT_CST_LT_UNSIGNED (op0, op1);
>        else
>  	result = INT_CST_LT (op0, op1);
>      }
> Index: gcc/gimple-fold.c
> ===================================================================
> --- gcc/gimple-fold.c	2013-10-27 14:11:53.006510519 +0000
> +++ gcc/gimple-fold.c	2013-10-27 14:19:27.662578700 +0000
> @@ -2834,7 +2834,7 @@ fold_array_ctor_reference (tree type, tr
>       be larger than size of array element.  */
>    if (!TYPE_SIZE_UNIT (type)
>        || TREE_CODE (TYPE_SIZE_UNIT (type)) != INTEGER_CST
> -      || wi::lts_p (elt_size, TYPE_SIZE_UNIT (type)))
> +      || wi::lts_p (elt_size, wi::to_offset (TYPE_SIZE_UNIT (type))))
>      return NULL_TREE;
>  
>    /* Compute the array index we look for.  */
> Index: gcc/java/expr.c
> ===================================================================
> --- gcc/java/expr.c	2013-10-27 14:11:53.006510519 +0000
> +++ gcc/java/expr.c	2013-10-27 14:19:27.675578817 +0000
> @@ -1716,7 +1716,7 @@ build_field_ref (tree self_value, tree s
>  	  tree field_offset = byte_position (field_decl);
>  	  if (! page_size)
>  	    page_size = size_int (4096); 	      
> -	  check = ! INT_CST_LT_UNSIGNED (field_offset, page_size);
> +	  check = ! INT_CST_LT (field_offset, page_size);
>  	}
>  
>        if (base_type != TREE_TYPE (self_value))
> Index: gcc/loop-doloop.c
> ===================================================================
> --- gcc/loop-doloop.c	2013-10-27 14:11:53.006510519 +0000
> +++ gcc/loop-doloop.c	2013-10-27 14:19:27.663578709 +0000
> @@ -462,8 +462,8 @@ doloop_modify (struct loop *loop, struct
>  	 Note that the maximum value loaded is iterations_max - 1.  */
>        if (get_max_loop_iterations (loop, &iterations)
>  	  && wi::leu_p (iterations,
> -			wi::set_bit_in_zero (GET_MODE_PRECISION (mode) - 1,
> -					     GET_MODE_PRECISION (mode))))
> +			wi::set_bit_in_zero <widest_int>
> +			(GET_MODE_PRECISION (mode) - 1)))
>  	nonneg = 1;
>        break;
>  
> Index: gcc/targhooks.c
> ===================================================================
> --- gcc/targhooks.c	2013-10-27 14:11:53.006510519 +0000
> +++ gcc/targhooks.c	2013-10-27 14:19:27.670578772 +0000
> @@ -288,7 +288,7 @@ default_cxx_get_cookie_size (tree type)
>  
>    sizetype_size = size_in_bytes (sizetype);
>    type_align = size_int (TYPE_ALIGN_UNIT (type));
> -  if (INT_CST_LT_UNSIGNED (type_align, sizetype_size))
> +  if (INT_CST_LT (type_align, sizetype_size))
>      cookie_size = sizetype_size;
>    else
>      cookie_size = type_align;
> Index: gcc/tree-ssa-loop-ivcanon.c
> ===================================================================
> --- gcc/tree-ssa-loop-ivcanon.c	2013-10-27 14:11:53.006510519 +0000
> +++ gcc/tree-ssa-loop-ivcanon.c	2013-10-27 14:19:27.662578700 +0000
> @@ -546,7 +546,8 @@ remove_redundant_iv_tests (struct loop *
>  	      || !integer_zerop (niter.may_be_zero)
>  	      || !niter.niter
>  	      || TREE_CODE (niter.niter) != INTEGER_CST
> -	      || !wi::ltu_p (loop->nb_iterations_upper_bound, niter.niter))
> +	      || !wi::ltu_p (loop->nb_iterations_upper_bound,
> +			     wi::to_widest (niter.niter)))
>  	    continue;
>  	  
>  	  if (dump_file && (dump_flags & TDF_DETAILS))
> Index: gcc/tree-ssa-loop-niter.c
> ===================================================================
> --- gcc/tree-ssa-loop-niter.c	2013-10-27 14:11:53.006510519 +0000
> +++ gcc/tree-ssa-loop-niter.c	2013-10-27 14:19:27.663578709 +0000
> @@ -2520,7 +2520,7 @@ do_warn_aggressive_loop_optimizations (s
>        || loop->warned_aggressive_loop_optimizations
>        /* Only warn if undefined behavior gives us lower estimate than the
>  	 known constant bound.  */
> -      || wi::cmpu (i_bound, loop->nb_iterations) >= 0
> +      || wi::cmpu (i_bound, wi::to_widest (loop->nb_iterations)) >= 0
>        /* And undefined behavior happens unconditionally.  */
>        || !dominated_by_p (CDI_DOMINATORS, loop->latch, gimple_bb (stmt)))
>      return;
> Index: gcc/tree-ssa-uninit.c
> ===================================================================
> --- gcc/tree-ssa-uninit.c	2013-10-27 14:11:53.006510519 +0000
> +++ gcc/tree-ssa-uninit.c	2013-10-27 14:19:27.670578772 +0000
> @@ -848,12 +848,11 @@ is_value_included_in (tree val, tree bou
>        if (cmpc == EQ_EXPR)
>          result = tree_int_cst_equal (val, boundary);
>        else if (cmpc == LT_EXPR)
> -        result = INT_CST_LT_UNSIGNED (val, boundary);
> +        result = INT_CST_LT (val, boundary);
>        else
>          {
>            gcc_assert (cmpc == LE_EXPR);
> -          result = (tree_int_cst_equal (val, boundary)
> -                    || INT_CST_LT_UNSIGNED (val, boundary));
> +          result = INT_CST_LE (val, boundary);
>          }
>      }
>    else
> Index: gcc/tree-ssa.c
> ===================================================================
> --- gcc/tree-ssa.c	2013-10-27 14:11:53.006510519 +0000
> +++ gcc/tree-ssa.c	2013-10-27 14:19:27.663578709 +0000
> @@ -1422,7 +1422,7 @@ non_rewritable_mem_ref_base (tree ref)
>  	  && useless_type_conversion_p (TREE_TYPE (base),
>  					TREE_TYPE (TREE_TYPE (decl)))
>  	  && wi::fits_uhwi_p (mem_ref_offset (base))
> -	  && wi::gtu_p (TYPE_SIZE_UNIT (TREE_TYPE (decl)),
> +	  && wi::gtu_p (wi::to_offset (TYPE_SIZE_UNIT (TREE_TYPE (decl))),
>  			mem_ref_offset (base))
>  	  && multiple_of_p (sizetype, TREE_OPERAND (base, 1),
>  			    TYPE_SIZE_UNIT (TREE_TYPE (base))))
> Index: gcc/tree-vrp.c
> ===================================================================
> --- gcc/tree-vrp.c	2013-10-27 14:11:53.006510519 +0000
> +++ gcc/tree-vrp.c	2013-10-27 14:19:27.671578781 +0000
> @@ -1127,15 +1127,7 @@ operand_less_p (tree val, tree val2)
>  {
>    /* LT is folded faster than GE and others.  Inline the common case.  */
>    if (TREE_CODE (val) == INTEGER_CST && TREE_CODE (val2) == INTEGER_CST)
> -    {
> -      if (TYPE_UNSIGNED (TREE_TYPE (val)))
> -	return INT_CST_LT_UNSIGNED (val, val2);
> -      else
> -	{
> -	  if (INT_CST_LT (val, val2))
> -	    return 1;
> -	}
> -    }
> +    return INT_CST_LT (val, val2);
>    else
>      {
>        tree tcmp;
> Index: gcc/tree.c
> ===================================================================
> --- gcc/tree.c	2013-10-27 14:11:53.006510519 +0000
> +++ gcc/tree.c	2013-10-27 14:19:27.665578727 +0000
> @@ -6899,26 +6899,7 @@ tree_int_cst_equal (const_tree t1, const
>  int
>  tree_int_cst_lt (const_tree t1, const_tree t2)
>  {
> -  if (t1 == t2)
> -    return 0;
> -
> -  if (TYPE_UNSIGNED (TREE_TYPE (t1)) != TYPE_UNSIGNED (TREE_TYPE (t2)))
> -    {
> -      int t1_sgn = tree_int_cst_sgn (t1);
> -      int t2_sgn = tree_int_cst_sgn (t2);
> -
> -      if (t1_sgn < t2_sgn)
> -	return 1;
> -      else if (t1_sgn > t2_sgn)
> -	return 0;
> -      /* Otherwise, both are non-negative, so we compare them as
> -	 unsigned just in case one of them would overflow a signed
> -	 type.  */
> -    }
> -  else if (!TYPE_UNSIGNED (TREE_TYPE (t1)))
> -    return INT_CST_LT (t1, t2);
> -
> -  return INT_CST_LT_UNSIGNED (t1, t2);
> +  return INT_CST_LT (t1, t2);
>  }
>  
>  /* Returns -1 if T1 < T2, 0 if T1 == T2, and 1 if T1 > T2.  */
> @@ -6926,12 +6907,7 @@ tree_int_cst_lt (const_tree t1, const_tr
>  int
>  tree_int_cst_compare (const_tree t1, const_tree t2)
>  {
> -  if (tree_int_cst_lt (t1, t2))
> -    return -1;
> -  else if (tree_int_cst_lt (t2, t1))
> -    return 1;
> -  else
> -    return 0;
> +  return wi::cmps (wi::to_widest (t1), wi::to_widest (t2));
>  }
>  
>  /* Return the HOST_WIDE_INT least significant bits of T, a sizetype
> @@ -8667,18 +8643,7 @@ int_fits_type_p (const_tree c, const_tre
>    /* Check if c >= type_low_bound.  */
>    if (type_low_bound && TREE_CODE (type_low_bound) == INTEGER_CST)
>      {
> -      wd = type_low_bound;
> -      if (sgn_c != TYPE_SIGN (TREE_TYPE (type_low_bound)))
> -	{
> -	  int c_neg = (sgn_c == SIGNED && wi::neg_p (wc));
> -	  int t_neg = (sgn_c == UNSIGNED && wi::neg_p (wd));
> -
> -	  if (c_neg && !t_neg)
> -	    return false;
> -	  if ((c_neg || !t_neg) && wi::ltu_p (wc, wd))
> -	    return false;
> -	}
> -      else if (wi::lt_p (wc, wd, sgn_c))
> +      if (INT_CST_LT (c, type_low_bound))
>  	return false;
>        ok_for_low_bound = true;
>      }
> @@ -8688,18 +8653,7 @@ int_fits_type_p (const_tree c, const_tre
>    /* Check if c <= type_high_bound.  */
>    if (type_high_bound && TREE_CODE (type_high_bound) == INTEGER_CST)
>      {
> -      wd = type_high_bound;
> -      if (sgn_c != TYPE_SIGN (TREE_TYPE (type_high_bound)))
> -	{
> -	  int c_neg = (sgn_c == SIGNED && wi::neg_p (wc));
> -	  int t_neg = (sgn_c == UNSIGNED && wi::neg_p (wd));
> -
> -	  if (t_neg && !c_neg)
> -	    return false;
> -	  if ((t_neg || !c_neg) && wi::gtu_p (wc, wd))
> -	    return false;
> -	}
> -      else if (wi::gt_p (wc, wd, sgn_c))
> +      if (INT_CST_LT (type_high_bound, c))
>  	return false;
>        ok_for_high_bound = true;
>      }
> Index: gcc/tree.h
> ===================================================================
> --- gcc/tree.h	2013-10-27 14:11:53.006510519 +0000
> +++ gcc/tree.h	2013-10-27 14:19:27.672578790 +0000
> @@ -877,18 +877,15 @@ #define TREE_LANG_FLAG_6(NODE) \
>  
>  /* Define additional fields and accessors for nodes representing constants.  */
>  
> -#define INT_CST_LT(A, B)				\
> -  (wi::lts_p (A, B))
> -
> -#define INT_CST_LT_UNSIGNED(A, B)			\
> -  (wi::ltu_p (A, B))
> -
>  #define TREE_INT_CST_NUNITS(NODE) \
>    (INTEGER_CST_CHECK (NODE)->base.u.int_length.unextended)
>  #define TREE_INT_CST_EXT_NUNITS(NODE) \
>    (INTEGER_CST_CHECK (NODE)->base.u.int_length.extended)
>  #define TREE_INT_CST_ELT(NODE, I) TREE_INT_CST_ELT_CHECK (NODE, I)
>  
> +#define INT_CST_LT(A, B) (wi::lts_p (wi::to_widest (A), wi::to_widest (B)))
> +#define INT_CST_LE(A, B) (wi::les_p (wi::to_widest (A), wi::to_widest (B)))
> +
>  #define TREE_REAL_CST_PTR(NODE) (REAL_CST_CHECK (NODE)->real_cst.real_cst_ptr)
>  #define TREE_REAL_CST(NODE) (*TREE_REAL_CST_PTR (NODE))
>  
> Index: gcc/wide-int.cc
> ===================================================================
> --- gcc/wide-int.cc	2013-10-27 14:11:53.006510519 +0000
> +++ gcc/wide-int.cc	2013-10-27 14:19:27.660578682 +0000
> @@ -416,22 +416,19 @@ wi::eq_p_large (const HOST_WIDE_INT *op0
>  /* Return true if OP0 < OP1 using signed comparisons.  */
>  bool
>  wi::lts_p_large (const HOST_WIDE_INT *op0, unsigned int op0len,
> -		 unsigned int p0,
> -		 const HOST_WIDE_INT *op1, unsigned int op1len,
> -		 unsigned int p1)
> +		 unsigned int precision,
> +		 const HOST_WIDE_INT *op1, unsigned int op1len)
>  {
>    HOST_WIDE_INT s0, s1;
>    unsigned HOST_WIDE_INT u0, u1;
> -  unsigned int blocks_needed0 = BLOCKS_NEEDED (p0);
> -  unsigned int blocks_needed1 = BLOCKS_NEEDED (p1);
> -  unsigned int small_prec0 = p0 & (HOST_BITS_PER_WIDE_INT - 1);
> -  unsigned int small_prec1 = p1 & (HOST_BITS_PER_WIDE_INT - 1);
> +  unsigned int blocks_needed = BLOCKS_NEEDED (precision);
> +  unsigned int small_prec = precision & (HOST_BITS_PER_WIDE_INT - 1);
>    int l = MAX (op0len - 1, op1len - 1);
>  
>    /* Only the top block is compared as signed.  The rest are unsigned
>       comparisons.  */
> -  s0 = selt (op0, op0len, blocks_needed0, small_prec0, l, SIGNED);
> -  s1 = selt (op1, op1len, blocks_needed1, small_prec1, l, SIGNED);
> +  s0 = selt (op0, op0len, blocks_needed, small_prec, l, SIGNED);
> +  s1 = selt (op1, op1len, blocks_needed, small_prec, l, SIGNED);
>    if (s0 < s1)
>      return true;
>    if (s0 > s1)
> @@ -440,8 +437,8 @@ wi::lts_p_large (const HOST_WIDE_INT *op
>    l--;
>    while (l >= 0)
>      {
> -      u0 = selt (op0, op0len, blocks_needed0, small_prec0, l, SIGNED);
> -      u1 = selt (op1, op1len, blocks_needed1, small_prec1, l, SIGNED);
> +      u0 = selt (op0, op0len, blocks_needed, small_prec, l, SIGNED);
> +      u1 = selt (op1, op1len, blocks_needed, small_prec, l, SIGNED);
>  
>        if (u0 < u1)
>  	return true;
> @@ -457,22 +454,19 @@ wi::lts_p_large (const HOST_WIDE_INT *op
>     signed compares.  */
>  int
>  wi::cmps_large (const HOST_WIDE_INT *op0, unsigned int op0len,
> -		unsigned int p0,
> -		const HOST_WIDE_INT *op1, unsigned int op1len,
> -		unsigned int p1)
> +		unsigned int precision,
> +		const HOST_WIDE_INT *op1, unsigned int op1len)
>  {
>    HOST_WIDE_INT s0, s1;
>    unsigned HOST_WIDE_INT u0, u1;
> -  unsigned int blocks_needed0 = BLOCKS_NEEDED (p0);
> -  unsigned int blocks_needed1 = BLOCKS_NEEDED (p1);
> -  unsigned int small_prec0 = p0 & (HOST_BITS_PER_WIDE_INT - 1);
> -  unsigned int small_prec1 = p1 & (HOST_BITS_PER_WIDE_INT - 1);
> +  unsigned int blocks_needed = BLOCKS_NEEDED (precision);
> +  unsigned int small_prec = precision & (HOST_BITS_PER_WIDE_INT - 1);
>    int l = MAX (op0len - 1, op1len - 1);
>  
>    /* Only the top block is compared as signed.  The rest are unsigned
>       comparisons.  */
> -  s0 = selt (op0, op0len, blocks_needed0, small_prec0, l, SIGNED);
> -  s1 = selt (op1, op1len, blocks_needed1, small_prec1, l, SIGNED);
> +  s0 = selt (op0, op0len, blocks_needed, small_prec, l, SIGNED);
> +  s1 = selt (op1, op1len, blocks_needed, small_prec, l, SIGNED);
>    if (s0 < s1)
>      return -1;
>    if (s0 > s1)
> @@ -481,8 +475,8 @@ wi::cmps_large (const HOST_WIDE_INT *op0
>    l--;
>    while (l >= 0)
>      {
> -      u0 = selt (op0, op0len, blocks_needed0, small_prec0, l, SIGNED);
> -      u1 = selt (op1, op1len, blocks_needed1, small_prec1, l, SIGNED);
> +      u0 = selt (op0, op0len, blocks_needed, small_prec, l, SIGNED);
> +      u1 = selt (op1, op1len, blocks_needed, small_prec, l, SIGNED);
>  
>        if (u0 < u1)
>  	return -1;
> @@ -496,21 +490,20 @@ wi::cmps_large (const HOST_WIDE_INT *op0
>  
>  /* Return true if OP0 < OP1 using unsigned comparisons.  */
>  bool
> -wi::ltu_p_large (const HOST_WIDE_INT *op0, unsigned int op0len, unsigned int p0,
> -		 const HOST_WIDE_INT *op1, unsigned int op1len, unsigned int p1)
> +wi::ltu_p_large (const HOST_WIDE_INT *op0, unsigned int op0len,
> +		 unsigned int precision,
> +		 const HOST_WIDE_INT *op1, unsigned int op1len)
>  {
>    unsigned HOST_WIDE_INT x0;
>    unsigned HOST_WIDE_INT x1;
> -  unsigned int blocks_needed0 = BLOCKS_NEEDED (p0);
> -  unsigned int blocks_needed1 = BLOCKS_NEEDED (p1);
> -  unsigned int small_prec0 = p0 & (HOST_BITS_PER_WIDE_INT - 1);
> -  unsigned int small_prec1 = p1 & (HOST_BITS_PER_WIDE_INT - 1);
> +  unsigned int blocks_needed = BLOCKS_NEEDED (precision);
> +  unsigned int small_prec = precision & (HOST_BITS_PER_WIDE_INT - 1);
>    int l = MAX (op0len - 1, op1len - 1);
>  
>    while (l >= 0)
>      {
> -      x0 = selt (op0, op0len, blocks_needed0, small_prec0, l, UNSIGNED);
> -      x1 = selt (op1, op1len, blocks_needed1, small_prec1, l, UNSIGNED);
> +      x0 = selt (op0, op0len, blocks_needed, small_prec, l, UNSIGNED);
> +      x1 = selt (op1, op1len, blocks_needed, small_prec, l, UNSIGNED);
>        if (x0 < x1)
>  	return true;
>        if (x0 > x1)
> @@ -524,21 +517,20 @@ wi::ltu_p_large (const HOST_WIDE_INT *op
>  /* Returns -1 if OP0 < OP1, 0 if OP0 == OP1 and 1 if OP0 > OP1 using
>     unsigned compares.  */
>  int
> -wi::cmpu_large (const HOST_WIDE_INT *op0, unsigned int op0len, unsigned int p0,
> -		const HOST_WIDE_INT *op1, unsigned int op1len, unsigned int p1)
> +wi::cmpu_large (const HOST_WIDE_INT *op0, unsigned int op0len,
> +		unsigned int precision,
> +		const HOST_WIDE_INT *op1, unsigned int op1len)
>  {
>    unsigned HOST_WIDE_INT x0;
>    unsigned HOST_WIDE_INT x1;
> -  unsigned int blocks_needed0 = BLOCKS_NEEDED (p0);
> -  unsigned int blocks_needed1 = BLOCKS_NEEDED (p1);
> -  unsigned int small_prec0 = p0 & (HOST_BITS_PER_WIDE_INT - 1);
> -  unsigned int small_prec1 = p1 & (HOST_BITS_PER_WIDE_INT - 1);
> +  unsigned int blocks_needed = BLOCKS_NEEDED (precision);
> +  unsigned int small_prec = precision & (HOST_BITS_PER_WIDE_INT - 1);
>    int l = MAX (op0len - 1, op1len - 1);
>  
>    while (l >= 0)
>      {
> -      x0 = selt (op0, op0len, blocks_needed0, small_prec0, l, UNSIGNED);
> -      x1 = selt (op1, op1len, blocks_needed1, small_prec1, l, UNSIGNED);
> +      x0 = selt (op0, op0len, blocks_needed, small_prec, l, UNSIGNED);
> +      x1 = selt (op1, op1len, blocks_needed, small_prec, l, UNSIGNED);
>        if (x0 < x1)
>  	return -1;
>        if (x0 > x1)
> Index: gcc/wide-int.h
> ===================================================================
> --- gcc/wide-int.h	2013-10-27 14:19:26.641569564 +0000
> +++ gcc/wide-int.h	2013-10-27 14:19:27.660578682 +0000
> @@ -1355,13 +1355,13 @@ decompose (HOST_WIDE_INT *scratch, unsig
>    bool eq_p_large (const HOST_WIDE_INT *, unsigned int,
>  		   const HOST_WIDE_INT *, unsigned int, unsigned int);
>    bool lts_p_large (const HOST_WIDE_INT *, unsigned int, unsigned int,
> -		    const HOST_WIDE_INT *, unsigned int, unsigned int);
> +		    const HOST_WIDE_INT *, unsigned int);
>    bool ltu_p_large (const HOST_WIDE_INT *, unsigned int, unsigned int,
> -		    const HOST_WIDE_INT *, unsigned int, unsigned int);
> +		    const HOST_WIDE_INT *, unsigned int);
>    int cmps_large (const HOST_WIDE_INT *, unsigned int, unsigned int,
> -		  const HOST_WIDE_INT *, unsigned int, unsigned int);
> +		  const HOST_WIDE_INT *, unsigned int);
>    int cmpu_large (const HOST_WIDE_INT *, unsigned int, unsigned int,
> -		  const HOST_WIDE_INT *, unsigned int, unsigned int);
> +		  const HOST_WIDE_INT *, unsigned int);
>    unsigned int sext_large (HOST_WIDE_INT *, const HOST_WIDE_INT *, 
>  			   unsigned int,
>  			   unsigned int, unsigned int);
> @@ -1525,10 +1525,11 @@ wi::ne_p (const T1 &x, const T2 &y)
>  inline bool
>  wi::lts_p (const T1 &x, const T2 &y)
>  {
> -  WIDE_INT_REF_FOR (T1) xi (x);
> -  WIDE_INT_REF_FOR (T2) yi (y);
> +  unsigned int precision = get_binary_precision (x, y);
> +  WIDE_INT_REF_FOR (T1) xi (x, precision);
> +  WIDE_INT_REF_FOR (T2) yi (y, precision);
>    // We optimize x < y, where y is 64 or fewer bits.
> -  if (yi.precision <= HOST_BITS_PER_WIDE_INT)
> +  if (wi::fits_shwi_p (yi))
>      {
>        // If x fits directly into a shwi, we can compare directly.
>        if (wi::fits_shwi_p (xi))
> @@ -1541,8 +1542,7 @@ wi::lts_p (const T1 &x, const T2 &y)
>        // and hence greater than y.
>        return false;
>      }
> -  return lts_p_large (xi.val, xi.len, xi.precision, yi.val, yi.len,
> -		      yi.precision);
> +  return lts_p_large (xi.val, xi.len, precision, yi.val, yi.len);
>  }
>  
>  /* Return true if X < Y when both are treated as unsigned values.  */
> @@ -1550,18 +1550,16 @@ wi::lts_p (const T1 &x, const T2 &y)
>  inline bool
>  wi::ltu_p (const T1 &x, const T2 &y)
>  {
> -  WIDE_INT_REF_FOR (T1) xi (x);
> -  WIDE_INT_REF_FOR (T2) yi (y);
> -  if (xi.precision <= HOST_BITS_PER_WIDE_INT
> -      && yi.precision <= HOST_BITS_PER_WIDE_INT)
> +  unsigned int precision = get_binary_precision (x, y);
> +  WIDE_INT_REF_FOR (T1) xi (x, precision);
> +  WIDE_INT_REF_FOR (T2) yi (y, precision);
> +  if (precision <= HOST_BITS_PER_WIDE_INT)
>      {
>        unsigned HOST_WIDE_INT xl = xi.to_uhwi ();
>        unsigned HOST_WIDE_INT yl = yi.to_uhwi ();
>        return xl < yl;
>      }
> -  else
> -    return ltu_p_large (xi.val, xi.len, xi.precision,
> -			yi.val, yi.len, yi.precision);
> +  return ltu_p_large (xi.val, xi.len, precision, yi.val, yi.len);
>  }
>  
>  /* Return true if X < Y.  Signedness of X and Y is indicated by SGN.  */
> @@ -1662,10 +1660,10 @@ wi::ge_p (const T1 &x, const T2 &y, sign
>  inline int
>  wi::cmps (const T1 &x, const T2 &y)
>  {
> -  WIDE_INT_REF_FOR (T1) xi (x);
> -  WIDE_INT_REF_FOR (T2) yi (y);
> -  if (xi.precision <= HOST_BITS_PER_WIDE_INT
> -      && yi.precision <= HOST_BITS_PER_WIDE_INT)
> +  unsigned int precision = get_binary_precision (x, y);
> +  WIDE_INT_REF_FOR (T1) xi (x, precision);
> +  WIDE_INT_REF_FOR (T2) yi (y, precision);
> +  if (precision <= HOST_BITS_PER_WIDE_INT)
>      {
>        HOST_WIDE_INT xl = xi.to_shwi ();
>        HOST_WIDE_INT yl = yi.to_shwi ();
> @@ -1676,8 +1674,7 @@ wi::cmps (const T1 &x, const T2 &y)
>        else
>  	return 0;
>      }
> -  return cmps_large (xi.val, xi.len, xi.precision, yi.val, yi.len,
> -		     yi.precision);
> +  return cmps_large (xi.val, xi.len, precision, yi.val, yi.len);
>  }
>  
>  /* Return -1 if X < Y, 0 if X == Y and 1 if X > Y.  Treat both X and Y
> @@ -1686,10 +1683,10 @@ wi::cmps (const T1 &x, const T2 &y)
>  inline int
>  wi::cmpu (const T1 &x, const T2 &y)
>  {
> -  WIDE_INT_REF_FOR (T1) xi (x);
> -  WIDE_INT_REF_FOR (T2) yi (y);
> -  if (xi.precision <= HOST_BITS_PER_WIDE_INT
> -      && yi.precision <= HOST_BITS_PER_WIDE_INT)
> +  unsigned int precision = get_binary_precision (x, y);
> +  WIDE_INT_REF_FOR (T1) xi (x, precision);
> +  WIDE_INT_REF_FOR (T2) yi (y, precision);
> +  if (precision <= HOST_BITS_PER_WIDE_INT)
>      {
>        unsigned HOST_WIDE_INT xl = xi.to_uhwi ();
>        unsigned HOST_WIDE_INT yl = yi.to_uhwi ();
> @@ -1700,8 +1697,7 @@ wi::cmpu (const T1 &x, const T2 &y)
>        else
>  	return 1;
>      }
> -  return cmpu_large (xi.val, xi.len, xi.precision, yi.val, yi.len,
> -		     yi.precision);
> +  return cmpu_large (xi.val, xi.len, precision, yi.val, yi.len);
>  }
>  
>  /* Return -1 if X < Y, 0 if X == Y and 1 if X > Y.  Signedness of
> 
>

Patch

Index: gcc/c-family/c-common.c
===================================================================
--- gcc/c-family/c-common.c	2013-10-27 14:11:53.006510519 +0000
+++ gcc/c-family/c-common.c	2013-10-27 14:19:27.667578745 +0000
@@ -4101,20 +4101,10 @@  shorten_compare (tree *op0_ptr, tree *op
 	  maxval = convert (*restype_ptr, maxval);
 	}
 
-      if (unsignedp && unsignedp0)
-	{
-	  min_gt = INT_CST_LT_UNSIGNED (primop1, minval);
-	  max_gt = INT_CST_LT_UNSIGNED (primop1, maxval);
-	  min_lt = INT_CST_LT_UNSIGNED (minval, primop1);
-	  max_lt = INT_CST_LT_UNSIGNED (maxval, primop1);
-	}
-      else
-	{
-	  min_gt = INT_CST_LT (primop1, minval);
-	  max_gt = INT_CST_LT (primop1, maxval);
-	  min_lt = INT_CST_LT (minval, primop1);
-	  max_lt = INT_CST_LT (maxval, primop1);
-	}
+      min_gt = INT_CST_LT (primop1, minval);
+      max_gt = INT_CST_LT (primop1, maxval);
+      min_lt = INT_CST_LT (minval, primop1);
+      max_lt = INT_CST_LT (maxval, primop1);
 
       val = 0;
       /* This used to be a switch, but Genix compiler can't handle that.  */
Index: gcc/c-family/c-lex.c
===================================================================
--- gcc/c-family/c-lex.c	2013-10-27 14:11:53.006510519 +0000
+++ gcc/c-family/c-lex.c	2013-10-27 14:19:27.664578718 +0000
@@ -48,9 +48,9 @@  static tree interpret_float (const cpp_t
 			     enum overflow_type *);
 static tree interpret_fixed (const cpp_token *, unsigned int);
 static enum integer_type_kind narrowest_unsigned_type
-	(const wide_int &, unsigned int);
+	(const widest_int &, unsigned int);
 static enum integer_type_kind narrowest_signed_type
-	(const wide_int &, unsigned int);
+	(const widest_int &, unsigned int);
 static enum cpp_ttype lex_string (const cpp_token *, tree *, bool, bool);
 static tree lex_charconst (const cpp_token *);
 static void update_header_times (const char *);
@@ -526,7 +526,7 @@  c_lex_with_flags (tree *value, location_
    there isn't one.  */
 
 static enum integer_type_kind
-narrowest_unsigned_type (const wide_int &val, unsigned int flags)
+narrowest_unsigned_type (const widest_int &val, unsigned int flags)
 {
   int itk;
 
@@ -545,7 +545,7 @@  narrowest_unsigned_type (const wide_int
 	continue;
       upper = TYPE_MAX_VALUE (integer_types[itk]);
 
-      if (wi::geu_p (upper, val))
+      if (wi::geu_p (wi::to_widest (upper), val))
 	return (enum integer_type_kind) itk;
     }
 
@@ -554,7 +554,7 @@  narrowest_unsigned_type (const wide_int
 
 /* Ditto, but narrowest signed type.  */
 static enum integer_type_kind
-narrowest_signed_type (const wide_int &val, unsigned int flags)
+narrowest_signed_type (const widest_int &val, unsigned int flags)
 {
   int itk;
 
@@ -573,7 +573,7 @@  narrowest_signed_type (const wide_int &v
 	continue;
       upper = TYPE_MAX_VALUE (integer_types[itk]);
 
-      if (wi::geu_p (upper, val))
+      if (wi::geu_p (wi::to_widest (upper), val))
 	return (enum integer_type_kind) itk;
     }
 
@@ -588,20 +588,18 @@  interpret_integer (const cpp_token *toke
   tree value, type;
   enum integer_type_kind itk;
   cpp_num integer;
-  cpp_options *options = cpp_get_options (parse_in);
-  HOST_WIDE_INT ival[2];
-  wide_int wval;
+  HOST_WIDE_INT ival[3];
 
   *overflow = OT_NONE;
 
   integer = cpp_interpret_integer (parse_in, token, flags);
-  integer = cpp_num_sign_extend (integer, options->precision);
   if (integer.overflow)
     *overflow = OT_OVERFLOW;
 
   ival[0] = integer.low;
   ival[1] = integer.high;
-  wval = wide_int::from_array (ival, 2, HOST_BITS_PER_WIDE_INT * 2);
+  ival[2] = 0;
+  widest_int wval = widest_int::from_array (ival, 3);
 
   /* The type of a constant with a U suffix is straightforward.  */
   if (flags & CPP_N_UNSIGNED)
Index: gcc/cp/call.c
===================================================================
--- gcc/cp/call.c	2013-10-27 14:11:53.006510519 +0000
+++ gcc/cp/call.c	2013-10-27 14:19:27.673578799 +0000
@@ -6493,8 +6493,7 @@  type_passed_as (tree type)
   else if (targetm.calls.promote_prototypes (type)
 	   && INTEGRAL_TYPE_P (type)
 	   && COMPLETE_TYPE_P (type)
-	   && INT_CST_LT_UNSIGNED (TYPE_SIZE (type),
-				   TYPE_SIZE (integer_type_node)))
+	   && INT_CST_LT (TYPE_SIZE (type), TYPE_SIZE (integer_type_node)))
     type = integer_type_node;
 
   return type;
@@ -6534,8 +6533,7 @@  convert_for_arg_passing (tree type, tree
   else if (targetm.calls.promote_prototypes (type)
 	   && INTEGRAL_TYPE_P (type)
 	   && COMPLETE_TYPE_P (type)
-	   && INT_CST_LT_UNSIGNED (TYPE_SIZE (type),
-				   TYPE_SIZE (integer_type_node)))
+	   && INT_CST_LT (TYPE_SIZE (type), TYPE_SIZE (integer_type_node)))
     val = cp_perform_integral_promotions (val, complain);
   if ((complain & tf_warning)
       && warn_suggest_attribute_format)
Index: gcc/cp/class.c
===================================================================
--- gcc/cp/class.c	2013-10-27 14:11:53.006510519 +0000
+++ gcc/cp/class.c	2013-10-27 14:19:27.675578817 +0000
@@ -5790,7 +5790,7 @@  end_of_class (tree t, int include_virtua
 	continue;
 
       offset = end_of_base (base_binfo);
-      if (INT_CST_LT_UNSIGNED (result, offset))
+      if (INT_CST_LT (result, offset))
 	result = offset;
     }
 
@@ -5800,7 +5800,7 @@  end_of_class (tree t, int include_virtua
 	 vec_safe_iterate (vbases, i, &base_binfo); i++)
       {
 	offset = end_of_base (base_binfo);
-	if (INT_CST_LT_UNSIGNED (result, offset))
+	if (INT_CST_LT (result, offset))
 	  result = offset;
       }
 
@@ -5880,7 +5880,7 @@  include_empty_classes (record_layout_inf
 		      CLASSTYPE_AS_BASE (rli->t) != NULL_TREE);
   rli_size = rli_size_unit_so_far (rli);
   if (TREE_CODE (rli_size) == INTEGER_CST
-      && INT_CST_LT_UNSIGNED (rli_size, eoc))
+      && INT_CST_LT (rli_size, eoc))
     {
       if (!abi_version_at_least (2))
 	/* In version 1 of the ABI, the size of a class that ends with
Index: gcc/cp/init.c
===================================================================
--- gcc/cp/init.c	2013-10-27 14:11:53.006510519 +0000
+++ gcc/cp/init.c	2013-10-27 14:19:27.661578691 +0000
@@ -2412,7 +2412,7 @@  build_new_1 (vec<tree, va_gc> **placemen
       gcc_assert (TREE_CODE (size) == INTEGER_CST);
       cookie_size = targetm.cxx.get_cookie_size (elt_type);
       gcc_assert (TREE_CODE (cookie_size) == INTEGER_CST);
-      gcc_checking_assert (wi::ltu_p (cookie_size, max_size));
+      gcc_checking_assert (wi::ltu_p (wi::to_offset (cookie_size), max_size));
       /* Unconditionally subtract the cookie size.  This decreases the
 	 maximum object size and is safe even if we choose not to use
 	 a cookie after all.  */
Index: gcc/fold-const.c
===================================================================
--- gcc/fold-const.c	2013-10-27 14:11:53.006510519 +0000
+++ gcc/fold-const.c	2013-10-27 14:19:27.669578763 +0000
@@ -16448,8 +16448,6 @@  fold_relational_const (enum tree_code co
     {
       if (code == EQ_EXPR)
 	result = tree_int_cst_equal (op0, op1);
-      else if (TYPE_UNSIGNED (TREE_TYPE (op0)))
-	result = INT_CST_LT_UNSIGNED (op0, op1);
       else
 	result = INT_CST_LT (op0, op1);
     }
Index: gcc/gimple-fold.c
===================================================================
--- gcc/gimple-fold.c	2013-10-27 14:11:53.006510519 +0000
+++ gcc/gimple-fold.c	2013-10-27 14:19:27.662578700 +0000
@@ -2834,7 +2834,7 @@  fold_array_ctor_reference (tree type, tr
      be larger than size of array element.  */
   if (!TYPE_SIZE_UNIT (type)
       || TREE_CODE (TYPE_SIZE_UNIT (type)) != INTEGER_CST
-      || wi::lts_p (elt_size, TYPE_SIZE_UNIT (type)))
+      || wi::lts_p (elt_size, wi::to_offset (TYPE_SIZE_UNIT (type))))
     return NULL_TREE;
 
   /* Compute the array index we look for.  */
Index: gcc/java/expr.c
===================================================================
--- gcc/java/expr.c	2013-10-27 14:11:53.006510519 +0000
+++ gcc/java/expr.c	2013-10-27 14:19:27.675578817 +0000
@@ -1716,7 +1716,7 @@  build_field_ref (tree self_value, tree s
 	  tree field_offset = byte_position (field_decl);
 	  if (! page_size)
 	    page_size = size_int (4096); 	      
-	  check = ! INT_CST_LT_UNSIGNED (field_offset, page_size);
+	  check = ! INT_CST_LT (field_offset, page_size);
 	}
 
       if (base_type != TREE_TYPE (self_value))
Index: gcc/loop-doloop.c
===================================================================
--- gcc/loop-doloop.c	2013-10-27 14:11:53.006510519 +0000
+++ gcc/loop-doloop.c	2013-10-27 14:19:27.663578709 +0000
@@ -462,8 +462,8 @@  doloop_modify (struct loop *loop, struct
 	 Note that the maximum value loaded is iterations_max - 1.  */
       if (get_max_loop_iterations (loop, &iterations)
 	  && wi::leu_p (iterations,
-			wi::set_bit_in_zero (GET_MODE_PRECISION (mode) - 1,
-					     GET_MODE_PRECISION (mode))))
+			wi::set_bit_in_zero <widest_int>
+			(GET_MODE_PRECISION (mode) - 1)))
 	nonneg = 1;
       break;
 
Index: gcc/targhooks.c
===================================================================
--- gcc/targhooks.c	2013-10-27 14:11:53.006510519 +0000
+++ gcc/targhooks.c	2013-10-27 14:19:27.670578772 +0000
@@ -288,7 +288,7 @@  default_cxx_get_cookie_size (tree type)
 
   sizetype_size = size_in_bytes (sizetype);
   type_align = size_int (TYPE_ALIGN_UNIT (type));
-  if (INT_CST_LT_UNSIGNED (type_align, sizetype_size))
+  if (INT_CST_LT (type_align, sizetype_size))
     cookie_size = sizetype_size;
   else
     cookie_size = type_align;
Index: gcc/tree-ssa-loop-ivcanon.c
===================================================================
--- gcc/tree-ssa-loop-ivcanon.c	2013-10-27 14:11:53.006510519 +0000
+++ gcc/tree-ssa-loop-ivcanon.c	2013-10-27 14:19:27.662578700 +0000
@@ -546,7 +546,8 @@  remove_redundant_iv_tests (struct loop *
 	      || !integer_zerop (niter.may_be_zero)
 	      || !niter.niter
 	      || TREE_CODE (niter.niter) != INTEGER_CST
-	      || !wi::ltu_p (loop->nb_iterations_upper_bound, niter.niter))
+	      || !wi::ltu_p (loop->nb_iterations_upper_bound,
+			     wi::to_widest (niter.niter)))
 	    continue;
 	  
 	  if (dump_file && (dump_flags & TDF_DETAILS))
Index: gcc/tree-ssa-loop-niter.c
===================================================================
--- gcc/tree-ssa-loop-niter.c	2013-10-27 14:11:53.006510519 +0000
+++ gcc/tree-ssa-loop-niter.c	2013-10-27 14:19:27.663578709 +0000
@@ -2520,7 +2520,7 @@  do_warn_aggressive_loop_optimizations (s
       || loop->warned_aggressive_loop_optimizations
       /* Only warn if undefined behavior gives us lower estimate than the
 	 known constant bound.  */
-      || wi::cmpu (i_bound, loop->nb_iterations) >= 0
+      || wi::cmpu (i_bound, wi::to_widest (loop->nb_iterations)) >= 0
       /* And undefined behavior happens unconditionally.  */
       || !dominated_by_p (CDI_DOMINATORS, loop->latch, gimple_bb (stmt)))
     return;
Index: gcc/tree-ssa-uninit.c
===================================================================
--- gcc/tree-ssa-uninit.c	2013-10-27 14:11:53.006510519 +0000
+++ gcc/tree-ssa-uninit.c	2013-10-27 14:19:27.670578772 +0000
@@ -848,12 +848,11 @@  is_value_included_in (tree val, tree bou
       if (cmpc == EQ_EXPR)
         result = tree_int_cst_equal (val, boundary);
       else if (cmpc == LT_EXPR)
-        result = INT_CST_LT_UNSIGNED (val, boundary);
+        result = INT_CST_LT (val, boundary);
       else
         {
           gcc_assert (cmpc == LE_EXPR);
-          result = (tree_int_cst_equal (val, boundary)
-                    || INT_CST_LT_UNSIGNED (val, boundary));
+          result = INT_CST_LE (val, boundary);
         }
     }
   else
Index: gcc/tree-ssa.c
===================================================================
--- gcc/tree-ssa.c	2013-10-27 14:11:53.006510519 +0000
+++ gcc/tree-ssa.c	2013-10-27 14:19:27.663578709 +0000
@@ -1422,7 +1422,7 @@  non_rewritable_mem_ref_base (tree ref)
 	  && useless_type_conversion_p (TREE_TYPE (base),
 					TREE_TYPE (TREE_TYPE (decl)))
 	  && wi::fits_uhwi_p (mem_ref_offset (base))
-	  && wi::gtu_p (TYPE_SIZE_UNIT (TREE_TYPE (decl)),
+	  && wi::gtu_p (wi::to_offset (TYPE_SIZE_UNIT (TREE_TYPE (decl))),
 			mem_ref_offset (base))
 	  && multiple_of_p (sizetype, TREE_OPERAND (base, 1),
 			    TYPE_SIZE_UNIT (TREE_TYPE (base))))
Index: gcc/tree-vrp.c
===================================================================
--- gcc/tree-vrp.c	2013-10-27 14:11:53.006510519 +0000
+++ gcc/tree-vrp.c	2013-10-27 14:19:27.671578781 +0000
@@ -1127,15 +1127,7 @@  operand_less_p (tree val, tree val2)
 {
   /* LT is folded faster than GE and others.  Inline the common case.  */
   if (TREE_CODE (val) == INTEGER_CST && TREE_CODE (val2) == INTEGER_CST)
-    {
-      if (TYPE_UNSIGNED (TREE_TYPE (val)))
-	return INT_CST_LT_UNSIGNED (val, val2);
-      else
-	{
-	  if (INT_CST_LT (val, val2))
-	    return 1;
-	}
-    }
+    return INT_CST_LT (val, val2);
   else
     {
       tree tcmp;
Index: gcc/tree.c
===================================================================
--- gcc/tree.c	2013-10-27 14:11:53.006510519 +0000
+++ gcc/tree.c	2013-10-27 14:19:27.665578727 +0000
@@ -6899,26 +6899,7 @@  tree_int_cst_equal (const_tree t1, const
 int
 tree_int_cst_lt (const_tree t1, const_tree t2)
 {
-  if (t1 == t2)
-    return 0;
-
-  if (TYPE_UNSIGNED (TREE_TYPE (t1)) != TYPE_UNSIGNED (TREE_TYPE (t2)))
-    {
-      int t1_sgn = tree_int_cst_sgn (t1);
-      int t2_sgn = tree_int_cst_sgn (t2);
-
-      if (t1_sgn < t2_sgn)
-	return 1;
-      else if (t1_sgn > t2_sgn)
-	return 0;
-      /* Otherwise, both are non-negative, so we compare them as
-	 unsigned just in case one of them would overflow a signed
-	 type.  */
-    }
-  else if (!TYPE_UNSIGNED (TREE_TYPE (t1)))
-    return INT_CST_LT (t1, t2);
-
-  return INT_CST_LT_UNSIGNED (t1, t2);
+  return INT_CST_LT (t1, t2);
 }
 
 /* Returns -1 if T1 < T2, 0 if T1 == T2, and 1 if T1 > T2.  */
@@ -6926,12 +6907,7 @@  tree_int_cst_lt (const_tree t1, const_tr
 int
 tree_int_cst_compare (const_tree t1, const_tree t2)
 {
-  if (tree_int_cst_lt (t1, t2))
-    return -1;
-  else if (tree_int_cst_lt (t2, t1))
-    return 1;
-  else
-    return 0;
+  return wi::cmps (wi::to_widest (t1), wi::to_widest (t2));
 }
 
 /* Return the HOST_WIDE_INT least significant bits of T, a sizetype
@@ -8667,18 +8643,7 @@  int_fits_type_p (const_tree c, const_tre
   /* Check if c >= type_low_bound.  */
   if (type_low_bound && TREE_CODE (type_low_bound) == INTEGER_CST)
     {
-      wd = type_low_bound;
-      if (sgn_c != TYPE_SIGN (TREE_TYPE (type_low_bound)))
-	{
-	  int c_neg = (sgn_c == SIGNED && wi::neg_p (wc));
-	  int t_neg = (sgn_c == UNSIGNED && wi::neg_p (wd));
-
-	  if (c_neg && !t_neg)
-	    return false;
-	  if ((c_neg || !t_neg) && wi::ltu_p (wc, wd))
-	    return false;
-	}
-      else if (wi::lt_p (wc, wd, sgn_c))
+      if (INT_CST_LT (c, type_low_bound))
 	return false;
       ok_for_low_bound = true;
     }
@@ -8688,18 +8653,7 @@  int_fits_type_p (const_tree c, const_tre
   /* Check if c <= type_high_bound.  */
   if (type_high_bound && TREE_CODE (type_high_bound) == INTEGER_CST)
     {
-      wd = type_high_bound;
-      if (sgn_c != TYPE_SIGN (TREE_TYPE (type_high_bound)))
-	{
-	  int c_neg = (sgn_c == SIGNED && wi::neg_p (wc));
-	  int t_neg = (sgn_c == UNSIGNED && wi::neg_p (wd));
-
-	  if (t_neg && !c_neg)
-	    return false;
-	  if ((t_neg || !c_neg) && wi::gtu_p (wc, wd))
-	    return false;
-	}
-      else if (wi::gt_p (wc, wd, sgn_c))
+      if (INT_CST_LT (type_high_bound, c))
 	return false;
       ok_for_high_bound = true;
     }
Index: gcc/tree.h
===================================================================
--- gcc/tree.h	2013-10-27 14:11:53.006510519 +0000
+++ gcc/tree.h	2013-10-27 14:19:27.672578790 +0000
@@ -877,18 +877,15 @@  #define TREE_LANG_FLAG_6(NODE) \
 
 /* Define additional fields and accessors for nodes representing constants.  */
 
-#define INT_CST_LT(A, B)				\
-  (wi::lts_p (A, B))
-
-#define INT_CST_LT_UNSIGNED(A, B)			\
-  (wi::ltu_p (A, B))
-
 #define TREE_INT_CST_NUNITS(NODE) \
   (INTEGER_CST_CHECK (NODE)->base.u.int_length.unextended)
 #define TREE_INT_CST_EXT_NUNITS(NODE) \
   (INTEGER_CST_CHECK (NODE)->base.u.int_length.extended)
 #define TREE_INT_CST_ELT(NODE, I) TREE_INT_CST_ELT_CHECK (NODE, I)
 
+#define INT_CST_LT(A, B) (wi::lts_p (wi::to_widest (A), wi::to_widest (B)))
+#define INT_CST_LE(A, B) (wi::les_p (wi::to_widest (A), wi::to_widest (B)))
+
 #define TREE_REAL_CST_PTR(NODE) (REAL_CST_CHECK (NODE)->real_cst.real_cst_ptr)
 #define TREE_REAL_CST(NODE) (*TREE_REAL_CST_PTR (NODE))
 
Index: gcc/wide-int.cc
===================================================================
--- gcc/wide-int.cc	2013-10-27 14:11:53.006510519 +0000
+++ gcc/wide-int.cc	2013-10-27 14:19:27.660578682 +0000
@@ -416,22 +416,19 @@  wi::eq_p_large (const HOST_WIDE_INT *op0
 /* Return true if OP0 < OP1 using signed comparisons.  */
 bool
 wi::lts_p_large (const HOST_WIDE_INT *op0, unsigned int op0len,
-		 unsigned int p0,
-		 const HOST_WIDE_INT *op1, unsigned int op1len,
-		 unsigned int p1)
+		 unsigned int precision,
+		 const HOST_WIDE_INT *op1, unsigned int op1len)
 {
   HOST_WIDE_INT s0, s1;
   unsigned HOST_WIDE_INT u0, u1;
-  unsigned int blocks_needed0 = BLOCKS_NEEDED (p0);
-  unsigned int blocks_needed1 = BLOCKS_NEEDED (p1);
-  unsigned int small_prec0 = p0 & (HOST_BITS_PER_WIDE_INT - 1);
-  unsigned int small_prec1 = p1 & (HOST_BITS_PER_WIDE_INT - 1);
+  unsigned int blocks_needed = BLOCKS_NEEDED (precision);
+  unsigned int small_prec = precision & (HOST_BITS_PER_WIDE_INT - 1);
   int l = MAX (op0len - 1, op1len - 1);
 
   /* Only the top block is compared as signed.  The rest are unsigned
      comparisons.  */
-  s0 = selt (op0, op0len, blocks_needed0, small_prec0, l, SIGNED);
-  s1 = selt (op1, op1len, blocks_needed1, small_prec1, l, SIGNED);
+  s0 = selt (op0, op0len, blocks_needed, small_prec, l, SIGNED);
+  s1 = selt (op1, op1len, blocks_needed, small_prec, l, SIGNED);
   if (s0 < s1)
     return true;
   if (s0 > s1)
@@ -440,8 +437,8 @@  wi::lts_p_large (const HOST_WIDE_INT *op
   l--;
   while (l >= 0)
     {
-      u0 = selt (op0, op0len, blocks_needed0, small_prec0, l, SIGNED);
-      u1 = selt (op1, op1len, blocks_needed1, small_prec1, l, SIGNED);
+      u0 = selt (op0, op0len, blocks_needed, small_prec, l, SIGNED);
+      u1 = selt (op1, op1len, blocks_needed, small_prec, l, SIGNED);
 
       if (u0 < u1)
 	return true;
@@ -457,22 +454,19 @@  wi::lts_p_large (const HOST_WIDE_INT *op
    signed compares.  */
 int
 wi::cmps_large (const HOST_WIDE_INT *op0, unsigned int op0len,
-		unsigned int p0,
-		const HOST_WIDE_INT *op1, unsigned int op1len,
-		unsigned int p1)
+		unsigned int precision,
+		const HOST_WIDE_INT *op1, unsigned int op1len)
 {
   HOST_WIDE_INT s0, s1;
   unsigned HOST_WIDE_INT u0, u1;
-  unsigned int blocks_needed0 = BLOCKS_NEEDED (p0);
-  unsigned int blocks_needed1 = BLOCKS_NEEDED (p1);
-  unsigned int small_prec0 = p0 & (HOST_BITS_PER_WIDE_INT - 1);
-  unsigned int small_prec1 = p1 & (HOST_BITS_PER_WIDE_INT - 1);
+  unsigned int blocks_needed = BLOCKS_NEEDED (precision);
+  unsigned int small_prec = precision & (HOST_BITS_PER_WIDE_INT - 1);
   int l = MAX (op0len - 1, op1len - 1);
 
   /* Only the top block is compared as signed.  The rest are unsigned
      comparisons.  */
-  s0 = selt (op0, op0len, blocks_needed0, small_prec0, l, SIGNED);
-  s1 = selt (op1, op1len, blocks_needed1, small_prec1, l, SIGNED);
+  s0 = selt (op0, op0len, blocks_needed, small_prec, l, SIGNED);
+  s1 = selt (op1, op1len, blocks_needed, small_prec, l, SIGNED);
   if (s0 < s1)
     return -1;
   if (s0 > s1)
@@ -481,8 +475,8 @@  wi::cmps_large (const HOST_WIDE_INT *op0
   l--;
   while (l >= 0)
     {
-      u0 = selt (op0, op0len, blocks_needed0, small_prec0, l, SIGNED);
-      u1 = selt (op1, op1len, blocks_needed1, small_prec1, l, SIGNED);
+      u0 = selt (op0, op0len, blocks_needed, small_prec, l, SIGNED);
+      u1 = selt (op1, op1len, blocks_needed, small_prec, l, SIGNED);
 
       if (u0 < u1)
 	return -1;
@@ -496,21 +490,20 @@  wi::cmps_large (const HOST_WIDE_INT *op0
 
 /* Return true if OP0 < OP1 using unsigned comparisons.  */
 bool
-wi::ltu_p_large (const HOST_WIDE_INT *op0, unsigned int op0len, unsigned int p0,
-		 const HOST_WIDE_INT *op1, unsigned int op1len, unsigned int p1)
+wi::ltu_p_large (const HOST_WIDE_INT *op0, unsigned int op0len,
+		 unsigned int precision,
+		 const HOST_WIDE_INT *op1, unsigned int op1len)
 {
   unsigned HOST_WIDE_INT x0;
   unsigned HOST_WIDE_INT x1;
-  unsigned int blocks_needed0 = BLOCKS_NEEDED (p0);
-  unsigned int blocks_needed1 = BLOCKS_NEEDED (p1);
-  unsigned int small_prec0 = p0 & (HOST_BITS_PER_WIDE_INT - 1);
-  unsigned int small_prec1 = p1 & (HOST_BITS_PER_WIDE_INT - 1);
+  unsigned int blocks_needed = BLOCKS_NEEDED (precision);
+  unsigned int small_prec = precision & (HOST_BITS_PER_WIDE_INT - 1);
   int l = MAX (op0len - 1, op1len - 1);
 
   while (l >= 0)
     {
-      x0 = selt (op0, op0len, blocks_needed0, small_prec0, l, UNSIGNED);
-      x1 = selt (op1, op1len, blocks_needed1, small_prec1, l, UNSIGNED);
+      x0 = selt (op0, op0len, blocks_needed, small_prec, l, UNSIGNED);
+      x1 = selt (op1, op1len, blocks_needed, small_prec, l, UNSIGNED);
       if (x0 < x1)
 	return true;
       if (x0 > x1)
@@ -524,21 +517,20 @@  wi::ltu_p_large (const HOST_WIDE_INT *op
 /* Returns -1 if OP0 < OP1, 0 if OP0 == OP1 and 1 if OP0 > OP1 using
    unsigned compares.  */
 int
-wi::cmpu_large (const HOST_WIDE_INT *op0, unsigned int op0len, unsigned int p0,
-		const HOST_WIDE_INT *op1, unsigned int op1len, unsigned int p1)
+wi::cmpu_large (const HOST_WIDE_INT *op0, unsigned int op0len,
+		unsigned int precision,
+		const HOST_WIDE_INT *op1, unsigned int op1len)
 {
   unsigned HOST_WIDE_INT x0;
   unsigned HOST_WIDE_INT x1;
-  unsigned int blocks_needed0 = BLOCKS_NEEDED (p0);
-  unsigned int blocks_needed1 = BLOCKS_NEEDED (p1);
-  unsigned int small_prec0 = p0 & (HOST_BITS_PER_WIDE_INT - 1);
-  unsigned int small_prec1 = p1 & (HOST_BITS_PER_WIDE_INT - 1);
+  unsigned int blocks_needed = BLOCKS_NEEDED (precision);
+  unsigned int small_prec = precision & (HOST_BITS_PER_WIDE_INT - 1);
   int l = MAX (op0len - 1, op1len - 1);
 
   while (l >= 0)
     {
-      x0 = selt (op0, op0len, blocks_needed0, small_prec0, l, UNSIGNED);
-      x1 = selt (op1, op1len, blocks_needed1, small_prec1, l, UNSIGNED);
+      x0 = selt (op0, op0len, blocks_needed, small_prec, l, UNSIGNED);
+      x1 = selt (op1, op1len, blocks_needed, small_prec, l, UNSIGNED);
       if (x0 < x1)
 	return -1;
       if (x0 > x1)
Index: gcc/wide-int.h
===================================================================
--- gcc/wide-int.h	2013-10-27 14:19:26.641569564 +0000
+++ gcc/wide-int.h	2013-10-27 14:19:27.660578682 +0000
@@ -1355,13 +1355,13 @@  decompose (HOST_WIDE_INT *scratch, unsig
   bool eq_p_large (const HOST_WIDE_INT *, unsigned int,
 		   const HOST_WIDE_INT *, unsigned int, unsigned int);
   bool lts_p_large (const HOST_WIDE_INT *, unsigned int, unsigned int,
-		    const HOST_WIDE_INT *, unsigned int, unsigned int);
+		    const HOST_WIDE_INT *, unsigned int);
   bool ltu_p_large (const HOST_WIDE_INT *, unsigned int, unsigned int,
-		    const HOST_WIDE_INT *, unsigned int, unsigned int);
+		    const HOST_WIDE_INT *, unsigned int);
   int cmps_large (const HOST_WIDE_INT *, unsigned int, unsigned int,
-		  const HOST_WIDE_INT *, unsigned int, unsigned int);
+		  const HOST_WIDE_INT *, unsigned int);
   int cmpu_large (const HOST_WIDE_INT *, unsigned int, unsigned int,
-		  const HOST_WIDE_INT *, unsigned int, unsigned int);
+		  const HOST_WIDE_INT *, unsigned int);
   unsigned int sext_large (HOST_WIDE_INT *, const HOST_WIDE_INT *, 
 			   unsigned int,
 			   unsigned int, unsigned int);
@@ -1525,10 +1525,11 @@  wi::ne_p (const T1 &x, const T2 &y)
 inline bool
 wi::lts_p (const T1 &x, const T2 &y)
 {
-  WIDE_INT_REF_FOR (T1) xi (x);
-  WIDE_INT_REF_FOR (T2) yi (y);
+  unsigned int precision = get_binary_precision (x, y);
+  WIDE_INT_REF_FOR (T1) xi (x, precision);
+  WIDE_INT_REF_FOR (T2) yi (y, precision);
   // We optimize x < y, where y is 64 or fewer bits.
-  if (yi.precision <= HOST_BITS_PER_WIDE_INT)
+  if (wi::fits_shwi_p (yi))
     {
       // If x fits directly into a shwi, we can compare directly.
       if (wi::fits_shwi_p (xi))
@@ -1541,8 +1542,7 @@  wi::lts_p (const T1 &x, const T2 &y)
       // and hence greater than y.
       return false;
     }
-  return lts_p_large (xi.val, xi.len, xi.precision, yi.val, yi.len,
-		      yi.precision);
+  return lts_p_large (xi.val, xi.len, precision, yi.val, yi.len);
 }
 
 /* Return true if X < Y when both are treated as unsigned values.  */
@@ -1550,18 +1550,16 @@  wi::lts_p (const T1 &x, const T2 &y)
 inline bool
 wi::ltu_p (const T1 &x, const T2 &y)
 {
-  WIDE_INT_REF_FOR (T1) xi (x);
-  WIDE_INT_REF_FOR (T2) yi (y);
-  if (xi.precision <= HOST_BITS_PER_WIDE_INT
-      && yi.precision <= HOST_BITS_PER_WIDE_INT)
+  unsigned int precision = get_binary_precision (x, y);
+  WIDE_INT_REF_FOR (T1) xi (x, precision);
+  WIDE_INT_REF_FOR (T2) yi (y, precision);
+  if (precision <= HOST_BITS_PER_WIDE_INT)
     {
       unsigned HOST_WIDE_INT xl = xi.to_uhwi ();
       unsigned HOST_WIDE_INT yl = yi.to_uhwi ();
       return xl < yl;
     }
-  else
-    return ltu_p_large (xi.val, xi.len, xi.precision,
-			yi.val, yi.len, yi.precision);
+  return ltu_p_large (xi.val, xi.len, precision, yi.val, yi.len);
 }
 
 /* Return true if X < Y.  Signedness of X and Y is indicated by SGN.  */
@@ -1662,10 +1660,10 @@  wi::ge_p (const T1 &x, const T2 &y, sign
 inline int
 wi::cmps (const T1 &x, const T2 &y)
 {
-  WIDE_INT_REF_FOR (T1) xi (x);
-  WIDE_INT_REF_FOR (T2) yi (y);
-  if (xi.precision <= HOST_BITS_PER_WIDE_INT
-      && yi.precision <= HOST_BITS_PER_WIDE_INT)
+  unsigned int precision = get_binary_precision (x, y);
+  WIDE_INT_REF_FOR (T1) xi (x, precision);
+  WIDE_INT_REF_FOR (T2) yi (y, precision);
+  if (precision <= HOST_BITS_PER_WIDE_INT)
     {
       HOST_WIDE_INT xl = xi.to_shwi ();
       HOST_WIDE_INT yl = yi.to_shwi ();
@@ -1676,8 +1674,7 @@  wi::cmps (const T1 &x, const T2 &y)
       else
 	return 0;
     }
-  return cmps_large (xi.val, xi.len, xi.precision, yi.val, yi.len,
-		     yi.precision);
+  return cmps_large (xi.val, xi.len, precision, yi.val, yi.len);
 }
 
 /* Return -1 if X < Y, 0 if X == Y and 1 if X > Y.  Treat both X and Y
@@ -1686,10 +1683,10 @@  wi::cmps (const T1 &x, const T2 &y)
 inline int
 wi::cmpu (const T1 &x, const T2 &y)
 {
-  WIDE_INT_REF_FOR (T1) xi (x);
-  WIDE_INT_REF_FOR (T2) yi (y);
-  if (xi.precision <= HOST_BITS_PER_WIDE_INT
-      && yi.precision <= HOST_BITS_PER_WIDE_INT)
+  unsigned int precision = get_binary_precision (x, y);
+  WIDE_INT_REF_FOR (T1) xi (x, precision);
+  WIDE_INT_REF_FOR (T2) yi (y, precision);
+  if (precision <= HOST_BITS_PER_WIDE_INT)
     {
       unsigned HOST_WIDE_INT xl = xi.to_uhwi ();
       unsigned HOST_WIDE_INT yl = yi.to_uhwi ();
@@ -1700,8 +1697,7 @@  wi::cmpu (const T1 &x, const T2 &y)
       else
 	return 1;
     }
-  return cmpu_large (xi.val, xi.len, xi.precision, yi.val, yi.len,
-		     yi.precision);
+  return cmpu_large (xi.val, xi.len, precision, yi.val, yi.len);
 }
 
 /* Return -1 if X < Y, 0 if X == Y and 1 if X > Y.  Signedness of