[llvm] [AArch64][llvm][tablegen] Restrict luti6 assembly (4 regs, 8-bit) to 0 <= Zn <= 7 (PR #200751)
Jonathan Thackray via llvm-commits
llvm-commits at lists.llvm.org
Thu Jun 4 01:22:45 PDT 2026
https://github.com/jthackray updated https://github.com/llvm/llvm-project/pull/200751
>From c411947b575c6f58bbcdf121e3809d93dbd30345 Mon Sep 17 00:00:00 2001
From: Jonathan Thackray <jonathan.thackray at arm.com>
Date: Mon, 1 Jun 2026 09:23:59 +0100
Subject: [PATCH 1/3] [AArch64][llvm] Restrict luti6 (4 regs, 8-bit) to 0 <= Zn
<= 7
The `luti6` instruction (table, four registers, 8-bit) should only
allow `0 <= Zn <= 7`, since there's only 3 bits. It actually allows:
```
luti6 { z0.b - z3.b }, zt0, { z8 - z10 }
```
which produces a duplicate encoding to the following:
```
luti6 { z0.b - z3.b }, zt0, { z0 - z2 }
```
Fix tablegen to ensure Zn is only allowed in correct range of 0 to 7.
---
llvm/lib/Target/AArch64/AArch64RegisterInfo.td | 15 +++++++++++++++
.../Target/AArch64/AsmParser/AArch64AsmParser.cpp | 4 ++++
llvm/lib/Target/AArch64/SMEInstrFormats.td | 2 +-
llvm/test/MC/AArch64/SME2p3/luti6-diagnostics.s | 5 +++++
4 files changed, 25 insertions(+), 1 deletion(-)
diff --git a/llvm/lib/Target/AArch64/AArch64RegisterInfo.td b/llvm/lib/Target/AArch64/AArch64RegisterInfo.td
index cd94a2590c6d2..700f798f271d5 100644
--- a/llvm/lib/Target/AArch64/AArch64RegisterInfo.td
+++ b/llvm/lib/Target/AArch64/AArch64RegisterInfo.td
@@ -1321,6 +1321,17 @@ class ZPRVectorList<int ElementWidth, int NumRegs> : AsmOperandClass {
let RenderMethod = "addVectorListOperands<AArch64Operand::VecListIdx_ZReg, " # NumRegs # ">";
}
+class ZPRVectorListZ0Z7<int ElementWidth, int NumRegs>
+ : ZPRVectorList<ElementWidth, NumRegs> {
+ let Name = "SVEVectorList" # NumRegs # "x" # ElementWidth # "Z0Z7";
+ let DiagnosticType = "Invalid" # Name;
+ let PredicateMethod =
+ "isTypedVectorListMultiple<RegKind::SVEDataVector, "
+ # NumRegs # ", 0, "
+ # ElementWidth # ", "
+ # "AArch64::ZPR_3bRegClassID" # ">";
+}
+
def Z_b : RegisterOperand<ZPR, "printTypedVectorList<0,'b'>"> {
let ParserMatchClass = ZPRVectorList<8, 1>;
}
@@ -1369,6 +1380,10 @@ def ZZZ_Any : RegisterOperand<ZPR3, "printTypedVectorList<0,0>"> {
let ParserMatchClass = ZPRVectorList<0, 3>;
}
+def ZZZ_Any_Z0Z7 : RegisterOperand<ZPR3, "printTypedVectorList<0,0>"> {
+ let ParserMatchClass = ZPRVectorListZ0Z7<0, 3>;
+}
+
def ZZZ_b : RegisterOperand<ZPR3, "printTypedVectorList<0,'b'>"> {
let ParserMatchClass = ZPRVectorList<8, 3>;
}
diff --git a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
index 6a6b73b8a4c88..d3886f47f4d6c 100644
--- a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
+++ b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
@@ -6615,6 +6615,9 @@ bool AArch64AsmParser::showMatchError(SMLoc Loc, unsigned ErrCode,
return Error(Loc, "Invalid vector list, expected list with 4 consecutive "
"SVE vectors, where the first vector is a multiple of 4 "
"and with matching element types");
+ case Match_InvalidSVEVectorList3x0Z0Z7:
+ return Error(Loc, "Invalid vector list, expected list with 3 consecutive "
+ "SVE vectors starting at z0-z7");
case Match_InvalidLookupTable:
return Error(Loc, "Invalid lookup table, expected zt0");
case Match_InvalidSVEVectorListStrided2x8:
@@ -7233,6 +7236,7 @@ bool AArch64AsmParser::matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
case Match_InvalidSVEVectorList2x16Mul2_Hi:
case Match_InvalidSVEVectorList2x32Mul2_Hi:
case Match_InvalidSVEVectorList2x64Mul2_Hi:
+ case Match_InvalidSVEVectorList3x0Z0Z7:
case Match_InvalidSVEVectorListStrided2x8:
case Match_InvalidSVEVectorListStrided2x16:
case Match_InvalidSVEVectorListStrided2x32:
diff --git a/llvm/lib/Target/AArch64/SMEInstrFormats.td b/llvm/lib/Target/AArch64/SMEInstrFormats.td
index 771c4c1fb2b6e..6cfbb8f0e404f 100644
--- a/llvm/lib/Target/AArch64/SMEInstrFormats.td
+++ b/llvm/lib/Target/AArch64/SMEInstrFormats.td
@@ -3935,7 +3935,7 @@ class sme2_lut_single<string asm>
//===----------------------------------------------------------------------===//
// Lookup table read with 6-bit indices (8-bit)
class sme2_luti6_zt_base<RegisterOperand zd_ty, string asm>
- : I<(outs zd_ty:$Zd), (ins ZTR:$ZTt, ZZZ_Any:$Zn),
+ : I<(outs zd_ty:$Zd), (ins ZTR:$ZTt, ZZZ_Any_Z0Z7:$Zn),
asm, "\t$Zd, $ZTt, $Zn", "", []>, Sched<[]> {
bits<0> ZTt;
bits<3> Zd;
diff --git a/llvm/test/MC/AArch64/SME2p3/luti6-diagnostics.s b/llvm/test/MC/AArch64/SME2p3/luti6-diagnostics.s
index c25ff664afb73..846c282c4de03 100644
--- a/llvm/test/MC/AArch64/SME2p3/luti6-diagnostics.s
+++ b/llvm/test/MC/AArch64/SME2p3/luti6-diagnostics.s
@@ -117,6 +117,11 @@ luti6 { z0.b - z3.b }, zt0, { z1 - z1 }
// CHECK-NEXT: luti6 { z0.b - z3.b }, zt0, { z1 - z1 }
// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+luti6 { z0.b - z3.b }, zt0, { z8 - z10 }
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: Invalid vector list, expected list with 3 consecutive SVE vectors starting at z0-z7
+// CHECK-NEXT: luti6 { z0.b - z3.b }, zt0, { z8 - z10 }
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
luti6 { z0.b - z5.b }, zt0, { z7 - z11 }
// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid number of vectors
// CHECK-NEXT: luti6 { z0.b - z5.b }, zt0, { z7 - z11 }
>From 79cf6b6b566975f96f6bbbdb420f8e066915dd4c Mon Sep 17 00:00:00 2001
From: Jonathan Thackray <jonathan.thackray at arm.com>
Date: Tue, 2 Jun 2026 22:35:38 +0100
Subject: [PATCH 2/3] fixup! Address CR comments
---
.../lib/Target/AArch64/AArch64RegisterInfo.td | 29 +++++++------------
1 file changed, 10 insertions(+), 19 deletions(-)
diff --git a/llvm/lib/Target/AArch64/AArch64RegisterInfo.td b/llvm/lib/Target/AArch64/AArch64RegisterInfo.td
index 700f798f271d5..1f1578b0007b5 100644
--- a/llvm/lib/Target/AArch64/AArch64RegisterInfo.td
+++ b/llvm/lib/Target/AArch64/AArch64RegisterInfo.td
@@ -1321,17 +1321,6 @@ class ZPRVectorList<int ElementWidth, int NumRegs> : AsmOperandClass {
let RenderMethod = "addVectorListOperands<AArch64Operand::VecListIdx_ZReg, " # NumRegs # ">";
}
-class ZPRVectorListZ0Z7<int ElementWidth, int NumRegs>
- : ZPRVectorList<ElementWidth, NumRegs> {
- let Name = "SVEVectorList" # NumRegs # "x" # ElementWidth # "Z0Z7";
- let DiagnosticType = "Invalid" # Name;
- let PredicateMethod =
- "isTypedVectorListMultiple<RegKind::SVEDataVector, "
- # NumRegs # ", 0, "
- # ElementWidth # ", "
- # "AArch64::ZPR_3bRegClassID" # ">";
-}
-
def Z_b : RegisterOperand<ZPR, "printTypedVectorList<0,'b'>"> {
let ParserMatchClass = ZPRVectorList<8, 1>;
}
@@ -1376,14 +1365,6 @@ def ZZ_q : RegisterOperand<ZPR2, "printTypedVectorList<0,'q'>"> {
let ParserMatchClass = ZPRVectorList<128, 2>;
}
-def ZZZ_Any : RegisterOperand<ZPR3, "printTypedVectorList<0,0>"> {
- let ParserMatchClass = ZPRVectorList<0, 3>;
-}
-
-def ZZZ_Any_Z0Z7 : RegisterOperand<ZPR3, "printTypedVectorList<0,0>"> {
- let ParserMatchClass = ZPRVectorListZ0Z7<0, 3>;
-}
-
def ZZZ_b : RegisterOperand<ZPR3, "printTypedVectorList<0,'b'>"> {
let ParserMatchClass = ZPRVectorList<8, 3>;
}
@@ -1444,6 +1425,16 @@ class ZPRVectorListMul<int ElementWidth, int NumRegs, string RegClassSuffix = ""
# "AArch64::ZPR" # RegClassSuffix # "RegClassID" # ">";
}
+class ZPRVectorList_3b<int ElementWidth, int NumRegs>
+ : ZPRVectorListMul<ElementWidth, NumRegs, "_3b"> {
+ let Name = "SVEVectorList" # NumRegs # "x" # ElementWidth # "Z0Z7";
+ let DiagnosticType = "Invalid" # Name;
+}
+
+def ZZZ_Any_Z0Z7 : RegisterOperand<ZPR3, "printTypedVectorList<0,0>"> {
+ let ParserMatchClass = ZPRVectorList_3b<0, 3>;
+}
+
let EncoderMethod = "EncodeRegMul_MinMax<2, 0, 30>",
DecoderMethod = "DecodeZPR2Mul2RegisterClass<0, 30>" in {
def ZZ_mul_r : RegisterOperand<ZPR2Mul2, "printTypedVectorList<0,0>"> {
>From bb138cbee2120e50c93d4ac6d71a9babb78c7a45 Mon Sep 17 00:00:00 2001
From: Jonathan Thackray <jonathan.thackray at arm.com>
Date: Wed, 3 Jun 2026 15:08:36 +0100
Subject: [PATCH 3/3] fixup! Address more CR comments
---
llvm/lib/Target/AArch64/AArch64RegisterInfo.td | 14 ++++++--------
.../Target/AArch64/AsmParser/AArch64AsmParser.cpp | 4 ++--
llvm/lib/Target/AArch64/SMEInstrFormats.td | 2 +-
llvm/utils/TableGen/Common/CodeGenRegisters.cpp | 11 ++++++++++-
4 files changed, 19 insertions(+), 12 deletions(-)
diff --git a/llvm/lib/Target/AArch64/AArch64RegisterInfo.td b/llvm/lib/Target/AArch64/AArch64RegisterInfo.td
index 1f1578b0007b5..75fe3c4ebe23d 100644
--- a/llvm/lib/Target/AArch64/AArch64RegisterInfo.td
+++ b/llvm/lib/Target/AArch64/AArch64RegisterInfo.td
@@ -1308,6 +1308,10 @@ def ZPR3 : RegisterClass<"AArch64", [untyped], 128, (add ZSeqTriples)> {
let Size = 384;
let DecoderMethod = "DecodeSimpleRegisterClass<AArch64::ZPR3RegClassID, 0, 32>";
}
+def ZPR3_3b : RegisterClass<"AArch64", [untyped], 128, (add (trunc ZSeqTriples, 8))> {
+ let Size = 384;
+ let DecoderMethod = "DecodeSimpleRegisterClass<AArch64::ZPR3_3bRegClassID, 0, 8>";
+}
def ZPR4 : RegisterClass<"AArch64", [untyped], 128, (add ZSeqQuads)> {
let Size = 512;
let DecoderMethod = "DecodeSimpleRegisterClass<AArch64::ZPR4RegClassID, 0, 32>";
@@ -1425,14 +1429,8 @@ class ZPRVectorListMul<int ElementWidth, int NumRegs, string RegClassSuffix = ""
# "AArch64::ZPR" # RegClassSuffix # "RegClassID" # ">";
}
-class ZPRVectorList_3b<int ElementWidth, int NumRegs>
- : ZPRVectorListMul<ElementWidth, NumRegs, "_3b"> {
- let Name = "SVEVectorList" # NumRegs # "x" # ElementWidth # "Z0Z7";
- let DiagnosticType = "Invalid" # Name;
-}
-
-def ZZZ_Any_Z0Z7 : RegisterOperand<ZPR3, "printTypedVectorList<0,0>"> {
- let ParserMatchClass = ZPRVectorList_3b<0, 3>;
+def ZZZ_Any_3b : RegisterOperand<ZPR3_3b, "printTypedVectorList<0,0>"> {
+ let ParserMatchClass = ZPRVectorListMul<0, 3, "_3b">;
}
let EncoderMethod = "EncodeRegMul_MinMax<2, 0, 30>",
diff --git a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
index d3886f47f4d6c..be71121bf4500 100644
--- a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
+++ b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
@@ -6615,7 +6615,7 @@ bool AArch64AsmParser::showMatchError(SMLoc Loc, unsigned ErrCode,
return Error(Loc, "Invalid vector list, expected list with 4 consecutive "
"SVE vectors, where the first vector is a multiple of 4 "
"and with matching element types");
- case Match_InvalidSVEVectorList3x0Z0Z7:
+ case Match_InvalidSVEVectorList3x0_3b:
return Error(Loc, "Invalid vector list, expected list with 3 consecutive "
"SVE vectors starting at z0-z7");
case Match_InvalidLookupTable:
@@ -7236,7 +7236,7 @@ bool AArch64AsmParser::matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
case Match_InvalidSVEVectorList2x16Mul2_Hi:
case Match_InvalidSVEVectorList2x32Mul2_Hi:
case Match_InvalidSVEVectorList2x64Mul2_Hi:
- case Match_InvalidSVEVectorList3x0Z0Z7:
+ case Match_InvalidSVEVectorList3x0_3b:
case Match_InvalidSVEVectorListStrided2x8:
case Match_InvalidSVEVectorListStrided2x16:
case Match_InvalidSVEVectorListStrided2x32:
diff --git a/llvm/lib/Target/AArch64/SMEInstrFormats.td b/llvm/lib/Target/AArch64/SMEInstrFormats.td
index 6cfbb8f0e404f..178a4825af62c 100644
--- a/llvm/lib/Target/AArch64/SMEInstrFormats.td
+++ b/llvm/lib/Target/AArch64/SMEInstrFormats.td
@@ -3935,7 +3935,7 @@ class sme2_lut_single<string asm>
//===----------------------------------------------------------------------===//
// Lookup table read with 6-bit indices (8-bit)
class sme2_luti6_zt_base<RegisterOperand zd_ty, string asm>
- : I<(outs zd_ty:$Zd), (ins ZTR:$ZTt, ZZZ_Any_Z0Z7:$Zn),
+ : I<(outs zd_ty:$Zd), (ins ZTR:$ZTt, ZZZ_Any_3b:$Zn),
asm, "\t$Zd, $ZTt, $Zn", "", []>, Sched<[]> {
bits<0> ZTt;
bits<3> Zd;
diff --git a/llvm/utils/TableGen/Common/CodeGenRegisters.cpp b/llvm/utils/TableGen/Common/CodeGenRegisters.cpp
index 741e94552639c..9565be8f5e865 100644
--- a/llvm/utils/TableGen/Common/CodeGenRegisters.cpp
+++ b/llvm/utils/TableGen/Common/CodeGenRegisters.cpp
@@ -1323,8 +1323,17 @@ CodeGenRegBank::getOrCreateSubClass(const CodeGenRegisterClass *RC,
if (FoundI != Key2RC.end())
return {FoundI->second, false};
+ auto HasRegClassNamed = [&](StringRef Candidate) {
+ return llvm::any_of(RegClasses, [&](const CodeGenRegisterClass &RC) {
+ return RC.getName() == Candidate;
+ });
+ };
+ std::string UniqueName = Name.str();
+ for (unsigned I = 1; HasRegClassNamed(UniqueName); ++I)
+ UniqueName = (Name + "_" + Twine(I)).str();
+
// Sub-class doesn't exist, create a new one.
- RegClasses.emplace_back(*this, Name, K);
+ RegClasses.emplace_back(*this, UniqueName, K);
addToMaps(&RegClasses.back());
return {&RegClasses.back(), true};
}
More information about the llvm-commits
mailing list