Hi All,

PR123055 showed a regression on power9 and power8 IEEE128 where
gcc.target/powerpc/pr116030.c started emitting stxvd2x after
r16-5947-ga6c50ec2c6ebcb.

The regression was caused by -ffuse-ops-with-volatile-access, which
allows volatile memory to satisfy general_operand. This made
vsx_stxvd2x4_le_const_<mode> match quad stores regardless of their
actual alignment.

Introduce quad_unaligned_memory_operand and restrict
vsx_stxvd2x4_le_const_<mode> to unaligned quad memory only. This
ensures stxvd2x is emitted only when required and aligned cases
continue to use stvx.

Bootstrapped and Regtested on powerpc64le-linux-gnu.

2026-01-22  Kishan Parmar  <[email protected]>

gcc/ChangeLog:
        PR target/123055
        * config/rs6000/predicates.md (quad_unaligned_memory_operand): New
        predicate, returns 1 if the operand is memory but not 16-byte aligned.
        * config/rs6000/vsx.md (vsx_stxvd2x4_le_const_<mode>): Check if
        quad_unaligned_memory_operand.

gcc/testsuite/ChangeLog:
        PR target/123055
        testsuite/gcc.target/powerpc/pr123055.c: New testcase.
---
 gcc/config/rs6000/predicates.md             |  5 +++++
 gcc/config/rs6000/vsx.md                    |  2 +-
 gcc/testsuite/gcc.target/powerpc/pr123055.c | 19 +++++++++++++++++++
 3 files changed, 25 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/gcc.target/powerpc/pr123055.c

diff --git a/gcc/config/rs6000/predicates.md b/gcc/config/rs6000/predicates.md
index 54dbc8bcc95..6438227cb97 100644
--- a/gcc/config/rs6000/predicates.md
+++ b/gcc/config/rs6000/predicates.md
@@ -981,6 +981,11 @@
   return quad_address_p (XEXP (op, 0), mode, false);
 })
 
+;; Return 1 if the operand is memory but not naturally 16-byte aligned.
+(define_predicate "quad_unaligned_memory_operand"
+  (and (match_operand 0 "memory_operand")
+       (match_test "MEM_ALIGN (op) < 128")))
+
 ;; Return 1 if the operand is suitable for load/store to vector registers with
 ;; d-form addressing (register+offset), which was added in ISA 3.0.
 ;; Unlike quad_memory_operand, we do not have to check for alignment.
diff --git a/gcc/config/rs6000/vsx.md b/gcc/config/rs6000/vsx.md
index cfad9b8c6d5..d01807dab70 100644
--- a/gcc/config/rs6000/vsx.md
+++ b/gcc/config/rs6000/vsx.md
@@ -3452,7 +3452,7 @@
   [(set_attr "type" "vecstore")])
 
 (define_insn_and_split "vsx_stxvd2x4_le_const_<mode>"
-  [(set (match_operand:VSX_W 0 "memory_operand" "=Z")
+  [(set (match_operand:VSX_W 0 "quad_unaligned_memory_operand" "=Z")
        (match_operand:VSX_W 1 "immediate_operand" "W"))
    (clobber (match_scratch:VSX_W 2 "=wa"))]
   "!BYTES_BIG_ENDIAN
diff --git a/gcc/testsuite/gcc.target/powerpc/pr123055.c 
b/gcc/testsuite/gcc.target/powerpc/pr123055.c
new file mode 100644
index 00000000000..c7dccf528e6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/pr123055.c
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-options "-mdejagnu-cpu=power8 -O2" } */
+
+/* { dg-final { scan-assembler-not "stvx" { target { le } } } } */
+
+#pragma pack(1)
+struct unaligned_wrapper {
+  __vector int v;
+};
+#pragma pack()
+
+void
+store_unaligned_pragma (struct unaligned_wrapper *ptr)
+{
+  /* Accessing a packed member tells GCC the alignment is 1 byte.
+     Triggers stxvd2x. */
+  ptr->v = (__vector int) { -1, -1, -1, -1 };
+}
+
-- 
2.47.3

Reply via email to