Skip to content

Commit 2f400a2

Browse files
[GISEL] Add G_VSCALE instruction (#84542)
1 parent e2468bf commit 2f400a2

File tree

8 files changed

+92
-0
lines changed

8 files changed

+92
-0
lines changed

llvm/docs/GlobalISel/GenericOpcode.rst

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -607,6 +607,17 @@ See the LLVM LangRef entry on '``llvm.lround.*'`` for details on behaviour.
607607
Vector Specific Operations
608608
--------------------------
609609

610+
G_VSCALE
611+
^^^^^^^^
612+
613+
Puts the value of the runtime ``vscale`` multiplied by the value in the source
614+
operand into the destination register. This can be useful in determining the
615+
actual runtime number of elements in a vector.
616+
617+
.. code-block::
618+
619+
%0:_(s32) = G_VSCALE 4
620+
610621
G_INSERT_SUBVECTOR
611622
^^^^^^^^^^^^^^^^^^
612623

llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1143,6 +1143,28 @@ class MachineIRBuilder {
11431143
MachineInstrBuilder buildInsert(const DstOp &Res, const SrcOp &Src,
11441144
const SrcOp &Op, unsigned Index);
11451145

1146+
/// Build and insert \p Res = G_VSCALE \p MinElts
1147+
///
1148+
/// G_VSCALE puts the value of the runtime vscale multiplied by \p MinElts
1149+
/// into \p Res.
1150+
///
1151+
/// \pre setBasicBlock or setMI must have been called.
1152+
/// \pre \p Res must be a generic virtual register with scalar type.
1153+
///
1154+
/// \return a MachineInstrBuilder for the newly created instruction.
1155+
MachineInstrBuilder buildVScale(const DstOp &Res, unsigned MinElts);
1156+
1157+
/// Build and insert \p Res = G_VSCALE \p MinElts
1158+
///
1159+
/// G_VSCALE puts the value of the runtime vscale multiplied by \p MinElts
1160+
/// into \p Res.
1161+
///
1162+
/// \pre setBasicBlock or setMI must have been called.
1163+
/// \pre \p Res must be a generic virtual register with scalar type.
1164+
///
1165+
/// \return a MachineInstrBuilder for the newly created instruction.
1166+
MachineInstrBuilder buildVScale(const DstOp &Res, const ConstantInt &MinElts);
1167+
11461168
/// Build and insert a G_INTRINSIC instruction.
11471169
///
11481170
/// There are four different opcodes based on combinations of whether the

llvm/include/llvm/Support/TargetOpcodes.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -727,6 +727,9 @@ HANDLE_TARGET_OPCODE(G_BR)
727727
/// Generic branch to jump table entry.
728728
HANDLE_TARGET_OPCODE(G_BRJT)
729729

730+
/// Generic vscale.
731+
HANDLE_TARGET_OPCODE(G_VSCALE)
732+
730733
/// Generic insert subvector.
731734
HANDLE_TARGET_OPCODE(G_INSERT_SUBVECTOR)
732735

llvm/include/llvm/Target/GenericOpcodes.td

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1289,6 +1289,15 @@ def G_MERGE_VALUES : GenericInstruction {
12891289
let variadicOpsType = type1;
12901290
}
12911291

1292+
// Generic vscale.
1293+
// Puts the value of the runtime vscale multiplied by the value in the source
1294+
// operand into the destination register.
1295+
def G_VSCALE : GenericInstruction {
1296+
let OutOperandList = (outs type0:$dst);
1297+
let InOperandList = (ins unknown:$src);
1298+
let hasSideEffects = false;
1299+
}
1300+
12921301
/// Create a vector from multiple scalar registers. No implicit
12931302
/// conversion is performed (i.e. the result element type must be the
12941303
/// same as all source operands)

llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -793,6 +793,24 @@ MachineInstrBuilder MachineIRBuilder::buildInsert(const DstOp &Res,
793793
return buildInstr(TargetOpcode::G_INSERT, Res, {Src, Op, uint64_t(Index)});
794794
}
795795

796+
MachineInstrBuilder MachineIRBuilder::buildVScale(const DstOp &Res,
797+
unsigned MinElts) {
798+
799+
auto IntN = IntegerType::get(getMF().getFunction().getContext(),
800+
Res.getLLTTy(*getMRI()).getScalarSizeInBits());
801+
ConstantInt *CI = ConstantInt::get(IntN, MinElts);
802+
return buildVScale(Res, *CI);
803+
}
804+
805+
MachineInstrBuilder MachineIRBuilder::buildVScale(const DstOp &Res,
806+
const ConstantInt &MinElts) {
807+
auto VScale = buildInstr(TargetOpcode::G_VSCALE);
808+
VScale->setDebugLoc(DebugLoc());
809+
Res.addDefToMIB(*getMRI(), VScale);
810+
VScale.addCImm(&MinElts);
811+
return VScale;
812+
}
813+
796814
static unsigned getIntrinsicOpcode(bool HasSideEffects, bool IsConvergent) {
797815
if (HasSideEffects && IsConvergent)
798816
return TargetOpcode::G_INTRINSIC_CONVERGENT_W_SIDE_EFFECTS;

llvm/lib/CodeGen/MachineVerifier.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1613,6 +1613,17 @@ void MachineVerifier::verifyPreISelGenericInstruction(const MachineInstr *MI) {
16131613
report("G_BSWAP size must be a multiple of 16 bits", MI);
16141614
break;
16151615
}
1616+
case TargetOpcode::G_VSCALE: {
1617+
if (!MI->getOperand(1).isCImm()) {
1618+
report("G_VSCALE operand must be cimm", MI);
1619+
break;
1620+
}
1621+
if (MI->getOperand(1).getCImm()->isZero()) {
1622+
report("G_VSCALE immediate cannot be zero", MI);
1623+
break;
1624+
}
1625+
break;
1626+
}
16161627
case TargetOpcode::G_INSERT_SUBVECTOR: {
16171628
const MachineOperand &Src0Op = MI->getOperand(1);
16181629
if (!Src0Op.isReg()) {

llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -616,6 +616,9 @@
616616
# DEBUG-NEXT: G_BRJT (opcode {{[0-9]+}}): 2 type indices
617617
# DEBUG-NEXT: .. the first uncovered type index: 2, OK
618618
# DEBUG-NEXT: .. the first uncovered imm index: 0, OK
619+
# DEBUG-NEXT: G_VSCALE (opcode {{[0-9]+}}): 1 type index, 0 imm indices
620+
# DEBUG-NEXT: .. type index coverage check SKIPPED: no rules defined
621+
# DEBUG-NEXT: .. imm index coverage check SKIPPED: no rules defined
619622
# DEBUG-NEXT: G_INSERT_SUBVECTOR (opcode {{[0-9]+}}): 2 type indices, 1 imm index
620623
# DEBUG-NEXT: .. type index coverage check SKIPPED: no rules defined
621624
# DEBUG-NEXT: .. imm index coverage check SKIPPED: no rules defined
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# RUN: not --crash llc -verify-machineinstrs -run-pass none -o /dev/null %s 2>&1 | FileCheck %s
2+
3+
---
4+
name: g_vscale
5+
body: |
6+
bb.0:
7+
8+
%1:_(s32) = G_CONSTANT i32 4
9+
10+
; CHECK: G_VSCALE operand must be cimm
11+
%2:_(s32) = G_VSCALE %1
12+
13+
; CHECK: G_VSCALE immediate cannot be zero
14+
%3:_(s32) = G_VSCALE i32 0
15+
...

0 commit comments

Comments
 (0)