Hi All,

The following patch has been bootstrapped and regtested on powerpc64le-linux.

The little-endian expansion of vec_permx modified the permute control
vector. When the same control vector was used by multiple vec_permx
calls, later calls used the modified value and produced incorrect
results.

Generate the negated control vector in a new pseudo register instead of
modifying the input operand.

2026-07-27  Jeevitha Palanisamy  <[email protected]>

gcc/
        PR target/125138
        * config/rs6000/vsx.md (xxpermx): Use a temporary register for the
        negated control vector.

gcc/testsuite/
        PR target/125138
        * gcc.target/powerpc/pr125138.c: New test.

diff --git a/gcc/config/rs6000/vsx.md b/gcc/config/rs6000/vsx.md
index 9863c476bac..739716c198f 100644
--- a/gcc/config/rs6000/vsx.md
+++ b/gcc/config/rs6000/vsx.md
@@ -6789,12 +6789,13 @@
         of element from 7.  */
       int value = INTVAL (operands[4]);
       rtx vreg = gen_reg_rtx (V16QImode);
+      rtx tmp = gen_reg_rtx (V16QImode);
 
       emit_insn (gen_xxspltib_v16qi (vreg, GEN_INT (-1)));
-      emit_insn (gen_xorv16qi3 (operands[3], operands[3], vreg));
+      emit_insn (gen_xorv16qi3 (tmp, operands[3], vreg));
       value = 7 - value;
       emit_insn (gen_xxpermx_inst (operands[0], operands[2],
-                                  operands[1], operands[3],
+                                  operands[1], tmp,
                                   GEN_INT (value)));
     }
 
diff --git a/gcc/testsuite/gcc.target/powerpc/pr125138.c 
b/gcc/testsuite/gcc.target/powerpc/pr125138.c
new file mode 100644
index 00000000000..f7f0d2c7f08
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/pr125138.c
@@ -0,0 +1,34 @@
+/* PR target/125138 */
+/* { dg-do compile } */
+/* { dg-require-effective-target power10_ok } */
+/* { dg-options "-O3 -mdejagnu-cpu=power10" } */
+
+#include <altivec.h>
+
+typedef vector unsigned char vui8_t;
+
+vui8_t
+test1 (vui8_t vra0, vui8_t vrb0, vui8_t vra1, vui8_t vrb1, vui8_t vrc)
+{
+  vui8_t perm0, perm1;
+  perm0 = vec_permx (vra0, vrb0, vrc, 0);
+  perm1 = vec_permx (vra1, vrb1, vrc, 1);
+  return vec_or (perm0, perm1);
+}
+
+vui8_t
+test2 (vui8_t vra0, vui8_t vrb0, vui8_t vra1, vui8_t vrb1, vui8_t vra2,
+       vui8_t vrb2, vui8_t vra3, vui8_t vrb3, vui8_t vrc)
+{
+  vui8_t perm0, perm1, perm2, perm3;
+  perm0 = vec_permx (vra0, vrb0, vrc, 0);
+  perm1 = vec_permx (vra1, vrb1, vrc, 1);
+  perm2 = vec_permx (vra2, vrb2, vrc, 2);
+  perm3 = vec_permx (vra3, vrb3, vrc, 3);
+  perm0 = vec_or (perm0, perm1);
+  perm2 = vec_or (perm2, perm3);
+  return vec_or (perm0, perm2);
+}
+
+/* { dg-final { scan-assembler-times {\mxxlnor\M} 2 } } */
+/* { dg-final { scan-assembler-times {\mxxpermx\M} 6 } } */

Reply via email to