From 53c615a2769209147ad242d646051954b3a2b8f4 Mon Sep 17 00:00:00 2001 From: Bernd Edlinger Date: Thu, 5 Mar 2015 18:56:37 +0000 Subject: [PATCH] re PR rtl-optimization/65067 (regression on accessing volatile bit field) gcc: 2015-03-05 Bernd Edlinger PR rtl-optimization/65067 * expmed.c (store_bit_field, extract_bit_field): Reworked the strict volatile bitfield handling. testsuite: 2015-03-05 Bernd Edlinger * gcc.target/arm/pr65067.c: New test. From-SVN: r221222 --- gcc/ChangeLog | 6 +++++ gcc/expmed.c | 34 +++++++++++++------------- gcc/testsuite/ChangeLog | 4 +++ gcc/testsuite/gcc.target/arm/pr65067.c | 22 +++++++++++++++++ 4 files changed, 49 insertions(+), 17 deletions(-) create mode 100644 gcc/testsuite/gcc.target/arm/pr65067.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index f78091957da..3ec2d1c7268 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2015-03-05 Bernd Edlinger + + PR rtl-optimization/65067 + * expmed.c (store_bit_field, extract_bit_field): Reworked the + strict volatile bitfield handling. + 2015-03-05 Martin Liska PR ipa/65318 diff --git a/gcc/expmed.c b/gcc/expmed.c index 18e62a000b4..0034203c2f7 100644 --- a/gcc/expmed.c +++ b/gcc/expmed.c @@ -976,7 +976,7 @@ store_bit_field (rtx str_rtx, unsigned HOST_WIDE_INT bitsize, /* 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 (simple_mem_bitfield_p (str_rtx, bitsize, bitnum, fieldmode)) + if (bitsize == GET_MODE_BITSIZE (fieldmode)) { str_rtx = adjust_bitfield_address (str_rtx, fieldmode, bitnum / BITS_PER_UNIT); @@ -984,12 +984,16 @@ store_bit_field (rtx str_rtx, unsigned HOST_WIDE_INT bitsize, } else { + rtx temp; + str_rtx = narrow_bit_field_mem (str_rtx, fieldmode, bitsize, bitnum, &bitnum); - /* Explicitly override the C/C++ memory model; ignore the - bit range so that we can do the access in the mode mandated - by -fstrict-volatile-bitfields instead. */ - store_fixed_bit_field_1 (str_rtx, bitsize, bitnum, value); + temp = copy_to_reg (str_rtx); + if (!store_bit_field_1 (temp, bitsize, bitnum, 0, 0, + fieldmode, value, true)) + gcc_unreachable (); + + emit_move_insn (str_rtx, temp); } return; @@ -1786,24 +1790,20 @@ extract_bit_field (rtx str_rtx, unsigned HOST_WIDE_INT bitsize, if (strict_volatile_bitfield_p (str_rtx, bitsize, bitnum, mode1, 0, 0)) { - rtx result; - /* 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 (simple_mem_bitfield_p (str_rtx, bitsize, bitnum, mode1)) - result = adjust_bitfield_address (str_rtx, mode1, - bitnum / BITS_PER_UNIT); - else + if (bitsize == GET_MODE_BITSIZE(mode1)) { - str_rtx = narrow_bit_field_mem (str_rtx, mode1, bitsize, bitnum, - &bitnum); - result = extract_fixed_bit_field_1 (mode, str_rtx, bitsize, bitnum, - target, unsignedp); + rtx result = adjust_bitfield_address (str_rtx, mode1, + bitnum / BITS_PER_UNIT); + return convert_extracted_bit_field (result, mode, tmode, unsignedp); } - return convert_extracted_bit_field (result, mode, tmode, unsignedp); + str_rtx = narrow_bit_field_mem (str_rtx, mode1, bitsize, bitnum, + &bitnum); + str_rtx = copy_to_reg (str_rtx); } - + return extract_bit_field_1 (str_rtx, bitsize, bitnum, unsignedp, target, mode, tmode, true); } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 09d42b3d851..321db122f76 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2015-03-05 Bernd Edlinger + + * gcc.target/arm/pr65067.c: New test. + 2015-03-05 Martin Liska PR ipa/65318 diff --git a/gcc/testsuite/gcc.target/arm/pr65067.c b/gcc/testsuite/gcc.target/arm/pr65067.c new file mode 100644 index 00000000000..9ddd7bb9e6e --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/pr65067.c @@ -0,0 +1,22 @@ +/* { dg-do compile } */ +/* { dg-options "-mthumb -mcpu=cortex-m3 -O2" } */ + +struct tmp { + unsigned int dummy; + union { + struct { + unsigned int xyz : 1; + unsigned int mode: 3; + unsigned int res : 28; + } bf; + unsigned int wordval; + } reg; +}; + +void set_mode(int mode) +{ + volatile struct tmp *t = (struct tmp *) 0x1000; + t->reg.bf.mode = mode; +} + +/* { dg-final { scan-assembler "bfi" } } */ -- 2.30.2