Skip to content

[AArch64] Verify consecutive vector registers in tbl, tbx #120262

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Dec 20, 2024

Conversation

guy-david
Copy link
Contributor

Table lookup instructions expect the vectors that define the table itself to be consecutive (wraparound allowed).
Relevant documentation:
https://developer.arm.com/documentation/100069/0606/SIMD-Vector-Instructions/TBL--vector-

@llvmbot llvmbot added backend:AArch64 mc Machine (object) code labels Dec 17, 2024
@llvmbot
Copy link
Member

llvmbot commented Dec 17, 2024

@llvm/pr-subscribers-mc

@llvm/pr-subscribers-backend-aarch64

Author: Guy David (guy-david)

Changes

Table lookup instructions expect the vectors that define the table itself to be consecutive (wraparound allowed).
Relevant documentation:
https://developer.arm.com/documentation/100069/0606/SIMD-Vector-Instructions/TBL--vector-


Full diff: https://github.com/llvm/llvm-project/pull/120262.diff

4 Files Affected:

  • (modified) llvm/lib/Target/AArch64/AArch64InstrFormats.td (+16-16)
  • (modified) llvm/lib/Target/AArch64/AArch64RegisterInfo.td (+12-1)
  • (modified) llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp (+5-3)
  • (modified) llvm/test/MC/AArch64/neon-diagnostics.s (+8)
diff --git a/llvm/lib/Target/AArch64/AArch64InstrFormats.td b/llvm/lib/Target/AArch64/AArch64InstrFormats.td
index 56ff7b0d3a280d..47c4c6c39565f4 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrFormats.td
+++ b/llvm/lib/Target/AArch64/AArch64InstrFormats.td
@@ -8528,28 +8528,28 @@ multiclass SIMDTableLookup<bit op, string asm> {
 
   def : SIMDTableLookupAlias<asm # ".8b",
                          !cast<Instruction>(NAME#"v8i8One"),
-                         V64, VecListOne128>;
+                         V64, VecListOneConsecutive128>;
   def : SIMDTableLookupAlias<asm # ".8b",
                          !cast<Instruction>(NAME#"v8i8Two"),
-                         V64, VecListTwo128>;
+                         V64, VecListTwoConsecutive128>;
   def : SIMDTableLookupAlias<asm # ".8b",
                          !cast<Instruction>(NAME#"v8i8Three"),
-                         V64, VecListThree128>;
+                         V64, VecListThreeConsecutive128>;
   def : SIMDTableLookupAlias<asm # ".8b",
                          !cast<Instruction>(NAME#"v8i8Four"),
-                         V64, VecListFour128>;
+                         V64, VecListFourConsecutive128>;
   def : SIMDTableLookupAlias<asm # ".16b",
                          !cast<Instruction>(NAME#"v16i8One"),
-                         V128, VecListOne128>;
+                         V128, VecListOneConsecutive128>;
   def : SIMDTableLookupAlias<asm # ".16b",
                          !cast<Instruction>(NAME#"v16i8Two"),
-                         V128, VecListTwo128>;
+                         V128, VecListTwoConsecutive128>;
   def : SIMDTableLookupAlias<asm # ".16b",
                          !cast<Instruction>(NAME#"v16i8Three"),
-                         V128, VecListThree128>;
+                         V128, VecListThreeConsecutive128>;
   def : SIMDTableLookupAlias<asm # ".16b",
                          !cast<Instruction>(NAME#"v16i8Four"),
-                         V128, VecListFour128>;
+                         V128, VecListFourConsecutive128>;
 }
 
 multiclass SIMDTableLookupTied<bit op, string asm> {
@@ -8572,28 +8572,28 @@ multiclass SIMDTableLookupTied<bit op, string asm> {
 
   def : SIMDTableLookupAlias<asm # ".8b",
                          !cast<Instruction>(NAME#"v8i8One"),
-                         V64, VecListOne128>;
+                         V64, VecListOneConsecutive128>;
   def : SIMDTableLookupAlias<asm # ".8b",
                          !cast<Instruction>(NAME#"v8i8Two"),
-                         V64, VecListTwo128>;
+                         V64, VecListTwoConsecutive128>;
   def : SIMDTableLookupAlias<asm # ".8b",
                          !cast<Instruction>(NAME#"v8i8Three"),
-                         V64, VecListThree128>;
+                         V64, VecListThreeConsecutive128>;
   def : SIMDTableLookupAlias<asm # ".8b",
                          !cast<Instruction>(NAME#"v8i8Four"),
-                         V64, VecListFour128>;
+                         V64, VecListFourConsecutive128>;
   def : SIMDTableLookupAlias<asm # ".16b",
                          !cast<Instruction>(NAME#"v16i8One"),
-                         V128, VecListOne128>;
+                         V128, VecListOneConsecutive128>;
   def : SIMDTableLookupAlias<asm # ".16b",
                          !cast<Instruction>(NAME#"v16i8Two"),
-                         V128, VecListTwo128>;
+                         V128, VecListTwoConsecutive128>;
   def : SIMDTableLookupAlias<asm # ".16b",
                          !cast<Instruction>(NAME#"v16i8Three"),
-                         V128, VecListThree128>;
+                         V128, VecListThreeConsecutive128>;
   def : SIMDTableLookupAlias<asm # ".16b",
                          !cast<Instruction>(NAME#"v16i8Four"),
-                         V128, VecListFour128>;
+                         V128, VecListFourConsecutive128>;
 }
 
 //----------------------------------------------------------------------------
diff --git a/llvm/lib/Target/AArch64/AArch64RegisterInfo.td b/llvm/lib/Target/AArch64/AArch64RegisterInfo.td
index 4fec120391f016..dd4f2549929f84 100644
--- a/llvm/lib/Target/AArch64/AArch64RegisterInfo.td
+++ b/llvm/lib/Target/AArch64/AArch64RegisterInfo.td
@@ -646,7 +646,7 @@ class TypedVecListRegOperand<RegisterClass Reg, int lanes, string eltsize>
                                                    # eltsize # "'>">;
 
 multiclass VectorList<int count, RegisterClass Reg64, RegisterClass Reg128> {
-  // With implicit types (probably on instruction instead). E.g. { v0, v1 }
+  // With implicit types (probably on instruction instead). E.g. { v0, v1 } or {v0, v2, v4}.
   def _64AsmOperand : AsmOperandClass {
     let Name = NAME # "64";
     let PredicateMethod = "isImplicitlyTypedVectorList<RegKind::NeonVector, " # count # ">";
@@ -667,6 +667,17 @@ multiclass VectorList<int count, RegisterClass Reg64, RegisterClass Reg128> {
     let ParserMatchClass = !cast<AsmOperandClass>(NAME # "_128AsmOperand");
   }
 
+  // With implicit types (probably on instruction instead), consecutive registers. E.g. { v0, v1, v2 }
+  def _Consecutive128AsmOperand : AsmOperandClass {
+    let Name = NAME # "Consecutive128";
+    let PredicateMethod = "isImplicitlyTypedVectorList<RegKind::NeonVector, " # count # ", true>";
+    let RenderMethod = "addVectorListOperands<AArch64Operand::VecListIdx_QReg, " # count # ", true>";
+  }
+
+  def "Consecutive128" : RegisterOperand<Reg128, "printImplicitlyTypedVectorList"> {
+    let ParserMatchClass = !cast<AsmOperandClass>(NAME # "_Consecutive128AsmOperand");
+  }
+
   // 64-bit register lists with explicit type.
 
   // { v0.8b, v1.8b }
diff --git a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
index 93c85ba62f90e2..5cda34dd4dde7e 100644
--- a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
+++ b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
@@ -1445,11 +1445,12 @@ class AArch64Operand : public MCParsedAsmOperand {
 
   /// Is this a vector list with the type implicit (presumably attached to the
   /// instruction itself)?
-  template <RegKind VectorKind, unsigned NumRegs>
+  template <RegKind VectorKind, unsigned NumRegs, bool IsConsecutive = false>
   bool isImplicitlyTypedVectorList() const {
     return Kind == k_VectorList && VectorList.Count == NumRegs &&
            VectorList.NumElements == 0 &&
-           VectorList.RegisterKind == VectorKind;
+           VectorList.RegisterKind == VectorKind &&
+           (!IsConsecutive || (VectorList.Stride == 1));
   }
 
   template <RegKind VectorKind, unsigned NumRegs, unsigned NumElements,
@@ -1864,9 +1865,10 @@ class AArch64Operand : public MCParsedAsmOperand {
     VecListIdx_PReg = 3,
   };
 
-  template <VecListIndexType RegTy, unsigned NumRegs>
+  template <VecListIndexType RegTy, unsigned NumRegs, bool IsConsecutive = false>
   void addVectorListOperands(MCInst &Inst, unsigned N) const {
     assert(N == 1 && "Invalid number of operands!");
+    assert((!IsConsecutive || (getVectorListStride() == 1)) && "Expected consecutive registers");
     static const unsigned FirstRegs[][5] = {
       /* DReg */ { AArch64::Q0,
                    AArch64::D0,       AArch64::D0_D1,
diff --git a/llvm/test/MC/AArch64/neon-diagnostics.s b/llvm/test/MC/AArch64/neon-diagnostics.s
index 6863a89bbe189e..8449ebbdef7ef6 100644
--- a/llvm/test/MC/AArch64/neon-diagnostics.s
+++ b/llvm/test/MC/AArch64/neon-diagnostics.s
@@ -6914,6 +6914,7 @@
         tbl v0.8b, {v1.8b, v2.8b, v3.8b}, v2.8b
         tbl v0.8b, {v1.8b, v2.8b, v3.8b, v4.8b}, v2.8b
         tbl v0.8b, {v1.16b, v2.16b, v3.16b, v4.16b, v5.16b}, v2.8b
+        tbl.8b v0, {v2, v4, v6, v8}, v10
 
 // CHECK-ERROR: error: invalid operand for instruction
 // CHECK-ERROR:        tbl v0.8b, {v1.8b}, v2.8b
@@ -6930,12 +6931,16 @@
 // CHECK-ERROR: error: invalid number of vectors
 // CHECK-ERROR:        tbl v0.8b, {v1.16b, v2.16b, v3.16b, v4.16b, v5.16b}, v2.8b
 // CHECK-ERROR:                                                    ^
+// CHECK-ERROR: error: invalid operand for instruction
+// CHECK-ERROR:        tbl.8b v0, {v2, v4, v6, v8}, v10
+// CHECK-ERROR:                            ^
 
         tbx v0.8b, {v1.8b}, v2.8b
         tbx v0.8b, {v1.8b, v2.8b}, v2.8b
         tbx v0.8b, {v1.8b, v2.8b, v3.8b}, v2.8b
         tbx v0.8b, {v1.8b, v2.8b, v3.8b, v4.8b}, v2.8b
         tbx v0.8b, {v1.16b, v2.16b, v3.16b, v4.16b, v5.16b}, v2.8b
+        tbx.8b v0, {v2, v4, v6, v8}, v10
 
 // CHECK-ERROR: error: invalid operand for instruction
 // CHECK-ERROR:        tbx v0.8b, {v1.8b}, v2.8b
@@ -6952,6 +6957,9 @@
 // CHECK-ERROR: error: invalid number of vectors
 // CHECK-ERROR:        tbx v0.8b, {v1.16b, v2.16b, v3.16b, v4.16b, v5.16b}, v2.8b
 // CHECK-ERROR:                                                    ^
+// CHECK-ERROR: error: invalid operand for instruction
+// CHECK-ERROR:        tbx.8b v0, {v2, v4, v6, v8}, v10
+// CHECK-ERROR:                            ^
 
 //----------------------------------------------------------------------
 // Scalar Floating-point Convert To Lower Precision Narrow, Rounding To

Copy link

github-actions bot commented Dec 17, 2024

✅ With the latest revision this PR passed the C/C++ code formatter.

Table lookup instructions expect the vectors that define the table
itself to be consecutive (wraparound allowed).
Relevant documentation:
https://developer.arm.com/documentation/100069/0606/SIMD-Vector-Instructions/TBL--vector-
Copy link
Collaborator

@ostannard ostannard left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@guy-david guy-david force-pushed the aarch64-table-lookup-consecutive branch from a41b23d to 7e210b6 Compare December 19, 2024 09:16
@guy-david guy-david merged commit 5e22597 into llvm:main Dec 20, 2024
11 checks passed
guy-david added a commit to swiftlang/llvm-project that referenced this pull request Mar 23, 2025
Table lookup instructions expect the vectors that define the table
itself to be consecutive (wraparound allowed).
Relevant documentation:

https://developer.arm.com/documentation/100069/0606/SIMD-Vector-Instructions/TBL--vector-
guy-david added a commit to swiftlang/llvm-project that referenced this pull request Mar 24, 2025
🍒 [AArch64] Verify consecutive vector registers in tbl, tbx (llvm#120262)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backend:AArch64 mc Machine (object) code
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants