aboutsummaryrefslogtreecommitdiff
path: root/gcc/expmed.c
diff options
context:
space:
mode:
authorRichard Sandiford <rdsandiford@googlemail.com>2012-11-28 20:13:22 +0000
committerRichard Sandiford <rsandifo@gcc.gnu.org>2012-11-28 20:13:22 +0000
commit00efe3ea3c907b4d7b090da19add210432b3de2c (patch)
treeaaafc068a028daa1ab2ecddaa3afa63e83019d13 /gcc/expmed.c
parent1099bb0a712134f8a43e06407292aa95f27c0e54 (diff)
downloadgcc-00efe3ea3c907b4d7b090da19add210432b3de2c.zip
gcc-00efe3ea3c907b4d7b090da19add210432b3de2c.tar.gz
gcc-00efe3ea3c907b4d7b090da19add210432b3de2c.tar.bz2
re PR middle-end/55438 (tmpdir-gcc.dg-struct-layout-1/t001 - t028, gcc.c-torture/execute/991118-1.c, gcc.c-torture/execute/bf64-1.c, ICE)
gcc/ PR middle-end/55438 * expmed.c (simple_mem_bitfield_p): New function, extracted from store_bit_field_1 and extract_bit_field_1. Use GET_MODE_ALIGNMENT rather than bitsize when checking the alignment. (store_bit_field_1, extract_bit_field_1): Call it. * stor-layout.c (bit_field_mode_iterator::bit_field_mode_iterator): Don't limit ALIGN_. Assume that memory is mapped in chunks of at least word size, regardless of BIGGEST_ALIGNMENT. (bit_field_mode_iterator::get_mode): Use GET_MODE_ALIGNMENT rather than unit when checking the alignment. (get_best_mode): Use GET_MODE_ALIGNMENT. From-SVN: r193905
Diffstat (limited to 'gcc/expmed.c')
-rw-r--r--gcc/expmed.c29
1 files changed, 17 insertions, 12 deletions
diff --git a/gcc/expmed.c b/gcc/expmed.c
index fc29ac4..d75f031 100644
--- a/gcc/expmed.c
+++ b/gcc/expmed.c
@@ -416,6 +416,21 @@ lowpart_bit_field_p (unsigned HOST_WIDE_INT bitnum,
else
return bitnum % BITS_PER_WORD == 0;
}
+
+/* Return true if OP is a memory and if a bitfield of size BITSIZE at
+ bit number BITNUM can be treated as a simple value of mode MODE. */
+
+static bool
+simple_mem_bitfield_p (rtx op0, unsigned HOST_WIDE_INT bitsize,
+ unsigned HOST_WIDE_INT bitnum, enum machine_mode mode)
+{
+ return (MEM_P (op0)
+ && bitnum % BITS_PER_UNIT == 0
+ && bitsize == GET_MODE_BITSIZE (mode)
+ && (!SLOW_UNALIGNED_ACCESS (mode, MEM_ALIGN (op0))
+ || (bitnum % GET_MODE_ALIGNMENT (mode) == 0
+ && MEM_ALIGN (op0) >= GET_MODE_ALIGNMENT (mode))));
+}
/* Try to use instruction INSV to store VALUE into a field of OP0.
BITSIZE and BITNUM are as for store_bit_field. */
@@ -624,12 +639,7 @@ store_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
/* If the target is memory, storing any naturally aligned field can be
done with a simple store. For targets that support fast unaligned
memory, any naturally sized, unit aligned field can be done directly. */
- if (MEM_P (op0)
- && bitnum % BITS_PER_UNIT == 0
- && bitsize == GET_MODE_BITSIZE (fieldmode)
- && (!SLOW_UNALIGNED_ACCESS (fieldmode, MEM_ALIGN (op0))
- || (bitnum % bitsize == 0
- && MEM_ALIGN (op0) % bitsize == 0)))
+ if (simple_mem_bitfield_p (op0, bitsize, bitnum, fieldmode))
{
op0 = adjust_bitfield_address (op0, fieldmode, bitnum / BITS_PER_UNIT);
emit_move_insn (op0, value);
@@ -1455,12 +1465,7 @@ extract_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
/* Extraction of a full MODE1 value can be done with a load as long as
the field is on a byte boundary and is sufficiently aligned. */
- if (MEM_P (op0)
- && bitnum % BITS_PER_UNIT == 0
- && bitsize == GET_MODE_BITSIZE (mode1)
- && (!SLOW_UNALIGNED_ACCESS (mode1, MEM_ALIGN (op0))
- || (bitnum % bitsize == 0
- && MEM_ALIGN (op0) % bitsize == 0)))
+ if (simple_mem_bitfield_p (op0, bitsize, bitnum, mode1))
{
op0 = adjust_bitfield_address (op0, mode1, bitnum / BITS_PER_UNIT);
return convert_extracted_bit_field (op0, mode, tmode, unsignedp);