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
This commit is contained in:
Jakub Jelinek 2012-04-25 16:27:08 +02:00 committed by Jakub Jelinek
parent 948e73b3d6
commit f1cc958978
7 changed files with 139 additions and 5 deletions

View File

@ -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.

View File

@ -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. */

View File

@ -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;
}

View File

@ -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.

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}