[v2] riscv: Add optimised memcmp implementation using RVV extension

Message ID 20260107015048.9552-1-zheng.ziyang@zte.com.cn (mailing list archive)
State New
Headers
Series [v2] riscv: Add optimised memcmp implementation using RVV extension |

Checks

Context Check Description
redhat-pt-bot/TryBot-apply_patch success Patch applied to master at the time it was sent
redhat-pt-bot/TryBot-32bit success Build for i686
redhat-pt-bot/TryBot-still_applies warning Patch no longer applies to master

Commit Message

Zheng Ziyang Jan. 7, 2026, 1:50 a.m. UTC
  From: zhengziyang <zheng.ziyang@zte.com.cn>

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                    | 102 ++++++
 .../unix/sysv/linux/riscv/multiarch/Makefile  |   3 +
 .../linux/riscv/multiarch/ifunc-impl-list.c   |   5 +
 .../unix/sysv/linux/riscv/multiarch/memcmp.c  |  57 +++
 ...imised-memcmp-implementation-using-R.patch | 326 ++++++++++++++++++
 8 files changed, 546 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
 create mode 100644 v2-0001-riscv-Add-optimised-memcmp-implementation-using-R.patch

-- 
2.21.0.windows.1
  

Comments

Peter Bergner Jan. 7, 2026, 4:25 p.m. UTC | #1
On 1/6/26 7:50 PM, Zheng Ziyang wrote:

> Subject: Re: [PATCH v2] riscv: Add optimised memcmp implementation using RVV extension

s/optimised/optimized/


> This patch adds an optimised memcmp implementation for RISC-V using the

Likewise.





> +++ b/sysdeps/riscv/multiarch/memcmp-generic.c
> @@ -0,0 +1,26 @@
> +/* Re-include the default memcpy implementation.
> +   Copyright (C) 2024 Free Software Foundation, Inc.

You still have copyright year issues here...




> +++ 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.

...and here.




> diff --git a/v2-0001-riscv-Add-optimised-memcmp-implementation-using-R.patch b/v2-0001-riscv-Add-optimised-memcmp-implementation-using-R.patch
> new file mode 100644
> index 0000000000..93bc6691c7
> --- /dev/null
> +++ b/v2-0001-riscv-Add-optimised-memcmp-implementation-using-R.patch
> @@ -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

And your patch diff contains another patch file.


I haven't looked at the rest of the patch, because it looked like
Jeff was in the process of reviewing some of the other patches and
I don't want to duplicate work.  I can step in and do that if needed.

Peter
  
Zheng Ziyang Jan. 16, 2026, 6:30 a.m. UTC | #2
Hi Peter,

Thanks for your careful review.

> s/optimised/optimized/
> Likewise.
I will correct the spelling in the next version.

> You still have copyright year issues here...
> ...and here.
I apologize for the oversight. I will update the copyright years to include 2026 in the v3 patch.

> And your patch diff contains another patch file.
This was a mistake in my `git format-patch` process. I will ensure the v3 patch is clean.

Regarding the implementation choice:
The current v2 patch follows Jeff's suggestion to use a "simple" version of the implementation to maintain better maintainability as a baseline.

I will address all the issues mentioned above and send out the v3 patch soon. 

Best regards,
Ziyang
  

Patch

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..b3d396e9ab
--- /dev/null
+++ b/sysdeps/riscv/multiarch/memcmp-vector.S
@@ -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
diff --git a/sysdeps/riscv/rvv/memcmp.S b/sysdeps/riscv/rvv/memcmp.S
new file mode 100644
index 0000000000..7303087551
--- /dev/null
+++ b/sysdeps/riscv/rvv/memcmp.S
@@ -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
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
diff --git a/v2-0001-riscv-Add-optimised-memcmp-implementation-using-R.patch b/v2-0001-riscv-Add-optimised-memcmp-implementation-using-R.patch
new file mode 100644
index 0000000000..93bc6691c7
--- /dev/null
+++ b/v2-0001-riscv-Add-optimised-memcmp-implementation-using-R.patch
@@ -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
+