summaryrefslogtreecommitdiff
path: root/gcc/expr.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/expr.c')
-rw-r--r--gcc/expr.c319
1 files changed, 152 insertions, 167 deletions
diff --git a/gcc/expr.c b/gcc/expr.c
index 8ef28709a4e..cb3abcdab89 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -715,64 +715,33 @@ convert_modes (enum machine_mode mode, enum machine_mode oldmode, rtx x, int uns
if (mode == oldmode)
return x;
- /* There is one case that we must handle specially: If we are converting
- a CONST_INT into a mode whose size is twice HOST_BITS_PER_WIDE_INT and
- we are to interpret the constant as unsigned, gen_lowpart will do
- the wrong if the constant appears negative. What we want to do is
- make the high-order word of the constant zero, not all ones. */
-
- if (unsignedp && GET_MODE_CLASS (mode) == MODE_INT
- && GET_MODE_BITSIZE (mode) == HOST_BITS_PER_DOUBLE_INT
- && CONST_INT_P (x) && INTVAL (x) < 0)
+ if (CONST_SCALAR_INT_P (x)
+ && GET_MODE_CLASS (mode) == MODE_INT)
{
- double_int val = double_int::from_uhwi (INTVAL (x));
-
- /* We need to zero extend VAL. */
- if (oldmode != VOIDmode)
- val = val.zext (GET_MODE_BITSIZE (oldmode));
-
- return immed_double_int_const (val, mode);
+ /* If the caller did not tell us the old mode, then there is
+ not much to do with respect to canonization. We have to assume
+ that all the bits are significant. */
+ if (GET_MODE_CLASS (oldmode) != MODE_INT)
+ oldmode = MAX_MODE_INT;
+ wide_int w = wide_int::from (std::make_pair (x, oldmode),
+ GET_MODE_PRECISION (mode),
+ unsignedp ? UNSIGNED : SIGNED);
+ return immed_wide_int_const (w, mode);
}
/* We can do this with a gen_lowpart if both desired and current modes
are integer, and this is either a constant integer, a register, or a
- non-volatile MEM. Except for the constant case where MODE is no
- wider than HOST_BITS_PER_WIDE_INT, we must be narrowing the operand. */
-
- if ((CONST_INT_P (x)
- && GET_MODE_PRECISION (mode) <= HOST_BITS_PER_WIDE_INT)
- || (GET_MODE_CLASS (mode) == MODE_INT
- && GET_MODE_CLASS (oldmode) == MODE_INT
- && (CONST_DOUBLE_AS_INT_P (x)
- || (GET_MODE_PRECISION (mode) <= GET_MODE_PRECISION (oldmode)
- && ((MEM_P (x) && ! MEM_VOLATILE_P (x)
- && direct_load[(int) mode])
- || (REG_P (x)
- && (! HARD_REGISTER_P (x)
- || HARD_REGNO_MODE_OK (REGNO (x), mode))
- && TRULY_NOOP_TRUNCATION_MODES_P (mode,
- GET_MODE (x))))))))
- {
- /* ?? If we don't know OLDMODE, we have to assume here that
- X does not need sign- or zero-extension. This may not be
- the case, but it's the best we can do. */
- if (CONST_INT_P (x) && oldmode != VOIDmode
- && GET_MODE_PRECISION (mode) > GET_MODE_PRECISION (oldmode))
- {
- HOST_WIDE_INT val = INTVAL (x);
-
- /* We must sign or zero-extend in this case. Start by
- zero-extending, then sign extend if we need to. */
- val &= GET_MODE_MASK (oldmode);
- if (! unsignedp
- && val_signbit_known_set_p (oldmode, val))
- val |= ~GET_MODE_MASK (oldmode);
-
- return gen_int_mode (val, mode);
- }
-
- return gen_lowpart (mode, x);
- }
+ non-volatile MEM. */
+ if (GET_MODE_CLASS (mode) == MODE_INT
+ && GET_MODE_CLASS (oldmode) == MODE_INT
+ && GET_MODE_PRECISION (mode) <= GET_MODE_PRECISION (oldmode)
+ && ((MEM_P (x) && !MEM_VOLATILE_P (x) && direct_load[(int) mode])
+ || (REG_P (x)
+ && (!HARD_REGISTER_P (x)
+ || HARD_REGNO_MODE_OK (REGNO (x), mode))
+ && TRULY_NOOP_TRUNCATION_MODES_P (mode, GET_MODE (x)))))
+
+ return gen_lowpart (mode, x);
/* Converting from integer constant into mode is always equivalent to an
subreg operation. */
@@ -1755,6 +1724,7 @@ emit_group_load_1 (rtx *tmps, rtx dst, rtx orig_src, tree type, int ssize)
{
rtx first, second;
+ /* TODO: const_wide_int can have sizes other than this... */
gcc_assert (2 * len == ssize);
split_double (src, &first, &second);
if (i)
@@ -4566,14 +4536,14 @@ get_bit_range (unsigned HOST_WIDE_INT *bitstart,
relative to the representative. DECL_FIELD_OFFSET of field and
repr are the same by construction if they are not constants,
see finish_bitfield_layout. */
- if (host_integerp (DECL_FIELD_OFFSET (field), 1)
- && host_integerp (DECL_FIELD_OFFSET (repr), 1))
- bitoffset = (tree_low_cst (DECL_FIELD_OFFSET (field), 1)
- - tree_low_cst (DECL_FIELD_OFFSET (repr), 1)) * BITS_PER_UNIT;
+ if (tree_fits_uhwi_p (DECL_FIELD_OFFSET (field))
+ && tree_fits_uhwi_p (DECL_FIELD_OFFSET (repr)))
+ bitoffset = (tree_to_uhwi (DECL_FIELD_OFFSET (field))
+ - tree_to_uhwi (DECL_FIELD_OFFSET (repr))) * BITS_PER_UNIT;
else
bitoffset = 0;
- bitoffset += (tree_low_cst (DECL_FIELD_BIT_OFFSET (field), 1)
- - tree_low_cst (DECL_FIELD_BIT_OFFSET (repr), 1));
+ bitoffset += (tree_to_uhwi (DECL_FIELD_BIT_OFFSET (field))
+ - tree_to_uhwi (DECL_FIELD_BIT_OFFSET (repr)));
/* If the adjustment is larger than bitpos, we would have a negative bit
position for the lower bound and this may wreak havoc later. This can
@@ -4594,7 +4564,7 @@ get_bit_range (unsigned HOST_WIDE_INT *bitstart,
else
*bitstart = *bitpos - bitoffset;
- *bitend = *bitstart + tree_low_cst (DECL_SIZE (repr), 1) - 1;
+ *bitend = *bitstart + tree_to_uhwi (DECL_SIZE (repr)) - 1;
}
/* Returns true if ADDR is an ADDR_EXPR of a DECL that does not reside
@@ -5214,10 +5184,10 @@ store_expr (tree exp, rtx target, int call_param_p, bool nontemporal)
&alt_rtl);
}
- /* If TEMP is a VOIDmode constant and the mode of the type of EXP is not
- the same as that of TARGET, adjust the constant. This is needed, for
- example, in case it is a CONST_DOUBLE and we want only a word-sized
- value. */
+ /* If TEMP is a VOIDmode constant and the mode of the type of EXP is
+ not the same as that of TARGET, adjust the constant. This is
+ needed, for example, in case it is a CONST_DOUBLE or
+ CONST_WIDE_INT and we want only a word-sized value. */
if (CONSTANT_P (temp) && GET_MODE (temp) == VOIDmode
&& TREE_CODE (exp) != ERROR_MARK
&& GET_MODE (target) != TYPE_MODE (TREE_TYPE (exp)))
@@ -5410,11 +5380,11 @@ count_type_elements (const_tree type, bool for_ctor_p)
tree nelts;
nelts = array_type_nelts (type);
- if (nelts && host_integerp (nelts, 1))
+ if (nelts && tree_fits_uhwi_p (nelts))
{
unsigned HOST_WIDE_INT n;
- n = tree_low_cst (nelts, 1) + 1;
+ n = tree_to_uhwi (nelts) + 1;
if (n == 0 || for_ctor_p)
return n;
else
@@ -5529,9 +5499,9 @@ categorize_ctor_elements_1 (const_tree ctor, HOST_WIDE_INT *p_nz_elts,
tree lo_index = TREE_OPERAND (purpose, 0);
tree hi_index = TREE_OPERAND (purpose, 1);
- if (host_integerp (lo_index, 1) && host_integerp (hi_index, 1))
- mult = (tree_low_cst (hi_index, 1)
- - tree_low_cst (lo_index, 1) + 1);
+ if (tree_fits_uhwi_p (lo_index) && tree_fits_uhwi_p (hi_index))
+ mult = (tree_to_uhwi (hi_index)
+ - tree_to_uhwi (lo_index) + 1);
}
num_fields += mult;
elt_type = TREE_TYPE (value);
@@ -5831,8 +5801,8 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size)
if (cleared && initializer_zerop (value))
continue;
- if (host_integerp (DECL_SIZE (field), 1))
- bitsize = tree_low_cst (DECL_SIZE (field), 1);
+ if (tree_fits_uhwi_p (DECL_SIZE (field)))
+ bitsize = tree_to_uhwi (DECL_SIZE (field));
else
bitsize = -1;
@@ -5841,14 +5811,14 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size)
mode = VOIDmode;
offset = DECL_FIELD_OFFSET (field);
- if (host_integerp (offset, 0)
- && host_integerp (bit_position (field), 0))
+ if (tree_fits_shwi_p (offset)
+ && tree_fits_shwi_p (bit_position (field)))
{
bitpos = int_bit_position (field);
offset = 0;
}
else
- bitpos = tree_low_cst (DECL_FIELD_BIT_OFFSET (field), 0);
+ bitpos = tree_to_shwi (DECL_FIELD_BIT_OFFSET (field));
if (offset)
{
@@ -5931,14 +5901,14 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size)
domain = TYPE_DOMAIN (type);
const_bounds_p = (TYPE_MIN_VALUE (domain)
&& TYPE_MAX_VALUE (domain)
- && host_integerp (TYPE_MIN_VALUE (domain), 0)
- && host_integerp (TYPE_MAX_VALUE (domain), 0));
+ && tree_fits_shwi_p (TYPE_MIN_VALUE (domain))
+ && tree_fits_shwi_p (TYPE_MAX_VALUE (domain)));
/* If we have constant bounds for the range of the type, get them. */
if (const_bounds_p)
{
- minelt = tree_low_cst (TYPE_MIN_VALUE (domain), 0);
- maxelt = tree_low_cst (TYPE_MAX_VALUE (domain), 0);
+ minelt = tree_to_shwi (TYPE_MIN_VALUE (domain));
+ maxelt = tree_to_shwi (TYPE_MAX_VALUE (domain));
}
/* If the constructor has fewer elements than the array, clear
@@ -5970,15 +5940,15 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size)
tree lo_index = TREE_OPERAND (index, 0);
tree hi_index = TREE_OPERAND (index, 1);
- if (! host_integerp (lo_index, 1)
- || ! host_integerp (hi_index, 1))
+ if (! tree_fits_uhwi_p (lo_index)
+ || ! tree_fits_uhwi_p (hi_index))
{
need_to_clear = 1;
break;
}
- this_node_count = (tree_low_cst (hi_index, 1)
- - tree_low_cst (lo_index, 1) + 1);
+ this_node_count = (tree_to_uhwi (hi_index)
+ - tree_to_uhwi (lo_index) + 1);
}
else
this_node_count = 1;
@@ -6025,8 +5995,8 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size)
mode = TYPE_MODE (elttype);
if (mode == BLKmode)
- bitsize = (host_integerp (TYPE_SIZE (elttype), 1)
- ? tree_low_cst (TYPE_SIZE (elttype), 1)
+ bitsize = (tree_fits_uhwi_p (TYPE_SIZE (elttype))
+ ? tree_to_uhwi (TYPE_SIZE (elttype))
: -1);
else
bitsize = GET_MODE_BITSIZE (mode);
@@ -6041,21 +6011,21 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size)
/* If the range is constant and "small", unroll the loop. */
if (const_bounds_p
- && host_integerp (lo_index, 0)
- && host_integerp (hi_index, 0)
- && (lo = tree_low_cst (lo_index, 0),
- hi = tree_low_cst (hi_index, 0),
+ && tree_fits_shwi_p (lo_index)
+ && tree_fits_shwi_p (hi_index)
+ && (lo = tree_to_shwi (lo_index),
+ hi = tree_to_shwi (hi_index),
count = hi - lo + 1,
(!MEM_P (target)
|| count <= 2
- || (host_integerp (TYPE_SIZE (elttype), 1)
- && (tree_low_cst (TYPE_SIZE (elttype), 1) * count
+ || (tree_fits_uhwi_p (TYPE_SIZE (elttype))
+ && (tree_to_uhwi (TYPE_SIZE (elttype)) * count
<= 40 * 8)))))
{
lo -= minelt; hi -= minelt;
for (; lo <= hi; lo++)
{
- bitpos = lo * tree_low_cst (TYPE_SIZE (elttype), 0);
+ bitpos = lo * tree_to_shwi (TYPE_SIZE (elttype));
if (MEM_P (target)
&& !MEM_KEEP_ALIAS_SET_P (target)
@@ -6130,8 +6100,8 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size)
emit_label (loop_end);
}
}
- else if ((index != 0 && ! host_integerp (index, 0))
- || ! host_integerp (TYPE_SIZE (elttype), 1))
+ else if ((index != 0 && ! tree_fits_shwi_p (index))
+ || ! tree_fits_uhwi_p (TYPE_SIZE (elttype)))
{
tree position;
@@ -6158,10 +6128,10 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size)
else
{
if (index != 0)
- bitpos = ((tree_low_cst (index, 0) - minelt)
- * tree_low_cst (TYPE_SIZE (elttype), 1));
+ bitpos = ((tree_to_shwi (index) - minelt)
+ * tree_to_uhwi (TYPE_SIZE (elttype)));
else
- bitpos = (i * tree_low_cst (TYPE_SIZE (elttype), 1));
+ bitpos = (i * tree_to_uhwi (TYPE_SIZE (elttype)));
if (MEM_P (target) && !MEM_KEEP_ALIAS_SET_P (target)
&& TREE_CODE (type) == ARRAY_TYPE
@@ -6185,7 +6155,7 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size)
int need_to_clear;
int icode = CODE_FOR_nothing;
tree elttype = TREE_TYPE (type);
- int elt_size = tree_low_cst (TYPE_SIZE (elttype), 1);
+ int elt_size = tree_to_uhwi (TYPE_SIZE (elttype));
enum machine_mode eltmode = TYPE_MODE (elttype);
HOST_WIDE_INT bitsize;
HOST_WIDE_INT bitpos;
@@ -6225,10 +6195,10 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size)
FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (exp), idx, value)
{
- int n_elts_here = tree_low_cst
+ int n_elts_here = tree_to_uhwi
(int_const_binop (TRUNC_DIV_EXPR,
TYPE_SIZE (TREE_TYPE (value)),
- TYPE_SIZE (elttype)), 1);
+ TYPE_SIZE (elttype)));
count += n_elts_here;
if (mostly_zeros_p (value))
@@ -6267,12 +6237,12 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size)
HOST_WIDE_INT eltpos;
tree value = ce->value;
- bitsize = tree_low_cst (TYPE_SIZE (TREE_TYPE (value)), 1);
+ bitsize = tree_to_uhwi (TYPE_SIZE (TREE_TYPE (value)));
if (cleared && initializer_zerop (value))
continue;
if (ce->index)
- eltpos = tree_low_cst (ce->index, 1);
+ eltpos = tree_to_uhwi (ce->index);
else
eltpos = i;
@@ -6549,7 +6519,7 @@ get_inner_reference (tree exp, HOST_WIDE_INT *pbitsize,
enum machine_mode mode = VOIDmode;
bool blkmode_bitfield = false;
tree offset = size_zero_node;
- double_int bit_offset = double_int_zero;
+ offset_int bit_offset = 0;
/* First get the mode, signedness, and size. We do this from just the
outermost expression. */
@@ -6599,10 +6569,10 @@ get_inner_reference (tree exp, HOST_WIDE_INT *pbitsize,
if (size_tree != 0)
{
- if (! host_integerp (size_tree, 1))
+ if (! tree_fits_uhwi_p (size_tree))
mode = BLKmode, *pbitsize = -1;
else
- *pbitsize = tree_low_cst (size_tree, 1);
+ *pbitsize = tree_to_uhwi (size_tree);
}
/* Compute cumulative bit-offset for nested component-refs and array-refs,
@@ -6612,7 +6582,7 @@ get_inner_reference (tree exp, HOST_WIDE_INT *pbitsize,
switch (TREE_CODE (exp))
{
case BIT_FIELD_REF:
- bit_offset += tree_to_double_int (TREE_OPERAND (exp, 2));
+ bit_offset += wi::to_offset (TREE_OPERAND (exp, 2));
break;
case COMPONENT_REF:
@@ -6627,7 +6597,7 @@ get_inner_reference (tree exp, HOST_WIDE_INT *pbitsize,
break;
offset = size_binop (PLUS_EXPR, offset, this_offset);
- bit_offset += tree_to_double_int (DECL_FIELD_BIT_OFFSET (field));
+ bit_offset += wi::to_offset (DECL_FIELD_BIT_OFFSET (field));
/* ??? Right now we don't do anything with DECL_OFFSET_ALIGN. */
}
@@ -6659,7 +6629,7 @@ get_inner_reference (tree exp, HOST_WIDE_INT *pbitsize,
break;
case IMAGPART_EXPR:
- bit_offset += double_int::from_uhwi (*pbitsize);
+ bit_offset += *pbitsize;
break;
case VIEW_CONVERT_EXPR:
@@ -6680,9 +6650,9 @@ get_inner_reference (tree exp, HOST_WIDE_INT *pbitsize,
tree off = TREE_OPERAND (exp, 1);
if (!integer_zerop (off))
{
- double_int boff, coff = mem_ref_offset (exp);
- boff = coff.lshift (BITS_PER_UNIT == 8
- ? 3 : exact_log2 (BITS_PER_UNIT));
+ offset_int boff, coff = mem_ref_offset (exp);
+ boff = wi::lshift (coff, (BITS_PER_UNIT == 8
+ ? 3 : exact_log2 (BITS_PER_UNIT)));
bit_offset += boff;
}
exp = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
@@ -6706,11 +6676,12 @@ get_inner_reference (tree exp, HOST_WIDE_INT *pbitsize,
this conversion. */
if (TREE_CODE (offset) == INTEGER_CST)
{
- double_int tem = tree_to_double_int (offset);
- tem = tem.sext (TYPE_PRECISION (sizetype));
- tem = tem.lshift (BITS_PER_UNIT == 8 ? 3 : exact_log2 (BITS_PER_UNIT));
+ offset_int tem = wi::sext (wi::to_offset (offset),
+ TYPE_PRECISION (sizetype));
+ tem = wi::lshift (tem, (BITS_PER_UNIT == 8
+ ? 3 : exact_log2 (BITS_PER_UNIT)));
tem += bit_offset;
- if (tem.fits_shwi ())
+ if (wi::fits_shwi_p (tem))
{
*pbitpos = tem.to_shwi ();
*poffset = offset = NULL_TREE;
@@ -6721,20 +6692,20 @@ get_inner_reference (tree exp, HOST_WIDE_INT *pbitsize,
if (offset)
{
/* Avoid returning a negative bitpos as this may wreak havoc later. */
- if (bit_offset.is_negative ())
+ if (wi::neg_p (bit_offset))
{
- double_int mask
- = double_int::mask (BITS_PER_UNIT == 8
- ? 3 : exact_log2 (BITS_PER_UNIT));
- double_int tem = bit_offset.and_not (mask);
+ offset_int mask
+ = wi::mask <offset_int> (BITS_PER_UNIT == 8
+ ? 3 : exact_log2 (BITS_PER_UNIT),
+ false);
+ offset_int tem = bit_offset.and_not (mask);
/* TEM is the bitpos rounded to BITS_PER_UNIT towards -Inf.
Subtract it to BIT_OFFSET and add it (scaled) to OFFSET. */
bit_offset -= tem;
- tem = tem.arshift (BITS_PER_UNIT == 8
- ? 3 : exact_log2 (BITS_PER_UNIT),
- HOST_BITS_PER_DOUBLE_INT);
+ tem = wi::arshift (tem, (BITS_PER_UNIT == 8
+ ? 3 : exact_log2 (BITS_PER_UNIT)));
offset = size_binop (PLUS_EXPR, offset,
- double_int_to_tree (sizetype, tem));
+ wide_int_to_tree (sizetype, tem));
}
*pbitpos = bit_offset.to_shwi ();
@@ -7665,11 +7636,12 @@ expand_constructor (tree exp, rtx target, enum expand_modifier modifier,
/* All elts simple constants => refer to a constant in memory. But
if this is a non-BLKmode mode, let it store a field at a time
- since that should make a CONST_INT or CONST_DOUBLE when we
- fold. Likewise, if we have a target we can use, it is best to
- store directly into the target unless the type is large enough
- that memcpy will be used. If we are making an initializer and
- all operands are constant, put it in memory as well.
+ since that should make a CONST_INT, CONST_WIDE_INT or
+ CONST_DOUBLE when we fold. Likewise, if we have a target we can
+ use, it is best to store directly into the target unless the type
+ is large enough that memcpy will be used. If we are making an
+ initializer and all operands are constant, put it in memory as
+ well.
FIXME: Avoid trying to fill vector constructors piece-meal.
Output them with output_constant_def below unless we're sure
@@ -7679,9 +7651,9 @@ expand_constructor (tree exp, rtx target, enum expand_modifier modifier,
&& ((mode == BLKmode
&& ! (target != 0 && safe_from_p (target, exp, 1)))
|| TREE_ADDRESSABLE (exp)
- || (host_integerp (TYPE_SIZE_UNIT (type), 1)
+ || (tree_fits_uhwi_p (TYPE_SIZE_UNIT (type))
&& (! MOVE_BY_PIECES_P
- (tree_low_cst (TYPE_SIZE_UNIT (type), 1),
+ (tree_to_uhwi (TYPE_SIZE_UNIT (type)),
TYPE_ALIGN (type)))
&& ! mostly_zeros_p (exp))))
|| ((modifier == EXPAND_INITIALIZER || modifier == EXPAND_CONST_ADDRESS)
@@ -8139,17 +8111,18 @@ expand_expr_real_2 (sepops ops, rtx target, enum machine_mode tmode,
&& TREE_CONSTANT (treeop1))
{
rtx constant_part;
+ HOST_WIDE_INT wc;
+ enum machine_mode wmode = TYPE_MODE (TREE_TYPE (treeop1));
op1 = expand_expr (treeop1, subtarget, VOIDmode,
EXPAND_SUM);
- /* Use immed_double_const to ensure that the constant is
+ /* Use wi::shwi to ensure that the constant is
truncated according to the mode of OP1, then sign extended
to a HOST_WIDE_INT. Using the constant directly can result
in non-canonical RTL in a 64x32 cross compile. */
- constant_part
- = immed_double_const (TREE_INT_CST_LOW (treeop0),
- (HOST_WIDE_INT) 0,
- TYPE_MODE (TREE_TYPE (treeop1)));
+ wc = tree_to_hwi (treeop0);
+ constant_part =
+ immed_wide_int_const (wi::shwi (wc, wmode), wmode);
op1 = plus_constant (mode, op1, INTVAL (constant_part));
if (modifier != EXPAND_SUM && modifier != EXPAND_INITIALIZER)
op1 = force_operand (op1, target);
@@ -8161,6 +8134,8 @@ expand_expr_real_2 (sepops ops, rtx target, enum machine_mode tmode,
&& TREE_CONSTANT (treeop0))
{
rtx constant_part;
+ HOST_WIDE_INT wc;
+ enum machine_mode wmode = TYPE_MODE (TREE_TYPE (treeop0));
op0 = expand_expr (treeop0, subtarget, VOIDmode,
(modifier == EXPAND_INITIALIZER
@@ -8175,14 +8150,13 @@ expand_expr_real_2 (sepops ops, rtx target, enum machine_mode tmode,
return simplify_gen_binary (PLUS, mode, op0, op1);
goto binop2;
}
- /* Use immed_double_const to ensure that the constant is
+ /* Use wi::shwi to ensure that the constant is
truncated according to the mode of OP1, then sign extended
to a HOST_WIDE_INT. Using the constant directly can result
in non-canonical RTL in a 64x32 cross compile. */
+ wc = tree_to_hwi (treeop1);
constant_part
- = immed_double_const (TREE_INT_CST_LOW (treeop1),
- (HOST_WIDE_INT) 0,
- TYPE_MODE (TREE_TYPE (treeop0)));
+ = immed_wide_int_const (wi::shwi (wc, wmode), wmode);
op0 = plus_constant (mode, op0, INTVAL (constant_part));
if (modifier != EXPAND_SUM && modifier != EXPAND_INITIALIZER)
op0 = force_operand (op0, target);
@@ -8461,7 +8435,7 @@ expand_expr_real_2 (sepops ops, rtx target, enum machine_mode tmode,
indexed address, for machines that support that. */
if (modifier == EXPAND_SUM && mode == ptr_mode
- && host_integerp (treeop1, 0))
+ && tree_fits_shwi_p (treeop1))
{
tree exp1 = treeop1;
@@ -8474,8 +8448,7 @@ expand_expr_real_2 (sepops ops, rtx target, enum machine_mode tmode,
op0 = copy_to_mode_reg (mode, op0);
return REDUCE_BIT_FIELD (gen_rtx_MULT (mode, op0,
- gen_int_mode (tree_low_cst (exp1, 0),
- TYPE_MODE (TREE_TYPE (exp1)))));
+ gen_int_mode (tree_to_shwi (exp1), TYPE_MODE (TREE_TYPE (exp1)))));
}
if (modifier == EXPAND_STACK_PARM)
@@ -8711,10 +8684,14 @@ expand_expr_real_2 (sepops ops, rtx target, enum machine_mode tmode,
for unsigned bitfield expand this as XOR with a proper constant
instead. */
if (reduce_bit_field && TYPE_UNSIGNED (type))
- temp = expand_binop (mode, xor_optab, op0,
- immed_double_int_const
- (double_int::mask (TYPE_PRECISION (type)), mode),
- target, 1, OPTAB_LIB_WIDEN);
+ {
+ wide_int mask = wi::mask (TYPE_PRECISION (type),
+ false, GET_MODE_PRECISION (mode));
+
+ temp = expand_binop (mode, xor_optab, op0,
+ immed_wide_int_const (mask, mode),
+ target, 1, OPTAB_LIB_WIDEN);
+ }
else
temp = expand_unop (mode, one_cmpl_optab, op0, target, 1);
gcc_assert (temp);
@@ -9365,11 +9342,19 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
return decl_rtl;
case INTEGER_CST:
- temp = immed_double_const (TREE_INT_CST_LOW (exp),
- TREE_INT_CST_HIGH (exp), mode);
-
- return temp;
-
+ {
+ tree type = TREE_TYPE (exp);
+ /* One could argue that GET_MODE_PRECISION (TYPE_MODE (type))
+ should always be the same as TYPE_PRECISION (type).
+ However, it is not. Since we are converting from tree to
+ rtl, we have to expose this ugly truth here. */
+ temp = immed_wide_int_const (wide_int::from
+ (exp,
+ GET_MODE_PRECISION (TYPE_MODE (type)),
+ TYPE_SIGN (type)),
+ TYPE_MODE (type));
+ return temp;
+ }
case VECTOR_CST:
{
tree tmp = NULL_TREE;
@@ -9553,12 +9538,12 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
might end up in a register. */
if (mem_ref_refers_to_non_mem_p (exp))
{
- HOST_WIDE_INT offset = mem_ref_offset (exp).low;
+ HOST_WIDE_INT offset = mem_ref_offset (exp).to_short_addr ();
base = TREE_OPERAND (base, 0);
if (offset == 0
- && host_integerp (TYPE_SIZE (type), 1)
+ && tree_fits_uhwi_p (TYPE_SIZE (type))
&& (GET_MODE_BITSIZE (DECL_MODE (base))
- == TREE_INT_CST_LOW (TYPE_SIZE (type))))
+ == tree_to_uhwi (TYPE_SIZE (type))))
return expand_expr (build1 (VIEW_CONVERT_EXPR, type, base),
target, tmode, modifier);
if (TYPE_MODE (type) == BLKmode)
@@ -9588,8 +9573,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
op0 = memory_address_addr_space (mode, op0, as);
if (!integer_zerop (TREE_OPERAND (exp, 1)))
{
- rtx off
- = immed_double_int_const (mem_ref_offset (exp), address_mode);
+ rtx off = immed_wide_int_const (mem_ref_offset (exp), address_mode);
op0 = simplify_gen_binary (PLUS, address_mode, op0, off);
op0 = memory_address_addr_space (mode, op0, as);
}
@@ -9737,11 +9721,11 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
{
tree type = TREE_TYPE (TREE_TYPE (init));
enum machine_mode mode = TYPE_MODE (type);
-
+
if (GET_MODE_CLASS (mode) == MODE_INT
&& GET_MODE_SIZE (mode) == 1)
return gen_int_mode (TREE_STRING_POINTER (init)
- [TREE_INT_CST_LOW (index1)],
+ [tree_to_hwi (index1)],
mode);
}
}
@@ -9778,7 +9762,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
op0 = expand_expr (value, target, tmode, modifier);
if (DECL_BIT_FIELD (field))
{
- HOST_WIDE_INT bitsize = TREE_INT_CST_LOW (DECL_SIZE (field));
+ HOST_WIDE_INT bitsize = tree_to_hwi (DECL_SIZE (field));
enum machine_mode imode = TYPE_MODE (TREE_TYPE (field));
if (TYPE_UNSIGNED (TREE_TYPE (field)))
@@ -10453,9 +10437,10 @@ reduce_to_bit_field_precision (rtx exp, rtx target, tree type)
}
else if (TYPE_UNSIGNED (type))
{
- rtx mask = immed_double_int_const (double_int::mask (prec),
- GET_MODE (exp));
- return expand_and (GET_MODE (exp), exp, mask, target);
+ enum machine_mode mode = GET_MODE (exp);
+ rtx mask = immed_wide_int_const
+ (wi::mask (prec, false, GET_MODE_PRECISION (mode)), mode);
+ return expand_and (mode, exp, mask, target);
}
else
{
@@ -10481,10 +10466,10 @@ is_aligning_offset (const_tree offset, const_tree exp)
/* We must now have a BIT_AND_EXPR with a constant that is one less than
power of 2 and which is larger than BIGGEST_ALIGNMENT. */
if (TREE_CODE (offset) != BIT_AND_EXPR
- || !host_integerp (TREE_OPERAND (offset, 1), 1)
+ || !tree_fits_uhwi_p (TREE_OPERAND (offset, 1))
|| compare_tree_int (TREE_OPERAND (offset, 1),
BIGGEST_ALIGNMENT / BITS_PER_UNIT) <= 0
- || !exact_log2 (tree_low_cst (TREE_OPERAND (offset, 1), 1) + 1) < 0)
+ || !exact_log2 (tree_to_uhwi (TREE_OPERAND (offset, 1)) + 1) < 0)
return 0;
/* Look at the first operand of BIT_AND_EXPR and strip any conversion.
@@ -10619,7 +10604,7 @@ string_constant (tree arg, tree *ptr_offset)
and inside of the bounds of the string literal. */
offset = fold_convert (sizetype, offset);
if (compare_tree_int (DECL_SIZE_UNIT (array), length) > 0
- && (! host_integerp (offset, 1)
+ && (! tree_fits_uhwi_p (offset)
|| compare_tree_int (offset, length) >= 0))
return 0;
@@ -11029,8 +11014,8 @@ const_vector_from_tree (tree exp)
RTVEC_ELT (v, i) = CONST_FIXED_FROM_FIXED_VALUE (TREE_FIXED_CST (elt),
inner);
else
- RTVEC_ELT (v, i) = immed_double_int_const (tree_to_double_int (elt),
- inner);
+ RTVEC_ELT (v, i)
+ = immed_wide_int_const (elt, TYPE_MODE (TREE_TYPE (elt)));
}
return gen_rtx_CONST_VECTOR (mode, v);