]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
aarch64: testsuite: Add test for supported FMV extensions.
authorAlfie Richards <alfie.richards@arm.com>
Tue, 7 Oct 2025 12:42:41 +0000 (12:42 +0000)
committerAlfie Richards <alfie.richards@arm.com>
Thu, 23 Oct 2025 12:30:32 +0000 (12:30 +0000)
Add tests that check the aarch64 version features are supported, that they
have the correct priority ordering, and that the generated resolver is correct.

gcc/testsuite/ChangeLog:

* gcc.target/aarch64/fmv_priority1.c: New test.
* gcc.target/aarch64/fmv_priority2.c: New test.
* gcc.target/aarch64/fmv_priority.in: Support file.

Reviewed-by: Wilco Dijkstra <wilco.dijkstra@arm.com>
gcc/testsuite/gcc.target/aarch64/fmv_priority.in [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/fmv_priority1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/fmv_priority2.c [new file with mode: 0644]

diff --git a/gcc/testsuite/gcc.target/aarch64/fmv_priority.in b/gcc/testsuite/gcc.target/aarch64/fmv_priority.in
new file mode 100644 (file)
index 0000000..93209bc
--- /dev/null
@@ -0,0 +1,92 @@
+int fn [[gnu::target_version("default")]] (int)                        { return 1; }
+int fn_default (int) asm("fn.default");
+int fn [[gnu::target_version("rng")]] (int)                    { return 1; }
+int fn_rng(int) asm("fn._Mrng");
+int fn [[gnu::target_version("flagm")]] (int)                  { return 1; }
+int fn_flagm(int) asm("fn._Mflagm");
+int fn [[gnu::target_version("flagm2")]] (int)                 { return 1; }
+int fn_flagm2(int) asm("fn._Mflagm2");
+int fn [[gnu::target_version("lse")]] (int)                    { return 1; }
+int fn_lse(int) asm("fn._Mlse");
+int fn [[gnu::target_version("fp")]] (int)                     { return 1; }
+int fn_fp(int) asm("fn._Mfp");
+int fn [[gnu::target_version("simd")]] (int)                   { return 1; }
+int fn_simd(int) asm("fn._Msimd");
+int fn [[gnu::target_version("dotprod")]] (int)                        { return 1; }
+int fn_dotprod(int) asm("fn._Mdotprod");
+int fn [[gnu::target_version("sm4")]] (int)                    { return 1; }
+int fn_sm4(int) asm("fn._Msm4");
+int fn [[gnu::target_version("rdm")]] (int)                    { return 1; }
+int fn_rdm(int) asm("fn._MrdmaMrdm");
+int fn [[gnu::target_version("crc")]] (int)                    { return 1; }
+int fn_crc(int) asm("fn._Mcrc");
+int fn [[gnu::target_version("sha2")]] (int)                   { return 1; }
+int fn_sha2(int) asm("fn._Msha2");
+int fn [[gnu::target_version("sha3")]] (int)                   { return 1; }
+int fn_sha3(int) asm("fn._Msha3");
+int fn [[gnu::target_version("aes")]] (int)                    { return 1; }
+int fn_aes(int) asm("fn._Maes");
+int fn [[gnu::target_version("fp16")]] (int)                   { return 1; }
+int fn_fp16(int) asm("fn._Mfp16");
+int fn [[gnu::target_version("fp16fml")]] (int)                        { return 1; }
+int fn_fp16fml(int) asm("fn._Mfp16fml");
+/* TODO: These FMV features are not yet supported in GCC. */
+// int fn [[gnu::target_version("dit")]] (int)                 { return 1; }
+// int fn [[gnu::target_version("dpb")]] (int)                 { return 1; }
+// int fn [[gnu::target_version("dpb2")]] (int)                        { return 1; }
+int fn [[gnu::target_version("jscvt")]] (int)                  { return 1; }
+int fn_jscvt(int) asm("fn._Mjscvt");
+int fn [[gnu::target_version("fcma")]] (int)                   { return 1; }
+int fn_fcma(int) asm("fn._Mfcma");
+int fn [[gnu::target_version("rcpc")]] (int)                   { return 1; }
+int fn_rcpc(int) asm("fn._Mrcpc");
+int fn [[gnu::target_version("rcpc2")]] (int)                  { return 1; }
+int fn_rcpc2(int) asm("fn._Mrcpc2");
+int fn [[gnu::target_version("rcpc3")]] (int)                  { return 1; }
+int fn_rcpc3(int) asm("fn._Mrcpc3");
+int fn [[gnu::target_version("frintts")]] (int)                        { return 1; }
+int fn_frintts(int) asm("fn._Mfrintts");
+int fn [[gnu::target_version("i8mm")]] (int)                   { return 1; }
+int fn_i8mm(int) asm("fn._Mi8mm");
+int fn [[gnu::target_version("bf16")]] (int)                   { return 1; }
+int fn_bf16(int) asm("fn._Mbf16");
+int fn [[gnu::target_version("sve")]] (int)                    { return 1; }
+int fn_sve(int) asm("fn._Msve");
+int fn [[gnu::target_version("f32mm")]] (int)                  { return 1; }
+int fn_f32mm(int) asm("fn._Mf32mm");
+int fn [[gnu::target_version("f64mm")]] (int)                  { return 1; }
+int fn_f64mm(int) asm("fn._Mf64mm");
+int fn [[gnu::target_version("sve2")]] (int)                   { return 1; }
+int fn_sve2(int) asm("fn._Msve2");
+int fn [[gnu::target_version("sve2-aes")]] (int)               { return 1; }
+int fn_sve2_aes(int) asm("fn._Msve2_aes");
+int fn [[gnu::target_version("sve2-bitperm")]] (int)           { return 1; }
+int fn_sve2_bitperm(int) asm("fn._Msve2_bitperm");
+int fn [[gnu::target_version("sve2-sha3")]] (int)              { return 1; }
+int fn_sve2_sha3(int) asm("fn._Msve2_sha3");
+int fn [[gnu::target_version("sve2-sm4")]] (int)               { return 1; }
+int fn_sve2_sm4(int) asm("fn._Msve2_sm4");
+int fn [[gnu::target_version("sve2+sme")]] (int)               { return 1; }
+int fn_sve2_sme(int) asm("fn._Msve2Msme");
+/* TODO: This FMV features is not yet supported in GCC. */
+// int fn [[gnu::target_version("memtag")]] (int)              { return 1; }
+int fn [[gnu::target_version("sb")]] (int)                     { return 1; }
+int fn_sb(int) asm("fn._Msb");
+/* TODO: This FMV feature is not yet supported in GCC. */
+// int fn [[gnu::target_version("ssbs")]] (int)                        { return 1; }
+// int fn_ssbs(int) asm("fn._Mssbs");
+/* TODO: This FMV feature is not yet supported in GCC. */
+// int fn [[gnu::target_version("bti")]] (int)                 { return 1; }
+int fn [[gnu::target_version("wfxt")]] (int)                   { return 1; }
+int fn_wfxt(int) asm("fn._Mwfxt");
+int fn [[gnu::target_version("sve2+sme-f64f64")]] (int)                { return 1; }
+int fn_sve2_sme_f64f64(int) asm("fn._Msve2Msme_f64f64");
+int fn [[gnu::target_version("sve2+sme-i16i64")]] (int)                { return 1; }
+int fn_sve2_sme_i16i64(int) asm("fn._Msve2Msme_i16i64");
+int fn [[gnu::target_version("sve2+sme2")]] (int)              { return 1; }
+int fn_sve2_sme2(int) asm("fn._Msve2Msme2");
+int fn [[gnu::target_version("mops")]] (int)                   { return 1; }
+int fn_mops(int) asm("fn._Mmops");
+int fn [[gnu::target_version("cssc")]] (int)                   { return 1; }
+int fn_cssc(int) asm("fn._Mcssc");
+
diff --git a/gcc/testsuite/gcc.target/aarch64/fmv_priority1.c b/gcc/testsuite/gcc.target/aarch64/fmv_priority1.c
new file mode 100644 (file)
index 0000000..942b7a7
--- /dev/null
@@ -0,0 +1,175 @@
+/* { dg-do run { target { aarch64_asm_sme2_ok } } }  */
+/* { dg-require-ifunc "" } */
+/* { dg-options "-O0 -march=armv8-a" } */
+
+#include <sys/auxv.h>
+#include "../../../common/config/aarch64/cpuinfo.h"
+
+/* This test has a FMV function set with one version per feature we support.
+   Each version is turned on incrementally and the generated resolver is
+   checked to show the correct version is chosen.  */
+
+/* The resolver does actually take arguments, but ignores them and uses
+   __aarch64_cpu_features global instead to establish what features are
+   present.  */
+int (*(resolver)(void)) (int) asm("fn.resolver");
+
+extern struct {
+  unsigned long long features;
+} aarch64_cpu_features asm("__aarch64_cpu_features");
+
+#include "fmv_priority.in"
+
+#define setCPUFeature(F) aarch64_cpu_features.features |= 1UL << F
+
+int main () {
+  aarch64_cpu_features.features = 0;
+
+  /* Initialize the CPU features, so the resolver doesn't try fetch it.  */
+  setCPUFeature(FEAT_INIT);
+
+  /* Go through features in order and assure the priorities are correct.
+     By checking the correct versions are resolved.  */
+
+  /* Some are missing as they are defined in the ACLE but are not yet
+     implemented.  */
+  if (resolver() != &fn_default) return 1;
+
+  setCPUFeature(FEAT_RNG);
+  if (resolver() != &fn_rng) return 1;
+
+  setCPUFeature(FEAT_FLAGM);
+ if (resolver() != &fn_flagm) return 1;
+
+  setCPUFeature(FEAT_FLAGM2);
+  if (resolver() != &fn_flagm2) return 1;
+
+  setCPUFeature (FEAT_LSE);
+  if (resolver () != &fn_lse) return 1;
+
+  setCPUFeature (FEAT_FP);
+  if (resolver () != &fn_fp) return 1;
+
+  setCPUFeature (FEAT_SIMD);
+  if (resolver () != &fn_simd) return 1;
+
+  setCPUFeature (FEAT_DOTPROD);
+  if (resolver () != &fn_dotprod) return 1;
+
+  setCPUFeature (FEAT_SM4);
+  if(resolver() != &fn_sm4) return 1;
+
+  setCPUFeature (FEAT_RDM);
+  if(resolver() != &fn_rdm) return 1;
+
+  setCPUFeature (FEAT_CRC);
+  if (resolver () != &fn_crc) return 1;
+
+  setCPUFeature (FEAT_SHA2);
+  if (resolver () != &fn_sha2) return 1;
+
+  setCPUFeature (FEAT_SHA3);
+  if (resolver () != &fn_sha3) return 1;
+
+  setCPUFeature(FEAT_PMULL);
+  if(resolver() != &fn_aes) return 1;
+
+  setCPUFeature (FEAT_FP16);
+  if (resolver () != &fn_fp16) return 1;
+
+  setCPUFeature (FEAT_FP16FML);
+  if(resolver() != &fn_fp16fml) return 1;
+
+  setCPUFeature (FEAT_DIT);
+  // if(resolver() != &fn_dit) return 1;
+  // 
+  setCPUFeature (FEAT_DPB);
+  // if(resolver() != &fn_dpb) return 1;
+  // 
+  setCPUFeature (FEAT_DPB2);
+  // if(resolver() != &fn_dpb2) return 1;
+  // 
+  setCPUFeature (FEAT_JSCVT);
+  if (resolver () != &fn_jscvt) return 1;
+
+  setCPUFeature (FEAT_FCMA);
+  if (resolver () != &fn_fcma) return 1;
+
+  setCPUFeature (FEAT_RCPC);
+  if (resolver () != &fn_rcpc) return 1;
+
+  setCPUFeature (FEAT_RCPC2);
+  if (resolver () != &fn_rcpc2) return 1;
+
+  setCPUFeature (FEAT_RCPC3);
+  // if(resolver() != &fn_rcpc3) return 1;
+  // 
+  setCPUFeature (FEAT_FRINTTS);
+  if (resolver () != &fn_frintts) return 1;
+
+  setCPUFeature (FEAT_I8MM);
+  if (resolver () != &fn_i8mm) return 1;
+
+  setCPUFeature (FEAT_BF16);
+  if (resolver () != &fn_bf16) return 1;
+
+  setCPUFeature (FEAT_SVE);
+  if (resolver () != &fn_sve) return 1;
+
+  setCPUFeature (FEAT_SVE_F32MM);
+  if(resolver() != &fn_f32mm) return 1;
+
+  setCPUFeature (FEAT_SVE_F64MM);
+  if(resolver() != &fn_f64mm) return 1;
+
+  setCPUFeature (FEAT_SVE2);
+  if (resolver () != &fn_sve2) return 1;
+
+  setCPUFeature(FEAT_SVE_PMULL128);
+  if(resolver() != &fn_sve2_aes) return 1;
+
+  setCPUFeature (FEAT_SVE_BITPERM);
+  if (resolver () != &fn_sve2_bitperm) return 1;
+
+  setCPUFeature (FEAT_SVE_SHA3);
+  if (resolver () != &fn_sve2_sha3) return 1;
+
+  setCPUFeature (FEAT_SVE_SM4);
+  if (resolver () != &fn_sve2_sm4) return 1;
+
+  setCPUFeature (FEAT_SME);
+  if (resolver () != &fn_sve2_sme) return 1;
+
+  setCPUFeature(FEAT_MEMTAG2);
+  // if(resolver() != &fn_memtag) return 1;
+
+  setCPUFeature (FEAT_SB);
+  if (resolver () != &fn_sb) return 1;
+
+  setCPUFeature(FEAT_SSBS2);
+  // if(resolver() != &fn_ssbs) return 1;
+  setCPUFeature(FEAT_BTI);
+  // if(resolver() != &fn_bti) return 1;
+
+  setCPUFeature (FEAT_WFXT);
+  if (resolver () != &fn_wfxt) return 1;
+
+  setCPUFeature (FEAT_SME_F64);
+  if (resolver () != &fn_sve2_sme_f64f64) return 1;
+
+  setCPUFeature (FEAT_SME_I64);
+  if (resolver () != &fn_sve2_sme_i16i64) return 1;
+
+  setCPUFeature (FEAT_SME2);
+  if (resolver () != &fn_sve2_sme2) return 1;
+
+  setCPUFeature (FEAT_MOPS);
+  if (resolver () != &fn_mops) return 1;
+
+  setCPUFeature (FEAT_CSSC);
+  if (resolver () != &fn_cssc) return 1;
+
+  return 0;
+}
+
diff --git a/gcc/testsuite/gcc.target/aarch64/fmv_priority2.c b/gcc/testsuite/gcc.target/aarch64/fmv_priority2.c
new file mode 100644 (file)
index 0000000..dbeb15e
--- /dev/null
@@ -0,0 +1,29 @@
+/* { dg-do compile }  */
+/* { dg-require-ifunc "" } */
+/* { dg-options "-O0 -march=armv8-a -fdump-ipa-targetclone1-details" } */
+
+#include "fmv_priority.in"
+
+// Checks that the versions are in the correct order
+// Each of these lines checks 3 consecutive versions in the list with one overlap
+/* { dg-final { scan-ipa-dump-times "Version order for fn/\[0-9\]+:\\nfn\.default/\[0-9\]+\\n" 1 "targetclone1" } } */
+/* { dg-final { scan-ipa-dump-times "fn\.default/\[0-9\]+\\nfn\._Mrng/\[0-9\]+\\nfn\._Mflagm/\[0-9\]+\\n" 1 "targetclone1" } } */
+/* { dg-final { scan-ipa-dump-times "fn\._Mflagm/\[0-9\]+\\nfn\._Mflagm2/\[0-9\]+\\nfn\._Mlse/\[0-9\]+\\n" 1 "targetclone1" } } */
+/* { dg-final { scan-ipa-dump-times "fn\._Mlse/\[0-9\]+\\nfn\._Mfp/\[0-9\]+\\nfn\._Msimd/\[0-9\]+\\n" 1 "targetclone1" } } */
+/* { dg-final { scan-ipa-dump-times "fn\._Msimd/\[0-9\]+\\nfn\._Mdotprod/\[0-9\]+\\nfn\._Msm4/\[0-9\]+\\n" 1 "targetclone1" } } */
+/* { dg-final { scan-ipa-dump-times "fn\._Msm4/\[0-9\]+\\nfn\._MrdmaMrdm/\[0-9\]+\\nfn\._Mcrc/\[0-9\]+\\n" 1 "targetclone1" } } */
+/* { dg-final { scan-ipa-dump-times "fn\._Mcrc/\[0-9\]+\\nfn\._Msha2/\[0-9\]+\\nfn\._Msha3/\[0-9\]+\\n" 1 "targetclone1" } } */
+/* { dg-final { scan-ipa-dump-times "fn\._Msha3/\[0-9\]+\\nfn\._Maes/\[0-9\]+\\nfn\._Mfp16/\[0-9\]+\\n" 1 "targetclone1" } } */
+/* { dg-final { scan-ipa-dump-times "fn\._Mfp16/\[0-9\]+\\nfn\._Mfp16fml/\[0-9\]+\\nfn\._Mjscvt/\[0-9\]+\\n" 1 "targetclone1" } } */
+/* { dg-final { scan-ipa-dump-times "fn\._Mjscvt/\[0-9\]+\\nfn\._Mfcma/\[0-9\]+\\nfn\._Mrcpc/\[0-9\]+\\n" 1 "targetclone1" } } */
+/* { dg-final { scan-ipa-dump-times "fn\._Mrcpc/\[0-9\]+\\nfn\._Mrcpc2/\[0-9\]+\\nfn\._Mrcpc3/\[0-9\]+\\n" 1 "targetclone1" } } */
+/* { dg-final { scan-ipa-dump-times "fn\._Mrcpc3/\[0-9\]+\\nfn\._Mfrintts/\[0-9\]+\\nfn\._Mi8mm/\[0-9\]+\\n" 1 "targetclone1" } } */
+/* { dg-final { scan-ipa-dump-times "fn\._Mi8mm/\[0-9\]+\\nfn\._Mbf16/\[0-9\]+\\nfn\._Msve/\[0-9\]+\\n" 1 "targetclone1" } } */
+/* { dg-final { scan-ipa-dump-times "fn\._Msve/\[0-9\]+\\nfn\._Mf32mm/\[0-9\]+\\nfn\._Mf64mm/\[0-9\]+\\n" 1 "targetclone1" } } */
+/* { dg-final { scan-ipa-dump-times "fn\._Mf64mm/\[0-9\]+\\nfn\._Msve2/\[0-9\]+\\nfn\._Msve2_aes/\[0-9\]+\\n" 1 "targetclone1" } } */
+/* { dg-final { scan-ipa-dump-times "fn\._Msve2_aes/\[0-9\]+\\nfn\._Msve2_bitperm/\[0-9\]+\\nfn\._Msve2_sha3/\[0-9\]+\\n" 1 "targetclone1" } } */
+/* { dg-final { scan-ipa-dump-times "fn\._Msve2_sha3/\[0-9\]+\\nfn\._Msve2_sm4/\[0-9\]+\\nfn\._Msve2Msme/\[0-9\]+\\n" 1 "targetclone1" } } */
+/* { dg-final { scan-ipa-dump-times "fn\._Msve2Msme/\[0-9\]+\\nfn\._Msb/\[0-9\]+\\nfn\._Mwfxt/\[0-9\]+\\n" 1 "targetclone1" } } */
+/* { dg-final { scan-ipa-dump-times "fn\._Mwfxt/\[0-9\]+\\nfn\._Msve2Msme_f64f64/\[0-9\]+\\nfn\._Msve2Msme_i16i64/\[0-9\]+\\n" 1 "targetclone1" } } */
+/* { dg-final { scan-ipa-dump-times "fn\._Msve2Msme_i16i64/\[0-9\]+\\nfn\._Msve2Msme2/\[0-9\]+\\nfn\._Mmops/\[0-9\]+\\n" 1 "targetclone1" } } */
+/* { dg-final { scan-ipa-dump-times "fn\._Mmops/\[0-9\]+\\nfn\._Mcssc/\[0-9\]+\\n" 1 "targetclone1" } } */