[PATCH v3 05/15] riscv: add vectorized strrchr

Pincheng Wang <[email protected]>
Newsgroups gmane.comp.lib.newlib
Message-ID <[email protected]>
The vector implementation makes a single forward pass, loading each chunk
with fault-only-first loads (vle8ff.v) and selecting the highest matching
lane index with a masked max-index reduction, so it 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/strrchr-asm.S | 38 +++++++++++++++++++++++++
 newlib/libc/machine/riscv/strrchr.c     |  5 ++++
 3 files changed, 46 insertions(+), 1 deletion(-)
 create mode 100644 newlib/libc/machine/riscv/strrchr-asm.S
 create mode 100644 newlib/libc/machine/riscv/strrchr.c

diff --git a/newlib/libc/machine/riscv/Makefile.inc b/newlib/libc/machine/riscv/Makefile.inc
index 3c13fbc1a..4bb7fefbb 100644
--- a/newlib/libc/machine/riscv/Makefile.inc
+++ b/newlib/libc/machine/riscv/Makefile.inc
@@ -29,4 +29,6 @@ libc_a_SOURCES += \
 	%D%/strlen-asm.S \
 	%D%/strlen.c \
 	%D%/strnlen-asm.S \
-	%D%/strnlen.c
+	%D%/strnlen.c \
+	%D%/strrchr-asm.S \
+	%D%/strrchr.c
diff --git a/newlib/libc/machine/riscv/strrchr-asm.S b/newlib/libc/machine/riscv/strrchr-asm.S
new file mode 100644
index 000000000..1bdb84338
--- /dev/null
+++ b/newlib/libc/machine/riscv/strrchr-asm.S
@@ -0,0 +1,38 @@
+#include <sys/asm.h>
+
+#if defined(__riscv_vector) && !defined(__riscv_e) && !defined(__OPTIMIZE_SIZE__) && !defined(PREFER_SIZE_OVER_SPEED)
+/* char *strrchr(const char *a0, int a1)
+   Return the last occurrence of (char)a1 in a0, including the terminating
+   NUL when a1==0, else NULL.  Single forward pass: each chunk is loaded with
+   vle8ff (page-boundary safe) and the highest matching lane index is found
+   with a masked max-index reduction.  */
+ENTRY(strrchr)
+  li a6, 0                  /* result pointer = NULL so far */
+.Lloop:
+  vsetvli a2, zero, e8, m1, ta, ma
+  vle8ff.v v8, (a0)
+  csrr a2, vl
+  vmseq.vi v1, v8, 0        /* NUL lanes */
+  vfirst.m a3, v1           /* first NUL position (or -1) */
+  vmseq.vx v2, v8, a1       /* lanes equal to (char)c */
+  vmsif.m v3, v1            /* valid lanes: up to & including first NUL */
+  vmand.mm v0, v2, v3       /* candidate matches within the string */
+  vfirst.m a4, v0           /* any candidate in this chunk? */
+  bltz a4, .Lskip
+  /* reduce the maximum lane index over candidate lanes (need e16 to be
+     safe for large VLEN where vl can exceed 255).  */
+  vsetvli zero, a2, e16, m2, ta, ma
+  vid.v v16
+  vmv.s.x v24, x0
+  vredmaxu.vs v24, v16, v24, v0.t
+  vmv.x.s a5, v24
+  add a6, a0, a5
+.Lskip:
+  bgez a3, .Ldone           /* reached end of string */
+  add a0, a0, a2
+  j .Lloop
+.Ldone:
+  mv a0, a6
+  ret
+END(strrchr)
+#endif
diff --git a/newlib/libc/machine/riscv/strrchr.c b/newlib/libc/machine/riscv/strrchr.c
new file mode 100644
index 000000000..d06b31e4c
--- /dev/null
+++ b/newlib/libc/machine/riscv/strrchr.c
@@ -0,0 +1,5 @@
+#if defined(__OPTIMIZE_SIZE__) || defined(PREFER_SIZE_OVER_SPEED) || !defined(__riscv_vector) || defined(__riscv_e)
+# include "../../string/strrchr.c"
+#else
+/* strrchr defined in strrchr-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.