[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