[glibc] riscv: Add RVV strcpy for both multiarch and non-multiarch builds

Peter Bergner via Glibc-cvs <[email protected]>
Newsgroups gmane.comp.lib.glibc.cvs
Message-ID <[email protected]>
https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=40fb13ac3de0dbd792d9fe09230dc0d0d4cde444

commit 40fb13ac3de0dbd792d9fe09230dc0d0d4cde444
Author: Yao Zihong <[email protected]>
Date:   Mon Apr 20 16:19:08 2026 -0500

    riscv: Add RVV strcpy for both multiarch and non-multiarch builds
    
    This patch adds an RVV-optimized implementation of strcpy for RISC-V and
    enables it for both multiarch (IFUNC) and non-multiarch builds.
    
    The implementation integrates Hau Hsu's 2023 RVV work under a unified
    ifunc-based framework. A vectorized version (__strcpy_vector) is added
    alongside the generic fallback (__strcpy_generic). The runtime resolver
    selects the RVV variant when RISCV_HWPROBE_KEY_IMA_EXT_0 reports vector
    support (RVV).
    
    Currently, the resolver still selects the RVV variant even when the RVV
    extension is disabled via prctl(). As a consequence, any process that
    has RVV disabled via prctl() will receive SIGILL when calling strcpy().
    
    Co-authored-by: Hau Hsu <[email protected]>
    Co-authored-by: Jerry Shih <[email protected]>
    Signed-off-by: Yao Zihong <[email protected]>
    Reviewed-by: Peter Bergner <[email protected]>

Diff:
---
 sysdeps/riscv/multiarch/strcpy-generic.c           | 26 ++++++++++
 sysdeps/riscv/multiarch/strcpy-vector.S            | 24 +++++++++
 sysdeps/riscv/rvv/strcpy.S                         | 59 ++++++++++++++++++++++
 sysdeps/unix/sysv/linux/riscv/multiarch/Makefile   |  3 ++
 .../sysv/linux/riscv/multiarch/ifunc-impl-list.c   |  5 ++
 sysdeps/unix/sysv/linux/riscv/multiarch/strcpy.c   | 56 ++++++++++++++++++++
 6 files changed, 173 insertions(+)

diff --git a/sysdeps/riscv/multiarch/strcpy-generic.c b/sysdeps/riscv/multiarch/strcpy-generic.c
new file mode 100644
index 0000000000..8a29992570
--- /dev/null
+++ b/sysdeps/riscv/multiarch/strcpy-generic.c
@@ -0,0 +1,26 @@
+/* Re-include the default strcpy implementation.
+   Copyright (C) 2026 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <string.h>
+
+#if IS_IN(libc)
+# define STRCPY __strcpy_generic
+# undef libc_hidden_builtin_def
+# define libc_hidden_builtin_def(x)
+# include <string/strcpy.c>
+#endif
diff --git a/sysdeps/riscv/multiarch/strcpy-vector.S b/sysdeps/riscv/multiarch/strcpy-vector.S
new file mode 100644
index 0000000000..f5381a98ce
--- /dev/null
+++ b/sysdeps/riscv/multiarch/strcpy-vector.S
@@ -0,0 +1,24 @@
+/* Re-include the RISC-V RVV based strcpy implementation.
+   Copyright (C) 2026 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#if IS_IN(libc)
+# define STRCPY __strcpy_vector
+# undef libc_hidden_builtin_def
+# define libc_hidden_builtin_def(name)
+# include <sysdeps/riscv/rvv/strcpy.S>
+#endif
diff --git a/sysdeps/riscv/rvv/strcpy.S b/sysdeps/riscv/rvv/strcpy.S
new file mode 100644
index 0000000000..e73558d812
--- /dev/null
+++ b/sysdeps/riscv/rvv/strcpy.S
@@ -0,0 +1,59 @@
+/* RISC-V RVV based strcpy.
+   Copyright (C) 2026 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <sysdep.h>
+#include <sys/asm.h>
+
+#ifndef STRCPY
+# define STRCPY strcpy
+#endif
+
+#define dst a0
+#define src a1
+#define dst_ptr a2
+
+#define ivl a3
+#define cur_vl a4
+#define active_elem_pos a5
+
+#define ELEM_LMUL_SETTING m1
+#define vmask1 v0
+#define vmask2 v1
+#define vstr1 v8
+#define vstr2 v16
+
+ENTRY (STRCPY)
+.option push
+.option arch, +v
+    mv dst_ptr, dst
+L(strcpy_loop):
+    vsetvli ivl, zero, e8, ELEM_LMUL_SETTING, ta, ma
+    vle8ff.v vstr1, (src)
+    vmseq.vx vmask2, vstr1, zero
+    csrr cur_vl, vl
+    vfirst.m active_elem_pos, vmask2
+    vmsif.m vmask1, vmask2
+    add src, src, cur_vl
+    vse8.v vstr1, (dst_ptr), vmask1.t
+    add dst_ptr, dst_ptr, cur_vl
+    bltz active_elem_pos, L(strcpy_loop)
+
+    ret
+.option pop
+END (STRCPY)
+libc_hidden_builtin_def (strcpy)
diff --git a/sysdeps/unix/sysv/linux/riscv/multiarch/Makefile b/sysdeps/unix/sysv/linux/riscv/multiarch/Makefile
index 41ba27793d..c82693251a 100644
--- a/sysdeps/unix/sysv/linux/riscv/multiarch/Makefile
+++ b/sysdeps/unix/sysv/linux/riscv/multiarch/Makefile
@@ -9,6 +9,9 @@ sysdep_routines += \
   strcat \
   strcat-generic \
   strcat-vector \
+  strcpy \
+  strcpy-generic \
+  strcpy-vector \
   # sysdep_routines
 
 CFLAGS-memcpy_noalignment.c += -mno-strict-align
diff --git a/sysdeps/unix/sysv/linux/riscv/multiarch/ifunc-impl-list.c b/sysdeps/unix/sysv/linux/riscv/multiarch/ifunc-impl-list.c
index af64c04249..f4154bb8f7 100644
--- a/sysdeps/unix/sysv/linux/riscv/multiarch/ifunc-impl-list.c
+++ b/sysdeps/unix/sysv/linux/riscv/multiarch/ifunc-impl-list.c
@@ -58,5 +58,10 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
 			      __strcat_vector)
 	      IFUNC_IMPL_ADD (array, i, strcat, 1, __strcat_generic))
 
+  IFUNC_IMPL (i, name, strcpy,
+	      IFUNC_IMPL_ADD (array, i, strcpy, rvv_enabled,
+			      __strcpy_vector)
+	      IFUNC_IMPL_ADD (array, i, strcpy, 1, __strcpy_generic))
+
   return 0;
 }
diff --git a/sysdeps/unix/sysv/linux/riscv/multiarch/strcpy.c b/sysdeps/unix/sysv/linux/riscv/multiarch/strcpy.c
new file mode 100644
index 0000000000..ba47e8f89c
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/riscv/multiarch/strcpy.c
@@ -0,0 +1,56 @@
+/* Multiple versions of strcpy.
+   All versions must be listed in ifunc-impl-list.c.
+   Copyright (C) 2026 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#if IS_IN (libc)
+/* Redefine strcpy so that the compiler won't complain about the type
+   mismatch with the IFUNC selector in strong_alias, below.  */
+# undef strcpy
+# define strcpy __redirect_strcpy
+# include <stdint.h>
+# include <string.h>
+# include <ifunc-init.h>
+# include <riscv-ifunc.h>
+# include <sys/hwprobe.h>
+
+extern __typeof (__redirect_strcpy) __libc_strcpy;
+
+extern __typeof (__redirect_strcpy) __strcpy_generic attribute_hidden;
+extern __typeof (__redirect_strcpy) __strcpy_vector attribute_hidden;
+
+static inline __typeof (__redirect_strcpy) *
+select_strcpy_ifunc (uint64_t dl_hwcap, __riscv_hwprobe_t hwprobe_func)
+{
+  unsigned long long int v;
+  if (__riscv_hwprobe_one (hwprobe_func, RISCV_HWPROBE_KEY_IMA_EXT_0, &v) == 0
+      && (v & RISCV_HWPROBE_IMA_V) == RISCV_HWPROBE_IMA_V)
+    return __strcpy_vector;
+  return __strcpy_generic;
+}
+
+riscv_libc_ifunc (__libc_strcpy, select_strcpy_ifunc);
+
+# undef strcpy
+strong_alias (__libc_strcpy, strcpy);
+# ifdef SHARED
+__hidden_ver1 (strcpy, __GI_strcpy, __redirect_strcpy)
+  __attribute__ ((visibility ("hidden"))) __attribute_copy__ (strcpy);
+# endif
+#else
+# include <string/strcpy.c>
+#endif
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.