diff options
author | Alexandros Lamprineas <alexandros.lamprineas@arm.com> | 2024-06-18 21:28:34 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-06-18 21:28:34 +0100 |
commit | a03d06a736fd8921c8f40637667d6af9c2c76505 (patch) | |
tree | 51a0269731c16998c37e99c06aa4c34c55c25899 | |
parent | e5f16393429bd73ea7d8a73cdc19408114c9e944 (diff) | |
download | llvm-a03d06a736fd8921c8f40637667d6af9c2c76505.zip llvm-a03d06a736fd8921c8f40637667d6af9c2c76505.tar.gz llvm-a03d06a736fd8921c8f40637667d6af9c2c76505.tar.bz2 |
Reland "[AArch64] Decouple feature dependency expansion. (#94279)" (#95519)
This is the second attempt. When parsing the target attribute
we should be letting cc1 features which don't correspond to
Extensions pass through to avoid errors like the following:
% cat neon.c
__attribute__((target("arch=armv8-a")))
uint64x2_t foo(uint64x2_t a, uint64x2_t b) { return veorq_u64(a, b); }
% clang --target=aarch64-linux-gnu -c neon.c
error: always_inline function 'veorq_u64' requires target feature
'outline-atomics', but would be inlined into function 'foo'
that is compiled without support for 'outline-atomics'
Co-authored-by: Tomas Matheson <Tomas.Matheson@arm.com>
-rw-r--r-- | clang/include/clang/AST/ASTContext.h | 3 | ||||
-rw-r--r-- | clang/lib/AST/ASTContext.cpp | 59 | ||||
-rw-r--r-- | clang/lib/AST/CMakeLists.txt | 2 | ||||
-rw-r--r-- | clang/lib/Basic/Targets/AArch64.cpp | 113 | ||||
-rw-r--r-- | clang/lib/Basic/Targets/AArch64.h | 4 | ||||
-rw-r--r-- | clang/test/CodeGen/aarch64-cpu-supports-target.c | 4 | ||||
-rw-r--r-- | clang/test/CodeGen/aarch64-sme-intrinsics/aarch64-sme-attrs.cpp | 2 | ||||
-rw-r--r-- | clang/test/CodeGen/aarch64-targetattr.c | 58 | ||||
-rw-r--r-- | clang/test/CodeGen/attr-target-version.c | 46 | ||||
-rw-r--r-- | clang/test/Sema/aarch64-neon-target.c | 10 | ||||
-rw-r--r-- | clang/test/Sema/aarch64-sve2-intrinsics/acle_sve2_aes_bitperm_sha3_sm4.cpp | 4 | ||||
-rw-r--r-- | clang/test/Sema/aarch64-sve2-intrinsics/acle_sve2_imm_lane.cpp | 4 | ||||
-rw-r--r-- | clang/test/Sema/aarch64-sve2-intrinsics/acle_sve2_imm_rotation.cpp | 4 | ||||
-rw-r--r-- | llvm/include/llvm/TargetParser/AArch64TargetParser.h | 109 | ||||
-rw-r--r-- | llvm/lib/TargetParser/AArch64TargetParser.cpp | 54 |
15 files changed, 239 insertions, 237 deletions
diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index 53ece99..f1f20fc 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -3210,9 +3210,6 @@ public: /// valid feature names. ParsedTargetAttr filterFunctionTargetAttrs(const TargetAttr *TD) const; - std::vector<std::string> - filterFunctionTargetVersionAttrs(const TargetVersionAttr *TV) const; - void getFunctionFeatureMap(llvm::StringMap<bool> &FeatureMap, const FunctionDecl *) const; void getFunctionFeatureMap(llvm::StringMap<bool> &FeatureMap, diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 34aa399..aa22825 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -87,6 +87,7 @@ #include "llvm/Support/MD5.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/TargetParser/AArch64TargetParser.h" #include "llvm/TargetParser/Triple.h" #include <algorithm> #include <cassert> @@ -13676,17 +13677,20 @@ QualType ASTContext::getCorrespondingSignedFixedPointType(QualType Ty) const { } } -std::vector<std::string> ASTContext::filterFunctionTargetVersionAttrs( - const TargetVersionAttr *TV) const { - assert(TV != nullptr); - llvm::SmallVector<StringRef, 8> Feats; - std::vector<std::string> ResFeats; - TV->getFeatures(Feats); - for (auto &Feature : Feats) - if (Target->validateCpuSupports(Feature.str())) - // Use '?' to mark features that came from TargetVersion. - ResFeats.push_back("?" + Feature.str()); - return ResFeats; +// Given a list of FMV features, return a concatenated list of the +// corresponding backend features (which may contain duplicates). +static std::vector<std::string> getFMVBackendFeaturesFor( + const llvm::SmallVectorImpl<StringRef> &FMVFeatStrings) { + std::vector<std::string> BackendFeats; + for (StringRef F : FMVFeatStrings) { + if (auto FMVExt = llvm::AArch64::parseArchExtension(F)) { + SmallVector<StringRef, 8> Feats; + FMVExt->DependentFeatures.split(Feats, ',', -1, false); + for (StringRef F : Feats) + BackendFeats.push_back(F.str()); + } + } + return BackendFeats; } ParsedTargetAttr @@ -13721,10 +13725,12 @@ void ASTContext::getFunctionFeatureMap(llvm::StringMap<bool> &FeatureMap, // Make a copy of the features as passed on the command line into the // beginning of the additional features from the function to override. - ParsedAttr.Features.insert( - ParsedAttr.Features.begin(), - Target->getTargetOpts().FeaturesAsWritten.begin(), - Target->getTargetOpts().FeaturesAsWritten.end()); + // AArch64 handles command line option features in parseTargetAttr(). + if (!Target->getTriple().isAArch64()) + ParsedAttr.Features.insert( + ParsedAttr.Features.begin(), + Target->getTargetOpts().FeaturesAsWritten.begin(), + Target->getTargetOpts().FeaturesAsWritten.end()); if (ParsedAttr.CPU != "" && Target->isValidCPUName(ParsedAttr.CPU)) TargetCPU = ParsedAttr.CPU; @@ -13745,32 +13751,31 @@ void ASTContext::getFunctionFeatureMap(llvm::StringMap<bool> &FeatureMap, Target->getTargetOpts().FeaturesAsWritten.end()); Target->initFeatureMap(FeatureMap, getDiagnostics(), TargetCPU, Features); } else if (const auto *TC = FD->getAttr<TargetClonesAttr>()) { - std::vector<std::string> Features; if (Target->getTriple().isAArch64()) { - // TargetClones for AArch64 llvm::SmallVector<StringRef, 8> Feats; TC->getFeatures(Feats, GD.getMultiVersionIndex()); - for (StringRef Feat : Feats) - if (Target->validateCpuSupports(Feat.str())) - // Use '?' to mark features that came from AArch64 TargetClones. - Features.push_back("?" + Feat.str()); + std::vector<std::string> Features = getFMVBackendFeaturesFor(Feats); Features.insert(Features.begin(), Target->getTargetOpts().FeaturesAsWritten.begin(), Target->getTargetOpts().FeaturesAsWritten.end()); + Target->initFeatureMap(FeatureMap, getDiagnostics(), TargetCPU, Features); } else { + std::vector<std::string> Features; StringRef VersionStr = TC->getFeatureStr(GD.getMultiVersionIndex()); if (VersionStr.starts_with("arch=")) TargetCPU = VersionStr.drop_front(sizeof("arch=") - 1); else if (VersionStr != "default") Features.push_back((StringRef{"+"} + VersionStr).str()); + Target->initFeatureMap(FeatureMap, getDiagnostics(), TargetCPU, Features); } - Target->initFeatureMap(FeatureMap, getDiagnostics(), TargetCPU, Features); } else if (const auto *TV = FD->getAttr<TargetVersionAttr>()) { - std::vector<std::string> Feats = filterFunctionTargetVersionAttrs(TV); - Feats.insert(Feats.begin(), - Target->getTargetOpts().FeaturesAsWritten.begin(), - Target->getTargetOpts().FeaturesAsWritten.end()); - Target->initFeatureMap(FeatureMap, getDiagnostics(), TargetCPU, Feats); + llvm::SmallVector<StringRef, 8> Feats; + TV->getFeatures(Feats); + std::vector<std::string> Features = getFMVBackendFeaturesFor(Feats); + Features.insert(Features.begin(), + Target->getTargetOpts().FeaturesAsWritten.begin(), + Target->getTargetOpts().FeaturesAsWritten.end()); + Target->initFeatureMap(FeatureMap, getDiagnostics(), TargetCPU, Features); } else { FeatureMap = Target->getTargetOpts().FeatureMap; } diff --git a/clang/lib/AST/CMakeLists.txt b/clang/lib/AST/CMakeLists.txt index a5d3dac..0328666 100644 --- a/clang/lib/AST/CMakeLists.txt +++ b/clang/lib/AST/CMakeLists.txt @@ -139,4 +139,6 @@ add_clang_library(clangAST omp_gen ClangDriverOptions intrinsics_gen + # These generated headers are included transitively. + AArch64TargetParserTableGen ) diff --git a/clang/lib/Basic/Targets/AArch64.cpp b/clang/lib/Basic/Targets/AArch64.cpp index 1351569..fba2ad0 100644 --- a/clang/lib/Basic/Targets/AArch64.cpp +++ b/clang/lib/Basic/Targets/AArch64.cpp @@ -1064,57 +1064,17 @@ bool AArch64TargetInfo::handleTargetFeatures(std::vector<std::string> &Features, return true; } -bool AArch64TargetInfo::initFeatureMap( - llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef CPU, - const std::vector<std::string> &FeaturesVec) const { - std::vector<std::string> UpdatedFeaturesVec; - // Parse the CPU and add any implied features. - std::optional<llvm::AArch64::CpuInfo> CpuInfo = llvm::AArch64::parseCpu(CPU); - if (CpuInfo) { - auto Exts = CpuInfo->getImpliedExtensions(); - std::vector<StringRef> CPUFeats; - llvm::AArch64::getExtensionFeatures(Exts, CPUFeats); - for (auto F : CPUFeats) { - assert((F[0] == '+' || F[0] == '-') && "Expected +/- in target feature!"); - UpdatedFeaturesVec.push_back(F.str()); - } - } - - // Process target and dependent features. This is done in two loops collecting - // them into UpdatedFeaturesVec: first to add dependent '+'features, second to - // add target '+/-'features that can later disable some of features added on - // the first loop. Function Multi Versioning features begin with '?'. - for (const auto &Feature : FeaturesVec) - if (((Feature[0] == '?' || Feature[0] == '+')) && - AArch64TargetInfo::doesFeatureAffectCodeGen(Feature.substr(1))) { - StringRef DepFeatures = - AArch64TargetInfo::getFeatureDependencies(Feature.substr(1)); - SmallVector<StringRef, 1> AttrFeatures; - DepFeatures.split(AttrFeatures, ","); - for (auto F : AttrFeatures) - UpdatedFeaturesVec.push_back(F.str()); - } - for (const auto &Feature : FeaturesVec) - if (Feature[0] != '?') { - std::string UpdatedFeature = Feature; - if (Feature[0] == '+') { - std::optional<llvm::AArch64::ExtensionInfo> Extension = - llvm::AArch64::parseArchExtension(Feature.substr(1)); - if (Extension) - UpdatedFeature = Extension->Feature.str(); - } - UpdatedFeaturesVec.push_back(UpdatedFeature); - } - - return TargetInfo::initFeatureMap(Features, Diags, CPU, UpdatedFeaturesVec); -} - // Parse AArch64 Target attributes, which are a comma separated list of: // "arch=<arch>" - parsed to features as per -march=.. // "cpu=<cpu>" - parsed to features as per -mcpu=.., with CPU set to <cpu> // "tune=<cpu>" - TuneCPU set to <cpu> // "feature", "no-feature" - Add (or remove) feature. // "+feature", "+nofeature" - Add (or remove) feature. +// +// A feature may correspond to an Extension (anything with a corresponding +// AEK_), in which case an ExtensionSet is used to parse it and expand its +// dependencies. If the feature does not yield a successful parse then it +// is passed through. ParsedTargetAttr AArch64TargetInfo::parseTargetAttr(StringRef Features) const { ParsedTargetAttr Ret; if (Features == "default") @@ -1124,23 +1084,31 @@ ParsedTargetAttr AArch64TargetInfo::parseTargetAttr(StringRef Features) const { bool FoundArch = false; auto SplitAndAddFeatures = [](StringRef FeatString, - std::vector<std::string> &Features) { + std::vector<std::string> &Features, + llvm::AArch64::ExtensionSet &FeatureBits) { SmallVector<StringRef, 8> SplitFeatures; FeatString.split(SplitFeatures, StringRef("+"), -1, false); for (StringRef Feature : SplitFeatures) { - StringRef FeatureName = llvm::AArch64::getArchExtFeature(Feature); - if (!FeatureName.empty()) - Features.push_back(FeatureName.str()); + if (FeatureBits.parseModifier(Feature)) + continue; + // Pass through anything that failed to parse so that we can emit + // diagnostics, as well as valid internal feature names. + // + // FIXME: We should consider rejecting internal feature names like + // neon, v8a, etc. + // FIXME: We should consider emitting diagnostics here. + if (Feature.starts_with("no")) + Features.push_back("-" + Feature.drop_front(2).str()); else - // Pushing the original feature string to give a sema error later on - // when they get checked. - if (Feature.starts_with("no")) - Features.push_back("-" + Feature.drop_front(2).str()); - else - Features.push_back("+" + Feature.str()); + Features.push_back("+" + Feature.str()); } }; + llvm::AArch64::ExtensionSet FeatureBits; + // Reconstruct the bitset from the command line option features. + FeatureBits.reconstructFromParsedFeatures(getTargetOpts().FeaturesAsWritten, + Ret.Features); + for (auto &Feature : AttrFeatures) { Feature = Feature.trim(); if (Feature.starts_with("fpmath=")) @@ -1163,9 +1131,9 @@ ParsedTargetAttr AArch64TargetInfo::parseTargetAttr(StringRef Features) const { // Ret.Features. if (!AI) continue; - Ret.Features.push_back(AI->ArchFeature.str()); + FeatureBits.addArchDefaults(*AI); // Add any extra features, after the + - SplitAndAddFeatures(Split.second, Ret.Features); + SplitAndAddFeatures(Split.second, Ret.Features, FeatureBits); } else if (Feature.starts_with("cpu=")) { if (!Ret.CPU.empty()) Ret.Duplicate = "cpu="; @@ -1175,7 +1143,10 @@ ParsedTargetAttr AArch64TargetInfo::parseTargetAttr(StringRef Features) const { std::pair<StringRef, StringRef> Split = Feature.split("=").second.trim().split("+"); Ret.CPU = Split.first; - SplitAndAddFeatures(Split.second, Ret.Features); + if (auto CpuInfo = llvm::AArch64::parseCpu(Ret.CPU)) { + FeatureBits.addCPUDefaults(*CpuInfo); + SplitAndAddFeatures(Split.second, Ret.Features, FeatureBits); + } } } else if (Feature.starts_with("tune=")) { if (!Ret.Tune.empty()) @@ -1183,25 +1154,23 @@ ParsedTargetAttr AArch64TargetInfo::parseTargetAttr(StringRef Features) const { else Ret.Tune = Feature.split("=").second.trim(); } else if (Feature.starts_with("+")) { - SplitAndAddFeatures(Feature, Ret.Features); - } else if (Feature.starts_with("no-")) { - StringRef FeatureName = - llvm::AArch64::getArchExtFeature(Feature.split("-").second); - if (!FeatureName.empty()) - Ret.Features.push_back("-" + FeatureName.drop_front(1).str()); - else - Ret.Features.push_back("-" + Feature.split("-").second.str()); + SplitAndAddFeatures(Feature, Ret.Features, FeatureBits); } else { - // Try parsing the string to the internal target feature name. If it is - // invalid, add the original string (which could already be an internal - // name). These should be checked later by isValidFeatureName. - StringRef FeatureName = llvm::AArch64::getArchExtFeature(Feature); - if (!FeatureName.empty()) - Ret.Features.push_back(FeatureName.str()); + if (FeatureBits.parseModifier(Feature, /* AllowNoDashForm = */ true)) + continue; + // Pass through anything that failed to parse so that we can emit + // diagnostics, as well as valid internal feature names. + // + // FIXME: We should consider rejecting internal feature names like + // neon, v8a, etc. + // FIXME: We should consider emitting diagnostics here. + if (Feature.starts_with("no-")) + Ret.Features.push_back("-" + Feature.drop_front(3).str()); else Ret.Features.push_back("+" + Feature.str()); } } + FeatureBits.toLLVMFeatureList(Ret.Features); return Ret; } diff --git a/clang/lib/Basic/Targets/AArch64.h b/clang/lib/Basic/Targets/AArch64.h index 22d7c42..c0a6bd2 100644 --- a/clang/lib/Basic/Targets/AArch64.h +++ b/clang/lib/Basic/Targets/AArch64.h @@ -107,10 +107,6 @@ public: unsigned multiVersionSortPriority(StringRef Name) const override; unsigned multiVersionFeatureCost() const override; - bool - initFeatureMap(llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, - StringRef CPU, - const std::vector<std::string> &FeaturesVec) const override; bool useFP16ConversionIntrinsics() const override { return false; } diff --git a/clang/test/CodeGen/aarch64-cpu-supports-target.c b/clang/test/CodeGen/aarch64-cpu-supports-target.c index e023944..28187bcf 100644 --- a/clang/test/CodeGen/aarch64-cpu-supports-target.c +++ b/clang/test/CodeGen/aarch64-cpu-supports-target.c @@ -48,5 +48,5 @@ int test_versions() { return code(); } // CHECK: attributes #0 = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" } -// CHECK: attributes #1 = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+neon" } -// CHECK: attributes #2 = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+fullfp16,+neon,+sve" } +// CHECK: attributes #1 = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+neon" } +// CHECK: attributes #2 = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+fullfp16,+sve" } diff --git a/clang/test/CodeGen/aarch64-sme-intrinsics/aarch64-sme-attrs.cpp b/clang/test/CodeGen/aarch64-sme-intrinsics/aarch64-sme-attrs.cpp index af8933d..9885ac4 100644 --- a/clang/test/CodeGen/aarch64-sme-intrinsics/aarch64-sme-attrs.cpp +++ b/clang/test/CodeGen/aarch64-sme-intrinsics/aarch64-sme-attrs.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sme \ +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sme -target-feature +bf16 \ // RUN: -disable-O0-optnone -Werror -emit-llvm -o - %s \ // RUN: | opt -S -passes=mem2reg \ // RUN: | opt -S -passes=inline \ diff --git a/clang/test/CodeGen/aarch64-targetattr.c b/clang/test/CodeGen/aarch64-targetattr.c index 2fbe105..7aabecd 100644 --- a/clang/test/CodeGen/aarch64-targetattr.c +++ b/clang/test/CodeGen/aarch64-targetattr.c @@ -132,21 +132,21 @@ __attribute__((target("+sve"))) void plussve() {} __attribute__((target("+sve+nosve2"))) // CHECK-LABEL: define {{[^@]+}}@plussveplussve2 -// CHECK-SAME: () #[[ATTR13:[0-9]+]] { +// CHECK-SAME: () #[[ATTR12]] { // CHECK-NEXT: entry: // CHECK-NEXT: ret void // void plussveplussve2() {} __attribute__((target("sve,no-sve2"))) // CHECK-LABEL: define {{[^@]+}}@plussveminusnosve2 -// CHECK-SAME: () #[[ATTR13]] { +// CHECK-SAME: () #[[ATTR12]] { // CHECK-NEXT: entry: // CHECK-NEXT: ret void // void plussveminusnosve2() {} __attribute__((target("+fp16"))) // CHECK-LABEL: define {{[^@]+}}@plusfp16 -// CHECK-SAME: () #[[ATTR14:[0-9]+]] { +// CHECK-SAME: () #[[ATTR13:[0-9]+]] { // CHECK-NEXT: entry: // CHECK-NEXT: ret void // @@ -154,44 +154,29 @@ void plusfp16() {} __attribute__((target("cpu=neoverse-n1,tune=cortex-a710,arch=armv8.6-a+sve2"))) // CHECK-LABEL: define {{[^@]+}}@all -// CHECK-SAME: () #[[ATTR15:[0-9]+]] { +// CHECK-SAME: () #[[ATTR14:[0-9]+]] { // CHECK-NEXT: entry: // CHECK-NEXT: ret void // void all() {} __attribute__((target("cpu=neoverse-n1,tune=cortex-a710,arch=armv8.6-a+sve2,branch-protection=standard"))) // CHECK-LABEL: define {{[^@]+}}@allplusbranchprotection -// CHECK-SAME: () #[[ATTR16:[0-9]+]] { +// CHECK-SAME: () #[[ATTR15:[0-9]+]] { // CHECK-NEXT: entry: // CHECK-NEXT: ret void // void allplusbranchprotection() {} -// These tests check that the user facing and internal llvm name are both accepted. -__attribute__((target("+noneon"))) -// CHECK-LABEL: define {{[^@]+}}@plusnoneon -// CHECK-SAME: () #[[ATTR17:[0-9]+]] { -// CHECK-NEXT: entry: -// CHECK-NEXT: ret void -// -void plusnoneon() {} __attribute__((target("+nosimd"))) // CHECK-LABEL: define {{[^@]+}}@plusnosimd -// CHECK-SAME: () #[[ATTR17]] { +// CHECK-SAME: () #[[ATTR16:[0-9]+]] { // CHECK-NEXT: entry: // CHECK-NEXT: ret void // void plusnosimd() {} -__attribute__((target("no-neon"))) -// CHECK-LABEL: define {{[^@]+}}@noneon -// CHECK-SAME: () #[[ATTR17]] { -// CHECK-NEXT: entry: -// CHECK-NEXT: ret void -// -void noneon() {} __attribute__((target("no-simd"))) // CHECK-LABEL: define {{[^@]+}}@nosimd -// CHECK-SAME: () #[[ATTR17]] { +// CHECK-SAME: () #[[ATTR16]] { // CHECK-NEXT: entry: // CHECK-NEXT: ret void // @@ -200,7 +185,7 @@ void nosimd() {} // This isn't part of the standard interface, but test that -arch features should not apply anything else. __attribute__((target("no-v9.3a"))) // CHECK-LABEL: define {{[^@]+}}@minusarch -// CHECK-SAME: () #[[ATTR18:[0-9]+]] { +// CHECK-SAME: () #[[ATTR17:[0-9]+]] { // CHECK-NEXT: entry: // CHECK-NEXT: ret void // @@ -210,22 +195,21 @@ void minusarch() {} // CHECK: attributes #[[ATTR0]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+crc,+fp-armv8,+lse,+neon,+ras,+rdm,+v8.1a,+v8.2a,+v8a" } // CHECK: attributes #[[ATTR1]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+crc,+fp-armv8,+fullfp16,+lse,+neon,+ras,+rdm,+sve,+v8.1a,+v8.2a,+v8a" } // CHECK: attributes #[[ATTR2]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+crc,+fp-armv8,+fullfp16,+lse,+neon,+ras,+rdm,+sve,+sve2,+v8.1a,+v8.2a,+v8a" } -// CHECK: attributes #[[ATTR3]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bf16,+complxnum,+crc,+dotprod,+fp-armv8,+fullfp16,+i8mm,+jsconv,+lse,+neon,+pauth,+ras,+rcpc,+rdm,+sve,+sve2,+v8.1a,+v8.2a,+v8.3a,+v8.4a,+v8.5a,+v8.6a,+v8a" } -// CHECK: attributes #[[ATTR4]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="cortex-a710" "target-features"="+bf16,+complxnum,+crc,+dotprod,+flagm,+fp-armv8,+fp16fml,+fullfp16,+i8mm,+jsconv,+lse,+mte,+neon,+pauth,+perfmon,+ras,+rcpc,+rdm,+sb,+sve,+sve2,+sve2-bitperm" } +// CHECK: attributes #[[ATTR3]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bf16,+complxnum,+crc,+dotprod,+fp-armv8,+fp16fml,+fullfp16,+i8mm,+jsconv,+lse,+neon,+pauth,+ras,+rcpc,+rdm,+sve,+sve2,+v8.1a,+v8.2a,+v8.3a,+v8.4a,+v8.5a,+v8.6a,+v8a" } +// CHECK: attributes #[[ATTR4]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="cortex-a710" "target-features"="+bf16,+complxnum,+crc,+dotprod,+flagm,+fp-armv8,+fp16fml,+fullfp16,+i8mm,+jsconv,+lse,+mte,+neon,+pauth,+perfmon,+ras,+rcpc,+rdm,+sb,+sve,+sve2,+sve2-bitperm,+v8.1a,+v8.2a,+v8.3a,+v8.4a,+v8.5a,+v8a,+v9a" } // CHECK: attributes #[[ATTR5]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "tune-cpu"="cortex-a710" } -// CHECK: attributes #[[ATTR6]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="generic" "target-features"="+fp-armv8,+neon" } +// CHECK: attributes #[[ATTR6]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="generic" "target-features"="+fp-armv8,+neon,+v8a" } // CHECK: attributes #[[ATTR7]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "tune-cpu"="generic" } -// CHECK: attributes #[[ATTR8]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="neoverse-n1" "target-features"="+aes,+crc,+dotprod,+fp-armv8,+fullfp16,+lse,+neon,+perfmon,+ras,+rcpc,+rdm,+sha2,+spe,+ssbs" "tune-cpu"="cortex-a710" } -// CHECK: attributes #[[ATTR9]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+fullfp16,+neon,+sve" "tune-cpu"="cortex-a710" } -// CHECK: attributes #[[ATTR10]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="neoverse-v1" "target-features"="+aes,+bf16,+complxnum,+crc,+dotprod,+fp-armv8,+fp16fml,+fullfp16,+i8mm,+jsconv,+lse,+neon,+pauth,+perfmon,+rand,+ras,+rcpc,+rdm,+sha2,+sha3,+sm4,+spe,+ssbs,+sve,+sve2" } -// CHECK: attributes #[[ATTR11]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="neoverse-v1" "target-features"="+aes,+bf16,+complxnum,+crc,+dotprod,+fp-armv8,+fp16fml,+fullfp16,+i8mm,+jsconv,+lse,+neon,+pauth,+perfmon,+rand,+ras,+rcpc,+rdm,+sha2,+sha3,+sm4,+spe,+ssbs,-sve" } -// CHECK: attributes #[[ATTR12]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+fullfp16,+neon,+sve" } -// CHECK: attributes #[[ATTR13]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+fullfp16,+neon,+sve,-sve2" } -// CHECK: attributes #[[ATTR14]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fullfp16" } -// CHECK: attributes #[[ATTR15]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="neoverse-n1" "target-features"="+aes,+bf16,+complxnum,+crc,+dotprod,+fp-armv8,+fullfp16,+i8mm,+jsconv,+lse,+neon,+pauth,+perfmon,+ras,+rcpc,+rdm,+sha2,+spe,+ssbs,+sve,+sve2,+v8.1a,+v8.2a,+v8.3a,+v8.4a,+v8.5a,+v8.6a,+v8a" "tune-cpu"="cortex-a710" } -// CHECK: attributes #[[ATTR16]] = { noinline nounwind optnone "branch-protection-pauth-lr"="false" "branch-target-enforcement"="true" "guarded-control-stack"="true" "no-trapping-math"="true" "sign-return-address"="non-leaf" "sign-return-address-key"="a_key" "stack-protector-buffer-size"="8" "target-cpu"="neoverse-n1" "target-features"="+aes,+bf16,+complxnum,+crc,+dotprod,+fp-armv8,+fullfp16,+i8mm,+jsconv,+lse,+neon,+pauth,+perfmon,+ras,+rcpc,+rdm,+sha2,+spe,+ssbs,+sve,+sve2,+v8.1a,+v8.2a,+v8.3a,+v8.4a,+v8.5a,+v8.6a,+v8a" "tune-cpu"="cortex-a710" } -// CHECK: attributes #[[ATTR17]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="-neon" } -// CHECK: attributes #[[ATTR18]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="-v9.3a" } +// CHECK: attributes #[[ATTR8]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="neoverse-n1" "target-features"="+aes,+crc,+dotprod,+fp-armv8,+fullfp16,+lse,+neon,+perfmon,+ras,+rcpc,+rdm,+sha2,+spe,+ssbs,+v8.1a,+v8.2a,+v8a" "tune-cpu"="cortex-a710" } +// CHECK: attributes #[[ATTR9]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+fullfp16,+sve" "tune-cpu"="cortex-a710" } +// CHECK: attributes #[[ATTR10]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="neoverse-v1" "target-features"="+aes,+bf16,+complxnum,+crc,+dotprod,+fp-armv8,+fp16fml,+fullfp16,+i8mm,+jsconv,+lse,+neon,+pauth,+perfmon,+rand,+ras,+rcpc,+rdm,+sha2,+sha3,+sm4,+spe,+ssbs,+sve,+sve2,+v8.1a,+v8.2a,+v8.3a,+v8.4a,+v8a" } +// CHECK: attributes #[[ATTR11]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="neoverse-v1" "target-features"="+aes,+bf16,+complxnum,+crc,+dotprod,+fp-armv8,+fp16fml,+fullfp16,+i8mm,+jsconv,+lse,+neon,+pauth,+perfmon,+rand,+ras,+rcpc,+rdm,+sha2,+sha3,+sm4,+spe,+ssbs,+v8.1a,+v8.2a,+v8.3a,+v8.4a,+v8a,-sve" } +// CHECK: attributes #[[ATTR12]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+fullfp16,+sve" } +// CHECK: attributes #[[ATTR13]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+fullfp16" } +// CHECK: attributes #[[ATTR14]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="neoverse-n1" "target-features"="+aes,+bf16,+complxnum,+crc,+dotprod,+fp-armv8,+fullfp16,+i8mm,+jsconv,+lse,+neon,+pauth,+perfmon,+ras,+rcpc,+rdm,+sha2,+spe,+ssbs,+sve,+sve2,+v8.1a,+v8.2a,+v8.3a,+v8.4a,+v8.5a,+v8.6a,+v8a" "tune-cpu"="cortex-a710" } +// CHECK: attributes #[[ATTR15]] = { noinline nounwind optnone "branch-protection-pauth-lr"="false" "branch-target-enforcement"="true" "guarded-control-stack"="true" "no-trapping-math"="true" "sign-return-address"="non-leaf" "sign-return-address-key"="a_key" "stack-protector-buffer-size"="8" "target-cpu"="neoverse-n1" "target-features"="+aes,+bf16,+complxnum,+crc,+dotprod,+fp-armv8,+fullfp16,+i8mm,+jsconv,+lse,+neon,+pauth,+perfmon,+ras,+rcpc,+rdm,+sha2,+spe,+ssbs,+sve,+sve2,+v8.1a,+v8.2a,+v8.3a,+v8.4a,+v8.5a,+v8.6a,+v8a" "tune-cpu"="cortex-a710" } +// CHECK: attributes #[[ATTR16]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" } +// CHECK: attributes #[[ATTR17]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="-v9.3a" } //. // CHECK: [[META0:![0-9]+]] = !{i32 1, !"wchar_size", i32 4} // CHECK: [[META1:![0-9]+]] = !{!"{{.*}}clang version {{.*}}"} diff --git a/clang/test/CodeGen/attr-target-version.c b/clang/test/CodeGen/attr-target-version.c index 35977113..75f8734 100644 --- a/clang/test/CodeGen/attr-target-version.c +++ b/clang/test/CodeGen/attr-target-version.c @@ -1129,42 +1129,42 @@ int caller(void) { return used_def_without_default_decl() + used_decl_without_de // CHECK-NOFMV-NEXT: ret i32 0 // //. -// CHECK: attributes #[[ATTR0]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+flagm,+fp16fml,+fullfp16,+neon,+rand,-fp-armv8,-v9.5a" } +// CHECK: attributes #[[ATTR0]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+flagm,+fp-armv8,+fp16fml,+fullfp16,+neon,+rand,-v9.5a" } // CHECK: attributes #[[ATTR1]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+altnzcv,+bf16,+flagm,+sme,+sme-i16i64,-fp-armv8,-v9.5a" } -// CHECK: attributes #[[ATTR2]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+lse,+neon,+sha2,-fp-armv8,-v9.5a" } -// CHECK: attributes #[[ATTR3]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+dotprod,+ls64,+neon,-fp-armv8,-v9.5a" } -// CHECK: attributes #[[ATTR4]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp16fml,+fullfp16,+neon,-fp-armv8,-v9.5a" } -// CHECK: attributes #[[ATTR5]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+neon,-fp-armv8,-v9.5a" } +// CHECK: attributes #[[ATTR2]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+lse,+neon,+sha2,-v9.5a" } +// CHECK: attributes #[[ATTR3]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+dotprod,+fp-armv8,+ls64,+neon,-v9.5a" } +// CHECK: attributes #[[ATTR4]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+fp16fml,+fullfp16,+neon,-v9.5a" } +// CHECK: attributes #[[ATTR5]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+neon,-v9.5a" } // CHECK: attributes #[[ATTR6]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+crc,-fp-armv8,-v9.5a" } // CHECK: attributes #[[ATTR7]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bti,-fp-armv8,-v9.5a" } // CHECK: attributes #[[ATTR8]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bf16,+sme,+sme2,-fp-armv8,-v9.5a" } // CHECK: attributes #[[ATTR9:[0-9]+]] = { "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="-fp-armv8,-v9.5a" } // CHECK: attributes #[[ATTR10]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+ccpp,-fp-armv8,-v9.5a" } // CHECK: attributes #[[ATTR11]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="-fp-armv8,-v9.5a" } -// CHECK: attributes #[[ATTR12]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fullfp16,+neon,-fp-armv8,-v9.5a" } +// CHECK: attributes #[[ATTR12]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+fullfp16,+neon,-v9.5a" } // CHECK: attributes #[[ATTR13]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+sb,-fp-armv8,-v9.5a" } // CHECK: attributes #[[ATTR14]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+mops,-fp-armv8,-v9.5a" } -// CHECK: attributes #[[ATTR15]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+dotprod,+neon,-fp-armv8,-v9.5a" } -// CHECK: attributes #[[ATTR16]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fullfp16,+neon,+sve,-fp-armv8,-v9.5a" } +// CHECK: attributes #[[ATTR15]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+dotprod,+fp-armv8,+neon,-v9.5a" } +// CHECK: attributes #[[ATTR16]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+fullfp16,+neon,+sve,-v9.5a" } // CHECK: attributes #[[ATTR17]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+lse,-fp-armv8,-v9.5a" } -// CHECK: attributes #[[ATTR18]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+neon,+rdm,-fp-armv8,-v9.5a" } -// CHECK: attributes #[[ATTR19:[0-9]+]] = { "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+jsconv,+neon,-fp-armv8,-v9.5a" } -// CHECK: attributes #[[ATTR20:[0-9]+]] = { "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+neon,+rdm,-fp-armv8,-v9.5a" } -// CHECK: attributes #[[ATTR21]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+jsconv,+neon,-fp-armv8,-v9.5a" } -// CHECK: attributes #[[ATTR22]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+aes,+f64mm,+fullfp16,+neon,+sve,-fp-armv8,-v9.5a" } -// CHECK: attributes #[[ATTR23]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bf16,+complxnum,+fullfp16,+neon,+rdm,+sme,-fp-armv8,-v9.5a" } -// CHECK: attributes #[[ATTR24]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+f32mm,+fullfp16,+i8mm,+neon,+sha2,+sha3,+sve,-fp-armv8,-v9.5a" } -// CHECK: attributes #[[ATTR25]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bf16,+dit,+fullfp16,+neon,+sve,-fp-armv8,-v9.5a" } +// CHECK: attributes #[[ATTR18]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+neon,+rdm,-v9.5a" } +// CHECK: attributes #[[ATTR19:[0-9]+]] = { "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+jsconv,+neon,-v9.5a" } +// CHECK: attributes #[[ATTR20:[0-9]+]] = { "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+neon,+rdm,-v9.5a" } +// CHECK: attributes #[[ATTR21]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+jsconv,+neon,-v9.5a" } +// CHECK: attributes #[[ATTR22]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+aes,+f64mm,+fp-armv8,+fullfp16,+neon,+sve,-v9.5a" } +// CHECK: attributes #[[ATTR23]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bf16,+complxnum,+fp-armv8,+fullfp16,+neon,+rdm,+sme,-v9.5a" } +// CHECK: attributes #[[ATTR24]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+f32mm,+fp-armv8,+fullfp16,+i8mm,+neon,+sha2,+sha3,+sve,-v9.5a" } +// CHECK: attributes #[[ATTR25]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bf16,+dit,+fp-armv8,+fullfp16,+neon,+sve,-v9.5a" } // CHECK: attributes #[[ATTR26]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+ccpp,+rcpc,-fp-armv8,-v9.5a" } -// CHECK: attributes #[[ATTR27]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+ccdp,+ccpp,+jsconv,+neon,-fp-armv8,-v9.5a" } +// CHECK: attributes #[[ATTR27]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+ccdp,+ccpp,+fp-armv8,+jsconv,+neon,-v9.5a" } // CHECK: attributes #[[ATTR28]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fptoint,+rcpc,-fp-armv8,-v9.5a" } -// CHECK: attributes #[[ATTR29]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bf16,+fullfp16,+neon,+sve,-fp-armv8,-v9.5a" } -// CHECK: attributes #[[ATTR30]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fullfp16,+neon,+sve,+sve2,+sve2-aes,+sve2-sha3,-fp-armv8,-v9.5a" } -// CHECK: attributes #[[ATTR31]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fullfp16,+neon,+sve,+sve2,+sve2-aes,+sve2-bitperm,-fp-armv8,-v9.5a" } -// CHECK: attributes #[[ATTR32]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fullfp16,+mte,+neon,+sve,+sve2,+sve2-sm4,-fp-armv8,-v9.5a" } +// CHECK: attributes #[[ATTR29]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bf16,+fp-armv8,+fullfp16,+neon,+sve,-v9.5a" } +// CHECK: attributes #[[ATTR30]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+fullfp16,+neon,+sve,+sve2,+sve2-aes,+sve2-sha3,-v9.5a" } +// CHECK: attributes #[[ATTR31]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+fullfp16,+neon,+sve,+sve2,+sve2-aes,+sve2-bitperm,-v9.5a" } +// CHECK: attributes #[[ATTR32]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+fullfp16,+mte,+neon,+sve,+sve2,+sve2-sm4,-v9.5a" } // CHECK: attributes #[[ATTR33]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+mops,+mte,+rcpc,+rcpc3,-fp-armv8,-v9.5a" } -// CHECK: attributes #[[ATTR34]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+neon,+sm4,-fp-armv8,-v9.5a" } -// CHECK: attributes #[[ATTR35]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+lse,+neon,+rdm,-fp-armv8,-v9.5a" } +// CHECK: attributes #[[ATTR34]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+neon,+sm4,-v9.5a" } +// CHECK: attributes #[[ATTR35]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+lse,+neon,+rdm,-v9.5a" } //. // CHECK-NOFMV: attributes #[[ATTR0]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="-fmv" } // CHECK-NOFMV: attributes #[[ATTR1:[0-9]+]] = { "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="-fmv" } diff --git a/clang/test/Sema/aarch64-neon-target.c b/clang/test/Sema/aarch64-neon-target.c index fa45fff..fd84b7f 100644 --- a/clang/test/Sema/aarch64-neon-target.c +++ b/clang/test/Sema/aarch64-neon-target.c @@ -1,4 +1,5 @@ // RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +neon -verify -emit-llvm -o - %s +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +neon -target-feature +outline-atomics -verify -emit-llvm -o - %s // REQUIRES: aarch64-registered-target // Test that functions with the correct target attributes can use the correct NEON intrinsics. @@ -41,6 +42,11 @@ void bf16(uint32x2_t v2i32, uint32x4_t v4i32, uint16x8_t v8i16, uint8x16_t v16i8 vcvt_bf16_f32(v4f32); } +__attribute__((target("arch=armv8-a"))) +uint64x2_t test_v8(uint64x2_t a, uint64x2_t b) { + return veorq_u64(a, b); +} + __attribute__((target("arch=armv8.1-a"))) void test_v81(int32x2_t d, int32x4_t v, int s) { vqrdmlahq_s32(v, v, v); @@ -69,8 +75,8 @@ void undefined(uint32x2_t v2i32, uint32x4_t v4i32, uint16x8_t v8i16, uint8x16_t vrnd_f16(v4f16); // expected-error {{always_inline function 'vrnd_f16' requires target feature 'fullfp16'}} vmaxnm_f16(v4f16, v4f16); // expected-error {{always_inline function 'vmaxnm_f16' requires target feature 'fullfp16'}} vrndi_f16(v4f16); // expected-error {{always_inline function 'vrndi_f16' requires target feature 'fullfp16'}} - // fp16fml - vfmlal_low_f16(v2f32, v4f16, v4f16); // expected-error {{always_inline function 'vfmlal_low_f16' requires target feature 'fp16fml'}} + // fp16fml depends on fp-armv8 + vfmlal_low_f16(v2f32, v4f16, v4f16); // expected-error {{always_inline function 'vfmlal_low_f16' requires target feature 'fp-armv8'}} // i8mm vmmlaq_s32(v4i32, v8i16, v8i16); // expected-error {{always_inline function 'vmmlaq_s32' requires target feature 'i8mm'}} vusdot_laneq_s32(v2i32, v8i8, v8i16, 0); // expected-error {{always_inline function 'vusdot_s32' requires target feature 'i8mm'}} diff --git a/clang/test/Sema/aarch64-sve2-intrinsics/acle_sve2_aes_bitperm_sha3_sm4.cpp b/clang/test/Sema/aarch64-sve2-intrinsics/acle_sve2_aes_bitperm_sha3_sm4.cpp index 898f18e..81cbb2d 100644 --- a/clang/test/Sema/aarch64-sve2-intrinsics/acle_sve2_aes_bitperm_sha3_sm4.cpp +++ b/clang/test/Sema/aarch64-sve2-intrinsics/acle_sve2_aes_bitperm_sha3_sm4.cpp @@ -1,7 +1,7 @@ // REQUIRES: aarch64-registered-target -// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve2 -verify -verify-ignore-unexpected=error,note -emit-llvm -o - %s -// RUN: %clang_cc1 -DSVE_OVERLOADED_FORMS -triple aarch64-none-linux-gnu -target-feature +sve2 -verify=overload -verify-ignore-unexpected=error,note -emit-llvm -o - %s +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve -target-feature +sve2 -verify -verify-ignore-unexpected=error,note -emit-llvm -o - %s +// RUN: %clang_cc1 -DSVE_OVERLOADED_FORMS -triple aarch64-none-linux-gnu -target-feature +sve -target-feature +sve2 -verify=overload -verify-ignore-unexpected=error,note -emit-llvm -o - %s #ifdef SVE_OVERLOADED_FORMS // A simple used,unused... macro, long enough to represent any SVE builtin. diff --git a/clang/test/Sema/aarch64-sve2-intrinsics/acle_sve2_imm_lane.cpp b/clang/test/Sema/aarch64-sve2-intrinsics/acle_sve2_imm_lane.cpp index 520238b..bca0633 100644 --- a/clang/test/Sema/aarch64-sve2-intrinsics/acle_sve2_imm_lane.cpp +++ b/clang/test/Sema/aarch64-sve2-intrinsics/acle_sve2_imm_lane.cpp @@ -1,7 +1,7 @@ // REQUIRES: aarch64-registered-target -// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve2 -fsyntax-only -verify %s -// RUN: %clang_cc1 -DSVE_OVERLOADED_FORMS -triple aarch64-none-linux-gnu -target-feature +sve2 -fsyntax-only -verify %s +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve -target-feature +sve2 -fsyntax-only -verify %s +// RUN: %clang_cc1 -DSVE_OVERLOADED_FORMS -triple aarch64-none-linux-gnu -target-feature +sve -target-feature +sve2 -fsyntax-only -verify %s #ifdef SVE_OVERLOADED_FORMS // A simple used,unused... macro, long enough to represent any SVE builtin. diff --git a/clang/test/Sema/aarch64-sve2-intrinsics/acle_sve2_imm_rotation.cpp b/clang/test/Sema/aarch64-sve2-intrinsics/acle_sve2_imm_rotation.cpp index 0ccc35f..343d2a0 100644 --- a/clang/test/Sema/aarch64-sve2-intrinsics/acle_sve2_imm_rotation.cpp +++ b/clang/test/Sema/aarch64-sve2-intrinsics/acle_sve2_imm_rotation.cpp @@ -1,7 +1,7 @@ // REQUIRES: aarch64-registered-target -// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve2 -fsyntax-only -verify %s -// RUN: %clang_cc1 -DSVE_OVERLOADED_FORMS -triple aarch64-none-linux-gnu -target-feature +sve2 -fsyntax-only -verify %s +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve -target-feature +sve2 -fsyntax-only -verify %s +// RUN: %clang_cc1 -DSVE_OVERLOADED_FORMS -triple aarch64-none-linux-gnu -target-feature +sve -target-feature +sve2 -fsyntax-only -verify %s #ifdef SVE_OVERLOADED_FORMS // A simple used,unused... macro, long enough to represent any SVE builtin. diff --git a/llvm/include/llvm/TargetParser/AArch64TargetParser.h b/llvm/include/llvm/TargetParser/AArch64TargetParser.h index e1962b3..b15c62b 100644 --- a/llvm/include/llvm/TargetParser/AArch64TargetParser.h +++ b/llvm/include/llvm/TargetParser/AArch64TargetParser.h @@ -132,48 +132,6 @@ struct ExtensionInfo { #define EMIT_EXTENSIONS #include "llvm/TargetParser/AArch64TargetParserDef.inc" -struct ExtensionSet { - // Set of extensions which are currently enabled. - ExtensionBitset Enabled; - // Set of extensions which have been enabled or disabled at any point. Used - // to avoid cluttering the cc1 command-line with lots of unneeded features. - ExtensionBitset Touched; - // Base architecture version, which we need to know because some feature - // dependencies change depending on this. - const ArchInfo *BaseArch; - - ExtensionSet() : Enabled(), Touched(), BaseArch(nullptr) {} - - // Enable the given architecture extension, and any other extensions it - // depends on. Does not change the base architecture, or follow dependencies - // between features which are only related by required arcitecture versions. - void enable(ArchExtKind E); - - // Disable the given architecture extension, and any other extensions which - // depend on it. Does not change the base architecture, or follow - // dependencies between features which are only related by required - // arcitecture versions. - void disable(ArchExtKind E); - - // Add default extensions for the given CPU. Records the base architecture, - // to later resolve dependencies which depend on it. - void addCPUDefaults(const CpuInfo &CPU); - - // Add default extensions for the given architecture version. Records the - // base architecture, to later resolve dependencies which depend on it. - void addArchDefaults(const ArchInfo &Arch); - - // Add or remove a feature based on a modifier string. The string must be of - // the form "<name>" to enable a feature or "no<name>" to disable it. This - // will also enable or disable any features as required by the dependencies - // between them. - bool parseModifier(StringRef Modifier); - - // Convert the set of enabled extension to an LLVM feature list, appending - // them to Features. - void toLLVMFeatureList(std::vector<StringRef> &Features) const; -}; - // Represents a dependency between two architecture extensions. Later is the // feature which was added to the architecture after Earlier, and expands the // functionality provided by it. If Later is enabled, then Earlier will also be @@ -264,6 +222,67 @@ struct CpuInfo { #define EMIT_CPU_INFO #include "llvm/TargetParser/AArch64TargetParserDef.inc" +struct ExtensionSet { + // Set of extensions which are currently enabled. + ExtensionBitset Enabled; + // Set of extensions which have been enabled or disabled at any point. Used + // to avoid cluttering the cc1 command-line with lots of unneeded features. + ExtensionBitset Touched; + // Base architecture version, which we need to know because some feature + // dependencies change depending on this. + const ArchInfo *BaseArch; + + ExtensionSet() : Enabled(), Touched(), BaseArch(nullptr) {} + + // Enable the given architecture extension, and any other extensions it + // depends on. Does not change the base architecture, or follow dependencies + // between features which are only related by required arcitecture versions. + void enable(ArchExtKind E); + + // Disable the given architecture extension, and any other extensions which + // depend on it. Does not change the base architecture, or follow + // dependencies between features which are only related by required + // arcitecture versions. + void disable(ArchExtKind E); + + // Add default extensions for the given CPU. Records the base architecture, + // to later resolve dependencies which depend on it. + void addCPUDefaults(const CpuInfo &CPU); + + // Add default extensions for the given architecture version. Records the + // base architecture, to later resolve dependencies which depend on it. + void addArchDefaults(const ArchInfo &Arch); + + // Add or remove a feature based on a modifier string. The string must be of + // the form "<name>" to enable a feature or "no<name>" to disable it. This + // will also enable or disable any features as required by the dependencies + // between them. + bool parseModifier(StringRef Modifier, const bool AllowNoDashForm = false); + + // Constructs a new ExtensionSet by toggling the corresponding bits for every + // feature in the \p Features list without expanding their dependencies. Used + // for reconstructing an ExtensionSet from the output of toLLVMFeatures(). + // Features that are not recognized are pushed back to \p NonExtensions. + void reconstructFromParsedFeatures(const std::vector<std::string> &Features, + std::vector<std::string> &NonExtensions); + + // Convert the set of enabled extension to an LLVM feature list, appending + // them to Features. + template <typename T> void toLLVMFeatureList(std::vector<T> &Features) const { + if (BaseArch && !BaseArch->ArchFeature.empty()) + Features.emplace_back(T(BaseArch->ArchFeature)); + + for (const auto &E : Extensions) { + if (E.Feature.empty() || !Touched.test(E.ID)) + continue; + if (Enabled.test(E.ID)) + Features.emplace_back(T(E.Feature)); + else + Features.emplace_back(T(E.NegFeature)); + } + } +}; + // Name alias. struct Alias { StringRef AltName; @@ -287,7 +306,13 @@ const ArchInfo *getArchForCpu(StringRef CPU); // Parser const ArchInfo *parseArch(StringRef Arch); + +// Return the extension which has the given -target-feature name. +std::optional<ExtensionInfo> targetFeatureToExtension(StringRef TargetFeature); + +// Parse a name as defined by the Extension class in tablegen. std::optional<ExtensionInfo> parseArchExtension(StringRef Extension); + // Given the name of a CPU or alias, return the correponding CpuInfo. std::optional<CpuInfo> parseCpu(StringRef Name); // Used by target parser tests diff --git a/llvm/lib/TargetParser/AArch64TargetParser.cpp b/llvm/lib/TargetParser/AArch64TargetParser.cpp index f099498..58cae70 100644 --- a/llvm/lib/TargetParser/AArch64TargetParser.cpp +++ b/llvm/lib/TargetParser/AArch64TargetParser.cpp @@ -119,6 +119,14 @@ AArch64::parseArchExtension(StringRef ArchExt) { return {}; } +std::optional<AArch64::ExtensionInfo> +AArch64::targetFeatureToExtension(StringRef TargetFeature) { + for (const auto &E : Extensions) + if (TargetFeature == E.Feature) + return E; + return {}; +} + std::optional<AArch64::CpuInfo> AArch64::parseCpu(StringRef Name) { // Resolve aliases first. Name = resolveCPUAlias(Name); @@ -210,21 +218,6 @@ void AArch64::ExtensionSet::disable(ArchExtKind E) { disable(Dep.Later); } -void AArch64::ExtensionSet::toLLVMFeatureList( - std::vector<StringRef> &Features) const { - if (BaseArch && !BaseArch->ArchFeature.empty()) - Features.push_back(BaseArch->ArchFeature); - - for (const auto &E : Extensions) { - if (E.Feature.empty() || !Touched.test(E.ID)) - continue; - if (Enabled.test(E.ID)) - Features.push_back(E.Feature); - else - Features.push_back(E.NegFeature); - } -} - void AArch64::ExtensionSet::addCPUDefaults(const CpuInfo &CPU) { LLVM_DEBUG(llvm::dbgs() << "addCPUDefaults(" << CPU.Name << ")\n"); BaseArch = &CPU.Arch; @@ -244,11 +237,18 @@ void AArch64::ExtensionSet::addArchDefaults(const ArchInfo &Arch) { enable(E.ID); } -bool AArch64::ExtensionSet::parseModifier(StringRef Modifier) { +bool AArch64::ExtensionSet::parseModifier(StringRef Modifier, + const bool AllowNoDashForm) { LLVM_DEBUG(llvm::dbgs() << "parseModifier(" << Modifier << ")\n"); - bool IsNegated = Modifier.starts_with("no"); - StringRef ArchExt = IsNegated ? Modifier.drop_front(2) : Modifier; + size_t NChars = 0; + // The "no-feat" form is allowed in the target attribute but nowhere else. + if (AllowNoDashForm && Modifier.starts_with("no-")) + NChars = 3; + else if (Modifier.starts_with("no")) + NChars = 2; + bool IsNegated = NChars != 0; + StringRef ArchExt = Modifier.drop_front(NChars); if (auto AE = parseArchExtension(ArchExt)) { if (AE->Feature.empty() || AE->NegFeature.empty()) @@ -262,6 +262,24 @@ bool AArch64::ExtensionSet::parseModifier(StringRef Modifier) { return false; } +void AArch64::ExtensionSet::reconstructFromParsedFeatures( + const std::vector<std::string> &Features, + std::vector<std::string> &NonExtensions) { + assert(Touched.none() && "Bitset already initialized"); + for (auto &F : Features) { + bool IsNegated = F[0] == '-'; + if (auto AE = targetFeatureToExtension(F)) { + Touched.set(AE->ID); + if (IsNegated) + Enabled.reset(AE->ID); + else + Enabled.set(AE->ID); + continue; + } + NonExtensions.push_back(F); + } +} + const AArch64::ExtensionInfo & AArch64::getExtensionByID(AArch64::ArchExtKind ExtID) { return lookupExtensionByID(ExtID); |