Commit bd3647bf by Jakub Jelinek Committed by Jakub Jelinek

re PR rtl-optimization/57344 (wrong code with pragma pack(1) and -O1 on x86)

	PR middle-end/57344
	* expmed.c (store_split_bit_field): If op0 is a REG or
	SUBREG of a REG, don't lower unit.  Handle unit not being
	always BITS_PER_WORD.

	* gcc.c-torture/execute/pr57344-1.c: New test.
	* gcc.c-torture/execute/pr57344-2.c: New test.
	* gcc.c-torture/execute/pr57344-3.c: New test.
	* gcc.c-torture/execute/pr57344-4.c: New test.

From-SVN: r199238
parent a55757ea
2013-05-23 Jakub Jelinek <jakub@redhat.com>
PR middle-end/57344
* expmed.c (store_split_bit_field): If op0 is a REG or
SUBREG of a REG, don't lower unit. Handle unit not being
always BITS_PER_WORD.
2013-05-23 Richard Biener <rguenther@suse.de> 2013-05-23 Richard Biener <rguenther@suse.de>
PR rtl-optimization/57341 PR rtl-optimization/57341
......
...@@ -1094,10 +1094,14 @@ store_split_bit_field (rtx op0, unsigned HOST_WIDE_INT bitsize, ...@@ -1094,10 +1094,14 @@ store_split_bit_field (rtx op0, unsigned HOST_WIDE_INT bitsize,
thispos = (bitpos + bitsdone) % unit; thispos = (bitpos + bitsdone) % unit;
/* When region of bytes we can touch is restricted, decrease /* When region of bytes we can touch is restricted, decrease
UNIT close to the end of the region as needed. */ UNIT close to the end of the region as needed. If op0 is a REG
or SUBREG of REG, don't do this, as there can't be data races
on a register and we can expand shorter code in some cases. */
if (bitregion_end if (bitregion_end
&& unit > BITS_PER_UNIT && unit > BITS_PER_UNIT
&& bitpos + bitsdone - thispos + unit > bitregion_end + 1) && bitpos + bitsdone - thispos + unit > bitregion_end + 1
&& !REG_P (op0)
&& (GET_CODE (op0) != SUBREG || !REG_P (SUBREG_REG (op0))))
{ {
unit = unit / 2; unit = unit / 2;
continue; continue;
...@@ -1147,14 +1151,15 @@ store_split_bit_field (rtx op0, unsigned HOST_WIDE_INT bitsize, ...@@ -1147,14 +1151,15 @@ store_split_bit_field (rtx op0, unsigned HOST_WIDE_INT bitsize,
the current word starting from the base register. */ the current word starting from the base register. */
if (GET_CODE (op0) == SUBREG) if (GET_CODE (op0) == SUBREG)
{ {
int word_offset = (SUBREG_BYTE (op0) / UNITS_PER_WORD) + offset; int word_offset = (SUBREG_BYTE (op0) / UNITS_PER_WORD)
+ (offset * unit / BITS_PER_WORD);
enum machine_mode sub_mode = GET_MODE (SUBREG_REG (op0)); enum machine_mode sub_mode = GET_MODE (SUBREG_REG (op0));
if (sub_mode != BLKmode && GET_MODE_SIZE (sub_mode) < UNITS_PER_WORD) if (sub_mode != BLKmode && GET_MODE_SIZE (sub_mode) < UNITS_PER_WORD)
word = word_offset ? const0_rtx : op0; word = word_offset ? const0_rtx : op0;
else else
word = operand_subword_force (SUBREG_REG (op0), word_offset, word = operand_subword_force (SUBREG_REG (op0), word_offset,
GET_MODE (SUBREG_REG (op0))); GET_MODE (SUBREG_REG (op0)));
offset = 0; offset &= BITS_PER_WORD / unit - 1;
} }
else if (REG_P (op0)) else if (REG_P (op0))
{ {
...@@ -1162,8 +1167,9 @@ store_split_bit_field (rtx op0, unsigned HOST_WIDE_INT bitsize, ...@@ -1162,8 +1167,9 @@ store_split_bit_field (rtx op0, unsigned HOST_WIDE_INT bitsize,
if (op0_mode != BLKmode && GET_MODE_SIZE (op0_mode) < UNITS_PER_WORD) if (op0_mode != BLKmode && GET_MODE_SIZE (op0_mode) < UNITS_PER_WORD)
word = offset ? const0_rtx : op0; word = offset ? const0_rtx : op0;
else else
word = operand_subword_force (op0, offset, GET_MODE (op0)); word = operand_subword_force (op0, offset * unit / BITS_PER_WORD,
offset = 0; GET_MODE (op0));
offset &= BITS_PER_WORD / unit - 1;
} }
else else
word = op0; word = op0;
......
2013-05-23 Jakub Jelinek <jakub@redhat.com>
PR middle-end/57344
* gcc.c-torture/execute/pr57344-1.c: New test.
* gcc.c-torture/execute/pr57344-2.c: New test.
* gcc.c-torture/execute/pr57344-3.c: New test.
* gcc.c-torture/execute/pr57344-4.c: New test.
2013-05-23 Richard Biener <rguenther@suse.de> 2013-05-23 Richard Biener <rguenther@suse.de>
PR rtl-optimization/57341 PR rtl-optimization/57341
......
/* PR middle-end/57344 */
struct __attribute__((packed)) S
{
int a : 11;
#if __SIZEOF_INT__ * __CHAR_BIT__ >= 32
int b : 22;
#else
int b : 13;
#endif
char c;
int : 0;
} s[2];
int i;
__attribute__((noinline, noclone)) void
foo (int x)
{
if (x != -3161)
__builtin_abort ();
asm volatile ("" : : : "memory");
}
int
main ()
{
struct S t = { 0, -3161L };
s[1] = t;
for (; i < 1; i++)
foo (s[1].b);
return 0;
}
/* PR middle-end/57344 */
struct __attribute__((packed)) S
{
int a : 27;
#if __SIZEOF_INT__ * __CHAR_BIT__ >= 32
int b : 22;
#else
int b : 13;
#endif
char c;
int : 0;
} s[2];
int i;
__attribute__((noinline, noclone)) void
foo (int x)
{
if (x != -3161)
__builtin_abort ();
asm volatile ("" : : : "memory");
}
int
main ()
{
struct S t = { 0, -3161L };
s[1] = t;
for (; i < 1; i++)
foo (s[1].b);
return 0;
}
/* PR middle-end/57344 */
struct __attribute__((packed)) S
{
long long int a : 43;
long long int b : 22;
char c;
long long int : 0;
} s[2];
int i;
__attribute__((noinline, noclone)) void
foo (long long int x)
{
if (x != -3161LL)
__builtin_abort ();
asm volatile ("" : : : "memory");
}
int
main ()
{
struct S t = { 0, -3161LL };
s[1] = t;
for (; i < 1; i++)
foo (s[1].b);
return 0;
}
/* PR middle-end/57344 */
struct __attribute__((packed)) S
{
long long int a : 59;
long long int b : 54;
char c;
long long int : 0;
} s[2];
int i;
__attribute__((noinline, noclone)) void
foo (long long int x)
{
if (x != -1220975898975746LL)
__builtin_abort ();
asm volatile ("" : : : "memory");
}
int
main ()
{
struct S t = { 0, -1220975898975746LL };
s[1] = t;
for (; i < 1; i++)
foo (s[1].b);
return 0;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment