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 <zad...@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 --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) \