[PATCH v3 15/15] riscv: add vectorized strstr

Pincheng Wang <[email protected]>
Newsgroups gmane.comp.lib.newlib
Message-ID <[email protected]>
The vector implementation uses a fault-only-first (vle8ff.v) scan to find
candidate positions of the needle's first byte, then verifies each
candidate with a byte loop that stops at the needle's NUL or at a
mismatch; both phases stop at a NUL, so no load ever crosses past the end
of either string 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/strstr-asm.S | 51 ++++++++++++++++++++++++++
 newlib/libc/machine/riscv/strstr.c     |  5 +++
 3 files changed, 59 insertions(+), 1 deletion(-)
 create mode 100644 newlib/libc/machine/riscv/strstr-asm.S
 create mode 100644 newlib/libc/machine/riscv/strstr.c

diff --git a/newlib/libc/machine/riscv/Makefile.inc b/newlib/libc/machine/riscv/Makefile.inc
index d145a3024..c2d918d03 100644
--- a/newlib/libc/machine/riscv/Makefile.inc
+++ b/newlib/libc/machine/riscv/Makefile.inc
@@ -47,4 +47,6 @@ libc_a_SOURCES += \
 	%D%/strrchr-asm.S \
 	%D%/strrchr.c \
 	%D%/strspn-asm.S \
-	%D%/strspn.c
+	%D%/strspn.c \
+	%D%/strstr-asm.S \
+	%D%/strstr.c
diff --git a/newlib/libc/machine/riscv/strstr-asm.S b/newlib/libc/machine/riscv/strstr-asm.S
new file mode 100644
index 000000000..d887458b9
--- /dev/null
+++ b/newlib/libc/machine/riscv/strstr-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 *strstr(const char *a0, const char *a1)
+   Locate substring a1 in a0.  A vectorized scan (vle8ff, page-boundary safe)
+   finds candidate positions of needle[0]; each candidate is verified with a
+   byte loop that stops at the needle's NUL (match) or at a mismatch/the
+   haystack NUL.  Both phases stop at a NUL, so no load ever crosses past the
+   end of either string into an unmapped page.  */
+ENTRY(strstr)
+  lbu t0, 0(a1)            /* c0 = needle[0] */
+  beqz t0, .Lret_h         /* empty needle -> return haystack */
+.Lloop:
+  vsetvli t1, zero, e8, m1, ta, ma
+  vle8ff.v v8, (a0)
+  csrr t1, vl
+  vmseq.vx v1, v8, t0      /* lanes == c0 */
+  vmseq.vi v2, v8, 0       /* NUL lanes */
+  vfirst.m t2, v1
+  vfirst.m t3, v2
+  bltz t2, .Lno_c0         /* no c0 in this chunk */
+  bltz t3, .Lcandidate     /* c0 present, no NUL -> candidate */
+  bltu t2, t3, .Lcandidate /* c0 occurs before NUL */
+  /* NUL at or before c0 -> end of haystack reached */
+.Lnotfound:
+  li a0, 0
+  ret
+.Lno_c0:
+  bgez t3, .Lnotfound      /* hit NUL with no c0 -> not found */
+  add a0, a0, t1
+  j .Lloop
+.Lcandidate:
+  add a0, a0, t2           /* a0 -> candidate (h[*]==c0) */
+  mv t4, a0                /* haystack cursor */
+  mv t5, a1                /* needle cursor */
+.Lverify:
+  lbu t6, 0(t5)
+  beqz t6, .Lmatch         /* needle exhausted -> match at a0 */
+  lbu a2, 0(t4)
+  bne a2, t6, .Ladvance    /* mismatch (a2 may be NUL) */
+  addi t4, t4, 1
+  addi t5, t5, 1
+  j .Lverify
+.Ladvance:
+  addi a0, a0, 1           /* slide one byte and rescan */
+  j .Lloop
+.Lmatch:
+.Lret_h:
+  ret
+END(strstr)
+#endif
diff --git a/newlib/libc/machine/riscv/strstr.c b/newlib/libc/machine/riscv/strstr.c
new file mode 100644
index 000000000..08cdd00a6
--- /dev/null
+++ b/newlib/libc/machine/riscv/strstr.c
@@ -0,0 +1,5 @@
+#if defined(__OPTIMIZE_SIZE__) || defined(PREFER_SIZE_OVER_SPEED) || !defined(__riscv_vector) || defined(__riscv_e)
+# include "../../string/strstr.c"
+#else
+/* strstr defined in strstr-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.