This reverts commit 70510733af.
The following code is now incorrectly rejected.
```
% cat neon.c
#include <arm_neon.h>
__attribute__((target("arch=armv8-a")))
uint64x2_t foo(uint64x2_t a, uint64x2_t b) {
return veorq_u64(a, b);
}
% newclang --target=aarch64-linux-gnu -c neon.c
neon.c:5:10: 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'
5 | return veorq_u64(a, b);
| ^
1 error generated.
```
"+outline-atomics" seems misleading here.
This commit is contained in:
@@ -3210,6 +3210,9 @@ 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,
|
||||
|
||||
@@ -87,7 +87,6 @@
|
||||
#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>
|
||||
@@ -13677,20 +13676,17 @@ QualType ASTContext::getCorrespondingSignedFixedPointType(QualType Ty) const {
|
||||
}
|
||||
}
|
||||
|
||||
// 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;
|
||||
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;
|
||||
}
|
||||
|
||||
ParsedTargetAttr
|
||||
@@ -13725,12 +13721,10 @@ 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.
|
||||
// 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());
|
||||
ParsedAttr.Features.insert(
|
||||
ParsedAttr.Features.begin(),
|
||||
Target->getTargetOpts().FeaturesAsWritten.begin(),
|
||||
Target->getTargetOpts().FeaturesAsWritten.end());
|
||||
|
||||
if (ParsedAttr.CPU != "" && Target->isValidCPUName(ParsedAttr.CPU))
|
||||
TargetCPU = ParsedAttr.CPU;
|
||||
@@ -13751,31 +13745,32 @@ 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());
|
||||
std::vector<std::string> Features = getFMVBackendFeaturesFor(Feats);
|
||||
for (StringRef Feat : Feats)
|
||||
if (Target->validateCpuSupports(Feat.str()))
|
||||
// Use '?' to mark features that came from AArch64 TargetClones.
|
||||
Features.push_back("?" + Feat.str());
|
||||
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);
|
||||
}
|
||||
} else if (const auto *TV = FD->getAttr<TargetVersionAttr>()) {
|
||||
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 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);
|
||||
} else {
|
||||
FeatureMap = Target->getTargetOpts().FeatureMap;
|
||||
}
|
||||
|
||||
@@ -139,6 +139,4 @@ add_clang_library(clangAST
|
||||
omp_gen
|
||||
ClangDriverOptions
|
||||
intrinsics_gen
|
||||
# These generated headers are included transitively.
|
||||
AArch64TargetParserTableGen
|
||||
)
|
||||
|
||||
@@ -1052,18 +1052,57 @@ 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. Otherwise the feature is passed through (e.g. +v8.1a,
|
||||
// +outline-atomics, -fmv, etc). Features coming from the command line are
|
||||
// already parsed, therefore their dependencies do not need expansion.
|
||||
ParsedTargetAttr AArch64TargetInfo::parseTargetAttr(StringRef Features) const {
|
||||
ParsedTargetAttr Ret;
|
||||
if (Features == "default")
|
||||
@@ -1073,26 +1112,23 @@ ParsedTargetAttr AArch64TargetInfo::parseTargetAttr(StringRef Features) const {
|
||||
bool FoundArch = false;
|
||||
|
||||
auto SplitAndAddFeatures = [](StringRef FeatString,
|
||||
std::vector<std::string> &Features,
|
||||
llvm::AArch64::ExtensionSet &FeatureBits) {
|
||||
std::vector<std::string> &Features) {
|
||||
SmallVector<StringRef, 8> SplitFeatures;
|
||||
FeatString.split(SplitFeatures, StringRef("+"), -1, false);
|
||||
for (StringRef Feature : SplitFeatures) {
|
||||
if (FeatureBits.parseModifier(Feature, /* AllowNoDashForm = */ true))
|
||||
continue;
|
||||
// Pass through features that are not extensions, e.g. +v8.1a,
|
||||
// +outline-atomics, -fmv, etc.
|
||||
if (Feature.starts_with("no"))
|
||||
Features.push_back("-" + Feature.drop_front(2).str());
|
||||
StringRef FeatureName = llvm::AArch64::getArchExtFeature(Feature);
|
||||
if (!FeatureName.empty())
|
||||
Features.push_back(FeatureName.str());
|
||||
else
|
||||
Features.push_back("+" + Feature.str());
|
||||
// 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());
|
||||
}
|
||||
};
|
||||
|
||||
llvm::AArch64::ExtensionSet FeatureBits;
|
||||
// Reconstruct the bitset from the command line option features.
|
||||
FeatureBits.reconstructFromParsedFeatures(getTargetOpts().FeaturesAsWritten);
|
||||
|
||||
for (auto &Feature : AttrFeatures) {
|
||||
Feature = Feature.trim();
|
||||
if (Feature.starts_with("fpmath="))
|
||||
@@ -1115,9 +1151,9 @@ ParsedTargetAttr AArch64TargetInfo::parseTargetAttr(StringRef Features) const {
|
||||
// Ret.Features.
|
||||
if (!AI)
|
||||
continue;
|
||||
FeatureBits.addArchDefaults(*AI);
|
||||
Ret.Features.push_back(AI->ArchFeature.str());
|
||||
// Add any extra features, after the +
|
||||
SplitAndAddFeatures(Split.second, Ret.Features, FeatureBits);
|
||||
SplitAndAddFeatures(Split.second, Ret.Features);
|
||||
} else if (Feature.starts_with("cpu=")) {
|
||||
if (!Ret.CPU.empty())
|
||||
Ret.Duplicate = "cpu=";
|
||||
@@ -1127,10 +1163,7 @@ ParsedTargetAttr AArch64TargetInfo::parseTargetAttr(StringRef Features) const {
|
||||
std::pair<StringRef, StringRef> Split =
|
||||
Feature.split("=").second.trim().split("+");
|
||||
Ret.CPU = Split.first;
|
||||
if (auto CpuInfo = llvm::AArch64::parseCpu(Ret.CPU)) {
|
||||
FeatureBits.addCPUDefaults(*CpuInfo);
|
||||
SplitAndAddFeatures(Split.second, Ret.Features, FeatureBits);
|
||||
}
|
||||
SplitAndAddFeatures(Split.second, Ret.Features);
|
||||
}
|
||||
} else if (Feature.starts_with("tune=")) {
|
||||
if (!Ret.Tune.empty())
|
||||
@@ -1138,19 +1171,25 @@ ParsedTargetAttr AArch64TargetInfo::parseTargetAttr(StringRef Features) const {
|
||||
else
|
||||
Ret.Tune = Feature.split("=").second.trim();
|
||||
} else if (Feature.starts_with("+")) {
|
||||
SplitAndAddFeatures(Feature, Ret.Features, FeatureBits);
|
||||
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());
|
||||
} else {
|
||||
if (FeatureBits.parseModifier(Feature, /* AllowNoDashForm = */ true))
|
||||
continue;
|
||||
// Pass through features that are not extensions, e.g. +v8.1a,
|
||||
// +outline-atomics, -fmv, etc.
|
||||
if (Feature.starts_with("no-"))
|
||||
Ret.Features.push_back("-" + Feature.drop_front(3).str());
|
||||
// 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());
|
||||
else
|
||||
Ret.Features.push_back("+" + Feature.str());
|
||||
}
|
||||
}
|
||||
FeatureBits.toLLVMFeatureList(Ret.Features);
|
||||
return Ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -107,6 +107,10 @@ 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;
|
||||
}
|
||||
|
||||
@@ -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"="+fp-armv8,+neon" }
|
||||
// CHECK: attributes #2 = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+fullfp16,+sve" }
|
||||
// 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" }
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sme -target-feature +bf16 \
|
||||
// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sme \
|
||||
// RUN: -disable-O0-optnone -Werror -emit-llvm -o - %s \
|
||||
// RUN: | opt -S -passes=mem2reg \
|
||||
// RUN: | opt -S -passes=inline \
|
||||
|
||||
@@ -58,50 +58,58 @@ void v1msve() {}
|
||||
// CHECK-LABEL: @plussve() #12
|
||||
__attribute__((target("+sve")))
|
||||
void plussve() {}
|
||||
// CHECK-LABEL: @plussveplussve2() #12
|
||||
// CHECK-LABEL: @plussveplussve2() #13
|
||||
__attribute__((target("+sve+nosve2")))
|
||||
void plussveplussve2() {}
|
||||
// CHECK-LABEL: @plussveminusnosve2() #12
|
||||
// CHECK-LABEL: @plussveminusnosve2() #13
|
||||
__attribute__((target("sve,no-sve2")))
|
||||
void plussveminusnosve2() {}
|
||||
// CHECK-LABEL: @plusfp16() #13
|
||||
// CHECK-LABEL: @plusfp16() #14
|
||||
__attribute__((target("+fp16")))
|
||||
void plusfp16() {}
|
||||
|
||||
// CHECK-LABEL: @all() #14
|
||||
// CHECK-LABEL: @all() #15
|
||||
__attribute__((target("cpu=neoverse-n1,tune=cortex-a710,arch=armv8.6-a+sve2")))
|
||||
void all() {}
|
||||
// CHECK-LABEL: @allplusbranchprotection() #15
|
||||
// CHECK-LABEL: @allplusbranchprotection() #16
|
||||
__attribute__((target("cpu=neoverse-n1,tune=cortex-a710,arch=armv8.6-a+sve2,branch-protection=standard")))
|
||||
void allplusbranchprotection() {}
|
||||
|
||||
// CHECK-LABEL: @plusnosimd() #16
|
||||
// These tests check that the user facing and internal llvm name are both accepted.
|
||||
// CHECK-LABEL: @plusnoneon() #17
|
||||
__attribute__((target("+noneon")))
|
||||
void plusnoneon() {}
|
||||
// CHECK-LABEL: @plusnosimd() #17
|
||||
__attribute__((target("+nosimd")))
|
||||
void plusnosimd() {}
|
||||
// CHECK-LABEL: @nosimd() #16
|
||||
// CHECK-LABEL: @noneon() #17
|
||||
__attribute__((target("no-neon")))
|
||||
void noneon() {}
|
||||
// CHECK-LABEL: @nosimd() #17
|
||||
__attribute__((target("no-simd")))
|
||||
void nosimd() {}
|
||||
|
||||
// This isn't part of the standard interface, but test that -arch features should not apply anything else.
|
||||
// CHECK-LABEL: @minusarch() #17
|
||||
// CHECK-LABEL: @minusarch() #18
|
||||
__attribute__((target("no-v9.3a")))
|
||||
void minusarch() {}
|
||||
|
||||
// CHECK: attributes #0 = { {{.*}} "target-features"="+crc,+fp-armv8,+lse,+neon,+ras,+rdm,+v8.1a,+v8.2a,+v8a" }
|
||||
// CHECK: attributes #1 = { {{.*}} "target-features"="+crc,+fp-armv8,+fullfp16,+lse,+neon,+ras,+rdm,+sve,+v8.1a,+v8.2a,+v8a" }
|
||||
// CHECK: attributes #2 = { {{.*}} "target-features"="+crc,+fp-armv8,+fullfp16,+lse,+neon,+ras,+rdm,+sve,+sve2,+v8.1a,+v8.2a,+v8a" }
|
||||
// CHECK: attributes #3 = { {{.*}} "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 #4 = { {{.*}} "target-cpu"="cortex-a710" "target-features"="+bf16,+complxnum,+crc,+dotprod,+flagm,+fp-armv8,+fp16fml,+fullfp16,+i8mm,+jsconv,+lse,+mte,+neon,+pauth,+ras,+rcpc,+rdm,+sb,+sve,+sve2,+sve2-bitperm,+v8.1a,+v8.2a,+v8.3a,+v8.4a,+v8.5a,+v8a,+v9a" }
|
||||
// CHECK: attributes #3 = { {{.*}} "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 #4 = { {{.*}} "target-cpu"="cortex-a710" "target-features"="+bf16,+complxnum,+crc,+dotprod,+flagm,+fp-armv8,+fp16fml,+fullfp16,+i8mm,+jsconv,+lse,+mte,+neon,+pauth,+ras,+rcpc,+rdm,+sb,+sve,+sve2,+sve2-bitperm" }
|
||||
// CHECK: attributes #5 = { {{.*}} "tune-cpu"="cortex-a710" }
|
||||
// CHECK: attributes #6 = { {{.*}} "target-cpu"="generic" }
|
||||
// CHECK: attributes #7 = { {{.*}} "tune-cpu"="generic" }
|
||||
// CHECK: attributes #8 = { {{.*}} "target-cpu"="neoverse-n1" "target-features"="+aes,+crc,+dotprod,+fp-armv8,+fullfp16,+lse,+neon,+ras,+rcpc,+rdm,+sha2,+spe,+ssbs,+v8.1a,+v8.2a,+v8a" "tune-cpu"="cortex-a710" }
|
||||
// CHECK: attributes #9 = { {{.*}} "target-features"="+fp-armv8,+fullfp16,+sve" "tune-cpu"="cortex-a710" }
|
||||
// CHECK: attributes #10 = { {{.*}} "target-cpu"="neoverse-v1" "target-features"="+aes,+bf16,+complxnum,+crc,+dotprod,+fp-armv8,+fp16fml,+fullfp16,+i8mm,+jsconv,+lse,+neon,+pauth,+rand,+ras,+rcpc,+rdm,+sha2,+sha3,+sm4,+spe,+ssbs,+sve,+sve2,+v8.1a,+v8.2a,+v8.3a,+v8.4a,+v8a" }
|
||||
// CHECK: attributes #11 = { {{.*}} "target-cpu"="neoverse-v1" "target-features"="+aes,+bf16,+complxnum,+crc,+dotprod,+fp-armv8,+fp16fml,+fullfp16,+i8mm,+jsconv,+lse,+neon,+pauth,+rand,+ras,+rcpc,+rdm,+sha2,+sha3,+sm4,+spe,+ssbs,+v8.1a,+v8.2a,+v8.3a,+v8.4a,+v8a,-sve" }
|
||||
// CHECK: attributes #12 = { {{.*}} "target-features"="+fp-armv8,+fullfp16,+sve" }
|
||||
// CHECK: attributes #13 = { {{.*}} "target-features"="+fp-armv8,+fullfp16" }
|
||||
// CHECK: attributes #14 = { {{.*}} "target-cpu"="neoverse-n1" "target-features"="+aes,+bf16,+complxnum,+crc,+dotprod,+fp-armv8,+fullfp16,+i8mm,+jsconv,+lse,+neon,+pauth,+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 #15 = { {{.*}} "branch-target-enforcement"="true" "guarded-control-stack"="true" {{.*}} "target-features"="+aes,+bf16,+complxnum,+crc,+dotprod,+fp-armv8,+fullfp16,+i8mm,+jsconv,+lse,+neon,+pauth,+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-NOT: attributes #16 = {{.*}} "target-features"
|
||||
// CHECK: attributes #17 = { {{.*}} "target-features"="-v9.3a" }
|
||||
// CHECK: attributes #8 = { {{.*}} "target-cpu"="neoverse-n1" "target-features"="+aes,+crc,+dotprod,+fp-armv8,+fullfp16,+lse,+neon,+ras,+rcpc,+rdm,+sha2,+spe,+ssbs" "tune-cpu"="cortex-a710" }
|
||||
// CHECK: attributes #9 = { {{.*}} "target-features"="+fp-armv8,+fullfp16,+neon,+sve" "tune-cpu"="cortex-a710" }
|
||||
// CHECK: attributes #10 = { {{.*}} "target-cpu"="neoverse-v1" "target-features"="+aes,+bf16,+complxnum,+crc,+dotprod,+fp-armv8,+fp16fml,+fullfp16,+i8mm,+jsconv,+lse,+neon,+pauth,+rand,+ras,+rcpc,+rdm,+sha2,+sha3,+sm4,+spe,+ssbs,+sve,+sve2" }
|
||||
// CHECK: attributes #11 = { {{.*}} "target-cpu"="neoverse-v1" "target-features"="+aes,+bf16,+complxnum,+crc,+dotprod,+fp-armv8,+fp16fml,+fullfp16,+i8mm,+jsconv,+lse,+neon,+pauth,+rand,+ras,+rcpc,+rdm,+sha2,+sha3,+sm4,+spe,+ssbs,-sve" }
|
||||
// CHECK: attributes #12 = { {{.*}} "target-features"="+fp-armv8,+fullfp16,+neon,+sve" }
|
||||
// CHECK: attributes #13 = { {{.*}} "target-features"="+fp-armv8,+fullfp16,+neon,+sve,-sve2" }
|
||||
// CHECK: attributes #14 = { {{.*}} "target-features"="+fullfp16" }
|
||||
// CHECK: attributes #15 = { {{.*}} "target-cpu"="neoverse-n1" "target-features"="+aes,+bf16,+complxnum,+crc,+dotprod,+fp-armv8,+fullfp16,+i8mm,+jsconv,+lse,+neon,+pauth,+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 #16 = { {{.*}} "branch-target-enforcement"="true" "guarded-control-stack"="true" {{.*}} "target-features"="+aes,+bf16,+complxnum,+crc,+dotprod,+fp-armv8,+fullfp16,+i8mm,+jsconv,+lse,+neon,+pauth,+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 #17 = { {{.*}} "target-features"="-neon" }
|
||||
// CHECK: attributes #18 = { {{.*}} "target-features"="-v9.3a" }
|
||||
|
||||
@@ -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,+fp-armv8,+fp16fml,+fullfp16,+neon,+rand,-v9.5a" }
|
||||
// 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 #[[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"="+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 #[[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 #[[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"="+fp-armv8,+fullfp16,+neon,-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 #[[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,+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 #[[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 #[[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"="+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 #[[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 #[[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,+fp-armv8,+jsconv,+neon,-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 #[[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,+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 #[[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 #[[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"="+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: 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-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" }
|
||||
|
||||
@@ -69,8 +69,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 depends on fp-armv8
|
||||
vfmlal_low_f16(v2f32, v4f16, v4f16); // expected-error {{always_inline function 'vfmlal_low_f16' requires target feature 'fp-armv8'}}
|
||||
// fp16fml
|
||||
vfmlal_low_f16(v2f32, v4f16, v4f16); // expected-error {{always_inline function 'vfmlal_low_f16' requires target feature 'fp16fml'}}
|
||||
// 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'}}
|
||||
|
||||
@@ -132,6 +132,48 @@ 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
|
||||
@@ -554,65 +596,6 @@ inline constexpr CpuInfo CpuInfos[] = {
|
||||
AArch64::AEK_PROFILE}))},
|
||||
};
|
||||
|
||||
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().
|
||||
void reconstructFromParsedFeatures(const std::vector<std::string> &Features);
|
||||
|
||||
// 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;
|
||||
@@ -636,13 +619,7 @@ 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
|
||||
|
||||
@@ -122,14 +122,6 @@ 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);
|
||||
@@ -221,6 +213,21 @@ 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;
|
||||
@@ -240,18 +247,11 @@ void AArch64::ExtensionSet::addArchDefaults(const ArchInfo &Arch) {
|
||||
enable(E.ID);
|
||||
}
|
||||
|
||||
bool AArch64::ExtensionSet::parseModifier(StringRef Modifier,
|
||||
const bool AllowNoDashForm) {
|
||||
bool AArch64::ExtensionSet::parseModifier(StringRef Modifier) {
|
||||
LLVM_DEBUG(llvm::dbgs() << "parseModifier(" << Modifier << ")\n");
|
||||
|
||||
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);
|
||||
bool IsNegated = Modifier.starts_with("no");
|
||||
StringRef ArchExt = IsNegated ? Modifier.drop_front(2) : Modifier;
|
||||
|
||||
if (auto AE = parseArchExtension(ArchExt)) {
|
||||
if (AE->Feature.empty() || AE->NegFeature.empty())
|
||||
@@ -265,21 +265,6 @@ bool AArch64::ExtensionSet::parseModifier(StringRef Modifier,
|
||||
return false;
|
||||
}
|
||||
|
||||
void AArch64::ExtensionSet::reconstructFromParsedFeatures(
|
||||
const std::vector<std::string> &Features) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const AArch64::ExtensionInfo &
|
||||
AArch64::getExtensionByID(AArch64::ArchExtKind ExtID) {
|
||||
return lookupExtensionByID(ExtID);
|
||||
|
||||
Reference in New Issue
Block a user