From 3e2542ccdb5eeb12cc0b65a7d1a8e7d2f74e2626 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E6=9C=B1=E5=A8=9C?= <zhuna.1024@bytedance.com>
Date: Mon, 31 Oct 2022 21:57:49 +0800
Subject: [PATCH] risc-v: Add support on mem* functions with V & B extension
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
To: libc-alpha@sourceware.org

Hi. I wrote mem* functions, taking advantage of RISC-V V & B extensions. SIMD mechanism mostly learned from x86_64 & aarch64 SIMD implementation. Hope I got it right. IFUNCs resolved to multiarchs version by default.

Signed-off-by: 朱娜 <zhuna.1024@bytedance.com>
---
 sysdeps/riscv/hp-timing.h                  |  39 +++++
 sysdeps/riscv/init-arch.h                  |   4 +
 sysdeps/riscv/multiarch/Makefile           |  19 +++
 sysdeps/riscv/multiarch/ifunc-impl-list.c  |  58 ++++++++
 sysdeps/riscv/multiarch/ifunc-memchr.h     |  28 ++++
 sysdeps/riscv/multiarch/ifunc-memcmp.h     |  28 ++++
 sysdeps/riscv/multiarch/ifunc-memcmpeq.h   |  29 ++++
 sysdeps/riscv/multiarch/ifunc-memcpy.h     |  28 ++++
 sysdeps/riscv/multiarch/ifunc-memset.h     |  28 ++++
 sysdeps/riscv/multiarch/memchr-rvv-vlen.S  | 118 +++++++++++++++
 sysdeps/riscv/multiarch/memchr-rvv.S       | 132 +++++++++++++++++
 sysdeps/riscv/multiarch/memchr.c           |  35 +++++
 sysdeps/riscv/multiarch/memcmp-rvv-vlen.S  | 120 ++++++++++++++++
 sysdeps/riscv/multiarch/memcmp-rvv.S       | 158 +++++++++++++++++++++
 sysdeps/riscv/multiarch/memcmp.c           |  35 +++++
 sysdeps/riscv/multiarch/memcmpeq.c         |  35 +++++
 sysdeps/riscv/multiarch/memcpy-rvv-vlen.S  | 100 +++++++++++++
 sysdeps/riscv/multiarch/memcpy-rvv.S       | 127 +++++++++++++++++
 sysdeps/riscv/multiarch/memcpy.c           |  35 +++++
 sysdeps/riscv/multiarch/memmove-rvv-vlen.S | 110 ++++++++++++++
 sysdeps/riscv/multiarch/memmove-rvv.S      | 138 ++++++++++++++++++
 sysdeps/riscv/multiarch/memset-rvv-vlen.S  |  94 ++++++++++++
 sysdeps/riscv/multiarch/memset-rvv.S       | 126 ++++++++++++++++
 sysdeps/riscv/multiarch/memset.c           |  35 +++++
 24 files changed, 1659 insertions(+)
 create mode 100644 sysdeps/riscv/hp-timing.h
 create mode 100644 sysdeps/riscv/init-arch.h
 create mode 100644 sysdeps/riscv/multiarch/Makefile
 create mode 100644 sysdeps/riscv/multiarch/ifunc-impl-list.c
 create mode 100644 sysdeps/riscv/multiarch/ifunc-memchr.h
 create mode 100644 sysdeps/riscv/multiarch/ifunc-memcmp.h
 create mode 100644 sysdeps/riscv/multiarch/ifunc-memcmpeq.h
 create mode 100644 sysdeps/riscv/multiarch/ifunc-memcpy.h
 create mode 100644 sysdeps/riscv/multiarch/ifunc-memset.h
 create mode 100644 sysdeps/riscv/multiarch/memchr-rvv-vlen.S
 create mode 100644 sysdeps/riscv/multiarch/memchr-rvv.S
 create mode 100644 sysdeps/riscv/multiarch/memchr.c
 create mode 100644 sysdeps/riscv/multiarch/memcmp-rvv-vlen.S
 create mode 100644 sysdeps/riscv/multiarch/memcmp-rvv.S
 create mode 100644 sysdeps/riscv/multiarch/memcmp.c
 create mode 100644 sysdeps/riscv/multiarch/memcmpeq.c
 create mode 100644 sysdeps/riscv/multiarch/memcpy-rvv-vlen.S
 create mode 100644 sysdeps/riscv/multiarch/memcpy-rvv.S
 create mode 100644 sysdeps/riscv/multiarch/memcpy.c
 create mode 100644 sysdeps/riscv/multiarch/memmove-rvv-vlen.S
 create mode 100644 sysdeps/riscv/multiarch/memmove-rvv.S
 create mode 100644 sysdeps/riscv/multiarch/memset-rvv-vlen.S
 create mode 100644 sysdeps/riscv/multiarch/memset-rvv.S
 create mode 100644 sysdeps/riscv/multiarch/memset.c

diff --git a/sysdeps/riscv/hp-timing.h b/sysdeps/riscv/hp-timing.h
new file mode 100644
index 0000000000..f728d864a1
--- /dev/null
+++ b/sysdeps/riscv/hp-timing.h
@@ -0,0 +1,39 @@
+/* High precision, low overhead timing functions.  RISC-V version.
+   Copyright (C) 2021-2022 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/>.  */
+
+#ifndef _HP_TIMING_H
+#define _HP_TIMING_H	1
+
+#include <time.h>
+#include <stdint.h>
+#include <hp-timing-common.h>
+#include <libc-symbols.h>
+
+/* Don't use inline timer in ld.so.  */
+#if IS_IN(rtld)
+# define HP_TIMING_INLINE	(0)
+#else
+# define HP_TIMING_INLINE	(1)
+#endif
+
+typedef uint64_t hp_timing_t;
+
+#define HP_TIMING_NOW(var) \
+  __asm__ __volatile__ ("rdcycle %0 " : "=r" (var)) \
+
+#endif	/* hp-timing.h */
diff --git a/sysdeps/riscv/init-arch.h b/sysdeps/riscv/init-arch.h
new file mode 100644
index 0000000000..85dfc4e398
--- /dev/null
+++ b/sysdeps/riscv/init-arch.h
@@ -0,0 +1,4 @@
+#include <ldsodefs.h>
+#include <ifunc-init.h>
+
+# define INIT_ARCH()    
diff --git a/sysdeps/riscv/multiarch/Makefile b/sysdeps/riscv/multiarch/Makefile
new file mode 100644
index 0000000000..5bd02ab974
--- /dev/null
+++ b/sysdeps/riscv/multiarch/Makefile
@@ -0,0 +1,19 @@
+ifeq ($(subdir),string)
+sysdep_routines += \
+  memset-rvv \
+  memcpy-rvv \
+  memcmp-rvv \
+  memchr-rvv \
+  memmove-rvv \
+  memset-rvv-vlen \
+  memcpy-rvv-vlen \
+  memcmp-rvv-vlen \
+  memchr-rvv-vlen \
+  memmove-rvv-vlen \
+  # generic-memset \
+  # generic-memchr \
+  # generic-memcpy \
+  # generic-memcmp \
+
+# sysdep_routines
+endif
diff --git a/sysdeps/riscv/multiarch/ifunc-impl-list.c b/sysdeps/riscv/multiarch/ifunc-impl-list.c
new file mode 100644
index 0000000000..efb0d1cdb5
--- /dev/null
+++ b/sysdeps/riscv/multiarch/ifunc-impl-list.c
@@ -0,0 +1,58 @@
+/* Enumerate available IFUNC implementations of a function.  RISCV64 version.
+   Copyright (C) 2012-2022 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 <assert.h>
+#include <string.h>
+#include <wchar.h>
+#include <ifunc-impl-list.h>
+#include <stdio.h>
+
+
+/* Fill ARRAY of MAX elements with IFUNC implementations for function
+   NAME supported on target machine and return the number of valid
+   entries.  Each set of implementations for a given function is sorted in
+   descending order by ISA level.  */
+
+size_t
+__libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
+			size_t max)
+{
+  size_t i = max;
+
+  /* Support sysdeps/riscv/multiarch/memset-rvv.S.  */
+  IFUNC_IMPL (i, name, memset,
+	      IFUNC_IMPL_ADD (array, i, memset, 1, memset_rvv)
+	      IFUNC_IMPL_ADD (array, i, memset, 1, memset_rvv_vlen)
+	     );
+  /* Support sysdeps/riscv/multiarch/memcpy-rvv.S.  */
+  IFUNC_IMPL (i, name, memcpy,
+	      IFUNC_IMPL_ADD (array, i, memcpy, 1, memcpy_rvv)
+	      IFUNC_IMPL_ADD (array, i, memcpy, 1, memcpy_rvv_vlen)
+	     );
+  /* Support sysdeps/riscv/multiarch/memcmp-rvv.S.  */
+  IFUNC_IMPL (i, name, memcmp,
+	      IFUNC_IMPL_ADD (array, i, memcmp, 1, memcmp_rvv)
+	      IFUNC_IMPL_ADD (array, i, memcmp, 1, memcmp_rvv_vlen)
+	     );
+  /* Support sysdeps/riscv/multiarch/memchr-rvv.S.  */
+  IFUNC_IMPL (i, name, memchr,
+	      IFUNC_IMPL_ADD (array, i, memchr, 1, memchr_rvv)
+	      IFUNC_IMPL_ADD (array, i, memchr, 1, memchr_rvv_vlen)
+	     );
+  return 0;
+}
diff --git a/sysdeps/riscv/multiarch/ifunc-memchr.h b/sysdeps/riscv/multiarch/ifunc-memchr.h
new file mode 100644
index 0000000000..25e2500864
--- /dev/null
+++ b/sysdeps/riscv/multiarch/ifunc-memchr.h
@@ -0,0 +1,28 @@
+/* All versions must be listed in ifunc-memchr.c.
+   Copyright (C) 2017-2022 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 <init-arch.h>
+
+extern __typeof (REDIRECT_NAME) memchr_rvv attribute_hidden;
+extern __typeof (REDIRECT_NAME) memchr_rvv_vlen attribute_hidden;
+
+static inline void *
+IFUNC_SELECTOR (void)
+{
+  return memchr_rvv_vlen;
+}
diff --git a/sysdeps/riscv/multiarch/ifunc-memcmp.h b/sysdeps/riscv/multiarch/ifunc-memcmp.h
new file mode 100644
index 0000000000..b86a6615b8
--- /dev/null
+++ b/sysdeps/riscv/multiarch/ifunc-memcmp.h
@@ -0,0 +1,28 @@
+/* All versions must be listed in ifunc-memcmp.c.
+   Copyright (C) 2017-2022 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 <init-arch.h>
+
+extern __typeof (REDIRECT_NAME) memcmp_rvv attribute_hidden;
+extern __typeof (REDIRECT_NAME) memcmp_rvv_vlen attribute_hidden;
+
+static inline void *
+IFUNC_SELECTOR (void)
+{
+  return memcmp_rvv_vlen;
+}
diff --git a/sysdeps/riscv/multiarch/ifunc-memcmpeq.h b/sysdeps/riscv/multiarch/ifunc-memcmpeq.h
new file mode 100644
index 0000000000..877edc94f4
--- /dev/null
+++ b/sysdeps/riscv/multiarch/ifunc-memcmpeq.h
@@ -0,0 +1,29 @@
+/* Common definition for __memcmpeq ifunc selections.
+   All versions must be listed in ifunc-impl-list.c.
+   Copyright (C) 2017-2022 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 <init-arch.h>
+
+extern __typeof (REDIRECT_NAME) memcmp_rvv attribute_hidden;
+extern __typeof (REDIRECT_NAME) memcmp_rvv_vlen attribute_hidden;
+
+static inline void *
+IFUNC_SELECTOR (void)
+{
+  return memcmp_rvv_vlen;
+}
diff --git a/sysdeps/riscv/multiarch/ifunc-memcpy.h b/sysdeps/riscv/multiarch/ifunc-memcpy.h
new file mode 100644
index 0000000000..d4e1d9004b
--- /dev/null
+++ b/sysdeps/riscv/multiarch/ifunc-memcpy.h
@@ -0,0 +1,28 @@
+/* All versions must be listed in ifunc-memcpy.c.
+   Copyright (C) 2017-2022 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 <init-arch.h>
+
+extern __typeof (REDIRECT_NAME) memcpy_rvv attribute_hidden;
+extern __typeof (REDIRECT_NAME) memcpy_rvv_vlen attribute_hidden;
+
+static inline void *
+IFUNC_SELECTOR (void)
+{
+  return memcpy_rvv_vlen;
+}
diff --git a/sysdeps/riscv/multiarch/ifunc-memset.h b/sysdeps/riscv/multiarch/ifunc-memset.h
new file mode 100644
index 0000000000..d8301009f2
--- /dev/null
+++ b/sysdeps/riscv/multiarch/ifunc-memset.h
@@ -0,0 +1,28 @@
+/* All versions must be listed in ifunc-memset.c.
+   Copyright (C) 2017-2022 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 <init-arch.h>
+
+extern __typeof (REDIRECT_NAME) memset_rvv attribute_hidden;
+extern __typeof (REDIRECT_NAME) memset_rvv_vlen attribute_hidden;
+
+static inline void *
+IFUNC_SELECTOR (void)
+{
+  return memset_rvv_vlen;
+}
diff --git a/sysdeps/riscv/multiarch/memchr-rvv-vlen.S b/sysdeps/riscv/multiarch/memchr-rvv-vlen.S
new file mode 100644
index 0000000000..26635aa5ff
--- /dev/null
+++ b/sysdeps/riscv/multiarch/memchr-rvv-vlen.S
@@ -0,0 +1,118 @@
+/* Copyright (C) 2017-2022 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/>.  */
+   
+	.text
+	.globl	memchr_rvv_vlen                 # -- Begin function memchr_rvv
+	.p2align	1
+	.type	memchr_rvv_vlen,@function
+
+# a0: src a1: c a2: nbyte
+#define SRC a0
+#define SRC_END a7
+#define CC a1
+#define CC_U8 a6
+#define NBYTE a2
+# utilities
+#define VLEN a3
+#define CTZ_I a4
+#define XLEN a5
+#define ALIGN 8
+#define L(label) .memchr_rvv_vlen_##label
+
+memchr_rvv_vlen:
+	beqz NBYTE, L(not_found)
+	add SRC_END, SRC, NBYTE
+	addi XLEN, zero, 8  # xlen = 8B
+	# to uint8
+	andi CC, CC, 0xff
+	mv CC_U8, CC
+	# broadcast in uint64
+	slli t0, CC, 8     # t0 = CC << 8
+	or CC, t0, CC      # CC = CC | t0
+	slli t0, CC, 16    # t0 = CC << 16
+	or CC, t0, CC      # CC = CC | t0
+	slli t0, CC, 32    # t0 = CC << 32
+	or CC, t0, CC      # CC = CC | t0
+# BEGIN small lengths
+	addi t1, zero, 16
+	addi VLEN, zero, -1
+	vsetvli VLEN, VLEN, e8, m8, ta, ma
+	# blt NBYTE, t1, L(less_m8x1)
+	slli t1, VLEN, 1
+	blt NBYTE, t1, L(m8x1_loop)
+# END small length
+# nbyte >= vlen x 2
+
+# BEGIN align on 8B
+	andi t0, SRC, 7
+	beqz t0, L(vec_set)
+	sub t0, zero, t0
+	addi t0, t0, 8
+	ld t2, (SRC)
+	xor t1, CC, t2
+	orc.b t3, t1
+	xori t3, t3, -1
+	ctz CTZ_I, t3
+	srli CTZ_I, CTZ_I, 3
+	bne CTZ_I, XLEN, L(found)
+	add SRC, SRC, t0
+# END align on 8B
+# BEGIN VEC STORE BULK
+L(vec_set):
+# t0: total vlen * 2  t1: src + total vlen * 2
+	slli t0, VLEN, 1
+	add t1, SRC, t0
+	blt SRC_END, t1, L(m8x2_loop_end)  # branch if less than total vlen
+# use many t* to exploit data parallelism
+L(m8x2_loop):
+	vle8.v	v0, (SRC)
+	add t2, SRC, VLEN
+	vle8.v	v16, (t2)
+	vmseq.vx v8, v0, CC
+	vmseq.vx v24, v16, CC
+	vfirst.m	CTZ_I, v8
+	bge CTZ_I, zero, L(found)
+	vfirst.m	CTZ_I, v24
+	mv SRC, t2
+	bge CTZ_I, zero, L(found)
+	add SRC, SRC, VLEN
+	add t1, SRC, t0
+	bge SRC_END, t1, L(m8x2_loop)  # branch if less than total vlen
+L(m8x2_loop_end):
+# END VEC STORE BULK
+	sub NBYTE, SRC_END, SRC
+	mv t1, NBYTE
+L(m8x1_loop):
+	mv NBYTE, t1
+	vsetvli VLEN, NBYTE, e8, m8, ta, ma
+	vle8.v	v0, (SRC)
+	vmseq.vx v8, v0, CC
+	vfirst.m	CTZ_I, v8
+	bge CTZ_I, zero, L(found)
+	add SRC, SRC, VLEN
+	sub t1, NBYTE, VLEN
+	bnez t1, L(m8x1_loop)
+	# not found
+	mv a0, zero
+	ret
+L(found):
+	add SRC, SRC, CTZ_I
+	bge SRC, SRC_END, L(not_found)
+	ret
+L(not_found):
+	mv a0, zero
+	ret
diff --git a/sysdeps/riscv/multiarch/memchr-rvv.S b/sysdeps/riscv/multiarch/memchr-rvv.S
new file mode 100644
index 0000000000..36b6ccb80f
--- /dev/null
+++ b/sysdeps/riscv/multiarch/memchr-rvv.S
@@ -0,0 +1,132 @@
+/* Copyright (C) 2017-2022 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/>.  */
+   
+	.text
+	.globl	memchr_rvv                 # -- Begin function memchr_rvv
+	.p2align	1
+	.type	memchr_rvv,@function
+
+# a0: src a1: c a2: nbyte
+#define SRC a0
+#define SRC_END a7
+#define CC a1
+#define CC_U8 a6
+#define NBYTE a2
+# utilities
+#define VLEN a3
+#define CTZ_I a4
+#define XLEN a5
+#define ALIGN 8
+#define L(label) .memchr_rvv_##label
+
+memchr_rvv:
+	beqz NBYTE, L(not_found)
+	add SRC_END, SRC, NBYTE
+	addi XLEN, zero, 8  # xlen = 8B
+	# to uint8
+	andi CC, CC, 0xff
+	mv CC_U8, CC
+	# broadcast in uint64
+	slli t0, CC, 8     # t0 = CC << 8
+	or CC, t0, CC      # CC = CC | t0
+	slli t0, CC, 16    # t0 = CC << 16
+	or CC, t0, CC      # CC = CC | t0
+	slli t0, CC, 32    # t0 = CC << 32
+	or CC, t0, CC      # CC = CC | t0
+# BEGIN small lengths
+	addi t1, zero, 16
+	addi VLEN, zero, -1
+	vsetvli VLEN, VLEN, e8, m8, ta, ma
+	blt NBYTE, t1, L(less_m8x1)
+	slli t1, VLEN, 1
+	blt NBYTE, t1, L(less_m8x2)
+# END small length
+# nbyte >= vlen x 2
+
+# BEGIN align on 8B
+	andi t0, SRC, 7
+	beqz t0, L(vec_set)
+	sub t0, zero, t0
+	addi t0, t0, 8
+	ld t2, (SRC)
+	xor t1, CC, t2
+	orc.b t3, t1
+	xori t3, t3, -1
+	ctz CTZ_I, t3
+	srli CTZ_I, CTZ_I, 3
+	bne CTZ_I, XLEN, L(found)
+	add SRC, SRC, t0
+# END align on 8B
+# BEGIN VEC STORE BULK
+L(vec_set):
+# t0: total vlen * 2  t1: src + total vlen * 2
+	slli t0, VLEN, 1
+	add t1, SRC, t0
+	blt SRC_END, t1, L(m8x2_loop_end)  # branch if less than total vlen
+# use many t* to exploit data parallelism
+L(m8x2_loop):
+	vle8.v	v0, (SRC)
+	add t2, SRC, VLEN
+	vle8.v	v16, (t2)
+	vmseq.vx v8, v0, CC
+	vmseq.vx v24, v16, CC
+	vfirst.m	CTZ_I, v8
+	bge CTZ_I, zero, L(found)
+	vfirst.m	CTZ_I, v24
+	mv SRC, t2
+	bge CTZ_I, zero, L(found)
+	add SRC, SRC, VLEN
+	add t1, SRC, t0
+	bge SRC_END, t1, L(m8x2_loop)  # branch if less than total vlen
+L(m8x2_loop_end):
+# END VEC STORE BULK
+	sub NBYTE, SRC_END, SRC
+
+L(less_m8x2):
+	blt NBYTE, VLEN, L(less_m8x1)
+	# nbyte >= vlen(m8) * 1
+	# 1 load followed by an overlap load
+	sub t1, SRC_END, VLEN
+	# first load
+	vle8.v	v0, (SRC)
+	vmseq.vx v8, v0, CC
+	# overlap load
+	vle8.v	v16, (t1)
+	vmseq.vx v24, v16, CC
+	vfirst.m	CTZ_I, v8
+	bge CTZ_I, zero, L(found)
+	vfirst.m	CTZ_I, v24
+	bge CTZ_I, zero, L(found)
+	# not found
+	mv a0, zero
+	ret
+L(less_m8x1):
+	vsetvli VLEN, NBYTE, e8, m8, ta, ma
+	vle8.v	v0, (SRC)
+	vmseq.vx v8, v0, CC
+	vfirst.m	CTZ_I, v8
+	bge CTZ_I, zero, L(found)
+	# not found
+	mv a0, zero
+	ret
+L(found):
+	add SRC, SRC, CTZ_I
+	bge SRC, SRC_END, L(not_found)
+	ret
+L(not_found):
+	mv a0, zero
+	ret
diff --git a/sysdeps/riscv/multiarch/memchr.c b/sysdeps/riscv/multiarch/memchr.c
new file mode 100644
index 0000000000..89391e7821
--- /dev/null
+++ b/sysdeps/riscv/multiarch/memchr.c
@@ -0,0 +1,35 @@
+/* Multiple versions of memchr.
+   All versions must be listed in ifunc-impl-list.c.
+   Copyright (C) 2017-2022 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/>.  */
+
+/* Define multiple versions only for the definition in libc.  */
+#if IS_IN (libc)
+# define memchr __redirect_memchr
+# include <string.h>
+# undef memchr
+
+# define SYMBOL_NAME memchr
+# include "ifunc-memchr.h"
+
+libc_ifunc_redirected (__redirect_memchr, memchr, IFUNC_SELECTOR ());
+
+# ifdef SHARED
+__hidden_ver1 (memchr, __GI_memchr, __redirect_memchr)
+  __attribute__ ((visibility ("hidden"))) __attribute_copy__ (memchr);
+# endif
+#endif
diff --git a/sysdeps/riscv/multiarch/memcmp-rvv-vlen.S b/sysdeps/riscv/multiarch/memcmp-rvv-vlen.S
new file mode 100644
index 0000000000..875c5bbbf3
--- /dev/null
+++ b/sysdeps/riscv/multiarch/memcmp-rvv-vlen.S
@@ -0,0 +1,120 @@
+/* Copyright (C) 2017-2022 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/>.  */
+   
+	.text
+	.globl	memcmp_rvv_vlen                 # -- Begin function memchr_rvv
+	.p2align	1
+	.type	memcmp_rvv_vlen,@function
+
+# a0: src1 a1: src2 a2: nbyte
+#define SRC1 a0
+#define SRC2 a1
+#define NBYTE a2
+#define SRC_END1 a5
+#define SRC_END2 a6
+# utilities
+#define VLEN a3
+#define XLEN a4
+#define MASK a7
+#define L(label) .memcmp_rvv_vlen_##label
+
+memcmp_rvv_vlen:
+	bnez NBYTE, L(gt_0)
+	mv a0, zero
+	ret
+L(gt_0):
+	add SRC_END1, SRC1, NBYTE
+	add SRC_END2, SRC2, NBYTE
+
+	addi VLEN, zero, -1
+	vsetvli VLEN, VLEN, e8, m8, ta, ma
+	# blt NBYTE, VLEN, L(less_m8x1)
+	slli t0, VLEN, 1
+	blt NBYTE, t0, L(m8x2_loop_end)
+# nbyte >= vlen x 2
+
+L(m8x2_loop):
+	# load first
+	vle8.v	v0, (SRC1)
+	add t2, SRC1, VLEN
+	vle8.v	v8, (SRC2)
+	add t3, SRC2, VLEN
+	# compare first
+	vmsne.vv v24, v0, v8
+	vfirst.m t1, v24
+	blt t1, zero, L(m8x2_loop_first_not_found)
+	# found in first load
+	vslidedown.vx v0, v0, t1
+	vslidedown.vx v8, v8, t1
+	vmv.x.s t0, v0
+	vmv.x.s t1, v8
+	andi t0, t0, 0xff
+	andi t1, t1, 0xff
+	sub a0, t0, t1
+	ret
+L(m8x2_loop_first_not_found):
+	# load second
+	vle8.v v16, (t2)
+	vle8.v v24, (t3)
+	# compare second
+	vmsne.vv v16, v16, v24
+	vfirst.m t1, v16
+	blt t1, zero, L(m8x2_loop_second_not_found)
+	# found in second load
+	vslidedown.vx v16, v16, t1
+	vslidedown.vx v24, v24, t1
+	vmv.x.s t0, v16
+	vmv.x.s t1, v24
+	andi t0, t0, 0xff
+	andi t1, t1, 0xff
+	sub a0, t0, t1
+	ret
+L(m8x2_loop_second_not_found):
+	add SRC1, t2, VLEN
+	add SRC2, t3, VLEN 
+	add t1, SRC1, t0
+	blt t1, SRC_END1, L(m8x2_loop)
+L(m8x2_loop_end):
+# END VEC STORE BULK
+	sub NBYTE, SRC_END1, SRC1
+	mv t1, NBYTE
+L(m8x1_loop):
+	mv NBYTE, t1
+	vsetvli VLEN, NBYTE, e8, m8, ta, ma
+	vle8.v	v0, (SRC1)
+	vle8.v	v8, (SRC2)
+	vmsne.vv v24, v0, v8
+	vfirst.m t1, v24
+	blt t1, zero, L(m8x1_loop_not_found)
+	# found
+	vslidedown.vx v0, v0, t1
+	vslidedown.vx v8, v8, t1
+	vmv.x.s t0, v0
+	vmv.x.s t1, v8
+	andi t0, t0, 0xff
+	andi t1, t1, 0xff
+	sub a0, t0, t1
+	ret
+L(m8x1_loop_not_found):
+	add SRC1, SRC1, VLEN
+	add SRC2, SRC2, VLEN
+	sub t1, NBYTE, VLEN
+	bnez t1, L(m8x1_loop)
+	# not found
+	mv a0, zero
+	ret
+	
\ No newline at end of file
diff --git a/sysdeps/riscv/multiarch/memcmp-rvv.S b/sysdeps/riscv/multiarch/memcmp-rvv.S
new file mode 100644
index 0000000000..b60486db21
--- /dev/null
+++ b/sysdeps/riscv/multiarch/memcmp-rvv.S
@@ -0,0 +1,158 @@
+/* Copyright (C) 2017-2022 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/>.  */
+   
+	.text
+	.globl	memcmp_rvv                 # -- Begin function memchr_rvv
+	.p2align	1
+	.type	memcmp_rvv,@function
+
+# a0: src1 a1: src2 a2: nbyte
+#define SRC1 a0
+#define SRC2 a1
+#define NBYTE a2
+#define SRC_END1 a5
+#define SRC_END2 a6
+# utilities
+#define VLEN a3
+#define XLEN a4
+#define MASK a7
+#define L(label) .memcmp_rvv_##label
+
+memcmp_rvv:
+	bnez NBYTE, L(gt_0)
+	mv a0, zero
+	ret
+L(gt_0):
+	add SRC_END1, SRC1, NBYTE
+	add SRC_END2, SRC2, NBYTE
+
+	addi VLEN, zero, -1
+	vsetvli VLEN, VLEN, e8, m8, ta, ma
+	blt NBYTE, VLEN, L(less_m8x1)
+	slli t0, VLEN, 1
+	blt NBYTE, t0, L(less_m8x2)
+# nbyte >= vlen x 2
+
+L(m8x2_loop):
+	# load first
+	vle8.v	v0, (SRC1)
+	add t2, SRC1, VLEN
+	vle8.v	v8, (SRC2)
+	add t3, SRC2, VLEN
+	# compare first
+	vmsne.vv v24, v0, v8
+	vfirst.m t1, v24
+	blt t1, zero, L(m8x2_loop_first_not_found)
+	# found in first load
+	vslidedown.vx v0, v0, t1
+	vslidedown.vx v8, v8, t1
+	vmv.x.s t0, v0
+	vmv.x.s t1, v8
+	andi t0, t0, 0xff
+	andi t1, t1, 0xff
+	sub a0, t0, t1
+	ret
+L(m8x2_loop_first_not_found):
+	# load second
+	vle8.v v16, (t2)
+	vle8.v v24, (t3)
+	# compare second
+	vmsne.vv v16, v16, v24
+	vfirst.m t1, v16
+	blt t1, zero, L(m8x2_loop_second_not_found)
+	# found in second load
+	vslidedown.vx v16, v16, t1
+	vslidedown.vx v24, v24, t1
+	vmv.x.s t0, v16
+	vmv.x.s t1, v24
+	andi t0, t0, 0xff
+	andi t1, t1, 0xff
+	sub a0, t0, t1
+	ret
+L(m8x2_loop_second_not_found):
+	add SRC1, t2, VLEN
+	add SRC2, t3, VLEN 
+	add t1, SRC1, t0
+	blt t1, SRC_END1, L(m8x2_loop)
+L(m8x2_loop_end):
+# END VEC STORE BULK
+	sub NBYTE, SRC_END1, SRC1
+
+L(less_m8x2):
+	blt NBYTE, VLEN, L(less_m8x1)
+	# nbyte >= vlen(m8) * 1
+	# 1 load followed by an overlap load
+	sub t1, SRC_END1, VLEN
+	sub t2, SRC_END2, VLEN
+	# first load
+	vle8.v	v0, (SRC1)
+	vle8.v	v8, (SRC2)
+	vmsne.vv v16, v0, v8
+	vfirst.m t0, v16
+	blt t0, zero, L(less_m8x2_first_not_found)
+	# found in vector
+	vslidedown.vx v0, v0, t0
+	vslidedown.vx v8, v8, t0
+	vmv.x.s t0, v0
+	vmv.x.s t1, v8
+	andi t0, t0, 0xff
+	andi t1, t1, 0xff
+	sub a0, t0, t1
+	ret
+L(less_m8x2_first_not_found):
+	# overlap load
+	vle8.v	v16, (t1)
+	vle8.v	v24, (t2)
+	vmsne.vv v0, v16, v24
+	vfirst.m t0, v0
+	blt t0, zero, L(less_m8x2_second_not_found)
+	# found in vector
+	vslidedown.vx v16, v16, t0
+	vslidedown.vx v24, v24, t0
+	vmv.x.s t0, v16
+	vmv.x.s t1, v24
+	andi t0, t0, 0xff
+	andi t1, t1, 0xff
+	sub a0, t0, t1
+	ret
+L(less_m8x2_second_not_found):
+	# identical
+	mv a0, zero
+	ret
+
+L(less_m8x1):
+	# addi t3, zero, 1
+	# beq NBYTE, t3, L(1byte)
+	vsetvli VLEN, NBYTE, e8, m8, ta, ma
+	vle8.v v0, (SRC1)
+	vle8.v v8, (SRC2)
+	vmsne.vv v16, v0, v8
+	vfirst.m t0, v16
+	blt t0, zero, L(less_m8x1_not_found)
+	# found in vector
+	vslidedown.vx v0, v0, t0
+	vslidedown.vx v8, v8, t0
+	vmv.x.s t0, v0
+	vmv.x.s t1, v8
+	andi t0, t0, 0xff
+	andi t1, t1, 0xff
+	sub a0, t0, t1
+	ret
+L(less_m8x1_not_found):
+	mv a0, zero
+	ret
+	
\ No newline at end of file
diff --git a/sysdeps/riscv/multiarch/memcmp.c b/sysdeps/riscv/multiarch/memcmp.c
new file mode 100644
index 0000000000..bae29d8dad
--- /dev/null
+++ b/sysdeps/riscv/multiarch/memcmp.c
@@ -0,0 +1,35 @@
+/* Multiple versions of memcmp.
+   All versions must be listed in ifunc-impl-list.c.
+   Copyright (C) 2017-2022 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/>.  */
+
+/* Define multiple versions only for the definition in libc.  */
+#if IS_IN (libc)
+# define memcmp __redirect_memcmp
+# include <string.h>
+# undef memcmp
+
+# define SYMBOL_NAME memcmp
+# include "ifunc-memcmp.h"
+
+libc_ifunc_redirected (__redirect_memcmp, memcmp, IFUNC_SELECTOR ());
+
+# ifdef SHARED
+__hidden_ver1 (memcmp, __GI_memcmp, __redirect_memcmp)
+  __attribute__ ((visibility ("hidden"))) __attribute_copy__ (memcmp);
+# endif
+#endif
diff --git a/sysdeps/riscv/multiarch/memcmpeq.c b/sysdeps/riscv/multiarch/memcmpeq.c
new file mode 100644
index 0000000000..aa1c8ad4de
--- /dev/null
+++ b/sysdeps/riscv/multiarch/memcmpeq.c
@@ -0,0 +1,35 @@
+/* Multiple versions of __memcmpeq.
+   All versions must be listed in ifunc-impl-list.c.
+   Copyright (C) 2017-2022 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/>.  */
+
+/* Define multiple versions only for the definition in libc.  */
+#if IS_IN (libc)
+# define __memcmpeq __redirect___memcmpeq
+# include <string.h>
+# undef __memcmpeq
+
+# define SYMBOL_NAME __memcmpeq
+# include "ifunc-memcmpeq.h"
+
+libc_ifunc_redirected (__redirect___memcmpeq, __memcmpeq, IFUNC_SELECTOR ());
+
+# ifdef SHARED
+__hidden_ver1 (__memcmpeq, __GI___memcmpeq, __redirect___memcmpeq)
+    __attribute__ ((visibility ("hidden"))) __attribute_copy__ (__memcmpeq);
+# endif
+#endif
diff --git a/sysdeps/riscv/multiarch/memcpy-rvv-vlen.S b/sysdeps/riscv/multiarch/memcpy-rvv-vlen.S
new file mode 100644
index 0000000000..876c13f509
--- /dev/null
+++ b/sysdeps/riscv/multiarch/memcpy-rvv-vlen.S
@@ -0,0 +1,100 @@
+/* Copyright (C) 2017-2022 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/>.  */
+   
+	.globl	memcpy_rvv_vlen
+	.p2align	1
+	.type	memcpy_rvv_vlen,@function
+# a0: dst a1: src a2: nbyte
+#define DST a5
+#define DST_END a6
+#define SRC a1
+#define SRC_END a4
+#define NBYTE a2
+# utilities
+#define VLEN a3
+#define ALIGN 8
+#define L(label) .memcpy_rvv_vlen_##label
+
+memcpy_rvv_vlen:
+	# return value
+	mv DST, a0
+	add DST_END, DST, NBYTE
+	add SRC_END, SRC, NBYTE
+# BEGIN small lengths
+	# addi t1, zero, 16
+	# blt NBYTE, t1, L(less_16bytes)
+	addi VLEN, zero, -1
+	vsetvli VLEN, VLEN, e8, m8, ta, ma
+	# blt NBYTE, VLEN, L(less_m8x1)
+	slli t1, VLEN, 2
+	blt NBYTE, t1, L(m8x4_loop_end)
+# END small length
+
+# BEGIN check alignment
+# align on 8B
+	andi t0, DST, 7
+	beqz t0, L(vec_set)
+	sub t0, zero, t0
+	addi t0, t0, 8
+	ld t1, (SRC)
+	sd t1, (DST)
+	add SRC, SRC, t0
+	add DST, DST, t0
+# END check alignment
+# BEGIN VEC STORE BULK
+L(vec_set):
+# t0: total vlen * 4  t1: dst + total vlen * 4
+	slli t0, VLEN, 2
+	add t1, DST, t0
+	blt DST_END, t1, L(m8x4_loop_end)  # branch if less than total vlen
+# use many t* to exploit data parallelism
+L(m8x4_loop):
+	# loads
+	vle8.v v0, (SRC)
+	add t1, SRC, VLEN
+	vle8.v v8, (t1)
+	add t2, t1, VLEN
+	vle8.v v16, (t2)
+	add t3, t2, VLEN
+	vle8.v v24, (t3)
+	add SRC, t3, VLEN
+	# store
+	vse8.v v0, (DST)
+	add t1, DST, VLEN
+	vse8.v v8, (t1)
+	add t2, t1, VLEN
+	vse8.v v16, (t2)
+	add t3, t2, VLEN
+	vse8.v v24, (t3)
+	add DST, t3, VLEN
+	# check loop
+	add t4, DST, t0
+	bge DST_END, t4, L(m8x4_loop)  # branch if less than total vlen
+L(m8x4_loop_end):
+# END VEC STORE BULK
+	sub NBYTE, DST_END, DST
+	mv t1, NBYTE
+L(m8x1_loop):
+	mv NBYTE, t1
+	vsetvli VLEN, NBYTE, e8, m8, ta, ma
+	vle8.v v0, (SRC)
+	vse8.v v0, (DST)
+	add SRC, SRC, VLEN
+	add DST, DST, VLEN
+	sub t1, NBYTE, VLEN
+	bnez t1, L(m8x1_loop)
+	ret
diff --git a/sysdeps/riscv/multiarch/memcpy-rvv.S b/sysdeps/riscv/multiarch/memcpy-rvv.S
new file mode 100644
index 0000000000..586a92ee50
--- /dev/null
+++ b/sysdeps/riscv/multiarch/memcpy-rvv.S
@@ -0,0 +1,127 @@
+/* Copyright (C) 2017-2022 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/>.  */
+
+	.globl	memcpy_rvv
+	.p2align	1
+	.type	memcpy_rvv,@function
+# a0: dst a1: src a2: nbyte
+#define DST a5
+#define DST_END a6
+#define SRC a1
+#define SRC_END a4
+#define NBYTE a2
+# utilities
+#define VLEN a3
+#define ALIGN 8
+#define L(label) .memcpy_rvv_##label
+
+memcpy_rvv:
+	# return value
+	mv DST, a0
+	add DST_END, DST, NBYTE
+	add SRC_END, SRC, NBYTE
+# BEGIN small lengths
+	# addi t1, zero, 16
+	# blt NBYTE, t1, L(less_16bytes)
+	addi VLEN, zero, -1
+	vsetvli VLEN, VLEN, e8, m8, ta, ma
+	blt NBYTE, VLEN, L(less_m8x1)
+	slli t1, VLEN, 2
+	blt NBYTE, t1, L(less_m8x4)
+# END small length
+
+# BEGIN check alignment
+# align on 8B
+	andi t0, DST, 7
+	beqz t0, L(vec_set)
+	sub t0, zero, t0
+	addi t0, t0, 8
+	ld t1, (SRC)
+	sd t1, (DST)
+	add SRC, SRC, t0
+	add DST, DST, t0
+# END check alignment
+# BEGIN VEC STORE BULK
+L(vec_set):
+# t0: total vlen * 4  t1: dst + total vlen * 4
+	slli t0, VLEN, 2
+	add t1, DST, t0
+	blt DST_END, t1, L(m8x4_loop_end)  # branch if less than total vlen
+# use many t* to exploit data parallelism
+L(m8x4_loop):
+	# loads
+	vle8.v v0, (SRC)
+	add t1, SRC, VLEN
+	vle8.v v8, (t1)
+	add t2, t1, VLEN
+	vle8.v v16, (t2)
+	add t3, t2, VLEN
+	vle8.v v24, (t3)
+	add SRC, t3, VLEN
+	# store
+	vse8.v v0, (DST)
+	add t1, DST, VLEN
+	vse8.v v8, (t1)
+	add t2, t1, VLEN
+	vse8.v v16, (t2)
+	add t3, t2, VLEN
+	vse8.v v24, (t3)
+	add DST, t3, VLEN
+	# check loop
+	add t4, DST, t0
+	bge DST_END, t4, L(m8x4_loop)  # branch if less than total vlen
+L(m8x4_loop_end):
+# END VEC STORE BULK
+	sub NBYTE, DST_END, DST
+L(less_m8x4):
+	slli t1, VLEN, 1
+	blt NBYTE, t1, L(less_m8x2)
+	# nbyte >= vlen(m8) * 2
+	# loads
+	vle8.v v0, (SRC)
+	add t1, SRC, VLEN
+	vle8.v v8, (t1)
+	sub t2, SRC_END, VLEN
+	vle8.v v24, (t2)
+	sub t3, t2, VLEN
+	vle8.v v16, (t3)
+	# stores
+	vse8.v v0, (DST)
+	add t1, DST, VLEN
+	vse8.v v8, (t1)
+	sub t2, DST_END, VLEN
+	vse8.v v24, (t2)
+	sub t3, t2, VLEN
+	vse8.v v16, (t3)
+	ret
+L(less_m8x2):
+	blt NBYTE, VLEN, L(less_m8x1)
+	# nbyte >= vlen(m8) * 1
+	# loads
+	vle8.v v0, (SRC)
+	sub t1, SRC_END, VLEN
+	vle8.v v8, (t1)
+	# stores
+	vse8.v v0, (DST)
+	sub t2, DST_END, VLEN
+	vse8.v v8, (t2)
+	ret
+L(less_m8x1):
+	vsetvli VLEN, NBYTE, e8, m8, ta, ma
+	vle8.v v8, (SRC)
+	vse8.v v8, (DST)
+	ret
diff --git a/sysdeps/riscv/multiarch/memcpy.c b/sysdeps/riscv/multiarch/memcpy.c
new file mode 100644
index 0000000000..7c90237ad9
--- /dev/null
+++ b/sysdeps/riscv/multiarch/memcpy.c
@@ -0,0 +1,35 @@
+/* Multiple versions of memcpy.
+   All versions must be listed in ifunc-impl-list.c.
+   Copyright (C) 2017-2022 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/>.  */
+
+/* Define multiple versions only for the definition in libc.  */
+#if IS_IN (libc)
+# define memcpy __redirect_memcpy
+# include <string.h>
+# undef memcpy
+
+# define SYMBOL_NAME memcpy
+# include "ifunc-memcpy.h"
+
+libc_ifunc_redirected (__redirect_memcpy, memcpy, IFUNC_SELECTOR ());
+
+# ifdef SHARED
+__hidden_ver1 (memcpy, __GI_memcpy, __redirect_memcpy)
+  __attribute__ ((visibility ("hidden"))) __attribute_copy__ (memcpy);
+# endif
+#endif
diff --git a/sysdeps/riscv/multiarch/memmove-rvv-vlen.S b/sysdeps/riscv/multiarch/memmove-rvv-vlen.S
new file mode 100644
index 0000000000..edc7a7b0ef
--- /dev/null
+++ b/sysdeps/riscv/multiarch/memmove-rvv-vlen.S
@@ -0,0 +1,110 @@
+/* Copyright (C) 2017-2022 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/>.  */
+   
+	.globl	memmove_rvv_vlen
+	.p2align	1
+	.type	memmove_rvv_vlen,@function
+# a0: dst a1: src a2: nbyte
+#define DST a5
+#define DST_END a6
+#define SRC a1
+#define SRC_END a4
+#define NBYTE a2
+# utilities
+#define VLEN a3
+#define ALIGN 8
+#define L(label) .memmove_rvv_vlen_##label
+
+memmove_rvv_vlen:
+	# return value
+	mv DST, a0
+	add DST_END, DST, NBYTE
+	add SRC_END, SRC, NBYTE
+# BEGIN overlapping condition
+    sub t0, DST, SRC
+    blt t0, NBYTE, L(overlapping)  # use memcpy if dst - src >= nbyte
+    mv s1, ra
+    jal ra, memcpy_rvv
+    mv ra, s1
+    ret
+# END overlapping condition
+# BEGIN small lengths
+	# addi t1, zero, 16
+	# blt NBYTE, t1, L(less_16bytes)
+L(overlapping):
+	addi VLEN, zero, -1
+	vsetvli VLEN, VLEN, e8, m8, ta, ma
+	# blt NBYTE, VLEN, L(less_m8x1)
+	slli t1, VLEN, 2
+	blt NBYTE, t1, L(m8x4_loop_end)
+# END small length
+
+# BEGIN check alignment
+# align on 8B
+# hard to get alignment right
+	# andi t0, DST_END, 7
+	# beqz t0, L(vec_set)
+	# ld t1, -8(SRC_END)
+	# sd t1, -8(DST_END)
+	# sub SRC_END, SRC_END, t0
+	# sub DST_END, DST_END, t0
+# END check alignment
+# BEGIN VEC STORE BULK
+L(vec_set):
+# t0: total vlen * 4  t1: dst_end - total vlen * 4
+	slli t0, VLEN, 2
+	sub t1, DST_END, t0
+	blt t1, DST, L(m8x4_loop_end)  # branch if less than total vlen
+# use many t* to exploit data parallelism
+L(m8x4_loop):
+	# loads
+    sub SRC_END, SRC_END, VLEN
+	vle8.v v0, (SRC_END)
+	sub t1, SRC_END, VLEN
+	vle8.v v8, (t1)
+	sub t2, t1, VLEN
+	vle8.v v16, (t2)
+	sub t3, t2, VLEN
+	vle8.v v24, (t3)
+    mv SRC_END, t3
+	# store
+    sub DST_END, DST_END, VLEN
+	vse8.v v0, (DST_END)
+	sub t1, DST_END, VLEN
+	vse8.v v8, (t1)
+	sub t2, t1, VLEN
+	vse8.v v16, (t2)
+	sub t3, t2, VLEN
+	vse8.v v24, (t3)
+	mv DST_END, t3
+	# check loop
+	sub t4, DST_END, t0
+	bge t4, DST, L(m8x4_loop)  # branch if less than total vlen
+L(m8x4_loop_end):
+# END VEC STORE BULK
+	sub NBYTE, DST_END, DST
+    mv t1, NBYTE
+L(m8x1_loop):
+	mv NBYTE, t1
+	vsetvli VLEN, NBYTE, e8, m8, ta, ma
+    sub SRC_END, SRC_END, VLEN
+    sub DST_END, DST_END, VLEN
+	vle8.v v0, (SRC_END)
+	vse8.v v0, (DST_END)
+	sub t1, NBYTE, VLEN
+	bnez t1, L(m8x1_loop)
+	ret
diff --git a/sysdeps/riscv/multiarch/memmove-rvv.S b/sysdeps/riscv/multiarch/memmove-rvv.S
new file mode 100644
index 0000000000..8e40352a23
--- /dev/null
+++ b/sysdeps/riscv/multiarch/memmove-rvv.S
@@ -0,0 +1,138 @@
+/* Copyright (C) 2017-2022 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/>.  */
+   
+	.globl	memmove_rvv
+	.p2align	1
+	.type	memmove_rvv,@function
+# a0: dst a1: src a2: nbyte
+#define DST a5
+#define DST_END a6
+#define SRC a1
+#define SRC_END a4
+#define NBYTE a2
+# utilities
+#define VLEN a3
+#define ALIGN 8
+#define L(label) .memmove_rvv_##label
+
+memmove_rvv:
+	# return value
+	mv DST, a0
+	add DST_END, DST, NBYTE
+	add SRC_END, SRC, NBYTE
+# BEGIN overlapping condition
+    sub t0, DST, SRC
+    blt t0, NBYTE, L(overlapping)  # use memcpy if dst - src >= nbyte
+    mv s1, ra
+    jal ra, memcpy_rvv
+    mv ra, s1
+    ret
+# END overlapping condition
+# BEGIN small lengths
+	# addi t1, zero, 16
+	# blt NBYTE, t1, L(less_16bytes)
+L(overlapping):
+	addi VLEN, zero, -1
+	vsetvli VLEN, VLEN, e8, m8, ta, ma
+	# blt NBYTE, VLEN, L(less_m8x1)
+	slli t1, VLEN, 2
+	blt NBYTE, t1, L(less_m8x4)
+# END small length
+
+# BEGIN check alignment
+# align on 8B
+# hard to get alignment right
+	# andi t0, DST_END, 7
+	# beqz t0, L(vec_set)
+	# ld t1, -8(SRC_END)
+	# sd t1, -8(DST_END)
+	# sub SRC_END, SRC_END, t0
+	# sub DST_END, DST_END, t0
+# END check alignment
+# BEGIN VEC STORE BULK
+L(vec_set):
+# t0: total vlen * 4  t1: dst_end - total vlen * 4
+	slli t0, VLEN, 2
+	sub t1, DST_END, t0
+	blt t1, DST, L(m8x4_loop_end)  # branch if less than total vlen
+# use many t* to exploit data parallelism
+L(m8x4_loop):
+	# loads
+    sub SRC_END, SRC_END, VLEN
+	vle8.v v0, (SRC_END)
+	sub t1, SRC_END, VLEN
+	vle8.v v8, (t1)
+	sub t2, t1, VLEN
+	vle8.v v16, (t2)
+	sub t3, t2, VLEN
+	vle8.v v24, (t3)
+    mv SRC_END, t3
+	# store
+    sub DST_END, DST_END, VLEN
+	vse8.v v0, (DST_END)
+	sub t1, DST_END, VLEN
+	vse8.v v8, (t1)
+	sub t2, t1, VLEN
+	vse8.v v16, (t2)
+	sub t3, t2, VLEN
+	vse8.v v24, (t3)
+	mv DST_END, t3
+	# check loop
+	sub t4, DST_END, t0
+	bge t4, DST, L(m8x4_loop)  # branch if less than total vlen
+L(m8x4_loop_end):
+# END VEC STORE BULK
+	sub NBYTE, DST_END, DST
+L(less_m8x4):
+	slli t1, VLEN, 1
+	blt NBYTE, t1, L(less_m8x2)
+	# nbyte >= vlen(m8) * 2
+	# loads
+	vle8.v v0, (SRC)
+	add t1, SRC, VLEN
+	vle8.v v8, (t1)
+	sub t2, SRC_END, VLEN
+	vle8.v v24, (t2)
+	sub t3, t2, VLEN
+	vle8.v v16, (t3)
+	# stores
+	vse8.v v0, (DST)
+	add t1, DST, VLEN
+	vse8.v v8, (t1)
+	sub t2, DST_END, VLEN
+	vse8.v v24, (t2)
+	sub t3, t2, VLEN
+	vse8.v v16, (t3)
+	ret
+L(less_m8x2):
+	blt NBYTE, VLEN, L(less_m8x1)
+	# nbyte >= vlen(m8) * 1
+	# loads
+	vle8.v v0, (SRC)
+	sub t1, SRC_END, VLEN
+	vle8.v v8, (t1)
+	# stores
+	vse8.v v0, (DST)
+	sub t2, DST_END, VLEN
+	vse8.v v8, (t2)
+	ret
+L(less_m8x1):
+	vsetvli VLEN, NBYTE, e8, m8, ta, ma
+	vle8.v v8, (SRC)
+	vse8.v v8, (DST)
+	ret
+    
\ No newline at end of file
diff --git a/sysdeps/riscv/multiarch/memset-rvv-vlen.S b/sysdeps/riscv/multiarch/memset-rvv-vlen.S
new file mode 100644
index 0000000000..2a015b6900
--- /dev/null
+++ b/sysdeps/riscv/multiarch/memset-rvv-vlen.S
@@ -0,0 +1,94 @@
+/* Copyright (C) 2017-2022 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/>.  */
+	.globl	memset_rvv_vlen
+	.p2align	1
+	.type	memset_rvv_vlen,@function
+# a0: dst a1: c a2: nbyte
+#define DST a5
+#define DST_END a7
+#define CC a1
+#define NBYTE a2
+# utilities
+#define VLEN a3
+#define A4 a4
+#define A6 a6
+#define ALIGN 8
+#define L(label) .memset_rvv_vlen_##label
+
+memset_rvv_vlen:
+	# return value
+	mv DST, a0
+	add DST_END, DST, NBYTE
+	# to uint8
+	andi CC, CC, 0xff
+	# broadcast in uint64
+	slli t0, CC, 8     # t0 = CC << 8
+	or CC, t0, CC      # CC = CC | t0
+	slli t0, CC, 16    # t0 = CC << 16
+	or CC, t0, CC      # CC = CC | t0
+	slli t0, CC, 32    # t0 = CC << 32
+	or CC, t0, CC      # CC = CC | t0
+# BEGIN small lengths
+	# addi t1, zero, 16
+	# blt NBYTE, t1, L(less_16bytes)
+	addi VLEN, zero, -1
+	vsetvli VLEN, VLEN, e8, m8, ta, ma
+	vmv.v.x	v8, CC
+	# blt NBYTE, VLEN, L(less_m8x1)
+	slli t1, VLEN, 2
+	blt NBYTE, t1, L(m8x4_loop_end)
+# END small length
+# nbyte >= vlen x 4
+
+# BEGIN align on 8B
+	andi t0, DST, 7
+	beqz t0, L(vec_set)
+	sub t0, zero, t0
+	addi t0, t0, 8
+	sd CC, (DST)
+	add DST, DST, t0
+# END align on 8B
+# BEGIN VEC STORE BULK
+L(vec_set):
+# t0: total vlen * 4  t1: dst + total vlen * 4
+	slli t0, VLEN, 2
+	add t1, DST, t0
+	blt DST_END, t1, L(m8x4_loop_end)  # branch if less than total vlen
+# use many t* to exploit data parallelism
+L(m8x4_loop):
+	vse8.v	v8, (DST)
+	add t2, DST, VLEN
+	vse8.v	v8, (t2)
+	add t3, t2, VLEN
+	vse8.v	v8, (t3)
+	add t4, t3, VLEN
+	vse8.v	v8, (t4)
+	add DST, t4, VLEN
+	add t1, DST, t0
+	bge DST_END, t1, L(m8x4_loop)  # branch if less than total vlen
+L(m8x4_loop_end):
+# END VEC STORE BULK
+	sub NBYTE, DST_END, DST
+	mv t1, NBYTE
+L(m8x1_loop):
+	mv NBYTE, t1
+	vsetvli t0, NBYTE, e8, m8, ta, ma
+	vse8.v v8, (DST)
+	add DST, DST, t0
+	sub t1, NBYTE, t0
+	bnez t1, L(m8x1_loop)
+	ret
diff --git a/sysdeps/riscv/multiarch/memset-rvv.S b/sysdeps/riscv/multiarch/memset-rvv.S
new file mode 100644
index 0000000000..e516185e61
--- /dev/null
+++ b/sysdeps/riscv/multiarch/memset-rvv.S
@@ -0,0 +1,126 @@
+/* Copyright (C) 2017-2022 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/>.  */
+   
+	.globl	memset_rvv
+	.p2align	1
+	.type	memset_rvv,@function
+# a0: dst a1: c a2: nbyte
+#define DST a5
+#define DST_END a7
+#define CC a1
+#define NBYTE a2
+# utilities
+#define VLEN a3
+#define A4 a4
+#define A6 a6
+#define ALIGN 8
+#define L(label) .memset_rvv_##label
+
+memset_rvv:
+	# return value
+	mv DST, a0
+	add DST_END, DST, NBYTE
+	# to uint8
+	andi CC, CC, 0xff
+	# broadcast in uint64
+	slli t0, CC, 8     # t0 = CC << 8
+	or CC, t0, CC      # CC = CC | t0
+	slli t0, CC, 16    # t0 = CC << 16
+	or CC, t0, CC      # CC = CC | t0
+	slli t0, CC, 32    # t0 = CC << 32
+	or CC, t0, CC      # CC = CC | t0
+# BEGIN small lengths
+	# addi t1, zero, 16
+	# blt NBYTE, t1, L(less_16bytes)
+	addi VLEN, zero, -1
+	vsetvli VLEN, VLEN, e8, m8, ta, ma
+	vmv.v.x	v8, CC
+	blt NBYTE, VLEN, L(less_m8x1)
+	slli t1, VLEN, 2
+	blt NBYTE, t1, L(less_m8x4)
+# END small length
+# nbyte >= vlen x 4
+
+# BEGIN align on 8B
+	andi t0, DST, 7
+	beqz t0, L(vec_set)
+	sub t0, zero, t0
+	addi t0, t0, 8
+	sd CC, (DST)
+	add DST, DST, t0
+# END align on 8B
+# BEGIN VEC STORE BULK
+L(vec_set):
+# t0: total vlen * 4  t1: dst + total vlen * 4
+	slli t0, VLEN, 2
+	add t1, DST, t0
+	blt DST_END, t1, L(m8x4_loop_end)  # branch if less than total vlen
+# use many t* to exploit data parallelism
+L(m8x4_loop):
+	vse8.v	v8, (DST)
+	add t2, DST, VLEN
+	vse8.v	v8, (t2)
+	add t3, t2, VLEN
+	vse8.v	v8, (t3)
+	add t4, t3, VLEN
+	vse8.v	v8, (t4)
+	add DST, t4, VLEN
+	add t1, DST, t0
+	bge DST_END, t1, L(m8x4_loop)  # branch if less than total vlen
+L(m8x4_loop_end):
+# END VEC STORE BULK
+	sub NBYTE, DST_END, DST
+L(less_m8x4):
+	addi t1, zero, 3
+	mul t1, VLEN, t1
+	blt NBYTE, t1, L(less_m8x3)
+	# nbyte >= vlen(m8) * 3
+	# 3 stores followed by an overlap store
+	vse8.v v8, (DST)
+	add t2, DST, VLEN
+	vse8.v v8, (t2)
+	add t3, t2, VLEN
+	vse8.v v8, (t3)
+	# overlap store
+	sub t1, DST_END, VLEN
+	vse8.v v8, (t1)
+	ret
+L(less_m8x3):
+	slli t1, VLEN, 1
+	blt NBYTE, t1, L(less_m8x2)
+	# nbyte >= vlen(m8) * 2
+	# 2 stores followed by an overlap store
+	vse8.v v8, (DST)
+	add DST, DST, VLEN
+	vse8.v v8, (DST)
+	# overlap store
+	sub t1, DST_END, VLEN
+	vse8.v v8, (t1)
+	ret
+L(less_m8x2):
+	blt NBYTE, VLEN, L(less_m8x1)
+	# nbyte >= vlen(m8) * 1
+	# 1 stores followed by an overlap store
+	vse8.v v8, (DST)
+	# overlap store
+	sub t1, DST_END, VLEN
+	vse8.v v8, (t1)
+	ret
+L(less_m8x1):
+	vsetvli VLEN, NBYTE, e8, m8, ta, ma
+	vse8.v v8, (DST)
+	ret
diff --git a/sysdeps/riscv/multiarch/memset.c b/sysdeps/riscv/multiarch/memset.c
new file mode 100644
index 0000000000..7c93360699
--- /dev/null
+++ b/sysdeps/riscv/multiarch/memset.c
@@ -0,0 +1,35 @@
+/* Multiple versions of memset.
+   All versions must be listed in ifunc-impl-list.c.
+   Copyright (C) 2017-2022 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/>.  */
+
+/* Define multiple versions only for the definition in libc.  */
+#if IS_IN (libc)
+# define memset __redirect_memset
+# include <string.h>
+# undef memset
+
+# define SYMBOL_NAME memset
+# include "ifunc-memset.h"
+
+libc_ifunc_redirected (__redirect_memset, memset, IFUNC_SELECTOR ());
+
+# ifdef SHARED
+__hidden_ver1 (memset, __GI_memset, __redirect_memset)
+  __attribute__ ((visibility ("hidden"))) __attribute_copy__ (memset);
+# endif
+#endif
-- 
2.20.1

