Skip to content

[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

Merged
merged 4 commits into from
Mar 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions llvm/docs/GlobalISel/GenericOpcode.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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
^^^^^^^^^^^^^^^^^^

Expand Down
22 changes: 22 additions & 0 deletions llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -1143,6 +1143,28 @@ 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.
///
/// \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
Expand Down
3 changes: 3 additions & 0 deletions llvm/include/llvm/Support/TargetOpcodes.def
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down
9 changes: 9 additions & 0 deletions llvm/include/llvm/Target/GenericOpcodes.td
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
18 changes: 18 additions & 0 deletions llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
11 changes: 11 additions & 0 deletions llvm/lib/CodeGen/MachineVerifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
15 changes: 15 additions & 0 deletions llvm/test/MachineVerifier/test_g_vscale.mir
Original file line number Diff line number Diff line change
@@ -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
...