Skip to content

Commit 2497739

Browse files
authored
[AArch64][AsmParser] Directives should clear transitively implied features (#106625)
The commit ff3f3a5 made it possible to enable transitively implied features when parsing assembler directives. For example enabling sve2 also enables sve. This patch allows disabling features which depend on each other. For example disabling sve also disables sve2.
1 parent 362d37a commit 2497739

File tree

6 files changed

+84
-59
lines changed

6 files changed

+84
-59
lines changed

llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp

Lines changed: 47 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -6947,18 +6947,22 @@ static void ExpandCryptoAEK(const AArch64::ArchInfo &ArchInfo,
69476947
}
69486948
}
69496949

6950+
static SMLoc incrementLoc(SMLoc L, int Offset) {
6951+
return SMLoc::getFromPointer(L.getPointer() + Offset);
6952+
}
6953+
69506954
/// parseDirectiveArch
69516955
/// ::= .arch token
69526956
bool AArch64AsmParser::parseDirectiveArch(SMLoc L) {
6953-
SMLoc ArchLoc = getLoc();
6957+
SMLoc CurLoc = getLoc();
69546958

69556959
StringRef Arch, ExtensionString;
69566960
std::tie(Arch, ExtensionString) =
69576961
getParser().parseStringToEndOfStatement().trim().split('+');
69586962

69596963
const AArch64::ArchInfo *ArchInfo = AArch64::parseArch(Arch);
69606964
if (!ArchInfo)
6961-
return Error(ArchLoc, "unknown arch name");
6965+
return Error(CurLoc, "unknown arch name");
69626966

69636967
if (parseToken(AsmToken::EndOfStatement))
69646968
return true;
@@ -6978,27 +6982,30 @@ bool AArch64AsmParser::parseDirectiveArch(SMLoc L) {
69786982
ExtensionString.split(RequestedExtensions, '+');
69796983

69806984
ExpandCryptoAEK(*ArchInfo, RequestedExtensions);
6985+
CurLoc = incrementLoc(CurLoc, Arch.size());
69816986

6982-
FeatureBitset Features = STI.getFeatureBits();
6983-
setAvailableFeatures(ComputeAvailableFeatures(Features));
69846987
for (auto Name : RequestedExtensions) {
6988+
// Advance source location past '+'.
6989+
CurLoc = incrementLoc(CurLoc, 1);
6990+
69856991
bool EnableFeature = !Name.consume_front_insensitive("no");
69866992

6987-
for (const auto &Extension : ExtensionMap) {
6988-
if (Extension.Name != Name)
6989-
continue;
6993+
auto It = llvm::find_if(ExtensionMap, [&Name](const auto &Extension) {
6994+
return Extension.Name == Name;
6995+
});
69906996

6991-
if (Extension.Features.none())
6992-
report_fatal_error("unsupported architectural extension: " + Name);
6997+
if (It == std::end(ExtensionMap))
6998+
Error(CurLoc, "unsupported architectural extension: " + Name);
69936999

6994-
FeatureBitset ToggleFeatures =
6995-
EnableFeature
6996-
? STI.SetFeatureBitsTransitively(~Features & Extension.Features)
6997-
: STI.ToggleFeature(Features & Extension.Features);
6998-
setAvailableFeatures(ComputeAvailableFeatures(ToggleFeatures));
6999-
break;
7000-
}
7000+
if (EnableFeature)
7001+
STI.SetFeatureBitsTransitively(It->Features);
7002+
else
7003+
STI.ClearFeatureBitsTransitively(It->Features);
7004+
7005+
CurLoc = incrementLoc(CurLoc, Name.size());
70017006
}
7007+
FeatureBitset Features = ComputeAvailableFeatures(STI.getFeatureBits());
7008+
setAvailableFeatures(Features);
70027009
return false;
70037010
}
70047011

@@ -7018,28 +7025,21 @@ bool AArch64AsmParser::parseDirectiveArchExtension(SMLoc L) {
70187025
Name = Name.substr(2);
70197026
}
70207027

7021-
MCSubtargetInfo &STI = copySTI();
7022-
FeatureBitset Features = STI.getFeatureBits();
7023-
for (const auto &Extension : ExtensionMap) {
7024-
if (Extension.Name != Name)
7025-
continue;
7026-
7027-
if (Extension.Features.none())
7028-
return Error(ExtLoc, "unsupported architectural extension: " + Name);
7029-
7030-
FeatureBitset ToggleFeatures =
7031-
EnableFeature
7032-
? STI.SetFeatureBitsTransitively(~Features & Extension.Features)
7033-
: STI.ToggleFeature(Features & Extension.Features);
7034-
setAvailableFeatures(ComputeAvailableFeatures(ToggleFeatures));
7035-
return false;
7036-
}
7028+
auto It = llvm::find_if(ExtensionMap, [&Name](const auto &Extension) {
7029+
return Extension.Name == Name;
7030+
});
70377031

7038-
return Error(ExtLoc, "unknown architectural extension: " + Name);
7039-
}
7032+
if (It == std::end(ExtensionMap))
7033+
return Error(ExtLoc, "unsupported architectural extension: " + Name);
70407034

7041-
static SMLoc incrementLoc(SMLoc L, int Offset) {
7042-
return SMLoc::getFromPointer(L.getPointer() + Offset);
7035+
MCSubtargetInfo &STI = copySTI();
7036+
if (EnableFeature)
7037+
STI.SetFeatureBitsTransitively(It->Features);
7038+
else
7039+
STI.ClearFeatureBitsTransitively(It->Features);
7040+
FeatureBitset Features = ComputeAvailableFeatures(STI.getFeatureBits());
7041+
setAvailableFeatures(Features);
7042+
return false;
70437043
}
70447044

70457045
/// parseDirectiveCPU
@@ -7075,30 +7075,22 @@ bool AArch64AsmParser::parseDirectiveCPU(SMLoc L) {
70757075

70767076
bool EnableFeature = !Name.consume_front_insensitive("no");
70777077

7078-
bool FoundExtension = false;
7079-
for (const auto &Extension : ExtensionMap) {
7080-
if (Extension.Name != Name)
7081-
continue;
7082-
7083-
if (Extension.Features.none())
7084-
report_fatal_error("unsupported architectural extension: " + Name);
7085-
7086-
FeatureBitset Features = STI.getFeatureBits();
7087-
FeatureBitset ToggleFeatures =
7088-
EnableFeature
7089-
? STI.SetFeatureBitsTransitively(~Features & Extension.Features)
7090-
: STI.ToggleFeature(Features & Extension.Features);
7091-
setAvailableFeatures(ComputeAvailableFeatures(ToggleFeatures));
7092-
FoundExtension = true;
7078+
auto It = llvm::find_if(ExtensionMap, [&Name](const auto &Extension) {
7079+
return Extension.Name == Name;
7080+
});
70937081

7094-
break;
7095-
}
7082+
if (It == std::end(ExtensionMap))
7083+
Error(CurLoc, "unsupported architectural extension: " + Name);
70967084

7097-
if (!FoundExtension)
7098-
Error(CurLoc, "unsupported architectural extension");
7085+
if (EnableFeature)
7086+
STI.SetFeatureBitsTransitively(It->Features);
7087+
else
7088+
STI.ClearFeatureBitsTransitively(It->Features);
70997089

71007090
CurLoc = incrementLoc(CurLoc, Name.size());
71017091
}
7092+
FeatureBitset Features = ComputeAvailableFeatures(STI.getFeatureBits());
7093+
setAvailableFeatures(Features);
71027094
return false;
71037095
}
71047096

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// RUN: not llvm-mc -triple aarch64 -filetype asm -o - %s 2>&1 | FileCheck %s
2+
3+
// Check that setting +nosve implies +nosve2
4+
.arch armv9-a+nosve
5+
6+
adclb z0.s, z1.s, z31.s
7+
// CHECK: error: instruction requires: sve2
8+
// CHECK-NEXT: adclb z0.s, z1.s, z31.s
Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
11
// RUN: not llvm-mc -triple aarch64 -filetype asm -o - %s 2>&1 | FileCheck %s
22

3-
.arch_extension nosve
3+
.arch_extension sve2+nosve
44

55
ptrue p0.b, pow2
66
// CHECK: error: instruction requires: sve or sme
77
// CHECK-NEXT: ptrue p0.b, pow2
8+
9+
// Check that setting +nosve implies +nosve2
10+
adclb z0.s, z1.s, z31.s
11+
// CHECK: error: instruction requires: sve2
12+
// CHECK-NEXT: adclb z0.s, z1.s, z31.s
Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
// RUN: not llvm-mc -triple aarch64 -filetype asm -o - %s 2>&1 | FileCheck %s
22

3-
.cpu generic+sve+nosve
3+
.cpu generic+sve2+nosve
44
ptrue p0.b, pow2
55
// CHECK: error: instruction requires: sve or sme
66
// CHECK-NEXT: ptrue p0.b, pow2
7+
8+
// Check that setting +nosve implies +nosve2
9+
adclb z0.s, z1.s, z31.s
10+
// CHECK: error: instruction requires: sve2
11+
// CHECK-NEXT: adclb z0.s, z1.s, z31.s

llvm/test/MC/AArch64/directive-arch-negative.s

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,13 @@
1212
# CHECK-NEXT: aese v0.8h, v1.8h
1313
# CHECK-NEXT: ^
1414

15-
// We silently ignore invalid features.
1615
.arch armv8+foo
1716
aese v0.8h, v1.8h
1817

18+
# CHECK: error: unsupported architectural extension: foo
19+
# CHECK-NEXT: .arch armv8+foo
20+
# CHECK-NEXT: ^
21+
1922
# CHECK: error: invalid operand for instruction
2023
# CHECK-NEXT: aese v0.8h, v1.8h
2124
# CHECK-NEXT: ^

llvm/test/MC/AArch64/directive-arch_extension-negative.s

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
// RUN: -filetype asm -o - %s 2>&1 | FileCheck %s
55

66
.arch_extension axp64
7-
// CHECK: error: unknown architectural extension: axp64
7+
// CHECK: error: unsupported architectural extension: axp64
88
// CHECK-NEXT: .arch_extension axp64
99

1010
crc32cx w0, w1, x3
@@ -49,6 +49,8 @@ fminnm d0, d0, d1
4949
// CHECK: [[@LINE-1]]:1: error: instruction requires: fp
5050
// CHECK-NEXT: fminnm d0, d0, d1
5151

52+
// nofp implied nosimd, so reinstate it
53+
.arch_extension simd
5254
addp v0.4s, v0.4s, v0.4s
5355
// CHECK-NOT: [[@LINE-1]]:1: error: instruction requires: neon
5456
.arch_extension nosimd
@@ -70,6 +72,8 @@ casa w5, w7, [x20]
7072
// CHECK: [[@LINE-1]]:1: error: instruction requires: lse
7173
// CHECK-NEXT: casa w5, w7, [x20]
7274

75+
// nolse implied nolse128, so reinstate it
76+
.arch_extension lse128
7377
swpp x0, x2, [x3]
7478
// CHECK-NOT: [[@LINE-1]]:1: error: instruction requires: lse128
7579
.arch_extension nolse128
@@ -84,6 +88,8 @@ cfp rctx, x0
8488
// CHECK: [[@LINE-1]]:5: error: CFPRCTX requires: predres
8589
// CHECK-NEXT: cfp rctx, x0
8690

91+
// nopredres implied nopredres2, so reinstate it
92+
.arch_extension predres2
8793
cosp rctx, x0
8894
// CHECK-NOT: [[@LINE-1]]:6: error: COSP requires: predres2
8995
.arch_extension nopredres2
@@ -133,6 +139,8 @@ ldapr x0, [x1]
133139
// CHECK: [[@LINE-1]]:1: error: instruction requires: rcpc
134140
// CHECK-NEXT: ldapr x0, [x1]
135141

142+
// norcpc implied norcpc3, so reinstate it
143+
.arch_extension rcpc3
136144
stilp w24, w0, [x16, #-8]!
137145
// CHECK-NOT: [[@LINE-1]]:1: error: instruction requires: rcpc3
138146
.arch_extension norcpc3
@@ -169,6 +177,8 @@ cpyfp [x0]!, [x1]!, x2!
169177
// CHECK: [[@LINE-1]]:1: error: instruction requires: mops
170178
// CHECK-NEXT: cpyfp [x0]!, [x1]!, x2!
171179

180+
// nolse128 implied nod128, so reinstate it
181+
.arch_extension d128
172182
// This needs to come before `.arch_extension nothe` as it uses an instruction
173183
// that requires both the and d128
174184
sysp #0, c2, c0, #0, x0, x1
@@ -204,6 +214,8 @@ umax x0, x1, x2
204214
// CHECK: [[@LINE-1]]:1: error: instruction requires: cssc
205215
// CHECK-NEXT: umax x0, x1, x2
206216

217+
// noras implied norasv2, so reinstate it
218+
.arch_extension rasv2
207219
mrs x0, ERXGSR_EL1
208220
// CHECK-NOT: [[@LINE-1]]:9: error: expected readable system register
209221
.arch_extension norasv2

0 commit comments

Comments
 (0)