-
Notifications
You must be signed in to change notification settings - Fork 13.4k
[GISEL] Add G_VSCALE instruction #84542
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
Conversation
@llvm/pr-subscribers-backend-aarch64 @llvm/pr-subscribers-llvm-globalisel Author: Michael Maitland (michaelmaitland) ChangesFull diff: https://github.com/llvm/llvm-project/pull/84542.diff 8 Files Affected:
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..d63f2d628133b6 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
+...
|
✅ With the latest revision this PR passed the C/C++ code formatter. |
e5178b8
to
cafaae8
Compare
@@ -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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The target isn't specified here, and this doesn't need one as written
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated
// operand into the destination register. | ||
def G_VSCALE : GenericInstruction { | ||
let OutOperandList = (outs type0:$dst); | ||
let InOperandList = (ins untyped_imm_0:$src); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure this should be an untyped_imm_0. Does that limit the upper bound of the immediate to 64 or 32 bits? SelectionDAG folds (mul (vscale C1), C2) to (vscale C1*C2). The constant on the mul could be an APInt. So I think we need to allow the immediate to be an APInt.
I see G_CONSTANT uses unknown, but I don't know how unknown vs untyped_imm_0.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For G_CONSTANT, we retrieve the value as following:
std::optional<APInt> getCImmAsAPInt(const MachineInstr *MI) { |
7982fdf
to
ec48477
Compare
258826a
to
1833e2a
Compare
1833e2a
to
36306fd
Compare
No description provided.