aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorRichard Sandiford <richard.sandiford@arm.com>2022-08-30 15:43:48 +0100
committerRichard Sandiford <richard.sandiford@arm.com>2022-08-30 15:43:48 +0100
commit1025025b612d632920fe710bb58d36e4d43f3220 (patch)
tree5ea7660a3c830874be57000418cad382253f2dc5 /gcc
parent61c4c989034548f481d1f10198447be27fb9a55f (diff)
downloadgcc-1025025b612d632920fe710bb58d36e4d43f3220.zip
gcc-1025025b612d632920fe710bb58d36e4d43f3220.tar.gz
gcc-1025025b612d632920fe710bb58d36e4d43f3220.tar.bz2
expmed: Fix store_bit_field_1 subreg offset
store_bit_field_1 tries to convert a field assignment into a subreg assignment. Normally it must check that the field occupies a full word (or more specifically, a full REGMODE_NATURAL_SIZE chunk), so that writing to the subreg doesn't clobber any other fields. But it can skip that check if the structure is known to be in an undefined state. The idea was that, in the undefined case, we could rely on simplify_gen_subreg to do the check for a valid subreg, rather than having to repeat the required endianness logic in the caller. Before the addition of the undefined case, the code could use regnum * regsize to get the byte offset, where regnum came from checking that the start was word-aligned. In the undefined case we need to calculate the byte offset explicitly. gcc/ * expmed.cc (store_bit_field_1): Fix byte offset calculation for undefined structures.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/expmed.cc12
1 files changed, 6 insertions, 6 deletions
diff --git a/gcc/expmed.cc b/gcc/expmed.cc
index cdc0adb..6c02c3b 100644
--- a/gcc/expmed.cc
+++ b/gcc/expmed.cc
@@ -794,7 +794,7 @@ store_bit_field_1 (rtx str_rtx, poly_uint64 bitsize, poly_uint64 bitnum,
words or to cope with mode punning between equal-sized modes.
In the latter case, use subreg on the rhs side, not lhs. */
rtx sub;
- HOST_WIDE_INT regnum = 0;
+ poly_uint64 bytenum;
poly_uint64 regsize = REGMODE_NATURAL_SIZE (GET_MODE (op0));
if (known_eq (bitnum, 0U)
&& known_eq (bitsize, GET_MODE_BITSIZE (GET_MODE (op0))))
@@ -808,13 +808,13 @@ store_bit_field_1 (rtx str_rtx, poly_uint64 bitsize, poly_uint64 bitnum,
return true;
}
}
- else if (((constant_multiple_p (bitnum, regsize * BITS_PER_UNIT, &regnum)
- && multiple_p (bitsize, regsize * BITS_PER_UNIT))
- || undefined_p)
+ else if (multiple_p (bitnum, BITS_PER_UNIT, &bytenum)
+ && (undefined_p
+ || (multiple_p (bitnum, regsize * BITS_PER_UNIT)
+ && multiple_p (bitsize, regsize * BITS_PER_UNIT)))
&& known_ge (GET_MODE_BITSIZE (GET_MODE (op0)), bitsize))
{
- sub = simplify_gen_subreg (fieldmode, op0, GET_MODE (op0),
- regnum * regsize);
+ sub = simplify_gen_subreg (fieldmode, op0, GET_MODE (op0), bytenum);
if (sub)
{
if (reverse)