[PATCH] AArch64: Remove EMAG ifuncs
Adhemerval Zanella Netto
adhemerval.zanella@linaro.org
Tue Mar 3 11:37:56 GMT 2026
On 02/03/26 15:54, Wilco Dijkstra wrote:
>
> Remove the old EMAG ifuncs for memset and memchr. Also remove old
> entries from cpu_list[].
>
> Passes regress, OK for commit?
I am not sure how common is the Ampere eMAG, but even though what the real gain
about dropping these specific routines? They do not really add much maintainance
(besides adding some extra runtime on string tests).
>
> ---
>
> diff --git a/sysdeps/aarch64/cpu-features.h b/sysdeps/aarch64/cpu-features.h
> index 1fe35d986b14a14fd55d6e4d3ac59fbb21e55f71..2957cd9c255bdb811a84b6b0fb3e8ab193d62233 100644
> --- a/sysdeps/aarch64/cpu-features.h
> +++ b/sysdeps/aarch64/cpu-features.h
> @@ -40,9 +40,6 @@
> #define MIDR_IMPLEMENTOR(midr) \
> (((midr) & MIDR_IMPLEMENTOR_MASK) >> MIDR_IMPLEMENTOR_SHIFT)
>
> -#define IS_EMAG(midr) (MIDR_IMPLEMENTOR(midr) == 'P' \
> - && MIDR_PARTNUM(midr) == 0x000)
> -
> #define IS_KUNPENG920(midr) (MIDR_IMPLEMENTOR(midr) == 'H' \
> && MIDR_PARTNUM(midr) == 0xd01)
>
> diff --git a/sysdeps/aarch64/multiarch/Makefile b/sysdeps/aarch64/multiarch/Makefile
> index deef7349fc4922aa158d72af285d042351c0bb71..988f7cec2562127cdae463b449245aab2a0e00dc 100644
> --- a/sysdeps/aarch64/multiarch/Makefile
> +++ b/sysdeps/aarch64/multiarch/Makefile
> @@ -1,7 +1,5 @@
> ifeq ($(subdir),string)
> sysdep_routines += \
> - memchr_generic \
> - memchr_nosimd \
> memcpy_a64fx \
> memcpy_generic \
> memcpy_kunpeng950 \
> @@ -10,7 +8,6 @@ sysdep_routines += \
> memcpy_sve \
> memmove_mops \
> memset_a64fx \
> - memset_emag \
> memset_generic \
> memset_kunpeng \
> memset_mops \
> diff --git a/sysdeps/aarch64/multiarch/ifunc-impl-list.c b/sysdeps/aarch64/multiarch/ifunc-impl-list.c
> index 2fddf58010a912ae3ea1e2d123a886066f0b3880..ea5f5853c312e61fcf12458654a76740114c8a4d 100644
> --- a/sysdeps/aarch64/multiarch/ifunc-impl-list.c
> +++ b/sysdeps/aarch64/multiarch/ifunc-impl-list.c
> @@ -50,16 +50,11 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
> IFUNC_IMPL (i, name, memset,
> IFUNC_IMPL_ADD (array, i, memset, (zva_size == 64), __memset_zva64)
> IFUNC_IMPL_ADD (array, i, memset, (zva_size == 64), __memset_oryon1)
> - IFUNC_IMPL_ADD (array, i, memset, 1, __memset_emag)
> IFUNC_IMPL_ADD (array, i, memset, 1, __memset_kunpeng)
> IFUNC_IMPL_ADD (array, i, memset, sve && zva_size == 256, __memset_a64fx)
> IFUNC_IMPL_ADD (array, i, memset, sve && zva_size == 64, __memset_sve_zva64)
> IFUNC_IMPL_ADD (array, i, memset, mops, __memset_mops)
> IFUNC_IMPL_ADD (array, i, memset, 1, __memset_generic))
> - IFUNC_IMPL (i, name, memchr,
> - IFUNC_IMPL_ADD (array, i, memchr, !mte, __memchr_nosimd)
> - IFUNC_IMPL_ADD (array, i, memchr, 1, __memchr_generic))
> -
> IFUNC_IMPL (i, name, strlen,
> IFUNC_IMPL_ADD (array, i, strlen, !mte, __strlen_asimd)
> IFUNC_IMPL_ADD (array, i, strlen, 1, __strlen_generic))
> diff --git a/sysdeps/aarch64/multiarch/memchr.c b/sysdeps/aarch64/multiarch/memchr.c
> deleted file mode 100644
> index 3b9f14e49054b3dd004577278ab08259e3d7c928..0000000000000000000000000000000000000000
> --- a/sysdeps/aarch64/multiarch/memchr.c
> +++ /dev/null
> @@ -1,41 +0,0 @@
> -/* Multiple versions of memchr. AARCH64 version.
> - Copyright (C) 2018-2026 Free Software Foundation, Inc.
> - This file is part of the GNU C Library.
> -
> - The GNU C Library is free software; you can redistribute it and/or
> - modify it under the terms of the GNU Lesser General Public
> - License as published by the Free Software Foundation; either
> - version 2.1 of the License, or (at your option) any later version.
> -
> - The GNU C Library is distributed in the hope that it will be useful,
> - but WITHOUT ANY WARRANTY; without even the implied warranty of
> - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> - Lesser General Public License for more details.
> -
> - You should have received a copy of the GNU Lesser General Public
> - License along with the GNU C Library; if not, see
> - <https://www.gnu.org/licenses/>. */
> -
> -/* Define multiple versions only for the definition in libc. */
> -
> -#if IS_IN (libc)
> -/* Redefine memchr so that the compiler won't complain about the type
> - mismatch with the IFUNC selector in strong_alias, below. */
> -# undef memchr
> -# define memchr __redirect_memchr
> -# include <string.h>
> -# include <init-arch.h>
> -
> -extern __typeof (__redirect_memchr) __memchr;
> -
> -extern __typeof (__redirect_memchr) __memchr_generic attribute_hidden;
> -extern __typeof (__redirect_memchr) __memchr_nosimd attribute_hidden;
> -
> -libc_ifunc (__memchr,
> - ((IS_EMAG (midr)
> - ? __memchr_nosimd
> - : __memchr_generic)));
> -
> -# undef memchr
> -strong_alias (__memchr, memchr);
> -#endif
> diff --git a/sysdeps/aarch64/multiarch/memchr_generic.S b/sysdeps/aarch64/multiarch/memchr_generic.S
> deleted file mode 100644
> index 2de3d535e571252cd7d0bd69803145661e826e9e..0000000000000000000000000000000000000000
> --- a/sysdeps/aarch64/multiarch/memchr_generic.S
> +++ /dev/null
> @@ -1,36 +0,0 @@
> -/* Memchr for aarch64, default version for internal use.
> - Copyright (C) 2018-2026 Free Software Foundation, Inc.
> -
> - This file is part of the GNU C Library.
> -
> - The GNU C Library is free software; you can redistribute it and/or
> - modify it under the terms of the GNU Lesser General Public
> - License as published by the Free Software Foundation; either
> - version 2.1 of the License, or (at your option) any later version.
> -
> - The GNU C Library is distributed in the hope that it will be useful,
> - but WITHOUT ANY WARRANTY; without even the implied warranty of
> - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> - Lesser General Public License for more details.
> -
> - You should have received a copy of the GNU Lesser General Public
> - License along with the GNU C Library. If not, see
> - <https://www.gnu.org/licenses/>. */
> -
> -#if IS_IN (libc)
> -# define MEMCHR __memchr_generic
> -
> -/* Do not hide the generic version of memchr, we use it internally. */
> -# undef libc_hidden_builtin_def
> -# define libc_hidden_builtin_def(name)
> -
> -# undef weak_alias
> -# define weak_alias(a, b)
> -
> -/* Add a hidden definition for use within libc.so. */
> -# ifdef SHARED
> - .globl __GI_memchr; __GI_memchr = __memchr_generic
> -# endif
> -#endif
> -
> -# include "../memchr.S"
> diff --git a/sysdeps/aarch64/multiarch/memchr_nosimd.S b/sysdeps/aarch64/multiarch/memchr_nosimd.S
> deleted file mode 100644
> index a7e331f3af0729e43922b84ac5da1d9866489c2c..0000000000000000000000000000000000000000
> --- a/sysdeps/aarch64/multiarch/memchr_nosimd.S
> +++ /dev/null
> @@ -1,215 +0,0 @@
> -/* memchr - find a character in a memory zone using base integer registers
> -
> - Copyright (C) 2018-2026 Free Software Foundation, Inc.
> -
> - This file is part of the GNU C Library.
> -
> - The GNU C Library is free software; you can redistribute it and/or
> - modify it under the terms of the GNU Lesser General Public
> - License as published by the Free Software Foundation; either
> - version 2.1 of the License, or (at your option) any later version.
> -
> - The GNU C Library is distributed in the hope that it will be useful,
> - but WITHOUT ANY WARRANTY; without even the implied warranty of
> - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> - Lesser General Public License for more details.
> -
> - You should have received a copy of the GNU Lesser General Public
> - License along with the GNU C Library. If not, see
> - <https://www.gnu.org/licenses/>. */
> -
> -#include <sysdep.h>
> -
> -/* Assumptions:
> - *
> - * ARMv8-a, AArch64
> - * Use base integer registers.
> - */
> -
> -/* Arguments and results. */
> -#define srcin x0
> -#define chrin x1
> -#define cntin x2
> -
> -#define result x0
> -
> -#define repchr x1
> -
> -#define tmp1 x2
> -#define tmp2 x3
> -#define tmp3 x4
> -#define tmp4 x5
> -
> -#define src x6
> -#define srcend x7
> -#define srcend16 x8
> -
> -#define anymore x9
> -
> -#define zeroones x10
> -
> -#define data1 x11
> -#define data2 x12
> -
> -#define has_chr1 x13
> -#define has_chr2 x14
> -
> -#define REP8_01 0x0101010101010101
> -#define REP8_7f 0x7f7f7f7f7f7f7f7f
> -
> -
> -ENTRY (__memchr_nosimd)
> -
> - /* Do not dereference srcin if no bytes to compare. */
> - cbz cntin, L(none_chr)
> -
> - /* Start address is 16-byte aligned or not? */
> - tst srcin, 15
> - bic src, srcin, 15
> -
> - mov zeroones, REP8_01
> - and repchr, chrin, 255
> - /* Generate a qword integer as |c|c|c|c|c|c|c|c|. */
> - mul repchr, repchr, zeroones
> -
> - add srcend, srcin, cntin
> - /*
> - * srcend16 is address of the block following the last block.
> - *
> - * [A block is 16-byte aligned and sized.]
> - */
> - add srcend16, srcend, 15
> - bic srcend16, srcend16, 15
> -
> - b.eq L(loop)
> -
> - /* Load the first block containing start address. */
> - ldp data1, data2, [src], 16
> -
> - lsl tmp1, srcin, 3
> - mov tmp2, ~0
> -#ifdef __AARCH64EB__
> - lsr tmp3, tmp2, tmp1
> -#else
> - lsl tmp3, tmp2, tmp1
> -#endif
> - /* Start address is in the first or the second qword? */
> - tst srcin, 8
> -
> - /*
> - * Transform any byte in the block to zero using XOR operation,
> - * if that byte equals the char to search. In this way, searching
> - * the char becomes detecting zero in the resulting two qwords.
> - */
> - eor data1, data1, repchr
> - eor data2, data2, repchr
> -
> - /*
> - * Set those unused bytes(before start address) to 0xff, so
> - * that they will not hit any zero detection.
> - */
> - orn tmp1, data1, tmp3
> - orn tmp2, data2, tmp3
> -
> - csinv data1, tmp1, xzr, eq
> - csel data2, data2, tmp2, eq
> -
> - /*
> - * When the first and last block are the same, there are two cases:
> - * o. Memory range to search is just in one block.
> - * ( start address - end address) < 0
> - *
> - * o. Memory range is so large that end address wrap-around.
> - * ( start address - end address) > 0
> - */
> - cmp srcin, srcend
> - ccmp src, srcend16, 0, mi
> - csetm anymore, ne
> - b L(find_chr)
> -
> - .p2align 4
> -L(loop):
> - ldp data1, data2, [src], 16
> -
> - subs anymore, src, srcend16
> -
> - /*
> - * Transform any byte in the block to zero using XOR operation,
> - * if that byte equals the char to search.
> - */
> - eor data1, data1, repchr
> - eor data2, data2, repchr
> -
> -L(find_chr):
> - /*
> - * Use the following integer test to find out if any byte in a
> - * qword is zero. If do not contain zero-valued byte, test result
> - * is zero.
> - *
> - * (qword - 0x0101010101010101) & ~(qword) & 0x8080808080808080
> - * =
> - * (qword - 0x0101010101010101) & ~(qword | 0x7f7f7f7f7f7f7f7f)
> - *
> - */
> - sub tmp1, data1, zeroones
> - sub tmp2, data2, zeroones
> -
> - orr tmp3, data1, REP8_7f
> - orr tmp4, data2, REP8_7f
> -
> - bic has_chr1, tmp1, tmp3
> - bic has_chr2, tmp2, tmp4
> -
> - orr tmp1, has_chr1, has_chr2
> - ccmp tmp1, 0, 0, ne
> -
> - b.eq L(loop)
> -
> - cbz has_chr1, 1f
> - sub result, src, 16
> -#ifdef __AARCH64EB__
> - rev data1, data1
> -#else
> - rev has_chr1, has_chr1
> -#endif
> - b L(done)
> -
> -1: cbz has_chr2, L(none_chr)
> - sub result, src, 8
> -#ifdef __AARCH64EB__
> - rev data1, data2
> -#else
> - rev has_chr1, has_chr2
> -#endif
> -
> -L(done):
> -#ifdef __AARCH64EB__
> - /*
> - * For big-endian, can not directly use has_chr1/has_chr2 because
> - * two qwords has been reversed after loading from memory.
> - * Thus, have to perform char detection on two qwords again, which
> - * should be byte-swapped this time.
> - */
> - sub tmp1, data1, zeroones
> - orr tmp3, data1, REP8_7f
> - bic has_chr1, tmp1, tmp3
> - rev has_chr1, has_chr1
> -#endif
> -
> - /*
> - * If the specified char is found in a qword, the corresponding
> - * byte of in has_chr has value of 1, while this is only true for
> - * the first occurrence, not other occurrences.
> - */
> - cmp anymore, 0
> - clz tmp1, has_chr1
> - add result, result, tmp1, lsr 3
> - ccmp result, srcend, 8, eq /* NZCV = 8000 */
> - csel result, result, xzr, mi
> - ret
> -
> -L(none_chr):
> - mov result, 0
> - ret
> -
> -END (__memchr_nosimd)
> diff --git a/sysdeps/aarch64/multiarch/memset.c b/sysdeps/aarch64/multiarch/memset.c
> index 76c6532b811e3bfab31bb60b4270305c8b60a811..438845eec9e2d273272a270a0f87833e26ea8c84 100644
> --- a/sysdeps/aarch64/multiarch/memset.c
> +++ b/sysdeps/aarch64/multiarch/memset.c
> @@ -30,7 +30,6 @@
> extern __typeof (__redirect_memset) __libc_memset;
>
> extern __typeof (__redirect_memset) __memset_zva64 attribute_hidden;
> -extern __typeof (__redirect_memset) __memset_emag attribute_hidden;
> extern __typeof (__redirect_memset) __memset_kunpeng attribute_hidden;
> extern __typeof (__redirect_memset) __memset_a64fx attribute_hidden;
> extern __typeof (__redirect_memset) __memset_generic attribute_hidden;
> @@ -61,9 +60,6 @@ select_memset_ifunc (void)
> if (IS_KUNPENG920 (midr))
> return __memset_kunpeng;
>
> - if (IS_EMAG (midr))
> - return __memset_emag;
> -
> if (zva_size == 64)
> return __memset_zva64;
>
> diff --git a/sysdeps/aarch64/multiarch/memset_emag.S b/sysdeps/aarch64/multiarch/memset_emag.S
> deleted file mode 100644
> index 8f68de6f72d0f75acc068351c8689b004bdbab0d..0000000000000000000000000000000000000000
> --- a/sysdeps/aarch64/multiarch/memset_emag.S
> +++ /dev/null
> @@ -1,115 +0,0 @@
> -/* Optimized memset for AmpereComputing emag processor.
> - Copyright (C) 2018-2026 Free Software Foundation, Inc.
> -
> - This file is part of the GNU C Library.
> -
> - The GNU C Library is free software; you can redistribute it and/or
> - modify it under the terms of the GNU Lesser General Public
> - License as published by the Free Software Foundation; either
> - version 2.1 of the License, or (at your option) any later version.
> -
> - The GNU C Library is distributed in the hope that it will be useful,
> - but WITHOUT ANY WARRANTY; without even the implied warranty of
> - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> - Lesser General Public License for more details.
> -
> - You should have received a copy of the GNU Lesser General Public
> - License along with the GNU C Library. If not, see
> - <https://www.gnu.org/licenses/>. */
> -
> -#include <sysdep.h>
> -
> -/* Assumptions:
> - *
> - * ARMv8-a, AArch64, unaligned accesses
> - *
> - */
> -
> -#define dstin x0
> -#define val x1
> -#define valw w1
> -#define count x2
> -#define dst x3
> -#define dstend x4
> -
> -ENTRY (__memset_emag)
> -
> - bfi valw, valw, 8, 8
> - bfi valw, valw, 16, 16
> - bfi val, val, 32, 32
> -
> - add dstend, dstin, count
> -
> - cmp count, 96
> - b.hi L(set_long)
> - cmp count, 16
> - b.hs L(set_medium)
> -
> - /* Set 0..15 bytes. */
> - tbz count, 3, 1f
> - str val, [dstin]
> - str val, [dstend, -8]
> - ret
> -
> - .p2align 3
> -1: tbz count, 2, 2f
> - str valw, [dstin]
> - str valw, [dstend, -4]
> - ret
> -2: cbz count, 3f
> - strb valw, [dstin]
> - tbz count, 1, 3f
> - strh valw, [dstend, -2]
> -3: ret
> -
> - .p2align 3
> - /* Set 16..96 bytes. */
> -L(set_medium):
> - stp val, val, [dstin]
> - tbnz count, 6, L(set96)
> - stp val, val, [dstend, -16]
> - tbz count, 5, 1f
> - stp val, val, [dstin, 16]
> - stp val, val, [dstend, -32]
> -1: ret
> -
> - .p2align 4
> - /* Set 64..96 bytes. Write 64 bytes from the start and
> - 32 bytes from the end. */
> -L(set96):
> - stp val, val, [dstin, 16]
> - stp val, val, [dstin, 32]
> - stp val, val, [dstin, 48]
> - stp val, val, [dstend, -32]
> - stp val, val, [dstend, -16]
> - ret
> -
> - .p2align 4
> -L(set_long):
> - stp val, val, [dstin]
> - bic dst, dstin, 15
> - /* Small-size or non-zero memset does not use DC ZVA. */
> - sub count, dstend, dst
> -
> - /*
> - * Adjust count and bias for loop. By subtracting extra 1 from count,
> - * it is easy to use tbz instruction to check whether loop tailing
> - * count is less than 33 bytes, so as to bypass 2 unnecessary stps.
> - */
> - sub count, count, 64+16+1
> -
> -1: stp val, val, [dst, 16]
> - stp val, val, [dst, 32]
> - stp val, val, [dst, 48]
> - stp val, val, [dst, 64]!
> - subs count, count, 64
> - b.hs 1b
> -
> - tbz count, 5, 1f /* Remaining count is less than 33 bytes? */
> - stp val, val, [dst, 16]
> - stp val, val, [dst, 32]
> -1: stp val, val, [dstend, -32]
> - stp val, val, [dstend, -16]
> - ret
> -
> -END (__memset_emag)
> diff --git a/sysdeps/unix/sysv/linux/aarch64/cpu-features.c b/sysdeps/unix/sysv/linux/aarch64/cpu-features.c
> index 15aed15a667e89abd2790a22a319a8a6aaecba02..70d3272772f5f36a3435d0ae8919d781a1e2412e 100644
> --- a/sysdeps/unix/sysv/linux/aarch64/cpu-features.c
> +++ b/sysdeps/unix/sysv/linux/aarch64/cpu-features.c
> @@ -44,11 +44,6 @@ struct cpu_list
> static const struct cpu_list cpu_list[] =
> {
> #define CPU_LIST_ENTRY(__str, __num) { __str, sizeof (__str) - 1, __num }
> - CPU_LIST_ENTRY ("thunderxt88", 0x430F0A10),
> - CPU_LIST_ENTRY ("thunderx2t99", 0x431F0AF0),
> - CPU_LIST_ENTRY ("thunderx2t99p1", 0x420F5160),
> - CPU_LIST_ENTRY ("ares", 0x411FD0C0),
> - CPU_LIST_ENTRY ("emag", 0x503F0001),
> CPU_LIST_ENTRY ("kunpeng920", 0x481FD010),
> CPU_LIST_ENTRY ("kunpeng950", 0x480FD060),
> CPU_LIST_ENTRY ("a64fx", 0x460F0010),
>
More information about the Libc-alpha
mailing list