Which gcc version does this patch apply to?

Thanks!


Bugzilla from ja...@redhat.com wrote:
> 
> Hi!
> 
> This patch changes get_best_mode, so that it doesn't suggest using larger
> modes if it means it could clobber variables located after the containing
> one.
> 
> On the attached testcase on x86_64, the structure is 12 bytes wide,
> and the last bitfield occupies 14 bits in the bytes 8 and 9 from the
> beginning of the structure, then there are 2 padding bytes.
> get_best_mode returns DImode as preferred way to store the structure,
> which means it reads and stores not just the 2 remaining bits in
> the 9th byte and two padding bytes, but also for unrelated bytes
> afterwards.
> The aliasing code, when comparing mem access that stores to that bitfield
> using DImode and another store to the following 32-bit variable, sees
> both stores are to different variables and say they must not alias.
> So we end up incorrect:
>       movq    e+8(%rip), %rax
>       movl    $2, f(%rip)
>       andq    $-16384, %rax
>       movq    %rax, e+8(%rip)
> instead of:
>       movl    e+8(%rip), %eax
>       movl    $2, f(%rip)
>       andl    $-16384, %eax
>       movl    %eax, e+8(%rip)
> (with the patch) or:
>         movq    e+8(%rip), %rax
>         andq    $-16384, %rax
>         movq    %rax, e+8(%rip)
>         movl    $2, f(%rip)
> (if aliasing didn't say accesses to e and f don't alias).
> 
> This patch fixes this by passing get_best_mode the type of the containing
> object, so get_best_mode can better decide what mode to use (the intent
> is mainly for Aldy to do something more strict for C++0x memory model,
> currently it just looks at TYPE_SIZE).
> 
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk
> and after a while to 4.6?
> 
> I've also done instrumented bootstrap/regtest on both of these targets,
> which showed that the patch only makes difference in get_best_mode
> return value on libmudflap/testsuite/libmudflap.c/fail38-frag.c (main)
> (both -m32 and -m64) and on the two newly added testcases (only -m64).
> 
> 2011-04-01  Jakub Jelinek  <ja...@redhat.com>
> 
>       PR middle-end/48124
>       * stor-layout.c (get_best_mode): Add TYPE argument, if non-NULL
>       and bitpos + tmode's bitsize is bigger than TYPE_SIZE, don't
>       use tmode as wider_mode.
>       * rtl.h (get_best_mode): New prototype.
>       * machmode.h (get_best_mode): Remove prototype.
>       * expmed.c (store_fixed_bit_field, store_split_bit_field,
>       store_bit_field_1): Add ORIG_MEM argument, pass it down and
>       pass its MEM_EXPR's type to get_best_mode.
>       (store_bit_field): Pass str_rtx as ORIG_MEM to store_bit_field_1
>       if it is a MEM.
>       (extract_bit_field_1, extract_fixed_bit_field): Pass NULL as
>       last argument to get_best_mode.
>       * expr.c (optimize_bitfield_assignment_op): Pass MEM_EXPR (str_rtx)
>       type as last argument to get_best_mode.
>       * fold-const.c (optimize_bit_field_compare, fold_truthop): Pass
>       NULL as last argument to get_best_mode.
> 
>       * gcc.c-torture/execute/pr48124.c: New test.
>       * gcc.dg/pr48124.c: New test.
> 
> --- gcc/stor-layout.c.jj      2011-03-11 12:16:39.000000000 +0100
> +++ gcc/stor-layout.c 2011-03-31 15:58:05.000000000 +0200
> @@ -2445,7 +2445,8 @@ fixup_unsigned_type (tree type)
>  
>  enum machine_mode
>  get_best_mode (int bitsize, int bitpos, unsigned int align,
> -            enum machine_mode largest_mode, int volatilep)
> +            enum machine_mode largest_mode, int volatilep,
> +            tree type)
>  {
>    enum machine_mode mode;
>    unsigned int unit = 0;
> @@ -2484,7 +2485,12 @@ get_best_mode (int bitsize, int bitpos, 
>             && unit <= BITS_PER_WORD
>             && unit <= MIN (align, BIGGEST_ALIGNMENT)
>             && (largest_mode == VOIDmode
> -               || unit <= GET_MODE_BITSIZE (largest_mode)))
> +               || unit <= GET_MODE_BITSIZE (largest_mode))
> +           && (type == NULL_TREE
> +               || !host_integerp (TYPE_SIZE (type), 1)
> +               || bitpos + (unsigned HOST_WIDE_INT) GET_MODE_BITSIZE (tmode)
> +                  <= (unsigned HOST_WIDE_INT)
> +                     tree_low_cst (TYPE_SIZE (type), 1)))
>           wide_mode = tmode;
>       }
>  
> --- gcc/rtl.h.jj      2011-03-31 08:51:04.000000000 +0200
> +++ gcc/rtl.h 2011-03-31 14:07:18.000000000 +0200
> @@ -2525,6 +2525,11 @@ extern bool expensive_function_p (int);
>  extern unsigned int variable_tracking_main (void);
>  
>  /* In stor-layout.c.  */
> +
> +/* Find the best mode to use to access a bit field.  */
> +extern enum machine_mode get_best_mode (int, int, unsigned int,
> +                                     enum machine_mode, int, tree);
> +
>  extern void get_mode_bounds (enum machine_mode, int, enum machine_mode,
>                            rtx *, rtx *);
>  
> --- gcc/machmode.h.jj 2011-01-06 10:21:52.000000000 +0100
> +++ gcc/machmode.h    2011-03-31 14:06:54.000000000 +0200
> @@ -246,11 +246,6 @@ extern enum machine_mode int_mode_for_mo
>  
>  extern enum machine_mode mode_for_vector (enum machine_mode, unsigned);
>  
> -/* Find the best mode to use to access a bit field.  */
> -
> -extern enum machine_mode get_best_mode (int, int, unsigned int,
> -                                     enum machine_mode, int);
> -
>  /* Determine alignment, 1<=result<=BIGGEST_ALIGNMENT.  */
>  
>  extern CONST_MODE_BASE_ALIGN unsigned char
> mode_base_align[NUM_MACHINE_MODES];
> --- gcc/expmed.c.jj   2011-03-31 08:50:43.000000000 +0200
> +++ gcc/expmed.c      2011-03-31 16:21:25.000000000 +0200
> @@ -47,9 +47,9 @@ struct target_expmed *this_target_expmed
>  
>  static void store_fixed_bit_field (rtx, unsigned HOST_WIDE_INT,
>                                  unsigned HOST_WIDE_INT,
> -                                unsigned HOST_WIDE_INT, rtx);
> +                                unsigned HOST_WIDE_INT, rtx, rtx);
>  static void store_split_bit_field (rtx, unsigned HOST_WIDE_INT,
> -                                unsigned HOST_WIDE_INT, rtx);
> +                                unsigned HOST_WIDE_INT, rtx, rtx);
>  static rtx extract_fixed_bit_field (enum machine_mode, rtx,
>                                   unsigned HOST_WIDE_INT,
>                                   unsigned HOST_WIDE_INT,
> @@ -334,7 +334,7 @@ mode_for_extraction (enum extraction_pat
>  static bool
>  store_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
>                  unsigned HOST_WIDE_INT bitnum, enum machine_mode fieldmode,
> -                rtx value, bool fallback_p)
> +                rtx value, bool fallback_p, rtx orig_mem)
>  {
>    unsigned int unit
>      = (MEM_P (str_rtx)) ? BITS_PER_UNIT : BITS_PER_WORD;
> @@ -542,7 +542,7 @@ store_bit_field_1 (rtx str_rtx, unsigned
>         if (!store_bit_field_1 (op0, MIN (BITS_PER_WORD,
>                                           bitsize - i * BITS_PER_WORD),
>                                 bitnum + bit_offset, word_mode,
> -                               value_word, fallback_p))
> +                               value_word, fallback_p, orig_mem))
>           {
>             delete_insns_since (last);
>             return false;
> @@ -714,10 +714,18 @@ store_bit_field_1 (rtx str_rtx, unsigned
>        if (GET_MODE (op0) == BLKmode
>         || (op_mode != MAX_MACHINE_MODE
>             && GET_MODE_SIZE (GET_MODE (op0)) > GET_MODE_SIZE (op_mode)))
> -     bestmode = get_best_mode (bitsize, bitnum, MEM_ALIGN (op0),
> +     bestmode = get_best_mode (bitsize,
> +                               bitnum + (orig_mem && MEM_EXPR (orig_mem)
> +                                         && MEM_OFFSET (orig_mem)
> +                                         ? INTVAL (MEM_OFFSET (orig_mem))
> +                                         : 0),
> +                               MEM_ALIGN (op0),
>                                 (op_mode == MAX_MACHINE_MODE
>                                  ? VOIDmode : op_mode),
> -                               MEM_VOLATILE_P (op0));
> +                               MEM_VOLATILE_P (op0),
> +                               orig_mem && MEM_EXPR (orig_mem)
> +                               ? TREE_TYPE (MEM_EXPR (orig_mem))
> +                               : NULL_TREE);
>        else
>       bestmode = GET_MODE (op0);
>  
> @@ -743,7 +751,7 @@ store_bit_field_1 (rtx str_rtx, unsigned
>            the unit.  */
>         tempreg = copy_to_reg (xop0);
>         if (store_bit_field_1 (tempreg, bitsize, xbitpos,
> -                              fieldmode, orig_value, false))
> +                              fieldmode, orig_value, false, NULL_RTX))
>           {
>             emit_move_insn (xop0, tempreg);
>             return true;
> @@ -755,7 +763,7 @@ store_bit_field_1 (rtx str_rtx, unsigned
>    if (!fallback_p)
>      return false;
>  
> -  store_fixed_bit_field (op0, offset, bitsize, bitpos, value);
> +  store_fixed_bit_field (op0, offset, bitsize, bitpos, value, orig_mem);
>    return true;
>  }
>  
> @@ -769,7 +777,8 @@ store_bit_field (rtx str_rtx, unsigned H
>                unsigned HOST_WIDE_INT bitnum, enum machine_mode fieldmode,
>                rtx value)
>  {
> -  if (!store_bit_field_1 (str_rtx, bitsize, bitnum, fieldmode, value,
> true))
> +  if (!store_bit_field_1 (str_rtx, bitsize, bitnum, fieldmode, value,
> true,
> +                       MEM_P (str_rtx) ? str_rtx : NULL_RTX))
>      gcc_unreachable ();
>  }
>  
> @@ -785,7 +794,7 @@ store_bit_field (rtx str_rtx, unsigned H
>  static void
>  store_fixed_bit_field (rtx op0, unsigned HOST_WIDE_INT offset,
>                      unsigned HOST_WIDE_INT bitsize,
> -                    unsigned HOST_WIDE_INT bitpos, rtx value)
> +                    unsigned HOST_WIDE_INT bitpos, rtx value, rtx orig_mem)
>  {
>    enum machine_mode mode;
>    unsigned int total_bits = BITS_PER_WORD;
> @@ -806,7 +815,7 @@ store_fixed_bit_field (rtx op0, unsigned
>        /* Special treatment for a bit field split across two registers. 
> */
>        if (bitsize + bitpos > BITS_PER_WORD)
>       {
> -       store_split_bit_field (op0, bitsize, bitpos, value);
> +       store_split_bit_field (op0, bitsize, bitpos, value, NULL_RTX);
>         return;
>       }
>      }
> @@ -827,15 +836,21 @@ store_fixed_bit_field (rtx op0, unsigned
>         && flag_strict_volatile_bitfields > 0)
>       mode = GET_MODE (op0);
>        else
> -     mode = get_best_mode (bitsize, bitpos + offset * BITS_PER_UNIT,
> -                           MEM_ALIGN (op0), mode, MEM_VOLATILE_P (op0));
> +     mode = get_best_mode (bitsize,
> +                           bitpos + offset * BITS_PER_UNIT
> +                           + (orig_mem && MEM_EXPR (orig_mem)
> +                              && MEM_OFFSET (orig_mem)
> +                              ? INTVAL (MEM_OFFSET (orig_mem)) : 0),
> +                           MEM_ALIGN (op0), mode, MEM_VOLATILE_P (op0),
> +                           orig_mem && MEM_EXPR (orig_mem)
> +                           ? TREE_TYPE (MEM_EXPR (orig_mem)) : NULL_TREE);
>  
>        if (mode == VOIDmode)
>       {
>         /* The only way this should occur is if the field spans word
>            boundaries.  */
>         store_split_bit_field (op0, bitsize, bitpos + offset * BITS_PER_UNIT,
> -                              value);
> +                              value, orig_mem);
>         return;
>       }
>  
> @@ -955,7 +970,7 @@ store_fixed_bit_field (rtx op0, unsigned
>  
>  static void
>  store_split_bit_field (rtx op0, unsigned HOST_WIDE_INT bitsize,
> -                    unsigned HOST_WIDE_INT bitpos, rtx value)
> +                    unsigned HOST_WIDE_INT bitpos, rtx value, rtx orig_mem)
>  {
>    unsigned int unit;
>    unsigned int bitsdone = 0;
> @@ -1060,7 +1075,7 @@ store_split_bit_field (rtx op0, unsigned
>        /* OFFSET is in UNITs, and UNIT is in bits.
>           store_fixed_bit_field wants offset in bytes.  */
>        store_fixed_bit_field (word, offset * unit / BITS_PER_UNIT,
> thissize,
> -                          thispos, part);
> +                          thispos, part, orig_mem);
>        bitsdone += thissize;
>      }
>  }
> @@ -1511,7 +1526,7 @@ extract_bit_field_1 (rtx str_rtx, unsign
>       bestmode = get_best_mode (bitsize, bitnum, MEM_ALIGN (op0),
>                                 (ext_mode == MAX_MACHINE_MODE
>                                  ? VOIDmode : ext_mode),
> -                               MEM_VOLATILE_P (op0));
> +                               MEM_VOLATILE_P (op0), NULL_TREE);
>        else
>       bestmode = GET_MODE (op0);
>  
> @@ -1635,7 +1650,8 @@ extract_fixed_bit_field (enum machine_mo
>       }
>        else
>       mode = get_best_mode (bitsize, bitpos + offset * BITS_PER_UNIT,
> -                           MEM_ALIGN (op0), word_mode, MEM_VOLATILE_P (op0));
> +                           MEM_ALIGN (op0), word_mode, MEM_VOLATILE_P (op0),
> +                           NULL_TREE);
>  
>        if (mode == VOIDmode)
>       /* The only way this should occur is if the field spans word
> --- gcc/expr.c.jj     2011-03-31 08:51:03.000000000 +0200
> +++ gcc/expr.c        2011-03-31 16:23:36.000000000 +0200
> @@ -3997,8 +3997,13 @@ optimize_bitfield_assignment_op (unsigne
>  
>        if (str_bitsize == 0 || str_bitsize > BITS_PER_WORD)
>       str_mode = word_mode;
> -      str_mode = get_best_mode (bitsize, bitpos,
> -                             MEM_ALIGN (str_rtx), str_mode, 0);
> +      str_mode = get_best_mode (bitsize,
> +                             bitpos + (MEM_EXPR (str_rtx)
> +                                       && MEM_OFFSET (str_rtx)
> +                                       ? INTVAL (MEM_OFFSET (str_rtx)) : 0),
> +                             MEM_ALIGN (str_rtx), str_mode, 0,
> +                             MEM_EXPR (str_rtx)
> +                             ? TREE_TYPE (MEM_EXPR (str_rtx)) : NULL_TREE);
>        if (str_mode == VOIDmode)
>       return false;
>        str_bitsize = GET_MODE_BITSIZE (str_mode);
> --- gcc/fold-const.c.jj       2011-03-31 08:51:02.000000000 +0200
> +++ gcc/fold-const.c  2011-03-31 15:29:59.000000000 +0200
> @@ -3411,7 +3411,7 @@ optimize_bit_field_compare (location_t l
>                          const_p ? TYPE_ALIGN (TREE_TYPE (linner))
>                          : MIN (TYPE_ALIGN (TREE_TYPE (linner)),
>                                 TYPE_ALIGN (TREE_TYPE (rinner))),
> -                        word_mode, lvolatilep || rvolatilep);
> +                        word_mode, lvolatilep || rvolatilep, NULL_TREE);
>    if (nmode == VOIDmode)
>      return 0;
>  
> @@ -5237,7 +5237,7 @@ fold_truthop (location_t loc, enum tree_
>    end_bit = MAX (ll_bitpos + ll_bitsize, rl_bitpos + rl_bitsize);
>    lnmode = get_best_mode (end_bit - first_bit, first_bit,
>                         TYPE_ALIGN (TREE_TYPE (ll_inner)), word_mode,
> -                       volatilep);
> +                       volatilep, NULL_TREE);
>    if (lnmode == VOIDmode)
>      return 0;
>  
> @@ -5302,7 +5302,7 @@ fold_truthop (location_t loc, enum tree_
>        end_bit = MAX (lr_bitpos + lr_bitsize, rr_bitpos + rr_bitsize);
>        rnmode = get_best_mode (end_bit - first_bit, first_bit,
>                             TYPE_ALIGN (TREE_TYPE (lr_inner)), word_mode,
> -                           volatilep);
> +                           volatilep, NULL_TREE);
>        if (rnmode == VOIDmode)
>       return 0;
>  
> --- gcc/testsuite/gcc.c-torture/execute/pr48124.c.jj  2011-04-01
> 10:53:07.000000000 +0200
> +++ gcc/testsuite/gcc.c-torture/execute/pr48124.c     2011-04-01
> 10:53:26.000000000 +0200
> @@ -0,0 +1,32 @@
> +/* PR middle-end/48124 */
> +
> +extern void abort (void);
> +
> +struct S
> +{
> +  signed a : 26;
> +  signed b : 16;
> +  signed c : 10;
> +  volatile signed d : 14;
> +};
> +
> +static struct S e = { 0, 0, 0, 1 };
> +static int f = 1;
> +
> +void __attribute__((noinline))
> +foo (void)
> +{
> +  e.d = 0;
> +  f = 2;
> +}
> +
> +int
> +main ()
> +{
> +  if (e.a || e.b || e.c || e.d != 1 || f != 1)
> +    abort ();
> +  foo ();
> +  if (e.a || e.b || e.c || e.d || f != 2)
> +    abort ();
> +  return 0;
> +}
> --- gcc/testsuite/gcc.dg/pr48124.c.jj 2011-04-01 10:52:55.000000000 +0200
> +++ gcc/testsuite/gcc.dg/pr48124.c    2011-04-01 10:53:40.000000000 +0200
> @@ -0,0 +1,34 @@
> +/* PR middle-end/48124 */
> +/* { dg-do run } */
> +/* { dg-options "-Os -fno-toplevel-reorder" } */
> +
> +extern void abort (void);
> +
> +struct S
> +{
> +  signed a : 26;
> +  signed b : 16;
> +  signed c : 10;
> +  volatile signed d : 14;
> +};
> +
> +static struct S e = { 0, 0, 0, 1 };
> +static int f = 1;
> +
> +void __attribute__((noinline))
> +foo (void)
> +{
> +  e.d = 0;
> +  f = 2;
> +}
> +
> +int
> +main ()
> +{
> +  if (e.a || e.b || e.c || e.d != 1 || f != 1)
> +    abort ();
> +  foo ();
> +  if (e.a || e.b || e.c || e.d || f != 2)
> +    abort ();
> +  return 0;
> +}
> 
>       Jakub
> 
> 

-- 
View this message in context: 
http://old.nabble.com/-PATCH--Avoid-bitfield-stores-to-clobber-adjacent-variables-%28PR-middle-end-48124%29-tp31296214p34450067.html
Sent from the gcc - patches mailing list archive at Nabble.com.

Reply via email to