@@ -3320,6 +3320,112 @@ static bool isConstValidTrue(const TargetLowering &TLI, unsigned ScalarSizeBits,
33203320 isConstTrueVal (TLI, Cst, IsVector, IsFP);
33213321}
33223322
3323+ // This combine tries to reduce the number of scalarised G_TRUNC instructions by
3324+ // using vector truncates instead
3325+ //
3326+ // EXAMPLE:
3327+ // %a(i32), %b(i32) = G_UNMERGE_VALUES %src(<2 x i32>)
3328+ // %T_a(i16) = G_TRUNC %a(i32)
3329+ // %T_b(i16) = G_TRUNC %b(i32)
3330+ // %Undef(i16) = G_IMPLICIT_DEF(i16)
3331+ // %dst(v4i16) = G_BUILD_VECTORS %T_a(i16), %T_b(i16), %Undef(i16), %Undef(i16)
3332+ //
3333+ // ===>
3334+ // %Undef(<2 x i32>) = G_IMPLICIT_DEF(<2 x i32>)
3335+ // %Mid(<4 x s32>) = G_CONCAT_VECTORS %src(<2 x i32>), %Undef(<2 x i32>)
3336+ // %dst(<4 x s16>) = G_TRUNC %Mid(<4 x s32>)
3337+ //
3338+ // Only matches sources made up of G_TRUNCs followed by G_IMPLICIT_DEFs
3339+ bool CombinerHelper::matchUseVectorTruncate (MachineInstr &MI,
3340+ Register &MatchInfo) {
3341+ auto BuildMI = cast<GBuildVector>(&MI);
3342+ unsigned NumOperands = BuildMI->getNumSources ();
3343+ LLT DstTy = MRI.getType (BuildMI->getReg (0 ));
3344+
3345+ // Check the G_BUILD_VECTOR sources
3346+ unsigned I;
3347+ MachineInstr *UnmergeMI = nullptr ;
3348+
3349+ // Check all source TRUNCs come from the same UNMERGE instruction
3350+ for (I = 0 ; I < NumOperands; ++I) {
3351+ auto SrcMI = MRI.getVRegDef (BuildMI->getSourceReg (I));
3352+ auto SrcMIOpc = SrcMI->getOpcode ();
3353+
3354+ // Check if the G_TRUNC instructions all come from the same MI
3355+ if (SrcMIOpc == TargetOpcode::G_TRUNC) {
3356+ if (!UnmergeMI) {
3357+ UnmergeMI = MRI.getVRegDef (SrcMI->getOperand (1 ).getReg ());
3358+ if (UnmergeMI->getOpcode () != TargetOpcode::G_UNMERGE_VALUES)
3359+ return false ;
3360+ } else {
3361+ auto UnmergeSrcMI = MRI.getVRegDef (SrcMI->getOperand (1 ).getReg ());
3362+ if (UnmergeMI != UnmergeSrcMI)
3363+ return false ;
3364+ }
3365+ } else {
3366+ break ;
3367+ }
3368+ }
3369+ if (I < 2 )
3370+ return false ;
3371+
3372+ // Check the remaining source elements are only G_IMPLICIT_DEF
3373+ for (; I < NumOperands; ++I) {
3374+ auto SrcMI = MRI.getVRegDef (BuildMI->getSourceReg (I));
3375+ auto SrcMIOpc = SrcMI->getOpcode ();
3376+
3377+ if (SrcMIOpc != TargetOpcode::G_IMPLICIT_DEF)
3378+ return false ;
3379+ }
3380+
3381+ // Check the size of unmerge source
3382+ MatchInfo = cast<GUnmerge>(UnmergeMI)->getSourceReg ();
3383+ LLT UnmergeSrcTy = MRI.getType (MatchInfo);
3384+ if (!DstTy.getElementCount ().isKnownMultipleOf (UnmergeSrcTy.getNumElements ()))
3385+ return false ;
3386+
3387+ // Only generate legal instructions post-legalizer
3388+ if (!IsPreLegalize) {
3389+ LLT MidTy = DstTy.changeElementType (UnmergeSrcTy.getScalarType ());
3390+
3391+ if (DstTy.getElementCount () != UnmergeSrcTy.getElementCount () &&
3392+ !isLegal ({TargetOpcode::G_CONCAT_VECTORS, {MidTy, UnmergeSrcTy}}))
3393+ return false ;
3394+
3395+ if (!isLegal ({TargetOpcode::G_TRUNC, {DstTy, MidTy}}))
3396+ return false ;
3397+ }
3398+
3399+ return true ;
3400+ }
3401+
3402+ void CombinerHelper::applyUseVectorTruncate (MachineInstr &MI,
3403+ Register &MatchInfo) {
3404+ Register MidReg;
3405+ auto BuildMI = cast<GBuildVector>(&MI);
3406+ Register DstReg = BuildMI->getReg (0 );
3407+ LLT DstTy = MRI.getType (DstReg);
3408+ LLT UnmergeSrcTy = MRI.getType (MatchInfo);
3409+ unsigned DstTyNumElt = DstTy.getNumElements ();
3410+ unsigned UnmergeSrcTyNumElt = UnmergeSrcTy.getNumElements ();
3411+
3412+ // No need to pad vector if only G_TRUNC is needed
3413+ if (DstTyNumElt / UnmergeSrcTyNumElt == 1 ) {
3414+ MidReg = MatchInfo;
3415+ } else {
3416+ Register UndefReg = Builder.buildUndef (UnmergeSrcTy).getReg (0 );
3417+ SmallVector<Register> ConcatRegs = {MatchInfo};
3418+ for (unsigned I = 1 ; I < DstTyNumElt / UnmergeSrcTyNumElt; ++I)
3419+ ConcatRegs.push_back (UndefReg);
3420+
3421+ auto MidTy = DstTy.changeElementType (UnmergeSrcTy.getScalarType ());
3422+ MidReg = Builder.buildConcatVectors (MidTy, ConcatRegs).getReg (0 );
3423+ }
3424+
3425+ Builder.buildTrunc (DstReg, MidReg);
3426+ MI.eraseFromParent ();
3427+ }
3428+
33233429bool CombinerHelper::matchNotCmp (MachineInstr &MI,
33243430 SmallVectorImpl<Register> &RegsToNegate) {
33253431 assert (MI.getOpcode () == TargetOpcode::G_XOR);
0 commit comments