diff options
author | Eric Botcazou <ebotcazou@adacore.com> | 2023-01-11 15:58:47 +0100 |
---|---|---|
committer | Eric Botcazou <ebotcazou@adacore.com> | 2023-01-11 16:03:25 +0100 |
commit | 3e1cba12a8d71e70235a9a9b8f1a237a561db3e7 (patch) | |
tree | ab50dad9a88b4fbfaf9d650658644084fad4bc95 /gcc | |
parent | de99049f6fe5341024d4d939ac50d063280f90db (diff) | |
download | gcc-3e1cba12a8d71e70235a9a9b8f1a237a561db3e7.zip gcc-3e1cba12a8d71e70235a9a9b8f1a237a561db3e7.tar.gz gcc-3e1cba12a8d71e70235a9a9b8f1a237a561db3e7.tar.bz2 |
Fix problematic interaction between bitfields, unions, SSO and SRA
The handling of bitfields by the SRA pass is peculiar and this must be taken
into account to support the scalar_storage_order attribute.
gcc/
PR tree-optimization/108199
* tree-sra.cc (sra_modify_expr): Deal with reverse storage order
for bit-field references.
gcc/testsuite/
* gcc.dg/sso-17.c: New test.
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/testsuite/gcc.dg/sso-17.c | 52 | ||||
-rw-r--r-- | gcc/tree-sra.cc | 18 |
2 files changed, 69 insertions, 1 deletions
diff --git a/gcc/testsuite/gcc.dg/sso-17.c b/gcc/testsuite/gcc.dg/sso-17.c new file mode 100644 index 0000000..67e2d37 --- /dev/null +++ b/gcc/testsuite/gcc.dg/sso-17.c @@ -0,0 +1,52 @@ +/* { dg-do run } */ +/* { dg-options "-O2" } */ + +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ +#define REV_ENDIANNESS __attribute__((scalar_storage_order("big-endian"))) +#else +#define REV_ENDIANNESS __attribute__((scalar_storage_order("little-endian"))) +#endif + +typedef unsigned long long u64; + +union DST { + u64 val; + + struct { + u64 x : 1; + u64 y : 1; + u64 r: 62; + } REV_ENDIANNESS; +} REV_ENDIANNESS; + + +struct SRC { + u64 a; +} REV_ENDIANNESS; + +[[gnu::noipa]] +void foo () {__builtin_abort();} + +[[gnu::noinline]] +int bar(struct SRC *src) +{ + union DST dst; + + dst.val = src->a; + + if (dst.y) { + foo(); + } + return 0; +} + +int main(void) +{ +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + struct SRC t = {-1ull & (~(0x01ull<<62))}; +#else + struct SRC t = {-1ull & (~(0x01ull<<1))}; +#endif + bar(&t); + return 0; +} diff --git a/gcc/tree-sra.cc b/gcc/tree-sra.cc index f0182a4..ad0c738 100644 --- a/gcc/tree-sra.cc +++ b/gcc/tree-sra.cc @@ -3858,7 +3858,23 @@ sra_modify_expr (tree *expr, gimple_stmt_iterator *gsi, bool write) } } else - *expr = repl; + { + /* If we are going to replace a scalar field in a structure with + reverse storage order by a stand-alone scalar, we are going to + effectively byte-swap the scalar and we also need to byte-swap + the portion of it represented by the bit-field. */ + if (bfr && REF_REVERSE_STORAGE_ORDER (bfr)) + { + REF_REVERSE_STORAGE_ORDER (bfr) = 0; + TREE_OPERAND (bfr, 2) + = size_binop (MINUS_EXPR, TYPE_SIZE (TREE_TYPE (repl)), + size_binop (PLUS_EXPR, TREE_OPERAND (bfr, 1), + TREE_OPERAND (bfr, 2))); + } + + *expr = repl; + } + sra_stats.exprs++; } else if (write && access->grp_to_be_debug_replaced) |