This patch removes redundant vector compare instructions and logic
from the vec_first_mismatch_or_eos_index intrinsic.
Currently, GCC generates extra vcmpneb instructions and additional
masking logic (xxland, xxlorc) to handle EOS and mismatch comparisons.
However, a single vcmpnezb instruction already suffices, as it covers
both. By eliminating the redundant comparisons (vcmpneb) and the
associated logic (xxland/xxlorc) we produce shorter,
more efficient code.

Bootstrapped and regtested on powerpc64le-linux-gnu with no regressions.
Bootstrapped and regtested on powerpc64-linux-gnu with no regressions.

2025-10-22  Vijay Shankar  <[email protected]>

gcc/ChangeLog:
        PR target/116004
        * config/rs6000/vsx.md (first_mismatch_or_eos_index): Remove redundant
        emit_insns.

gcc/testsuite/ChangeLog:
        PR target/116004
        * gcc.target/powerpc/pr116004.c: New Test.
---
 gcc/config/rs6000/vsx.md                    | 21 ++-------
 gcc/testsuite/gcc.target/powerpc/pr116004.c | 47 +++++++++++++++++++++
 2 files changed, 50 insertions(+), 18 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/powerpc/pr116004.c

diff --git a/gcc/config/rs6000/vsx.md b/gcc/config/rs6000/vsx.md
index 18a22411d75..dfb2485f2ec 100644
--- a/gcc/config/rs6000/vsx.md
+++ b/gcc/config/rs6000/vsx.md
@@ -5717,29 +5717,14 @@
   "TARGET_P9_VECTOR"
 {
   int sh;
-  rtx cmpz1_result = gen_reg_rtx (<MODE>mode);
-  rtx cmpz2_result = gen_reg_rtx (<MODE>mode);
-  rtx cmpz_result = gen_reg_rtx (<MODE>mode);
-  rtx not_cmpz_result = gen_reg_rtx (<MODE>mode);
-  rtx and_result = gen_reg_rtx (<MODE>mode);
   rtx result = gen_reg_rtx (<MODE>mode);
-  rtx vzero = gen_reg_rtx (<MODE>mode);
 
-  /* Vector with zeros in elements that correspond to zeros in operands.  */
-  emit_move_insn (vzero, CONST0_RTX (<MODE>mode));
+  /* Vector with ones in elements that do not match or elements corresponding
+     to zeros in operands.  */
 
-  emit_insn (gen_vcmpne<VSX_EXTRACT_WIDTH> (cmpz1_result, operands[1], vzero));
-  emit_insn (gen_vcmpne<VSX_EXTRACT_WIDTH> (cmpz2_result, operands[2], vzero));
-  emit_insn (gen_and<mode>3 (and_result, cmpz1_result, cmpz2_result));
-
-  /* Vector with ones in elements that match.  */
-  emit_insn (gen_vcmpnez<VSX_EXTRACT_WIDTH> (cmpz_result, operands[1],
+  emit_insn (gen_vcmpnez<VSX_EXTRACT_WIDTH> (result, operands[1],
                                              operands[2]));
-  emit_insn (gen_one_cmpl<mode>2 (not_cmpz_result, cmpz_result));
 
-  /* Create vector with ones in elements where there was a zero in one of
-     the source elements or the elements did not match.  */
-  emit_insn (gen_nand<mode>3 (result, and_result, not_cmpz_result));
   sh = GET_MODE_SIZE (GET_MODE_INNER (<MODE>mode)) / 2;
 
   if (<MODE>mode == V16QImode)
diff --git a/gcc/testsuite/gcc.target/powerpc/pr116004.c 
b/gcc/testsuite/gcc.target/powerpc/pr116004.c
new file mode 100644
index 00000000000..4bcb59c54eb
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/pr116004.c
@@ -0,0 +1,47 @@
+/* { dg-do compile } */
+/* { dg-options "-mdejagnu-cpu=power9 -O2" } */
+/* { dg-final { scan-assembler-times {\mvcmpnezb\M} 2 } } */
+/* { dg-final { scan-assembler-times {\mvcmpnezh\M} 2 } } */
+/* { dg-final { scan-assembler-times {\mvcmpnezw\M} 2 } } */
+/* { dg-final { scan-assembler-not {\mvcmpneb\M} } } */
+/* { dg-final { scan-assembler-not {\mvcmpneh\M} } } */
+/* { dg-final { scan-assembler-not {\mvcmpnew\M} } } */
+
+#include <altivec.h>
+#include <stdint.h>
+
+unsigned int
+test_schar (vector signed char a, vector signed char b)
+{
+  return vec_first_mismatch_or_eos_index (a, b);
+}
+
+unsigned int
+test_uchar (vector unsigned char a, vector unsigned char b)
+{
+  return vec_first_mismatch_or_eos_index (a, b);
+}
+
+unsigned int
+test_sshort (vector signed short a, vector signed short b)
+{
+  return vec_first_mismatch_or_eos_index (a, b);
+}
+
+unsigned int
+test_ushort (vector unsigned short a, vector unsigned short b)
+{
+  return vec_first_mismatch_or_eos_index (a, b);
+}
+
+unsigned int
+test_sint (vector signed int a, vector signed int b)
+{
+  return vec_first_mismatch_or_eos_index (a, b);
+}
+
+unsigned int
+test_uint (vector unsigned int a, vector unsigned int b)
+{
+  return vec_first_mismatch_or_eos_index (a, b);
+}
-- 
2.52.0

Reply via email to