[PATCH 02/17] riscv: add vectorized strnlen

Pincheng Wang <[email protected]> Thu, 16 Jul 2026 23:00:33 +0800
Newsgroups gmane.comp.lib.newlib
Message-ID <[email protected]>
The vector implementation scans the string in vector-length chunks using
fault-only-first loads (vle8ff.v); vl is additionally capped by the
remaining count so the scan never reads past the maxlen-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  |  4 +++-
 newlib/libc/machine/riscv/strnlen-asm.S | 28 +++++++++++++++++++++++++
 newlib/libc/machine/riscv/strnlen.c     |  5 +++++
 3 files changed, 36 insertions(+), 1 deletion(-)
 create mode 100644 newlib/libc/machine/riscv/strnlen-asm.S
 create mode 100644 newlib/libc/machine/riscv/strnlen.c

diff --git a/newlib/libc/machine/riscv/Makefile.inc b/newlib/libc/machine/riscv/Makefile.inc
index a410a512f..d3f72e471 100644
--- a/newlib/libc/machine/riscv/Makefile.inc
+++ b/newlib/libc/machine/riscv/Makefile.inc
@@ -23,4 +23,6 @@ libc_a_SOURCES += \
 	%D%/strcmp.S \
 	%D%/strcpy.c \
 	%D%/strlen-asm.S \
-	%D%/strlen.c
+	%D%/strlen.c \
+	%D%/strnlen-asm.S \
+	%D%/strnlen.c
diff --git a/newlib/libc/machine/riscv/strnlen-asm.S b/newlib/libc/machine/riscv/strnlen-asm.S
new file mode 100644
index 000000000..57948857b
--- /dev/null
+++ b/newlib/libc/machine/riscv/strnlen-asm.S
@@ -0,0 +1,28 @@
+#if defined(__riscv_vector) && __riscv_xlen == 64 && !defined(__OPTIMIZE_SIZE__) && !defined(PREFER_SIZE_OVER_SPEED)
+.text
+.option push
+.option arch, +v
+.global strnlen
+.type strnlen, @function
+strnlen:
+  mv a2, a0
+  mv a0, a1
+.Lloop:
+  beqz a1, .Ldone
+  vsetvli zero, a1, e8, m1, ta, ma
+  vle8ff.v v0, (a2)
+  vmseq.vi v8, v0, 0
+  vfirst.m a4, v8      /* first occurrence of \0 */
+  csrr a3, vl
+  add a2, a2, a3
+  sub a1, a1, a3
+  bltz a4, .Lloop
+
+  add a1, a1, a3
+  sub a0, a0, a1
+  add a0, a0, a4
+.Ldone:
+  ret
+.size strnlen, .-strnlen
+.option pop
+#endif
diff --git a/newlib/libc/machine/riscv/strnlen.c b/newlib/libc/machine/riscv/strnlen.c
new file mode 100644
index 000000000..bb2bc2cf0
--- /dev/null
+++ b/newlib/libc/machine/riscv/strnlen.c
@@ -0,0 +1,5 @@
+#if defined(__OPTIMIZE_SIZE__) || defined(PREFER_SIZE_OVER_SPEED) || !defined(__riscv_vector) || __riscv_xlen != 64
+# include "../../string/strnlen.c"
+#else
+/* strnlen defined in strnlen-asm.S */
+#endif
-- 
2.39.5