[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