summaryrefslogtreecommitdiff
path: root/gcc/builtins.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/builtins.c')
-rw-r--r--gcc/builtins.c191
1 files changed, 53 insertions, 138 deletions
diff --git a/gcc/builtins.c b/gcc/builtins.c
index 42e4af263ab..a7a80ea7435 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -413,7 +413,7 @@ get_object_alignment_2 (tree exp, unsigned int *alignp,
bitpos += ptr_bitpos;
if (TREE_CODE (exp) == MEM_REF
|| TREE_CODE (exp) == TARGET_MEM_REF)
- bitpos += mem_ref_offset (exp).low * BITS_PER_UNIT;
+ bitpos += mem_ref_offset (exp).to_short_addr () * BITS_PER_UNIT;
}
}
else if (TREE_CODE (exp) == STRING_CST)
@@ -672,20 +672,24 @@ c_getstr (tree src)
return TREE_STRING_POINTER (src) + tree_to_uhwi (offset_node);
}
-/* Return a CONST_INT or CONST_DOUBLE corresponding to target reading
+/* Return a constant integer corresponding to target reading
GET_MODE_BITSIZE (MODE) bits from string constant STR. */
static rtx
c_readstr (const char *str, enum machine_mode mode)
{
- HOST_WIDE_INT c[2];
HOST_WIDE_INT ch;
unsigned int i, j;
+ HOST_WIDE_INT tmp[MAX_BITSIZE_MODE_ANY_INT / HOST_BITS_PER_WIDE_INT];
gcc_assert (GET_MODE_CLASS (mode) == MODE_INT);
+ unsigned int len = (GET_MODE_PRECISION (mode) + HOST_BITS_PER_WIDE_INT - 1)
+ / HOST_BITS_PER_WIDE_INT;
+
+ gcc_assert (len <= MAX_BITSIZE_MODE_ANY_INT / HOST_BITS_PER_WIDE_INT);
+ for (i = 0; i < len; i++)
+ tmp[i] = 0;
- c[0] = 0;
- c[1] = 0;
ch = 1;
for (i = 0; i < GET_MODE_SIZE (mode); i++)
{
@@ -696,13 +700,14 @@ c_readstr (const char *str, enum machine_mode mode)
&& GET_MODE_SIZE (mode) >= UNITS_PER_WORD)
j = j + UNITS_PER_WORD - 2 * (j % UNITS_PER_WORD) - 1;
j *= BITS_PER_UNIT;
- gcc_assert (j < HOST_BITS_PER_DOUBLE_INT);
if (ch)
ch = (unsigned char) str[i];
- c[j / HOST_BITS_PER_WIDE_INT] |= ch << (j % HOST_BITS_PER_WIDE_INT);
+ tmp[j / HOST_BITS_PER_WIDE_INT] |= ch << (j % HOST_BITS_PER_WIDE_INT);
}
- return immed_double_const (c[0], c[1], mode);
+
+ wide_int c = wide_int::from_array (tmp, len, GET_MODE_PRECISION (mode));
+ return immed_wide_int_const (c, mode);
}
/* Cast a target constant CST to target CHAR and if that value fits into
@@ -718,7 +723,9 @@ target_char_cast (tree cst, char *p)
|| CHAR_TYPE_SIZE > HOST_BITS_PER_WIDE_INT)
return 1;
+ /* Do not care if it fits or not right here. */
val = TREE_INT_CST_LOW (cst);
+
if (CHAR_TYPE_SIZE < HOST_BITS_PER_WIDE_INT)
val &= (((unsigned HOST_WIDE_INT) 1) << CHAR_TYPE_SIZE) - 1;
@@ -3128,7 +3135,7 @@ determine_block_size (tree len, rtx len_rtx,
}
else
{
- double_int min, max;
+ wide_int min, max;
enum value_range_type range_type = VR_UNDEFINED;
/* Determine bounds from the type. */
@@ -3146,18 +3153,18 @@ determine_block_size (tree len, rtx len_rtx,
range_type = get_range_info (len, &min, &max);
if (range_type == VR_RANGE)
{
- if (min.fits_uhwi () && *min_size < min.to_uhwi ())
+ if (wi::fits_uhwi_p (min) && *min_size < min.to_uhwi ())
*min_size = min.to_uhwi ();
- if (max.fits_uhwi () && *max_size > max.to_uhwi ())
+ if (wi::fits_uhwi_p (max) && *max_size > max.to_uhwi ())
*probable_max_size = *max_size = max.to_uhwi ();
}
else if (range_type == VR_ANTI_RANGE)
{
/* Anti range 0...N lets us to determine minimal size to N+1. */
- if (min.is_zero ())
+ if (min == 0)
{
- if ((max + double_int_one).fits_uhwi ())
- *min_size = (max + double_int_one).to_uhwi ();
+ if (wi::fits_uhwi_p (max) && max.to_uhwi () + 1 != 0)
+ *min_size = max.to_uhwi () + 1;
}
/* Code like
@@ -3168,9 +3175,8 @@ determine_block_size (tree len, rtx len_rtx,
Produce anti range allowing negative values of N. We still
can use the information and make a guess that N is not negative.
*/
- else if (!max.ule (double_int_one.lshift (30))
- && min.fits_uhwi ())
- *probable_max_size = min.to_uhwi () - 1;
+ else if (!wi::leu_p (max, 1 << 30) && wi::fits_uhwi_p (min))
+ *probable_max_size = min.to_uhwi () - 1;
}
}
gcc_checking_assert (*max_size <=
@@ -4943,12 +4949,12 @@ expand_builtin_signbit (tree exp, rtx target)
if (bitpos < GET_MODE_BITSIZE (rmode))
{
- double_int mask = double_int_zero.set_bit (bitpos);
+ wide_int mask = wi::set_bit_in_zero (bitpos, GET_MODE_PRECISION (rmode));
if (GET_MODE_SIZE (imode) > GET_MODE_SIZE (rmode))
temp = gen_lowpart (rmode, temp);
temp = expand_binop (rmode, and_optab, temp,
- immed_double_int_const (mask, rmode),
+ immed_wide_int_const (mask, rmode),
NULL_RTX, 1, OPTAB_LIB_WIDEN);
}
else
@@ -8012,8 +8018,8 @@ 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;
REAL_VALUE_TYPE r;
+ bool fail = false;
switch (DECL_FUNCTION_CODE (fndecl))
{
@@ -8039,9 +8045,9 @@ 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);
+ wide_int val = real_to_integer (&r, &fail, TYPE_PRECISION (itype));
+ if (!fail)
+ return wide_int_to_tree (itype, val);
}
}
@@ -8074,94 +8080,32 @@ 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 &= ~(HOST_WIDE_INT_M1U << (width - HOST_BITS_PER_WIDE_INT));
- }
- else
- {
- hi = 0;
- if (width < HOST_BITS_PER_WIDE_INT)
- lo &= ~(HOST_WIDE_INT_M1U << width);
- }
+ 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 = wi::ffs (arg);
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 = wi::clz (arg);
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 = wi::ctz (arg);
break;
CASE_INT_FN (BUILT_IN_CLRSB):
- if (width > 2 * HOST_BITS_PER_WIDE_INT)
- return NULL_TREE;
- if (width > HOST_BITS_PER_WIDE_INT
- && (hi & ((unsigned HOST_WIDE_INT) 1
- << (width - HOST_BITS_PER_WIDE_INT - 1))) != 0)
- {
- hi = ~hi & ~(HOST_WIDE_INT_M1U
- << (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 & ~(HOST_WIDE_INT_M1U << (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 = wi::clrsb (arg);
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 = wi::popcount (arg);
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 = wi::parity (arg);
break;
default:
@@ -8185,49 +8129,24 @@ 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);
- }
+ signop sgn = TYPE_SIGN (type);
+ tree result =
+ wide_int_to_tree (type,
+ wide_int::from (arg, TYPE_PRECISION (type),
+ sgn).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;
@@ -8289,7 +8208,7 @@ fold_builtin_logarithm (location_t loc, tree fndecl, tree arg,
/* Prepare to do logN(exp10(exponent) -> exponent*logN(10). */
{
REAL_VALUE_TYPE dconst10;
- real_from_integer (&dconst10, VOIDmode, 10, 0, 0);
+ real_from_integer (&dconst10, VOIDmode, 10, SIGNED);
x = build_real (type, dconst10);
}
exponent = CALL_EXPR_ARG (arg, 0);
@@ -8442,7 +8361,7 @@ fold_builtin_pow (location_t loc, tree fndecl, tree arg0, tree arg1, tree type)
/* Check for an integer exponent. */
n = real_to_integer (&c);
- real_from_integer (&cint, VOIDmode, n, n < 0 ? -1 : 0, 0);
+ real_from_integer (&cint, VOIDmode, n, SIGNED);
if (real_identical (&c, &cint))
{
/* Attempt to evaluate pow at compile-time, unless this should
@@ -8814,20 +8733,18 @@ 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;
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 ())
+ offset_int off = mem_ref_offset (src_base) + src_offset;
+ if (!wi::fits_shwi_p (off))
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 = mem_ref_offset (dest_base) + dest_offset;
+ if (!wi::fits_shwi_p (off))
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;
@@ -12690,8 +12607,7 @@ 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)))
+ if (wi::fits_to_tree_p (bytes, size_type_node))
return build_int_cstu (size_type_node, bytes);
}
else if (TREE_CODE (ptr) == SSA_NAME)
@@ -12701,8 +12617,7 @@ fold_builtin_object_size (tree ptr, tree ost)
it. */
bytes = compute_builtin_object_size (ptr, object_size_type);
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)))
+ && wi::fits_to_tree_p (bytes, size_type_node))
return build_int_cstu (size_type_node, bytes);
}