summaryrefslogtreecommitdiff
path: root/gcc/expmed.c
diff options
context:
space:
mode:
authorjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>2012-04-25 14:27:08 +0000
committerjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>2012-04-25 14:27:08 +0000
commit7e9ba3f31fac3d4e975cf68f8a14aa6252bbfa3d (patch)
tree81ecc613d94b359b676a0ac3492e351643109575 /gcc/expmed.c
parentd10b66d79dacf3ec41be95943a3df193ba0476ed (diff)
downloadgcc-7e9ba3f31fac3d4e975cf68f8a14aa6252bbfa3d.tar.gz
PR middle-end/52979
* stor-layout.c (get_best_mode): Don't return mode with bitsize larger than maxbits. Don't compute maxbits modulo align. Also check that unit bytes long store at bitpos / unit * unit doesn't affect bits beyond bitregion_end. * expmed.c (store_bit_field_1): Avoid trying insv if OP_MODE MEM would not fit into bitregion_start ... bitregion_end + 1 bit region. (store_split_bit_field): Decrease unit close to end of bitregion_end if access is restricted in order to avoid mutual recursion. * gcc.c-torture/compile/pr52979-1.c: New test. * gcc.c-torture/execute/pr52979-1.c: New test. * gcc.c-torture/execute/pr52979-2.c: New test. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@186819 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/expmed.c')
-rw-r--r--gcc/expmed.c20
1 files changed, 18 insertions, 2 deletions
diff --git a/gcc/expmed.c b/gcc/expmed.c
index aa24fbf630b..a0a0960bfa2 100644
--- a/gcc/expmed.c
+++ b/gcc/expmed.c
@@ -640,7 +640,13 @@ store_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
&& !(MEM_P (op0) && MEM_VOLATILE_P (op0)
&& flag_strict_volatile_bitfields > 0)
&& ! ((REG_P (op0) || GET_CODE (op0) == SUBREG)
- && (bitsize + bitpos > GET_MODE_BITSIZE (op_mode))))
+ && (bitsize + bitpos > GET_MODE_BITSIZE (op_mode)))
+ /* Do not use insv if the bit region is restricted and
+ op_mode integer at offset doesn't fit into the
+ restricted region. */
+ && !(MEM_P (op0) && bitregion_end
+ && bitnum - bitpos + GET_MODE_BITSIZE (op_mode)
+ > bitregion_end + 1))
{
struct expand_operand ops[4];
int xbitpos = bitpos;
@@ -760,7 +766,7 @@ store_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
|| GET_MODE_BITSIZE (GET_MODE (op0)) > maxbits
|| (op_mode != MAX_MACHINE_MODE
&& GET_MODE_SIZE (GET_MODE (op0)) > GET_MODE_SIZE (op_mode)))
- bestmode = get_best_mode (bitsize, bitnum,
+ bestmode = get_best_mode (bitsize, bitnum,
bitregion_start, bitregion_end,
MEM_ALIGN (op0),
(op_mode == MAX_MACHINE_MODE
@@ -1096,6 +1102,16 @@ store_split_bit_field (rtx op0, unsigned HOST_WIDE_INT bitsize,
offset = (bitpos + bitsdone) / unit;
thispos = (bitpos + bitsdone) % unit;
+ /* When region of bytes we can touch is restricted, decrease
+ UNIT close to the end of the region as needed. */
+ if (bitregion_end
+ && unit > BITS_PER_UNIT
+ && bitpos + bitsdone - thispos + unit > bitregion_end + 1)
+ {
+ unit = unit / 2;
+ continue;
+ }
+
/* THISSIZE must not overrun a word boundary. Otherwise,
store_fixed_bit_field will call us again, and we will mutually
recurse forever. */