Skip to content

Commit 3e55c53

Browse files
[GISel][CombinerHelper] Add a helper that unmerges a vector to a target size
1 parent 18000f7 commit 3e55c53

File tree

2 files changed

+58
-0
lines changed

2 files changed

+58
-0
lines changed

llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,16 @@ class CombinerHelper {
261261
bool matchCombineShuffleVector(MachineInstr &MI, GeneratorType Generator,
262262
const size_t TargetDstSize);
263263

264+
/// Create G_UNMERGE_VECTOR instructions until the source has reached a
265+
/// target vector size.
266+
///
267+
/// Requires that the destination fits evenly in the source register. It
268+
/// allows you to pass which of the different destination sized slices
269+
/// you require.
270+
Register createUnmergeValue(MachineInstr &MI, const Register SrcReg,
271+
const Register DstReg, uint8_t DestinationIndex,
272+
const uint32_t Start, const uint32_t End);
273+
264274
/// Replace \p MI with a concat_vectors with \p Ops.
265275
void applyCombineShuffleVector(MachineInstr &MI,
266276
const ArrayRef<Register> Ops);

llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,54 @@ adderGenerator(const int32_t From, const int32_t To, const int32_t StepSize) {
316316
};
317317
}
318318

319+
Register CombinerHelper::createUnmergeValue(
320+
MachineInstr &MI, const Register SrcReg, const Register DstReg,
321+
const uint8_t DestinationIndex, const uint32_t Start, const uint32_t End) {
322+
Builder.setInsertPt(*MI.getParent(), MI);
323+
const LLT DstTy = MRI.getType(DstReg);
324+
const LLT SrcTy = MRI.getType(SrcReg);
325+
assert((!DstTy.isVector() ||
326+
(SrcTy.getNumElements() % DstTy.getNumElements()) == 0) &&
327+
"destination vector must divide source cleanly");
328+
329+
const unsigned HalfElements = SrcTy.getNumElements() / 2;
330+
const LLT ScalarTy = SrcTy.getScalarType();
331+
const LLT HalfSizeTy = (HalfElements == 1)
332+
? ScalarTy
333+
: LLT::fixed_vector(HalfElements, ScalarTy);
334+
const Register TmpReg = MRI.createGenericVirtualRegister(HalfSizeTy);
335+
Register TargetReg = DstReg;
336+
if (DstTy != HalfSizeTy) {
337+
TargetReg = MRI.createGenericVirtualRegister(HalfSizeTy);
338+
}
339+
340+
// Each destination fits n times into the source and each iteration we exactly
341+
// half the source. Therefore we need to pick on which side we want to iterate
342+
// on.
343+
const uint32_t DstNumElements = DstTy.isVector() ? DstTy.getNumElements() : 1;
344+
const uint32_t HalfWay = Start + ((End - Start) / 2);
345+
const uint32_t Position = DestinationIndex * DstNumElements;
346+
347+
uint32_t NextStart, NextEnd;
348+
if (Position < HalfWay) {
349+
Builder.buildInstr(TargetOpcode::G_UNMERGE_VALUES, {TargetReg, TmpReg},
350+
{SrcReg});
351+
NextStart = Start;
352+
NextEnd = HalfWay;
353+
} else {
354+
Builder.buildInstr(TargetOpcode::G_UNMERGE_VALUES, {TmpReg, TargetReg},
355+
{SrcReg});
356+
NextStart = HalfWay;
357+
NextEnd = End;
358+
}
359+
360+
if (HalfSizeTy.isVector() && DstTy != HalfSizeTy)
361+
return createUnmergeValue(MI, TargetReg, DstReg, DestinationIndex,
362+
NextStart, NextEnd);
363+
364+
return DstReg;
365+
}
366+
319367
bool CombinerHelper::tryCombineShuffleVector(MachineInstr &MI) {
320368
const Register DstReg = MI.getOperand(0).getReg();
321369
const LLT DstTy = MRI.getType(DstReg);

0 commit comments

Comments
 (0)