[PATCH v3 06/15] riscv: add vectorized strcmp

Pincheng Wang pincheng.plct@isrc.iscas.ac.cn
Fri Aug 14 02:26:47 GMT 2026


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 <pincheng.plct@isrc.iscas.ac.cn>
---
 newlib/libc/machine/riscv/Makefile.inc |  1 +
 newlib/libc/machine/riscv/strcmp-asm.S | 51 ++++++++++++++++++++++++++
 newlib/libc/machine/riscv/strcmp.S     |  4 ++
 3 files changed, 56 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..5592a88b6
--- /dev/null
+++ b/newlib/libc/machine/riscv/strcmp-asm.S
@@ -0,0 +1,51 @@
+#include <sys/asm.h>
+
+#if defined(__riscv_vector) && !defined(__OPTIMIZE_SIZE__) && !defined(PREFER_SIZE_OVER_SPEED)
+ENTRY(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
+END(strcmp)
+#endif
diff --git a/newlib/libc/machine/riscv/strcmp.S b/newlib/libc/machine/riscv/strcmp.S
index 1fd0f1440..8f2f406af 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) && !defined(__OPTIMIZE_SIZE__) && !defined(PREFER_SIZE_OVER_SPEED))
+
 ENTRY(strcmp)
 
 #if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__)
@@ -243,3 +245,5 @@ mask:
 .dword 0x7f7f7f7f7f7f7f7f
 #endif
 #endif
+
+#endif /* not __riscv_vector */
-- 
2.39.5



More information about the Newlib mailing list