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
