aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/CodeGen
diff options
context:
space:
mode:
authorKonstantin Schwarz <konstantin.schwarz@amd.com>2024-11-14 15:13:41 -0800
committerGitHub <noreply@github.com>2024-11-14 15:13:41 -0800
commit0f0e2fe97b6c771b7a70964bf321ad91788e6a22 (patch)
tree0b88276bfab72087ff1d5ed63b654b6e6121569a /llvm/lib/CodeGen
parent44adc245d8e7e16b730fb247f3b8b47428e2864b (diff)
downloadllvm-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.cpp66
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;
+}