Commit 2c58f7dd by Richard Sandiford Committed by Richard Sandiford

expmed.c (store_bit_field): Make the SUBREG code adjust bitnum.

	* expmed.c (store_bit_field): Make the SUBREG code adjust bitnum.
	Set bitpos and offset later in the function.  Do nothing if the
	target is a register and if the bitfield lies completely outside
	that register.
	(extract_bit_field): Make the same SUBREG, bitpos and offset changes
	here.  Return an uninitialised register if the source value is stored
	in a register and the bitfield lies completely outside that register.

From-SVN: r94677
parent 55c4ae3f
2005-02-06 Richard Sandiford <rsandifo@redhat.com>
* expmed.c (store_bit_field): Make the SUBREG code adjust bitnum.
Set bitpos and offset later in the function. Do nothing if the
target is a register and if the bitfield lies completely outside
that register.
(extract_bit_field): Make the same SUBREG, bitpos and offset changes
here. Return an uninitialised register if the source value is stored
in a register and the bitfield lies completely outside that register.
2005-02-06 Steven Bosscher <stevenb@suse.de> 2005-02-06 Steven Bosscher <stevenb@suse.de>
* df.c (df_insn_refs_record): Use XEXP to get the operand of a USE, * df.c (df_insn_refs_record): Use XEXP to get the operand of a USE,
......
...@@ -337,8 +337,7 @@ store_bit_field (rtx str_rtx, unsigned HOST_WIDE_INT bitsize, ...@@ -337,8 +337,7 @@ store_bit_field (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
{ {
unsigned int unit unsigned int unit
= (MEM_P (str_rtx)) ? BITS_PER_UNIT : BITS_PER_WORD; = (MEM_P (str_rtx)) ? BITS_PER_UNIT : BITS_PER_WORD;
unsigned HOST_WIDE_INT offset = bitnum / unit; unsigned HOST_WIDE_INT offset, bitpos;
unsigned HOST_WIDE_INT bitpos = bitnum % unit;
rtx op0 = str_rtx; rtx op0 = str_rtx;
int byte_offset; int byte_offset;
rtx orig_value; rtx orig_value;
...@@ -352,12 +351,16 @@ store_bit_field (rtx str_rtx, unsigned HOST_WIDE_INT bitsize, ...@@ -352,12 +351,16 @@ store_bit_field (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
meaningful at a much higher level; when structures are copied meaningful at a much higher level; when structures are copied
between memory and regs, the higher-numbered regs between memory and regs, the higher-numbered regs
always get higher addresses. */ always get higher addresses. */
offset += (SUBREG_BYTE (op0) / UNITS_PER_WORD); bitnum += SUBREG_BYTE (op0) * BITS_PER_UNIT;
/* We used to adjust BITPOS here, but now we do the whole adjustment
right after the loop. */
op0 = SUBREG_REG (op0); op0 = SUBREG_REG (op0);
} }
/* No action is needed if the target is a register and if the field
lies completely outside that register. This can occur if the source
code contains an out-of-bounds access to a small array. */
if (REG_P (op0) && bitnum >= GET_MODE_BITSIZE (GET_MODE (op0)))
return value;
/* Use vec_set patterns for inserting parts of vectors whenever /* Use vec_set patterns for inserting parts of vectors whenever
available. */ available. */
if (VECTOR_MODE_P (GET_MODE (op0)) if (VECTOR_MODE_P (GET_MODE (op0))
...@@ -419,6 +422,8 @@ store_bit_field (rtx str_rtx, unsigned HOST_WIDE_INT bitsize, ...@@ -419,6 +422,8 @@ store_bit_field (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
done with a simple store. For targets that support fast unaligned done with a simple store. For targets that support fast unaligned
memory, any naturally sized, unit aligned field can be done directly. */ memory, any naturally sized, unit aligned field can be done directly. */
offset = bitnum / unit;
bitpos = bitnum % unit;
byte_offset = (bitnum % BITS_PER_WORD) / BITS_PER_UNIT byte_offset = (bitnum % BITS_PER_WORD) / BITS_PER_UNIT
+ (offset * UNITS_PER_WORD); + (offset * UNITS_PER_WORD);
...@@ -1064,8 +1069,7 @@ extract_bit_field (rtx str_rtx, unsigned HOST_WIDE_INT bitsize, ...@@ -1064,8 +1069,7 @@ extract_bit_field (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
{ {
unsigned int unit unsigned int unit
= (MEM_P (str_rtx)) ? BITS_PER_UNIT : BITS_PER_WORD; = (MEM_P (str_rtx)) ? BITS_PER_UNIT : BITS_PER_WORD;
unsigned HOST_WIDE_INT offset = bitnum / unit; unsigned HOST_WIDE_INT offset, bitpos;
unsigned HOST_WIDE_INT bitpos = bitnum % unit;
rtx op0 = str_rtx; rtx op0 = str_rtx;
rtx spec_target = target; rtx spec_target = target;
rtx spec_target_subreg = 0; rtx spec_target_subreg = 0;
...@@ -1080,15 +1084,16 @@ extract_bit_field (rtx str_rtx, unsigned HOST_WIDE_INT bitsize, ...@@ -1080,15 +1084,16 @@ extract_bit_field (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
while (GET_CODE (op0) == SUBREG) while (GET_CODE (op0) == SUBREG)
{ {
bitpos += SUBREG_BYTE (op0) * BITS_PER_UNIT; bitnum += SUBREG_BYTE (op0) * BITS_PER_UNIT;
if (bitpos > unit)
{
offset += (bitpos / unit);
bitpos %= unit;
}
op0 = SUBREG_REG (op0); op0 = SUBREG_REG (op0);
} }
/* If we have an out-of-bounds access to a register, just return an
uninitialised register of the required mode. This can occur if the
source code contains an out-of-bounds access to a small array. */
if (REG_P (op0) && bitnum >= GET_MODE_BITSIZE (GET_MODE (op0)))
return gen_reg_rtx (tmode);
if (REG_P (op0) if (REG_P (op0)
&& mode == GET_MODE (op0) && mode == GET_MODE (op0)
&& bitnum == 0 && bitnum == 0
...@@ -1188,6 +1193,8 @@ extract_bit_field (rtx str_rtx, unsigned HOST_WIDE_INT bitsize, ...@@ -1188,6 +1193,8 @@ extract_bit_field (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
can also be extracted with a SUBREG. For this, we need the can also be extracted with a SUBREG. For this, we need the
byte offset of the value in op0. */ byte offset of the value in op0. */
bitpos = bitnum % unit;
offset = bitnum / unit;
byte_offset = bitpos / BITS_PER_UNIT + offset * UNITS_PER_WORD; byte_offset = bitpos / BITS_PER_UNIT + offset * UNITS_PER_WORD;
/* If OP0 is a register, BITPOS must count within a word. /* If OP0 is a register, BITPOS must count within a word.
......
2005-02-06 Richard Sandiford <rsandifo@redhat.com>
* gcc.c-torture/compile/20050206-1.c: New test.
2005-02-03 Andrew Pinski <pinskia@physics.uc.edu> 2005-02-03 Andrew Pinski <pinskia@physics.uc.edu>
PR tree-opt/19768 PR tree-opt/19768
......
unsigned short foo (void)
{
unsigned short u[1] = { 1 };
u[0] = 0;
u[1] = 1;
u[2] = 2;
return u[0] + u[1] + u[2];
}
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