diff options
author | Jakub Jelinek <jakub@redhat.com> | 2012-04-25 16:27:08 +0200 |
---|---|---|
committer | Jakub Jelinek <jakub@gcc.gnu.org> | 2012-04-25 16:27:08 +0200 |
commit | f1cc958978c4b3a76ccf96571972f95963c9f0ea (patch) | |
tree | 81ecc613d94b359b676a0ac3492e351643109575 | |
parent | 948e73b3d6a3d10ada7c0240bfbfa4aef147f59d (diff) | |
download | gcc-f1cc958978c4b3a76ccf96571972f95963c9f0ea.zip gcc-f1cc958978c4b3a76ccf96571972f95963c9f0ea.tar.gz gcc-f1cc958978c4b3a76ccf96571972f95963c9f0ea.tar.bz2 |
re PR tree-optimization/52979 (likely wrong code bug w/packed bitfields)
PR middle-end/52979
* stor-layout.c (get_best_mode): Don't return mode with bitsize
larger than maxbits. Don't compute maxbits modulo align.
Also check that unit bytes long store at bitpos / unit * unit
doesn't affect bits beyond bitregion_end.
* expmed.c (store_bit_field_1): Avoid trying insv if OP_MODE MEM
would not fit into bitregion_start ... bitregion_end + 1 bit
region.
(store_split_bit_field): Decrease unit close to end of bitregion_end
if access is restricted in order to avoid mutual recursion.
* gcc.c-torture/compile/pr52979-1.c: New test.
* gcc.c-torture/execute/pr52979-1.c: New test.
* gcc.c-torture/execute/pr52979-2.c: New test.
From-SVN: r186819
-rw-r--r-- | gcc/ChangeLog | 11 | ||||
-rw-r--r-- | gcc/expmed.c | 20 | ||||
-rw-r--r-- | gcc/stor-layout.c | 11 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/testsuite/gcc.c-torture/compile/pr52979-1.c | 15 | ||||
-rw-r--r-- | gcc/testsuite/gcc.c-torture/execute/pr52979-1.c | 40 | ||||
-rw-r--r-- | gcc/testsuite/gcc.c-torture/execute/pr52979-2.c | 40 |
7 files changed, 139 insertions, 5 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 9edaf93..d5154ec 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,16 @@ 2012-04-25 Jakub Jelinek <jakub@redhat.com> + PR middle-end/52979 + * stor-layout.c (get_best_mode): Don't return mode with bitsize + larger than maxbits. Don't compute maxbits modulo align. + Also check that unit bytes long store at bitpos / unit * unit + doesn't affect bits beyond bitregion_end. + * expmed.c (store_bit_field_1): Avoid trying insv if OP_MODE MEM + would not fit into bitregion_start ... bitregion_end + 1 bit + region. + (store_split_bit_field): Decrease unit close to end of bitregion_end + if access is restricted in order to avoid mutual recursion. + PR tree-optimization/53058 * double-int.h (double_int_max_value, double_int_min_value): New prototypes. diff --git a/gcc/expmed.c b/gcc/expmed.c index aa24fbf..a0a0960 100644 --- a/gcc/expmed.c +++ b/gcc/expmed.c @@ -640,7 +640,13 @@ store_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize, && !(MEM_P (op0) && MEM_VOLATILE_P (op0) && flag_strict_volatile_bitfields > 0) && ! ((REG_P (op0) || GET_CODE (op0) == SUBREG) - && (bitsize + bitpos > GET_MODE_BITSIZE (op_mode)))) + && (bitsize + bitpos > GET_MODE_BITSIZE (op_mode))) + /* Do not use insv if the bit region is restricted and + op_mode integer at offset doesn't fit into the + restricted region. */ + && !(MEM_P (op0) && bitregion_end + && bitnum - bitpos + GET_MODE_BITSIZE (op_mode) + > bitregion_end + 1)) { struct expand_operand ops[4]; int xbitpos = bitpos; @@ -760,7 +766,7 @@ store_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize, || GET_MODE_BITSIZE (GET_MODE (op0)) > maxbits || (op_mode != MAX_MACHINE_MODE && GET_MODE_SIZE (GET_MODE (op0)) > GET_MODE_SIZE (op_mode))) - bestmode = get_best_mode (bitsize, bitnum, + bestmode = get_best_mode (bitsize, bitnum, bitregion_start, bitregion_end, MEM_ALIGN (op0), (op_mode == MAX_MACHINE_MODE @@ -1096,6 +1102,16 @@ store_split_bit_field (rtx op0, unsigned HOST_WIDE_INT bitsize, offset = (bitpos + bitsdone) / unit; thispos = (bitpos + bitsdone) % unit; + /* When region of bytes we can touch is restricted, decrease + UNIT close to the end of the region as needed. */ + if (bitregion_end + && unit > BITS_PER_UNIT + && bitpos + bitsdone - thispos + unit > bitregion_end + 1) + { + unit = unit / 2; + continue; + } + /* THISSIZE must not overrun a word boundary. Otherwise, store_fixed_bit_field will call us again, and we will mutually recurse forever. */ diff --git a/gcc/stor-layout.c b/gcc/stor-layout.c index d79be14..e72e7f3 100644 --- a/gcc/stor-layout.c +++ b/gcc/stor-layout.c @@ -2624,7 +2624,7 @@ get_best_mode (int bitsize, int bitpos, if (!bitregion_end) maxbits = MAX_FIXED_MODE_SIZE; else - maxbits = (bitregion_end - bitregion_start) % align + 1; + maxbits = bitregion_end - bitregion_start + 1; /* Find the narrowest integer mode that contains the bit field. */ for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT); mode != VOIDmode; @@ -2645,7 +2645,10 @@ get_best_mode (int bitsize, int bitpos, (Though at least one Unix compiler ignores this problem: that on the Sequent 386 machine. */ || MIN (unit, BIGGEST_ALIGNMENT) > align - || (largest_mode != VOIDmode && unit > GET_MODE_BITSIZE (largest_mode))) + || (largest_mode != VOIDmode && unit > GET_MODE_BITSIZE (largest_mode)) + || unit > maxbits + || (bitregion_end + && bitpos - (bitpos % unit) + unit > bitregion_end + 1)) return VOIDmode; if ((SLOW_BYTE_ACCESS && ! volatilep) @@ -2663,7 +2666,9 @@ get_best_mode (int bitsize, int bitpos, && unit <= MIN (align, BIGGEST_ALIGNMENT) && unit <= maxbits && (largest_mode == VOIDmode - || unit <= GET_MODE_BITSIZE (largest_mode))) + || unit <= GET_MODE_BITSIZE (largest_mode)) + && (bitregion_end == 0 + || bitpos - (bitpos % unit) + unit <= bitregion_end + 1)) wide_mode = tmode; } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index d479cd6..b7fe632 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2012-04-25 Jakub Jelinek <jakub@redhat.com> + + PR middle-end/52979 + * gcc.c-torture/compile/pr52979-1.c: New test. + * gcc.c-torture/execute/pr52979-1.c: New test. + * gcc.c-torture/execute/pr52979-2.c: New test. + 2012-04-25 Richard Guenther <rguenther@suse.de> * gcc.target/i386/l_fma_float_5.c: Adjust. diff --git a/gcc/testsuite/gcc.c-torture/compile/pr52979-1.c b/gcc/testsuite/gcc.c-torture/compile/pr52979-1.c new file mode 100644 index 0000000..c703073 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/compile/pr52979-1.c @@ -0,0 +1,15 @@ +/* PR middle-end/52979 */ + +struct S +{ + unsigned int a : 16, b : 16, c : 16, d : 16, e : 14; + unsigned int f : 4, g : 14, h : 8; + char i; + int j; +}; + +void +foo (struct S *s) +{ + s->f = 1; +} diff --git a/gcc/testsuite/gcc.c-torture/execute/pr52979-1.c b/gcc/testsuite/gcc.c-torture/execute/pr52979-1.c new file mode 100644 index 0000000..246b1fd --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/pr52979-1.c @@ -0,0 +1,40 @@ +/* PR middle-end/52979 */ + +extern void abort (void); +int c, d, e; + +void +foo (void) +{ +} + +struct __attribute__((packed)) S { int g : 31; int h : 6; }; +struct S a = { 1 }; +static struct S b = { 1 }; + +void +bar (void) +{ + a.h = 1; + struct S f = { }; + b = f; + e = 0; + if (d) + c = a.g; +} + +void +baz (void) +{ + bar (); + a = b; +} + +int +main () +{ + baz (); + if (a.g) + abort (); + return 0; +} diff --git a/gcc/testsuite/gcc.c-torture/execute/pr52979-2.c b/gcc/testsuite/gcc.c-torture/execute/pr52979-2.c new file mode 100644 index 0000000..52f5bb8 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/pr52979-2.c @@ -0,0 +1,40 @@ +/* PR middle-end/52979 */ + +extern void abort (void); +int c, d, e; + +void +foo (void) +{ +} + +struct __attribute__((packed)) S { int g : 31; int h : 6; }; +static struct S b = { 1 }; +struct S a = { 1 }; + +void +bar (void) +{ + a.h = 1; + struct S f = { }; + b = f; + e = 0; + if (d) + c = a.g; +} + +void +baz (void) +{ + bar (); + a = b; +} + +int +main () +{ + baz (); + if (a.g) + abort (); + return 0; +} |