From patchwork Wed Jan 7 01:50:48 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Zheng Ziyang X-Patchwork-Id: 127478 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from vm01.sourceware.org (localhost [127.0.0.1]) by sourceware.org (Postfix) with ESMTP id EA50C4BA2E29 for ; Wed, 7 Jan 2026 01:52:18 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org EA50C4BA2E29 X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from mxct.zte.com.cn (mxct.zte.com.cn [183.62.165.209]) by sourceware.org (Postfix) with ESMTPS id 85C714BA2E04 for ; Wed, 7 Jan 2026 01:51:35 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 85C714BA2E04 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=zte.com.cn Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=zte.com.cn ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 85C714BA2E04 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=183.62.165.209 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1767750698; cv=none; b=PYliVPlsAyFZAdXAqvuak8aIKmMPqxsJl4rfwaudhta1uOu9G9jrCUYiuvva/K5CX0H8bpXNtAuV3Lo0Nt5sW6W6AQn1GrhjNu2csUQJwPitNbeEvN/ud3wumglymeMW/xRlsPwA1tgEXIkveFCPMmjhg1n1ugLBxgOy65xQoeY= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1767750698; c=relaxed/simple; bh=O+HaB5U3hJ69/Jg+/GF/N+Nhyqsv9sn1Es1DXbwTqKw=; h=From:To:Subject:Date:Message-Id:MIME-Version; b=eqvlR0Iaohui02tj1ZvHnMYseEFhDC98kFeiB4qfyNq5nKsZ6Ch/0Fk+OhG0/6DYy35EvSL/Ve9mAzlVU4CL08UNz/YAmII4/IzFFRK74JRdzWpIZA6WZy7OvlMVjdob4vdoMzj+XOqRMV48zfV1fQATPAHZ/DVcaPBnGe9xgZk= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 85C714BA2E04 Received: from mse-fl2.zte.com.cn (unknown [10.5.228.133]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange x25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mxct.zte.com.cn (FangMail) with ESMTPS id 4dm9xb2865z4xNv9; Wed, 07 Jan 2026 09:51:31 +0800 (CST) Received: from szxl2zmapp05.zte.com.cn ([10.1.32.37]) by mse-fl2.zte.com.cn with SMTP id 6071pDaY008613; Wed, 7 Jan 2026 09:51:13 +0800 (+08) (envelope-from zheng.ziyang@zte.com.cn) Received: from localhost.localdomain (unknown [10.4.24.57]) by smtp (Zmail) with SMTP; Fri, 7 Jan 2026 09:51:14 +0800 X-Zmail-TransId: 3e81695dbc12001-a4e1d X-Zmail-LocalSMTP: 1 X-Zmail-RealSender: zheng.ziyang@zte.com.cn From: Zheng Ziyang To: libc-alpha@sourceware.org Cc: jeffrey.law@oss.qualcomm.com, adhemerval.zanella@linaro.org, bergner@tenstorrent.com, palmer@dabbelt.com, darius@bluespec.com, zhengziyang Subject: [PATCH v2] riscv: Add optimised memcmp implementation using RVV extension Date: Wed, 7 Jan 2026 09:50:48 +0800 Message-Id: <20260107015048.9552-1-zheng.ziyang@zte.com.cn> X-Mailer: git-send-email 2.21.0.windows.1 In-Reply-To: <20251230062550.15804-1-zheng.ziyang@zte.com.cn> References: <20251230062550.15804-1-zheng.ziyang@zte.com.cn> MIME-Version: 1.0 X-MAIL: mse-fl2.zte.com.cn 6071pDaY008613 X-TLS: YES X-SPF-DOMAIN: zte.com.cn X-ENVELOPE-SENDER: zheng.ziyang@zte.com.cn X-SPF: None X-SOURCE-IP: 10.5.228.133 unknown Wed, 07 Jan 2026 09:51:31 +0800 X-Fangmail-Anti-Spam-Filtered: true X-Fangmail-MID-QID: 695DBC23.000/4dm9xb2865z4xNv9 X-Spam-Status: No, score=-12.0 required=5.0 tests=BAYES_00, GIT_PATCH_0, HTML_MESSAGE, KAM_DMARC_STATUS, KAM_SHORT, RCVD_IN_DNSWL_BLOCKED, RCVD_IN_MSPIKE_H2, RCVD_IN_VALIDITY_RPBL_BLOCKED, RCVD_IN_VALIDITY_SAFE_BLOCKED, SPF_HELO_NONE, SPF_PASS, TXREP, URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on sourceware.org X-BeenThere: libc-alpha@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Libc-alpha mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libc-alpha-bounces~patchwork=sourceware.org@sourceware.org From: zhengziyang 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 --- 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 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 + . */ + +#include + +#if IS_IN(libc) +# define MEMCMP __memcmp_generic +# undef libc_hidden_builtin_def +# define libc_hidden_builtin_def(x) +#endif +#include 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 + . */ + +#if IS_IN(libc) +# define MEMCMP __memcmp_vector +# undef libc_hidden_builtin_def +# define libc_hidden_builtin_def(name) +#include +#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 + . +*/ + +#include +#include + +/* ---------------------------------------------------- + * 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 + . */ + +#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 +# include +# include +# include +# include + +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 +#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 +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 +--- + 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 ++ . */ ++ ++#include ++ ++#if IS_IN(libc) ++# define MEMCMP __memcmp_generic ++# undef libc_hidden_builtin_def ++# define libc_hidden_builtin_def(x) ++#endif ++#include +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 ++ . */ ++ ++#if IS_IN(libc) ++# define MEMCMP __memcmp_vector ++# undef libc_hidden_builtin_def ++# define libc_hidden_builtin_def(name) ++#include ++#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 ++ . ++*/ ++ ++#include ++#include ++ ++/* ---------------------------------------------------- ++ * 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 ++ . */ ++ ++#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 ++# include ++# include ++# include ++# include ++ ++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 ++#endif +-- +2.21.0.windows.1 +