On Wed, Aug 12, 2026 at 3:20 AM Matt Turner <mattst88@gmail.com> wrote:
>
> Add the framework for runtime CPU-based dispatch on alpha.
>
> init-arch.h wraps the implver and amask instructions, which resolvers use
> directly rather than going through AT_HWCAP: both are unprivileged, so a
> resolver can ask the processor what it is without help from the kernel.
> IS_EV6_OR_LATER tests implver for the 21264 family, IS_EV7_OR_LATER for the
> 21364, and HAS_CIX asks amask for the count extension the 21264A introduced.
>
> ifunc-impl-list.c enumerates the implementations for the string tests, which
> run each one in turn rather than only whichever the resolver picks.
>
> The dynamic linker cannot dispatch through an IFUNC before it has relocated
> itself, so dl-symbol-redir-ifunc.h names an implementation directly for the
> functions it needs while bootstrapping. Only the static dynamic linker
> needs the redirection; the shared one has its own copies of these functions
> and the multiarch variants are not linked into it.
>
> configure inserts <machine>/multiarch immediately before <machine> for each
> term of the Implies chain, so a multiarch directory shadows only the assembly
> in its own directory. sysdeps/alpha/multiarch therefore sits after
> sysdeps/alpha/alphaev6 and sysdeps/alpha/alphaev67 in sysnames, and an
> --host=alphaev6 or later build picks the CPU assembly over the dispatchers,
> leaving IFUNC dispatch inert on exactly the configurations that have the
> tuned implementations. Give the two levels that carry assembly an
> Implies-only multiarch directory chaining down to sysdeps/alpha/multiarch,
> as powerpc does for its per-CPU directories, which places the dispatchers
> ahead of the assembly. A --disable-multi-arch build is unaffected: no
> multiarch directory enters sysnames and the assembly is used directly.
> ---
Hi Matt,
It does not build on its own with multiarch enabled.
sysdeps/alpha/multiarch/Makefile at this commit has
sysdep_routines += memset_ev5 memset_ev6 rawmemchr_ev5 ... strncat_ev67
and ifunc-impl-list.c references __memset_ev5, __strlen_ev67 and the rest, but
all 36 wrapper sources arrive in 20/20. make stops at "No rule to make target
memset_ev5.o". Either the Makefile and ifunc-impl-list.c move to 20/20, or the
wrappers move here.
Magnus
new file mode 100644
@@ -0,0 +1 @@
+alpha/multiarch
new file mode 100644
@@ -0,0 +1 @@
+alpha/alphaev6/multiarch
new file mode 100644
@@ -0,0 +1,20 @@
+ifeq ($(subdir),string)
+sysdep_routines += \
+ memset_ev5 \
+ memset_ev6 \
+ rawmemchr_ev5 \
+ rawmemchr_ev67 \
+ stpcpy_ev5 \
+ stpcpy_ev67 \
+ stpncpy_ev5 \
+ stpncpy_ev67 \
+ strcat_ev5 \
+ strcat_ev67 \
+ strchr_ev5 \
+ strchr_ev67 \
+ strlen_ev5 \
+ strlen_ev67 \
+ strncat_ev5 \
+ strncat_ev67 \
+# sysdep_routines
+endif
new file mode 100644
@@ -0,0 +1,25 @@
+/* Symbol redirection for loader/static initialization code.
+ 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
+ <https://www.gnu.org/licenses/>. */
+
+#ifndef _DL_IFUNC_GENERIC_H
+#define _DL_IFUNC_GENERIC_H
+
+asm ("memset = __memset_ev5");
+asm ("strlen = __strlen_ev5");
+
+#endif
new file mode 100644
@@ -0,0 +1,64 @@
+/* Enumerate available IFUNC implementations of a function. Alpha version.
+ 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
+ <https://www.gnu.org/licenses/>. */
+
+#include <assert.h>
+#include <string.h>
+#include <wchar.h>
+#include <ifunc-impl-list.h>
+#include <init-arch.h>
+
+size_t
+__libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
+ size_t max)
+{
+ size_t i = max;
+
+ IFUNC_IMPL (i, name, memset,
+ IFUNC_IMPL_ADD (array, i, memset, IS_EV6_OR_LATER, __memset_ev6)
+ IFUNC_IMPL_ADD (array, i, memset, 1, __memset_ev5));
+
+ IFUNC_IMPL (i, name, rawmemchr,
+ IFUNC_IMPL_ADD (array, i, rawmemchr, HAS_CIX, ___rawmemchr_ev67)
+ IFUNC_IMPL_ADD (array, i, rawmemchr, 1, ___rawmemchr_ev5));
+
+ IFUNC_IMPL (i, name, stpcpy,
+ IFUNC_IMPL_ADD (array, i, stpcpy, HAS_CIX, ___stpcpy_ev67)
+ IFUNC_IMPL_ADD (array, i, stpcpy, 1, ___stpcpy_ev5));
+
+ IFUNC_IMPL (i, name, stpncpy,
+ IFUNC_IMPL_ADD (array, i, stpncpy, HAS_CIX, ___stpncpy_ev67)
+ IFUNC_IMPL_ADD (array, i, stpncpy, 1, ___stpncpy_ev5));
+
+ IFUNC_IMPL (i, name, strcat,
+ IFUNC_IMPL_ADD (array, i, strcat, HAS_CIX, __strcat_ev67)
+ IFUNC_IMPL_ADD (array, i, strcat, 1, __strcat_ev5));
+
+ IFUNC_IMPL (i, name, strchr,
+ IFUNC_IMPL_ADD (array, i, strchr, HAS_CIX, __strchr_ev67)
+ IFUNC_IMPL_ADD (array, i, strchr, 1, __strchr_ev5));
+
+ IFUNC_IMPL (i, name, strlen,
+ IFUNC_IMPL_ADD (array, i, strlen, HAS_CIX, __strlen_ev67)
+ IFUNC_IMPL_ADD (array, i, strlen, 1, __strlen_ev5));
+
+ IFUNC_IMPL (i, name, strncat,
+ IFUNC_IMPL_ADD (array, i, strncat, HAS_CIX, __strncat_ev67)
+ IFUNC_IMPL_ADD (array, i, strncat, 1, __strncat_ev5));
+
+ return 0;
+}
new file mode 100644
@@ -0,0 +1,69 @@
+/* Define IFUNC resolver CPU detection for Alpha.
+ 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
+ <https://www.gnu.org/licenses/>. */
+
+#ifndef _ALPHA_INIT_ARCH_H
+#define _ALPHA_INIT_ARCH_H
+
+/* implver returns:
+ 0 = EV4 (21064)
+ 1 = EV5 (21164)
+ 2 = EV6 (21264) family (EV6, EV67, EV68)
+ 3 = EV7 (21364) */
+
+static inline unsigned long
+__attribute__ ((always_inline))
+alpha_implver (void)
+{
+ unsigned long implver;
+ __asm__ ("implver %0" : "=r" (implver));
+ return implver;
+}
+
+/* amask tests for optional extensions. Returns zero bits for
+ supported features. Known bits:
+ 0x01 = BWX (byte/word extensions, EV56+)
+ 0x02 = FIX (sqrt/ftoi extensions, EV6+)
+ 0x04 = CIX (count extensions, EV67+)
+ 0x08 = MVI (multimedia extensions, EV6+) */
+
+static inline unsigned long
+__attribute__ ((always_inline))
+alpha_amask (unsigned long mask)
+{
+ unsigned long result;
+ __asm__ ("amask %1, %0" : "=r" (result) : "rI" (mask));
+ return result;
+}
+
+#define ALPHA_IMPL_EV4 0
+#define ALPHA_IMPL_EV5 1
+#define ALPHA_IMPL_EV6 2
+#define ALPHA_IMPL_EV7 3
+
+#define ALPHA_AMASK_BWX 0x01
+#define ALPHA_AMASK_FIX 0x02
+#define ALPHA_AMASK_CIX 0x04
+#define ALPHA_AMASK_MVI 0x08
+
+#define IS_EV6_OR_LATER (alpha_implver () >= ALPHA_IMPL_EV6)
+#define IS_EV7_OR_LATER (alpha_implver () >= ALPHA_IMPL_EV7)
+#define HAS_CIX (!(alpha_amask (ALPHA_AMASK_CIX)))
+
+#define INIT_ARCH()
+
+#endif /* _ALPHA_INIT_ARCH_H */