@@ -353,9 +353,9 @@ MEMCMP (const void *s1, const void *s2, size_t len)
libc_hidden_builtin_def(memcmp)
#ifdef weak_alias
# undef bcmp
-weak_alias (memcmp, bcmp)
+weak_alias (MEMCMP, bcmp)
#endif
#undef __memcmpeq
-strong_alias (memcmp, __memcmpeq)
+strong_alias (MEMCMP, __memcmpeq)
libc_hidden_def(__memcmpeq)
new file mode 100644
@@ -0,0 +1,26 @@
+/* Re-include the default memcpy implementation.
+ Copyright (C) 2024 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 MEMCMP __memcmp_generic
+# undef libc_hidden_builtin_def
+# define libc_hidden_builtin_def(x)
+#endif
+#include <string/memcmp.c>
new file mode 100644
@@ -0,0 +1,25 @@
+
+/* RISC-V RVV based memcmp.
+ 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
+ <http://www.gnu.org/licenses/>. */
+
+#if IS_IN(libc)
+# define MEMCMP __memcmp_vector
+# undef libc_hidden_builtin_def
+# define libc_hidden_builtin_def(name)
+#include <sysdeps/riscv/rvv/memcmp.S>
+#endif
new file mode 100644
@@ -0,0 +1,102 @@
+/* memcmp for RISC-V, ignoring buffer alignment
+ 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 Lesser General Public License. If not, see
+ <https://www.gnu.org/licenses/>.
+*/
+
+#include <sysdep.h>
+#include <sys/asm.h>
+
+/* ----------------------------------------------------
+ * Register Aliases
+ * ---------------------------------------------------- */
+
+/* Return value: difference between first mismatched bytes */
+#define result a0
+
+/* Function arguments */
+#define src1 a0 /* const void *s1 - first buffer pointer */
+#define src2 a1 /* const void *s2 - second buffer pointer */
+#define num a2 /* size_t n - number of bytes to compare */
+
+/* Temporary registers */
+#define ivl a3
+#define temp a4
+#define temp1 a5
+#define temp2 a6
+
+/* Vector configuration */
+#define ELEM_LMUL_SETTING m8
+#define vdata1 v0
+#define vdata2 v8
+#define vmask v16
+
+
+ENTRY (__memcmp_vector)
+.option push
+.option arch, +v
+
+ /* ----------------------------------------------------
+ * Initial Check
+ * If length is 0, buffers are trivially equal.
+ * ---------------------------------------------------- */
+ beqz num, L(equal)
+
+ vsetvli ivl, num, e8, ELEM_LMUL_SETTING, ta, ma
+
+L(loop):
+ /* Load vector chunks from both source buffers */
+ vle8.v vdata1, (src1)
+ sub num, num, ivl
+ vle8.v vdata2, (src2)
+
+ vmsne.vv vmask, vdata1, vdata2
+ vfirst.m temp, vmask
+
+ /* If temp >= 0, we found a difference - exit loop */
+ bgez temp, L(found)
+
+ /* No difference found in this chunk - advance to next */
+ add src1, src1, ivl
+ add src2, src2, ivl
+ bgeu num, ivl, L(loop)
+
+ /* ----------------------------------------------------
+ * Process remaining bytes (0 < num < ivl).
+ * ---------------------------------------------------- */
+ beqz num, L(equal)
+
+ vsetvli ivl, num, e8, ELEM_LMUL_SETTING, ta, ma
+ vle8.v vdata1, (src1)
+ vle8.v vdata2, (src2)
+ vmsne.vv vmask, vdata1, vdata2
+ vfirst.m temp, vmask
+ bgez temp, L(found)
+
+
+L(equal):
+ li result, 0 /* Set return value to 0 */
+ ret
+
+L(found):
+ add src1, src1, temp
+ add src2, src2, temp
+ lbu temp1, 0(src1)
+ lbu temp2, 0(src2)
+ sub result, temp1, temp2
+ ret
+.option pop
+END (__memcmp_vector)
\ No newline at end of file
@@ -1,5 +1,8 @@
ifeq ($(subdir),string)
sysdep_routines += \
+ memcmp \
+ memcmp-generic \
+ memcmp-vector \
memcpy \
memcpy-generic \
memcpy_noalignment \
@@ -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, memcmp,
+ IFUNC_IMPL_ADD (array, i, memcmp, rvv_enabled,
+ __memcmp_vector)
+ IFUNC_IMPL_ADD (array, i, memcmp, 1, __memcmp_generic))
+
return 0;
}
new file mode 100644
@@ -0,0 +1,57 @@
+/* Multiple versions of memcpy.
+ All versions must be listed in ifunc-impl-list.c.
+ Copyright (C) 2017-2024 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 memcpy so that the compiler won't complain about the type
+ mismatch with the IFUNC selector in strong_alias, below. */
+# undef memcmp
+# define memcmp __redirect_memcmp
+# include <stdint.h>
+# include <string.h>
+# include <ifunc-init.h>
+# include <riscv-ifunc.h>
+# include <sys/hwprobe.h>
+
+extern __typeof (__redirect_memcmp) __libc_memcmp;
+
+extern __typeof (__redirect_memcmp) __memcmp_generic attribute_hidden;
+extern __typeof (__redirect_memcmp) __memcmp_vector attribute_hidden;
+
+static inline __typeof (__redirect_memcmp) *
+select_memcmp_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 __memcmp_vector;
+
+ return __memcmp_generic;
+}
+
+riscv_libc_ifunc (__libc_memcmp, select_memcmp_ifunc);
+
+# undef memcmp
+strong_alias (__libc_memcmp, memcmp);
+# ifdef SHARED
+__hidden_ver1 (memcmp, __GI_memcmp, __redirect_memcmp)
+ __attribute__ ((visibility ("hidden"))) __attribute_copy__ (memcmp);
+# endif
+#else
+# include <string/memcmp.c>
+#endif
new file mode 100644
@@ -0,0 +1,326 @@
+From 18885d1840745ecfa82ebe3748692d21bb12ea9b Mon Sep 17 00:00:00 2001
+From: zhengziyang <zheng.ziyang@zte.com.cn>
+Date: Tue, 23 Dec 2025 14:18:08 +0800
+Subject: [PATCH v2] riscv: Add optimised memcmp implementation using RVV
+ extension
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+This patch adds an optimised memcmp implementation for RISC-V using the
+RVV extension.
+
+The implementation assumes RVV 1.0 with VLEN >= 128, supports arbitrary
+VLEN configurations, and works on both RV32 and RV64 platforms. No
+page-size assumptions are made.
+
+Performance improvements (relative speedup %) over __memcmp_generic
+baseline:
+
+| Test Category | Config (VLENB) | vs. __memcmp_generic |
+|--------------------|-----------------------|----------------------|
+| **memcmp-default** | XuanTie C920 (128) | +52.6% |
+| | Spacemit(R) X60 (256) | +11.2% |
+
+Signed-off-by: Zheng Ziyang <zheng.ziyang@zte.com.cn>
+---
+ string/memcmp.c | 4 +-
+ sysdeps/riscv/multiarch/memcmp-generic.c | 26 +++++
+ sysdeps/riscv/multiarch/memcmp-vector.S | 25 ++++
+ sysdeps/riscv/rvv/memcmp.S | 107 ++++++++++++++++++
+ .../unix/sysv/linux/riscv/multiarch/Makefile | 3 +
+ .../linux/riscv/multiarch/ifunc-impl-list.c | 5 +
+ .../unix/sysv/linux/riscv/multiarch/memcmp.c | 57 ++++++++++
+ 7 files changed, 225 insertions(+), 2 deletions(-)
+ create mode 100644 sysdeps/riscv/multiarch/memcmp-generic.c
+ create mode 100644 sysdeps/riscv/multiarch/memcmp-vector.S
+ create mode 100644 sysdeps/riscv/rvv/memcmp.S
+ create mode 100644 sysdeps/unix/sysv/linux/riscv/multiarch/memcmp.c
+
+diff --git a/string/memcmp.c b/string/memcmp.c
+index cd595ce95e..5f8b0698f0 100644
+--- a/string/memcmp.c
++++ b/string/memcmp.c
+@@ -353,9 +353,9 @@ MEMCMP (const void *s1, const void *s2, size_t len)
+ libc_hidden_builtin_def(memcmp)
+ #ifdef weak_alias
+ # undef bcmp
+-weak_alias (memcmp, bcmp)
++weak_alias (MEMCMP, bcmp)
+ #endif
+
+ #undef __memcmpeq
+-strong_alias (memcmp, __memcmpeq)
++strong_alias (MEMCMP, __memcmpeq)
+ libc_hidden_def(__memcmpeq)
+diff --git a/sysdeps/riscv/multiarch/memcmp-generic.c b/sysdeps/riscv/multiarch/memcmp-generic.c
+new file mode 100644
+index 0000000000..a5ddb2bec8
+--- /dev/null
++++ b/sysdeps/riscv/multiarch/memcmp-generic.c
+@@ -0,0 +1,26 @@
++/* Re-include the default memcpy implementation.
++ Copyright (C) 2024 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 MEMCMP __memcmp_generic
++# undef libc_hidden_builtin_def
++# define libc_hidden_builtin_def(x)
++#endif
++#include <string/memcmp.c>
+diff --git a/sysdeps/riscv/multiarch/memcmp-vector.S b/sysdeps/riscv/multiarch/memcmp-vector.S
+new file mode 100644
+index 0000000000..fc9bce8cb8
+--- /dev/null
++++ b/sysdeps/riscv/multiarch/memcmp-vector.S
+@@ -0,0 +1,25 @@
++
++/* RISC-V RVV based memcmp.
++ Copyright (C) 2025 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
++ <http://www.gnu.org/licenses/>. */
++
++#if IS_IN(libc)
++# define MEMCMP __memcmp_vector
++# undef libc_hidden_builtin_def
++# define libc_hidden_builtin_def(name)
++#include <sysdeps/riscv/rvv/memcmp.S>
++#endif
+diff --git a/sysdeps/riscv/rvv/memcmp.S b/sysdeps/riscv/rvv/memcmp.S
+new file mode 100644
+index 0000000000..83fe66b2db
+--- /dev/null
++++ b/sysdeps/riscv/rvv/memcmp.S
+@@ -0,0 +1,107 @@
++/* memcmp for RISC-V, ignoring buffer alignment
++ Copyright (C) 2024-2025 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 Lesser General Public License. If not, see
++ <https://www.gnu.org/licenses/>.
++*/
++
++#include <sysdep.h>
++#include <sys/asm.h>
++
++/* ----------------------------------------------------
++ * Register Aliases
++ * ---------------------------------------------------- */
++
++/* Return value: difference between first mismatched bytes */
++#define result a0
++
++/* Function arguments */
++#define src1 a0 /* const void *s1 - first buffer pointer */
++#define src2 a1 /* const void *s2 - second buffer pointer */
++#define num a2 /* size_t n - number of bytes to compare */
++
++/* Temporary registers */
++#define ivl a3
++#define temp a4
++#define temp1 a5
++#define temp2 a6
++
++/* Vector configuration */
++#define ELEM_LMUL_SETTING m8
++#define vdata1 v0
++#define vdata2 v8
++#define vmask v16
++
++
++ENTRY (__memcmp_vector)
++.option push
++.option arch, +v
++
++ /* ----------------------------------------------------
++ * Initial Check
++ * If length is 0, buffers are trivially equal.
++ * ---------------------------------------------------- */
++ beqz num, L(equal)
++
++ vsetvli ivl, num, e8, ELEM_LMUL_SETTING, ta, ma
++
++L(loop):
++ /* Load vector chunks from both source buffers */
++ vle8.v vdata1, (src1)
++ sub num, num, ivl
++ vle8.v vdata2, (src2)
++
++ vmsne.vv vmask, vdata1, vdata2
++ vfirst.m temp, vmask
++
++ /* If temp >= 0, we found a difference - exit loop */
++ bgez temp, L(found)
++
++ /* No difference found in this chunk - advance to next */
++
++ add src1, src1, ivl
++ add src2, src2, ivl
++ bgeu num, ivl, L(loop)
++
++ /* ----------------------------------------------------
++ * Process remaining bytes (0 < num < ivl).
++ * ---------------------------------------------------- */
++ beqz num, L(equal)
++
++ vsetvli ivl, num, e8, ELEM_LMUL_SETTING, ta, ma
++ vle8.v vdata1, (src1)
++ vle8.v vdata2, (src2)
++ vmsne.vv vmask, vdata1, vdata2
++ vfirst.m temp, vmask
++
++ /* If mismatch found in tail, calculate difference */
++ bgez temp, L(found)
++
++
++L(equal):
++ li result, 0 /* Set return value to 0 */
++ ret
++
++L(found):
++ add src1, src1, temp
++ add src2, src2, temp
++ lbu temp1, 0(src1)
++ lbu temp2, 0(src2)
++
++ /* Return difference: positive if src1 > src2, negative if src1 < src2 */
++ sub result, temp1, temp2
++ ret
++.option pop
++END (__memcmp_vector)
+\ No newline at end of file
+diff --git a/sysdeps/unix/sysv/linux/riscv/multiarch/Makefile b/sysdeps/unix/sysv/linux/riscv/multiarch/Makefile
+index 1d26966ded..fa1b5a84ed 100644
+--- a/sysdeps/unix/sysv/linux/riscv/multiarch/Makefile
++++ b/sysdeps/unix/sysv/linux/riscv/multiarch/Makefile
+@@ -1,5 +1,8 @@
+ ifeq ($(subdir),string)
+ sysdep_routines += \
++ memcmp \
++ memcmp-generic \
++ memcmp-vector \
+ memcpy \
+ memcpy-generic \
+ memcpy_noalignment \
+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 87456f3370..d5cb49aa5c 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, memcmp,
++ IFUNC_IMPL_ADD (array, i, memcmp, rvv_enabled,
++ __memcmp_vector)
++ IFUNC_IMPL_ADD (array, i, memcmp, 1, __memcmp_generic))
++
+ return 0;
+ }
+diff --git a/sysdeps/unix/sysv/linux/riscv/multiarch/memcmp.c b/sysdeps/unix/sysv/linux/riscv/multiarch/memcmp.c
+new file mode 100644
+index 0000000000..aa7db13f1f
+--- /dev/null
++++ b/sysdeps/unix/sysv/linux/riscv/multiarch/memcmp.c
+@@ -0,0 +1,57 @@
++/* Multiple versions of memcpy.
++ All versions must be listed in ifunc-impl-list.c.
++ Copyright (C) 2017-2024 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 memcpy so that the compiler won't complain about the type
++ mismatch with the IFUNC selector in strong_alias, below. */
++# undef memcmp
++# define memcmp __redirect_memcmp
++# include <stdint.h>
++# include <string.h>
++# include <ifunc-init.h>
++# include <riscv-ifunc.h>
++# include <sys/hwprobe.h>
++
++extern __typeof (__redirect_memcmp) __libc_memcmp;
++
++extern __typeof (__redirect_memcmp) __memcmp_generic attribute_hidden;
++extern __typeof (__redirect_memcmp) __memcmp_vector attribute_hidden;
++
++static inline __typeof (__redirect_memcmp) *
++select_memcmp_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 __memcmp_vector;
++
++ return __memcmp_generic;
++}
++
++riscv_libc_ifunc (__libc_memcmp, select_memcmp_ifunc);
++
++# undef memcmp
++strong_alias (__libc_memcmp, memcmp);
++# ifdef SHARED
++__hidden_ver1 (memcmp, __GI_memcmp, __redirect_memcmp)
++ __attribute__ ((visibility ("hidden"))) __attribute_copy__ (memcmp);
++# endif
++#else
++# include <string/memcmp.c>
++#endif
+--
+2.21.0.windows.1
+