Skip to content

Commit 2146fd0

Browse files
committed
Revert "Reland "[AArch64] Decouple feature dependency expansion. (#94279)" (#95231)"
This reverts commit 7051073. 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.
1 parent 86bee81 commit 2146fd0

File tree

12 files changed

+222
-213
lines changed

12 files changed

+222
-213
lines changed

clang/include/clang/AST/ASTContext.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3210,6 +3210,9 @@ class ASTContext : public RefCountedBase<ASTContext> {
32103210
/// valid feature names.
32113211
ParsedTargetAttr filterFunctionTargetAttrs(const TargetAttr *TD) const;
32123212

3213+
std::vector<std::string>
3214+
filterFunctionTargetVersionAttrs(const TargetVersionAttr *TV) const;
3215+
32133216
void getFunctionFeatureMap(llvm::StringMap<bool> &FeatureMap,
32143217
const FunctionDecl *) const;
32153218
void getFunctionFeatureMap(llvm::StringMap<bool> &FeatureMap,

clang/lib/AST/ASTContext.cpp

Lines changed: 27 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,6 @@
8787
#include "llvm/Support/MD5.h"
8888
#include "llvm/Support/MathExtras.h"
8989
#include "llvm/Support/raw_ostream.h"
90-
#include "llvm/TargetParser/AArch64TargetParser.h"
9190
#include "llvm/TargetParser/Triple.h"
9291
#include <algorithm>
9392
#include <cassert>
@@ -13677,20 +13676,17 @@ QualType ASTContext::getCorrespondingSignedFixedPointType(QualType Ty) const {
1367713676
}
1367813677
}
1367913678

13680-
// Given a list of FMV features, return a concatenated list of the
13681-
// corresponding backend features (which may contain duplicates).
13682-
static std::vector<std::string> getFMVBackendFeaturesFor(
13683-
const llvm::SmallVectorImpl<StringRef> &FMVFeatStrings) {
13684-
std::vector<std::string> BackendFeats;
13685-
for (StringRef F : FMVFeatStrings) {
13686-
if (auto FMVExt = llvm::AArch64::parseArchExtension(F)) {
13687-
SmallVector<StringRef, 8> Feats;
13688-
FMVExt->DependentFeatures.split(Feats, ',', -1, false);
13689-
for (StringRef F : Feats)
13690-
BackendFeats.push_back(F.str());
13691-
}
13692-
}
13693-
return BackendFeats;
13679+
std::vector<std::string> ASTContext::filterFunctionTargetVersionAttrs(
13680+
const TargetVersionAttr *TV) const {
13681+
assert(TV != nullptr);
13682+
llvm::SmallVector<StringRef, 8> Feats;
13683+
std::vector<std::string> ResFeats;
13684+
TV->getFeatures(Feats);
13685+
for (auto &Feature : Feats)
13686+
if (Target->validateCpuSupports(Feature.str()))
13687+
// Use '?' to mark features that came from TargetVersion.
13688+
ResFeats.push_back("?" + Feature.str());
13689+
return ResFeats;
1369413690
}
1369513691

1369613692
ParsedTargetAttr
@@ -13725,12 +13721,10 @@ void ASTContext::getFunctionFeatureMap(llvm::StringMap<bool> &FeatureMap,
1372513721

1372613722
// Make a copy of the features as passed on the command line into the
1372713723
// beginning of the additional features from the function to override.
13728-
// AArch64 handles command line option features in parseTargetAttr().
13729-
if (!Target->getTriple().isAArch64())
13730-
ParsedAttr.Features.insert(
13731-
ParsedAttr.Features.begin(),
13732-
Target->getTargetOpts().FeaturesAsWritten.begin(),
13733-
Target->getTargetOpts().FeaturesAsWritten.end());
13724+
ParsedAttr.Features.insert(
13725+
ParsedAttr.Features.begin(),
13726+
Target->getTargetOpts().FeaturesAsWritten.begin(),
13727+
Target->getTargetOpts().FeaturesAsWritten.end());
1373413728

1373513729
if (ParsedAttr.CPU != "" && Target->isValidCPUName(ParsedAttr.CPU))
1373613730
TargetCPU = ParsedAttr.CPU;
@@ -13751,31 +13745,32 @@ void ASTContext::getFunctionFeatureMap(llvm::StringMap<bool> &FeatureMap,
1375113745
Target->getTargetOpts().FeaturesAsWritten.end());
1375213746
Target->initFeatureMap(FeatureMap, getDiagnostics(), TargetCPU, Features);
1375313747
} else if (const auto *TC = FD->getAttr<TargetClonesAttr>()) {
13748+
std::vector<std::string> Features;
1375413749
if (Target->getTriple().isAArch64()) {
13750+
// TargetClones for AArch64
1375513751
llvm::SmallVector<StringRef, 8> Feats;
1375613752
TC->getFeatures(Feats, GD.getMultiVersionIndex());
13757-
std::vector<std::string> Features = getFMVBackendFeaturesFor(Feats);
13753+
for (StringRef Feat : Feats)
13754+
if (Target->validateCpuSupports(Feat.str()))
13755+
// Use '?' to mark features that came from AArch64 TargetClones.
13756+
Features.push_back("?" + Feat.str());
1375813757
Features.insert(Features.begin(),
1375913758
Target->getTargetOpts().FeaturesAsWritten.begin(),
1376013759
Target->getTargetOpts().FeaturesAsWritten.end());
13761-
Target->initFeatureMap(FeatureMap, getDiagnostics(), TargetCPU, Features);
1376213760
} else {
13763-
std::vector<std::string> Features;
1376413761
StringRef VersionStr = TC->getFeatureStr(GD.getMultiVersionIndex());
1376513762
if (VersionStr.starts_with("arch="))
1376613763
TargetCPU = VersionStr.drop_front(sizeof("arch=") - 1);
1376713764
else if (VersionStr != "default")
1376813765
Features.push_back((StringRef{"+"} + VersionStr).str());
13769-
Target->initFeatureMap(FeatureMap, getDiagnostics(), TargetCPU, Features);
1377013766
}
13771-
} else if (const auto *TV = FD->getAttr<TargetVersionAttr>()) {
13772-
llvm::SmallVector<StringRef, 8> Feats;
13773-
TV->getFeatures(Feats);
13774-
std::vector<std::string> Features = getFMVBackendFeaturesFor(Feats);
13775-
Features.insert(Features.begin(),
13776-
Target->getTargetOpts().FeaturesAsWritten.begin(),
13777-
Target->getTargetOpts().FeaturesAsWritten.end());
1377813767
Target->initFeatureMap(FeatureMap, getDiagnostics(), TargetCPU, Features);
13768+
} else if (const auto *TV = FD->getAttr<TargetVersionAttr>()) {
13769+
std::vector<std::string> Feats = filterFunctionTargetVersionAttrs(TV);
13770+
Feats.insert(Feats.begin(),
13771+
Target->getTargetOpts().FeaturesAsWritten.begin(),
13772+
Target->getTargetOpts().FeaturesAsWritten.end());
13773+
Target->initFeatureMap(FeatureMap, getDiagnostics(), TargetCPU, Feats);
1377913774
} else {
1378013775
FeatureMap = Target->getTargetOpts().FeatureMap;
1378113776
}

clang/lib/AST/CMakeLists.txt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,4 @@ add_clang_library(clangAST
139139
omp_gen
140140
ClangDriverOptions
141141
intrinsics_gen
142-
# These generated headers are included transitively.
143-
AArch64TargetParserTableGen
144142
)

clang/lib/Basic/Targets/AArch64.cpp

Lines changed: 72 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1052,18 +1052,57 @@ bool AArch64TargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
10521052
return true;
10531053
}
10541054

1055+
bool AArch64TargetInfo::initFeatureMap(
1056+
llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef CPU,
1057+
const std::vector<std::string> &FeaturesVec) const {
1058+
std::vector<std::string> UpdatedFeaturesVec;
1059+
// Parse the CPU and add any implied features.
1060+
std::optional<llvm::AArch64::CpuInfo> CpuInfo = llvm::AArch64::parseCpu(CPU);
1061+
if (CpuInfo) {
1062+
auto Exts = CpuInfo->getImpliedExtensions();
1063+
std::vector<StringRef> CPUFeats;
1064+
llvm::AArch64::getExtensionFeatures(Exts, CPUFeats);
1065+
for (auto F : CPUFeats) {
1066+
assert((F[0] == '+' || F[0] == '-') && "Expected +/- in target feature!");
1067+
UpdatedFeaturesVec.push_back(F.str());
1068+
}
1069+
}
1070+
1071+
// Process target and dependent features. This is done in two loops collecting
1072+
// them into UpdatedFeaturesVec: first to add dependent '+'features, second to
1073+
// add target '+/-'features that can later disable some of features added on
1074+
// the first loop. Function Multi Versioning features begin with '?'.
1075+
for (const auto &Feature : FeaturesVec)
1076+
if (((Feature[0] == '?' || Feature[0] == '+')) &&
1077+
AArch64TargetInfo::doesFeatureAffectCodeGen(Feature.substr(1))) {
1078+
StringRef DepFeatures =
1079+
AArch64TargetInfo::getFeatureDependencies(Feature.substr(1));
1080+
SmallVector<StringRef, 1> AttrFeatures;
1081+
DepFeatures.split(AttrFeatures, ",");
1082+
for (auto F : AttrFeatures)
1083+
UpdatedFeaturesVec.push_back(F.str());
1084+
}
1085+
for (const auto &Feature : FeaturesVec)
1086+
if (Feature[0] != '?') {
1087+
std::string UpdatedFeature = Feature;
1088+
if (Feature[0] == '+') {
1089+
std::optional<llvm::AArch64::ExtensionInfo> Extension =
1090+
llvm::AArch64::parseArchExtension(Feature.substr(1));
1091+
if (Extension)
1092+
UpdatedFeature = Extension->Feature.str();
1093+
}
1094+
UpdatedFeaturesVec.push_back(UpdatedFeature);
1095+
}
1096+
1097+
return TargetInfo::initFeatureMap(Features, Diags, CPU, UpdatedFeaturesVec);
1098+
}
1099+
10551100
// Parse AArch64 Target attributes, which are a comma separated list of:
10561101
// "arch=<arch>" - parsed to features as per -march=..
10571102
// "cpu=<cpu>" - parsed to features as per -mcpu=.., with CPU set to <cpu>
10581103
// "tune=<cpu>" - TuneCPU set to <cpu>
10591104
// "feature", "no-feature" - Add (or remove) feature.
10601105
// "+feature", "+nofeature" - Add (or remove) feature.
1061-
//
1062-
// A feature may correspond to an Extension (anything with a corresponding
1063-
// AEK_), in which case an ExtensionSet is used to parse it and expand its
1064-
// dependencies. Otherwise the feature is passed through (e.g. +v8.1a,
1065-
// +outline-atomics, -fmv, etc). Features coming from the command line are
1066-
// already parsed, therefore their dependencies do not need expansion.
10671106
ParsedTargetAttr AArch64TargetInfo::parseTargetAttr(StringRef Features) const {
10681107
ParsedTargetAttr Ret;
10691108
if (Features == "default")
@@ -1073,26 +1112,23 @@ ParsedTargetAttr AArch64TargetInfo::parseTargetAttr(StringRef Features) const {
10731112
bool FoundArch = false;
10741113

10751114
auto SplitAndAddFeatures = [](StringRef FeatString,
1076-
std::vector<std::string> &Features,
1077-
llvm::AArch64::ExtensionSet &FeatureBits) {
1115+
std::vector<std::string> &Features) {
10781116
SmallVector<StringRef, 8> SplitFeatures;
10791117
FeatString.split(SplitFeatures, StringRef("+"), -1, false);
10801118
for (StringRef Feature : SplitFeatures) {
1081-
if (FeatureBits.parseModifier(Feature, /* AllowNoDashForm = */ true))
1082-
continue;
1083-
// Pass through features that are not extensions, e.g. +v8.1a,
1084-
// +outline-atomics, -fmv, etc.
1085-
if (Feature.starts_with("no"))
1086-
Features.push_back("-" + Feature.drop_front(2).str());
1119+
StringRef FeatureName = llvm::AArch64::getArchExtFeature(Feature);
1120+
if (!FeatureName.empty())
1121+
Features.push_back(FeatureName.str());
10871122
else
1088-
Features.push_back("+" + Feature.str());
1123+
// Pushing the original feature string to give a sema error later on
1124+
// when they get checked.
1125+
if (Feature.starts_with("no"))
1126+
Features.push_back("-" + Feature.drop_front(2).str());
1127+
else
1128+
Features.push_back("+" + Feature.str());
10891129
}
10901130
};
10911131

1092-
llvm::AArch64::ExtensionSet FeatureBits;
1093-
// Reconstruct the bitset from the command line option features.
1094-
FeatureBits.reconstructFromParsedFeatures(getTargetOpts().FeaturesAsWritten);
1095-
10961132
for (auto &Feature : AttrFeatures) {
10971133
Feature = Feature.trim();
10981134
if (Feature.starts_with("fpmath="))
@@ -1115,9 +1151,9 @@ ParsedTargetAttr AArch64TargetInfo::parseTargetAttr(StringRef Features) const {
11151151
// Ret.Features.
11161152
if (!AI)
11171153
continue;
1118-
FeatureBits.addArchDefaults(*AI);
1154+
Ret.Features.push_back(AI->ArchFeature.str());
11191155
// Add any extra features, after the +
1120-
SplitAndAddFeatures(Split.second, Ret.Features, FeatureBits);
1156+
SplitAndAddFeatures(Split.second, Ret.Features);
11211157
} else if (Feature.starts_with("cpu=")) {
11221158
if (!Ret.CPU.empty())
11231159
Ret.Duplicate = "cpu=";
@@ -1127,30 +1163,33 @@ ParsedTargetAttr AArch64TargetInfo::parseTargetAttr(StringRef Features) const {
11271163
std::pair<StringRef, StringRef> Split =
11281164
Feature.split("=").second.trim().split("+");
11291165
Ret.CPU = Split.first;
1130-
if (auto CpuInfo = llvm::AArch64::parseCpu(Ret.CPU)) {
1131-
FeatureBits.addCPUDefaults(*CpuInfo);
1132-
SplitAndAddFeatures(Split.second, Ret.Features, FeatureBits);
1133-
}
1166+
SplitAndAddFeatures(Split.second, Ret.Features);
11341167
}
11351168
} else if (Feature.starts_with("tune=")) {
11361169
if (!Ret.Tune.empty())
11371170
Ret.Duplicate = "tune=";
11381171
else
11391172
Ret.Tune = Feature.split("=").second.trim();
11401173
} else if (Feature.starts_with("+")) {
1141-
SplitAndAddFeatures(Feature, Ret.Features, FeatureBits);
1174+
SplitAndAddFeatures(Feature, Ret.Features);
1175+
} else if (Feature.starts_with("no-")) {
1176+
StringRef FeatureName =
1177+
llvm::AArch64::getArchExtFeature(Feature.split("-").second);
1178+
if (!FeatureName.empty())
1179+
Ret.Features.push_back("-" + FeatureName.drop_front(1).str());
1180+
else
1181+
Ret.Features.push_back("-" + Feature.split("-").second.str());
11421182
} else {
1143-
if (FeatureBits.parseModifier(Feature, /* AllowNoDashForm = */ true))
1144-
continue;
1145-
// Pass through features that are not extensions, e.g. +v8.1a,
1146-
// +outline-atomics, -fmv, etc.
1147-
if (Feature.starts_with("no-"))
1148-
Ret.Features.push_back("-" + Feature.drop_front(3).str());
1183+
// Try parsing the string to the internal target feature name. If it is
1184+
// invalid, add the original string (which could already be an internal
1185+
// name). These should be checked later by isValidFeatureName.
1186+
StringRef FeatureName = llvm::AArch64::getArchExtFeature(Feature);
1187+
if (!FeatureName.empty())
1188+
Ret.Features.push_back(FeatureName.str());
11491189
else
11501190
Ret.Features.push_back("+" + Feature.str());
11511191
}
11521192
}
1153-
FeatureBits.toLLVMFeatureList(Ret.Features);
11541193
return Ret;
11551194
}
11561195

clang/lib/Basic/Targets/AArch64.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,10 @@ class LLVM_LIBRARY_VISIBILITY AArch64TargetInfo : public TargetInfo {
107107
unsigned multiVersionSortPriority(StringRef Name) const override;
108108
unsigned multiVersionFeatureCost() const override;
109109

110+
bool
111+
initFeatureMap(llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags,
112+
StringRef CPU,
113+
const std::vector<std::string> &FeaturesVec) const override;
110114
bool useFP16ConversionIntrinsics() const override {
111115
return false;
112116
}

clang/test/CodeGen/aarch64-cpu-supports-target.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,5 +48,5 @@ int test_versions() {
4848
return code();
4949
}
5050
// CHECK: attributes #0 = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
51-
// CHECK: attributes #1 = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+neon" }
52-
// CHECK: attributes #2 = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+fullfp16,+sve" }
51+
// CHECK: attributes #1 = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+neon" }
52+
// CHECK: attributes #2 = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+fullfp16,+neon,+sve" }

clang/test/CodeGen/aarch64-sme-intrinsics/aarch64-sme-attrs.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sme -target-feature +bf16 \
1+
// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sme \
22
// RUN: -disable-O0-optnone -Werror -emit-llvm -o - %s \
33
// RUN: | opt -S -passes=mem2reg \
44
// RUN: | opt -S -passes=inline \

0 commit comments

Comments
 (0)