aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorYury Khrustalev <yury.khrustalev@arm.com>2025-07-22 15:50:03 +0100
committerYury Khrustalev <yury.khrustalev@arm.com>2025-07-31 12:39:10 +0100
commit479446beb4d212c19fe6b12d22a5dc6593798c47 (patch)
tree8a0ecf24d35f68e9bb81836d11a3d001e40ba3e9 /gcc
parentccffdcbbe90381eefb84c479aa9b7ff982fde6f1 (diff)
downloadgcc-479446beb4d212c19fe6b12d22a5dc6593798c47.zip
gcc-479446beb4d212c19fe6b12d22a5dc6593798c47.tar.gz
gcc-479446beb4d212c19fe6b12d22a5dc6593798c47.tar.bz2
testsuite: Add runtime test for FMV resolvers
gcc/testsuite/ChangeLog: * g++.target/aarch64/mv-cpu-features.C: new test.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/testsuite/g++.target/aarch64/mv-cpu-features.C82
1 files changed, 82 insertions, 0 deletions
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
index 0000000..ad6accd
--- /dev/null
+++ b/gcc/testsuite/g++.target/aarch64/mv-cpu-features.C
@@ -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;
+}