From: Richard Sandiford Date: Sun, 6 Feb 2005 15:39:07 +0000 (+0000) Subject: expmed.c (store_bit_field): Make the SUBREG code adjust bitnum. X-Git-Tag: releases/gcc-4.0.0~1057 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=2c58f7dde2bdb003105479ffe316cb7935b711c3;p=thirdparty%2Fgcc.git 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 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index b1a5558fc363..e02434e999df 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,13 @@ +2005-02-06 Richard Sandiford + + * 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 * df.c (df_insn_refs_record): Use XEXP to get the operand of a USE, diff --git a/gcc/expmed.c b/gcc/expmed.c index 87a219d2605f..1a1bdf74b048 100644 --- a/gcc/expmed.c +++ b/gcc/expmed.c @@ -337,8 +337,7 @@ store_bit_field (rtx str_rtx, unsigned HOST_WIDE_INT bitsize, { unsigned int unit = (MEM_P (str_rtx)) ? BITS_PER_UNIT : BITS_PER_WORD; - unsigned HOST_WIDE_INT offset = bitnum / unit; - unsigned HOST_WIDE_INT bitpos = bitnum % unit; + unsigned HOST_WIDE_INT offset, bitpos; rtx op0 = str_rtx; int byte_offset; rtx orig_value; @@ -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 between memory and regs, the higher-numbered regs always get higher addresses. */ - offset += (SUBREG_BYTE (op0) / UNITS_PER_WORD); - /* We used to adjust BITPOS here, but now we do the whole adjustment - right after the loop. */ + bitnum += SUBREG_BYTE (op0) * BITS_PER_UNIT; 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 available. */ if (VECTOR_MODE_P (GET_MODE (op0)) @@ -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 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 + (offset * UNITS_PER_WORD); @@ -1064,8 +1069,7 @@ extract_bit_field (rtx str_rtx, unsigned HOST_WIDE_INT bitsize, { unsigned int unit = (MEM_P (str_rtx)) ? BITS_PER_UNIT : BITS_PER_WORD; - unsigned HOST_WIDE_INT offset = bitnum / unit; - unsigned HOST_WIDE_INT bitpos = bitnum % unit; + unsigned HOST_WIDE_INT offset, bitpos; rtx op0 = str_rtx; rtx spec_target = target; rtx spec_target_subreg = 0; @@ -1080,15 +1084,16 @@ extract_bit_field (rtx str_rtx, unsigned HOST_WIDE_INT bitsize, while (GET_CODE (op0) == SUBREG) { - bitpos += SUBREG_BYTE (op0) * BITS_PER_UNIT; - if (bitpos > unit) - { - offset += (bitpos / unit); - bitpos %= unit; - } + bitnum += SUBREG_BYTE (op0) * BITS_PER_UNIT; 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) && mode == GET_MODE (op0) && bitnum == 0 @@ -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 byte offset of the value in op0. */ + bitpos = bitnum % unit; + offset = bitnum / unit; byte_offset = bitpos / BITS_PER_UNIT + offset * UNITS_PER_WORD; /* If OP0 is a register, BITPOS must count within a word. diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 608b077b2337..2dfc38fff8c2 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2005-02-06 Richard Sandiford + + * gcc.c-torture/compile/20050206-1.c: New test. + 2005-02-03 Andrew Pinski PR tree-opt/19768 diff --git a/gcc/testsuite/gcc.c-torture/compile/20050206-1.c b/gcc/testsuite/gcc.c-torture/compile/20050206-1.c new file mode 100644 index 000000000000..5ea49a6b2389 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/compile/20050206-1.c @@ -0,0 +1,8 @@ +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]; +}