[llvm] [GISEL] Add G_VSCALE instruction (PR #84542)
Michael Maitland via llvm-commits
llvm-commits at lists.llvm.org
Mon Mar 11 06:37:22 PDT 2024
https://github.com/michaelmaitland updated https://github.com/llvm/llvm-project/pull/84542
>From cafaae8b558a872bbc9d6d71a15060e17ad70968 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/3] [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 | 11 +++++++++++
.../GlobalISel/legalizer-info-validation.mir | 3 +++
llvm/test/MachineVerifier/test_g_vscale.mir | 16 ++++++++++++++++
8 files changed, 70 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 dda367607d0432..6cfaa566494d23 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_CONCAT_VECTORS
^^^^^^^^^^^^^^^^
diff --git a/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h b/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h
index 6762b1b360d5e8..203fdda1b29234 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h
@@ -1124,6 +1124,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 94fba491148b2e..34e6e665b06e1c 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 insertelement.
HANDLE_TARGET_OPCODE(G_INSERT_VECTOR_ELT)
diff --git a/llvm/include/llvm/Target/GenericOpcodes.td b/llvm/include/llvm/Target/GenericOpcodes.td
index d967885aa2d758..88d23d332b6ada 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 28e5bf85ca9ce6..11c45636daa35f 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 ecb3bd33bdfd49..9ecb1a063bc5e4 100644
--- a/llvm/lib/CodeGen/MachineVerifier.cpp
+++ b/llvm/lib/CodeGen/MachineVerifier.cpp
@@ -1603,6 +1603,17 @@ 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;
+ }
+ break;
+ }
case TargetOpcode::G_SHUFFLE_VECTOR: {
const MachineOperand &MaskOp = MI->getOperand(3);
if (!MaskOp.isShuffleMask()) {
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir b/llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir
index ecad3f11513487..545a555b2e9c4f 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_VECTOR_ELT (opcode {{[0-9]+}}): 3 type indices, 0 imm indices
# DEBUG-NEXT: .. type index coverage check SKIPPED: user-defined predicate detected
# DEBUG-NEXT: .. imm index coverage check SKIPPED: user-defined predicate detected
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 727ec645422ce3fa182d7f7299bfa7256019d891 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/3] 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 7982fdffe845f27c97d0a206206dcbdaa4d3292c 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/3] fixup use ConstantInt to represent G_VSCALE operand
---
.../llvm/CodeGen/GlobalISel/MachineIRBuilder.h | 13 ++++++++++++-
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, 32 insertions(+), 8 deletions(-)
diff --git a/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h b/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h
index 203fdda1b29234..921b8d4d6689e0 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h
@@ -1131,11 +1131,22 @@ 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 88d23d332b6ada..37c5b9f3089141 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 11c45636daa35f..365714d74f522c 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 9ecb1a063bc5e4..d93e56c51d2db9 100644
--- a/llvm/lib/CodeGen/MachineVerifier.cpp
+++ b/llvm/lib/CodeGen/MachineVerifier.cpp
@@ -1604,11 +1604,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 545a555b2e9c4f..e7ac04fd7594ea 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_VECTOR_ELT (opcode {{[0-9]+}}): 3 type indices, 0 imm indices
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
More information about the llvm-commits
mailing list