Skip to content

Commit db00814

Browse files
[GISEL] Add G_INSERT_SUBVECTOR and G_EXTRACT_SUBVECTOR
G_INSERT and G_EXTRACT are not sufficient to use to represent both INSERT/EXTRACT on a subregister and INSERT/EXTRACT on a vector. We would like to be able to INSERT/EXTRACT on vectors in cases that INSERT/EXTRACT on vector subregisters are not sufficient, so we add these opcodes.
1 parent 9405d5a commit db00814

File tree

8 files changed

+264
-0
lines changed

8 files changed

+264
-0
lines changed

llvm/docs/GlobalISel/GenericOpcode.rst

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

610+
G_INSERT_SUBVECTOR
611+
^^^^^^^^^^^^^^^^^^
612+
613+
Insert the second source vector into the first source vector. The index operand
614+
represents the starting index in the first source vector at which the second
615+
source vector should be inserted into.
616+
617+
The index must be a constant multiple of the second source vector's minimum
618+
vector length. If the vectors are scalable, then the index is first scaled by
619+
the runtime scaling factor. The indices inserted in the source vector must be
620+
valid indicies of that vector. If this condition cannot be determined statically
621+
but is false at runtime, then the result vector is undefined.
622+
623+
.. code-block:: none
624+
625+
%2:_(<vscale x 4 x i64>) = G_INSERT_SUBVECTOR %0:_(<vscale x 4 x i64>), %1:_(<vscale x 2 x i64>), 0
626+
627+
G_EXTRACT_SUBVECTOR
628+
^^^^^^^^^^^^^^^^^^^
629+
630+
Extract a vector of destination type from the source vector. The index operand
631+
represents the starting index from which a subvector is extracted from
632+
the source vector.
633+
634+
The index must be a constant multiple of the source vector's minimum vector
635+
length. If the source vector is a scalable vector, then the index is first
636+
scaled by the runtime scaling factor. The indices extracted from the source
637+
vector must be valid indicies of that vector. If this condition cannot be
638+
determined statically but is false at runtime, then the result vector is
639+
undefined.
640+
641+
.. code-block:: none
642+
643+
%3:_(<vscale x 4 x i64>) = G_EXTRACT_SUBVECTOR %2:_(<vscale x 8 x i64>), 2
644+
610645
G_CONCAT_VECTORS
611646
^^^^^^^^^^^^^^^^
612647

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

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1121,6 +1121,25 @@ class MachineIRBuilder {
11211121
MachineInstrBuilder buildConcatVectors(const DstOp &Res,
11221122
ArrayRef<Register> Ops);
11231123

1124+
/// Build and insert `Res = G_INSERT_SUBVECTOR Src0, Src1, Idx`.
1125+
///
1126+
/// \pre setBasicBlock or setMI must have been called.
1127+
/// \pre \p Res, \p Src0, and \p Src1 must be generic virtual registers with
1128+
/// vector type.
1129+
///
1130+
/// \return a MachineInstrBuilder for the newly created instruction.
1131+
MachineInstrBuilder buildInsertSubvector(const DstOp &Res, const SrcOp &Src0,
1132+
const SrcOp &Src1, unsigned Index);
1133+
1134+
/// Build and insert `Res = G_EXTRACT_SUBVECTOR Src, Idx0`.
1135+
///
1136+
/// \pre setBasicBlock or setMI must have been called.
1137+
/// \pre \p Res and \p Src must be generic virtual registers with vector type.
1138+
///
1139+
/// \return a MachineInstrBuilder for the newly created instruction.
1140+
MachineInstrBuilder buildExtractSubvector(const DstOp &Res, const SrcOp &Src,
1141+
unsigned Index);
1142+
11241143
MachineInstrBuilder buildInsert(const DstOp &Res, const SrcOp &Src,
11251144
const SrcOp &Op, unsigned Index);
11261145

llvm/include/llvm/Support/TargetOpcodes.def

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

730+
/// Generic insert subvector.
731+
HANDLE_TARGET_OPCODE(G_INSERT_SUBVECTOR)
732+
733+
/// Generic extract subvector.
734+
HANDLE_TARGET_OPCODE(G_EXTRACT_SUBVECTOR)
735+
730736
/// Generic insertelement.
731737
HANDLE_TARGET_OPCODE(G_INSERT_VECTOR_ELT)
732738

llvm/include/llvm/Target/GenericOpcodes.td

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1426,6 +1426,20 @@ def G_WRITE_REGISTER : GenericInstruction {
14261426
// Vector ops
14271427
//------------------------------------------------------------------------------
14281428

1429+
// Generic insert subvector.
1430+
def G_INSERT_SUBVECTOR : GenericInstruction {
1431+
let OutOperandList = (outs type0:$dst);
1432+
let InOperandList = (ins type0:$src0, type1:$src1, untyped_imm_0:$idx);
1433+
let hasSideEffects = false;
1434+
}
1435+
1436+
// Generic extract subvector.
1437+
def G_EXTRACT_SUBVECTOR : GenericInstruction {
1438+
let OutOperandList = (outs type0:$dst);
1439+
let InOperandList = (ins type0:$src, untyped_imm_0:$idx);
1440+
let hasSideEffects = false;
1441+
}
1442+
14291443
// Generic insertelement.
14301444
def G_INSERT_VECTOR_ELT : GenericInstruction {
14311445
let OutOperandList = (outs type0:$dst);

llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -877,6 +877,21 @@ MachineIRBuilder::buildSelect(const DstOp &Res, const SrcOp &Tst,
877877
return buildInstr(TargetOpcode::G_SELECT, {Res}, {Tst, Op0, Op1}, Flags);
878878
}
879879

880+
MachineInstrBuilder MachineIRBuilder::buildInsertSubvector(const DstOp &Res,
881+
const SrcOp &Src0,
882+
const SrcOp &Src1,
883+
unsigned Idx) {
884+
return buildInstr(TargetOpcode::G_INSERT_SUBVECTOR, Res,
885+
{Src0, Src1, uint64_t(Idx)});
886+
}
887+
888+
MachineInstrBuilder MachineIRBuilder::buildExtractSubvector(const DstOp &Res,
889+
const SrcOp &Src,
890+
unsigned Idx) {
891+
return buildInstr(TargetOpcode::G_INSERT_SUBVECTOR, Res,
892+
{Src, uint64_t(Idx)});
893+
}
894+
880895
MachineInstrBuilder
881896
MachineIRBuilder::buildInsertVectorElement(const DstOp &Res, const SrcOp &Val,
882897
const SrcOp &Elt, const SrcOp &Idx) {

llvm/lib/CodeGen/MachineVerifier.cpp

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1603,6 +1603,104 @@ void MachineVerifier::verifyPreISelGenericInstruction(const MachineInstr *MI) {
16031603
report("G_BSWAP size must be a multiple of 16 bits", MI);
16041604
break;
16051605
}
1606+
case TargetOpcode::G_INSERT_SUBVECTOR: {
1607+
const MachineOperand &Src0Op = MI->getOperand(1);
1608+
if (!Src0Op.isReg()) {
1609+
report("G_INSERT_SUBVECTOR first source must be a register", MI);
1610+
break;
1611+
}
1612+
1613+
const MachineOperand &Src1Op = MI->getOperand(2);
1614+
if (!Src1Op.isReg()) {
1615+
report("G_INSERT_SUBVECTOR second source must be a register", MI);
1616+
break;
1617+
}
1618+
1619+
const MachineOperand &IndexOp = MI->getOperand(3);
1620+
if (!IndexOp.isImm()) {
1621+
report("G_INSERT_SUBVECTOR index must be an immediate", MI);
1622+
break;
1623+
}
1624+
1625+
LLT DstTy = MRI->getType(MI->getOperand(0).getReg());
1626+
LLT Src0Ty = MRI->getType(Src0Op.getReg());
1627+
LLT Src1Ty = MRI->getType(Src1Op.getReg());
1628+
1629+
if (!DstTy.isVector()) {
1630+
report("Destination type must be a vector", MI);
1631+
break;
1632+
}
1633+
1634+
if (!Src0Ty.isVector()) {
1635+
report("First source must be a vector", MI);
1636+
break;
1637+
}
1638+
1639+
if (!Src1Ty.isVector()) {
1640+
report("Second source must be a vector", MI);
1641+
break;
1642+
}
1643+
1644+
if (DstTy != Src0Ty) {
1645+
report("Destination type must match the first source vector type", MI);
1646+
break;
1647+
}
1648+
1649+
if (Src0Ty.getElementType() != Src1Ty.getElementType()) {
1650+
report("Element type of source vectors must be the same", MI);
1651+
break;
1652+
}
1653+
1654+
if (IndexOp.getImm() != 0 &&
1655+
Src1Ty.getElementCount().getKnownMinValue() % IndexOp.getImm() != 0) {
1656+
report("Index must be a multiple of the second source vector's "
1657+
"minimum vector length",
1658+
MI);
1659+
break;
1660+
}
1661+
break;
1662+
}
1663+
case TargetOpcode::G_EXTRACT_SUBVECTOR: {
1664+
const MachineOperand &SrcOp = MI->getOperand(1);
1665+
if (!SrcOp.isReg()) {
1666+
report("G_EXTRACT_SUBVECTOR first source must be a register", MI);
1667+
break;
1668+
}
1669+
1670+
const MachineOperand &IndexOp = MI->getOperand(2);
1671+
if (!IndexOp.isImm()) {
1672+
report("G_EXTRACT_SUBVECTOR index must be an immediate", MI);
1673+
break;
1674+
}
1675+
1676+
LLT DstTy = MRI->getType(MI->getOperand(0).getReg());
1677+
LLT SrcTy = MRI->getType(SrcOp.getReg());
1678+
1679+
if (!DstTy.isVector()) {
1680+
report("Destination type must be a vector", MI);
1681+
break;
1682+
}
1683+
1684+
if (!SrcTy.isVector()) {
1685+
report("First source must be a vector", MI);
1686+
break;
1687+
}
1688+
1689+
if (DstTy.getElementType() != SrcTy.getElementType()) {
1690+
report("Element type of vectors must be the same", MI);
1691+
break;
1692+
}
1693+
1694+
if (IndexOp.getImm() != 0 &&
1695+
SrcTy.getElementCount().getKnownMinValue() % IndexOp.getImm() != 0) {
1696+
report("Index must be a multiple of the source vector's minimum vector "
1697+
"length",
1698+
MI);
1699+
break;
1700+
}
1701+
1702+
break;
1703+
}
16061704
case TargetOpcode::G_SHUFFLE_VECTOR: {
16071705
const MachineOperand &MaskOp = MI->getOperand(3);
16081706
if (!MaskOp.isShuffleMask()) {
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# RUN: not --crash llc -o - -mtriple=arm64 -run-pass=none -verify-machineinstrs %s 2>&1 | FileCheck %s
2+
# REQUIRES: aarch64-registered-target
3+
4+
---
5+
name: g_extract_subvector
6+
tracksRegLiveness: true
7+
liveins:
8+
body: |
9+
bb.0:
10+
%0:_(s32) = G_CONSTANT i32 0
11+
%1:_(<vscale x 2 x s32>) = G_IMPLICIT_DEF
12+
%2:_(<vscale x 1 x s32>) = G_IMPLICIT_DEF
13+
14+
; CHECK: G_EXTRACT_SUBVECTOR first source must be a register
15+
%3:_(<vscale x 2 x s32>) = G_EXTRACT_SUBVECTOR 1, 0
16+
17+
; CHECK: G_EXTRACT_SUBVECTOR index must be an immediate
18+
%4:_(<vscale x 1 x s32>) = G_EXTRACT_SUBVECTOR %2, %0
19+
20+
; CHECK: Destination type must be a vector
21+
%5:_(s32) = G_EXTRACT_SUBVECTOR %2, 0
22+
23+
; CHECK: First source must be a vector
24+
%6:_(<vscale x 2 x s32>) = G_EXTRACT_SUBVECTOR %0, 0
25+
26+
%7:_(<vscale x 1 x s16>) = G_IMPLICIT_DEF
27+
28+
; CHECK: Element type of vectors must be the same
29+
%8:_(<vscale x 2 x s32>) = G_EXTRACT_SUBVECTOR %7, 0
30+
31+
; CHECK: Index must be a multiple of the source vector's minimum vector length
32+
%9:_(<vscale x 4 x s32>) = G_EXTRACT_SUBVECTOR %1, 3
33+
...
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
# RUN: not --crash llc -o - -mtriple=arm64 -run-pass=none -verify-machineinstrs %s 2>&1 | FileCheck %s
2+
# REQUIRES: aarch64-registered-target
3+
4+
---
5+
name: g_splat_vector
6+
tracksRegLiveness: true
7+
liveins:
8+
body: |
9+
bb.0:
10+
%0:_(s32) = G_CONSTANT i32 0
11+
%1:_(<vscale x 2 x s32>) = G_IMPLICIT_DEF
12+
%2:_(<vscale x 1 x s32>) = G_IMPLICIT_DEF
13+
14+
; CHECK: G_INSERT_SUBVECTOR first source must be a register
15+
%3:_(<vscale x 2 x s32>) = G_INSERT_SUBVECTOR 1, %2, 0
16+
17+
; CHECK: G_INSERT_SUBVECTOR second source must be a register
18+
%4:_(<vscale x 2 x s32>) = G_INSERT_SUBVECTOR %1, 1, 0
19+
20+
; CHECK: G_INSERT_SUBVECTOR index must be an immediate
21+
%5:_(<vscale x 2 x s32>) = G_INSERT_SUBVECTOR %1, %2, %0
22+
23+
; CHECK: Destination type must be a vector
24+
%6:_(s32) = G_INSERT_SUBVECTOR %1, %2, 0
25+
26+
; CHECK: First source must be a vector
27+
%7:_(<vscale x 2 x s32>) = G_INSERT_SUBVECTOR %0, %2, 0
28+
29+
; CHECK: Second source must be a vector
30+
%8:_(<vscale x 2 x s32>) = G_INSERT_SUBVECTOR %1, %0, 0
31+
32+
; CHECK: Destination type must match the first source vector type
33+
%9:_(<vscale x 2 x s32>) = G_INSERT_SUBVECTOR %2, %1, 0
34+
35+
%10:_(<vscale x 1 x s16>) = G_IMPLICIT_DEF
36+
37+
; CHECK: Element type of source vectors must be the same
38+
%11:_(<vscale x 2 x s32>) = G_INSERT_SUBVECTOR %1, %10, 0
39+
40+
%12:_(<vscale x 4 x s32>) = G_IMPLICIT_DEF
41+
42+
; CHECK: Index must be a multiple of the second source vector's minimum vector length
43+
%13:_(<vscale x 4 x s32>) = G_INSERT_SUBVECTOR %12, %1, 3
44+
...

0 commit comments

Comments
 (0)