Skip to content

Commit 1b82c16

Browse files
authored
[FMV][AArch64] Allow user to override version priority. (#150267)
Implements ARM-software/acle#404 This allows the user to specify "featA+featB;priority=[1-255]" where priority=255 means highest priority. If the explicit priority string is omitted then the priority of "featA+featB" is implied, which is lower than priority=1. Internally this gets expanded using special FMV features P0 ... P7 which can encode up to 256-1 priority levels (excluding all zeros). Those do not have corresponding detection bit at pos FEAT_#enum so I made this field optional in FMVInfo. Also they don't affect the codegen or name mangling of versioned functions.
1 parent 719d079 commit 1b82c16

File tree

24 files changed

+508
-48
lines changed

24 files changed

+508
-48
lines changed

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12945,6 +12945,12 @@ def warn_target_clone_duplicate_options
1294512945
def warn_target_clone_no_impact_options
1294612946
: Warning<"version list contains entries that don't impact code generation">,
1294712947
InGroup<FunctionMultiVersioning>;
12948+
def warn_version_priority_out_of_range
12949+
: Warning<"version priority '%0' is outside the allowed range [1-255]; ignoring priority">,
12950+
InGroup<FunctionMultiVersioning>;
12951+
def warn_invalid_default_version_priority
12952+
: Warning<"priority of default version cannot be overridden; ignoring priority">,
12953+
InGroup<FunctionMultiVersioning>;
1294812954

1294912955
// three-way comparison operator diagnostics
1295012956
def err_implied_comparison_category_type_not_found : Error<

clang/include/clang/Sema/SemaARM.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,8 @@ class SemaARM : public SemaBase {
9292
/// false otherwise.
9393
bool areLaxCompatibleSveTypes(QualType FirstType, QualType SecondType);
9494

95-
bool checkTargetVersionAttr(const StringRef Str, const SourceLocation Loc);
95+
bool checkTargetVersionAttr(const StringRef Param, const SourceLocation Loc,
96+
SmallString<64> &NewParam);
9697
bool checkTargetClonesAttr(SmallVectorImpl<StringRef> &Params,
9798
SmallVectorImpl<SourceLocation> &Locs,
9899
SmallVectorImpl<SmallString<64>> &NewParams);

clang/include/clang/Sema/SemaRISCV.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,8 @@ class SemaRISCV : public SemaBase {
5656

5757
std::unique_ptr<sema::RISCVIntrinsicManager> IntrinsicManager;
5858

59-
bool checkTargetVersionAttr(const StringRef Param, const SourceLocation Loc);
59+
bool checkTargetVersionAttr(const StringRef Param, const SourceLocation Loc,
60+
SmallString<64> &NewParam);
6061
bool checkTargetClonesAttr(SmallVectorImpl<StringRef> &Params,
6162
SmallVectorImpl<SourceLocation> &Locs,
6263
SmallVectorImpl<SmallString<64>> &NewParams);

clang/lib/CodeGen/Targets/AArch64.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1359,9 +1359,10 @@ void AArch64ABIInfo::appendAttributeMangling(StringRef AttrStr,
13591359

13601360
llvm::SmallDenseSet<StringRef, 8> UniqueFeats;
13611361
for (auto &Feat : Features)
1362-
if (auto Ext = llvm::AArch64::parseFMVExtension(Feat))
1363-
if (UniqueFeats.insert(Ext->Name).second)
1364-
Out << 'M' << Ext->Name;
1362+
if (getTarget().doesFeatureAffectCodeGen(Feat))
1363+
if (auto Ext = llvm::AArch64::parseFMVExtension(Feat))
1364+
if (UniqueFeats.insert(Ext->Name).second)
1365+
Out << 'M' << Ext->Name;
13651366
}
13661367

13671368
std::unique_ptr<TargetCodeGenInfo>

clang/lib/Sema/SemaARM.cpp

Lines changed: 57 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1593,19 +1593,54 @@ bool SemaARM::areLaxCompatibleSveTypes(QualType FirstType,
15931593
IsLaxCompatible(SecondType, FirstType);
15941594
}
15951595

1596+
static void appendFeature(StringRef Feat, SmallString<64> &Buffer) {
1597+
if (!Buffer.empty())
1598+
Buffer.append("+");
1599+
Buffer.append(Feat);
1600+
}
1601+
1602+
static void convertPriorityString(unsigned Priority,
1603+
SmallString<64> &NewParam) {
1604+
StringRef PriorityString[8] = {"P0", "P1", "P2", "P3",
1605+
"P4", "P5", "P6", "P7"};
1606+
1607+
assert(Priority > 0 && Priority < 256 && "priority out of range");
1608+
// Convert priority=[1-255] -> P0 + ... + P7
1609+
for (unsigned BitPos = 0; BitPos < 8; ++BitPos)
1610+
if (Priority & (1U << BitPos))
1611+
appendFeature(PriorityString[BitPos], NewParam);
1612+
}
1613+
15961614
bool SemaARM::checkTargetVersionAttr(const StringRef Param,
1597-
const SourceLocation Loc) {
1615+
const SourceLocation Loc,
1616+
SmallString<64> &NewParam) {
15981617
using namespace DiagAttrParams;
15991618

1619+
auto [LHS, RHS] = Param.split(';');
1620+
RHS = RHS.trim();
1621+
bool IsDefault = false;
16001622
llvm::SmallVector<StringRef, 8> Features;
1601-
Param.split(Features, '+');
1623+
LHS.split(Features, '+');
16021624
for (StringRef Feat : Features) {
16031625
Feat = Feat.trim();
16041626
if (Feat == "default")
1605-
continue;
1606-
if (!getASTContext().getTargetInfo().validateCpuSupports(Feat))
1627+
IsDefault = true;
1628+
else if (!getASTContext().getTargetInfo().validateCpuSupports(Feat))
16071629
return Diag(Loc, diag::warn_unsupported_target_attribute)
16081630
<< Unsupported << None << Feat << TargetVersion;
1631+
appendFeature(Feat, NewParam);
1632+
}
1633+
1634+
if (!RHS.empty() && RHS.consume_front("priority=")) {
1635+
if (IsDefault)
1636+
Diag(Loc, diag::warn_invalid_default_version_priority);
1637+
else {
1638+
unsigned Digit;
1639+
if (RHS.getAsInteger(0, Digit) || Digit < 1 || Digit > 255)
1640+
Diag(Loc, diag::warn_version_priority_out_of_range) << RHS;
1641+
else
1642+
convertPriorityString(Digit, NewParam);
1643+
}
16091644
}
16101645
return false;
16111646
}
@@ -1627,15 +1662,21 @@ bool SemaARM::checkTargetClonesAttr(
16271662
const StringRef Param = Params[I].trim();
16281663
const SourceLocation &Loc = Locs[I];
16291664

1630-
if (Param.empty())
1665+
auto [LHS, RHS] = Param.split(';');
1666+
RHS = RHS.trim();
1667+
bool HasPriority = !RHS.empty() && RHS.consume_front("priority=");
1668+
1669+
if (LHS.empty())
16311670
return Diag(Loc, diag::warn_unsupported_target_attribute)
16321671
<< Unsupported << None << "" << TargetClones;
16331672

1634-
if (Param == "default") {
1673+
if (LHS == "default") {
16351674
if (HasDefault)
16361675
Diag(Loc, diag::warn_target_clone_duplicate_options);
16371676
else {
1638-
NewParams.push_back(Param);
1677+
if (HasPriority)
1678+
Diag(Loc, diag::warn_invalid_default_version_priority);
1679+
NewParams.push_back(LHS);
16391680
HasDefault = true;
16401681
}
16411682
continue;
@@ -1644,7 +1685,7 @@ bool SemaARM::checkTargetClonesAttr(
16441685
bool HasCodeGenImpact = false;
16451686
llvm::SmallVector<StringRef, 8> Features;
16461687
llvm::SmallVector<StringRef, 8> ValidFeatures;
1647-
Param.split(Features, '+');
1688+
LHS.split(Features, '+');
16481689
for (StringRef Feat : Features) {
16491690
Feat = Feat.trim();
16501691
if (!getASTContext().getTargetInfo().validateCpuSupports(Feat)) {
@@ -1674,6 +1715,14 @@ bool SemaARM::checkTargetClonesAttr(
16741715
continue;
16751716
}
16761717

1718+
if (HasPriority) {
1719+
unsigned Digit;
1720+
if (RHS.getAsInteger(0, Digit) || Digit < 1 || Digit > 255)
1721+
Diag(Loc, diag::warn_version_priority_out_of_range) << RHS;
1722+
else
1723+
convertPriorityString(Digit, NewParam);
1724+
}
1725+
16771726
// Valid non-default argument.
16781727
NewParams.push_back(NewParam);
16791728
HasNonDefault = true;

clang/lib/Sema/SemaDeclAttr.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3445,19 +3445,20 @@ bool Sema::checkTargetAttr(SourceLocation LiteralLoc, StringRef AttrStr) {
34453445
static void handleTargetVersionAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
34463446
StringRef Param;
34473447
SourceLocation Loc;
3448+
SmallString<64> NewParam;
34483449
if (!S.checkStringLiteralArgumentAttr(AL, 0, Param, &Loc))
34493450
return;
34503451

34513452
if (S.Context.getTargetInfo().getTriple().isAArch64()) {
3452-
if (S.ARM().checkTargetVersionAttr(Param, Loc))
3453+
if (S.ARM().checkTargetVersionAttr(Param, Loc, NewParam))
34533454
return;
34543455
} else if (S.Context.getTargetInfo().getTriple().isRISCV()) {
3455-
if (S.RISCV().checkTargetVersionAttr(Param, Loc))
3456+
if (S.RISCV().checkTargetVersionAttr(Param, Loc, NewParam))
34563457
return;
34573458
}
34583459

34593460
TargetVersionAttr *NewAttr =
3460-
::new (S.Context) TargetVersionAttr(S.Context, AL, Param);
3461+
::new (S.Context) TargetVersionAttr(S.Context, AL, NewParam);
34613462
D->addAttr(NewAttr);
34623463
}
34633464

clang/lib/Sema/SemaRISCV.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1739,7 +1739,8 @@ bool SemaRISCV::isValidFMVExtension(StringRef Ext) {
17391739
}
17401740

17411741
bool SemaRISCV::checkTargetVersionAttr(const StringRef Param,
1742-
const SourceLocation Loc) {
1742+
const SourceLocation Loc,
1743+
SmallString<64> &NewParam) {
17431744
using namespace DiagAttrParams;
17441745

17451746
llvm::SmallVector<StringRef, 8> AttrStrs;
@@ -1785,6 +1786,7 @@ bool SemaRISCV::checkTargetVersionAttr(const StringRef Param,
17851786
return Diag(Loc, diag::warn_unsupported_target_attribute)
17861787
<< Unsupported << None << Param << TargetVersion;
17871788

1789+
NewParam = Param;
17881790
return false;
17891791
}
17901792

clang/test/AST/attr-target-version.c

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,29 @@
22

33
int __attribute__((target_version("sve2-bitperm + sha2"))) foov(void) { return 1; }
44
int __attribute__((target_clones(" lse + fp + sha3 ", "default"))) fooc(void) { return 2; }
5-
// CHECK: TargetVersionAttr
6-
// CHECK: sve2-bitperm + sha2
7-
// CHECK: TargetClonesAttr
8-
// CHECK: fp+lse+sha3 default
5+
6+
int __attribute__((target_version("aes;priority=1"))) explicit_priority(void) { return 1; }
7+
int __attribute__((target_version("bf16;priority=2"))) explicit_priority(void) { return 2; }
8+
int __attribute__((target_version("crc;priority=4"))) explicit_priority(void) { return 4; }
9+
int __attribute__((target_version("dpb2;priority=8"))) explicit_priority(void) { return 8; }
10+
int __attribute__((target_version("fp16fml;priority=16"))) explicit_priority(void) { return 16; }
11+
int __attribute__((target_version("dotprod;priority=32"))) explicit_priority(void) { return 32; }
12+
int __attribute__((target_version("sve;priority=64"))) explicit_priority(void) { return 64; }
13+
int __attribute__((target_version("mops;priority=128"))) explicit_priority(void) { return 128; }
14+
15+
int __attribute__((target_clones("simd;priority=255", "default"))) explicit_priority(void) {
16+
return 0;
17+
}
18+
19+
// CHECK: TargetVersionAttr {{.*}} "sve2-bitperm+sha2"
20+
// CHECK: TargetClonesAttr {{.*}} fp+lse+sha3 default
21+
22+
// CHECK: TargetVersionAttr {{.*}} "aes+P0"
23+
// CHECK: TargetVersionAttr {{.*}} "bf16+P1"
24+
// CHECK: TargetVersionAttr {{.*}} "crc+P2"
25+
// CHECK: TargetVersionAttr {{.*}} "dpb2+P3"
26+
// CHECK: TargetVersionAttr {{.*}} "fp16fml+P4"
27+
// CHECK: TargetVersionAttr {{.*}} "dotprod+P5"
28+
// CHECK: TargetVersionAttr {{.*}} "sve+P6"
29+
// CHECK: TargetVersionAttr {{.*}} "mops+P7"
30+
// CHECK: TargetClonesAttr {{.*}} simd+P0+P1+P2+P3+P4+P5+P6+P7 default

clang/test/CodeGen/AArch64/fmv-duplicate-mangled-name.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
// RUN: %clang_cc1 -triple aarch64-linux-gnu -verify -emit-llvm-only %s -DCHECK_IMPLICIT_DEFAULT
22
// RUN: %clang_cc1 -triple aarch64-linux-gnu -verify -emit-llvm-only %s -DCHECK_EXPLICIT_DEFAULT
3+
// RUN: %clang_cc1 -triple aarch64-linux-gnu -verify -emit-llvm-only %s -DCHECK_EXPLICIT_VERSION_PRIORITY
4+
// RUN: %clang_cc1 -triple aarch64-linux-gnu -verify -emit-llvm-only %s -DCHECK_EXPLICIT_CLONES_PRIORITY
35

46
#if defined(CHECK_IMPLICIT_DEFAULT)
57

@@ -21,4 +23,18 @@ __attribute__((target_version("default"))) int explicit_default_bad(void) { retu
2123
// expected-note@-2 {{previous definition is here}}
2224
__attribute__((target_clones("aes", "lse", "default"))) int explicit_default_bad(void) { return 1; }
2325

26+
#elif defined(CHECK_EXPLICIT_VERSION_PRIORITY)
27+
28+
__attribute__((target_version("aes"))) int explicit_version_priority(void) { return 0; }
29+
// expected-error@+2 {{definition with same mangled name 'explicit_version_priority._Maes' as another definition}}
30+
// expected-note@-2 {{previous definition is here}}
31+
__attribute__((target_version("aes;priority=10"))) int explicit_version_priority(void) { return 1; }
32+
33+
#elif defined(CHECK_EXPLICIT_CLONES_PRIORITY)
34+
35+
__attribute__((target_version("aes;priority=20"))) int explicit_clones_priority(void) { return 0; }
36+
// expected-error@+2 {{definition with same mangled name 'explicit_clones_priority._Maes' as another definition}}
37+
// expected-note@-2 {{previous definition is here}}
38+
__attribute__((target_clones("aes;priority=5", "lse"))) int explicit_clones_priority(void) { return 1; }
39+
2440
#endif

0 commit comments

Comments
 (0)