[PATCH v2 1/3] AArch64: Remove eMAG memchr ifunc

Wilco Dijkstra Wilco.Dijkstra@arm.com
Mon Mar 16 17:24:44 GMT 2026


v2: Split patch

As a cleanup remove the eMAG ifunc for memchr.

Passes regress, OK for commit?

---

diff --git a/sysdeps/aarch64/multiarch/Makefile b/sysdeps/aarch64/multiarch/Makefile
index deef7349fc4922aa158d72af285d042351c0bb71..bc497782555896bb030139eae3b219577728eb43 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 \
diff --git a/sysdeps/aarch64/multiarch/ifunc-impl-list.c b/sysdeps/aarch64/multiarch/ifunc-impl-list.c
index 2fddf58010a912ae3ea1e2d123a886066f0b3880..b4416b044394f8811fc6f0c416b6580d23e4b0d2 100644
--- a/sysdeps/aarch64/multiarch/ifunc-impl-list.c
+++ b/sysdeps/aarch64/multiarch/ifunc-impl-list.c
@@ -56,10 +56,6 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
 	      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)



More information about the Libc-alpha mailing list