[PATCH v3 14/15] riscv: add vectorized strpbrk

Pincheng Wang <[email protected]>
Newsgroups gmane.comp.lib.newlib
Message-ID <[email protected]>
The vector implementation builds a 256-byte set table on the stack and
scans the string in vector-length chunks using fault-only-first loads
(vle8ff.v) with an indexed gather into the table, returning a pointer to
the first byte in the set or NULL, without ever 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/strpbrk-asm.S | 51 +++++++++++++++++++++++++
 newlib/libc/machine/riscv/strpbrk.c     |  5 +++
 3 files changed, 58 insertions(+)
 create mode 100644 newlib/libc/machine/riscv/strpbrk-asm.S
 create mode 100644 newlib/libc/machine/riscv/strpbrk.c

diff --git a/newlib/libc/machine/riscv/Makefile.inc b/newlib/libc/machine/riscv/Makefile.inc
index 1e35cf17d..d145a3024 100644
--- a/newlib/libc/machine/riscv/Makefile.inc
+++ b/newlib/libc/machine/riscv/Makefile.inc
@@ -42,6 +42,8 @@ libc_a_SOURCES += \
 	%D%/strncpy.c \
 	%D%/strnlen-asm.S \
 	%D%/strnlen.c \
+	%D%/strpbrk-asm.S \
+	%D%/strpbrk.c \
 	%D%/strrchr-asm.S \
 	%D%/strrchr.c \
 	%D%/strspn-asm.S \
diff --git a/newlib/libc/machine/riscv/strpbrk-asm.S b/newlib/libc/machine/riscv/strpbrk-asm.S
new file mode 100644
index 000000000..b8584fb25
--- /dev/null
+++ b/newlib/libc/machine/riscv/strpbrk-asm.S
@@ -0,0 +1,51 @@
+#include <sys/asm.h>
+
+#if defined(__riscv_vector) && !defined(__riscv_e) && !defined(__OPTIMIZE_SIZE__) && !defined(PREFER_SIZE_OVER_SPEED)
+/* char *strpbrk(const char *a0, const char *a1)
+   Return a pointer to the first byte of a0 that appears in a1, or NULL.
+   Equivalent to s + strcspn(s, b), returning NULL when that lands on the
+   terminating NUL.  Same page-safe vle8ff scan + stack-table gather as
+   strcspn; the NUL is marked as a stopper so the scan terminates.  */
+ENTRY(strpbrk)
+  addi sp, sp, -256
+  li t1, 256
+  mv t0, sp
+.Lzero:
+  vsetvli t2, t1, e8, m8, ta, ma
+  vmv.v.i v8, 0
+  vse8.v v8, (t0)
+  add t0, t0, t2
+  sub t1, t1, t2
+  bnez t1, .Lzero
+  li t1, 1
+  /* mark every byte of a1 (the set), but NOT NUL yet */
+.Lbuild:
+  lbu t0, 0(a1)
+  beqz t0, .Lsetnul
+  add t2, sp, t0
+  sb t1, 0(t2)
+  addi a1, a1, 1
+  j .Lbuild
+.Lsetnul:
+  /* mark NUL as a stopper so the scan halts at end of string */
+  sb t1, 0(sp)
+.Lloop:
+  vsetvli t3, zero, e8, m1, ta, ma
+  vle8ff.v v8, (a0)
+  csrr t3, vl
+  vluxei8.v v16, (sp), v8
+  vmsne.vi v0, v16, 0
+  vfirst.m t4, v0
+  bgez t4, .Lfound
+  add a0, a0, t3
+  j .Lloop
+.Lfound:
+  add a0, a0, t4
+  lbu t5, 0(a0)         /* did we stop on a real match or on the NUL? */
+  bnez t5, .Ldone
+  li a0, 0
+.Ldone:
+  addi sp, sp, 256
+  ret
+END(strpbrk)
+#endif
diff --git a/newlib/libc/machine/riscv/strpbrk.c b/newlib/libc/machine/riscv/strpbrk.c
new file mode 100644
index 000000000..6664f1404
--- /dev/null
+++ b/newlib/libc/machine/riscv/strpbrk.c
@@ -0,0 +1,5 @@
+#if defined(__OPTIMIZE_SIZE__) || defined(PREFER_SIZE_OVER_SPEED) || !defined(__riscv_vector) || defined(__riscv_e)
+# include "../../string/strpbrk.c"
+#else
+/* strpbrk defined in strpbrk-asm.S */
+#endif
-- 
2.39.5
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.