aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorRichard Sandiford <richard.sandiford@arm.com>2016-06-08 12:18:27 +0000
committerRichard Sandiford <rsandifo@gcc.gnu.org>2016-06-08 12:18:27 +0000
commit867a0126bcb8e2ea2b9ef900ac8b6b75c4fc6382 (patch)
tree40883c86eea64895001fccfa98cda344648a1326 /gcc
parentd821b79474ab6c3513fe0060decff0ecd5934fc0 (diff)
downloadgcc-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/ChangeLog8
-rw-r--r--gcc/expmed.c55
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;