[glibc] riscv: Add RVV strcat 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=9b5e9799b6af76e91b29334310ecd32096b274c2

commit 9b5e9799b6af76e91b29334310ecd32096b274c2
Author: Yao Zihong <[email protected]>
Date:   Wed Feb 18 15:12:09 2026 -0600

    riscv: Add RVV strcat for both multiarch and non-multiarch builds
    
    This patch adds an RVV-optimized implementation of strcat 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 (__strcat_vector) is added
    alongside the generic fallback (__strcat_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 strcat().
    
    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/strcat-generic.c           | 26 ++++++++
 sysdeps/riscv/multiarch/strcat-vector.S            | 24 +++++++
 sysdeps/riscv/rvv/strcat.S                         | 75 ++++++++++++++++++++++
 sysdeps/unix/sysv/linux/riscv/multiarch/Makefile   |  3 +
 .../sysv/linux/riscv/multiarch/ifunc-impl-list.c   |  5 ++
 sysdeps/unix/sysv/linux/riscv/multiarch/strcat.c   | 56 ++++++++++++++++
 6 files changed, 189 insertions(+)

diff --git a/sysdeps/riscv/multiarch/strcat-generic.c b/sysdeps/riscv/multiarch/strcat-generic.c
new file mode 100644
index 0000000000..e28f8f012c
--- /dev/null
+++ b/sysdeps/riscv/multiarch/strcat-generic.c
@@ -0,0 +1,26 @@
+/* Re-include the default strcat 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 STRCAT __strcat_generic
+# undef libc_hidden_builtin_def
+# define libc_hidden_builtin_def(x)
+# include <string/strcat.c>
+#endif
diff --git a/sysdeps/riscv/multiarch/strcat-vector.S b/sysdeps/riscv/multiarch/strcat-vector.S
new file mode 100644
index 0000000000..581f075fef
--- /dev/null
+++ b/sysdeps/riscv/multiarch/strcat-vector.S
@@ -0,0 +1,24 @@
+/* Re-include the RISC-V RVV based strcat 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 STRCAT __strcat_vector
+# undef libc_hidden_builtin_def
+# define libc_hidden_builtin_def(name)
+# include <sysdeps/riscv/rvv/strcat.S>
+#endif
diff --git a/sysdeps/riscv/rvv/strcat.S b/sysdeps/riscv/rvv/strcat.S
new file mode 100644
index 0000000000..af08ee561f
--- /dev/null
+++ b/sysdeps/riscv/rvv/strcat.S
@@ -0,0 +1,75 @@
+/* RISC-V RVV based strcat.
+   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 STRCAT
+# define STRCAT strcat
+#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 (STRCAT)
+.option push
+.option arch, +v
+    mv dst_ptr, dst
+    /* Perform `strlen(dst)`.  */
+L(strlen_loop):
+    vsetvli ivl, zero, e8, ELEM_LMUL_SETTING, ta, ma
+
+    vle8ff.v vstr1, (dst_ptr)
+    vmseq.vx vmask1, vstr1, zero
+    csrr cur_vl, vl
+    vfirst.m active_elem_pos, vmask1
+    add dst_ptr, dst_ptr, cur_vl
+    bltz active_elem_pos, L(strlen_loop)
+
+    sub dst_ptr, dst_ptr, cur_vl
+    add dst_ptr, dst_ptr, active_elem_pos
+
+    /* Perform `strcpy(dst, src)`.  */
+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 (STRCAT)
+libc_hidden_builtin_def (strcat)
diff --git a/sysdeps/unix/sysv/linux/riscv/multiarch/Makefile b/sysdeps/unix/sysv/linux/riscv/multiarch/Makefile
index a033ea9569..41ba27793d 100644
--- a/sysdeps/unix/sysv/linux/riscv/multiarch/Makefile
+++ b/sysdeps/unix/sysv/linux/riscv/multiarch/Makefile
@@ -6,6 +6,9 @@ sysdep_routines += \
   memset \
   memset-generic \
   memset-vector \
+  strcat \
+  strcat-generic \
+  strcat-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 a3b5731411..af64c04249 100644
--- a/sysdeps/unix/sysv/linux/riscv/multiarch/ifunc-impl-list.c
+++ b/sysdeps/unix/sysv/linux/riscv/multiarch/ifunc-impl-list.c
@@ -53,5 +53,10 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
 			      __memset_vector)
 	      IFUNC_IMPL_ADD (array, i, memset, 1, __memset_generic))
 
+  IFUNC_IMPL (i, name, strcat,
+	      IFUNC_IMPL_ADD (array, i, strcat, rvv_enabled,
+			      __strcat_vector)
+	      IFUNC_IMPL_ADD (array, i, strcat, 1, __strcat_generic))
+
   return 0;
 }
diff --git a/sysdeps/unix/sysv/linux/riscv/multiarch/strcat.c b/sysdeps/unix/sysv/linux/riscv/multiarch/strcat.c
new file mode 100644
index 0000000000..781b0d4cb1
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/riscv/multiarch/strcat.c
@@ -0,0 +1,56 @@
+/* Multiple versions of strcat.
+   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 strcat so that the compiler won't complain about the type
+   mismatch with the IFUNC selector in strong_alias, below.  */
+# undef strcat
+# define strcat __redirect_strcat
+# include <stdint.h>
+# include <string.h>
+# include <ifunc-init.h>
+# include <riscv-ifunc.h>
+# include <sys/hwprobe.h>
+
+extern __typeof (__redirect_strcat) __libc_strcat;
+
+extern __typeof (__redirect_strcat) __strcat_generic attribute_hidden;
+extern __typeof (__redirect_strcat) __strcat_vector attribute_hidden;
+
+static inline __typeof (__redirect_strcat) *
+select_strcat_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 __strcat_vector;
+  return __strcat_generic;
+}
+
+riscv_libc_ifunc (__libc_strcat, select_strcat_ifunc);
+
+# undef strcat
+strong_alias (__libc_strcat, strcat);
+# ifdef SHARED
+__hidden_ver1 (strcat, __GI_strcat, __redirect_strcat)
+  __attribute__ ((visibility ("hidden"))) __attribute_copy__ (strcat);
+# endif
+#else
+# include <string/strcat.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.