[llvm] [VectorCombine] Handle shuffle of selects (PR #128032)
via llvm-commits
llvm-commits at lists.llvm.org
Mon Feb 24 03:52:26 PST 2025
================
@@ -1899,6 +1900,65 @@ bool VectorCombine::foldShuffleOfBinops(Instruction &I) {
return true;
}
+/// Try to convert,
+/// (shuffle(select(c1,t1,f1)), (select(c2,t2,f2)), m) into
+/// (select (shuffle c1,c2,m), (shuffle t1,t2,m), (shuffle f1,f2,m))
+bool VectorCombine::foldShuffleOfSelects(Instruction &I) {
+ ArrayRef<int> Mask;
+ Value *C1, *T1, *F1, *C2, *T2, *F2;
+ if (!match(&I, m_Shuffle(
+ m_OneUse(m_Select(m_Value(C1), m_Value(T1), m_Value(F1))),
+ m_OneUse(m_Select(m_Value(C2), m_Value(T2), m_Value(F2))),
+ m_Mask(Mask))))
+ return false;
+
+ auto *DstVecTy = dyn_cast<FixedVectorType>(I.getType());
+ auto *C1VecTy = dyn_cast<FixedVectorType>(C1->getType());
+ auto *C2VecTy = dyn_cast<FixedVectorType>(C2->getType());
+ if (!C1VecTy || !C2VecTy)
+ return false;
+
+ auto *Select0 = cast<Instruction>(I.getOperand(0));
+ if (auto *SI0FOp = dyn_cast<FPMathOperator>(Select0))
+ if (auto *SI1FOp = dyn_cast<FPMathOperator>((I.getOperand(1))))
+ if (SI0FOp->getFastMathFlags() != SI1FOp->getFastMathFlags())
+ return false;
+
+ auto SK = TargetTransformInfo::SK_PermuteTwoSrc;
+ auto SelOp = Instruction::Select;
+ InstructionCost OldCost = TTI.getCmpSelInstrCost(
+ SelOp, T1->getType(), C1VecTy, CmpInst::BAD_ICMP_PREDICATE, CostKind);
+ OldCost += TTI.getCmpSelInstrCost(SelOp, T2->getType(), C2VecTy,
+ CmpInst::BAD_ICMP_PREDICATE, CostKind);
+ OldCost += TTI.getShuffleCost(SK, DstVecTy, Mask, CostKind, 0, nullptr,
+ {I.getOperand(0), I.getOperand(1)}, &I);
+
+ auto *C1C2VecTy = cast<FixedVectorType>(
+ toVectorTy(Type::getInt1Ty(I.getContext()), DstVecTy->getNumElements()));
+ InstructionCost NewCost =
+ TTI.getShuffleCost(SK, C1C2VecTy, Mask, CostKind, 0, nullptr, {C1, C2});
+ NewCost +=
+ TTI.getShuffleCost(SK, DstVecTy, Mask, CostKind, 0, nullptr, {T1, T2});
+ NewCost +=
+ TTI.getShuffleCost(SK, DstVecTy, Mask, CostKind, 0, nullptr, {F1, F2});
+ NewCost += TTI.getCmpSelInstrCost(SelOp, DstVecTy, DstVecTy,
+ CmpInst::BAD_ICMP_PREDICATE, CostKind);
+
+ if (NewCost > OldCost)
+ return false;
+
+ Value *ShuffleCmp = Builder.CreateShuffleVector(C1, C2, Mask);
+ Value *ShuffleTrue = Builder.CreateShuffleVector(T1, T2, Mask);
+ Value *ShuffleFalse = Builder.CreateShuffleVector(F1, F2, Mask);
+ Value *NewSel = Builder.CreateSelect(ShuffleCmp, ShuffleTrue, ShuffleFalse);
+ if (isa<FPMathOperator>(NewSel))
+ cast<Instruction>(NewSel)->setFastMathFlags(Select0->getFastMathFlags());
----------------
ParkHanbum wrote:
Since we previously forced the two Selects to proceed only if their FMFs are the same, shouldn't Select0's FMF be enough?
Does this mean that the above conversion is possible for Selects with different FMFs?
https://github.com/llvm/llvm-project/pull/128032
More information about the llvm-commits
mailing list