[PATCH 06/17] riscv: add vectorized strcmp
Pincheng Wang <[email protected]> Thu, 16 Jul 2026 23:00:37 +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), detecting the terminating NUL and the first differing byte in the same pass without ever crossing into an unmapped page. This provides significant performance improvements on RVV-capable hardware. Use conditional compilation to fall back to the existing scalar 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 | 1 + newlib/libc/machine/riscv/strcmp-asm.S | 55 ++++++++++++++++++++++++++ newlib/libc/machine/riscv/strcmp.S | 4 ++ 3 files changed, 60 insertions(+) create mode 100644 newlib/libc/machine/riscv/strcmp-asm.S diff --git a/newlib/libc/machine/riscv/Makefile.inc b/newlib/libc/machine/riscv/Makefile.inc index 4bb7fefbb..243195b36 100644 --- a/newlib/libc/machine/riscv/Makefile.inc +++ b/newlib/libc/machine/riscv/Makefile.inc @@ -24,6 +24,7 @@ libc_a_SOURCES += \ %D%/strchr.c \ %D%/strchrnul-asm.S \ %D%/strchrnul.c \ + %D%/strcmp-asm.S \ %D%/strcmp.S \ %D%/strcpy.c \ %D%/strlen-asm.S \ diff --git a/newlib/libc/machine/riscv/strcmp-asm.S b/newlib/libc/machine/riscv/strcmp-asm.S new file mode 100644 index 000000000..a858b8eab --- /dev/null +++ b/newlib/libc/machine/riscv/strcmp-asm.S @@ -0,0 +1,55 @@ +#if defined(__riscv_vector) && __riscv_xlen == 64 && !defined(__OPTIMIZE_SIZE__) && !defined(PREFER_SIZE_OVER_SPEED) +.text +.option push +.option arch, +v +.global strcmp +.type strcmp, @function +strcmp: +.Lloop: + vsetvli a2, zero, e8, m1, ta, ma + vle8ff.v v0, (a0) + /* check if v0[i] == 0 */ + vmseq.vx v16, v0, zero + + vle8ff.v v8, (a1) + /* check if v0[i] != v8[i] */ + vmsne.vv v17, v0, v8 + + /* find the index x for v0[x]==0 */ + vfirst.m a3, v16 + /* find the index x for v0[x]!=v8[x] */ + vfirst.m a4, v17 + + bgez a3, .Lcheck1 + bgez a4, .Lcheck2 + + /* get the current vl updated by vle8ff. */ + csrr a2, vl + add a0, a0, a2 + add a1, a1, a2 + j .Lloop + + /* a3>=0 */ +.Lcheck1: + bltz a4, .Lreturn_at_nul + blt a4, a3, .Lcheck2 +.Lreturn_at_nul: + /* a4<0, or a4>=0 && a3<=a4 */ + add a0, a0, a3 + add a1, a1, a3 + lbu a3, 0(a0) + lbu a4, 0(a1) + sub a0, a3, a4 + ret + + /* a3<0 && a4>=0, or a4<a3 */ +.Lcheck2: + add a0, a0, a4 + add a1, a1, a4 + lbu a3, 0(a0) + lbu a4, 0(a1) + sub a0, a3, a4 + ret +.size strcmp, .-strcmp +.option pop +#endif diff --git a/newlib/libc/machine/riscv/strcmp.S b/newlib/libc/machine/riscv/strcmp.S index 7668d3ef7..d4fad4de9 100644 --- a/newlib/libc/machine/riscv/strcmp.S +++ b/newlib/libc/machine/riscv/strcmp.S @@ -12,6 +12,8 @@ #include <sys/asm.h> #include "newlib.h" +#if !(defined(__riscv_vector) && __riscv_xlen == 64 && !defined(__OPTIMIZE_SIZE__) && !defined(PREFER_SIZE_OVER_SPEED)) + .text .globl strcmp .type strcmp, @function @@ -249,3 +251,5 @@ mask: .dword 0x7f7f7f7f7f7f7f7f #endif #endif + +#endif /* not __riscv_vector */ -- 2.39.5