Hi Vijay,

On 26/03/26 2:07 pm, Vijay Shankar wrote:
> Changes from v4:
>         * Update to use Use \m...\M in
> Changes from v3:
>       * Added New testcase.
> Changes from v2:
>       * Some formatting.
> Changes from v1:
>       * Added more info to commit message fixed indentation.
> 
> 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 tested on powerpc64le-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.

Small nit: "New test."

> ---
>  gcc/config/rs6000/vsx.md                    | 22 ++------
>  gcc/testsuite/gcc.target/powerpc/pr116004.c | 58 +++++++++++++++++++++
>  2 files changed, 61 insertions(+), 19 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 cfad9b8c6..3c2319a53 100644
> --- a/gcc/config/rs6000/vsx.md
> +++ b/gcc/config/rs6000/vsx.md
> @@ -5668,29 +5668,13 @@
>    "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));
>  
> -  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 do not match or elements corresponding
> +     to zeros in operands.  */
>  
> -  /* Vector with ones in elments 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 000000000..3f240c1c4
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/powerpc/pr116004.c
> @@ -0,0 +1,58 @@
> +/* { 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>
> +
> +int main(void) {
> +  vector signed char char_src1, char_src2;
> +  vector unsigned char uchar_src1, uchar_src2;
> +  vector signed short short_src1, short_src2;
> +  vector unsigned short ushort_src1, ushort_src2;
> +  vector signed int int_src1, int_src2;
> +  vector unsigned int uint_src1, uint_src2;
> +
> +  volatile unsigned int r1, r2, r3, r4, r5, r6;
> +
> +  /* signed char */
> +  char_src1 = (vector signed char) {-1, 2, 3, 0, -5, 6, 7, 8,
> +                                    9, 10, 11, 12, 13, 14, 15, 16};
> +  char_src2 = (vector signed char) {2, 3, 20, 0, -5, 6, 7, 8,
> +                                    9, 10, 11, 12, 13, 14, 15, 16};
> +  r1 = vec_first_mismatch_or_eos_index(char_src1, char_src2);
> +
> +  /* unsigned char */
> +  uchar_src1 = (vector unsigned char) {1, 2, 3, 4, 5, 6, 7, 8,
> +                                       9, 10, 11, 12, 13, 14, 15, 16};
> +  uchar_src2 = (vector unsigned char) {1, 0, 3, 4, 5, 6, 7, 8,
> +                                       9, 10, 11, 12, 13, 14, 15, 16};
> +  r2 = vec_first_mismatch_or_eos_index(uchar_src1, uchar_src2);
> +
> +  /* signed short */
> +  short_src1 = (vector signed short) {-10, -20, 30, 40, 50, 60, 70, 80};
> +  short_src2 = (vector signed short) {-10, 20, 30, 40, 50, 60, 70, 80};
> +  r3 = vec_first_mismatch_or_eos_index(short_src1, short_src2);
> +
> +  /* unsigned short */
> +  ushort_src1 = (vector unsigned short) {10, 20, 30, 40, 50, 60, 70, 0};
> +  ushort_src2 = (vector unsigned short) {10, 20, 30, 40, 50, 60, 70, 80};
> +  r4 = vec_first_mismatch_or_eos_index(ushort_src1, ushort_src2);
> +
> +  /* signed int */
> +  int_src1 = (vector signed int) {1, 2, 3, 4};
> +  int_src2 = (vector signed int) {1, 20, 3, 4};
> +  r5 = vec_first_mismatch_or_eos_index(int_src1, int_src2);
> +
> +  /* unsigned int */
> +  uint_src1 = (vector unsigned int) {1, 2, 3, 0};
> +  uint_src2 = (vector unsigned int) {1, 2, 3, 0};
> +  r6 = vec_first_mismatch_or_eos_index(uint_src1, uint_src2);
> +
> +  return 0;
> +}

One small suggestion for the testcase: since this is a code-generation test, 
could we use helper
functions with vector arguments instead of constant vectors initialized in 
main()?

Something like:

unsigned int
test (vector unsigned char a, vector unsigned char b)
{
  return vec_first_mismatch_or_eos_index (a, b);
}

-Jeevitha

Reply via email to