[PATCH 10/17] riscv: add vectorized strcat

Pincheng Wang <[email protected]> Thu, 16 Jul 2026 23:00:41 +0800
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 | 40 ++++++++++++++++++++++++++
 newlib/libc/machine/riscv/strcat.c     |  5 ++++
 3 files changed, 47 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..995b8c641
--- /dev/null
+++ b/newlib/libc/machine/riscv/strcat-asm.S
@@ -0,0 +1,40 @@
+#if defined(__riscv_vector) && __riscv_xlen == 64 && !defined(__OPTIMIZE_SIZE__) && !defined(PREFER_SIZE_OVER_SPEED)
+.text
+.option push
+.option arch, +v
+.global strcat
+.type strcat, @function
+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
+.size strcat, .-strcat
+.option pop
+#endif
diff --git a/newlib/libc/machine/riscv/strcat.c b/newlib/libc/machine/riscv/strcat.c
new file mode 100644
index 000000000..915bf0360
--- /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) || __riscv_xlen != 64
+# include "../../string/strcat.c"
+#else
+/* strcat defined in strcat-asm.S */
+#endif
-- 
2.39.5