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)