[llvm] [AArch64][llvm] Restrict luti6 (4 regs, 8-bit) to 0 <= Zn <= 7 (PR #200751)

Jonathan Thackray via llvm-commits llvm-commits at lists.llvm.org
Mon Jun 1 01:24:58 PDT 2026


https://github.com/jthackray created https://github.com/llvm/llvm-project/pull/200751

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.

>From 0cb280f343c55beb46fa3bd4242caae1f425277c 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] [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 99836aeed7c0a..c9667cb26053a 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 }



More information about the llvm-commits mailing list