* [PATCH] gimple-fold: Handle bitfields in fold_const_aggregate_ref_1 [PR93121]
@ 2020-07-18 8:17 Jakub Jelinek
2020-07-20 8:16 ` Richard Biener
0 siblings, 1 reply; 2+ messages in thread
From: Jakub Jelinek @ 2020-07-18 8:17 UTC (permalink / raw)
To: Richard Biener; +Cc: gcc-patches
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?
2020-07-18 Jakub Jelinek <jakub@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
^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: [PATCH] gimple-fold: Handle bitfields in fold_const_aggregate_ref_1 [PR93121]
2020-07-18 8:17 [PATCH] gimple-fold: Handle bitfields in fold_const_aggregate_ref_1 [PR93121] Jakub Jelinek
@ 2020-07-20 8:16 ` Richard Biener
0 siblings, 0 replies; 2+ messages in thread
From: Richard Biener @ 2020-07-20 8:16 UTC (permalink / raw)
To: Jakub Jelinek; +Cc: gcc-patches
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 <jakub@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 <rguenther@suse.de>
SUSE Software Solutions Germany GmbH, Maxfeldstrasse 5, 90409 Nuernberg,
Germany; GF: Felix Imendörffer; HRB 36809 (AG Nuernberg)
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2020-07-20 8:16 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-07-18 8:17 [PATCH] gimple-fold: Handle bitfields in fold_const_aggregate_ref_1 [PR93121] Jakub Jelinek
2020-07-20 8:16 ` Richard Biener
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).