[v3,07/15] riscv: add vectorized strncmp

Message ID 20260814022656.1071643-8-pincheng.plct@isrc.iscas.ac.cn
State New
Headers
Series riscv: vectorized str* routines |

Commit Message

Pincheng Wang Aug. 14, 2026, 2:26 a.m. UTC
  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 <pincheng.plct@isrc.iscas.ac.cn>
---
 newlib/libc/machine/riscv/Makefile.inc  |  2 ++
 newlib/libc/machine/riscv/strncmp-asm.S | 47 +++++++++++++++++++++++++
 newlib/libc/machine/riscv/strncmp.c     |  5 +++
 3 files changed, 54 insertions(+)
 create mode 100644 newlib/libc/machine/riscv/strncmp-asm.S
 create mode 100644 newlib/libc/machine/riscv/strncmp.c
  

Patch

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..c178c32e2
--- /dev/null
+++ b/newlib/libc/machine/riscv/strncmp-asm.S
@@ -0,0 +1,47 @@ 
+#include <sys/asm.h>
+
+#if defined(__riscv_vector) && !defined(__OPTIMIZE_SIZE__) && !defined(PREFER_SIZE_OVER_SPEED)
+ENTRY(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
+END(strncmp)
+#endif
diff --git a/newlib/libc/machine/riscv/strncmp.c b/newlib/libc/machine/riscv/strncmp.c
new file mode 100644
index 000000000..81ccf1e58
--- /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)
+# include "../../string/strncmp.c"
+#else
+/* strncmp defined in strncmp-asm.S */
+#endif