Skip to content

Commit 9ee1523

Browse files
committed
[FMV][AArch64] Allow user to override version priority.
Implements ARM-software/acle#404 This allows the user to specify "priority=[1-32];featA+featB" where priority=31 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 ... P5 which can encode up to 31 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 d449d3d commit 9ee1523

23 files changed

+414
-51
lines changed

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12747,6 +12747,12 @@ def warn_target_clone_duplicate_options
1274712747
def warn_target_clone_no_impact_options
1274812748
: Warning<"version list contains entries that don't impact code generation">,
1274912749
InGroup<FunctionMultiVersioning>;
12750+
def warn_version_priority_out_of_range
12751+
: Warning<"version priority '%0' is outside the allowed range [1-31]; ignoring priority">,
12752+
InGroup<FunctionMultiVersioning>;
12753+
def warn_invalid_default_version_priority
12754+
: Warning<"priority of default version cannot be overridden; ignoring priority">,
12755+
InGroup<FunctionMultiVersioning>;
1275012756

1275112757
// three-way comparison operator diagnostics
1275212758
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
@@ -1337,9 +1337,10 @@ void AArch64ABIInfo::appendAttributeMangling(StringRef AttrStr,
13371337

13381338
llvm::SmallDenseSet<StringRef, 8> UniqueFeats;
13391339
for (auto &Feat : Features)
1340-
if (auto Ext = llvm::AArch64::parseFMVExtension(Feat))
1341-
if (UniqueFeats.insert(Ext->Name).second)
1342-
Out << 'M' << Ext->Name;
1340+
if (getTarget().doesFeatureAffectCodeGen(Feat))
1341+
if (auto Ext = llvm::AArch64::parseFMVExtension(Feat))
1342+
if (UniqueFeats.insert(Ext->Name).second)
1343+
Out << 'M' << Ext->Name;
13431344
}
13441345

13451346
std::unique_ptr<TargetCodeGenInfo>

clang/lib/Sema/SemaARM.cpp

Lines changed: 54 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1535,19 +1535,52 @@ bool SemaARM::areLaxCompatibleSveTypes(QualType FirstType,
15351535
IsLaxCompatible(SecondType, FirstType);
15361536
}
15371537

1538+
static void appendFeature(StringRef Feat, SmallString<64> &Buffer) {
1539+
if (!Buffer.empty())
1540+
Buffer.append("+");
1541+
Buffer.append(Feat);
1542+
}
1543+
1544+
static void convertPriorityString(unsigned Priority,
1545+
SmallString<64> &NewParam) {
1546+
StringRef PriorityString[5] = {"P0", "P1", "P2", "P3", "P4"};
1547+
1548+
assert(Priority > 0 && Priority < 32 && "priority out of range");
1549+
// Convert priority=[1-31] -> P0 + ... + P4
1550+
for (unsigned BitPos = 0; BitPos < 5; ++BitPos)
1551+
if (Priority & (1U << BitPos))
1552+
appendFeature(PriorityString[BitPos], NewParam);
1553+
}
1554+
15381555
bool SemaARM::checkTargetVersionAttr(const StringRef Param,
1539-
const SourceLocation Loc) {
1556+
const SourceLocation Loc,
1557+
SmallString<64> &NewParam) {
15401558
using namespace DiagAttrParams;
15411559

1560+
auto [LHS, RHS] = Param.split(';');
1561+
bool IsDefault = false;
15421562
llvm::SmallVector<StringRef, 8> Features;
1543-
Param.split(Features, '+');
1563+
LHS.split(Features, '+');
15441564
for (StringRef Feat : Features) {
15451565
Feat = Feat.trim();
15461566
if (Feat == "default")
1547-
continue;
1548-
if (!getASTContext().getTargetInfo().validateCpuSupports(Feat))
1567+
IsDefault = true;
1568+
else if (!getASTContext().getTargetInfo().validateCpuSupports(Feat))
15491569
return Diag(Loc, diag::warn_unsupported_target_attribute)
15501570
<< Unsupported << None << Feat << TargetVersion;
1571+
appendFeature(Feat, NewParam);
1572+
}
1573+
1574+
if (!RHS.empty() && RHS.consume_front("priority=")) {
1575+
if (IsDefault)
1576+
Diag(Loc, diag::warn_invalid_default_version_priority);
1577+
else {
1578+
unsigned Digit;
1579+
if (RHS.getAsInteger(0, Digit) || Digit < 1 || Digit > 31)
1580+
Diag(Loc, diag::warn_version_priority_out_of_range) << RHS;
1581+
else
1582+
convertPriorityString(Digit, NewParam);
1583+
}
15511584
}
15521585
return false;
15531586
}
@@ -1569,15 +1602,20 @@ bool SemaARM::checkTargetClonesAttr(
15691602
const StringRef Param = Params[I].trim();
15701603
const SourceLocation &Loc = Locs[I];
15711604

1572-
if (Param.empty())
1605+
auto [LHS, RHS] = Param.split(';');
1606+
bool HasPriority = !RHS.empty() && RHS.consume_front("priority=");
1607+
1608+
if (LHS.empty())
15731609
return Diag(Loc, diag::warn_unsupported_target_attribute)
15741610
<< Unsupported << None << "" << TargetClones;
15751611

1576-
if (Param == "default") {
1612+
if (LHS == "default") {
15771613
if (HasDefault)
15781614
Diag(Loc, diag::warn_target_clone_duplicate_options);
15791615
else {
1580-
NewParams.push_back(Param);
1616+
if (HasPriority)
1617+
Diag(Loc, diag::warn_invalid_default_version_priority);
1618+
NewParams.push_back(LHS);
15811619
HasDefault = true;
15821620
}
15831621
continue;
@@ -1586,7 +1624,7 @@ bool SemaARM::checkTargetClonesAttr(
15861624
bool HasCodeGenImpact = false;
15871625
llvm::SmallVector<StringRef, 8> Features;
15881626
llvm::SmallVector<StringRef, 8> ValidFeatures;
1589-
Param.split(Features, '+');
1627+
LHS.split(Features, '+');
15901628
for (StringRef Feat : Features) {
15911629
Feat = Feat.trim();
15921630
if (!getASTContext().getTargetInfo().validateCpuSupports(Feat)) {
@@ -1616,6 +1654,14 @@ bool SemaARM::checkTargetClonesAttr(
16161654
continue;
16171655
}
16181656

1657+
if (HasPriority) {
1658+
unsigned Digit;
1659+
if (RHS.getAsInteger(0, Digit) || Digit < 1 || Digit > 31)
1660+
Diag(Loc, diag::warn_version_priority_out_of_range) << RHS;
1661+
else
1662+
convertPriorityString(Digit, NewParam);
1663+
}
1664+
16191665
// Valid non-default argument.
16201666
NewParams.push_back(NewParam);
16211667
HasNonDefault = true;

clang/lib/Sema/SemaDeclAttr.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3333,19 +3333,20 @@ bool Sema::checkTargetAttr(SourceLocation LiteralLoc, StringRef AttrStr) {
33333333
static void handleTargetVersionAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
33343334
StringRef Param;
33353335
SourceLocation Loc;
3336+
SmallString<64> NewParam;
33363337
if (!S.checkStringLiteralArgumentAttr(AL, 0, Param, &Loc))
33373338
return;
33383339

33393340
if (S.Context.getTargetInfo().getTriple().isAArch64()) {
3340-
if (S.ARM().checkTargetVersionAttr(Param, Loc))
3341+
if (S.ARM().checkTargetVersionAttr(Param, Loc, NewParam))
33413342
return;
33423343
} else if (S.Context.getTargetInfo().getTriple().isRISCV()) {
3343-
if (S.RISCV().checkTargetVersionAttr(Param, Loc))
3344+
if (S.RISCV().checkTargetVersionAttr(Param, Loc, NewParam))
33443345
return;
33453346
}
33463347

33473348
TargetVersionAttr *NewAttr =
3348-
::new (S.Context) TargetVersionAttr(S.Context, AL, Param);
3349+
::new (S.Context) TargetVersionAttr(S.Context, AL, NewParam);
33493350
D->addAttr(NewAttr);
33503351
}
33513352

clang/lib/Sema/SemaRISCV.cpp

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

16381638
bool SemaRISCV::checkTargetVersionAttr(const StringRef Param,
1639-
const SourceLocation Loc) {
1639+
const SourceLocation Loc,
1640+
SmallString<64> &NewParam) {
16401641
using namespace DiagAttrParams;
16411642

16421643
llvm::SmallVector<StringRef, 8> AttrStrs;
@@ -1682,6 +1683,7 @@ bool SemaRISCV::checkTargetVersionAttr(const StringRef Param,
16821683
return Diag(Loc, diag::warn_unsupported_target_attribute)
16831684
<< Unsupported << None << Param << TargetVersion;
16841685

1686+
NewParam = Param;
16851687
return false;
16861688
}
16871689

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

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,23 @@
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+
12+
int __attribute__((target_clones("simd;priority=31", "default"))) explicit_priority(void) {
13+
return 0;
14+
}
15+
16+
// CHECK: TargetVersionAttr {{.*}} "sve2-bitperm+sha2"
17+
// CHECK: TargetClonesAttr {{.*}} fp+lse+sha3 default
18+
19+
// CHECK: TargetVersionAttr {{.*}} "aes+P0"
20+
// CHECK: TargetVersionAttr {{.*}} "bf16+P1"
21+
// CHECK: TargetVersionAttr {{.*}} "crc+P2"
22+
// CHECK: TargetVersionAttr {{.*}} "dpb2+P3"
23+
// CHECK: TargetVersionAttr {{.*}} "fp16fml+P4"
24+
// CHECK: TargetClonesAttr {{.*}} simd+P0+P1+P2+P3+P4 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)