+2017-08-30 Richard Sandiford <richard.sandiford@linaro.org>
+ Alan Hayward <alan.hayward@arm.com>
+ David Sherwood <david.sherwood@arm.com>
+
+ * machmode.h (bit_field_mode_iterator::next_mode): Take a pointer
+ to a scalar_int_mode instead of a machine_mode.
+ (bit_field_mode_iterator::m_mode): Change type to opt_scalar_int_mode.
+ (get_best_mode): Return a boolean and use a pointer argument to store
+ the selected mode. Replace the limit mode parameter with a bit limit.
+ * expmed.c (adjust_bit_field_mem_for_reg): Use scalar_int_mode
+ for the values returned by bit_field_mode_iterator::next_mode.
+ (store_bit_field): Update call to get_best_mode.
+ (store_fixed_bit_field): Likewise.
+ (extract_fixed_bit_field): Likewise.
+ * expr.c (optimize_bitfield_assignment_op): Likewise.
+ * fold-const.c (optimize_bit_field_compare): Likewise.
+ (fold_truth_andor_1): Likewise.
+ * stor-layout.c (bit_field_mode_iterator::next_mode): As above.
+ Update for new type of m_mode.
+ (get_best_mode): As above.
+
2017-08-30 Richard Sandiford <richard.sandiford@linaro.org>
Alan Hayward <alan.hayward@arm.com>
David Sherwood <david.sherwood@arm.com>
bit_field_mode_iterator iter (bitsize, bitnum, bitregion_start,
bitregion_end, MEM_ALIGN (op0),
MEM_VOLATILE_P (op0));
- machine_mode best_mode;
+ scalar_int_mode best_mode;
if (iter.next_mode (&best_mode))
{
/* We can use a memory in BEST_MODE. See whether this is true for
fieldmode))
limit_mode = insn.field_mode;
- machine_mode wider_mode;
+ scalar_int_mode wider_mode;
while (iter.next_mode (&wider_mode)
&& GET_MODE_SIZE (wider_mode) <= GET_MODE_SIZE (limit_mode))
best_mode = wider_mode;
bit region. */
if (MEM_P (str_rtx) && bitregion_start > 0)
{
- machine_mode bestmode;
+ scalar_int_mode best_mode;
+ machine_mode addr_mode = VOIDmode;
HOST_WIDE_INT offset, size;
gcc_assert ((bitregion_start % BITS_PER_UNIT) == 0);
size = (bitnum + bitsize + BITS_PER_UNIT - 1) / BITS_PER_UNIT;
bitregion_end -= bitregion_start;
bitregion_start = 0;
- bestmode = get_best_mode (bitsize, bitnum,
- bitregion_start, bitregion_end,
- MEM_ALIGN (str_rtx), VOIDmode,
- MEM_VOLATILE_P (str_rtx));
- str_rtx = adjust_bitfield_address_size (str_rtx, bestmode, offset, size);
+ if (get_best_mode (bitsize, bitnum,
+ bitregion_start, bitregion_end,
+ MEM_ALIGN (str_rtx), INT_MAX,
+ MEM_VOLATILE_P (str_rtx), &best_mode))
+ addr_mode = best_mode;
+ str_rtx = adjust_bitfield_address_size (str_rtx, addr_mode,
+ offset, size);
}
if (!store_bit_field_1 (str_rtx, bitsize, bitnum,
if (GET_MODE_BITSIZE (mode) == 0
|| GET_MODE_BITSIZE (mode) > GET_MODE_BITSIZE (word_mode))
mode = word_mode;
- mode = get_best_mode (bitsize, bitnum, bitregion_start, bitregion_end,
- MEM_ALIGN (op0), mode, MEM_VOLATILE_P (op0));
-
- if (mode == VOIDmode)
+ scalar_int_mode best_mode;
+ if (!get_best_mode (bitsize, bitnum, bitregion_start, bitregion_end,
+ MEM_ALIGN (op0), GET_MODE_BITSIZE (mode),
+ MEM_VOLATILE_P (op0), &best_mode))
{
/* The only way this should occur is if the field spans word
boundaries. */
return;
}
- op0 = narrow_bit_field_mem (op0, mode, bitsize, bitnum, &bitnum);
+ op0 = narrow_bit_field_mem (op0, best_mode, bitsize, bitnum, &bitnum);
}
store_fixed_bit_field_1 (op0, bitsize, bitnum, value, reverse);
{
if (MEM_P (op0))
{
- machine_mode mode
- = get_best_mode (bitsize, bitnum, 0, 0, MEM_ALIGN (op0), word_mode,
- MEM_VOLATILE_P (op0));
-
- if (mode == VOIDmode)
+ scalar_int_mode mode;
+ if (!get_best_mode (bitsize, bitnum, 0, 0, MEM_ALIGN (op0),
+ BITS_PER_WORD, MEM_VOLATILE_P (op0), &mode))
/* The only way this should occur is if the field spans word
boundaries. */
return extract_split_bit_field (op0, bitsize, bitnum, unsignedp,
unsigned HOST_WIDE_INT offset1;
if (str_bitsize == 0 || str_bitsize > BITS_PER_WORD)
- str_mode = word_mode;
- str_mode = get_best_mode (bitsize, bitpos,
- bitregion_start, bitregion_end,
- MEM_ALIGN (str_rtx), str_mode, 0);
- if (str_mode == VOIDmode)
+ str_bitsize = BITS_PER_WORD;
+
+ scalar_int_mode best_mode;
+ if (!get_best_mode (bitsize, bitpos, bitregion_start, bitregion_end,
+ MEM_ALIGN (str_rtx), str_bitsize, false, &best_mode))
return false;
- str_bitsize = GET_MODE_BITSIZE (str_mode);
+ str_mode = best_mode;
+ str_bitsize = GET_MODE_BITSIZE (best_mode);
offset1 = bitpos;
bitpos %= str_bitsize;
tree type = TREE_TYPE (lhs);
tree unsigned_type;
int const_p = TREE_CODE (rhs) == INTEGER_CST;
- machine_mode lmode, rmode, nmode;
+ machine_mode lmode, rmode;
+ scalar_int_mode nmode;
int lunsignedp, runsignedp;
int lreversep, rreversep;
int lvolatilep = 0, rvolatilep = 0;
/* See if we can find a mode to refer to this field. We should be able to,
but fail if we can't. */
- nmode = get_best_mode (lbitsize, lbitpos, bitstart, bitend,
- const_p ? TYPE_ALIGN (TREE_TYPE (linner))
- : MIN (TYPE_ALIGN (TREE_TYPE (linner)),
- TYPE_ALIGN (TREE_TYPE (rinner))),
- word_mode, false);
- if (nmode == VOIDmode)
+ if (!get_best_mode (lbitsize, lbitpos, bitstart, bitend,
+ const_p ? TYPE_ALIGN (TREE_TYPE (linner))
+ : MIN (TYPE_ALIGN (TREE_TYPE (linner)),
+ TYPE_ALIGN (TREE_TYPE (rinner))),
+ BITS_PER_WORD, false, &nmode))
return 0;
/* Set signed and unsigned types of the precision of this mode for the
int ll_unsignedp, lr_unsignedp, rl_unsignedp, rr_unsignedp;
int ll_reversep, lr_reversep, rl_reversep, rr_reversep;
machine_mode ll_mode, lr_mode, rl_mode, rr_mode;
- machine_mode lnmode, rnmode;
+ scalar_int_mode lnmode, rnmode;
tree ll_mask, lr_mask, rl_mask, rr_mask;
tree ll_and_mask, lr_and_mask, rl_and_mask, rr_and_mask;
tree l_const, r_const;
to be relative to a field of that size. */
first_bit = MIN (ll_bitpos, rl_bitpos);
end_bit = MAX (ll_bitpos + ll_bitsize, rl_bitpos + rl_bitsize);
- lnmode = get_best_mode (end_bit - first_bit, first_bit, 0, 0,
- TYPE_ALIGN (TREE_TYPE (ll_inner)), word_mode,
- volatilep);
- if (lnmode == VOIDmode)
+ if (!get_best_mode (end_bit - first_bit, first_bit, 0, 0,
+ TYPE_ALIGN (TREE_TYPE (ll_inner)), BITS_PER_WORD,
+ volatilep, &lnmode))
return 0;
lnbitsize = GET_MODE_BITSIZE (lnmode);
first_bit = MIN (lr_bitpos, rr_bitpos);
end_bit = MAX (lr_bitpos + lr_bitsize, rr_bitpos + rr_bitsize);
- rnmode = get_best_mode (end_bit - first_bit, first_bit, 0, 0,
- TYPE_ALIGN (TREE_TYPE (lr_inner)), word_mode,
- volatilep);
- if (rnmode == VOIDmode)
+ if (!get_best_mode (end_bit - first_bit, first_bit, 0, 0,
+ TYPE_ALIGN (TREE_TYPE (lr_inner)), BITS_PER_WORD,
+ volatilep, &rnmode))
return 0;
rnbitsize = GET_MODE_BITSIZE (rnmode);
bit_field_mode_iterator (HOST_WIDE_INT, HOST_WIDE_INT,
HOST_WIDE_INT, HOST_WIDE_INT,
unsigned int, bool);
- bool next_mode (machine_mode *);
+ bool next_mode (scalar_int_mode *);
bool prefer_smaller_modes ();
private:
- machine_mode m_mode;
+ opt_scalar_int_mode m_mode;
/* We use signed values here because the bit position can be negative
for invalid input such as gcc.dg/pr48335-8.c. */
HOST_WIDE_INT m_bitsize;
/* Find the best mode to use to access a bit field. */
-extern machine_mode get_best_mode (int, int,
- unsigned HOST_WIDE_INT,
- unsigned HOST_WIDE_INT,
- unsigned int,
- machine_mode, bool);
+extern bool get_best_mode (int, int, unsigned HOST_WIDE_INT,
+ unsigned HOST_WIDE_INT, unsigned int,
+ unsigned HOST_WIDE_INT, bool, scalar_int_mode *);
/* Determine alignment, 1<=result<=BIGGEST_ALIGNMENT. */
available, storing it in *OUT_MODE if so. */
bool
-bit_field_mode_iterator::next_mode (machine_mode *out_mode)
+bit_field_mode_iterator::next_mode (scalar_int_mode *out_mode)
{
- for (; m_mode != VOIDmode;
- m_mode = GET_MODE_WIDER_MODE (m_mode).else_void ())
+ scalar_int_mode mode;
+ for (; m_mode.exists (&mode); m_mode = GET_MODE_WIDER_MODE (mode))
{
- unsigned int unit = GET_MODE_BITSIZE (m_mode);
+ unsigned int unit = GET_MODE_BITSIZE (mode);
/* Skip modes that don't have full precision. */
- if (unit != GET_MODE_PRECISION (m_mode))
+ if (unit != GET_MODE_PRECISION (mode))
continue;
/* Stop if the mode is too wide to handle efficiently. */
break;
/* Stop if the mode requires too much alignment. */
- if (GET_MODE_ALIGNMENT (m_mode) > m_align
- && SLOW_UNALIGNED_ACCESS (m_mode, m_align))
+ if (GET_MODE_ALIGNMENT (mode) > m_align
+ && SLOW_UNALIGNED_ACCESS (mode, m_align))
break;
- *out_mode = m_mode;
- m_mode = GET_MODE_WIDER_MODE (m_mode).else_void ();
+ *out_mode = mode;
+ m_mode = GET_MODE_WIDER_MODE (mode);
m_count++;
return true;
}
memory access to that range. Otherwise, we are allowed to touch
any adjacent non bit-fields.
- The underlying object is known to be aligned to a boundary of ALIGN bits.
- If LARGEST_MODE is not VOIDmode, it means that we should not use a mode
- larger than LARGEST_MODE (usually SImode).
+ The chosen mode must have no more than LARGEST_MODE_BITSIZE bits.
+ INT_MAX is a suitable value for LARGEST_MODE_BITSIZE if the caller
+ doesn't want to apply a specific limit.
If no mode meets all these conditions, we return VOIDmode.
+ The underlying object is known to be aligned to a boundary of ALIGN bits.
+
If VOLATILEP is false and SLOW_BYTE_ACCESS is false, we return the
smallest mode meeting these conditions.
If VOLATILEP is true the narrow_volatile_bitfields target hook is used to
decide which of the above modes should be used. */
-machine_mode
+bool
get_best_mode (int bitsize, int bitpos,
unsigned HOST_WIDE_INT bitregion_start,
unsigned HOST_WIDE_INT bitregion_end,
unsigned int align,
- machine_mode largest_mode, bool volatilep)
+ unsigned HOST_WIDE_INT largest_mode_bitsize, bool volatilep,
+ scalar_int_mode *best_mode)
{
bit_field_mode_iterator iter (bitsize, bitpos, bitregion_start,
bitregion_end, align, volatilep);
- machine_mode widest_mode = VOIDmode;
- machine_mode mode;
+ scalar_int_mode mode;
+ bool found = false;
while (iter.next_mode (&mode)
/* ??? For historical reasons, reject modes that would normally
receive greater alignment, even if unaligned accesses are
so that the final bitfield reference still has a MEM_EXPR
and MEM_OFFSET. */
&& GET_MODE_ALIGNMENT (mode) <= align
- && (largest_mode == VOIDmode
- || GET_MODE_SIZE (mode) <= GET_MODE_SIZE (largest_mode)))
+ && GET_MODE_BITSIZE (mode) <= largest_mode_bitsize)
{
- widest_mode = mode;
+ *best_mode = mode;
+ found = true;
if (iter.prefer_smaller_modes ())
break;
}
- return widest_mode;
+
+ return found;
}
/* Gets minimal and maximal values for MODE (signed or unsigned depending on