From bd3647bf76d1d207eaa80c7c6b5a460fecc327a9 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek <jakub@redhat.com> Date: Thu, 23 May 2013 11:17:34 +0200 Subject: [PATCH] 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 --- gcc/ChangeLog | 7 ++++ gcc/expmed.c | 18 +++++++---- gcc/testsuite/ChangeLog | 8 +++++ .../gcc.c-torture/execute/pr57344-1.c | 32 +++++++++++++++++++ .../gcc.c-torture/execute/pr57344-2.c | 32 +++++++++++++++++++ .../gcc.c-torture/execute/pr57344-3.c | 28 ++++++++++++++++ .../gcc.c-torture/execute/pr57344-4.c | 28 ++++++++++++++++ 7 files changed, 147 insertions(+), 6 deletions(-) create mode 100644 gcc/testsuite/gcc.c-torture/execute/pr57344-1.c create mode 100644 gcc/testsuite/gcc.c-torture/execute/pr57344-2.c create mode 100644 gcc/testsuite/gcc.c-torture/execute/pr57344-3.c create mode 100644 gcc/testsuite/gcc.c-torture/execute/pr57344-4.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 503215a741e5..a4bf07a1f92a 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +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> PR rtl-optimization/57341 diff --git a/gcc/expmed.c b/gcc/expmed.c index c85e68cf617a..daadd3def5d0 100644 --- a/gcc/expmed.c +++ b/gcc/expmed.c @@ -1094,10 +1094,14 @@ store_split_bit_field (rtx op0, unsigned HOST_WIDE_INT bitsize, thispos = (bitpos + bitsdone) % unit; /* 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 && 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; continue; @@ -1147,14 +1151,15 @@ store_split_bit_field (rtx op0, unsigned HOST_WIDE_INT bitsize, the current word starting from the base register. */ 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)); if (sub_mode != BLKmode && GET_MODE_SIZE (sub_mode) < UNITS_PER_WORD) word = word_offset ? const0_rtx : op0; else word = operand_subword_force (SUBREG_REG (op0), word_offset, GET_MODE (SUBREG_REG (op0))); - offset = 0; + offset &= BITS_PER_WORD / unit - 1; } else if (REG_P (op0)) { @@ -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) word = offset ? const0_rtx : op0; else - word = operand_subword_force (op0, offset, GET_MODE (op0)); - offset = 0; + word = operand_subword_force (op0, offset * unit / BITS_PER_WORD, + GET_MODE (op0)); + offset &= BITS_PER_WORD / unit - 1; } else word = op0; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index d1c0dda31865..6485a5cfbe01 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,11 @@ +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> PR rtl-optimization/57341 diff --git a/gcc/testsuite/gcc.c-torture/execute/pr57344-1.c b/gcc/testsuite/gcc.c-torture/execute/pr57344-1.c new file mode 100644 index 000000000000..66893269efa5 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/pr57344-1.c @@ -0,0 +1,32 @@ +/* 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; +} diff --git a/gcc/testsuite/gcc.c-torture/execute/pr57344-2.c b/gcc/testsuite/gcc.c-torture/execute/pr57344-2.c new file mode 100644 index 000000000000..9bf60cab8f05 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/pr57344-2.c @@ -0,0 +1,32 @@ +/* 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; +} diff --git a/gcc/testsuite/gcc.c-torture/execute/pr57344-3.c b/gcc/testsuite/gcc.c-torture/execute/pr57344-3.c new file mode 100644 index 000000000000..f9daea6d3a93 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/pr57344-3.c @@ -0,0 +1,28 @@ +/* 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; +} diff --git a/gcc/testsuite/gcc.c-torture/execute/pr57344-4.c b/gcc/testsuite/gcc.c-torture/execute/pr57344-4.c new file mode 100644 index 000000000000..0b2bf152490f --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/pr57344-4.c @@ -0,0 +1,28 @@ +/* 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; +} -- GitLab