[PATCH 08/17] riscv: add vectorized strcpy

Pincheng Wang <[email protected]> Thu, 16 Jul 2026 23:00:39 +0800
Newsgroups gmane.comp.lib.newlib
Message-ID <[email protected]>
The vector implementation copies the source in vector-length chunks using
fault-only-first loads (vle8ff.v) and masked stores that include the
terminating NUL, so the source is never read across an unmapped page.
This provides significant performance improvements on RVV-capable
hardware.  Use conditional compilation to fall back to the scalar
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 |  1 +
 newlib/libc/machine/riscv/strcpy-asm.S | 24 ++++++++++++++++++++++++
 newlib/libc/machine/riscv/strcpy.c     |  5 +++++
 3 files changed, 30 insertions(+)
 create mode 100644 newlib/libc/machine/riscv/strcpy-asm.S

diff --git a/newlib/libc/machine/riscv/Makefile.inc b/newlib/libc/machine/riscv/Makefile.inc
index 015b91799..334d4351b 100644
--- a/newlib/libc/machine/riscv/Makefile.inc
+++ b/newlib/libc/machine/riscv/Makefile.inc
@@ -26,6 +26,7 @@ libc_a_SOURCES += \
 	%D%/strchrnul.c \
 	%D%/strcmp-asm.S \
 	%D%/strcmp.S \
+	%D%/strcpy-asm.S \
 	%D%/strcpy.c \
 	%D%/strlen-asm.S \
 	%D%/strlen.c \
diff --git a/newlib/libc/machine/riscv/strcpy-asm.S b/newlib/libc/machine/riscv/strcpy-asm.S
new file mode 100644
index 000000000..97c69d64c
--- /dev/null
+++ b/newlib/libc/machine/riscv/strcpy-asm.S
@@ -0,0 +1,24 @@
+#if defined(__riscv_vector) && __riscv_xlen == 64 && !defined(__OPTIMIZE_SIZE__) && !defined(PREFER_SIZE_OVER_SPEED)
+.text
+.option push
+.option arch, +v
+.global strcpy
+.type strcpy, @function
+strcpy:
+  mv a2, a0
+.Lloop:
+  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, .Lloop
+
+  ret
+.size strcpy, .-strcpy
+.option pop
+#endif
diff --git a/newlib/libc/machine/riscv/strcpy.c b/newlib/libc/machine/riscv/strcpy.c
index a05ec1c0f..417ea4529 100644
--- a/newlib/libc/machine/riscv/strcpy.c
+++ b/newlib/libc/machine/riscv/strcpy.c
@@ -9,6 +9,10 @@
    http://www.opensource.org/licenses.
 */
 
+#if defined(__riscv_vector) && __riscv_xlen == 64 && !defined(__OPTIMIZE_SIZE__) && !defined(PREFER_SIZE_OVER_SPEED)
+/* strcpy defined in strcpy-asm.S */
+#else
+
 #include <stdbool.h>
 #include "rv_string.h"
 
@@ -16,3 +20,4 @@ char *strcpy(char *dst, const char *src)
 {
   return __libc_strcpy(dst, src, true);
 }
+#endif
-- 
2.39.5