Skip to content

Commit 9c0f927

Browse files
[GISel][CombinerHelper] Add a helper that unmerges a vector to a target size
1 parent a38842b commit 9c0f927

File tree

2 files changed

+48
-0
lines changed

2 files changed

+48
-0
lines changed

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,14 @@ 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);
264272
/// Replace \p MI with a concat_vectors with \p Ops.
265273
void applyCombineShuffleVector(MachineInstr &MI,
266274
const ArrayRef<Register> Ops);

llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp

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

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

0 commit comments

Comments
 (0)