[llvm] [GlobalISel] Turn shuffle a, b, mask -> shuffle undef, b, mask iff mask does not reference a (PR #115377)

Thorsten Schütt via llvm-commits llvm-commits at lists.llvm.org
Tue Nov 12 10:53:30 PST 2024


================
@@ -7726,3 +7726,65 @@ 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;
+
+  ArrayRef<int> Mask = Shuffle.getMask();
+  const LLT Src1Ty = MRI.getType(Shuffle.getSrc1Reg());
+
+  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) {
+    Register Undef = B.buildUndef(Src1Ty).getReg(0);
----------------
tschuett wrote:

Sorry, for sounding harsh. I(me) find it confusing to be weak about legality. Sometimes you have to go through isLegalOrBeforeLegalizer but not always, because undef is different. Why limit it to undef?

Can we instead document guidelines for building legalizers and using/querying them. 

https://github.com/llvm/llvm-project/pull/115377


More information about the llvm-commits mailing list