]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
store_integral_bit_field: Graceful fallback when SUBREG narrowing fails [PR123754]
authorKonstantinos Eleftheriou <konstantinos.eleftheriou@vrull.eu>
Fri, 22 May 2026 13:09:49 +0000 (15:09 +0200)
committerPhilipp Tomsich <philipp.tomsich@vrull.eu>
Mon, 15 Jun 2026 16:53:54 +0000 (18:53 +0200)
The multi-word narrowing path in store_integral_bit_field uses
simplify_gen_subreg followed by gcc_assert (op0).  The symmetric path
in extract_integral_bit_field was switched to force_subreg, but the
store side was deliberately left on simplify_gen_subreg because op0
is an lvalue.  When the subreg simplification fails (e.g. a vector
op0 punned through an int mode whose word-aligned subregs are rejected
by validate_subreg, as happens for V8SI on -mbig-endian aarch64),
the assert fires.

The avoid-store-forwarding pass (-favoid-store-forwarding) triggers
this: it routes such a vector op0 through store_integral_bit_field.

Replace the assert with a graceful fallback to store_split_bit_field,
mirroring the cross-word branch immediately above.  No change for
inputs where the narrowing succeeds.

Tested on AArch64, x86-64 and PowerPC BE.

PR rtl-optimization/123754

gcc/ChangeLog:

* expmed.cc (store_integral_bit_field): When the SUBREG
narrowing fails, defer to store_split_bit_field instead of
asserting.

gcc/testsuite/ChangeLog:

* gcc.target/aarch64/pr123754.c: New test.
* gcc.target/aarch64/avoid-store-forwarding-be-2.c: New test.

gcc/expmed.cc
gcc/testsuite/gcc.target/aarch64/avoid-store-forwarding-be-2.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/pr123754.c [new file with mode: 0644]

index e4433384c591360361e79d46e48e946e8411e2ed..da1b5b63287611817ac6934f3cae42b9e7a07807 100644 (file)
@@ -1064,9 +1064,21 @@ store_integral_bit_field (rtx op0, opt_scalar_int_mode op0_mode,
                                 value, value_mode, reverse);
          return true;
        }
-      op0 = simplify_gen_subreg (word_mode, op0, op0_mode.require (),
-                                bitnum / BITS_PER_WORD * UNITS_PER_WORD);
-      gcc_assert (op0);
+      rtx new_op0
+       = simplify_gen_subreg (word_mode, op0, op0_mode.require (),
+                              bitnum / BITS_PER_WORD * UNITS_PER_WORD);
+      if (!new_op0)
+       {
+         /* No valid word-mode SUBREG of op0 at this offset.  Defer to
+            store_split_bit_field, which addresses op0 a word at a time.  */
+         if (!fallback_p)
+           return false;
+         store_split_bit_field (op0, op0_mode, bitsize, bitnum,
+                                bitregion_start, bitregion_end,
+                                value, value_mode, reverse);
+         return true;
+       }
+      op0 = new_op0;
       op0_mode = word_mode;
       bitnum %= BITS_PER_WORD;
     }
diff --git a/gcc/testsuite/gcc.target/aarch64/avoid-store-forwarding-be-2.c b/gcc/testsuite/gcc.target/aarch64/avoid-store-forwarding-be-2.c
new file mode 100644 (file)
index 0000000..f060990
--- /dev/null
@@ -0,0 +1,41 @@
+/* PR rtl-optimization/123754 */
+/* { dg-do run } */
+/* { dg-require-effective-target aarch64_big_endian } */
+/* { dg-require-effective-target int128 } */
+/* { dg-options "-O2 -favoid-store-forwarding" } */
+
+typedef unsigned __int128 u128;
+
+union u {
+  u128 v;
+  unsigned char b[16];
+};
+
+u128 __attribute__ ((noinline))
+foo (unsigned char x, unsigned char y, u128 init)
+{
+  union u u;
+  u.v = init;
+  u.b[0] = x;
+  u.b[15] = y;
+  return u.v;
+}
+
+int
+main (void)
+{
+  u128 init = ((u128) 0xfedcba9876543210ULL << 64) | 0x0123456789abcdefULL;
+  u128 r = foo (0xAA, 0xBB, init);
+
+  unsigned char *p = (unsigned char *) &r;
+  unsigned char *q = (unsigned char *) &init;
+
+  if (p[0] != 0xAA || p[15] != 0xBB)
+    __builtin_abort ();
+
+  for (int i = 1; i < 15; i++)
+    if (p[i] != q[i])
+      __builtin_abort ();
+
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/pr123754.c b/gcc/testsuite/gcc.target/aarch64/pr123754.c
new file mode 100644 (file)
index 0000000..4478413
--- /dev/null
@@ -0,0 +1,15 @@
+/* PR rtl-optimization/123754 */
+/* { dg-do compile } */
+/* { dg-require-effective-target aarch64_big_endian } */
+/* { dg-options "-O2 -favoid-store-forwarding" } */
+
+typedef __attribute__((__vector_size__(32))) int V;
+long long i;
+V g;
+
+void
+foo (V *v)
+{
+  __builtin_memcpy (v, &i, 5);
+  g *= *v;
+}