[PATCH 19/20] alpha: add multiarch infrastructure for IFUNC dispatch

Matt Turner mattst88@gmail.com
Wed Aug 12 01:19:56 GMT 2026


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.
---
 sysdeps/alpha/alphaev6/multiarch/Implies      |  1 +
 sysdeps/alpha/alphaev67/multiarch/Implies     |  1 +
 sysdeps/alpha/multiarch/Makefile              | 20 ++++++
 .../alpha/multiarch/dl-symbol-redir-ifunc.h   | 25 +++++++
 sysdeps/alpha/multiarch/ifunc-impl-list.c     | 64 +++++++++++++++++
 sysdeps/alpha/multiarch/init-arch.h           | 69 +++++++++++++++++++
 6 files changed, 180 insertions(+)
 create mode 100644 sysdeps/alpha/alphaev6/multiarch/Implies
 create mode 100644 sysdeps/alpha/alphaev67/multiarch/Implies
 create mode 100644 sysdeps/alpha/multiarch/Makefile
 create mode 100644 sysdeps/alpha/multiarch/dl-symbol-redir-ifunc.h
 create mode 100644 sysdeps/alpha/multiarch/ifunc-impl-list.c
 create mode 100644 sysdeps/alpha/multiarch/init-arch.h

diff --git ./sysdeps/alpha/alphaev6/multiarch/Implies ./sysdeps/alpha/alphaev6/multiarch/Implies
new file mode 100644
index 0000000000..c07181098c
--- /dev/null
+++ ./sysdeps/alpha/alphaev6/multiarch/Implies
@@ -0,0 +1 @@
+alpha/multiarch
diff --git ./sysdeps/alpha/alphaev67/multiarch/Implies ./sysdeps/alpha/alphaev67/multiarch/Implies
new file mode 100644
index 0000000000..fb91f5988c
--- /dev/null
+++ ./sysdeps/alpha/alphaev67/multiarch/Implies
@@ -0,0 +1 @@
+alpha/alphaev6/multiarch
diff --git ./sysdeps/alpha/multiarch/Makefile ./sysdeps/alpha/multiarch/Makefile
new file mode 100644
index 0000000000..87b08ec50d
--- /dev/null
+++ ./sysdeps/alpha/multiarch/Makefile
@@ -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
diff --git ./sysdeps/alpha/multiarch/dl-symbol-redir-ifunc.h ./sysdeps/alpha/multiarch/dl-symbol-redir-ifunc.h
new file mode 100644
index 0000000000..9b7f1e258e
--- /dev/null
+++ ./sysdeps/alpha/multiarch/dl-symbol-redir-ifunc.h
@@ -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
diff --git ./sysdeps/alpha/multiarch/ifunc-impl-list.c ./sysdeps/alpha/multiarch/ifunc-impl-list.c
new file mode 100644
index 0000000000..cede63d975
--- /dev/null
+++ ./sysdeps/alpha/multiarch/ifunc-impl-list.c
@@ -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;
+}
diff --git ./sysdeps/alpha/multiarch/init-arch.h ./sysdeps/alpha/multiarch/init-arch.h
new file mode 100644
index 0000000000..03d5612e98
--- /dev/null
+++ ./sysdeps/alpha/multiarch/init-arch.h
@@ -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 */
-- 
2.54.0



More information about the Libc-alpha mailing list