[llvm] [VectorCombine][AMDGPU] Narrow Phi of Shuffles. (PR #140188)
Leon Clark via llvm-commits
llvm-commits at lists.llvm.org
Tue Jun 10 22:53:26 PDT 2025
================
@@ -3519,6 +3520,95 @@ bool VectorCombine::foldInterleaveIntrinsics(Instruction &I) {
return true;
}
+/// Attempt to narrow a phi of shufflevector instructions where the two incoming
+/// values have the same operands but different masks. If the two shuffle masks
+/// are offsets of one another we can use one branch to rotate the incoming
+/// vector and perform one larger shuffle after the phi.
+bool VectorCombine::shrinkPhiOfShuffles(Instruction &I) {
+ auto *Phi = dyn_cast<PHINode>(&I);
+ if (!Phi || Phi->getNumIncomingValues() != 2u)
+ return false;
+
+ Value *Op = nullptr;
+ ArrayRef<int> Mask0;
+ ArrayRef<int> Mask1;
+
+ if (!match(Phi->getOperand(0u),
+ m_OneUse(m_Shuffle(m_Value(Op), m_Poison(), m_Mask(Mask0)))) ||
+ !match(Phi->getOperand(1u),
+ m_OneUse(m_Shuffle(m_Specific(Op), m_Poison(), m_Mask(Mask1)))))
+ return false;
+
+ auto *Shuf = cast<ShuffleVectorInst>(Phi->getOperand(0u));
+
+ // Ensure result vectors are wider than the argument vector.
+ auto *InputVT = cast<FixedVectorType>(Op->getType());
+ auto *ResultVT = cast<FixedVectorType>(Shuf->getType());
+ auto const InputNumElements = InputVT->getNumElements();
+
+ if (InputNumElements >= ResultVT->getNumElements())
+ return false;
+
+ // Take the difference of the two shuffle masks at each index. Ignore poison
+ // values at the same index in both masks.
+ SmallVector<int, 16> NewMask;
+ NewMask.reserve(Mask0.size());
+
+ for (auto I = 0u; I < Mask0.size(); ++I) {
+ if (Mask0[I] >= 0 && Mask1[I] >= 0)
+ NewMask.push_back(Mask0[I] - Mask1[I]);
+ else if (Mask0[I] == -1 && Mask1[I] == -1)
+ continue;
+ else
+ return false;
+ }
+
+ // Ensure all elements of the new mask are equal. If the difference between
+ // the incoming mask elements is the same, the two must be constant offsets
+ // of one another.
+ if (NewMask.empty() || !all_equal(NewMask))
+ return false;
+
+ // Create new mask using difference of the two incoming masks.
+ int MaskOffset = NewMask[0u];
+ unsigned Index = (InputNumElements - MaskOffset) % InputNumElements;
+ NewMask.clear();
+
+ for (unsigned I = 0u; I < InputNumElements; ++I) {
+ NewMask.push_back(Index);
+ Index = (Index + 1u) % InputNumElements;
+ }
+
+ // Calculate costs for worst cases and compare.
+ auto const Kind = TTI::SK_PermuteSingleSrc;
+ auto OldCost = std::max(TTI.getShuffleCost(Kind, InputVT, Mask0, CostKind),
+ TTI.getShuffleCost(Kind, InputVT, Mask1, CostKind));
+ auto NewCost = TTI.getShuffleCost(Kind, InputVT, NewMask, CostKind) +
+ TTI.getShuffleCost(Kind, InputVT, Mask1, CostKind);
+
+ if (NewCost > OldCost)
+ return false;
+
+ // Create new shuffles and narrowed phi.
+ auto Builder = IRBuilder(Shuf);
+ Builder.SetCurrentDebugLocation(Shuf->getDebugLoc());
+ auto *PoisonVal = PoisonValue::get(InputVT);
+ auto *NewShuf0 = Builder.CreateShuffleVector(Op, PoisonVal, NewMask);
----------------
PeddleSpam wrote:
Adding it didn't seem to change anything.
https://github.com/llvm/llvm-project/pull/140188
More information about the llvm-commits
mailing list