]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
testsuite: Add runtime test for FMV resolvers
authorYury Khrustalev <yury.khrustalev@arm.com>
Tue, 22 Jul 2025 14:50:03 +0000 (15:50 +0100)
committerYury Khrustalev <yury.khrustalev@arm.com>
Thu, 31 Jul 2025 11:39:10 +0000 (12:39 +0100)
gcc/testsuite/ChangeLog:

* g++.target/aarch64/mv-cpu-features.C: new test.

gcc/testsuite/g++.target/aarch64/mv-cpu-features.C [new file with mode: 0644]

diff --git a/gcc/testsuite/g++.target/aarch64/mv-cpu-features.C b/gcc/testsuite/g++.target/aarch64/mv-cpu-features.C
new file mode 100644 (file)
index 0000000..ad6accd
--- /dev/null
@@ -0,0 +1,82 @@
+/* { dg-do run }  */
+/* { dg-require-ifunc "" } */
+/* { dg-require-effective-target mmap } */
+/* { dg-options "-Wno-experimental-fmv-target" } */
+
+#include <cstdint>
+#include <sys/auxv.h>
+
+__attribute__((target_version ("default")))
+int foo ()
+{
+  return 0;
+}
+
+__attribute__((target_version ("rng")))
+int foo ()
+{
+  return 1;
+}
+
+__attribute__((target_version ("lse")))
+int foo ()
+{
+  return 2;
+}
+
+typedef struct {
+  uint64_t size;
+  uint64_t hwcap;
+  uint64_t hwcap2;
+  uint64_t hwcap3;
+  uint64_t hwcap4;
+} ifunc_arg_t;
+
+int impl ()
+{
+  return 0;
+}
+
+#ifndef _IFUNC_ARG_HWCAP
+#define _IFUNC_ARG_HWCAP (1ULL << 62)
+#endif
+
+extern "C" void
+__init_cpu_features_resolver (unsigned long hwcap, const ifunc_arg_t *arg);
+
+extern "C" void *
+fun_resolver (uint64_t a0, const ifunc_arg_t *a1)
+{
+  ifunc_arg_t arg = {};
+  arg.size = sizeof (ifunc_arg_t);
+  /* These flags determine that the implementation of foo ()
+     that returns 2 will be selected.  */
+  arg.hwcap = HWCAP_ATOMICS;
+  arg.hwcap2 = HWCAP2_RNG;
+  __init_cpu_features_resolver (arg.hwcap | _IFUNC_ARG_HWCAP, &arg);
+  return (void *)(uintptr_t)impl;
+}
+
+extern "C" int fun (void) __attribute__((ifunc ("fun_resolver")));
+
+/* In this test we expect that the manual resolver for the fun ()
+   function will be executed before the automatic resolver for the
+   FMV function foo ().  This is because resolvers from the same TU
+   are executed according to the offset of corresponding relocations.
+
+   Automatic resolver is generated in a dedicated section while the
+   manually written resolver will be put in the .text section which
+   will come first.
+
+   The manual resolver above calls __init_cpu_features_resolver()
+   supplying synthetic ifunc_arg_t fields that will determine the
+   choice for the FMV implementation.
+   */
+
+int main ()
+{
+  int res = fun ();
+  if (res == 0 && foo () == 2)
+    return 0;
+  return 1;
+}