On Tue, 21 May 2013, Jakub Jelinek wrote:

> Hi!
> 
> My PR52979 patch introduced following regression in store_split_bit_field.
> If op0 is a REG or SUBREG, then the code was assuming that unit is still
> BITS_PER_WORD, which isn't the case after PR52979.  This patch changes
> those spots to no longer assume that (second and third hunks).
> The first hunk is just an optimization, I don't see how could we have
> data races on (reg) or (subreg (reg) ...), so by allowing to change whole
> words on those rather than limiting those because of too small bitregion_end
> we can generate smaller RTL out of the expansion (usually combine will
> optimize those back, but for e.g. -O0 it wouldn't).
> 
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk/4.8/4.7?
> 
> 2013-05-21  Jakub Jelinek  <ja...@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.
> 
>       * 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.
> 
> --- gcc/expmed.c.jj   2013-05-14 10:54:58.000000000 +0200
> +++ gcc/expmed.c      2013-05-21 11:59:00.275839242 +0200
> @@ -1094,10 +1094,14 @@ store_split_bit_field (rtx op0, unsigned
>        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))))

I wonder if !REG_P (SUBREG_REG (op0)) can happen - but I guess better
be safe than sorry.  The rest of the patch looks ok to me.

Thus, ok.

Thanks,
Richard.

>       {
>         unit = unit / 2;
>         continue;
> @@ -1147,14 +1151,15 @@ store_split_bit_field (rtx op0, unsigned
>        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
>         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;
> --- gcc/testsuite/gcc.c-torture/execute/pr57344-1.c.jj        2013-05-21 
> 11:38:07.828956569 +0200
> +++ gcc/testsuite/gcc.c-torture/execute/pr57344-1.c   2013-05-21 
> 11:58:21.242061844 +0200
> @@ -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;
> +}
> --- gcc/testsuite/gcc.c-torture/execute/pr57344-2.c.jj        2013-05-21 
> 11:38:13.536922710 +0200
> +++ gcc/testsuite/gcc.c-torture/execute/pr57344-2.c   2013-05-21 
> 11:58:36.119977546 +0200
> @@ -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;
> +}
> --- gcc/testsuite/gcc.c-torture/execute/pr57344-3.c.jj        2013-05-21 
> 11:43:11.157231567 +0200
> +++ gcc/testsuite/gcc.c-torture/execute/pr57344-3.c   2013-05-21 
> 11:55:33.220012554 +0200
> @@ -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;
> +}
> --- gcc/testsuite/gcc.c-torture/execute/pr57344-4.c.jj        2013-05-21 
> 11:55:09.346146134 +0200
> +++ gcc/testsuite/gcc.c-torture/execute/pr57344-4.c   2013-05-21 
> 11:53:31.000000000 +0200
> @@ -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;
> +}
> 
>       Jakub
> 
> 

-- 
Richard Biener <rguent...@suse.de>
SUSE / SUSE Labs
SUSE LINUX Products GmbH - Nuernberg - AG Nuernberg - HRB 16746
GF: Jeff Hawn, Jennifer Guild, Felix Imend

Reply via email to