[PATCH 03/17] riscv: add vectorized strchr

Pincheng Wang <[email protected]> Thu, 16 Jul 2026 23:00:34 +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), locating the target byte and the
terminating NUL in the same pass while never crossing 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 |  2 ++
 newlib/libc/machine/riscv/strchr-asm.S | 29 ++++++++++++++++++++++++++
 newlib/libc/machine/riscv/strchr.c     |  5 +++++
 3 files changed, 36 insertions(+)
 create mode 100644 newlib/libc/machine/riscv/strchr-asm.S
 create mode 100644 newlib/libc/machine/riscv/strchr.c

diff --git a/newlib/libc/machine/riscv/Makefile.inc b/newlib/libc/machine/riscv/Makefile.inc
index d3f72e471..01a0aaf50 100644
--- a/newlib/libc/machine/riscv/Makefile.inc
+++ b/newlib/libc/machine/riscv/Makefile.inc
@@ -20,6 +20,8 @@ libc_a_SOURCES += \
 	%D%/memset.S \
 	%D%/setjmp.S \
 	%D%/stpcpy.c \
+	%D%/strchr-asm.S \
+	%D%/strchr.c \
 	%D%/strcmp.S \
 	%D%/strcpy.c \
 	%D%/strlen-asm.S \
diff --git a/newlib/libc/machine/riscv/strchr-asm.S b/newlib/libc/machine/riscv/strchr-asm.S
new file mode 100644
index 000000000..79faf8273
--- /dev/null
+++ b/newlib/libc/machine/riscv/strchr-asm.S
@@ -0,0 +1,29 @@
+#if defined(__riscv_vector) && __riscv_xlen == 64 && !defined(__OPTIMIZE_SIZE__) && !defined(PREFER_SIZE_OVER_SPEED)
+.text
+.option push
+.option arch, +v
+.global strchr
+.type strchr, @function
+strchr:
+.Lloop:
+  vsetvli t0, zero, e8, m1, ta, ma
+  vle8ff.v v0, (a0)
+  vmseq.vi v8, v0, 0
+  vmseq.vx v9, v0, a1
+  vfirst.m a2, v8      /* first occurrence of \0 */
+  vfirst.m a3, v9      /* first occurrence of a1 */
+  sltz a4, a3
+  sltu a5, a2, a3
+  or a4, a4, a5
+  beqz a4, .Lfound     /* found a1, not preceded by \0? */
+  csrr a6, vl
+  add a0, a0, a6
+  bltz a2, .Lloop      /* didn't find \0? */
+  li a0, 0
+  ret
+.Lfound:
+  add a0, a0, a3
+  ret
+.size strchr, .-strchr
+.option pop
+#endif
diff --git a/newlib/libc/machine/riscv/strchr.c b/newlib/libc/machine/riscv/strchr.c
new file mode 100644
index 000000000..7a2f39aac
--- /dev/null
+++ b/newlib/libc/machine/riscv/strchr.c
@@ -0,0 +1,5 @@
+#if defined(__OPTIMIZE_SIZE__) || defined(PREFER_SIZE_OVER_SPEED) || !defined(__riscv_vector) || __riscv_xlen != 64
+# include "../../string/strchr.c"
+#else
+/* strchr defined in strchr-asm.S */
+#endif
-- 
2.39.5