On Sat, 18 Jul 2020, Jakub Jelinek wrote:

> Hi!
> 
> When working on __builtin_bit_cast that needs to handle bitfields too,
> I've made the following change to handle at least some bitfields in
> fold_const_aggregate_ref_1 (those that have integral representative).
> It already handles some, but only those that start and end at byte
> boundaries.
> 
> Bootstrapped/regtested on {x86_64,i686,powerpc64{,le}}-linux, ok for trunk?

OK.

Richard.

> 2020-07-18  Jakub Jelinek  <ja...@redhat.com>
> 
>       PR libstdc++/93121
>       * gimple-fold.c (fold_const_aggregate_ref_1): For COMPONENT_REF
>       of a bitfield not aligned on byte boundaries try to
>       fold_ctor_reference DECL_BIT_FIELD_REPRESENTATIVE if any and
>       adjust it depending on endianity.
> 
>       * gcc.dg/tree-ssa/pr93121-2.c: New test.
> 
> --- gcc/gimple-fold.c.jj      2020-07-13 19:09:33.218871556 +0200
> +++ gcc/gimple-fold.c 2020-07-17 19:17:59.694537680 +0200
> @@ -7189,8 +7189,64 @@ fold_const_aggregate_ref_1 (tree t, tree
>        if (maybe_lt (offset, 0))
>       return NULL_TREE;
>  
> -      return fold_ctor_reference (TREE_TYPE (t), ctor, offset, size,
> -                               base);
> +      tem = fold_ctor_reference (TREE_TYPE (t), ctor, offset, size, base);
> +      if (tem)
> +     return tem;
> +
> +      /* For bit field reads try to read the representative and
> +      adjust.  */
> +      if (TREE_CODE (t) == COMPONENT_REF
> +       && DECL_BIT_FIELD (TREE_OPERAND (t, 1))
> +       && DECL_BIT_FIELD_REPRESENTATIVE (TREE_OPERAND (t, 1)))
> +     {
> +       HOST_WIDE_INT csize, coffset;
> +       tree field = TREE_OPERAND (t, 1);
> +       tree repr = DECL_BIT_FIELD_REPRESENTATIVE (field);
> +       if (INTEGRAL_TYPE_P (TREE_TYPE (repr))
> +           && size.is_constant (&csize)
> +           && offset.is_constant (&coffset)
> +           && (coffset % BITS_PER_UNIT != 0
> +               || csize % BITS_PER_UNIT != 0)
> +           && !reverse
> +           && BYTES_BIG_ENDIAN == WORDS_BIG_ENDIAN)
> +         {
> +           poly_int64 bitoffset;
> +           poly_uint64 field_offset, repr_offset;
> +           if (poly_int_tree_p (DECL_FIELD_OFFSET (field), &field_offset)
> +               && poly_int_tree_p (DECL_FIELD_OFFSET (repr), &repr_offset))
> +             bitoffset = (field_offset - repr_offset) * BITS_PER_UNIT;
> +           else
> +             bitoffset = 0;
> +           bitoffset += (tree_to_uhwi (DECL_FIELD_BIT_OFFSET (field))
> +                         - tree_to_uhwi (DECL_FIELD_BIT_OFFSET (repr)));
> +           HOST_WIDE_INT bitoff;
> +           int diff = (TYPE_PRECISION (TREE_TYPE (repr))
> +                       - TYPE_PRECISION (TREE_TYPE (field)));
> +           if (bitoffset.is_constant (&bitoff)
> +               && bitoff >= 0
> +               && bitoff <= diff)
> +             {
> +               offset -= bitoff;
> +               size = tree_to_uhwi (DECL_SIZE (repr));
> +
> +               tem = fold_ctor_reference (TREE_TYPE (repr), ctor, offset,
> +                                          size, base);
> +               if (tem && TREE_CODE (tem) == INTEGER_CST)
> +                 {
> +                   if (!BYTES_BIG_ENDIAN)
> +                     tem = wide_int_to_tree (TREE_TYPE (field),
> +                                             wi::lrshift (wi::to_wide (tem),
> +                                                          bitoff));
> +                   else
> +                     tem = wide_int_to_tree (TREE_TYPE (field),
> +                                             wi::lrshift (wi::to_wide (tem),
> +                                                          diff - bitoff));
> +                   return tem;
> +                 }
> +             }
> +         }
> +     }
> +      break;
>  
>      case REALPART_EXPR:
>      case IMAGPART_EXPR:
> --- gcc/testsuite/gcc.dg/tree-ssa/pr93121-2.c.jj      2020-07-17 
> 19:47:31.842426096 +0200
> +++ gcc/testsuite/gcc.dg/tree-ssa/pr93121-2.c 2020-07-17 19:48:24.551649910 
> +0200
> @@ -0,0 +1,22 @@
> +/* PR libstdc++/93121 */
> +/* { dg-do compile { target { ilp32 || lp64 } } } */
> +/* { dg-options "-O2 -fdump-tree-optimized" } */
> +
> +union U { int a[3]; struct S { int d; int a : 3; int b : 24; int c : 5; int 
> e; } b; };
> +const union U u = { .a = { 0x7efa3412, 0x5a876543, 0x1eeffeed } };
> +int a, b, c;
> +
> +void
> +foo ()
> +{
> +  a = u.b.a;
> +  b = u.b.b;
> +  c = u.b.c;
> +}
> +
> +/* { dg-final { scan-tree-dump-times "a = 3;" 1 "optimized" { target le } } 
> } */
> +/* { dg-final { scan-tree-dump-times "b = 5303464;" 1 "optimized" { target 
> le } } } */
> +/* { dg-final { scan-tree-dump-times "c = 11;" 1 "optimized" { target le } } 
> } */
> +/* { dg-final { scan-tree-dump-times "a = 2;" 1 "optimized" { target be } } 
> } */
> +/* { dg-final { scan-tree-dump-times "b = -2868438;" 1 "optimized" { target 
> be } } } */
> +/* { dg-final { scan-tree-dump-times "c = 3;" 1 "optimized" { target be } } 
> } */
> 
> 
>       Jakub
> 
> 

-- 
Richard Biener <rguent...@suse.de>
SUSE Software Solutions Germany GmbH, Maxfeldstrasse 5, 90409 Nuernberg,
Germany; GF: Felix Imendörffer; HRB 36809 (AG Nuernberg)

Reply via email to