-
Notifications
You must be signed in to change notification settings - Fork 14.4k
[FMV][AArch64] Convert user facing priority syntax to internal. #147607
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
This allows the user to specify "priority=[1-32];featA+featB" where priority=1 means highest priority. If the explicit priority string is omitted then the priority of "featA+featB" is implied, which is lower than priority=32. Depends on llvm#146092.
@llvm/pr-subscribers-backend-aarch64 @llvm/pr-subscribers-clang-codegen Author: Alexandros Lamprineas (labrinea) ChangesThis allows the user to specify "priority=[1-32];featA+featB" Depends on #146092. Patch is 46.40 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/147607.diff 15 Files Affected:
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 9397546c8fc5d..71bf7dd9f09a1 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -4911,7 +4911,8 @@ class Sema final : public SemaBase {
bool checkTargetAttr(SourceLocation LiteralLoc, StringRef Str);
/// Check Target Version attrs
- bool checkTargetVersionAttr(SourceLocation Loc, Decl *D, StringRef Str);
+ bool checkTargetVersionAttr(SourceLocation Loc, Decl *D, StringRef Str,
+ SmallString<64> &);
bool checkTargetClonesAttrString(
SourceLocation LiteralLoc, StringRef Str, const StringLiteral *Literal,
Decl *D, bool &HasDefault, bool &HasCommas, bool &HasNotDefault,
diff --git a/clang/lib/CodeGen/Targets/AArch64.cpp b/clang/lib/CodeGen/Targets/AArch64.cpp
index b82c46966cf0b..e2ede08942183 100644
--- a/clang/lib/CodeGen/Targets/AArch64.cpp
+++ b/clang/lib/CodeGen/Targets/AArch64.cpp
@@ -1336,10 +1336,13 @@ void AArch64ABIInfo::appendAttributeMangling(StringRef AttrStr,
});
llvm::SmallDenseSet<StringRef, 8> UniqueFeats;
- for (auto &Feat : Features)
+ for (auto &Feat : Features) {
+ if (!getTarget().doesFeatureAffectCodeGen(Feat))
+ continue;
if (auto Ext = llvm::AArch64::parseFMVExtension(Feat))
if (UniqueFeats.insert(Ext->Name).second)
Out << 'M' << Ext->Name;
+ }
}
std::unique_ptr<TargetCodeGenInfo>
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index eba29e609cb05..69015b8e1a9d7 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -3279,20 +3279,52 @@ bool Sema::checkTargetAttr(SourceLocation LiteralLoc, StringRef AttrStr) {
}
bool Sema::checkTargetVersionAttr(SourceLocation LiteralLoc, Decl *D,
- StringRef AttrStr) {
+ StringRef AttrStr, SmallString<64> &NewStr) {
enum FirstParam { Unsupported };
enum SecondParam { None };
enum ThirdParam { Target, TargetClones, TargetVersion };
- llvm::SmallVector<StringRef, 8> Features;
- if (Context.getTargetInfo().getTriple().isRISCV()) {
- llvm::SmallVector<StringRef, 8> AttrStrs;
- AttrStr.split(AttrStrs, ';');
-
- bool HasArch = false;
- bool HasPriority = false;
- bool HasDefault = false;
- bool DuplicateAttr = false;
- for (auto &AttrStr : AttrStrs) {
+
+ StringRef PriorityString[5] = {"priority5", "priority4", "priority3",
+ "priority2", "priority1"};
+
+ llvm::SmallVector<StringRef, 8> AttrStrs;
+ AttrStr.split(AttrStrs, ';');
+
+ bool HasArch = false;
+ bool HasFeatures = false;
+ bool HasPriority = false;
+ bool HasDefault = false;
+ bool DuplicateAttr = false;
+ for (StringRef AttrStr : AttrStrs) {
+ AttrStr = AttrStr.trim();
+ if (AttrStr.starts_with("default")) {
+ if (HasDefault)
+ DuplicateAttr = true;
+ HasDefault = true;
+ if (Context.getTargetInfo().getTriple().isAArch64())
+ NewStr.append(AttrStr);
+ } else if (AttrStr.consume_front("priority=")) {
+ if (HasPriority)
+ DuplicateAttr = true;
+ HasPriority = true;
+ unsigned Digit;
+ if (AttrStr.getAsInteger(0, Digit))
+ return Diag(LiteralLoc, diag::warn_unsupported_target_attribute)
+ << Unsupported << None << AttrStr << TargetVersion;
+ if (Context.getTargetInfo().getTriple().isAArch64()) {
+ if (Digit < 1 || Digit > 32)
+ return Diag(LiteralLoc, diag::warn_unsupported_target_attribute)
+ << Unsupported << None << AttrStr << TargetVersion;
+ // Convert priority=[1-32] -> priority1 + ... + priority5
+ for (int BitPos = 4; BitPos >= 0; --BitPos) {
+ if ((32 - Digit) & (1U << BitPos)) {
+ if (!NewStr.empty())
+ NewStr.append("+");
+ NewStr.append(PriorityString[BitPos]);
+ }
+ }
+ }
+ } else if (Context.getTargetInfo().getTriple().isRISCV()) {
// Only support arch=+ext,... syntax.
if (AttrStr.starts_with("arch=+")) {
if (HasArch)
@@ -3307,51 +3339,46 @@ bool Sema::checkTargetVersionAttr(SourceLocation LiteralLoc, Decl *D,
}))
return Diag(LiteralLoc, diag::warn_unsupported_target_attribute)
<< Unsupported << None << AttrStr << TargetVersion;
- } else if (AttrStr.starts_with("default")) {
- if (HasDefault)
- DuplicateAttr = true;
- HasDefault = true;
- } else if (AttrStr.consume_front("priority=")) {
- if (HasPriority)
- DuplicateAttr = true;
- HasPriority = true;
- unsigned Digit;
- if (AttrStr.getAsInteger(0, Digit))
- return Diag(LiteralLoc, diag::warn_unsupported_target_attribute)
- << Unsupported << None << AttrStr << TargetVersion;
} else {
return Diag(LiteralLoc, diag::warn_unsupported_target_attribute)
<< Unsupported << None << AttrStr << TargetVersion;
}
+ } else if (Context.getTargetInfo().getTriple().isAArch64()) {
+ llvm::SmallVector<StringRef, 8> Features;
+ AttrStr.split(Features, "+");
+ for (StringRef Feat : Features) {
+ Feat = Feat.trim();
+ if (!Context.getTargetInfo().validateCpuSupports(Feat))
+ return Diag(LiteralLoc, diag::warn_unsupported_target_attribute)
+ << Unsupported << None << Feat << TargetVersion;
+ if (!NewStr.empty())
+ NewStr.append("+");
+ NewStr.append(Feat);
+ }
+ HasFeatures = !Features.empty();
}
+ }
- if (((HasPriority || HasArch) && HasDefault) || DuplicateAttr ||
- (HasPriority && !HasArch))
- return Diag(LiteralLoc, diag::warn_unsupported_target_attribute)
- << Unsupported << None << AttrStr << TargetVersion;
+ if ((HasDefault && (HasPriority || HasArch || HasFeatures)) ||
+ DuplicateAttr || (HasPriority && !HasArch && !HasFeatures))
+ return Diag(LiteralLoc, diag::warn_unsupported_target_attribute)
+ << Unsupported << None << AttrStr << TargetVersion;
+
+ if (Context.getTargetInfo().getTriple().isRISCV())
+ NewStr = AttrStr;
- return false;
- }
- AttrStr.split(Features, "+");
- for (auto &CurFeature : Features) {
- CurFeature = CurFeature.trim();
- if (CurFeature == "default")
- continue;
- if (!Context.getTargetInfo().validateCpuSupports(CurFeature))
- return Diag(LiteralLoc, diag::warn_unsupported_target_attribute)
- << Unsupported << None << CurFeature << TargetVersion;
- }
return false;
}
static void handleTargetVersionAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
StringRef Str;
+ SmallString<64> NewStr;
SourceLocation LiteralLoc;
if (!S.checkStringLiteralArgumentAttr(AL, 0, Str, &LiteralLoc) ||
- S.checkTargetVersionAttr(LiteralLoc, D, Str))
+ S.checkTargetVersionAttr(LiteralLoc, D, Str, NewStr))
return;
TargetVersionAttr *NewAttr =
- ::new (S.Context) TargetVersionAttr(S.Context, AL, Str);
+ ::new (S.Context) TargetVersionAttr(S.Context, AL, NewStr);
D->addAttr(NewAttr);
}
@@ -3368,7 +3395,7 @@ static void handleTargetAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
bool Sema::checkTargetClonesAttrString(
SourceLocation LiteralLoc, StringRef Str, const StringLiteral *Literal,
- Decl *D, bool &HasDefault, bool &HasCommas, bool &HasNotDefault,
+ Decl *D, bool &HasDefault, bool &HasCommas, bool &HasNonDefault,
SmallVectorImpl<SmallString<64>> &StringsBuffer) {
enum FirstParam { Unsupported, Duplicate, Unknown };
enum SecondParam { None, CPU, Tune };
@@ -3380,6 +3407,9 @@ bool Sema::checkTargetClonesAttrString(
return Diag(LiteralLoc, diag::warn_unsupported_target_attribute)
<< Unsupported << None << "" << TargetClones;
+ StringRef PriorityString[5] = {"priority5", "priority4", "priority3",
+ "priority2", "priority1"};
+
std::pair<StringRef, StringRef> Parts = {{}, Str};
while (!Parts.second.empty()) {
Parts = Parts.second.split(',');
@@ -3394,90 +3424,116 @@ bool Sema::checkTargetClonesAttrString(
return Diag(CurLoc, diag::warn_unsupported_target_attribute)
<< Unsupported << None << "" << TargetClones;
- if (TInfo.getTriple().isAArch64()) {
- // AArch64 target clones specific
- if (Cur == "default") {
+ if (TInfo.getTriple().isX86()) {
+ if (Cur.starts_with("arch=")) {
+ if (!Context.getTargetInfo().isValidCPUName(
+ Cur.drop_front(sizeof("arch=") - 1)))
+ return Diag(CurLoc, diag::warn_unsupported_target_attribute)
+ << Unsupported << CPU << Cur.drop_front(sizeof("arch=") - 1)
+ << TargetClones;
+ } else if (Cur == "default") {
DefaultIsDupe = HasDefault;
HasDefault = true;
- if (llvm::is_contained(StringsBuffer, Cur) || DefaultIsDupe)
- Diag(CurLoc, diag::warn_target_clone_duplicate_options);
- else
- StringsBuffer.push_back(Cur);
- } else {
- std::pair<StringRef, StringRef> CurParts = {{}, Cur};
- llvm::SmallVector<StringRef, 8> CurFeatures;
- while (!CurParts.second.empty()) {
- CurParts = CurParts.second.split('+');
- StringRef CurFeature = CurParts.first.trim();
- if (!TInfo.validateCpuSupports(CurFeature)) {
- Diag(CurLoc, diag::warn_unsupported_target_attribute)
- << Unsupported << None << CurFeature << TargetClones;
- continue;
- }
- if (TInfo.doesFeatureAffectCodeGen(CurFeature))
- HasCodeGenImpact = true;
- CurFeatures.push_back(CurFeature);
- }
- // Canonize TargetClones Attributes
- llvm::sort(CurFeatures);
- SmallString<64> Res;
- for (auto &CurFeat : CurFeatures) {
- if (!Res.empty())
- Res.append("+");
- Res.append(CurFeat);
- }
- if (llvm::is_contained(StringsBuffer, Res) || DefaultIsDupe)
- Diag(CurLoc, diag::warn_target_clone_duplicate_options);
- else if (!HasCodeGenImpact)
- // Ignore features in target_clone attribute that don't impact
- // code generation
- Diag(CurLoc, diag::warn_target_clone_no_impact_options);
- else if (!Res.empty()) {
- StringsBuffer.push_back(Res);
- HasNotDefault = true;
- }
+ } else if (!Context.getTargetInfo().isValidFeatureName(Cur) ||
+ Context.getTargetInfo().getFMVPriority(Cur) == 0)
+ return Diag(CurLoc, diag::warn_unsupported_target_attribute)
+ << Unsupported << None << Cur << TargetClones;
+ if (llvm::is_contained(StringsBuffer, Cur) || DefaultIsDupe)
+ Diag(CurLoc, diag::warn_target_clone_duplicate_options);
+ // Note: Add even if there are duplicates, since it changes name mangling.
+ StringsBuffer.push_back(Cur);
+ } else {
+ // Other targets ( currently AArch64 and RISC-V )
+ if (TInfo.getTriple().isRISCV()) {
+ // Suppress warn_target_clone_mixed_values
+ HasCommas = false;
+
+ // Cur is split's parts of Str. RISC-V uses Str directly,
+ // so skip when encountered more than once.
+ if (!Str.starts_with(Cur))
+ continue;
}
- } else if (TInfo.getTriple().isRISCV()) {
- // Suppress warn_target_clone_mixed_values
- HasCommas = false;
-
- // Cur is split's parts of Str. RISC-V uses Str directly,
- // so skip when encountered more than once.
- if (!Str.starts_with(Cur))
- continue;
-
+ SmallString<64> NewStr;
llvm::SmallVector<StringRef, 8> AttrStrs;
Str.split(AttrStrs, ";");
bool IsPriority = false;
bool IsDefault = false;
- for (auto &AttrStr : AttrStrs) {
- // Only support arch=+ext,... syntax.
- if (AttrStr.starts_with("arch=+")) {
- ParsedTargetAttr TargetAttr =
- Context.getTargetInfo().parseTargetAttr(AttrStr);
-
- if (TargetAttr.Features.empty() ||
- llvm::any_of(TargetAttr.Features, [&](const StringRef Ext) {
- return !RISCV().isValidFMVExtension(Ext);
- }))
- return Diag(CurLoc, diag::warn_unsupported_target_attribute)
- << Unsupported << None << Str << TargetClones;
- } else if (AttrStr.starts_with("default")) {
+ for (StringRef AttrStr : AttrStrs) {
+ AttrStr = AttrStr.trim();
+ if (AttrStr == "default") {
IsDefault = true;
DefaultIsDupe = HasDefault;
HasDefault = true;
+ if (TInfo.getTriple().isAArch64())
+ NewStr.append(AttrStr);
} else if (AttrStr.consume_front("priority=")) {
IsPriority = true;
unsigned Digit;
if (AttrStr.getAsInteger(0, Digit))
return Diag(CurLoc, diag::warn_unsupported_target_attribute)
<< Unsupported << None << Str << TargetClones;
- } else {
- return Diag(CurLoc, diag::warn_unsupported_target_attribute)
- << Unsupported << None << Str << TargetClones;
+ if (TInfo.getTriple().isAArch64()) {
+ if (Digit < 1 || Digit > 32)
+ return Diag(CurLoc, diag::warn_unsupported_target_attribute)
+ << Unsupported << None << Str << TargetClones;
+ // Convert priority=[1-32] -> priority1 + ... + priority5
+ for (int BitPos = 4; BitPos >= 0; --BitPos) {
+ if ((32 - Digit) & (1U << BitPos)) {
+ if (!NewStr.empty())
+ NewStr.append("+");
+ NewStr.append(PriorityString[BitPos]);
+ }
+ }
+ }
+ } else if (TInfo.getTriple().isRISCV()) {
+ // Only support arch=+ext,... syntax.
+ if (AttrStr.starts_with("arch=+")) {
+ ParsedTargetAttr TargetAttr =
+ Context.getTargetInfo().parseTargetAttr(AttrStr);
+
+ if (TargetAttr.Features.empty() ||
+ llvm::any_of(TargetAttr.Features, [&](const StringRef Ext) {
+ return !RISCV().isValidFMVExtension(Ext);
+ }))
+ return Diag(CurLoc, diag::warn_unsupported_target_attribute)
+ << Unsupported << None << Str << TargetClones;
+ } else {
+ return Diag(CurLoc, diag::warn_unsupported_target_attribute)
+ << Unsupported << None << Str << TargetClones;
+ }
+ } else if (TInfo.getTriple().isAArch64()) {
+ llvm::SmallVector<StringRef, 8> Features;
+ llvm::SmallVector<StringRef, 8> ValidFeatures;
+ AttrStr.split(Features, "+");
+ for (StringRef Feat : Features) {
+ Feat = Feat.trim();
+ if (!TInfo.validateCpuSupports(Feat)) {
+ Diag(CurLoc, diag::warn_unsupported_target_attribute)
+ << Unsupported << None << Feat << TargetClones;
+ continue;
+ }
+ if (TInfo.doesFeatureAffectCodeGen(Feat))
+ HasCodeGenImpact = true;
+ ValidFeatures.push_back(Feat);
+ }
+ HasNonDefault = !ValidFeatures.empty();
+ // Ignore features in target_clone attribute that don't impact
+ // code generation
+ if (!HasCodeGenImpact)
+ Diag(CurLoc, diag::warn_target_clone_no_impact_options);
+
+ // Canonize TargetClones Attributes
+ llvm::sort(ValidFeatures);
+ for (StringRef Feat : ValidFeatures) {
+ if (!NewStr.empty())
+ NewStr.append("+");
+ NewStr.append(Feat);
+ }
}
}
+ if (TInfo.getTriple().isAArch64())
+ Str = NewStr;
if (IsPriority && IsDefault)
return Diag(CurLoc, diag::warn_unsupported_target_attribute)
@@ -3486,25 +3542,6 @@ bool Sema::checkTargetClonesAttrString(
if (llvm::is_contained(StringsBuffer, Str) || DefaultIsDupe)
Diag(CurLoc, diag::warn_target_clone_duplicate_options);
StringsBuffer.push_back(Str);
- } else {
- // Other targets ( currently X86 )
- if (Cur.starts_with("arch=")) {
- if (!Context.getTargetInfo().isValidCPUName(
- Cur.drop_front(sizeof("arch=") - 1)))
- return Diag(CurLoc, diag::warn_unsupported_target_attribute)
- << Unsupported << CPU << Cur.drop_front(sizeof("arch=") - 1)
- << TargetClones;
- } else if (Cur == "default") {
- DefaultIsDupe = HasDefault;
- HasDefault = true;
- } else if (!Context.getTargetInfo().isValidFeatureName(Cur) ||
- Context.getTargetInfo().getFMVPriority(Cur) == 0)
- return Diag(CurLoc, diag::warn_unsupported_target_attribute)
- << Unsupported << None << Cur << TargetClones;
- if (llvm::is_contained(StringsBuffer, Cur) || DefaultIsDupe)
- Diag(CurLoc, diag::warn_target_clone_duplicate_options);
- // Note: Add even if there are duplicates, since it changes name mangling.
- StringsBuffer.push_back(Cur);
}
}
if (Str.rtrim().ends_with(","))
@@ -3530,7 +3567,7 @@ static void handleTargetClonesAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
SmallVector<StringRef, 2> Strings;
SmallVector<SmallString<64>, 2> StringsBuffer;
- bool HasCommas = false, HasDefault = false, HasNotDefault = false;
+ bool HasCommas = false, HasDefault = false, HasNonDefault = false;
for (unsigned I = 0, E = AL.getNumArgs(); I != E; ++I) {
StringRef CurStr;
@@ -3539,7 +3576,7 @@ static void handleTargetClonesAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
S.checkTargetClonesAttrString(
LiteralLoc, CurStr,
cast<StringLiteral>(AL.getArgAsExpr(I)->IgnoreParenCasts()), D,
- HasDefault, HasCommas, HasNotDefault, StringsBuffer))
+ HasDefault, HasCommas, HasNonDefault, StringsBuffer))
return;
}
for (auto &SmallStr : StringsBuffer)
@@ -3565,7 +3602,7 @@ static void handleTargetClonesAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
}
// No multiversion if we have default version only.
- if (S.Context.getTargetInfo().getTriple().isAArch64() && !HasNotDefault)
+ if (S.Context.getTargetInfo().getTriple().isAArch64() && !HasNonDefault)
return;
cast<FunctionDecl>(D)->setIsMultiVersion();
diff --git a/clang/test/AST/attr-target-version.c b/clang/test/AST/attr-target-version.c
index b537f5e685a31..adaef66193dee 100644
--- a/clang/test/AST/attr-target-version.c
+++ b/clang/test/AST/attr-target-version.c
@@ -2,7 +2,78 @@
int __attribute__((target_version("sve2-bitperm + sha2"))) foov(void) { return 1; }
int __attribute__((target_clones(" lse + fp + sha3 ", "default"))) fooc(void) { return 2; }
-// CHECK: TargetVersionAttr
-// CHECK: sve2-bitperm + sha2
+
+int __attribute__((target_version("priority=1;aes"))) explicit_priority(void) { return 1; }
+int __attribute__((target_version("priority=2;bf16"))) explicit_priority(void) { return 2; }
+int __attribute__((target_version("priority=3;bti"))) explicit_priority(void) { return 3; }
+int __attribute__((target_version("priority=4;crc"))) explicit_priority(void) { return 4; }
+int __attribute__((target_version("priority=5;dit"))) explicit_priority(void) { return 5; }
+int __attribute__((target_version("priority=6;dotprod"))) explicit_priority(void) { return 6; }
+int __attribute__((target_version("priority=7;dpb"))) explicit_priority(void) { return 7; }
+int __attribute__((target_version("priority=8;dpb2"))) explicit_priority(void) { return 8; }
+int __attribute__((target_version("f32mm;priority=9"))) explicit_priority(void) { return 9; }
+int __attribute__((target_version("f64mm;priority=10"))) explicit_priority(void) { return 10; }
+int __attribute__((target_version("fcma;priority=11"))) explicit_priority(void) { return 11; }
+int __attribute__((target_version("flagm;priority=12"))) explicit_priority(void) { return 12; }
+int __attribute__((target_version("flagm2;priority=13"))) explicit_priority(void) { return 13; }
+int __attribute__((target_version("fp;priority=14"))) explicit_priority(void) { return 14; }
+int __attribute__((target_version("fp16;priority=15"))) explicit_priority(vo...
[truncated]
|
✅ With the latest revision this PR passed the C/C++ code formatter. |
This allows the user to specify "priority=[1-32];featA+featB"
where priority=1 means highest priority. If the explicit
priority string is omitted then the priority of "featA+featB"
is implied, which is lower than priority=32.
Depends on #146092.