Skip to content

Commit 09c0337

Browse files
[Clang][SveEmitter] Split up TargetGuard into SVE and SME component. (#96482)
One reason to want to split this up is to simplify the code added in #93802, where it checks the SME streaming-mode requirements for a builtin by checking for the absence of SVE. If the target guards are separate, we can generate a table and make the Sema code to verify the runtime mode simpler. Another reason is to avoid an issue with a check in SveEmitter.cpp where it ensures that the 'VerifyRuntimeMode' is set correctly for functions that have both SVE and SME target guards: if (!Def->isFlagSet(VerifyRuntimeMode) && Def->getGuard().contains("sve") && Def->getGuard().contains("sme")) llvm_unreachable("Missing VerifyRuntimeMode flag"); However, if we ever add a new feature with "sme" in the name, even though it is unrelated to FEAT_SME, then this code no longer works. Note that the arm_sve.td and arm_sme.td files could do with a bit of restructuring after this but it seems better to follow that up in an NFC patch.
1 parent 62baf21 commit 09c0337

File tree

6 files changed

+242
-221
lines changed

6 files changed

+242
-221
lines changed

clang/include/clang/Basic/arm_sme.td

Lines changed: 43 additions & 39 deletions
Large diffs are not rendered by default.

clang/include/clang/Basic/arm_sve.td

Lines changed: 109 additions & 122 deletions
Large diffs are not rendered by default.

clang/include/clang/Basic/arm_sve_sme_incl.td

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -267,12 +267,15 @@ class ImmCheck<int arg, ImmCheckType kind, int eltSizeArg = -1> {
267267
ImmCheckType Kind = kind;
268268
}
269269

270+
defvar InvalidMode = "";
271+
270272
class Inst<string n, string p, string t, MergeType mt, string i,
271273
list<FlagType> ft, list<ImmCheck> ch, MemEltType met = MemEltTyDefault> {
272274
string Name = n;
273275
string Prototype = p;
274276
string Types = t;
275-
string TargetGuard = "sve|sme";
277+
string SVETargetGuard = "sve";
278+
string SMETargetGuard = "sme";
276279
int Merge = mt.Value;
277280
string MergeSuffix = mt.Suffix;
278281
string LLVMIntrinsic = i;

clang/test/Sema/aarch64-sve-intrinsics/acle_sve_bfloat.cpp

Lines changed: 29 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -6,23 +6,23 @@
66

77
void test_bfloat(svbool_t pg, uint64_t u64, int64_t i64, const bfloat16_t *const_bf16_ptr, bfloat16_t *bf16_ptr, svbfloat16_t bf16, svbfloat16x2_t bf16x2, svbfloat16x3_t bf16x3, svbfloat16x4_t bf16x4)
88
{
9-
// expected-error@+1 {{'svcreate2_bf16' needs target feature (sve|sme),bf16}}
9+
// expected-error@+1 {{'svcreate2_bf16' needs target feature (sve,bf16)|(sme,bf16)}}
1010
svcreate2_bf16(bf16, bf16);
11-
// expected-error@+1 {{'svcreate3_bf16' needs target feature (sve|sme),bf16}}
11+
// expected-error@+1 {{'svcreate3_bf16' needs target feature (sve,bf16)|(sme,bf16)}}
1212
svcreate3_bf16(bf16, bf16, bf16);
13-
// expected-error@+1 {{'svcreate4_bf16' needs target feature (sve|sme),bf16}}
13+
// expected-error@+1 {{'svcreate4_bf16' needs target feature (sve,bf16)|(sme,bf16)}}
1414
svcreate4_bf16(bf16, bf16, bf16, bf16);
15-
// expected-error@+1 {{'svget2_bf16' needs target feature (sve|sme),bf16}}
15+
// expected-error@+1 {{'svget2_bf16' needs target feature (sve,bf16)|(sme,bf16)}}
1616
svget2_bf16(bf16x2, 1);
17-
// expected-error@+1 {{'svget3_bf16' needs target feature (sve|sme),bf16}}
17+
// expected-error@+1 {{'svget3_bf16' needs target feature (sve,bf16)|(sme,bf16)}}
1818
svget3_bf16(bf16x3, 1);
19-
// expected-error@+1 {{'svget4_bf16' needs target feature (sve|sme),bf16}}
19+
// expected-error@+1 {{'svget4_bf16' needs target feature (sve,bf16)|(sme,bf16)}}
2020
svget4_bf16(bf16x4, 1);
21-
// expected-error@+1 {{'svld1_bf16' needs target feature (sve|sme),bf16}}
21+
// expected-error@+1 {{'svld1_bf16' needs target feature (sve,bf16)|(sme,bf16)}}
2222
svld1_bf16(pg, const_bf16_ptr);
23-
// expected-error@+1 {{'svld1_vnum_bf16' needs target feature (sve|sme),bf16}}
23+
// expected-error@+1 {{'svld1_vnum_bf16' needs target feature (sve,bf16)|(sme,bf16)}}
2424
svld1_vnum_bf16(pg, const_bf16_ptr, i64);
25-
// expected-error@+1 {{'svld1rq_bf16' needs target feature (sve|sme),bf16}}
25+
// expected-error@+1 {{'svld1rq_bf16' needs target feature (sve,bf16)|(sme,bf16)}}
2626
svld1rq_bf16(pg, const_bf16_ptr);
2727
// expected-error@+1 {{'svldff1_bf16' needs target feature sve,bf16}}
2828
svldff1_bf16(pg, const_bf16_ptr);
@@ -32,55 +32,55 @@ void test_bfloat(svbool_t pg, uint64_t u64, int64_t i64, const bfloat16_t *const
3232
svldnf1_bf16(pg, const_bf16_ptr);
3333
// expected-error@+1 {{'svldnf1_vnum_bf16' needs target feature sve,bf16}}
3434
svldnf1_vnum_bf16(pg, const_bf16_ptr, i64);
35-
// expected-error@+1 {{'svldnt1_bf16' needs target feature (sve|sme),bf16}}
35+
// expected-error@+1 {{'svldnt1_bf16' needs target feature (sve,bf16)|(sme,bf16)}}
3636
svldnt1_bf16(pg, const_bf16_ptr);
37-
// expected-error@+1 {{'svldnt1_vnum_bf16' needs target feature (sve|sme),bf16}}
37+
// expected-error@+1 {{'svldnt1_vnum_bf16' needs target feature (sve,bf16)|(sme,bf16)}}
3838
svldnt1_vnum_bf16(pg, const_bf16_ptr, i64);
39-
// expected-error@+1 {{'svrev_bf16' needs target feature (sve|sme),bf16}}
39+
// expected-error@+1 {{'svrev_bf16' needs target feature (sve,bf16)|(sme,bf16)}}
4040
svrev_bf16(bf16);
41-
// expected-error@+1 {{'svset2_bf16' needs target feature (sve|sme),bf16}}
41+
// expected-error@+1 {{'svset2_bf16' needs target feature (sve,bf16)|(sme,bf16)}}
4242
svset2_bf16(bf16x2, 1, bf16);
43-
// expected-error@+1 {{'svset3_bf16' needs target feature (sve|sme),bf16}}
43+
// expected-error@+1 {{'svset3_bf16' needs target feature (sve,bf16)|(sme,bf16)}}
4444
svset3_bf16(bf16x3, 1, bf16);
45-
// expected-error@+1 {{'svset4_bf16' needs target feature (sve|sme),bf16}}
45+
// expected-error@+1 {{'svset4_bf16' needs target feature (sve,bf16)|(sme,bf16)}}
4646
svset4_bf16(bf16x4, 1, bf16);
47-
// expected-error@+1 {{'svst1_bf16' needs target feature (sve|sme),bf16}}
47+
// expected-error@+1 {{'svst1_bf16' needs target feature (sve,bf16)|(sme,bf16)}}
4848
svst1_bf16(pg, bf16_ptr, bf16);
49-
// expected-error@+1 {{'svst1_vnum_bf16' needs target feature (sve|sme),bf16}}
49+
// expected-error@+1 {{'svst1_vnum_bf16' needs target feature (sve,bf16)|(sme,bf16)}}
5050
svst1_vnum_bf16(pg, bf16_ptr, i64, bf16);
51-
// expected-error@+1 {{'svstnt1_bf16' needs target feature (sve|sme),bf16}}
51+
// expected-error@+1 {{'svstnt1_bf16' needs target feature (sve,bf16)|(sme,bf16)}}
5252
svstnt1_bf16(pg, bf16_ptr, bf16);
53-
// expected-error@+1 {{'svstnt1_vnum_bf16' needs target feature (sve|sme),bf16}}
53+
// expected-error@+1 {{'svstnt1_vnum_bf16' needs target feature (sve,bf16)|(sme,bf16)}}
5454
svstnt1_vnum_bf16(pg, bf16_ptr, i64, bf16);
55-
// expected-error@+1 {{'svtrn1_bf16' needs target feature (sve|sme),bf16}}
55+
// expected-error@+1 {{'svtrn1_bf16' needs target feature (sve,bf16)|(sme,bf16)}}
5656
svtrn1_bf16(bf16, bf16);
5757
// expected-error@+1 {{'svtrn1q_bf16' needs target feature sve,bf16}}
5858
svtrn1q_bf16(bf16, bf16);
59-
// expected-error@+1 {{'svtrn2_bf16' needs target feature (sve|sme),bf16}}
59+
// expected-error@+1 {{'svtrn2_bf16' needs target feature (sve,bf16)|(sme,bf16)}}
6060
svtrn2_bf16(bf16, bf16);
6161
// expected-error@+1 {{'svtrn2q_bf16' needs target feature sve,bf16}}
6262
svtrn2q_bf16(bf16, bf16);
63-
// expected-error@+1 {{'svundef_bf16' needs target feature (sve|sme),bf16}}
63+
// expected-error@+1 {{'svundef_bf16' needs target feature (sve,bf16)|(sme,bf16)}}
6464
svundef_bf16();
65-
// expected-error@+1 {{'svundef2_bf16' needs target feature (sve|sme),bf16}}
65+
// expected-error@+1 {{'svundef2_bf16' needs target feature (sve,bf16)|(sme,bf16)}}
6666
svundef2_bf16();
67-
// expected-error@+1 {{'svundef3_bf16' needs target feature (sve|sme),bf16}}
67+
// expected-error@+1 {{'svundef3_bf16' needs target feature (sve,bf16)|(sme,bf16)}}
6868
svundef3_bf16();
69-
// expected-error@+1 {{'svundef4_bf16' needs target feature (sve|sme),bf16}}
69+
// expected-error@+1 {{'svundef4_bf16' needs target feature (sve,bf16)|(sme,bf16)}}
7070
svundef4_bf16();
71-
// expected-error@+1 {{'svuzp1_bf16' needs target feature (sve|sme),bf16}}
71+
// expected-error@+1 {{'svuzp1_bf16' needs target feature (sve,bf16)|(sme,bf16)}}
7272
svuzp1_bf16(bf16, bf16);
7373
// expected-error@+1 {{'svuzp1q_bf16' needs target feature sve,bf16}}
7474
svuzp1q_bf16(bf16, bf16);
75-
// expected-error@+1 {{'svuzp2_bf16' needs target feature (sve|sme),bf16}}
75+
// expected-error@+1 {{'svuzp2_bf16' needs target feature (sve,bf16)|(sme,bf16)}}
7676
svuzp2_bf16(bf16, bf16);
7777
// expected-error@+1 {{'svuzp2q_bf16' needs target feature sve,bf16}}
7878
svuzp2q_bf16(bf16, bf16);
79-
// expected-error@+1 {{'svzip1_bf16' needs target feature (sve|sme),bf16}}
79+
// expected-error@+1 {{'svzip1_bf16' needs target feature (sve,bf16)|(sme,bf16)}}
8080
svzip1_bf16(bf16, bf16);
8181
// expected-error@+1 {{'svzip1q_bf16' needs target feature sve,bf16}}
8282
svzip1q_bf16(bf16, bf16);
83-
// expected-error@+1 {{'svzip2_bf16' needs target feature (sve|sme),bf16}}
83+
// expected-error@+1 {{'svzip2_bf16' needs target feature (sve,bf16)|(sme,bf16)}}
8484
svzip2_bf16(bf16, bf16);
8585
// expected-error@+1 {{'svzip2q_bf16' needs target feature sve,bf16}}
8686
svzip2q_bf16(bf16, bf16);

clang/test/Sema/aarch64-sve2-intrinsics/acle_sve2_bfloat.cpp

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,16 +14,16 @@
1414

1515
void test_bfloat(const bfloat16_t *const_bf16_ptr, svbfloat16_t bf16, svbfloat16x2_t bf16x2)
1616
{
17-
// expected-error@+2 {{'svwhilerw_bf16' needs target feature (sve2|sme),bf16}}
18-
// overload-error@+1 {{'svwhilerw' needs target feature (sve2|sme),bf16}}
17+
// expected-error@+2 {{'svwhilerw_bf16' needs target feature (sve2,bf16)|(sme,bf16)}}
18+
// overload-error@+1 {{'svwhilerw' needs target feature (sve2,bf16)|(sme,bf16)}}
1919
SVE_ACLE_FUNC(svwhilerw,_bf16,,)(const_bf16_ptr, const_bf16_ptr);
20-
// expected-error@+2 {{'svtbx_bf16' needs target feature (sve2|sme),bf16}}
21-
// overload-error@+1 {{'svtbx' needs target feature (sve2|sme),bf16}}
20+
// expected-error@+2 {{'svtbx_bf16' needs target feature (sve2,bf16)|(sme,bf16)}}
21+
// overload-error@+1 {{'svtbx' needs target feature (sve2,bf16)|(sme,bf16)}}
2222
SVE_ACLE_FUNC(svtbx,_bf16,,)(bf16, bf16, svundef_u16());
23-
// expected-error@+2 {{'svtbl2_bf16' needs target feature (sve2|sme),bf16}}
24-
// overload-error@+1 {{'svtbl2' needs target feature (sve2|sme),bf16}}
23+
// expected-error@+2 {{'svtbl2_bf16' needs target feature (sve2,bf16)|(sme,bf16)}}
24+
// overload-error@+1 {{'svtbl2' needs target feature (sve2,bf16)|(sme,bf16)}}
2525
SVE_ACLE_FUNC(svtbl2,_bf16,,)(bf16x2, svundef_u16());
26-
// expected-error@+2 {{'svwhilewr_bf16' needs target feature (sve2|sme),bf16}}
27-
// overload-error@+1 {{'svwhilewr' needs target feature (sve2|sme),bf16}}
26+
// expected-error@+2 {{'svwhilewr_bf16' needs target feature (sve2,bf16)|(sme,bf16)}}
27+
// overload-error@+1 {{'svwhilewr' needs target feature (sve2,bf16)|(sme,bf16)}}
2828
SVE_ACLE_FUNC(svwhilewr,_bf16,,)(const_bf16_ptr, const_bf16_ptr);
2929
}

clang/utils/TableGen/SveEmitter.cpp

Lines changed: 49 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ class Intrinsic {
165165
ClassKind Class;
166166

167167
/// The architectural #ifdef guard.
168-
std::string Guard;
168+
std::string SVEGuard, SMEGuard;
169169

170170
// The merge suffix such as _m, _x or _z.
171171
std::string MergeSuffix;
@@ -184,7 +184,8 @@ class Intrinsic {
184184
Intrinsic(StringRef Name, StringRef Proto, uint64_t MergeTy,
185185
StringRef MergeSuffix, uint64_t MemoryElementTy, StringRef LLVMName,
186186
uint64_t Flags, ArrayRef<ImmCheck> ImmChecks, TypeSpec BT,
187-
ClassKind Class, SVEEmitter &Emitter, StringRef Guard);
187+
ClassKind Class, SVEEmitter &Emitter, StringRef SVEGuard,
188+
StringRef SMEGuard);
188189

189190
~Intrinsic()=default;
190191

@@ -194,7 +195,27 @@ class Intrinsic {
194195
TypeSpec getBaseTypeSpec() const { return BaseTypeSpec; }
195196
SVEType getBaseType() const { return BaseType; }
196197

197-
StringRef getGuard() const { return Guard; }
198+
StringRef getSVEGuard() const { return SVEGuard; }
199+
StringRef getSMEGuard() const { return SMEGuard; }
200+
void printGuard(raw_ostream &OS) const {
201+
if (!SVEGuard.empty() && SMEGuard.empty())
202+
OS << SVEGuard;
203+
else if (SVEGuard.empty() && !SMEGuard.empty())
204+
OS << SMEGuard;
205+
else {
206+
if (SVEGuard.find(",") != std::string::npos ||
207+
SVEGuard.find("|") != std::string::npos)
208+
OS << "(" << SVEGuard << ")";
209+
else
210+
OS << SVEGuard;
211+
OS << "|";
212+
if (SMEGuard.find(",") != std::string::npos ||
213+
SMEGuard.find("|") != std::string::npos)
214+
OS << "(" << SMEGuard << ")";
215+
else
216+
OS << SMEGuard;
217+
}
218+
}
198219
ClassKind getClassKind() const { return Class; }
199220

200221
SVEType getReturnType() const { return Types[0]; }
@@ -943,11 +964,12 @@ Intrinsic::Intrinsic(StringRef Name, StringRef Proto, uint64_t MergeTy,
943964
StringRef MergeSuffix, uint64_t MemoryElementTy,
944965
StringRef LLVMName, uint64_t Flags,
945966
ArrayRef<ImmCheck> Checks, TypeSpec BT, ClassKind Class,
946-
SVEEmitter &Emitter, StringRef Guard)
967+
SVEEmitter &Emitter, StringRef SVEGuard,
968+
StringRef SMEGuard)
947969
: Name(Name.str()), LLVMName(LLVMName), Proto(Proto.str()),
948-
BaseTypeSpec(BT), Class(Class), Guard(Guard.str()),
949-
MergeSuffix(MergeSuffix.str()), BaseType(BT, 'd'), Flags(Flags),
950-
ImmChecks(Checks.begin(), Checks.end()) {
970+
BaseTypeSpec(BT), Class(Class), SVEGuard(SVEGuard.str()),
971+
SMEGuard(SMEGuard.str()), MergeSuffix(MergeSuffix.str()),
972+
BaseType(BT, 'd'), Flags(Flags), ImmChecks(Checks.begin(), Checks.end()) {
951973
// Types[0] is the return value.
952974
for (unsigned I = 0; I < (getNumParams() + 1); ++I) {
953975
char Mod;
@@ -1147,7 +1169,8 @@ void SVEEmitter::createIntrinsic(
11471169
StringRef Name = R->getValueAsString("Name");
11481170
StringRef Proto = R->getValueAsString("Prototype");
11491171
StringRef Types = R->getValueAsString("Types");
1150-
StringRef Guard = R->getValueAsString("TargetGuard");
1172+
StringRef SVEGuard = R->getValueAsString("SVETargetGuard");
1173+
StringRef SMEGuard = R->getValueAsString("SMETargetGuard");
11511174
StringRef LLVMName = R->getValueAsString("LLVMIntrinsic");
11521175
uint64_t Merge = R->getValueAsInt("Merge");
11531176
StringRef MergeSuffix = R->getValueAsString("MergeSuffix");
@@ -1203,13 +1226,13 @@ void SVEEmitter::createIntrinsic(
12031226

12041227
Out.push_back(std::make_unique<Intrinsic>(
12051228
Name, Proto, Merge, MergeSuffix, MemEltType, LLVMName, Flags, ImmChecks,
1206-
TS, ClassS, *this, Guard));
1229+
TS, ClassS, *this, SVEGuard, SMEGuard));
12071230

12081231
// Also generate the short-form (e.g. svadd_m) for the given type-spec.
12091232
if (Intrinsic::isOverloadedIntrinsic(Name))
12101233
Out.push_back(std::make_unique<Intrinsic>(
12111234
Name, Proto, Merge, MergeSuffix, MemEltType, LLVMName, Flags,
1212-
ImmChecks, TS, ClassG, *this, Guard));
1235+
ImmChecks, TS, ClassG, *this, SVEGuard, SMEGuard));
12131236
}
12141237
}
12151238

@@ -1229,9 +1252,9 @@ void SVEEmitter::createCoreHeaderIntrinsics(raw_ostream &OS,
12291252
[](const std::unique_ptr<Intrinsic> &A,
12301253
const std::unique_ptr<Intrinsic> &B) {
12311254
auto ToTuple = [](const std::unique_ptr<Intrinsic> &I) {
1232-
return std::make_tuple(I->getGuard(),
1233-
(unsigned)I->getClassKind(),
1234-
I->getName());
1255+
return std::make_tuple(
1256+
I->getSVEGuard().str() + I->getSMEGuard().str(),
1257+
(unsigned)I->getClassKind(), I->getName());
12351258
};
12361259
return ToTuple(A) < ToTuple(B);
12371260
});
@@ -1434,10 +1457,12 @@ void SVEEmitter::createBuiltins(raw_ostream &OS) {
14341457
for (auto &Def : Defs) {
14351458
// Only create BUILTINs for non-overloaded intrinsics, as overloaded
14361459
// declarations only live in the header file.
1437-
if (Def->getClassKind() != ClassG)
1460+
if (Def->getClassKind() != ClassG) {
14381461
OS << "TARGET_BUILTIN(__builtin_sve_" << Def->getMangledName() << ", \""
1439-
<< Def->getBuiltinTypeStr() << "\", \"n\", \"" << Def->getGuard()
1440-
<< "\")\n";
1462+
<< Def->getBuiltinTypeStr() << "\", \"n\", \"";
1463+
Def->printGuard(OS);
1464+
OS << "\")\n";
1465+
}
14411466
}
14421467

14431468
// Add reinterpret functions.
@@ -1638,10 +1663,12 @@ void SVEEmitter::createSMEBuiltins(raw_ostream &OS) {
16381663
for (auto &Def : Defs) {
16391664
// Only create BUILTINs for non-overloaded intrinsics, as overloaded
16401665
// declarations only live in the header file.
1641-
if (Def->getClassKind() != ClassG)
1666+
if (Def->getClassKind() != ClassG) {
16421667
OS << "TARGET_BUILTIN(__builtin_sme_" << Def->getMangledName() << ", \""
1643-
<< Def->getBuiltinTypeStr() << "\", \"n\", \"" << Def->getGuard()
1644-
<< "\")\n";
1668+
<< Def->getBuiltinTypeStr() << "\", \"n\", \"";
1669+
Def->printGuard(OS);
1670+
OS << "\")\n";
1671+
}
16451672
}
16461673

16471674
OS << "#endif\n\n";
@@ -1783,9 +1810,9 @@ void SVEEmitter::createStreamingAttrs(raw_ostream &OS, ACLEKind Kind) {
17831810
getEnumValueForFlag("IsStreamingCompatible");
17841811

17851812
for (auto &Def : Defs) {
1786-
if (!Def->isFlagSet(VerifyRuntimeMode) && Def->getGuard().contains("sve") &&
1787-
Def->getGuard().contains("sme"))
1788-
llvm_unreachable("Missing VerifyRuntimeMode flag");
1813+
if (!Def->isFlagSet(VerifyRuntimeMode) && !Def->getSVEGuard().empty() &&
1814+
!Def->getSMEGuard().empty())
1815+
report_fatal_error("Missing VerifyRuntimeMode flag");
17891816

17901817
if (Def->isFlagSet(IsStreamingFlag))
17911818
StreamingMap["ArmStreaming"].insert(Def->getMangledName());

0 commit comments

Comments
 (0)