[PATCH 07/17] riscv: add vectorized strncmp
Pincheng Wang <[email protected]> Thu, 16 Jul 2026 23:00:38 +0800
| Newsgroups | gmane.comp.lib.newlib |
|---|---|
| Message-ID | <[email protected]> |
The vector implementation compares both operands in vector-length chunks using fault-only-first loads (vle8ff.v); vl is additionally capped by the remaining count so it never reads past the n-th byte and never crosses into an unmapped page. This provides significant performance improvements on RVV-capable hardware. Use conditional compilation to fall back to the generic implementation when __riscv_vector is not available, maintaining compatibility with non-vector RISC-V systems. Signed-off-by: Pincheng Wang <[email protected]> --- newlib/libc/machine/riscv/Makefile.inc | 2 + newlib/libc/machine/riscv/strncmp-asm.S | 51 +++++++++++++++++++++++++ newlib/libc/machine/riscv/strncmp.c | 5 +++ 3 files changed, 58 insertions(+) create mode 100644 newlib/libc/machine/riscv/strncmp-asm.S create mode 100644 newlib/libc/machine/riscv/strncmp.c diff --git a/newlib/libc/machine/riscv/Makefile.inc b/newlib/libc/machine/riscv/Makefile.inc index 243195b36..015b91799 100644 --- a/newlib/libc/machine/riscv/Makefile.inc +++ b/newlib/libc/machine/riscv/Makefile.inc @@ -29,6 +29,8 @@ libc_a_SOURCES += \ %D%/strcpy.c \ %D%/strlen-asm.S \ %D%/strlen.c \ + %D%/strncmp-asm.S \ + %D%/strncmp.c \ %D%/strnlen-asm.S \ %D%/strnlen.c \ %D%/strrchr-asm.S \ diff --git a/newlib/libc/machine/riscv/strncmp-asm.S b/newlib/libc/machine/riscv/strncmp-asm.S new file mode 100644 index 000000000..a4685943d --- /dev/null +++ b/newlib/libc/machine/riscv/strncmp-asm.S @@ -0,0 +1,51 @@ +#if defined(__riscv_vector) && __riscv_xlen == 64 && !defined(__OPTIMIZE_SIZE__) && !defined(PREFER_SIZE_OVER_SPEED) +.text +.option push +.option arch, +v +.global strncmp +.type strncmp, @function +strncmp: + beqz a2, .Lzero_length +.Lloop: + vsetvli zero, a2, e8, m1, ta, ma + + vle8ff.v v0, (a0) + /* v0[i] == 0. */ + vmseq.vx v8, v0, zero + + vle8ff.v v4, (a1) + /* v0[i] != v4[i]. */ + vmsne.vv v9, v0, v4 + + csrr a3, vl + + /* r = mask1 | mask2 + Combine the first NUL in a0 with the first differing byte so a single + vfirst.m locates whichever comes first. */ + vmor.mm v8, v8, v9 + + sub a2, a2, a3 + + vfirst.m a4, v8 + + bgez a4, .Lend_loop + + add a0, a0, a3 + add a1, a1, a3 + bnez a2, .Lloop +.Lend_loop: + + add a0, a0, a4 + add a1, a1, a4 + lbu a4, 0(a0) + lbu a5, 0(a1) + + sub a0, a4, a5 + ret + +.Lzero_length: + li a0, 0 + ret +.size strncmp, .-strncmp +.option pop +#endif diff --git a/newlib/libc/machine/riscv/strncmp.c b/newlib/libc/machine/riscv/strncmp.c new file mode 100644 index 000000000..cf64b88f6 --- /dev/null +++ b/newlib/libc/machine/riscv/strncmp.c @@ -0,0 +1,5 @@ +#if defined(__OPTIMIZE_SIZE__) || defined(PREFER_SIZE_OVER_SPEED) || !defined(__riscv_vector) || __riscv_xlen != 64 +# include "../../string/strncmp.c" +#else +/* strncmp defined in strncmp-asm.S */ +#endif -- 2.39.5