Skip to content

Commit b8652cc

Browse files
[GISel][CombinerHelper] Add a helper that unmerges a vector to a target size
1 parent df516f9 commit b8652cc

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
@@ -263,6 +263,16 @@ class CombinerHelper {
263263
bool matchCombineShuffleVector(MachineInstr &MI, GeneratorType Generator,
264264
const size_t TargetDstSize);
265265

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

llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -399,6 +399,54 @@ adderGenerator(const int32_t From, const int32_t To, const int32_t StepSize) {
399399
};
400400
}
401401

402+
Register CombinerHelper::createUnmergeValue(
403+
MachineInstr &MI, const Register SrcReg, const Register DstReg,
404+
const uint8_t DestinationIndex, const uint32_t Start, const uint32_t End) {
405+
Builder.setInsertPt(*MI.getParent(), MI);
406+
const LLT DstTy = MRI.getType(DstReg);
407+
const LLT SrcTy = MRI.getType(SrcReg);
408+
assert((DstTy.isScalar() ||
409+
(SrcTy.getNumElements() % DstTy.getNumElements()) == 0) &&
410+
"destination vector must divide source cleanly");
411+
412+
const unsigned HalfElements = SrcTy.getNumElements() / 2;
413+
const LLT ScalarTy = SrcTy.getScalarType();
414+
const LLT HalfSizeTy = (HalfElements == 1)
415+
? ScalarTy
416+
: LLT::fixed_vector(HalfElements, ScalarTy);
417+
const Register TmpReg = MRI.createGenericVirtualRegister(HalfSizeTy);
418+
Register TargetReg = DstReg;
419+
if (DstTy != HalfSizeTy) {
420+
TargetReg = MRI.createGenericVirtualRegister(HalfSizeTy);
421+
}
422+
423+
// Each destination fits n times into the source and each iteration we exactly
424+
// half the source. Therefore we need to pick on which side we want to iterate
425+
// on.
426+
const uint32_t DstNumElements = DstTy.isVector() ? DstTy.getNumElements() : 1;
427+
const uint32_t HalfWay = Start + ((End - Start) / 2);
428+
const uint32_t Position = DestinationIndex * DstNumElements;
429+
430+
uint32_t NextStart, NextEnd;
431+
if (Position < HalfWay) {
432+
Builder.buildInstr(TargetOpcode::G_UNMERGE_VALUES, {TargetReg, TmpReg},
433+
{SrcReg});
434+
NextStart = Start;
435+
NextEnd = HalfWay;
436+
} else {
437+
Builder.buildInstr(TargetOpcode::G_UNMERGE_VALUES, {TmpReg, TargetReg},
438+
{SrcReg});
439+
NextStart = HalfWay;
440+
NextEnd = End;
441+
}
442+
443+
if (HalfSizeTy.isVector() && DstTy != HalfSizeTy)
444+
return createUnmergeValue(MI, TargetReg, DstReg, DestinationIndex,
445+
NextStart, NextEnd);
446+
447+
return DstReg;
448+
}
449+
402450
bool CombinerHelper::tryCombineShuffleVector(MachineInstr &MI) {
403451
const Register DstReg = MI.getOperand(0).getReg();
404452
const LLT DstTy = MRI.getType(DstReg);

0 commit comments

Comments
 (0)