https://github.com/jthackray updated https://github.com/llvm/llvm-project/pull/190959
>From 77d22642c936deb7f3e117db39190655e185d7da Mon Sep 17 00:00:00 2001 From: Jonathan Thackray <[email protected]> Date: Fri, 3 Apr 2026 01:14:47 +0100 Subject: [PATCH 1/2] [AArch64][clang] Use tablegen rather than hard-coded feature dependencies Refactor AArch64 frontend feature handling so extension relationships come from the TargetParser extension graph instead of hand-written dependency code in C++. This makes `llvm::AArch64::ExtensionSet` the source of truth for dependency expansion while still keeping the short `Has...` names used in the frontend code. This removes a large amount of duplicated implication logic from `handleTargetFeatures` and related feature queries. The frontend now rebuilds its extension state from TableGen-derived data and then derives its cached feature state from that, rather than maintaining parallel dependency rules in C++. I also preserved several pieces of historical frontend behaviour that are not represented directly in the extension graph. Explicit disables such as `no-sme` still win after implied-feature expansion, direct `+fullfp16` and `+jscvt` still restore the expected NEON-facing state, and SME-family features no longer incorrectly appear to enable AdvSIMD/NEON. Finally, I added regression coverage for the direct-feature and explicit disable cases uncovered during review, including raw `-target-feature` combinations and target-attribute cases such as `no-sme`. --- clang/lib/Basic/Targets/AArch64.cpp | 517 ++++++++---------- clang/lib/Basic/Targets/AArch64.h | 80 +-- .../Targets/AArch64TargetInfoFeatures.inc | 69 +++ clang/lib/Sema/SemaARM.cpp | 6 +- clang/lib/Sema/SemaChecking.cpp | 2 +- .../Preprocessor/aarch64-target-features.c | 22 + ...-sme-func-attrs-without-target-feature.cpp | 5 + 7 files changed, 346 insertions(+), 355 deletions(-) create mode 100644 clang/lib/Basic/Targets/AArch64TargetInfoFeatures.inc diff --git a/clang/lib/Basic/Targets/AArch64.cpp b/clang/lib/Basic/Targets/AArch64.cpp index 9b951e69cce33..399d9ed5ae052 100644 --- a/clang/lib/Basic/Targets/AArch64.cpp +++ b/clang/lib/Basic/Targets/AArch64.cpp @@ -254,7 +254,8 @@ bool AArch64TargetInfo::validateBranchProtection(StringRef Spec, StringRef, const LangOptions &LO, StringRef &Err) const { llvm::ARM::ParsedBranchProtection PBP; - if (!llvm::ARM::parseBranchProtection(Spec, PBP, Err, HasPAuthLR)) + if (!llvm::ARM::parseBranchProtection( + Spec, PBP, Err, hasExtension(llvm::AArch64::AEK_PAUTHLR))) return false; // GCS is currently untested with ptrauth-returns, but enabling this could be @@ -494,6 +495,13 @@ void AArch64TargetInfo::getTargetDefines(const LangOptions &Opts, if (FPU & SveMode) Builder.defineMacro("__ARM_FEATURE_SVE", "1"); + const bool HasSVE = FPU & SveMode; + const bool HasNeon = FPU & NeonMode; +#define AARCH64_EXTENSION_FEATURE(Name, Ext) \ + [[maybe_unused]] const bool Name = hasExtension(llvm::AArch64::AEK_##Ext); +#include "AArch64TargetInfoFeatures.inc" +#undef AARCH64_EXTENSION_FEATURE + if (HasSVE2) Builder.defineMacro("__ARM_FEATURE_SVE2", "1"); @@ -621,7 +629,7 @@ void AArch64TargetInfo::getTargetDefines(const LangOptions &Opts, Builder.defineMacro("__ARM_FEATURE_SM4", "1"); } - if (HasPAuth) + if (hasPAuth()) Builder.defineMacro("__ARM_FEATURE_PAUTH", "1"); if (HasPAuthLR) @@ -633,10 +641,10 @@ void AArch64TargetInfo::getTargetDefines(const LangOptions &Opts, if (HasUnalignedAccess) Builder.defineMacro("__ARM_FEATURE_UNALIGNED", "1"); - if ((FPU & NeonMode) && HasFullFP16) + if ((FPU & NeonMode) && hasFullFP16()) Builder.defineMacro("__ARM_FEATURE_FP16_VECTOR_ARITHMETIC", "1"); - if (HasFullFP16) - Builder.defineMacro("__ARM_FEATURE_FP16_SCALAR_ARITHMETIC", "1"); + if (hasFullFP16()) + Builder.defineMacro("__ARM_FEATURE_FP16_SCALAR_ARITHMETIC", "1"); if (HasDotProd) Builder.defineMacro("__ARM_FEATURE_DOTPROD", "1"); @@ -644,7 +652,7 @@ void AArch64TargetInfo::getTargetDefines(const LangOptions &Opts, if (HasMTE) Builder.defineMacro("__ARM_FEATURE_MEMORY_TAGGING", "1"); - if (HasMatMul) + if (HasI8MM) Builder.defineMacro("__ARM_FEATURE_MATMUL_INT8", "1"); if (HasLSE) @@ -657,20 +665,20 @@ void AArch64TargetInfo::getTargetDefines(const LangOptions &Opts, Builder.defineMacro("__ARM_FEATURE_BF16_SCALAR_ARITHMETIC", "1"); } - if ((FPU & SveMode) && HasBFloat16) { + if (HasSVE && HasBFloat16) { Builder.defineMacro("__ARM_FEATURE_SVE_BF16", "1"); } - if ((FPU & SveMode) && HasMatmulFP64) + if (HasSVE && HasF64MM) Builder.defineMacro("__ARM_FEATURE_SVE_MATMUL_FP64", "1"); - if ((FPU & SveMode) && HasMatmulFP32) + if (HasSVE && HasF32MM) Builder.defineMacro("__ARM_FEATURE_SVE_MATMUL_FP32", "1"); - if ((FPU & SveMode) && HasMatMul) + if (HasSVE && HasI8MM) Builder.defineMacro("__ARM_FEATURE_SVE_MATMUL_INT8", "1"); - if ((FPU & NeonMode) && HasFP16FML) + if (HasNeon && HasFP16FML) Builder.defineMacro("__ARM_FEATURE_FP16_FML", "1"); if (Opts.hasSignReturnAddress()) { @@ -869,11 +877,19 @@ struct FeatureLookupBuilder { }; void AArch64TargetInfo::computeFeatureLookup() { + const bool HasFP = FPU & FPUMode; + const bool HasNeon = FPU & NeonMode; + const bool HasSVE = FPU & SveMode; +#define AARCH64_EXTENSION_FEATURE(Name, Ext) \ + [[maybe_unused]] const bool Name = hasExtension(llvm::AArch64::AEK_##Ext); +#include "AArch64TargetInfoFeatures.inc" +#undef AARCH64_EXTENSION_FEATURE + FeatureLookupBuilder(HasFeatureLookup) .Cases({"aarch64", "arm64", "arm"}, true) .Case("fmv", HasFMV) - .Case("fp", FPU & FPUMode) - .Cases({"neon", "simd"}, FPU & NeonMode) + .Case("fp", HasFP) + .Cases({"neon", "simd"}, HasNeon) .Case("jscvt", HasJSCVT) .Case("fcma", HasFCMA) .Case("rng", HasRandGen) @@ -889,24 +905,24 @@ void AArch64TargetInfo::computeFeatureLookup() { .Case("sha2", HasSHA2) .Case("sha3", HasSHA3) .Cases({"aes", "pmull"}, HasAES) - .Cases({"fp16", "fullfp16"}, HasFullFP16) + .Cases({"fp16", "fullfp16"}, hasFullFP16()) .Case("dit", HasDIT) .Case("dpb", HasCCPP) .Case("dpb2", HasCCDP) .Case("rcpc", HasRCPC) .Case("frintts", HasFRInt3264) - .Case("i8mm", HasMatMul) + .Case("i8mm", HasI8MM) .Case("bf16", HasBFloat16) - .Case("sve", FPU & SveMode) + .Case("sve", HasSVE) .Case("sve-b16b16", HasSVEB16B16) - .Case("f32mm", FPU & SveMode && HasMatmulFP32) - .Case("f64mm", FPU & SveMode && HasMatmulFP64) - .Case("sve2", FPU & SveMode && HasSVE2) + .Case("f32mm", HasSVE && HasF32MM) + .Case("f64mm", HasSVE && HasF64MM) + .Case("sve2", HasSVE && HasSVE2) .Case("sve-aes", HasSVEAES) .Case("sve-bitperm", FPU & HasSVEBitPerm) - .Case("sve2-sha3", FPU & SveMode && HasSVE2SHA3) - .Case("sve2-sm4", FPU & SveMode && HasSVE2SM4) - .Case("sve2p1", FPU & SveMode && HasSVE2p1) + .Case("sve2-sha3", HasSVE && HasSVE2SHA3) + .Case("sve2-sm4", HasSVE && HasSVE2SM4) + .Case("sve2p1", HasSVE && HasSVE2p1) .Case("sme", HasSME) .Case("sme2", HasSME2) .Case("sme2p1", HasSME2p1) @@ -939,7 +955,7 @@ void AArch64TargetInfo::computeFeatureLookup() { .Case("sve-bfscale", HasSVE_BFSCALE) .Case("sve-aes2", HasSVE_AES2) .Case("ssve-aes", HasSSVE_AES) - .Case("sve2p2", FPU & SveMode && HasSVE2p2) + .Case("sve2p2", HasSVE && HasSVE2p2) .Case("sme2p2", HasSME2p2); } @@ -947,6 +963,142 @@ bool AArch64TargetInfo::hasFeature(StringRef Feature) const { return HasFeatureLookup.contains(Feature); } +bool AArch64TargetInfo::hasExtension(llvm::AArch64::ArchExtKind Ext) const { + return EnabledExtensions.test(Ext); +} + +bool AArch64TargetInfo::hasPAuth() const { + return hasExtension(llvm::AArch64::AEK_PAUTH) || + hasExtension(llvm::AArch64::AEK_PAUTHLR); +} + +bool AArch64TargetInfo::hasFullFP16() const { + return hasExtension(llvm::AArch64::AEK_FP16) || + hasExtension(llvm::AArch64::AEK_SVEAES) || + hasExtension(llvm::AArch64::AEK_SVEBITPERM); +} + +// Find the most specific explicit architecture feature in a target-feature +// list, e.g. "+v8.6a +v9.2a +sve2" would return the ArchInfo for v9.2a. +static std::optional<llvm::AArch64::ArchInfo> +findExplicitBaseArchForTargetFeatures(ArrayRef<std::string> Features) { + std::optional<llvm::AArch64::ArchInfo> BaseArch; + for (const std::string &Feature : Features) { + StringRef Name = Feature; + if (!Name.starts_with("+")) + continue; + if (std::optional<llvm::AArch64::ArchInfo> Candidate = + llvm::AArch64::ArchInfo::findBySubArch(Name.drop_front())) { + if (!BaseArch || Candidate->Profile != BaseArch->Profile || + Candidate->Version > BaseArch->Version) + BaseArch = Candidate; + } + } + return BaseArch; +} + +// Map the frontend's legacy target-feature spellings onto the backend +// extension names before consulting the AArch64 extension graph. +static StringRef canonicalizeExtensionLookupFeature(StringRef Feature) { + return llvm::StringSwitch<StringRef>(Feature) + .Case("+fcma", "+complxnum") + .Case("-fcma", "-complxnum") + .Case("+jscvt", "+jsconv") + .Case("-jscvt", "-jsconv") + .Default(Feature); +} + +static std::optional<llvm::AArch64::ExtensionInfo> +lookupExtensionForTargetFeature(StringRef Feature) { + return llvm::AArch64::targetFeatureToExtension( + canonicalizeExtensionLookupFeature(Feature)); +} + +static std::optional<llvm::AArch64::ExtensionInfo> +lookupExtensionForFeatureName(StringRef Name) { + return lookupExtensionForTargetFeature(("+" + Name).str()); +} + +// Direct feature spellings that historically force Clang's NEON-facing FPU +// state. +static bool enablesNeonFPUCompat(StringRef Feature) { + return llvm::StringSwitch<bool>(Feature) + .Cases({"+neon", "+simd", "+fp-armv8", "+jscvt", "+jsconv"}, true) + .Cases({"+fcma", "+fullfp16", "+dotprod", "+fp16fml"}, true) + .Cases({"+aes", "+sha2", "+sha3", "+sm4", "+rdm"}, true) + .Default(false); +} + +// Rebuild a temporary extension set from the frontend feature map so AArch64 +// implied-feature queries can follow the extension dependency graph. +static llvm::AArch64::ExtensionSet +buildExtensionSetFromFeatureMap(const llvm::StringMap<bool> &Features) { + llvm::AArch64::ExtensionSet FeatureBits; + SmallVector<llvm::AArch64::ArchInfo, 4> EnabledArchs; + SmallVector<llvm::AArch64::ArchExtKind, 16> ExplicitEnables; + SmallVector<llvm::AArch64::ArchExtKind, 16> ExplicitDisables; + + for (const auto &Feature : Features) { + if (std::optional<llvm::AArch64::ArchInfo> AI = + llvm::AArch64::ArchInfo::findBySubArch(Feature.getKey())) { + if (Feature.getValue()) + EnabledArchs.push_back(*AI); + continue; + } + + std::string TargetFeature = + (Feature.getValue() ? "+" : "-") + Feature.getKey().str(); + if (auto ExtInfo = lookupExtensionForTargetFeature(TargetFeature)) { + if (Feature.getValue()) + ExplicitEnables.push_back(ExtInfo->ID); + else + ExplicitDisables.push_back(ExtInfo->ID); + } + } + + for (const llvm::AArch64::ArchInfo &AI : EnabledArchs) + FeatureBits.addArchDefaults(AI); + for (llvm::AArch64::ArchExtKind Ext : ExplicitEnables) + FeatureBits.enable(Ext); + for (llvm::AArch64::ArchExtKind Ext : ExplicitDisables) + FeatureBits.disable(Ext); + + return FeatureBits; +} + +// Synchronize the frontend's cached booleans and FPU mode bits from the +// expanded extension bitset, then reapply Clang-specific compatibility rules +// that are not represented directly in the extension graph +void AArch64TargetInfo::setFeatureStateFromEnabledExtensions( + const llvm::AArch64::ExtensionBitset &Exts) { + + EnabledExtensions = Exts; + const bool HasSVEAES = hasExtension(llvm::AArch64::AEK_SVEAES); + const bool HasSVEBitPerm = hasExtension(llvm::AArch64::AEK_SVEBITPERM); + + // clear the cached FPU mode bits (FPUMode, NeonMode, SveMode) + FPU &= ~(FPUMode | NeonMode | SveMode); + + // re-enable FPUMode if the fp extension is present + if (EnabledExtensions.test(llvm::AArch64::AEK_FP)) + FPU |= FPUMode; + + // re-enable SveMode if the sve extension is present + if (EnabledExtensions.test(llvm::AArch64::AEK_SVE)) + FPU |= SveMode; + + // Frontend FPU mode historically treats SVE as also enabling AdvSIMD, even + // though that dependency is not modeled as an architecture extension. + if (FPU & SveMode) + FPU |= NeonMode; + + // Keep the frontend's historical FPU compatibility for explicit feature + // strings such as +aes, +jscvt and +fullfp16 that are not pure ext-bit logic. + FPU |= ExplicitFPUCompat & (NeonMode | SveMode); + if (HasSVEAES || HasSVEBitPerm) + FPU |= NeonMode; +} + void AArch64TargetInfo::setFeatureEnabled(llvm::StringMap<bool> &Features, StringRef Name, bool Enabled) const { Features[Name] = Enabled; @@ -976,221 +1128,78 @@ void AArch64TargetInfo::setFeatureEnabled(llvm::StringMap<bool> &Features, } } +// Reconstruct enough of the AArch64 extension graph to answer implied-feature +// queries without over-expanding the generic frontend feature map. +bool AArch64TargetInfo::hasFeatureEnabled(const llvm::StringMap<bool> &Features, + StringRef Name) const { + auto QueryExt = lookupExtensionForFeatureName(Name); + if (!QueryExt) + return TargetInfo::hasFeatureEnabled(Features, Name); + + llvm::AArch64::ExtensionSet FeatureBits = + buildExtensionSetFromFeatureMap(Features); + return FeatureBits.Enabled.test(QueryExt->ID); +} + bool AArch64TargetInfo::handleTargetFeatures(std::vector<std::string> &Features, DiagnosticsEngine &Diags) { - for (const auto &Feature : Features) { + llvm::AArch64::ExtensionSet FeatureBits; + ExplicitFPUCompat = 0; + FeatureBits.enable(llvm::AArch64::AEK_FP); + + if (std::optional<llvm::AArch64::ArchInfo> BaseArch = + findExplicitBaseArchForTargetFeatures(Features)) { + FeatureBits.addArchDefaults(*BaseArch); + if (BaseArch->DefaultExts.test(llvm::AArch64::AEK_SIMD)) + ExplicitFPUCompat |= NeonMode; + if (BaseArch->DefaultExts.test(llvm::AArch64::AEK_SVE)) + ExplicitFPUCompat |= SveMode; + } + + std::vector<std::string> ExpandedFeatures; + ExpandedFeatures.reserve(Features.size()); + + for (const std::string &Feature : Features) { + if (enablesNeonFPUCompat(Feature)) + ExplicitFPUCompat |= NeonMode; + + if (auto ExtInfo = lookupExtensionForTargetFeature(Feature)) { + if (!Feature.empty() && Feature[0] == '+') + FeatureBits.enable(ExtInfo->ID); + else if (!Feature.empty() && Feature[0] == '-') { + switch (ExtInfo->ID) { + case llvm::AArch64::AEK_FP: + HasNoFP = true; + break; + case llvm::AArch64::AEK_SIMD: + HasNoNeon = true; + break; + case llvm::AArch64::AEK_SVE: + HasNoSVE = true; + break; + default: + break; + } + FeatureBits.disable(ExtInfo->ID); + } + continue; + } + ExpandedFeatures.push_back(Feature); + } + FeatureBits.toLLVMFeatureList(ExpandedFeatures); + llvm::sort(ExpandedFeatures); + + for (const auto &Feature : ExpandedFeatures) { if (Feature == "-fp-armv8") HasNoFP = true; if (Feature == "-neon") HasNoNeon = true; if (Feature == "-sve") HasNoSVE = true; - - if (Feature == "+neon" || Feature == "+fp-armv8") - FPU |= NeonMode; - if (Feature == "+jscvt") { - HasJSCVT = true; - FPU |= NeonMode; - } - if (Feature == "+fcma") { - HasFCMA = true; - FPU |= NeonMode; - } - - if (Feature == "+sve") { - FPU |= NeonMode; - FPU |= SveMode; - HasFullFP16 = true; - } - if (Feature == "+sve2") { - FPU |= NeonMode; - FPU |= SveMode; - HasFullFP16 = true; - HasSVE2 = true; - } - if (Feature == "+sve2p1") { - FPU |= NeonMode; - FPU |= SveMode; - HasFullFP16 = true; - HasSVE2 = true; - HasSVE2p1 = true; - } - if (Feature == "+sve-aes") { - FPU |= NeonMode; - HasFullFP16 = true; - HasSVEAES = true; - } - if (Feature == "+sve2-sha3") { - FPU |= NeonMode; - FPU |= SveMode; - HasFullFP16 = true; - HasSVE2 = true; - HasSVE2SHA3 = true; - } - if (Feature == "+sve2-sm4") { - FPU |= NeonMode; - FPU |= SveMode; - HasFullFP16 = true; - HasSVE2 = true; - HasSVE2SM4 = true; - } - if (Feature == "+sve-b16b16") - HasSVEB16B16 = true; - if (Feature == "+sve-bitperm") { - FPU |= NeonMode; - HasFullFP16 = true; - HasSVEBitPerm = true; - } - if (Feature == "+f32mm") { - FPU |= NeonMode; - FPU |= SveMode; - HasFullFP16 = true; - HasMatmulFP32 = true; - } - if (Feature == "+f64mm") { - FPU |= NeonMode; - FPU |= SveMode; - HasFullFP16 = true; - HasMatmulFP64 = true; - } - if (Feature == "+sme") { - HasSME = true; - HasBFloat16 = true; - HasFullFP16 = true; - } - if (Feature == "+sme2") { - HasSME = true; - HasSME2 = true; - HasBFloat16 = true; - HasFullFP16 = true; - } - if (Feature == "+sme2p1") { - HasSME = true; - HasSME2 = true; - HasSME2p1 = true; - HasBFloat16 = true; - HasFullFP16 = true; - } - if (Feature == "+sme-f64f64") { - HasSME = true; - HasSMEF64F64 = true; - HasBFloat16 = true; - HasFullFP16 = true; - } - if (Feature == "+sme-i16i64") { - HasSME = true; - HasSMEI16I64 = true; - HasBFloat16 = true; - HasFullFP16 = true; - } - if (Feature == "+sme-fa64") { - FPU |= NeonMode; - FPU |= SveMode; - HasSME = true; - HasSVE2 = true; - HasSMEFA64 = true; - } - if (Feature == "+sme-f16f16") { - HasSME = true; - HasSME2 = true; - HasBFloat16 = true; - HasFullFP16 = true; - HasSMEF16F16 = true; - } - if (Feature == "+sme-b16b16") { - HasSME = true; - HasSME2 = true; - HasBFloat16 = true; - HasFullFP16 = true; - HasSVEB16B16 = true; - HasSMEB16B16 = true; - } - - if (Feature == "+fp8") - HasFP8 = true; - if (Feature == "+fp8fma") - HasFP8FMA = true; - if (Feature == "+fp8dot2") - HasFP8DOT2 = true; - if (Feature == "+fp8dot4") - HasFP8DOT4 = true; - if (Feature == "+ssve-fp8dot2") - HasSSVE_FP8DOT2 = true; - if (Feature == "+ssve-fp8dot4") - HasSSVE_FP8DOT4 = true; - if (Feature == "+ssve-fp8fma") - HasSSVE_FP8FMA = true; - if (Feature == "+sme-f8f32") - HasSME_F8F32 = true; - if (Feature == "+sme-f8f16") - HasSME_F8F16 = true; - if (Feature == "+sb") - HasSB = true; - if (Feature == "+predres") - HasPredRes = true; - if (Feature == "+ssbs") - HasSSBS = true; - if (Feature == "+bti") - HasBTI = true; - if (Feature == "+wfxt") - HasWFxT = true; if (Feature == "-fmv") HasFMV = false; - if (Feature == "+crc") - HasCRC = true; - if (Feature == "+rcpc") - HasRCPC = true; - if (Feature == "+aes") { - FPU |= NeonMode; - HasAES = true; - } - if (Feature == "+sha2") { - FPU |= NeonMode; - HasSHA2 = true; - } - if (Feature == "+sha3") { - FPU |= NeonMode; - HasSHA2 = true; - HasSHA3 = true; - } - if (Feature == "+rdm") { - FPU |= NeonMode; - HasRDM = true; - } - if (Feature == "+dit") - HasDIT = true; - if (Feature == "+cccp") - HasCCPP = true; - if (Feature == "+ccdp") { - HasCCPP = true; - HasCCDP = true; - } - if (Feature == "+fptoint") - HasFRInt3264 = true; - if (Feature == "+sm4") { - FPU |= NeonMode; - HasSM4 = true; - } if (Feature == "+strict-align") HasUnalignedAccess = false; - if (Feature == "+fprcvt") - HasFPRCVT = true; - if (Feature == "+f8f16mm") - HasF8F16MM = true; - if (Feature == "+f8f32mm") - HasF8F32MM = true; - if (Feature == "+sve-f16f32mm") - HasSVE_F16F32MM = true; - if (Feature == "+sve-bfscale") - HasSVE_BFSCALE = true; - if (Feature == "+sve-aes2") - HasSVE_AES2 = true; - if (Feature == "+ssve-aes") - HasSSVE_AES = true; - if (Feature == "+sve2p2") - HasSVE2p2 = true; - if (Feature == "+sme2p2") - HasSME2p2 = true; // All predecessor archs are added but select the latest one for ArchKind. if (Feature == "+v8a" && ArchInfo->Version < llvm::AArch64::ARMV8A.Version) @@ -1247,62 +1256,9 @@ bool AArch64TargetInfo::handleTargetFeatures(std::vector<std::string> &Features, ArchInfo = &llvm::AArch64::ARMV9_7A; if (Feature == "+v8r") ArchInfo = &llvm::AArch64::ARMV8R; - if (Feature == "+fullfp16") { - FPU |= NeonMode; - HasFullFP16 = true; - } - if (Feature == "+dotprod") { - FPU |= NeonMode; - HasDotProd = true; - } - if (Feature == "+fp16fml") { - FPU |= NeonMode; - HasFullFP16 = true; - HasFP16FML = true; - } - if (Feature == "+mte") - HasMTE = true; - if (Feature == "+pauth") - HasPAuth = true; - if (Feature == "+i8mm") - HasMatMul = true; - if (Feature == "+bf16") - HasBFloat16 = true; - if (Feature == "+lse") - HasLSE = true; - if (Feature == "+ls64") - HasLS64 = true; - if (Feature == "+rand") - HasRandGen = true; - if (Feature == "+flagm") - HasFlagM = true; - if (Feature == "+altnzcv") { - HasFlagM = true; - HasAlternativeNZCV = true; - } - if (Feature == "+mops") - HasMOPS = true; - if (Feature == "+d128") - HasD128 = true; - if (Feature == "+gcs") - HasGCS = true; - if (Feature == "+rcpc3") - HasRCPC3 = true; - if (Feature == "+pauth-lr") { - HasPAuthLR = true; - HasPAuth = true; - } - if (Feature == "+cssc") - HasCSSC = true; } - // Check features that are manually disabled by command line options. - // This needs to be checked after architecture-related features are handled, - // making sure they are properly disabled when required. - for (const auto &Feature : Features) { - if (Feature == "-d128") - HasD128 = false; - } + setFeatureStateFromEnabledExtensions(FeatureBits.Enabled); resetDataLayout(); @@ -1678,6 +1634,7 @@ bool AArch64TargetInfo::validateConstraintModifier( return true; case 'z': case 'r': { + const bool HasLS64 = hasExtension(llvm::AArch64::AEK_LS64); switch (Modifier) { case 'x': case 'w': diff --git a/clang/lib/Basic/Targets/AArch64.h b/clang/lib/Basic/Targets/AArch64.h index 0a29bad81939b..b0c1fcedbc183 100644 --- a/clang/lib/Basic/Targets/AArch64.h +++ b/clang/lib/Basic/Targets/AArch64.h @@ -69,87 +69,23 @@ class LLVM_LIBRARY_VISIBILITY AArch64TargetInfo : public TargetInfo { }; unsigned FPU = FPUMode; - bool HasCRC = false; - bool HasCSSC = false; - bool HasAES = false; - bool HasSHA2 = false; - bool HasSHA3 = false; - bool HasSM4 = false; - bool HasFullFP16 = false; - bool HasDotProd = false; - bool HasFP16FML = false; - bool HasMTE = false; - bool HasPAuth = false; - bool HasLS64 = false; - bool HasRandGen = false; - bool HasMatMul = false; - bool HasBFloat16 = false; - bool HasSVE2 = false; - bool HasSVE2p1 = false; - bool HasSVEAES = false; - bool HasSVE2SHA3 = false; - bool HasSVE2SM4 = false; - bool HasSVEB16B16 = false; - bool HasSVEBitPerm = false; - bool HasMatmulFP64 = false; - bool HasMatmulFP32 = false; - bool HasLSE = false; - bool HasFlagM = false; - bool HasAlternativeNZCV = false; - bool HasMOPS = false; - bool HasD128 = false; - bool HasRCPC = false; - bool HasRDM = false; - bool HasDIT = false; - bool HasCCPP = false; - bool HasCCDP = false; - bool HasFRInt3264 = false; - bool HasSME = false; - bool HasSME2 = false; - bool HasSMEF64F64 = false; - bool HasSMEI16I64 = false; - bool HasSMEF16F16 = false; - bool HasSMEB16B16 = false; - bool HasSME2p1 = false; - bool HasFP8 = false; - bool HasFP8FMA = false; - bool HasFP8DOT2 = false; - bool HasFP8DOT4 = false; - bool HasSSVE_FP8DOT2 = false; - bool HasSSVE_FP8DOT4 = false; - bool HasSSVE_FP8FMA = false; - bool HasSME_F8F32 = false; - bool HasSME_F8F16 = false; - bool HasSB = false; - bool HasPredRes = false; - bool HasSSBS = false; - bool HasBTI = false; - bool HasWFxT = false; - bool HasJSCVT = false; - bool HasFCMA = false; + llvm::AArch64::ExtensionBitset EnabledExtensions; + unsigned ExplicitFPUCompat = 0; bool HasNoFP = false; bool HasNoNeon = false; bool HasNoSVE = false; bool HasFMV = true; - bool HasGCS = false; - bool HasRCPC3 = false; - bool HasSMEFA64 = false; - bool HasPAuthLR = false; - bool HasFPRCVT = false; - bool HasF8F16MM = false; - bool HasF8F32MM = false; - bool HasSVE_F16F32MM = false; - bool HasSVE_BFSCALE = false; - bool HasSVE_AES2 = false; - bool HasSSVE_AES = false; - bool HasSVE2p2 = false; - bool HasSME2p2 = false; const llvm::AArch64::ArchInfo *ArchInfo = &llvm::AArch64::ARMV8A; AArch64FeatureSet HasFeatureLookup; void computeFeatureLookup(); + bool hasExtension(llvm::AArch64::ArchExtKind Ext) const; + bool hasPAuth() const; + bool hasFullFP16() const; + void setFeatureStateFromEnabledExtensions( + const llvm::AArch64::ExtensionBitset &EnabledExtensions); protected: std::string ABI; @@ -159,6 +95,8 @@ class LLVM_LIBRARY_VISIBILITY AArch64TargetInfo : public TargetInfo { StringRef getABI() const override; bool setABI(const std::string &Name) override; + bool hasFeatureEnabled(const llvm::StringMap<bool> &Features, + StringRef Name) const override; bool validateBranchProtection(StringRef Spec, StringRef Arch, BranchProtectionInfo &BPI, diff --git a/clang/lib/Basic/Targets/AArch64TargetInfoFeatures.inc b/clang/lib/Basic/Targets/AArch64TargetInfoFeatures.inc new file mode 100644 index 0000000000000..018866eafb6ef --- /dev/null +++ b/clang/lib/Basic/Targets/AArch64TargetInfoFeatures.inc @@ -0,0 +1,69 @@ +AARCH64_EXTENSION_FEATURE(HasJSCVT, JSCVT) +AARCH64_EXTENSION_FEATURE(HasFCMA, FCMA) +AARCH64_EXTENSION_FEATURE(HasRandGen, RAND) +AARCH64_EXTENSION_FEATURE(HasFlagM, FLAGM) +AARCH64_EXTENSION_FEATURE(HasAlternativeNZCV, ALTERNATIVENZCV) +AARCH64_EXTENSION_FEATURE(HasFP16FML, FP16FML) +AARCH64_EXTENSION_FEATURE(HasDotProd, DOTPROD) +AARCH64_EXTENSION_FEATURE(HasSM4, SM4) +AARCH64_EXTENSION_FEATURE(HasRDM, RDM) +AARCH64_EXTENSION_FEATURE(HasLSE, LSE) +AARCH64_EXTENSION_FEATURE(HasCRC, CRC) +AARCH64_EXTENSION_FEATURE(HasCSSC, CSSC) +AARCH64_EXTENSION_FEATURE(HasSHA2, SHA2) +AARCH64_EXTENSION_FEATURE(HasSHA3, SHA3) +AARCH64_EXTENSION_FEATURE(HasAES, AES) +AARCH64_EXTENSION_FEATURE(HasDIT, DIT) +AARCH64_EXTENSION_FEATURE(HasCCPP, CCPP) +AARCH64_EXTENSION_FEATURE(HasCCDP, CCDP) +AARCH64_EXTENSION_FEATURE(HasRCPC, RCPC) +AARCH64_EXTENSION_FEATURE(HasFRInt3264, FRINT3264) +AARCH64_EXTENSION_FEATURE(HasI8MM, I8MM) +AARCH64_EXTENSION_FEATURE(HasBFloat16, BF16) +AARCH64_EXTENSION_FEATURE(HasSVEB16B16, SVEB16B16) +AARCH64_EXTENSION_FEATURE(HasF32MM, F32MM) +AARCH64_EXTENSION_FEATURE(HasF64MM, F64MM) +AARCH64_EXTENSION_FEATURE(HasSVE2, SVE2) +AARCH64_EXTENSION_FEATURE(HasSVEAES, SVEAES) +AARCH64_EXTENSION_FEATURE(HasSVEBitPerm, SVEBITPERM) +AARCH64_EXTENSION_FEATURE(HasSVE2SHA3, SVE2SHA3) +AARCH64_EXTENSION_FEATURE(HasSVE2SM4, SVE2SM4) +AARCH64_EXTENSION_FEATURE(HasSVE2p1, SVE2P1) +AARCH64_EXTENSION_FEATURE(HasSME, SME) +AARCH64_EXTENSION_FEATURE(HasSME2, SME2) +AARCH64_EXTENSION_FEATURE(HasSME2p1, SME2P1) +AARCH64_EXTENSION_FEATURE(HasSMEF64F64, SMEF64F64) +AARCH64_EXTENSION_FEATURE(HasSMEI16I64, SMEI16I64) +AARCH64_EXTENSION_FEATURE(HasSMEFA64, SMEFA64) +AARCH64_EXTENSION_FEATURE(HasSMEF16F16, SMEF16F16) +AARCH64_EXTENSION_FEATURE(HasSMEB16B16, SMEB16B16) +AARCH64_EXTENSION_FEATURE(HasMTE, MTE) +AARCH64_EXTENSION_FEATURE(HasSB, SB) +AARCH64_EXTENSION_FEATURE(HasPredRes, PREDRES) +AARCH64_EXTENSION_FEATURE(HasSSBS, SSBS) +AARCH64_EXTENSION_FEATURE(HasBTI, BTI) +AARCH64_EXTENSION_FEATURE(HasLS64, LS64) +AARCH64_EXTENSION_FEATURE(HasWFxT, WFXT) +AARCH64_EXTENSION_FEATURE(HasRCPC3, RCPC3) +AARCH64_EXTENSION_FEATURE(HasFP8, FP8) +AARCH64_EXTENSION_FEATURE(HasFP8FMA, FP8FMA) +AARCH64_EXTENSION_FEATURE(HasFP8DOT2, FP8DOT2) +AARCH64_EXTENSION_FEATURE(HasFP8DOT4, FP8DOT4) +AARCH64_EXTENSION_FEATURE(HasSSVE_FP8DOT2, SSVE_FP8DOT2) +AARCH64_EXTENSION_FEATURE(HasSSVE_FP8DOT4, SSVE_FP8DOT4) +AARCH64_EXTENSION_FEATURE(HasSSVE_FP8FMA, SSVE_FP8FMA) +AARCH64_EXTENSION_FEATURE(HasSME_F8F32, SMEF8F32) +AARCH64_EXTENSION_FEATURE(HasSME_F8F16, SMEF8F16) +AARCH64_EXTENSION_FEATURE(HasFPRCVT, FPRCVT) +AARCH64_EXTENSION_FEATURE(HasF8F16MM, F8F16MM) +AARCH64_EXTENSION_FEATURE(HasF8F32MM, F8F32MM) +AARCH64_EXTENSION_FEATURE(HasSVE_F16F32MM, SVE_F16F32MM) +AARCH64_EXTENSION_FEATURE(HasSVE_BFSCALE, SVE_BFSCALE) +AARCH64_EXTENSION_FEATURE(HasSVE_AES2, SVE_AES2) +AARCH64_EXTENSION_FEATURE(HasSSVE_AES, SSVE_AES) +AARCH64_EXTENSION_FEATURE(HasSVE2p2, SVE2P2) +AARCH64_EXTENSION_FEATURE(HasSME2p2, SME2P2) +AARCH64_EXTENSION_FEATURE(HasPAuthLR, PAUTHLR) +AARCH64_EXTENSION_FEATURE(HasMOPS, MOPS) +AARCH64_EXTENSION_FEATURE(HasD128, D128) +AARCH64_EXTENSION_FEATURE(HasGCS, GCS) diff --git a/clang/lib/Sema/SemaARM.cpp b/clang/lib/Sema/SemaARM.cpp index e54c8228e5ff8..be07d2e81aa50 100644 --- a/clang/lib/Sema/SemaARM.cpp +++ b/clang/lib/Sema/SemaARM.cpp @@ -1571,7 +1571,7 @@ void SemaARM::CheckSMEFunctionDefAttributes(const FunctionDecl *FD) { if (UsesSM || UsesZA) { llvm::StringMap<bool> FeatureMap; Context.getFunctionFeatureMap(FeatureMap, FD); - if (!FeatureMap.contains("sme")) { + if (!Context.getTargetInfo().hasFeatureEnabled(FeatureMap, "sme")) { if (UsesSM) Diag(FD->getLocation(), diag::err_sme_definition_using_sm_in_non_sme_target); @@ -1583,7 +1583,7 @@ void SemaARM::CheckSMEFunctionDefAttributes(const FunctionDecl *FD) { if (UsesZT0) { llvm::StringMap<bool> FeatureMap; Context.getFunctionFeatureMap(FeatureMap, FD); - if (!FeatureMap.contains("sme2")) { + if (!Context.getTargetInfo().hasFeatureEnabled(FeatureMap, "sme2")) { Diag(FD->getLocation(), diag::err_sme_definition_using_zt0_in_non_sme2_target); } @@ -1862,7 +1862,7 @@ bool SemaARM::checkSVETypeSupport(QualType Ty, SourceLocation Loc, return false; // No SVE environment available. - if (!FeatureMap.lookup("sme")) + if (!getASTContext().getTargetInfo().hasFeatureEnabled(FeatureMap, "sme")) return Diag(Loc, diag::err_sve_vector_in_non_sve_target) << Ty; // SVE environment only available to streaming functions. diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index d53c3b6ab2674..12cabce5c4385 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -4265,7 +4265,7 @@ void Sema::checkCall(NamedDecl *FDecl, const FunctionProtoType *Proto, if (auto *CallerFD = dyn_cast<FunctionDecl>(CurContext)) { llvm::StringMap<bool> CallerFeatureMap; Context.getFunctionFeatureMap(CallerFeatureMap, CallerFD); - if (!CallerFeatureMap.contains("sme")) + if (!Context.getTargetInfo().hasFeatureEnabled(CallerFeatureMap, "sme")) Diag(Loc, diag::err_sme_call_in_non_sme_target); } else if (!Context.getTargetInfo().hasFeature("sme")) { Diag(Loc, diag::err_sme_call_in_non_sme_target); diff --git a/clang/test/Preprocessor/aarch64-target-features.c b/clang/test/Preprocessor/aarch64-target-features.c index 60ddaad639d48..41393e423f17f 100644 --- a/clang/test/Preprocessor/aarch64-target-features.c +++ b/clang/test/Preprocessor/aarch64-target-features.c @@ -235,6 +235,7 @@ // RUN: %clang -target aarch64-none-linux-gnu -march=armv8-a+sve2-aes -x c -E -dM %s -o - | FileCheck --check-prefix=CHECK-SVE2AES %s // RUN: %clang -target aarch64-none-linux-gnu -march=armv8-a+sve-aes+sve2 -x c -E -dM %s -o - | FileCheck --check-prefix=CHECK-SVE2AES %s +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve2-aes -x c -E -dM %s -o - | FileCheck --check-prefix=CHECK-SVE2AES %s // CHECK-SVE2AES: __ARM_FEATURE_AES 1 // CHECK-SVE2AES: __ARM_FEATURE_SVE2 1 // CHECK-SVE2AES: __ARM_FEATURE_SVE2_AES 1 @@ -253,10 +254,12 @@ // RUN: %clang -target aarch64-none-linux-gnu -march=armv8-a+sve2-bitperm -x c -E -dM %s -o - | FileCheck --check-prefix=CHECK-SVE2BITPERM %s // RUN: %clang -target aarch64-none-linux-gnu -march=armv8-a+sve-bitperm+sve2 -x c -E -dM %s -o - | FileCheck --check-prefix=CHECK-SVE2BITPERM %s +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve2-bitperm -x c -E -dM %s -o - | FileCheck --check-prefix=CHECK-SVE2BITPERM %s // CHECK-SVE2BITPERM: __ARM_FEATURE_SVE2 1 // CHECK-SVE2BITPERM: __ARM_FEATURE_SVE2_BITPERM 1 // RUN: %clang -target aarch64-none-linux-gnu -march=armv9-a+sve2p1 -x c -E -dM %s -o - | FileCheck --check-prefix=CHECK-SVE2p1 %s +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve2p1 -x c -E -dM %s -o - | FileCheck --check-prefix=CHECK-SVE2p1 %s // CHECK-SVE2p1: __ARM_FEATURE_FP16_SCALAR_ARITHMETIC 1 // CHECK-SVE2p1: __ARM_FEATURE_FP16_VECTOR_ARITHMETIC 1 // CHECK-SVE2p1: __ARM_FEATURE_SVE2 1 @@ -271,6 +274,16 @@ // CHECK-DOTPROD: __ARM_NEON 1 // CHECK-DOTPROD: __ARM_NEON_FP 0xE +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +jscvt -x c -E -dM %s -o - | FileCheck --check-prefix=CHECK-JSCVT-DIRECT %s +// CHECK-JSCVT-DIRECT: #define __ARM_NEON 1 +// CHECK-JSCVT-DIRECT: #define __ARM_NEON_FP 0xE + +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sme -x c -E -dM %s -o - | FileCheck --check-prefix=CHECK-SME-DIRECT %s +// CHECK-SME-DIRECT-NOT: #define __ARM_NEON 1 +// CHECK-SME-DIRECT-NOT: #define __ARM_NEON_FP 0xE +// CHECK-SME-DIRECT: #define __ARM_FEATURE_LOCALLY_STREAMING 1 +// CHECK-SME-DIRECT: #define __ARM_FEATURE_SME + // On ARMv8.2-A and above, +fp16fml implies +fp16. // On ARMv8.4-A and above, +fp16 implies +fp16fml. // RUN: %clang --target=aarch64 -march=armv8.2-a+nofp16fml+fp16 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-FULLFP16-NOFML --check-prefix=CHECK-FULLFP16-VECTOR-SCALAR %s @@ -283,12 +296,18 @@ // RUN: %clang --target=aarch64 -march=armv8.4-a+fp16+nofp16fml -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-FULLFP16-NOFML --check-prefix=CHECK-FULLFP16-VECTOR-SCALAR %s // RUN: %clang --target=aarch64 -march=armv8.4-a+fp16fml -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-FULLFP16-FML --check-prefix=CHECK-FULLFP16-VECTOR-SCALAR %s // RUN: %clang --target=aarch64 -march=armv8.4-a+fp16 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-FULLFP16-FML --check-prefix=CHECK-FULLFP16-VECTOR-SCALAR %s +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +fullfp16 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-FULLFP16-DIRECT %s // CHECK-FULLFP16-FML: #define __ARM_FEATURE_FP16_FML 1 // CHECK-FULLFP16-NOFML-NOT: #define __ARM_FEATURE_FP16_FML 1 // CHECK-FULLFP16-VECTOR-SCALAR: #define __ARM_FEATURE_FP16_SCALAR_ARITHMETIC 1 // CHECK-FULLFP16-VECTOR-SCALAR: #define __ARM_FEATURE_FP16_VECTOR_ARITHMETIC 1 // CHECK-FULLFP16-VECTOR-SCALAR: #define __ARM_FP 0xE // CHECK-FULLFP16-VECTOR-SCALAR: #define __ARM_FP16_FORMAT_IEEE 1 +// CHECK-FULLFP16-DIRECT: #define __ARM_FEATURE_FP16_SCALAR_ARITHMETIC 1 +// CHECK-FULLFP16-DIRECT: #define __ARM_FEATURE_FP16_VECTOR_ARITHMETIC 1 +// CHECK-FULLFP16-DIRECT: #define __ARM_FP 0xE +// CHECK-FULLFP16-DIRECT: #define __ARM_FP16_FORMAT_IEEE 1 +// CHECK-FULLFP16-DIRECT: #define __ARM_NEON 1 // +fp16fml+nosimd doesn't make sense as the fp16fml instructions all require SIMD. // However, as +fp16fml implies +fp16 there is a set of defines that we would expect. @@ -736,12 +755,14 @@ // CHECK-SVEB16B16: __ARM_FEATURE_SVE_B16B16 1 // RUN: %clang --target=aarch64 -march=armv9-a+sme-f16f16 -x c -E -dM %s -o - | FileCheck --check-prefix=CHECK-SMEF16F16 %s +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sme-f16f16 -x c -E -dM %s -o - | FileCheck --check-prefix=CHECK-SMEF16F16 %s // CHECK-SMEF16F16: __ARM_FEATURE_LOCALLY_STREAMING 1 // CHECK-SMEF16F16: __ARM_FEATURE_SME 1 // CHECK-SMEF16F16: __ARM_FEATURE_SME2 1 // CHECK-SMEF16F16: __ARM_FEATURE_SME_F16F16 1 // RUN: %clang --target=aarch64 -march=armv9-a+sme-b16b16 -x c -E -dM %s -o - | FileCheck --check-prefix=CHECK-SMEB16B16 %s +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sme-b16b16 -x c -E -dM %s -o - | FileCheck --check-prefix=CHECK-SMEB16B16 %s // CHECK-SMEB16B16: __ARM_FEATURE_LOCALLY_STREAMING 1 // CHECK-SMEB16B16: __ARM_FEATURE_SME 1 // CHECK-SMEB16B16: __ARM_FEATURE_SME2 1 @@ -818,6 +839,7 @@ // CHECK-SSVE-AES: __ARM_FEATURE_SVE2_AES 1 // RUN: %clang -target aarch64-none-linux-gnu -march=armv9-a+sve2p2 -x c -E -dM %s -o - | FileCheck --check-prefix=CHECK-SVE2p2 %s +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve2p2 -x c -E -dM %s -o - | FileCheck --check-prefix=CHECK-SVE2p2 %s // CHECK-SVE2p2: __ARM_FEATURE_FP16_SCALAR_ARITHMETIC 1 // CHECK-SVE2p2: __ARM_FEATURE_FP16_VECTOR_ARITHMETIC 1 // CHECK-SVE2p2: __ARM_FEATURE_SVE2 1 diff --git a/clang/test/Sema/aarch64-sme-func-attrs-without-target-feature.cpp b/clang/test/Sema/aarch64-sme-func-attrs-without-target-feature.cpp index 2ba266a93f94f..821c0082a3458 100644 --- a/clang/test/Sema/aarch64-sme-func-attrs-without-target-feature.cpp +++ b/clang/test/Sema/aarch64-sme-func-attrs-without-target-feature.cpp @@ -21,6 +21,11 @@ __arm_locally_streaming __attribute__((target("sme"))) void locally_streaming_de // Test that it also works with the target("sme2") attribute. __attribute__((target("sme2"))) void streaming_def_sme2_attr() __arm_streaming { } // OK +// Explicit target disables must win over arch/default SME implications. +__attribute__((target("arch=armv9.3-a,no-sme"))) void streaming_def_arch_no_sme() __arm_streaming { } // expected-error {{function executed in streaming-SVE mode requires 'sme'}} +__attribute__((target("sme2,no-sme"))) void streaming_def_sme2_no_sme() __arm_streaming { } // expected-error {{function executed in streaming-SVE mode requires 'sme'}} +__attribute__((target("sme2,no-sme"))) void inout_zt0_def_sme2_no_sme() __arm_inout("zt0") { } // expected-error {{function using ZT0 state requires 'sme2'}} + // No code is generated for declarations, so it should be fine to declare using the attribute. void streaming_compatible_decl() __arm_streaming_compatible; // OK void streaming_decl() __arm_streaming; // OK >From 82fa0a0cce4a4d53f556239f5bbb70ed55f6dd32 Mon Sep 17 00:00:00 2001 From: Jonathan Thackray <[email protected]> Date: Wed, 8 Apr 2026 15:25:27 +0100 Subject: [PATCH 2/2] fixup! Don't checkin AArch64TargetInfoFeatures.inc but generate from tablegen --- clang/lib/Basic/Targets/AArch64.cpp | 24 ++++--- .../Targets/AArch64TargetInfoFeatures.inc | 69 ------------------- .../TableGen/Basic/ARMTargetDefEmitter.cpp | 23 +++++++ 3 files changed, 39 insertions(+), 77 deletions(-) delete mode 100644 clang/lib/Basic/Targets/AArch64TargetInfoFeatures.inc diff --git a/clang/lib/Basic/Targets/AArch64.cpp b/clang/lib/Basic/Targets/AArch64.cpp index 399d9ed5ae052..0bb7b489e1d00 100644 --- a/clang/lib/Basic/Targets/AArch64.cpp +++ b/clang/lib/Basic/Targets/AArch64.cpp @@ -42,6 +42,20 @@ static_assert(NumBuiltins == (NumNeonBuiltins + NumFp16Builtins + NumSVEBuiltins + NumSVENeonBridgeBuiltins + NumSMEBuiltins + NumAArch64Builtins)); +#define AARCH64_HAS_EXT(ArchExtKind) hasExtension(llvm::AArch64::ArchExtKind) +#define EMIT_EXTENSION_FEATURE_LOCAL_DECLS +#include "llvm/TargetParser/AArch64TargetParserDef.inc" +#define DECLARE_AARCH64_EXTENSION_FEATURE_LOCALS() \ + AARCH64_DECLARE_EXTENSION_FEATURE_LOCALS(AARCH64_HAS_EXT) \ + [[maybe_unused]] const bool HasFCMA = HasComplxNum; \ + [[maybe_unused]] const bool HasJSCVT = HasJS; \ + [[maybe_unused]] const bool HasBFloat16 = HasBF16; \ + [[maybe_unused]] const bool HasI8MM = HasMatMulInt8; \ + [[maybe_unused]] const bool HasF32MM = HasMatMulFP32; \ + [[maybe_unused]] const bool HasF64MM = HasMatMulFP64; \ + [[maybe_unused]] const bool HasSME_F8F32 = HasSMEF8F32; \ + [[maybe_unused]] const bool HasSME_F8F16 = HasSMEF8F16; + namespace clang { namespace AArch64 { #define GET_BUILTIN_STR_TABLE @@ -497,10 +511,7 @@ void AArch64TargetInfo::getTargetDefines(const LangOptions &Opts, const bool HasSVE = FPU & SveMode; const bool HasNeon = FPU & NeonMode; -#define AARCH64_EXTENSION_FEATURE(Name, Ext) \ - [[maybe_unused]] const bool Name = hasExtension(llvm::AArch64::AEK_##Ext); -#include "AArch64TargetInfoFeatures.inc" -#undef AARCH64_EXTENSION_FEATURE + DECLARE_AARCH64_EXTENSION_FEATURE_LOCALS() if (HasSVE2) Builder.defineMacro("__ARM_FEATURE_SVE2", "1"); @@ -880,10 +891,7 @@ void AArch64TargetInfo::computeFeatureLookup() { const bool HasFP = FPU & FPUMode; const bool HasNeon = FPU & NeonMode; const bool HasSVE = FPU & SveMode; -#define AARCH64_EXTENSION_FEATURE(Name, Ext) \ - [[maybe_unused]] const bool Name = hasExtension(llvm::AArch64::AEK_##Ext); -#include "AArch64TargetInfoFeatures.inc" -#undef AARCH64_EXTENSION_FEATURE + DECLARE_AARCH64_EXTENSION_FEATURE_LOCALS() FeatureLookupBuilder(HasFeatureLookup) .Cases({"aarch64", "arm64", "arm"}, true) diff --git a/clang/lib/Basic/Targets/AArch64TargetInfoFeatures.inc b/clang/lib/Basic/Targets/AArch64TargetInfoFeatures.inc deleted file mode 100644 index 018866eafb6ef..0000000000000 --- a/clang/lib/Basic/Targets/AArch64TargetInfoFeatures.inc +++ /dev/null @@ -1,69 +0,0 @@ -AARCH64_EXTENSION_FEATURE(HasJSCVT, JSCVT) -AARCH64_EXTENSION_FEATURE(HasFCMA, FCMA) -AARCH64_EXTENSION_FEATURE(HasRandGen, RAND) -AARCH64_EXTENSION_FEATURE(HasFlagM, FLAGM) -AARCH64_EXTENSION_FEATURE(HasAlternativeNZCV, ALTERNATIVENZCV) -AARCH64_EXTENSION_FEATURE(HasFP16FML, FP16FML) -AARCH64_EXTENSION_FEATURE(HasDotProd, DOTPROD) -AARCH64_EXTENSION_FEATURE(HasSM4, SM4) -AARCH64_EXTENSION_FEATURE(HasRDM, RDM) -AARCH64_EXTENSION_FEATURE(HasLSE, LSE) -AARCH64_EXTENSION_FEATURE(HasCRC, CRC) -AARCH64_EXTENSION_FEATURE(HasCSSC, CSSC) -AARCH64_EXTENSION_FEATURE(HasSHA2, SHA2) -AARCH64_EXTENSION_FEATURE(HasSHA3, SHA3) -AARCH64_EXTENSION_FEATURE(HasAES, AES) -AARCH64_EXTENSION_FEATURE(HasDIT, DIT) -AARCH64_EXTENSION_FEATURE(HasCCPP, CCPP) -AARCH64_EXTENSION_FEATURE(HasCCDP, CCDP) -AARCH64_EXTENSION_FEATURE(HasRCPC, RCPC) -AARCH64_EXTENSION_FEATURE(HasFRInt3264, FRINT3264) -AARCH64_EXTENSION_FEATURE(HasI8MM, I8MM) -AARCH64_EXTENSION_FEATURE(HasBFloat16, BF16) -AARCH64_EXTENSION_FEATURE(HasSVEB16B16, SVEB16B16) -AARCH64_EXTENSION_FEATURE(HasF32MM, F32MM) -AARCH64_EXTENSION_FEATURE(HasF64MM, F64MM) -AARCH64_EXTENSION_FEATURE(HasSVE2, SVE2) -AARCH64_EXTENSION_FEATURE(HasSVEAES, SVEAES) -AARCH64_EXTENSION_FEATURE(HasSVEBitPerm, SVEBITPERM) -AARCH64_EXTENSION_FEATURE(HasSVE2SHA3, SVE2SHA3) -AARCH64_EXTENSION_FEATURE(HasSVE2SM4, SVE2SM4) -AARCH64_EXTENSION_FEATURE(HasSVE2p1, SVE2P1) -AARCH64_EXTENSION_FEATURE(HasSME, SME) -AARCH64_EXTENSION_FEATURE(HasSME2, SME2) -AARCH64_EXTENSION_FEATURE(HasSME2p1, SME2P1) -AARCH64_EXTENSION_FEATURE(HasSMEF64F64, SMEF64F64) -AARCH64_EXTENSION_FEATURE(HasSMEI16I64, SMEI16I64) -AARCH64_EXTENSION_FEATURE(HasSMEFA64, SMEFA64) -AARCH64_EXTENSION_FEATURE(HasSMEF16F16, SMEF16F16) -AARCH64_EXTENSION_FEATURE(HasSMEB16B16, SMEB16B16) -AARCH64_EXTENSION_FEATURE(HasMTE, MTE) -AARCH64_EXTENSION_FEATURE(HasSB, SB) -AARCH64_EXTENSION_FEATURE(HasPredRes, PREDRES) -AARCH64_EXTENSION_FEATURE(HasSSBS, SSBS) -AARCH64_EXTENSION_FEATURE(HasBTI, BTI) -AARCH64_EXTENSION_FEATURE(HasLS64, LS64) -AARCH64_EXTENSION_FEATURE(HasWFxT, WFXT) -AARCH64_EXTENSION_FEATURE(HasRCPC3, RCPC3) -AARCH64_EXTENSION_FEATURE(HasFP8, FP8) -AARCH64_EXTENSION_FEATURE(HasFP8FMA, FP8FMA) -AARCH64_EXTENSION_FEATURE(HasFP8DOT2, FP8DOT2) -AARCH64_EXTENSION_FEATURE(HasFP8DOT4, FP8DOT4) -AARCH64_EXTENSION_FEATURE(HasSSVE_FP8DOT2, SSVE_FP8DOT2) -AARCH64_EXTENSION_FEATURE(HasSSVE_FP8DOT4, SSVE_FP8DOT4) -AARCH64_EXTENSION_FEATURE(HasSSVE_FP8FMA, SSVE_FP8FMA) -AARCH64_EXTENSION_FEATURE(HasSME_F8F32, SMEF8F32) -AARCH64_EXTENSION_FEATURE(HasSME_F8F16, SMEF8F16) -AARCH64_EXTENSION_FEATURE(HasFPRCVT, FPRCVT) -AARCH64_EXTENSION_FEATURE(HasF8F16MM, F8F16MM) -AARCH64_EXTENSION_FEATURE(HasF8F32MM, F8F32MM) -AARCH64_EXTENSION_FEATURE(HasSVE_F16F32MM, SVE_F16F32MM) -AARCH64_EXTENSION_FEATURE(HasSVE_BFSCALE, SVE_BFSCALE) -AARCH64_EXTENSION_FEATURE(HasSVE_AES2, SVE_AES2) -AARCH64_EXTENSION_FEATURE(HasSSVE_AES, SSVE_AES) -AARCH64_EXTENSION_FEATURE(HasSVE2p2, SVE2P2) -AARCH64_EXTENSION_FEATURE(HasSME2p2, SME2P2) -AARCH64_EXTENSION_FEATURE(HasPAuthLR, PAUTHLR) -AARCH64_EXTENSION_FEATURE(HasMOPS, MOPS) -AARCH64_EXTENSION_FEATURE(HasD128, D128) -AARCH64_EXTENSION_FEATURE(HasGCS, GCS) diff --git a/llvm/utils/TableGen/Basic/ARMTargetDefEmitter.cpp b/llvm/utils/TableGen/Basic/ARMTargetDefEmitter.cpp index a18fed082207f..4d62215d3d395 100644 --- a/llvm/utils/TableGen/Basic/ARMTargetDefEmitter.cpp +++ b/llvm/utils/TableGen/Basic/ARMTargetDefEmitter.cpp @@ -150,6 +150,29 @@ static void emitARMTargetDef(const RecordKeeper &RK, raw_ostream &OS) { << "#endif // EMIT_EXTENSIONS\n" << "\n"; + // Emit a macro that expands to local bool declarations for each extension, + // parameterized by a caller-provided extension test helper. + OS << "#ifdef EMIT_EXTENSION_FEATURE_LOCAL_DECLS\n" + << "#ifndef AARCH64_DECLARE_EXTENSION_FEATURE_LOCALS\n" + << "#define AARCH64_DECLARE_EXTENSION_FEATURE_LOCALS(TEST_EXT) \\\n"; + for (size_t I = 0; I < SortedExtensions.size(); ++I) { + const Record *Rec = SortedExtensions[I]; + std::string FieldName(Rec->getValueAsString("FieldName")); + if (FieldName == "HasSVE") + FieldName = "HasSVEExt"; + auto AEK = Rec->getValueAsString("ArchExtKindSpelling").upper(); + OS << " [[maybe_unused]] const bool " << FieldName << " = TEST_EXT(" << AEK + << ");"; + if (I + 1 != SortedExtensions.size()) + OS << " \\\n"; + else + OS << "\n"; + } + OS << "#endif\n" + << "#undef EMIT_EXTENSION_FEATURE_LOCAL_DECLS\n" + << "#endif // EMIT_EXTENSION_FEATURE_LOCAL_DECLS\n" + << "\n"; + // Emit FMV information auto FMVExts = RK.getAllDerivedDefinitionsIfDefined("FMVExtension"); OS << "#ifdef EMIT_FMV_INFO\n" _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
