From 2f400a2fd77b44d34281792aca84c42e149095e7 Mon Sep 17 00:00:00 2001 From: Michael Maitland Date: Tue, 12 Mar 2024 20:22:49 -0400 Subject: [GISEL] Add G_VSCALE instruction (#84542) --- llvm/docs/GlobalISel/GenericOpcode.rst | 11 +++++++++++ .../llvm/CodeGen/GlobalISel/MachineIRBuilder.h | 22 ++++++++++++++++++++++ llvm/include/llvm/Support/TargetOpcodes.def | 3 +++ llvm/include/llvm/Target/GenericOpcodes.td | 9 +++++++++ llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp | 18 ++++++++++++++++++ llvm/lib/CodeGen/MachineVerifier.cpp | 11 +++++++++++ .../GlobalISel/legalizer-info-validation.mir | 3 +++ llvm/test/MachineVerifier/test_g_vscale.mir | 15 +++++++++++++++ 8 files changed, 92 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 f9f9e11..bf1b3cb 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 4732eaf..aaa8134 100644 --- a/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h +++ b/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h @@ -1143,6 +1143,28 @@ public: 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. + /// + /// \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/Support/TargetOpcodes.def b/llvm/include/llvm/Support/TargetOpcodes.def index 3dade14..899eaad 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 8dc84fb..67d405b 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 unknown:$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 9b12d44..f7aaa0f 100644 --- a/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp +++ b/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp @@ -793,6 +793,24 @@ 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) { + + 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) { 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 90cbf09..c2d6dd3 100644 --- a/llvm/lib/CodeGen/MachineVerifier.cpp +++ b/llvm/lib/CodeGen/MachineVerifier.cpp @@ -1613,6 +1613,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).isCImm()) { + report("G_VSCALE operand must be cimm", MI); + break; + } + if (MI->getOperand(1).getCImm()->isZero()) { + 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/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir b/llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir index ac33091..c9e5f89 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, 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 # 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 0000000..7885462 --- /dev/null +++ b/llvm/test/MachineVerifier/test_g_vscale.mir @@ -0,0 +1,15 @@ +# RUN: not --crash llc -verify-machineinstrs -run-pass none -o /dev/null %s 2>&1 | FileCheck %s + +--- +name: g_vscale +body: | + bb.0: + + %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 i32 0 +... -- cgit v1.1