diff mbox

patch to fix constant math - builtins.c - the first of the tree level patches for wide-int

Message ID 516DB380.6000505@naturalbridge.com
State New
Headers show

Commit Message

Kenneth Zadeck April 16, 2013, 8:24 p.m. UTC
Richard, this is the first of the tree level patches so that you can see 
how the wide-int changes will effect the tree level.   This patch 
converts builtins.c so that it does not in any way assume that tree-cst 
holds two HWIs.   The patch divides all math into two categories:   
Things that are always so small that we can easily assume that the math 
can be done using a single HWI and everything else.   The things that it 
assumes can easily be done with a HWI are guarded with assertions.   The 
everything else is done with wide-int.  Everything else in this patch is 
additional abi to support this.

The idea is that each pass will be converted, 1 pass per patch in this 
way.    Once everything does not depend on the internals of tree-cst as 
they do now, then tree-cst will be converted to have an array inside of 
it rather than just two hwis.

Kenny
2012-04-16  Kenneth Zadeck <zadeck@naturalbridge.com>

	* builtins.c (get_object_alignment_2, get_pointer_alignment_1,
	c_strlen, c_getstr, target_char_cast,
	expand_builtin_mempcpy_args, expand_builtin_strncpy,
	expand_builtin_memset_args, expand_builtin_strncpy,
	expand_builtin_memset_args, expand_builtin_frame_address,
	expand_builtin_alloca, expand_builtin_atomic_compare_exchange,
	fold_builtin_powi, fold_builtin_memset,
	fold_builtin_memory_op, fold_builtin_memchr,
	fold_builtin_memcmp, fold_builtin_strncmp,
	fold_builtin_load_exponent, fold_builtin_snprintf,
	expand_builtin_object_size, expand_builtin_memory_chk,
	maybe_emit_chk_warning, maybe_emit_sprintf_chk_warning,
	fold_builtin_object_size, fold_builtin_memory_chk,
	fold_builtin_stxcpy_chk, fold_builtin_strcat_chk,
	fold_builtin_sprintf_chk_1, fold_builtin_snprintf_chk_1,
	do_mpfr_bessel_n): Convert to api that does not assume that
	tree_cst is two HWIs.
	(fold_builtin_int_roundingfn, fold_builtin_bitop,
	fold_builtin_bswap, fold_builtin_memory_op,
	expand_builtin_object_size): Use wide-int rather than double-int api.
	
	* dfp.c (decimal_real_to_integer): Add wide-int version. 
	* real.c (real_to_integer): Ditto.
	* tree.h (tree_fits_uhwi_p, tree_fits_shwi_p, tree_fits_hwi_p, 
	tree_to_shwi, tree_to_hwi, tree_to_uhwi): New functions.
diff mbox

Patch

diff --git a/gcc/builtins.c b/gcc/builtins.c
index ed5a6b3..5ba2297 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -339,8 +339,8 @@  get_object_alignment_2 (tree exp, unsigned int *alignp,
       if (TREE_CODE (addr) == BIT_AND_EXPR
 	  && TREE_CODE (TREE_OPERAND (addr, 1)) == INTEGER_CST)
 	{
-	  align = (TREE_INT_CST_LOW (TREE_OPERAND (addr, 1))
-		    & -TREE_INT_CST_LOW (TREE_OPERAND (addr, 1)));
+	  align = (tree_to_hwi (TREE_OPERAND (addr, 1))
+		   & -tree_to_hwi (TREE_OPERAND (addr, 1)));
 	  align *= BITS_PER_UNIT;
 	  addr = TREE_OPERAND (addr, 0);
 	}
@@ -357,7 +357,7 @@  get_object_alignment_2 (tree exp, unsigned int *alignp,
 	    {
 	      unsigned HOST_WIDE_INT step = 1;
 	      if (TMR_STEP (exp))
-		step = TREE_INT_CST_LOW (TMR_STEP (exp));
+		step = tree_to_hwi (TMR_STEP (exp));
 	      align = MIN (align, (step & -step) * BITS_PER_UNIT);
 	    }
 	  if (TMR_INDEX2 (exp))
@@ -379,7 +379,8 @@  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 += wide_int::from_tree (TREE_OPERAND (exp, 1))
+	      .to_shwi () * BITS_PER_UNIT;
 	}
     }
   else if (TREE_CODE (exp) == STRING_CST)
@@ -408,23 +409,23 @@  get_object_alignment_2 (tree exp, unsigned int *alignp,
 	}
       else
 	next_offset = NULL;
-      if (host_integerp (offset, 1))
+      if (tree_fits_uhwi_p (offset))
 	{
 	  /* Any overflow in calculating offset_bits won't change
 	     the alignment.  */
 	  unsigned offset_bits
-	    = ((unsigned) tree_low_cst (offset, 1) * BITS_PER_UNIT);
+	    = ((unsigned) tree_to_hwi (offset) * BITS_PER_UNIT);
 
 	  if (offset_bits)
 	    inner = MIN (inner, (offset_bits & -offset_bits));
 	}
       else if (TREE_CODE (offset) == MULT_EXPR
-	       && host_integerp (TREE_OPERAND (offset, 1), 1))
+	       && tree_fits_uhwi_p (TREE_OPERAND (offset, 1)))
 	{
 	  /* Any overflow in calculating offset_factor won't change
 	     the alignment.  */
 	  unsigned offset_factor
-	    = ((unsigned) tree_low_cst (TREE_OPERAND (offset, 1), 1)
+	    = ((unsigned) tree_to_hwi (TREE_OPERAND (offset, 1))
 	       * BITS_PER_UNIT);
 
 	  if (offset_factor)
@@ -515,7 +516,7 @@  get_pointer_alignment_1 (tree exp, unsigned int *alignp,
   else if (TREE_CODE (exp) == INTEGER_CST)
     {
       *alignp = BIGGEST_ALIGNMENT;
-      *bitposp = ((TREE_INT_CST_LOW (exp) * BITS_PER_UNIT)
+      *bitposp = ((tree_to_hwi (exp) * BITS_PER_UNIT)
 		  & (BIGGEST_ALIGNMENT - 1));
       return true;
     }
@@ -624,10 +625,10 @@  c_strlen (tree src, int only_value)
      a null character if we can represent it as a single HOST_WIDE_INT.  */
   if (offset_node == 0)
     offset = 0;
-  else if (! host_integerp (offset_node, 0))
+  else if (!tree_fits_shwi_p (offset_node))
     offset = -1;
   else
-    offset = tree_low_cst (offset_node, 0);
+    offset = tree_to_hwi (offset_node);
 
   /* If the offset is known to be out of bounds, warn, and call strlen at
      runtime.  */
@@ -665,11 +666,11 @@  c_getstr (tree src)
 
   if (offset_node == 0)
     return TREE_STRING_POINTER (src);
-  else if (!host_integerp (offset_node, 1)
+  else if (!tree_fits_uhwi_p (offset_node)
 	   || compare_tree_int (offset_node, TREE_STRING_LENGTH (src) - 1) > 0)
     return 0;
 
-  return TREE_STRING_POINTER (src) + tree_low_cst (offset_node, 1);
+  return TREE_STRING_POINTER (src) + tree_to_uhwi (offset_node);
 }
 
 /* Return a constant integer corresponding to target reading
@@ -723,7 +724,9 @@  target_char_cast (tree cst, char *p)
       || CHAR_TYPE_SIZE > HOST_BITS_PER_WIDE_INT)
     return 1;
 
-  val = TREE_INT_CST_LOW (cst);
+  /* Do not care if it fits or not right here.  */
+  val = tree_to_hwi (cst);
+
   if (CHAR_TYPE_SIZE < HOST_BITS_PER_WIDE_INT)
     val &= (((unsigned HOST_WIDE_INT) 1) << CHAR_TYPE_SIZE) - 1;
 
@@ -3168,7 +3171,7 @@  expand_builtin_mempcpy_args (tree dest, tree src, tree len,
 	return NULL_RTX;
 
       /* If LEN is not constant, call the normal function.  */
-      if (! host_integerp (len, 1))
+      if (! tree_fits_uhwi_p (len))
 	return NULL_RTX;
 
       len_rtx = expand_normal (len);
@@ -3403,7 +3406,7 @@  expand_builtin_strncpy (tree exp, rtx target)
       tree slen = c_strlen (src, 1);
 
       /* We must be passed a constant len and src parameter.  */
-      if (!host_integerp (len, 1) || !slen || !host_integerp (slen, 1))
+      if (!tree_fits_uhwi_p (len) || !slen || !tree_fits_uhwi_p (slen))
 	return NULL_RTX;
 
       slen = size_binop_loc (loc, PLUS_EXPR, slen, ssize_int (1));
@@ -3417,15 +3420,15 @@  expand_builtin_strncpy (tree exp, rtx target)
 	  const char *p = c_getstr (src);
 	  rtx dest_mem;
 
-	  if (!p || dest_align == 0 || !host_integerp (len, 1)
-	      || !can_store_by_pieces (tree_low_cst (len, 1),
+	  if (!p || dest_align == 0 || !tree_fits_uhwi_p (len)
+	      || !can_store_by_pieces (tree_to_uhwi (len),
 				       builtin_strncpy_read_str,
 				       CONST_CAST (char *, p),
 				       dest_align, false))
 	    return NULL_RTX;
 
 	  dest_mem = get_memory_rtx (dest, len);
-	  store_by_pieces (dest_mem, tree_low_cst (len, 1),
+	  store_by_pieces (dest_mem, tree_to_uhwi (len),
 			   builtin_strncpy_read_str,
 			   CONST_CAST (char *, p), dest_align, false, 0);
 	  dest_mem = force_operand (XEXP (dest_mem, 0), target);
@@ -3558,13 +3561,13 @@  expand_builtin_memset_args (tree dest, tree val, tree len,
        * the coefficients by pieces (in the required modes).
        * We can't pass builtin_memset_gen_str as that emits RTL.  */
       c = 1;
-      if (host_integerp (len, 1)
-	  && can_store_by_pieces (tree_low_cst (len, 1),
+      if (tree_fits_uhwi_p (len)
+	  && can_store_by_pieces (tree_to_hwi (len),
 				  builtin_memset_read_str, &c, dest_align,
 				  true))
 	{
 	  val_rtx = force_reg (val_mode, val_rtx);
-	  store_by_pieces (dest_mem, tree_low_cst (len, 1),
+	  store_by_pieces (dest_mem, tree_to_hwi (len),
 			   builtin_memset_gen_str, val_rtx, dest_align,
 			   true, 0);
 	}
@@ -3583,11 +3586,11 @@  expand_builtin_memset_args (tree dest, tree val, tree len,
 
   if (c)
     {
-      if (host_integerp (len, 1)
-	  && can_store_by_pieces (tree_low_cst (len, 1),
+      if (tree_fits_uhwi_p (len)
+	  && can_store_by_pieces (tree_to_hwi (len),
 				  builtin_memset_read_str, &c, dest_align,
 				  true))
-	store_by_pieces (dest_mem, tree_low_cst (len, 1),
+	store_by_pieces (dest_mem, tree_to_hwi (len),
 			 builtin_memset_read_str, &c, dest_align, true, 0);
       else if (!set_storage_via_setmem (dest_mem, len_rtx,
 					gen_int_mode (c, val_mode),
@@ -4492,7 +4495,7 @@  expand_builtin_frame_address (tree fndecl, tree exp)
   if (call_expr_nargs (exp) == 0)
     /* Warning about missing arg was already issued.  */
     return const0_rtx;
-  else if (! host_integerp (CALL_EXPR_ARG (exp, 0), 1))
+  else if (! tree_fits_uhwi_p (CALL_EXPR_ARG (exp, 0)))
     {
       if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FRAME_ADDRESS)
 	error ("invalid argument to %<__builtin_frame_address%>");
@@ -4504,7 +4507,7 @@  expand_builtin_frame_address (tree fndecl, tree exp)
     {
       rtx tem
 	= expand_builtin_return_addr (DECL_FUNCTION_CODE (fndecl),
-				      tree_low_cst (CALL_EXPR_ARG (exp, 0), 1));
+				      tree_to_uhwi (CALL_EXPR_ARG (exp, 0)));
 
       /* Some ports cannot access arbitrary stack frames.  */
       if (tem == NULL)
@@ -4558,7 +4561,7 @@  expand_builtin_alloca (tree exp, bool cannot_accumulate)
 
   /* Compute the alignment.  */
   align = (alloca_with_align
-	   ? TREE_INT_CST_LOW (CALL_EXPR_ARG (exp, 1))
+	   ? tree_to_uhwi (CALL_EXPR_ARG (exp, 1))
 	   : BIGGEST_ALIGNMENT);
 
   /* Allocate the desired space.  */
@@ -5390,7 +5393,7 @@  expand_builtin_atomic_compare_exchange (enum machine_mode mode, tree exp,
 
   weak = CALL_EXPR_ARG (exp, 3);
   is_weak = false;
-  if (host_integerp (weak, 0) && tree_low_cst (weak, 0) != 0)
+  if (tree_fits_shwi_p (weak) && tree_to_hwi (weak) != 0)
     is_weak = true;
 
   oldval = expect;
@@ -8026,8 +8029,9 @@  fold_builtin_int_roundingfn (location_t loc, tree fndecl, tree arg)
 	{
 	  tree itype = TREE_TYPE (TREE_TYPE (fndecl));
 	  tree ftype = TREE_TYPE (arg);
-	  double_int val;
+	  wide_int val;
 	  REAL_VALUE_TYPE r;
+	  bool fail = false;
 
 	  switch (DECL_FUNCTION_CODE (fndecl))
 	    {
@@ -8053,9 +8057,10 @@  fold_builtin_int_roundingfn (location_t loc, tree fndecl, tree arg)
 	      gcc_unreachable ();
 	    }
 
-	  real_to_integer2 ((HOST_WIDE_INT *)&val.low, &val.high, &r);
-	  if (double_int_fits_to_tree_p (itype, val))
-	    return double_int_to_tree (itype, val);
+	  val = real_to_integer (&r, &fail, 
+				 TYPE_PRECISION (itype));
+	  if (!fail)
+	    return wide_int_to_tree (itype, val);
 	}
     }
 
@@ -8088,100 +8093,40 @@  fold_builtin_bitop (tree fndecl, tree arg)
   /* Optimize for constant argument.  */
   if (TREE_CODE (arg) == INTEGER_CST && !TREE_OVERFLOW (arg))
     {
-      HOST_WIDE_INT hi, width, result;
-      unsigned HOST_WIDE_INT lo;
-      tree type;
-
-      type = TREE_TYPE (arg);
-      width = TYPE_PRECISION (type);
-      lo = TREE_INT_CST_LOW (arg);
-
-      /* Clear all the bits that are beyond the type's precision.  */
-      if (width > HOST_BITS_PER_WIDE_INT)
-	{
-	  hi = TREE_INT_CST_HIGH (arg);
-	  if (width < HOST_BITS_PER_DOUBLE_INT)
-	    hi &= ~((unsigned HOST_WIDE_INT) (-1)
-		    << (width - HOST_BITS_PER_WIDE_INT));
-	}
-      else
-	{
-	  hi = 0;
-	  if (width < HOST_BITS_PER_WIDE_INT)
-	    lo &= ~((unsigned HOST_WIDE_INT) (-1) << width);
-	}
+      wide_int warg = wide_int::from_tree (arg);
+      wide_int result;
 
       switch (DECL_FUNCTION_CODE (fndecl))
 	{
 	CASE_INT_FN (BUILT_IN_FFS):
-	  if (lo != 0)
-	    result = ffs_hwi (lo);
-	  else if (hi != 0)
-	    result = HOST_BITS_PER_WIDE_INT + ffs_hwi (hi);
-	  else
-	    result = 0;
+	  result = warg.ffs ();
 	  break;
 
 	CASE_INT_FN (BUILT_IN_CLZ):
-	  if (hi != 0)
-	    result = width - floor_log2 (hi) - 1 - HOST_BITS_PER_WIDE_INT;
-	  else if (lo != 0)
-	    result = width - floor_log2 (lo) - 1;
-	  else if (! CLZ_DEFINED_VALUE_AT_ZERO (TYPE_MODE (type), result))
-	    result = width;
+	  result = warg.clz ();
 	  break;
 
 	CASE_INT_FN (BUILT_IN_CTZ):
-	  if (lo != 0)
-	    result = ctz_hwi (lo);
-	  else if (hi != 0)
-	    result = HOST_BITS_PER_WIDE_INT + ctz_hwi (hi);
-	  else if (! CTZ_DEFINED_VALUE_AT_ZERO (TYPE_MODE (type), result))
-	    result = width;
+	  result = warg.ctz ();
 	  break;
 
 	CASE_INT_FN (BUILT_IN_CLRSB):
-	  if (width > HOST_BITS_PER_WIDE_INT
-	      && (hi & ((unsigned HOST_WIDE_INT) 1
-			<< (width - HOST_BITS_PER_WIDE_INT - 1))) != 0)
-	    {
-	      hi = ~hi & ~((unsigned HOST_WIDE_INT) (-1)
-			   << (width - HOST_BITS_PER_WIDE_INT - 1));
-	      lo = ~lo;
-	    }
-	  else if (width <= HOST_BITS_PER_WIDE_INT
-		   && (lo & ((unsigned HOST_WIDE_INT) 1 << (width - 1))) != 0)
-	    lo = ~lo & ~((unsigned HOST_WIDE_INT) (-1) << (width - 1));
-	  if (hi != 0)
-	    result = width - floor_log2 (hi) - 2 - HOST_BITS_PER_WIDE_INT;
-	  else if (lo != 0)
-	    result = width - floor_log2 (lo) - 2;
-	  else
-	    result = width - 1;
+	  result = warg.clrsb ();
 	  break;
 
 	CASE_INT_FN (BUILT_IN_POPCOUNT):
-	  result = 0;
-	  while (lo)
-	    result++, lo &= lo - 1;
-	  while (hi)
-	    result++, hi &= (unsigned HOST_WIDE_INT) hi - 1;
+	  result = warg.popcount ();
 	  break;
 
 	CASE_INT_FN (BUILT_IN_PARITY):
-	  result = 0;
-	  while (lo)
-	    result++, lo &= lo - 1;
-	  while (hi)
-	    result++, hi &= (unsigned HOST_WIDE_INT) hi - 1;
-	  result &= 1;
+	  result = warg.parity ();
 	  break;
 
 	default:
 	  gcc_unreachable ();
 	}
 
-      return build_int_cst (TREE_TYPE (TREE_TYPE (fndecl)), result);
+      return wide_int_to_tree (TREE_TYPE (TREE_TYPE (fndecl)), result);
     }
 
   return NULL_TREE;
@@ -8198,49 +8143,21 @@  fold_builtin_bswap (tree fndecl, tree arg)
   /* Optimize constant value.  */
   if (TREE_CODE (arg) == INTEGER_CST && !TREE_OVERFLOW (arg))
     {
-      HOST_WIDE_INT hi, width, r_hi = 0;
-      unsigned HOST_WIDE_INT lo, r_lo = 0;
       tree type = TREE_TYPE (TREE_TYPE (fndecl));
 
-      width = TYPE_PRECISION (type);
-      lo = TREE_INT_CST_LOW (arg);
-      hi = TREE_INT_CST_HIGH (arg);
-
       switch (DECL_FUNCTION_CODE (fndecl))
 	{
 	  case BUILT_IN_BSWAP16:
 	  case BUILT_IN_BSWAP32:
 	  case BUILT_IN_BSWAP64:
 	    {
-	      int s;
-
-	      for (s = 0; s < width; s += 8)
-		{
-		  int d = width - s - 8;
-		  unsigned HOST_WIDE_INT byte;
-
-		  if (s < HOST_BITS_PER_WIDE_INT)
-		    byte = (lo >> s) & 0xff;
-		  else
-		    byte = (hi >> (s - HOST_BITS_PER_WIDE_INT)) & 0xff;
-
-		  if (d < HOST_BITS_PER_WIDE_INT)
-		    r_lo |= byte << d;
-		  else
-		    r_hi |= byte << (d - HOST_BITS_PER_WIDE_INT);
-		}
+	      tree result = wide_int_to_tree (type, wide_int::from_tree (arg)
+					      .force_to_size (type).bswap ());
+	      return result;
 	    }
-
-	    break;
-
 	default:
 	  gcc_unreachable ();
 	}
-
-      if (width < HOST_BITS_PER_WIDE_INT)
-	return build_int_cst (type, r_lo);
-      else
-	return build_int_cst_wide (type, r_lo, r_hi);
     }
 
   return NULL_TREE;
@@ -8553,9 +8470,9 @@  fold_builtin_powi (location_t loc, tree fndecl ATTRIBUTE_UNUSED,
   if (real_onep (arg0))
     return omit_one_operand_loc (loc, type, build_real (type, dconst1), arg1);
 
-  if (host_integerp (arg1, 0))
+  if (tree_fits_shwi_p (arg1))
     {
-      HOST_WIDE_INT c = TREE_INT_CST_LOW (arg1);
+      HOST_WIDE_INT c = tree_to_hwi (arg1);
 
       /* Evaluate powi at compile-time.  */
       if (TREE_CODE (arg0) == REAL_CST
@@ -8652,7 +8569,7 @@  fold_builtin_memset (location_t loc, tree dest, tree c, tree len,
       || ! validate_arg (len, INTEGER_TYPE))
     return NULL_TREE;
 
-  if (! host_integerp (len, 1))
+  if (! tree_fits_uhwi_p (len))
     return NULL_TREE;
 
   /* If the LEN parameter is zero, return DEST.  */
@@ -8682,7 +8599,7 @@  fold_builtin_memset (location_t loc, tree dest, tree c, tree len,
   if (! var_decl_component_p (var))
     return NULL_TREE;
 
-  length = tree_low_cst (len, 1);
+  length = tree_to_uhwi (len);
   if (GET_MODE_SIZE (TYPE_MODE (etype)) != length
       || get_pointer_alignment (dest) / BITS_PER_UNIT < length)
     return NULL_TREE;
@@ -8697,7 +8614,7 @@  fold_builtin_memset (location_t loc, tree dest, tree c, tree len,
       if (CHAR_BIT != 8 || BITS_PER_UNIT != 8 || HOST_BITS_PER_WIDE_INT > 64)
 	return NULL_TREE;
 
-      cval = TREE_INT_CST_LOW (c);
+      cval = tree_to_hwi (c);
       cval &= 0xff;
       cval |= cval << 8;
       cval |= cval << 16;
@@ -8785,9 +8702,9 @@  fold_builtin_memory_op (location_t loc, tree dest, tree src,
 	  if (!dest_align || !src_align)
 	    return NULL_TREE;
 	  if (readonly_data_expr (src)
-	      || (host_integerp (len, 1)
+	      || (tree_fits_uhwi_p (len)
 		  && (MIN (src_align, dest_align) / BITS_PER_UNIT
-		      >= (unsigned HOST_WIDE_INT) tree_low_cst (len, 1))))
+		      >= (unsigned HOST_WIDE_INT) tree_to_uhwi (len))))
 	    {
 	      tree fn = builtin_decl_implicit (BUILT_IN_MEMCPY);
 	      if (!fn)
@@ -8810,8 +8727,8 @@  fold_builtin_memory_op (location_t loc, tree dest, tree src,
 	      destvar = TREE_OPERAND (dest, 0);
 	      dest_base = get_ref_base_and_extent (destvar, &dest_offset,
 						   &size, &maxsize);
-	      if (host_integerp (len, 1))
-		maxsize = tree_low_cst (len, 1);
+	      if (tree_fits_uhwi_p (len))
+		maxsize = tree_to_hwi (len);
 	      else
 		maxsize = -1;
 	      src_offset /= BITS_PER_UNIT;
@@ -8827,20 +8744,19 @@  fold_builtin_memory_op (location_t loc, tree dest, tree src,
 	      else if (TREE_CODE (src_base) == MEM_REF
 		       && TREE_CODE (dest_base) == MEM_REF)
 		{
-		  double_int off;
+		  wide_int off;
 		  if (! operand_equal_p (TREE_OPERAND (src_base, 0),
 					 TREE_OPERAND (dest_base, 0), 0))
 		    return NULL_TREE;
-		  off = mem_ref_offset (src_base) +
-					double_int::from_shwi (src_offset);
-		  if (!off.fits_shwi ())
+		  off = wide_int::from_tree (TREE_OPERAND (src_base, 1)) + src_offset;
+		  if (!off.fits_shwi_p ())
 		    return NULL_TREE;
-		  src_offset = off.low;
-		  off = mem_ref_offset (dest_base) +
-					double_int::from_shwi (dest_offset);
-		  if (!off.fits_shwi ())
+		  src_offset = off.to_shwi ();
+
+		  off = wide_int::from_tree (TREE_OPERAND (dest_base, 1)) + dest_offset;
+		  if (!off.fits_shwi_p ())
 		    return NULL_TREE;
-		  dest_offset = off.low;
+		  dest_offset = off.to_shwi ();
 		  if (ranges_overlap_p (src_offset, maxsize,
 					dest_offset, maxsize))
 		    return NULL_TREE;
@@ -8877,7 +8793,7 @@  fold_builtin_memory_op (location_t loc, tree dest, tree src,
 	  return NULL_TREE;
 	}
 
-      if (!host_integerp (len, 0))
+      if (!tree_fits_shwi_p (len))
 	return NULL_TREE;
       /* FIXME:
          This logic lose for arguments like (type *)malloc (sizeof (type)),
@@ -9165,7 +9081,7 @@  fold_builtin_memchr (location_t loc, tree arg1, tree arg2, tree len, tree type)
       const char *p1;
 
       if (TREE_CODE (arg2) != INTEGER_CST
-	  || !host_integerp (len, 1))
+	  || !tree_fits_uhwi_p (len))
 	return NULL_TREE;
 
       p1 = c_getstr (arg1);
@@ -9178,7 +9094,7 @@  fold_builtin_memchr (location_t loc, tree arg1, tree arg2, tree len, tree type)
 	  if (target_char_cast (arg2, &c))
 	    return NULL_TREE;
 
-	  r = (const char *) memchr (p1, c, tree_low_cst (len, 1));
+	  r = (const char *) memchr (p1, c, tree_to_uhwi (len));
 
 	  if (r == NULL)
 	    return build_int_cst (TREE_TYPE (arg1), 0);
@@ -9217,11 +9133,11 @@  fold_builtin_memcmp (location_t loc, tree arg1, tree arg2, tree len)
 
   /* If all arguments are constant, and the value of len is not greater
      than the lengths of arg1 and arg2, evaluate at compile-time.  */
-  if (host_integerp (len, 1) && p1 && p2
+  if (tree_fits_uhwi_p (len) && p1 && p2
       && compare_tree_int (len, strlen (p1) + 1) <= 0
       && compare_tree_int (len, strlen (p2) + 1) <= 0)
     {
-      const int r = memcmp (p1, p2, tree_low_cst (len, 1));
+      const int r = memcmp (p1, p2, tree_to_uhwi (len));
 
       if (r > 0)
 	return integer_one_node;
@@ -9233,7 +9149,7 @@  fold_builtin_memcmp (location_t loc, tree arg1, tree arg2, tree len)
 
   /* If len parameter is one, return an expression corresponding to
      (*(const unsigned char*)arg1 - (const unsigned char*)arg2).  */
-  if (host_integerp (len, 1) && tree_low_cst (len, 1) == 1)
+  if (tree_fits_uhwi_p (len) && tree_to_hwi (len) == 1)
     {
       tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
       tree cst_uchar_ptr_node
@@ -9345,9 +9261,9 @@  fold_builtin_strncmp (location_t loc, tree arg1, tree arg2, tree len)
   p1 = c_getstr (arg1);
   p2 = c_getstr (arg2);
 
-  if (host_integerp (len, 1) && p1 && p2)
+  if (tree_fits_uhwi_p (len) && p1 && p2)
     {
-      const int i = strncmp (p1, p2, tree_low_cst (len, 1));
+      const int i = strncmp (p1, p2, tree_to_hwi (len));
       if (i > 0)
 	return integer_one_node;
       else if (i < 0)
@@ -9393,7 +9309,7 @@  fold_builtin_strncmp (location_t loc, tree arg1, tree arg2, tree len)
 
   /* If len parameter is one, return an expression corresponding to
      (*(const unsigned char*)arg1 - (const unsigned char*)arg2).  */
-  if (host_integerp (len, 1) && tree_low_cst (len, 1) == 1)
+  if (tree_fits_uhwi_p (len) && tree_to_hwi (len) == 1)
     {
       tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
       tree cst_uchar_ptr_node
@@ -9842,7 +9758,7 @@  fold_builtin_load_exponent (location_t loc, tree arg0, tree arg1,
       /* If both arguments are constant, then try to evaluate it.  */
       if ((ldexp || REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2)
 	  && TREE_CODE (arg0) == REAL_CST && !TREE_OVERFLOW (arg0)
-	  && host_integerp (arg1, 0))
+	  && tree_fits_shwi_p (arg1))
         {
 	  /* Bound the maximum adjustment to twice the range of the
 	     mode's valid exponents.  Use abs to ensure the range is
@@ -9852,7 +9768,7 @@  fold_builtin_load_exponent (location_t loc, tree arg0, tree arg1,
 		 - REAL_MODE_FORMAT (TYPE_MODE (type))->emin);
 
 	  /* Get the user-requested adjustment.  */
-	  const HOST_WIDE_INT req_exp_adj = tree_low_cst (arg1, 0);
+	  const HOST_WIDE_INT req_exp_adj = tree_to_shwi (arg1);
 
 	  /* The requested adjustment must be inside this range.  This
 	     is a preliminary cap to avoid things like overflow, we
@@ -12322,7 +12238,7 @@  fold_builtin_snprintf (location_t loc, tree dest, tree destsize, tree fmt,
   if (orig && !validate_arg (orig, POINTER_TYPE))
     return NULL_TREE;
 
-  if (!host_integerp (destsize, 1))
+  if (!tree_fits_uhwi_p (destsize))
     return NULL_TREE;
 
   /* Check whether the format is a literal string constant.  */
@@ -12336,7 +12252,7 @@  fold_builtin_snprintf (location_t loc, tree dest, tree destsize, tree fmt,
   if (!init_target_chars ())
     return NULL_TREE;
 
-  destlen = tree_low_cst (destsize, 1);
+  destlen = tree_to_hwi (destsize);
 
   /* If the format doesn't contain % args or %%, use strcpy.  */
   if (strchr (fmt_str, target_percent) == NULL)
@@ -12381,10 +12297,10 @@  fold_builtin_snprintf (location_t loc, tree dest, tree destsize, tree fmt,
 	return NULL_TREE;
 
       retval = c_strlen (orig, 1);
-      if (!retval || !host_integerp (retval, 1))  
+      if (!retval || !tree_fits_uhwi_p (retval))  
 	return NULL_TREE;
 
-      origlen = tree_low_cst (retval, 1);
+      origlen = tree_to_hwi (retval);
       /* We could expand this as
 	 memcpy (str1, str2, cst - 1); str1[cst - 1] = '\0';
 	 or to
@@ -12446,7 +12362,7 @@  expand_builtin_object_size (tree exp)
       return const0_rtx;
     }
 
-  object_size_type = tree_low_cst (ost, 0);
+  object_size_type = tree_to_shwi (ost);
 
   return object_size_type < 2 ? constm1_rtx : const0_rtx;
 }
@@ -12475,10 +12391,10 @@  expand_builtin_memory_chk (tree exp, rtx target, enum machine_mode mode,
   len = CALL_EXPR_ARG (exp, 2);
   size = CALL_EXPR_ARG (exp, 3);
 
-  if (! host_integerp (size, 1))
+  if (! tree_fits_uhwi_p (size))
     return NULL_RTX;
 
-  if (host_integerp (len, 1) || integer_all_onesp (size))
+  if (tree_fits_uhwi_p (len) || integer_all_onesp (size))
     {
       tree fn;
 
@@ -12609,22 +12525,22 @@  maybe_emit_chk_warning (tree exp, enum built_in_function fcode)
   if (!len || !size)
     return;
 
-  if (! host_integerp (size, 1) || integer_all_onesp (size))
+  if (! tree_fits_uhwi_p (size) || integer_all_onesp (size))
     return;
 
   if (is_strlen)
     {
       len = c_strlen (len, 1);
-      if (! len || ! host_integerp (len, 1) || tree_int_cst_lt (len, size))
+      if (! len || ! tree_fits_uhwi_p (len) || tree_int_cst_lt (len, size))
 	return;
     }
   else if (fcode == BUILT_IN_STRNCAT_CHK)
     {
       tree src = CALL_EXPR_ARG (exp, 1);
-      if (! src || ! host_integerp (len, 1) || tree_int_cst_lt (len, size))
+      if (! src || ! tree_fits_uhwi_p (len) || tree_int_cst_lt (len, size))
 	return;
       src = c_strlen (src, 1);
-      if (! src || ! host_integerp (src, 1))
+      if (! src || ! tree_fits_uhwi_p (src))
 	{
 	  warning_at (loc, 0, "%Kcall to %D might overflow destination buffer",
 		      exp, get_callee_fndecl (exp));
@@ -12633,7 +12549,7 @@  maybe_emit_chk_warning (tree exp, enum built_in_function fcode)
       else if (tree_int_cst_lt (src, size))
 	return;
     }
-  else if (! host_integerp (len, 1) || ! tree_int_cst_lt (size, len))
+  else if (! tree_fits_uhwi_p (len) || ! tree_int_cst_lt (size, len))
     return;
 
   warning_at (loc, 0, "%Kcall to %D will always overflow destination buffer",
@@ -12657,7 +12573,7 @@  maybe_emit_sprintf_chk_warning (tree exp, enum built_in_function fcode)
   size = CALL_EXPR_ARG (exp, 2);
   fmt = CALL_EXPR_ARG (exp, 3);
 
-  if (! host_integerp (size, 1) || integer_all_onesp (size))
+  if (! tree_fits_uhwi_p (size) || integer_all_onesp (size))
     return;
 
   /* Check whether the format is a literal string constant.  */
@@ -12685,7 +12601,7 @@  maybe_emit_sprintf_chk_warning (tree exp, enum built_in_function fcode)
 	return;
 
       len = c_strlen (arg, 1);
-      if (!len || ! host_integerp (len, 1))
+      if (!len || ! tree_fits_uhwi_p (len))
 	return;
     }
   else
@@ -12728,6 +12644,7 @@  fold_builtin_object_size (tree ptr, tree ost)
 {
   unsigned HOST_WIDE_INT bytes;
   int object_size_type;
+  int precision = TYPE_PRECISION (TREE_TYPE (ptr));
 
   if (!validate_arg (ptr, POINTER_TYPE)
       || !validate_arg (ost, INTEGER_TYPE))
@@ -12740,7 +12657,7 @@  fold_builtin_object_size (tree ptr, tree ost)
       || compare_tree_int (ost, 3) > 0)
     return NULL_TREE;
 
-  object_size_type = tree_low_cst (ost, 0);
+  object_size_type = tree_to_shwi (ost);
 
   /* __builtin_object_size doesn't evaluate side-effects in its arguments;
      if there are any side-effects, it returns (size_t) -1 for types 0 and 1
@@ -12750,21 +12667,24 @@  fold_builtin_object_size (tree ptr, tree ost)
 
   if (TREE_CODE (ptr) == ADDR_EXPR)
     {
-      bytes = compute_builtin_object_size (ptr, object_size_type);
-      if (double_int_fits_to_tree_p (size_type_node,
-				     double_int::from_uhwi (bytes)))
-	return build_int_cstu (size_type_node, bytes);
+
+      wide_int wbytes 
+	= wide_int::from_uhwi (compute_builtin_object_size (ptr, object_size_type),
+			       precision);
+      if (wbytes.fits_to_tree_p (size_type_node))
+	return wide_int_to_tree (size_type_node, wbytes);
     }
   else if (TREE_CODE (ptr) == SSA_NAME)
     {
       /* If object size is not known yet, delay folding until
        later.  Maybe subsequent passes will help determining
        it.  */
+      wide_int wbytes;
       bytes = compute_builtin_object_size (ptr, object_size_type);
+      wbytes = wide_int::from_uhwi (bytes, precision);
       if (bytes != (unsigned HOST_WIDE_INT) (object_size_type < 2 ? -1 : 0)
-          && double_int_fits_to_tree_p (size_type_node,
-					double_int::from_uhwi (bytes)))
-	return build_int_cstu (size_type_node, bytes);
+          && wbytes.fits_to_tree_p (size_type_node))
+	return wide_int_to_tree (size_type_node, wbytes);
     }
 
   return NULL_TREE;
@@ -12806,17 +12726,17 @@  fold_builtin_memory_chk (location_t loc, tree fndecl,
 	}
     }
 
-  if (! host_integerp (size, 1))
+  if (! tree_fits_uhwi_p (size))
     return NULL_TREE;
 
   if (! integer_all_onesp (size))
     {
-      if (! host_integerp (len, 1))
+      if (! tree_fits_uhwi_p (len))
 	{
 	  /* If LEN is not constant, try MAXLEN too.
 	     For MAXLEN only allow optimizing into non-_ocs function
 	     if SIZE is >= MAXLEN, never convert to __ocs_fail ().  */
-	  if (maxlen == NULL_TREE || ! host_integerp (maxlen, 1))
+	  if (maxlen == NULL_TREE || ! tree_fits_uhwi_p (maxlen))
 	    {
 	      if (fcode == BUILT_IN_MEMPCPY_CHK && ignore)
 		{
@@ -12888,18 +12808,18 @@  fold_builtin_stxcpy_chk (location_t loc, tree fndecl, tree dest,
   if (fcode == BUILT_IN_STRCPY_CHK && operand_equal_p (src, dest, 0))
     return fold_convert_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)), dest);
 
-  if (! host_integerp (size, 1))
+  if (! tree_fits_uhwi_p (size))
     return NULL_TREE;
 
   if (! integer_all_onesp (size))
     {
       len = c_strlen (src, 1);
-      if (! len || ! host_integerp (len, 1))
+      if (! len || ! tree_fits_uhwi_p (len))
 	{
 	  /* If LEN is not constant, try MAXLEN too.
 	     For MAXLEN only allow optimizing into non-_ocs function
 	     if SIZE is >= MAXLEN, never convert to __ocs_fail ().  */
-	  if (maxlen == NULL_TREE || ! host_integerp (maxlen, 1))
+	  if (maxlen == NULL_TREE || ! tree_fits_uhwi_p (maxlen))
 	    {
 	      if (fcode == BUILT_IN_STPCPY_CHK)
 		{
@@ -12975,17 +12895,17 @@  fold_builtin_stxncpy_chk (location_t loc, tree dest, tree src,
          return build_call_expr_loc (loc, fn, 4, dest, src, len, size);
     }
 
-  if (! host_integerp (size, 1))
+  if (! tree_fits_uhwi_p (size))
     return NULL_TREE;
 
   if (! integer_all_onesp (size))
     {
-      if (! host_integerp (len, 1))
+      if (! tree_fits_uhwi_p (len))
 	{
 	  /* If LEN is not constant, try MAXLEN too.
 	     For MAXLEN only allow optimizing into non-_ocs function
 	     if SIZE is >= MAXLEN, never convert to __ocs_fail ().  */
-	  if (maxlen == NULL_TREE || ! host_integerp (maxlen, 1))
+	  if (maxlen == NULL_TREE || ! tree_fits_uhwi_p (maxlen))
 	    return NULL_TREE;
 	}
       else
@@ -13024,7 +12944,7 @@  fold_builtin_strcat_chk (location_t loc, tree fndecl, tree dest,
   if (p && *p == '\0')
     return omit_one_operand_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)), dest, src);
 
-  if (! host_integerp (size, 1) || ! integer_all_onesp (size))
+  if (! tree_fits_uhwi_p (size) || ! integer_all_onesp (size))
     return NULL_TREE;
 
   /* If __builtin_strcat_chk is used, assume strcat is available.  */
@@ -13058,15 +12978,15 @@  fold_builtin_strncat_chk (location_t loc, tree fndecl,
   else if (integer_zerop (len))
     return omit_one_operand_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)), dest, src);
 
-  if (! host_integerp (size, 1))
+  if (! tree_fits_uhwi_p (size))
     return NULL_TREE;
 
   if (! integer_all_onesp (size))
     {
       tree src_len = c_strlen (src, 1);
       if (src_len
-	  && host_integerp (src_len, 1)
-	  && host_integerp (len, 1)
+	  && tree_fits_uhwi_p (src_len)
+	  && tree_fits_uhwi_p (len)
 	  && ! tree_int_cst_lt (len, src_len))
 	{
 	  /* If LEN >= strlen (SRC), optimize into __strcat_chk.  */
@@ -13115,7 +13035,7 @@  fold_builtin_sprintf_chk_1 (location_t loc, int nargs, tree *args,
   if (!validate_arg (fmt, POINTER_TYPE))
     return NULL_TREE;
 
-  if (! host_integerp (size, 1))
+  if (! tree_fits_uhwi_p (size))
     return NULL_TREE;
 
   len = NULL_TREE;
@@ -13146,7 +13066,7 @@  fold_builtin_sprintf_chk_1 (location_t loc, int nargs, tree *args,
 	      if (validate_arg (arg, POINTER_TYPE))
 		{
 		  len = c_strlen (arg, 1);
-		  if (! len || ! host_integerp (len, 1))
+		  if (! len || ! tree_fits_uhwi_p (len))
 		    len = NULL_TREE;
 		}
 	    }
@@ -13223,17 +13143,17 @@  fold_builtin_snprintf_chk_1 (location_t loc, int nargs, tree *args,
   if (!validate_arg (fmt, POINTER_TYPE))
     return NULL_TREE;
 
-  if (! host_integerp (size, 1))
+  if (! tree_fits_uhwi_p (size))
     return NULL_TREE;
 
   if (! integer_all_onesp (size))
     {
-      if (! host_integerp (len, 1))
+      if (! tree_fits_uhwi_p (len))
 	{
 	  /* If LEN is not constant, try MAXLEN too.
 	     For MAXLEN only allow optimizing into non-_ocs function
 	     if SIZE is >= MAXLEN, never convert to __ocs_fail ().  */
-	  if (maxlen == NULL_TREE || ! host_integerp (maxlen, 1))
+	  if (maxlen == NULL_TREE || ! tree_fits_uhwi_p (maxlen))
 	    return NULL_TREE;
 	}
       else
@@ -13878,10 +13798,10 @@  do_mpfr_bessel_n (tree arg1, tree arg2, tree type,
   /* To proceed, MPFR must exactly represent the target floating point
      format, which only happens when the target base equals two.  */
   if (REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2
-      && host_integerp (arg1, 0)
+      && tree_fits_shwi_p (arg1)
       && TREE_CODE (arg2) == REAL_CST && !TREE_OVERFLOW (arg2))
     {
-      const HOST_WIDE_INT n = tree_low_cst(arg1, 0);
+      const HOST_WIDE_INT n = tree_to_hwi(arg1);
       const REAL_VALUE_TYPE *const ra = &TREE_REAL_CST (arg2);
 
       if (n == (long)n
diff --git a/gcc/dfp.c b/gcc/dfp.c
index d15ee8f..f0172c1 100644
--- a/gcc/dfp.c
+++ b/gcc/dfp.c
@@ -24,6 +24,7 @@  along with GCC; see the file COPYING3.  If not see
 #include "tree.h"
 #include "tm_p.h"
 #include "dfp.h"
+#include "wide-int.h"
 
 /* The order of the following headers is important for making sure
    decNumber structure is large enough to hold decimal128 digits.  */
@@ -631,6 +632,33 @@  decimal_real_to_integer2 (HOST_WIDE_INT *plow, HOST_WIDE_INT *phigh,
   real_to_integer2 (plow, phigh, &to);
 }
 
+/* Likewise, but returns a wide_int with PRECISION.  Fail
+   is set if the value does not fit.  */
+
+wide_int
+decimal_real_to_integer (const REAL_VALUE_TYPE *r, bool *fail, int precision)
+{
+  decContext set;
+  decNumber dn, dn2, dn3;
+  REAL_VALUE_TYPE to;
+  char string[256];
+
+  decContextDefault (&set, DEC_INIT_DECIMAL128);
+  set.traps = 0;
+  set.round = DEC_ROUND_DOWN;
+  decimal128ToNumber ((const decimal128 *) r->sig, &dn);
+
+  decNumberToIntegralValue (&dn2, &dn, &set);
+  decNumberZero (&dn3);
+  decNumberRescale (&dn, &dn2, &dn3, &set);
+
+  /* Convert to REAL_VALUE_TYPE and call appropriate conversion
+     function.  */
+  decNumberToString (&dn, string);
+  real_from_string (&to, string);
+  return real_to_integer (&to, fail, precision);
+}
+
 /* Perform the decimal floating point operation described by CODE.
    For a unary operation, OP1 will be NULL.  This function returns
    true if the result may be inexact due to loss of precision.  */
diff --git a/gcc/real.c b/gcc/real.c
index b80aeac..7acc3df 100644
--- a/gcc/real.c
+++ b/gcc/real.c
@@ -29,6 +29,7 @@ 
 #include "realmpfr.h"
 #include "tm_p.h"
 #include "dfp.h"
+#include "wide-int.h"
 
 /* The floating point model used internally is not exactly IEEE 754
    compliant, and close to the description in the ISO C99 standard,
@@ -1459,6 +1460,91 @@  real_to_integer2 (HOST_WIDE_INT *plow, HOST_WIDE_INT *phigh,
   *phigh = high;
 }
 
+/* Likewise, but producing a wide-int of PRECISION.  If
+   the value cannot be represented in precision, FAIL is set to
+   TRUE.  */
+
+wide_int
+real_to_integer (const REAL_VALUE_TYPE *r, bool *fail, int precision)
+{
+  HOST_WIDE_INT val[2 * MAX_BITSIZE_MODE_ANY_INT / HOST_BITS_PER_WIDE_INT];
+  int exp;
+  int words;
+  wide_int result;
+  int w;
+
+  switch (r->cl)
+    {
+    case rvc_zero:
+    underflow:
+      return wide_int::zero (precision);
+
+    case rvc_inf:
+    case rvc_nan:
+    overflow:
+      *fail = true;
+      
+      if (r->sign)
+	return wide_int::set_bit_in_zero (precision, precision);
+      else
+	return ~wide_int::set_bit_in_zero (precision, precision);
+
+    case rvc_normal:
+      if (r->decimal)
+	return decimal_real_to_integer (r, fail, precision);
+
+      exp = REAL_EXP (r);
+      if (exp <= 0)
+	goto underflow;
+      /* Only force overflow for unsigned overflow.  Signed overflow is
+	 undefined, so it doesn't matter what we return, and some callers
+	 expect to be able to use this routine for both signed and
+	 unsigned conversions.  */
+      if (exp > precision)
+	goto overflow;
+
+      words = (precision + HOST_BITS_PER_WIDE_INT - 1) / HOST_BITS_PER_WIDE_INT;
+
+      for (int i = 0; i < 2 * MAX_BITSIZE_MODE_ANY_INT / HOST_BITS_PER_WIDE_INT; i++)
+	val[i] = 0;
+
+#if (HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_LONG)
+      for (int i = 0; i < words; i++)
+	{
+	  int j = SIGSZ - words + i;
+	  val[i] = (j < 0) ? 0 : r->sig[j]; 
+	}
+#else
+      gcc_assert (HOST_BITS_PER_WIDE_INT == 2*HOST_BITS_PER_LONG);
+      for (int i = 0; i < words; i++)
+	{
+	  int j = SIGSZ - (words * 2) + (i + 2) + 1;
+	  if (j < 0)
+	    val[i] = 0;
+	  else 
+	    {
+	      val[i] = r->sig[j];
+	      val[i] <<= HOST_BITS_PER_LONG;
+	      val[i] |= r->sig[j - 1];
+	    }
+	}
+#endif 
+      w = SIGSZ * HOST_BITS_PER_LONG + words * HOST_BITS_PER_WIDE_INT; 
+      result = wide_int::from_array (val, 
+	  (w + HOST_BITS_PER_WIDE_INT - 1) / HOST_BITS_PER_WIDE_INT, w, w); 
+      result = result.rshiftu ((words * HOST_BITS_PER_WIDE_INT) - exp);
+      result = result.force_to_size (precision, wide_int::UNSIGNED);
+
+      if (r->sign)
+	return result.neg ();
+      else
+	return result;
+
+    default:
+      gcc_unreachable ();
+    }
+}
+
 /* A subroutine of real_to_decimal.  Compute the quotient and remainder
    of NUM / DEN.  Return the quotient and place the remainder in NUM.
    It is expected that NUM / DEN are close enough that the quotient is
diff --git a/gcc/tree.h b/gcc/tree.h
index be43440..2bd4132 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -735,6 +735,8 @@  enum tree_node_structure_enum {
 };
 #undef DEFTREESTRUCT
 
+#define NULL_TREE (tree) NULL
+
 /* Define accessors for the fields that all tree nodes have
    (though some fields are not used for all kinds of nodes).  */
 
@@ -4101,6 +4103,113 @@  omp_clause_elt_check (const_tree __t, int __i,
 
 #endif
 
+/* Return true if T is an INTEGER_CST whose value must be non-negative
+   and can be represented in a single unsigned HOST_WIDE_INT.  */
+
+static inline bool
+tree_fits_uhwi_p (const_tree cst)
+{
+  if (cst == NULL_TREE)
+    return false;
+
+  if (TREE_CODE (cst) != INTEGER_CST)
+    return false;
+
+#ifdef NEW_REP_FOR_INT_CST
+  return TREE_INT_CST_NUNITS (cst) == 1 
+    || (TREE_INT_CST_NUNITS (cst) == 2 && TREE_INT_CST_ELT[1] == 0);
+
+#else
+  return (TREE_INT_CST_HIGH (cst) == 0);
+#endif
+}
+
+/* Return true if CST is an INTEGER_CST whose value can be represented
+   in a single HOST_WIDE_INT.  */
+
+static inline bool
+tree_fits_shwi_p (const_tree cst)
+{
+  if (cst == NULL_TREE)
+    return false;
+
+  if (TREE_CODE (cst) != INTEGER_CST)
+    return false;
+
+#ifdef NEW_REP_FOR_INT_CST
+  return TREE_INT_CST_NUNITS (cst) == 1;
+#else
+  return ((TREE_INT_CST_HIGH (cst) == 0
+	   && (HOST_WIDE_INT) TREE_INT_CST_LOW (cst) >= 0)
+	  || (TREE_INT_CST_HIGH (cst) == -1
+	      && (HOST_WIDE_INT) TREE_INT_CST_LOW (cst) < 0
+	      && !TYPE_UNSIGNED (TREE_TYPE (cst))));
+#endif
+}
+
+/* Return true if T is an INTEGER_CST that can be manipulated
+   efficiently on the host.  If POS is false, the value can be
+   represented in a single HOST_WIDE_INT.  If POS is true, the value
+   must be non-negative and can be represented in a single unsigned
+   HOST_WIDE_INT.  */
+
+static inline bool
+tree_fits_hwi_p (const_tree cst, bool pos)
+{
+  if (cst == NULL_TREE)
+    return 0;
+
+  if (TREE_CODE (cst) != INTEGER_CST)
+    return false;
+
+  return pos ? tree_fits_uhwi_p (cst) : tree_fits_shwi_p (cst);
+}
+
+/* Return the unsigned HOST_WIDE_INT least significant bits of CST.
+   If checking is enabled, this ices if the value does not fit.  */
+
+static inline unsigned HOST_WIDE_INT
+tree_to_uhwi (const_tree cst)
+{
+  gcc_checking_assert (tree_fits_uhwi_p (cst));
+
+#ifdef NEW_REP_FOR_INT_CST
+  return (unsigned HOST_WIDE_INT)TREE_INT_CST_ELT (cst, 0);
+#else
+  return (unsigned HOST_WIDE_INT)TREE_INT_CST_LOW (cst);
+#endif
+}
+
+/* Return the HOST_WIDE_INT least significant bits of CST.  If
+   checking is enabled, this ices if the value does not fit.  */
+
+static inline HOST_WIDE_INT
+tree_to_shwi (const_tree cst)
+{
+  gcc_checking_assert (tree_fits_shwi_p (cst));
+
+#ifdef NEW_REP_FOR_INT_CST
+  return (HOST_WIDE_INT)TREE_INT_CST_ELT (cst, 0);
+#else
+  return (HOST_WIDE_INT)TREE_INT_CST_LOW (cst);
+#endif
+}
+
+/* Return the HOST_WIDE_INT least significant bits of CST.  No
+   checking is done to assure that it fits.  It is assumed that one of
+   tree_fits_uhwi_p or tree_fits_shwi_p was done before this call. */
+
+static inline HOST_WIDE_INT
+tree_to_hwi (const_tree cst)
+{
+#ifdef NEW_REP_FOR_INT_CST
+  return TREE_INT_CST_ELT (cst, 0);
+#else
+  return TREE_INT_CST_LOW (cst);
+#endif
+}
+
+
 /* Compute the number of operands in an expression node NODE.  For
    tcc_vl_exp nodes like CALL_EXPRs, this is stored in the node itself,
    otherwise it is looked up from the node's code.  */
@@ -4568,8 +4677,6 @@  enum ptrmemfunc_vbit_where_t
   ptrmemfunc_vbit_in_delta
 };
 
-#define NULL_TREE (tree) NULL
-
 /* True if NODE is an erroneous expression.  */
 
 #define error_operand_p(NODE)					\