[PATCH] AArch64: Remove EMAG ifuncs

Andrew Pinski pinskia@gmail.com
Tue Mar 3 01:47:35 GMT 2026


On Mon, Mar 2, 2026 at 10:57 AM Wilco Dijkstra <Wilco.Dijkstra@arm.com> wrote:
>
>
> Remove the old EMAG ifuncs for memset and memchr.  Also remove old
> entries from cpu_list[].
>
> Passes regress, OK for commit?

LGTM but I should NOT be the one to comment on if removing EMAG versions or not.

Thanks,
Andrew

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