]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
Fix problematic interaction between bitfields, unions, SSO and SRA
authorEric Botcazou <ebotcazou@adacore.com>
Wed, 11 Jan 2023 14:58:47 +0000 (15:58 +0100)
committerEric Botcazou <ebotcazou@adacore.com>
Wed, 11 Jan 2023 16:24:56 +0000 (17:24 +0100)
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.

gcc/testsuite/gcc.dg/sso-17.c [new file with mode: 0644]
gcc/tree-sra.cc

diff --git a/gcc/testsuite/gcc.dg/sso-17.c b/gcc/testsuite/gcc.dg/sso-17.c
new file mode 100644 (file)
index 0000000..67e2d37
--- /dev/null
@@ -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;
+}
index 95291e8df9343b39d77a20d14b2e8e23665f0af6..09dbd7be77fe729645f263f5ceea3f62abb98e9e 100644 (file)
@@ -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)