Skip to content

Commit 0575957

Browse files
committed
[FMV][AArch64] Allow user to override version priority.
Implements ARM-software/acle#404 This allows the user to specify "priority=[1-255];featA+featB" 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 267f592 commit 0575957

23 files changed

+427
-51
lines changed

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12781,6 +12781,12 @@ def warn_target_clone_duplicate_options
1278112781
def warn_target_clone_no_impact_options
1278212782
: Warning<"version list contains entries that don't impact code generation">,
1278312783
InGroup<FunctionMultiVersioning>;
12784+
def warn_version_priority_out_of_range
12785+
: Warning<"version priority '%0' is outside the allowed range [1-255]; ignoring priority">,
12786+
InGroup<FunctionMultiVersioning>;
12787+
def warn_invalid_default_version_priority
12788+
: Warning<"priority of default version cannot be overridden; ignoring priority">,
12789+
InGroup<FunctionMultiVersioning>;
1278412790

1278512791
// three-way comparison operator diagnostics
1278612792
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
@@ -1338,9 +1338,10 @@ void AArch64ABIInfo::appendAttributeMangling(StringRef AttrStr,
13381338

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

13461347
std::unique_ptr<TargetCodeGenInfo>

clang/lib/Sema/SemaARM.cpp

Lines changed: 55 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1579,19 +1579,53 @@ bool SemaARM::areLaxCompatibleSveTypes(QualType FirstType,
15791579
IsLaxCompatible(SecondType, FirstType);
15801580
}
15811581

1582+
static void appendFeature(StringRef Feat, SmallString<64> &Buffer) {
1583+
if (!Buffer.empty())
1584+
Buffer.append("+");
1585+
Buffer.append(Feat);
1586+
}
1587+
1588+
static void convertPriorityString(unsigned Priority,
1589+
SmallString<64> &NewParam) {
1590+
StringRef PriorityString[8] = {"P0", "P1", "P2", "P3",
1591+
"P4", "P5", "P6", "P7"};
1592+
1593+
assert(Priority > 0 && Priority < 256 && "priority out of range");
1594+
// Convert priority=[1-31] -> P0 + ... + P4
1595+
for (unsigned BitPos = 0; BitPos < 8; ++BitPos)
1596+
if (Priority & (1U << BitPos))
1597+
appendFeature(PriorityString[BitPos], NewParam);
1598+
}
1599+
15821600
bool SemaARM::checkTargetVersionAttr(const StringRef Param,
1583-
const SourceLocation Loc) {
1601+
const SourceLocation Loc,
1602+
SmallString<64> &NewParam) {
15841603
using namespace DiagAttrParams;
15851604

1605+
auto [LHS, RHS] = Param.split(';');
1606+
bool IsDefault = false;
15861607
llvm::SmallVector<StringRef, 8> Features;
1587-
Param.split(Features, '+');
1608+
LHS.split(Features, '+');
15881609
for (StringRef Feat : Features) {
15891610
Feat = Feat.trim();
15901611
if (Feat == "default")
1591-
continue;
1592-
if (!getASTContext().getTargetInfo().validateCpuSupports(Feat))
1612+
IsDefault = true;
1613+
else if (!getASTContext().getTargetInfo().validateCpuSupports(Feat))
15931614
return Diag(Loc, diag::warn_unsupported_target_attribute)
15941615
<< Unsupported << None << Feat << TargetVersion;
1616+
appendFeature(Feat, NewParam);
1617+
}
1618+
1619+
if (!RHS.empty() && RHS.consume_front("priority=")) {
1620+
if (IsDefault)
1621+
Diag(Loc, diag::warn_invalid_default_version_priority);
1622+
else {
1623+
unsigned Digit;
1624+
if (RHS.getAsInteger(0, Digit) || Digit < 1 || Digit > 255)
1625+
Diag(Loc, diag::warn_version_priority_out_of_range) << RHS;
1626+
else
1627+
convertPriorityString(Digit, NewParam);
1628+
}
15951629
}
15961630
return false;
15971631
}
@@ -1613,15 +1647,20 @@ bool SemaARM::checkTargetClonesAttr(
16131647
const StringRef Param = Params[I].trim();
16141648
const SourceLocation &Loc = Locs[I];
16151649

1616-
if (Param.empty())
1650+
auto [LHS, RHS] = Param.split(';');
1651+
bool HasPriority = !RHS.empty() && RHS.consume_front("priority=");
1652+
1653+
if (LHS.empty())
16171654
return Diag(Loc, diag::warn_unsupported_target_attribute)
16181655
<< Unsupported << None << "" << TargetClones;
16191656

1620-
if (Param == "default") {
1657+
if (LHS == "default") {
16211658
if (HasDefault)
16221659
Diag(Loc, diag::warn_target_clone_duplicate_options);
16231660
else {
1624-
NewParams.push_back(Param);
1661+
if (HasPriority)
1662+
Diag(Loc, diag::warn_invalid_default_version_priority);
1663+
NewParams.push_back(LHS);
16251664
HasDefault = true;
16261665
}
16271666
continue;
@@ -1630,7 +1669,7 @@ bool SemaARM::checkTargetClonesAttr(
16301669
bool HasCodeGenImpact = false;
16311670
llvm::SmallVector<StringRef, 8> Features;
16321671
llvm::SmallVector<StringRef, 8> ValidFeatures;
1633-
Param.split(Features, '+');
1672+
LHS.split(Features, '+');
16341673
for (StringRef Feat : Features) {
16351674
Feat = Feat.trim();
16361675
if (!getASTContext().getTargetInfo().validateCpuSupports(Feat)) {
@@ -1660,6 +1699,14 @@ bool SemaARM::checkTargetClonesAttr(
16601699
continue;
16611700
}
16621701

1702+
if (HasPriority) {
1703+
unsigned Digit;
1704+
if (RHS.getAsInteger(0, Digit) || Digit < 1 || Digit > 255)
1705+
Diag(Loc, diag::warn_version_priority_out_of_range) << RHS;
1706+
else
1707+
convertPriorityString(Digit, NewParam);
1708+
}
1709+
16631710
// Valid non-default argument.
16641711
NewParams.push_back(NewParam);
16651712
HasNonDefault = true;

clang/lib/Sema/SemaDeclAttr.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3343,19 +3343,20 @@ bool Sema::checkTargetAttr(SourceLocation LiteralLoc, StringRef AttrStr) {
33433343
static void handleTargetVersionAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
33443344
StringRef Param;
33453345
SourceLocation Loc;
3346+
SmallString<64> NewParam;
33463347
if (!S.checkStringLiteralArgumentAttr(AL, 0, Param, &Loc))
33473348
return;
33483349

33493350
if (S.Context.getTargetInfo().getTriple().isAArch64()) {
3350-
if (S.ARM().checkTargetVersionAttr(Param, Loc))
3351+
if (S.ARM().checkTargetVersionAttr(Param, Loc, NewParam))
33513352
return;
33523353
} else if (S.Context.getTargetInfo().getTriple().isRISCV()) {
3353-
if (S.RISCV().checkTargetVersionAttr(Param, Loc))
3354+
if (S.RISCV().checkTargetVersionAttr(Param, Loc, NewParam))
33543355
return;
33553356
}
33563357

33573358
TargetVersionAttr *NewAttr =
3358-
::new (S.Context) TargetVersionAttr(S.Context, AL, Param);
3359+
::new (S.Context) TargetVersionAttr(S.Context, AL, NewParam);
33593360
D->addAttr(NewAttr);
33603361
}
33613362

clang/lib/Sema/SemaRISCV.cpp

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

16481648
bool SemaRISCV::checkTargetVersionAttr(const StringRef Param,
1649-
const SourceLocation Loc) {
1649+
const SourceLocation Loc,
1650+
SmallString<64> &NewParam) {
16501651
using namespace DiagAttrParams;
16511652

16521653
llvm::SmallVector<StringRef, 8> AttrStrs;
@@ -1692,6 +1693,7 @@ bool SemaRISCV::checkTargetVersionAttr(const StringRef Param,
16921693
return Diag(Loc, diag::warn_unsupported_target_attribute)
16931694
<< Unsupported << None << Param << TargetVersion;
16941695

1696+
NewParam = Param;
16951697
return false;
16961698
}
16971699

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)