diff options
author | Konstantin Schwarz <konstantin.schwarz@amd.com> | 2024-11-14 15:13:41 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-11-14 15:13:41 -0800 |
commit | 0f0e2fe97b6c771b7a70964bf321ad91788e6a22 (patch) | |
tree | 0b88276bfab72087ff1d5ed63b654b6e6121569a /llvm/lib/CodeGen | |
parent | 44adc245d8e7e16b730fb247f3b8b47428e2864b (diff) | |
download | llvm-0f0e2fe97b6c771b7a70964bf321ad91788e6a22.zip llvm-0f0e2fe97b6c771b7a70964bf321ad91788e6a22.tar.gz llvm-0f0e2fe97b6c771b7a70964bf321ad91788e6a22.tar.bz2 |
[GlobalISel] Turn shuffle a, b, mask -> shuffle undef, b, mask iff mask does not reference a (#115377)
Diffstat (limited to 'llvm/lib/CodeGen')
-rw-r--r-- | llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp | 66 |
1 files changed, 66 insertions, 0 deletions
diff --git a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp index 1a1a1c2..83d78c0 100644 --- a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp +++ b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp @@ -7724,3 +7724,69 @@ bool CombinerHelper::matchShuffleUndefRHS(MachineInstr &MI, return true; } + +static void commuteMask(MutableArrayRef<int> Mask, const unsigned NumElems) { + const unsigned MaskSize = Mask.size(); + for (unsigned I = 0; I < MaskSize; ++I) { + int Idx = Mask[I]; + if (Idx < 0) + continue; + + if (Idx < (int)NumElems) + Mask[I] = Idx + NumElems; + else + Mask[I] = Idx - NumElems; + } +} + +bool CombinerHelper::matchShuffleDisjointMask(MachineInstr &MI, + BuildFnTy &MatchInfo) { + + auto &Shuffle = cast<GShuffleVector>(MI); + // If any of the two inputs is already undef, don't check the mask again to + // prevent infinite loop + if (getOpcodeDef(TargetOpcode::G_IMPLICIT_DEF, Shuffle.getSrc1Reg(), MRI)) + return false; + + if (getOpcodeDef(TargetOpcode::G_IMPLICIT_DEF, Shuffle.getSrc2Reg(), MRI)) + return false; + + const LLT DstTy = MRI.getType(Shuffle.getReg(0)); + const LLT Src1Ty = MRI.getType(Shuffle.getSrc1Reg()); + if (!isLegalOrBeforeLegalizer( + {TargetOpcode::G_SHUFFLE_VECTOR, {DstTy, Src1Ty}})) + return false; + + ArrayRef<int> Mask = Shuffle.getMask(); + const unsigned NumSrcElems = Src1Ty.isVector() ? Src1Ty.getNumElements() : 1; + + bool TouchesSrc1 = false; + bool TouchesSrc2 = false; + const unsigned NumElems = Mask.size(); + for (unsigned Idx = 0; Idx < NumElems; ++Idx) { + if (Mask[Idx] < 0) + continue; + + if (Mask[Idx] < (int)NumSrcElems) + TouchesSrc1 = true; + else + TouchesSrc2 = true; + } + + if (TouchesSrc1 == TouchesSrc2) + return false; + + Register NewSrc1 = Shuffle.getSrc1Reg(); + SmallVector<int, 16> NewMask(Mask); + if (TouchesSrc2) { + NewSrc1 = Shuffle.getSrc2Reg(); + commuteMask(NewMask, NumSrcElems); + } + + MatchInfo = [=, &Shuffle](MachineIRBuilder &B) { + auto Undef = B.buildUndef(Src1Ty); + B.buildShuffleVector(Shuffle.getReg(0), NewSrc1, Undef, NewMask); + }; + + return true; +} |