[PATCH v3 10/15] riscv: add vectorized strcat

Pincheng Wang <[email protected]>
Newsgroups gmane.comp.lib.newlib
Message-ID <[email protected]>
The vector implementation locates the end of the destination and appends
the source in vector-length chunks using fault-only-first loads
(vle8ff.v), so neither string is ever read across 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/strcat-asm.S | 36 ++++++++++++++++++++++++++
 newlib/libc/machine/riscv/strcat.c     |  5 ++++
 3 files changed, 43 insertions(+)
 create mode 100644 newlib/libc/machine/riscv/strcat-asm.S
 create mode 100644 newlib/libc/machine/riscv/strcat.c

diff --git a/newlib/libc/machine/riscv/Makefile.inc b/newlib/libc/machine/riscv/Makefile.inc
index db572be82..b8f4d2f9c 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%/strcat-asm.S \
+	%D%/strcat.c \
 	%D%/strchr-asm.S \
 	%D%/strchr.c \
 	%D%/strchrnul-asm.S \
diff --git a/newlib/libc/machine/riscv/strcat-asm.S b/newlib/libc/machine/riscv/strcat-asm.S
new file mode 100644
index 000000000..edce2f67d
--- /dev/null
+++ b/newlib/libc/machine/riscv/strcat-asm.S
@@ -0,0 +1,36 @@
+#include <sys/asm.h>
+
+#if defined(__riscv_vector) && !defined(__OPTIMIZE_SIZE__) && !defined(PREFER_SIZE_OVER_SPEED)
+ENTRY(strcat)
+  mv a2, a0
+  /* Perform `strlen(a0)`.  */
+.Lstrlen_loop:
+  vsetvli a3, zero, e8, m1, ta, ma
+
+  vle8ff.v v8, (a2)
+  vmseq.vx v0, v8, zero
+  csrr a4, vl
+  vfirst.m a5, v0
+  add a2, a2, a4
+  bltz a5, .Lstrlen_loop
+
+  sub a2, a2, a4
+  add a2, a2, a5
+
+  /* Perform `strcpy(a0 + strlen(a0), a1)`.  */
+.Lstrcpy_loop:
+  vsetvli a3, zero, e8, m1, ta, ma
+
+  vle8ff.v v8, (a1)
+  vmseq.vx v1, v8, zero
+  csrr a4, vl
+  vfirst.m a5, v1
+  vmsif.m v0, v1
+  add a1, a1, a4
+  vse8.v v8, (a2), v0.t
+  add a2, a2, a4
+  bltz a5, .Lstrcpy_loop
+
+  ret
+END(strcat)
+#endif
diff --git a/newlib/libc/machine/riscv/strcat.c b/newlib/libc/machine/riscv/strcat.c
new file mode 100644
index 000000000..e4daff495
--- /dev/null
+++ b/newlib/libc/machine/riscv/strcat.c
@@ -0,0 +1,5 @@
+#if defined(__OPTIMIZE_SIZE__) || defined(PREFER_SIZE_OVER_SPEED) || !defined(__riscv_vector)
+# include "../../string/strcat.c"
+#else
+/* strcat defined in strcat-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.