diff options
author | jakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4> | 2013-05-23 09:17:34 +0000 |
---|---|---|
committer | jakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4> | 2013-05-23 09:17:34 +0000 |
commit | 98908b236587fb46b5cec5e56bd34361da58bdac (patch) | |
tree | 57fea5153070c42926cb9de1a4e5502db3ae37bd /gcc/expmed.c | |
parent | 81c3220e0b032744b1bfaa05c7ce9cb8cae36760 (diff) | |
download | gcc-98908b236587fb46b5cec5e56bd34361da58bdac.tar.gz |
PR middle-end/57344
* expmed.c (store_split_bit_field): If op0 is a REG or
SUBREG of a REG, don't lower unit. Handle unit not being
always BITS_PER_WORD.
* gcc.c-torture/execute/pr57344-1.c: New test.
* gcc.c-torture/execute/pr57344-2.c: New test.
* gcc.c-torture/execute/pr57344-3.c: New test.
* gcc.c-torture/execute/pr57344-4.c: New test.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@199238 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/expmed.c')
-rw-r--r-- | gcc/expmed.c | 18 |
1 files changed, 12 insertions, 6 deletions
diff --git a/gcc/expmed.c b/gcc/expmed.c index c85e68cf617..daadd3def5d 100644 --- a/gcc/expmed.c +++ b/gcc/expmed.c @@ -1094,10 +1094,14 @@ store_split_bit_field (rtx op0, unsigned HOST_WIDE_INT bitsize, thispos = (bitpos + bitsdone) % unit; /* When region of bytes we can touch is restricted, decrease - UNIT close to the end of the region as needed. */ + UNIT close to the end of the region as needed. If op0 is a REG + or SUBREG of REG, don't do this, as there can't be data races + on a register and we can expand shorter code in some cases. */ if (bitregion_end && unit > BITS_PER_UNIT - && bitpos + bitsdone - thispos + unit > bitregion_end + 1) + && bitpos + bitsdone - thispos + unit > bitregion_end + 1 + && !REG_P (op0) + && (GET_CODE (op0) != SUBREG || !REG_P (SUBREG_REG (op0)))) { unit = unit / 2; continue; @@ -1147,14 +1151,15 @@ store_split_bit_field (rtx op0, unsigned HOST_WIDE_INT bitsize, the current word starting from the base register. */ if (GET_CODE (op0) == SUBREG) { - int word_offset = (SUBREG_BYTE (op0) / UNITS_PER_WORD) + offset; + int word_offset = (SUBREG_BYTE (op0) / UNITS_PER_WORD) + + (offset * unit / BITS_PER_WORD); enum 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 = 0; + offset &= BITS_PER_WORD / unit - 1; } else if (REG_P (op0)) { @@ -1162,8 +1167,9 @@ store_split_bit_field (rtx op0, unsigned HOST_WIDE_INT bitsize, if (op0_mode != BLKmode && GET_MODE_SIZE (op0_mode) < UNITS_PER_WORD) word = offset ? const0_rtx : op0; else - word = operand_subword_force (op0, offset, GET_MODE (op0)); - offset = 0; + word = operand_subword_force (op0, offset * unit / BITS_PER_WORD, + GET_MODE (op0)); + offset &= BITS_PER_WORD / unit - 1; } else word = op0; |