[llvm] [GISEL] Add G_VSCALE instruction (PR #84542)

Michael Maitland via llvm-commits llvm-commits at lists.llvm.org
Tue Mar 12 11:30:23 PDT 2024


https://github.com/michaelmaitland updated https://github.com/llvm/llvm-project/pull/84542

>From f85a126e76b81bd87b421b84697355517d079c62 Mon Sep 17 00:00:00 2001
From: Michael Maitland <michaeltmaitland at gmail.com>
Date: Wed, 6 Mar 2024 12:54:05 -0800
Subject: [PATCH 1/4] [GISEL] Add G_VSCALE instruction

---
 llvm/docs/GlobalISel/GenericOpcode.rst           | 11 +++++++++++
 .../llvm/CodeGen/GlobalISel/MachineIRBuilder.h   | 12 ++++++++++++
 llvm/include/llvm/Support/TargetOpcodes.def      |  3 +++
 llvm/include/llvm/Target/GenericOpcodes.td       |  9 +++++++++
 llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp |  5 +++++
 llvm/lib/CodeGen/MachineVerifier.cpp             | 10 ++++++++++
 .../GlobalISel/legalizer-info-validation.mir     |  3 +++
 llvm/test/MachineVerifier/test_g_vscale.mir      | 16 ++++++++++++++++
 8 files changed, 69 insertions(+)
 create mode 100644 llvm/test/MachineVerifier/test_g_vscale.mir

diff --git a/llvm/docs/GlobalISel/GenericOpcode.rst b/llvm/docs/GlobalISel/GenericOpcode.rst
index f9f9e1186460ee..bf1b3cb30a52e5 100644
--- a/llvm/docs/GlobalISel/GenericOpcode.rst
+++ b/llvm/docs/GlobalISel/GenericOpcode.rst
@@ -607,6 +607,17 @@ See the LLVM LangRef entry on '``llvm.lround.*'`` for details on behaviour.
 Vector Specific Operations
 --------------------------
 
+G_VSCALE
+^^^^^^^^
+
+Puts the value of the runtime ``vscale`` multiplied by the value in the source
+operand into the destination register. This can be useful in determining the
+actual runtime number of elements in a vector.
+
+.. code-block::
+
+  %0:_(s32) = G_VSCALE 4
+
 G_INSERT_SUBVECTOR
 ^^^^^^^^^^^^^^^^^^
 
diff --git a/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h b/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h
index 4732eaf4ee27c5..85affb9d784f80 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h
@@ -1143,6 +1143,18 @@ class MachineIRBuilder {
   MachineInstrBuilder buildInsert(const DstOp &Res, const SrcOp &Src,
                                   const SrcOp &Op, unsigned Index);
 
+  /// Build and insert \p Res = G_VSCALE \p MinElts
+  ///
+  /// G_VSCALE puts the value of the runtime vscale multiplied by \p MinElts
+  /// into \p Res.
+  ///
+  /// \pre setBasicBlock or setMI must have been called.
+  /// \pre \p Res must be a generic virtual register with scalar type.
+  /// \pre \p Src must be a generic virtual register with scalar type.
+  ///
+  /// \return a MachineInstrBuilder for the newly created instruction.
+  MachineInstrBuilder buildVScale(const DstOp &Res, unsigned MinElts);
+
   /// Build and insert a G_INTRINSIC instruction.
   ///
   /// There are four different opcodes based on combinations of whether the
diff --git a/llvm/include/llvm/Support/TargetOpcodes.def b/llvm/include/llvm/Support/TargetOpcodes.def
index 3dade14f043b60..899eaad5842ae0 100644
--- a/llvm/include/llvm/Support/TargetOpcodes.def
+++ b/llvm/include/llvm/Support/TargetOpcodes.def
@@ -727,6 +727,9 @@ HANDLE_TARGET_OPCODE(G_BR)
 /// Generic branch to jump table entry.
 HANDLE_TARGET_OPCODE(G_BRJT)
 
+/// Generic vscale.
+HANDLE_TARGET_OPCODE(G_VSCALE)
+
 /// Generic insert subvector.
 HANDLE_TARGET_OPCODE(G_INSERT_SUBVECTOR)
 
diff --git a/llvm/include/llvm/Target/GenericOpcodes.td b/llvm/include/llvm/Target/GenericOpcodes.td
index 8dc84fb0ba0524..b044b8efd42056 100644
--- a/llvm/include/llvm/Target/GenericOpcodes.td
+++ b/llvm/include/llvm/Target/GenericOpcodes.td
@@ -1289,6 +1289,15 @@ def G_MERGE_VALUES : GenericInstruction {
   let variadicOpsType = type1;
 }
 
+// Generic vscale.
+// Puts the value of the runtime vscale multiplied by the value in the source
+// operand into the destination register.
+def G_VSCALE : GenericInstruction {
+  let OutOperandList = (outs type0:$dst);
+  let InOperandList = (ins untyped_imm_0:$src);
+  let hasSideEffects = false;
+}
+
 /// Create a vector from multiple scalar registers. No implicit
 /// conversion is performed (i.e. the result element type must be the
 /// same as all source operands)
diff --git a/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp b/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp
index 9b12d443c96e98..ce6a2f9ca087ee 100644
--- a/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp
@@ -793,6 +793,11 @@ MachineInstrBuilder MachineIRBuilder::buildInsert(const DstOp &Res,
   return buildInstr(TargetOpcode::G_INSERT, Res, {Src, Op, uint64_t(Index)});
 }
 
+MachineInstrBuilder MachineIRBuilder::buildVScale(const DstOp &Res,
+                                                  unsigned MinElts) {
+  return buildInstr(TargetOpcode::G_VSCALE, {Res}, {uint64_t(MinElts)});
+}
+
 static unsigned getIntrinsicOpcode(bool HasSideEffects, bool IsConvergent) {
   if (HasSideEffects && IsConvergent)
     return TargetOpcode::G_INTRINSIC_CONVERGENT_W_SIDE_EFFECTS;
diff --git a/llvm/lib/CodeGen/MachineVerifier.cpp b/llvm/lib/CodeGen/MachineVerifier.cpp
index 90cbf097370de2..cd0b795e7e39ee 100644
--- a/llvm/lib/CodeGen/MachineVerifier.cpp
+++ b/llvm/lib/CodeGen/MachineVerifier.cpp
@@ -1613,6 +1613,16 @@ void MachineVerifier::verifyPreISelGenericInstruction(const MachineInstr *MI) {
       report("G_BSWAP size must be a multiple of 16 bits", MI);
     break;
   }
+  case TargetOpcode::G_VSCALE: {
+    if (!MI->getOperand(1).isImm()) {
+      report("G_VSCALE operand #1 must be an immediate", MI);
+      break;
+    }
+    if (MI->getOperand(1).getImm() == 0) {
+      report("G_VSCALE immediate cannot be zero", MI);
+      break;
+    }
+
   case TargetOpcode::G_INSERT_SUBVECTOR: {
     const MachineOperand &Src0Op = MI->getOperand(1);
     if (!Src0Op.isReg()) {
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir b/llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir
index ac330918b430a0..c9ebbf3e738d48 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir
@@ -616,6 +616,9 @@
 # DEBUG-NEXT: G_BRJT (opcode {{[0-9]+}}): 2 type indices
 # DEBUG-NEXT: .. the first uncovered type index: 2, OK
 # DEBUG-NEXT: .. the first uncovered imm index: 0, OK
+# DEBUG-NEXT: G_VSCALE (opcode {{[0-9]+}}): 1 type index, 1 imm index
+# DEBUG-NEXT: .. type index coverage check SKIPPED: no rules defined
+# DEBUG-NEXT: .. imm index coverage check SKIPPED: no rules defined
 # DEBUG-NEXT: G_INSERT_SUBVECTOR (opcode {{[0-9]+}}): 2 type indices, 1 imm index
 # DEBUG-NEXT: .. type index coverage check SKIPPED: no rules defined
 # DEBUG-NEXT: .. imm index coverage check SKIPPED: no rules defined
diff --git a/llvm/test/MachineVerifier/test_g_vscale.mir b/llvm/test/MachineVerifier/test_g_vscale.mir
new file mode 100644
index 00000000000000..74c147a42bc6ee
--- /dev/null
+++ b/llvm/test/MachineVerifier/test_g_vscale.mir
@@ -0,0 +1,16 @@
+# RUN: not --crash llc -verify-machineinstrs -run-pass none -o /dev/null %s 2>&1 | FileCheck %s
+# REQUIRES: aarch64-registered-target
+
+---
+name:            g_vscale
+body: |
+  bb.0:
+
+  %1:_(s32) = G_CONSTANT 4
+
+  ; CHECK: G_VSCALE operand #1 must be an immediate
+  %2:_(s32) = G_VSCALE %1
+
+  ; CHECK: G_VSCALE immediate cannot be zero
+  %3:_(s32) = G_VSCALE 0
+...

>From 8770ba0541d081397c4954d41646a66cf2d3af48 Mon Sep 17 00:00:00 2001
From: Michael Maitland <michaeltmaitland at gmail.com>
Date: Sat, 9 Mar 2024 08:24:47 -0800
Subject: [PATCH 2/4] fixup! remove requires

---
 llvm/test/MachineVerifier/test_g_vscale.mir | 1 -
 1 file changed, 1 deletion(-)

diff --git a/llvm/test/MachineVerifier/test_g_vscale.mir b/llvm/test/MachineVerifier/test_g_vscale.mir
index 74c147a42bc6ee..e068c2e1fc464e 100644
--- a/llvm/test/MachineVerifier/test_g_vscale.mir
+++ b/llvm/test/MachineVerifier/test_g_vscale.mir
@@ -1,5 +1,4 @@
 # RUN: not --crash llc -verify-machineinstrs -run-pass none -o /dev/null %s 2>&1 | FileCheck %s
-# REQUIRES: aarch64-registered-target
 
 ---
 name:            g_vscale

>From e13e848a00e74c327f3f3f38295421be3dc90344 Mon Sep 17 00:00:00 2001
From: Michael Maitland <michaeltmaitland at gmail.com>
Date: Mon, 11 Mar 2024 06:37:05 -0700
Subject: [PATCH 3/4] fixup! use ConstantInt to represent G_VSCALE operand

---
 .../llvm/CodeGen/GlobalISel/MachineIRBuilder.h    | 12 +++++++++++-
 llvm/include/llvm/Target/GenericOpcodes.td        |  2 +-
 llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp  | 15 ++++++++++++++-
 llvm/lib/CodeGen/MachineVerifier.cpp              |  6 +++---
 .../GlobalISel/legalizer-info-validation.mir      |  2 +-
 llvm/test/MachineVerifier/test_g_vscale.mir       |  2 +-
 6 files changed, 31 insertions(+), 8 deletions(-)

diff --git a/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h b/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h
index 85affb9d784f80..aaa81342845bff 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h
@@ -1150,11 +1150,21 @@ class MachineIRBuilder {
   ///
   /// \pre setBasicBlock or setMI must have been called.
   /// \pre \p Res must be a generic virtual register with scalar type.
-  /// \pre \p Src must be a generic virtual register with scalar type.
   ///
   /// \return a MachineInstrBuilder for the newly created instruction.
   MachineInstrBuilder buildVScale(const DstOp &Res, unsigned MinElts);
 
+  /// Build and insert \p Res = G_VSCALE \p MinElts
+  ///
+  /// G_VSCALE puts the value of the runtime vscale multiplied by \p MinElts
+  /// into \p Res.
+  ///
+  /// \pre setBasicBlock or setMI must have been called.
+  /// \pre \p Res must be a generic virtual register with scalar type.
+  ///
+  /// \return a MachineInstrBuilder for the newly created instruction.
+  MachineInstrBuilder buildVScale(const DstOp &Res, const ConstantInt &MinElts);
+
   /// Build and insert a G_INTRINSIC instruction.
   ///
   /// There are four different opcodes based on combinations of whether the
diff --git a/llvm/include/llvm/Target/GenericOpcodes.td b/llvm/include/llvm/Target/GenericOpcodes.td
index b044b8efd42056..67d405ba96fa10 100644
--- a/llvm/include/llvm/Target/GenericOpcodes.td
+++ b/llvm/include/llvm/Target/GenericOpcodes.td
@@ -1294,7 +1294,7 @@ def G_MERGE_VALUES : GenericInstruction {
 // operand into the destination register.
 def G_VSCALE : GenericInstruction {
   let OutOperandList = (outs type0:$dst);
-  let InOperandList = (ins untyped_imm_0:$src);
+  let InOperandList = (ins unknown:$src);
   let hasSideEffects = false;
 }
 
diff --git a/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp b/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp
index ce6a2f9ca087ee..f7aaa0f02efcb3 100644
--- a/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp
@@ -795,7 +795,20 @@ MachineInstrBuilder MachineIRBuilder::buildInsert(const DstOp &Res,
 
 MachineInstrBuilder MachineIRBuilder::buildVScale(const DstOp &Res,
                                                   unsigned MinElts) {
-  return buildInstr(TargetOpcode::G_VSCALE, {Res}, {uint64_t(MinElts)});
+
+  auto IntN = IntegerType::get(getMF().getFunction().getContext(),
+                               Res.getLLTTy(*getMRI()).getScalarSizeInBits());
+  ConstantInt *CI = ConstantInt::get(IntN, MinElts);
+  return buildVScale(Res, *CI);
+}
+
+MachineInstrBuilder MachineIRBuilder::buildVScale(const DstOp &Res,
+                                                  const ConstantInt &MinElts) {
+  auto VScale = buildInstr(TargetOpcode::G_VSCALE);
+  VScale->setDebugLoc(DebugLoc());
+  Res.addDefToMIB(*getMRI(), VScale);
+  VScale.addCImm(&MinElts);
+  return VScale;
 }
 
 static unsigned getIntrinsicOpcode(bool HasSideEffects, bool IsConvergent) {
diff --git a/llvm/lib/CodeGen/MachineVerifier.cpp b/llvm/lib/CodeGen/MachineVerifier.cpp
index cd0b795e7e39ee..c7098d0b7b912a 100644
--- a/llvm/lib/CodeGen/MachineVerifier.cpp
+++ b/llvm/lib/CodeGen/MachineVerifier.cpp
@@ -1614,11 +1614,11 @@ void MachineVerifier::verifyPreISelGenericInstruction(const MachineInstr *MI) {
     break;
   }
   case TargetOpcode::G_VSCALE: {
-    if (!MI->getOperand(1).isImm()) {
-      report("G_VSCALE operand #1 must be an immediate", MI);
+    if (!MI->getOperand(1).isCImm()) {
+      report("G_VSCALE operand must be cimm", MI);
       break;
     }
-    if (MI->getOperand(1).getImm() == 0) {
+    if (MI->getOperand(1).getCImm()->isZero()) {
       report("G_VSCALE immediate cannot be zero", MI);
       break;
     }
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir b/llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir
index c9ebbf3e738d48..c9e5f8924f8a0e 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir
@@ -616,7 +616,7 @@
 # DEBUG-NEXT: G_BRJT (opcode {{[0-9]+}}): 2 type indices
 # DEBUG-NEXT: .. the first uncovered type index: 2, OK
 # DEBUG-NEXT: .. the first uncovered imm index: 0, OK
-# DEBUG-NEXT: G_VSCALE (opcode {{[0-9]+}}): 1 type index, 1 imm index
+# DEBUG-NEXT: G_VSCALE (opcode {{[0-9]+}}): 1 type index, 0 imm indices
 # DEBUG-NEXT: .. type index coverage check SKIPPED: no rules defined
 # DEBUG-NEXT: .. imm index coverage check SKIPPED: no rules defined
 # DEBUG-NEXT: G_INSERT_SUBVECTOR (opcode {{[0-9]+}}): 2 type indices, 1 imm index
diff --git a/llvm/test/MachineVerifier/test_g_vscale.mir b/llvm/test/MachineVerifier/test_g_vscale.mir
index e068c2e1fc464e..009658a14e4361 100644
--- a/llvm/test/MachineVerifier/test_g_vscale.mir
+++ b/llvm/test/MachineVerifier/test_g_vscale.mir
@@ -7,7 +7,7 @@ body: |
 
   %1:_(s32) = G_CONSTANT 4
 
-  ; CHECK: G_VSCALE operand #1 must be an immediate
+  ; CHECK: G_VSCALE operand must be cimm
   %2:_(s32) = G_VSCALE %1
 
   ; CHECK: G_VSCALE immediate cannot be zero

>From 36306fddad98eaebc75093d07c48fa57fa0588d9 Mon Sep 17 00:00:00 2001
From: Michael Maitland <michaeltmaitland at gmail.com>
Date: Mon, 11 Mar 2024 08:40:02 -0700
Subject: [PATCH 4/4] fixup! fix test case

---
 llvm/lib/CodeGen/MachineVerifier.cpp        | 3 ++-
 llvm/test/MachineVerifier/test_g_vscale.mir | 4 ++--
 2 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/llvm/lib/CodeGen/MachineVerifier.cpp b/llvm/lib/CodeGen/MachineVerifier.cpp
index c7098d0b7b912a..c2d6dd35e1cb21 100644
--- a/llvm/lib/CodeGen/MachineVerifier.cpp
+++ b/llvm/lib/CodeGen/MachineVerifier.cpp
@@ -1622,7 +1622,8 @@ void MachineVerifier::verifyPreISelGenericInstruction(const MachineInstr *MI) {
       report("G_VSCALE immediate cannot be zero", MI);
       break;
     }
-
+    break;
+  }
   case TargetOpcode::G_INSERT_SUBVECTOR: {
     const MachineOperand &Src0Op = MI->getOperand(1);
     if (!Src0Op.isReg()) {
diff --git a/llvm/test/MachineVerifier/test_g_vscale.mir b/llvm/test/MachineVerifier/test_g_vscale.mir
index 009658a14e4361..78854620913a16 100644
--- a/llvm/test/MachineVerifier/test_g_vscale.mir
+++ b/llvm/test/MachineVerifier/test_g_vscale.mir
@@ -5,11 +5,11 @@ name:            g_vscale
 body: |
   bb.0:
 
-  %1:_(s32) = G_CONSTANT 4
+  %1:_(s32) = G_CONSTANT i32 4
 
   ; CHECK: G_VSCALE operand must be cimm
   %2:_(s32) = G_VSCALE %1
 
   ; CHECK: G_VSCALE immediate cannot be zero
-  %3:_(s32) = G_VSCALE 0
+  %3:_(s32) = G_VSCALE i32 0
 ...



More information about the llvm-commits mailing list