diff options
author | Richard Sandiford <richard.sandiford@arm.com> | 2016-06-08 12:18:27 +0000 |
---|---|---|
committer | Richard Sandiford <rsandifo@gcc.gnu.org> | 2016-06-08 12:18:27 +0000 |
commit | 867a0126bcb8e2ea2b9ef900ac8b6b75c4fc6382 (patch) | |
tree | 40883c86eea64895001fccfa98cda344648a1326 /gcc | |
parent | d821b79474ab6c3513fe0060decff0ecd5934fc0 (diff) | |
download | gcc-867a0126bcb8e2ea2b9ef900ac8b6b75c4fc6382.zip gcc-867a0126bcb8e2ea2b9ef900ac8b6b75c4fc6382.tar.gz gcc-867a0126bcb8e2ea2b9ef900ac8b6b75c4fc6382.tar.bz2 |
Remove word_mode hack for split bitfields
This patch is effectively reverting a change from 1994. The reason
I think it's a hack is that store_bit_field_1 is creating a subreg
reference to one word of a field even though it has already proven that
the field spills into the following word. We then rely on the special
SUBREG handling in store_split_bit_field to ignore the extent of op0 and
look inside the SUBREG_REG regardless. I don't see any reason why we can't
pass the original op0 to store_split_bit_field instead.
Tested on aarch64-linux-gnu and x86_64-linux-gnu.
gcc/
* expmed.c (store_bit_field_1): Do not restrict a multiword op0
to one word if the field is known to overlap other words.
(extract_bit_field_1): Likewise.
(store_split_bit_field): Remove compensating code.
(extract_split_bit_field): Likewise.
From-SVN: r237211
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/expmed.c | 55 |
2 files changed, 21 insertions, 42 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index df5b0df..6767537 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2016-06-08 Richard Sandiford <richard.sandiford@arm.com> + + * expmed.c (store_bit_field_1): Do not restrict a multiword op0 + to one word if the field is known to overlap other words. + (extract_bit_field_1): Likewise. + (store_split_bit_field): Remove compensating code. + (extract_split_bit_field): Likewise. + 2016-06-08 Bernd Schmidt <bschmidt@redhat.com> PR debug/71432 diff --git a/gcc/expmed.c b/gcc/expmed.c index ec968da..6645a53 100644 --- a/gcc/expmed.c +++ b/gcc/expmed.c @@ -967,11 +967,7 @@ store_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize, If the region spans two words, defer to store_split_bit_field. */ if (!MEM_P (op0) && GET_MODE_SIZE (GET_MODE (op0)) > UNITS_PER_WORD) { - op0 = simplify_gen_subreg (word_mode, op0, GET_MODE (op0), - bitnum / BITS_PER_WORD * UNITS_PER_WORD); - gcc_assert (op0); - bitnum %= BITS_PER_WORD; - if (bitnum + bitsize > BITS_PER_WORD) + if (bitnum % BITS_PER_WORD + bitsize > BITS_PER_WORD) { if (!fallback_p) return false; @@ -980,6 +976,10 @@ store_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize, bitregion_end, value, reverse); return true; } + op0 = simplify_gen_subreg (word_mode, op0, GET_MODE (op0), + bitnum / BITS_PER_WORD * UNITS_PER_WORD); + gcc_assert (op0); + bitnum %= BITS_PER_WORD; } /* From here on we can assume that the field to be stored in fits @@ -1383,25 +1383,8 @@ store_split_bit_field (rtx op0, unsigned HOST_WIDE_INT bitsize, bitsdone, NULL_RTX, 1, false); } - /* If OP0 is a register, then handle OFFSET here. - - When handling multiword bitfields, extract_bit_field may pass - down a word_mode SUBREG of a larger REG for a bitfield that actually - crosses a word boundary. Thus, for a SUBREG, we must find - the current word starting from the base register. */ - if (GET_CODE (op0) == SUBREG) - { - int word_offset = (SUBREG_BYTE (op0) / UNITS_PER_WORD) - + (offset * unit / BITS_PER_WORD); - machine_mode sub_mode = GET_MODE (SUBREG_REG (op0)); - if (sub_mode != BLKmode && GET_MODE_SIZE (sub_mode) < UNITS_PER_WORD) - word = word_offset ? const0_rtx : op0; - else - word = operand_subword_force (SUBREG_REG (op0), word_offset, - GET_MODE (SUBREG_REG (op0))); - offset &= BITS_PER_WORD / unit - 1; - } - else if (REG_P (op0)) + /* If OP0 is a register, then handle OFFSET here. */ + if (SUBREG_P (op0) || REG_P (op0)) { machine_mode op0_mode = GET_MODE (op0); if (op0_mode != BLKmode && GET_MODE_SIZE (op0_mode) < UNITS_PER_WORD) @@ -1787,10 +1770,7 @@ extract_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize, If the region spans two words, defer to extract_split_bit_field. */ if (!MEM_P (op0) && GET_MODE_SIZE (GET_MODE (op0)) > UNITS_PER_WORD) { - op0 = simplify_gen_subreg (word_mode, op0, GET_MODE (op0), - bitnum / BITS_PER_WORD * UNITS_PER_WORD); - bitnum %= BITS_PER_WORD; - if (bitnum + bitsize > BITS_PER_WORD) + if (bitnum % BITS_PER_WORD + bitsize > BITS_PER_WORD) { if (!fallback_p) return NULL_RTX; @@ -1798,6 +1778,9 @@ extract_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize, reverse); return convert_extracted_bit_field (target, mode, tmode, unsignedp); } + op0 = simplify_gen_subreg (word_mode, op0, GET_MODE (op0), + bitnum / BITS_PER_WORD * UNITS_PER_WORD); + bitnum %= BITS_PER_WORD; } /* From here on we know the desired field is smaller than a word. @@ -2109,20 +2092,8 @@ extract_split_bit_field (rtx op0, unsigned HOST_WIDE_INT bitsize, thissize = MIN (bitsize - bitsdone, BITS_PER_WORD); thissize = MIN (thissize, unit - thispos); - /* If OP0 is a register, then handle OFFSET here. - - When handling multiword bitfields, extract_bit_field may pass - down a word_mode SUBREG of a larger REG for a bitfield that actually - crosses a word boundary. Thus, for a SUBREG, we must find - the current word starting from the base register. */ - if (GET_CODE (op0) == SUBREG) - { - int word_offset = (SUBREG_BYTE (op0) / UNITS_PER_WORD) + offset; - word = operand_subword_force (SUBREG_REG (op0), word_offset, - GET_MODE (SUBREG_REG (op0))); - offset = 0; - } - else if (REG_P (op0)) + /* If OP0 is a register, then handle OFFSET here. */ + if (SUBREG_P (op0) || REG_P (op0)) { word = operand_subword_force (op0, offset, GET_MODE (op0)); offset = 0; |