Commit 82f620e2 by Eric Botcazou

Fix unaligned load with small memcpy on the ARM

store_integral_bit_field is ready to handle BLKmode fields, there is
even a subtlety with their handling on big-endian targets, see e.g.
PR middle-end/50325, but not if they are unaligned, so the fix is
simply to call extract_bit_field for them in order to generate an
unaligned load.  As a bonus, this subsumes  the big-endian specific
path that was added under PR middle-end/50325.

	PR middle-end/92071
	* expmed.c (store_integral_bit_field): For fields larger than a
	word, call extract_bit_field on the value if the mode is BLKmode.
	Remove specific path for big-endian targets and tidy things up a
	little bit.
parent 54e69cb0
2019-03-13 Eric Botcazou <ebotcazou@adacore.com>
PR middle-end/92071
* expmed.c (store_integral_bit_field): For fields larger than a word,
call extract_bit_field on the value if the mode is BLKmode. Remove
specific path for big-endian targets and tidy things up a little bit.
2020-03-12 Richard Sandiford <richard.sandiford@arm.com> 2020-03-12 Richard Sandiford <richard.sandiford@arm.com>
PR rtl-optimization/90275 PR rtl-optimization/90275
......
...@@ -933,8 +933,7 @@ store_integral_bit_field (rtx op0, opt_scalar_int_mode op0_mode, ...@@ -933,8 +933,7 @@ store_integral_bit_field (rtx op0, opt_scalar_int_mode op0_mode,
However, only do that if the value is not BLKmode. */ However, only do that if the value is not BLKmode. */
const bool backwards = WORDS_BIG_ENDIAN && fieldmode != BLKmode; const bool backwards = WORDS_BIG_ENDIAN && fieldmode != BLKmode;
unsigned int nwords = (bitsize + (BITS_PER_WORD - 1)) / BITS_PER_WORD; const int nwords = (bitsize + (BITS_PER_WORD - 1)) / BITS_PER_WORD;
unsigned int i;
rtx_insn *last; rtx_insn *last;
/* This is the mode we must force value to, so that there will be enough /* This is the mode we must force value to, so that there will be enough
...@@ -950,35 +949,31 @@ store_integral_bit_field (rtx op0, opt_scalar_int_mode op0_mode, ...@@ -950,35 +949,31 @@ store_integral_bit_field (rtx op0, opt_scalar_int_mode op0_mode,
value_mode = smallest_int_mode_for_size (nwords * BITS_PER_WORD); value_mode = smallest_int_mode_for_size (nwords * BITS_PER_WORD);
last = get_last_insn (); last = get_last_insn ();
for (i = 0; i < nwords; i++) for (int i = 0; i < nwords; i++)
{ {
/* If I is 0, use the low-order word in both field and target; /* Number of bits to be stored in this iteration, i.e. BITS_PER_WORD
if I is 1, use the next to lowest word; and so on. */ except maybe for the last iteration. */
unsigned int wordnum = (backwards const unsigned HOST_WIDE_INT new_bitsize
? GET_MODE_SIZE (value_mode) / UNITS_PER_WORD = MIN (BITS_PER_WORD, bitsize - i * BITS_PER_WORD);
- i - 1 /* Bit offset from the starting bit number in the target. */
: i); const unsigned int bit_offset
unsigned int bit_offset = (backwards ^ reverse = backwards ^ reverse
? MAX ((int) bitsize - ((int) i + 1) ? MAX ((int) bitsize - (i + 1) * BITS_PER_WORD, 0)
* BITS_PER_WORD, : i * BITS_PER_WORD;
0) /* Starting word number in the value. */
: (int) i * BITS_PER_WORD); const unsigned int wordnum
rtx value_word = operand_subword_force (value, wordnum, value_mode); = backwards
unsigned HOST_WIDE_INT new_bitsize = ? GET_MODE_SIZE (value_mode) / UNITS_PER_WORD - (i + 1)
MIN (BITS_PER_WORD, bitsize - i * BITS_PER_WORD); : i;
/* The chunk of the value in word_mode. We use bit-field extraction
/* If the remaining chunk doesn't have full wordsize we have in BLKmode to handle unaligned memory references and to shift the
to make sure that for big-endian machines the higher order last chunk right on big-endian machines if need be. */
bits are used. */ rtx value_word
if (new_bitsize < BITS_PER_WORD && BYTES_BIG_ENDIAN && !backwards) = fieldmode == BLKmode
{ ? extract_bit_field (value, new_bitsize, wordnum * BITS_PER_WORD,
int shift = BITS_PER_WORD - new_bitsize; 1, NULL_RTX, word_mode, word_mode, false,
rtx shift_rtx = gen_int_shift_amount (word_mode, shift); NULL)
value_word = simplify_expand_binop (word_mode, lshr_optab, : operand_subword_force (value, wordnum, value_mode);
value_word, shift_rtx,
NULL_RTX, true,
OPTAB_LIB_WIDEN);
}
if (!store_bit_field_1 (op0, new_bitsize, if (!store_bit_field_1 (op0, new_bitsize,
bitnum + bit_offset, bitnum + bit_offset,
......
2019-03-13 Eric Botcazou <ebotcazou@adacore.com>
* gcc.c-torture/compile/20200313-1.c: New test.
2020-03-12 Jeff Law <law@redhat.com> 2020-03-12 Jeff Law <law@redhat.com>
PR rtl-optimization/90275 PR rtl-optimization/90275
......
/* PR middle-end/92071 */
/* Testcase by David Binderman <dcb314@hotmail.com> */
void *a;
union U { double c; char d[8]; };
void bar (union U);
void
foo (void)
{
union U b;
__builtin_memcpy (b.d, a, 8);
bar (b);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment