@@ -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+
319359bool CombinerHelper::tryCombineShuffleVector (MachineInstr &MI) {
320360 const Register DstReg = MI.getOperand (0 ).getReg ();
321361 const LLT DstTy = MRI.getType (DstReg);
0 commit comments