@@ -120,6 +120,7 @@ class VectorCombine {
120120 bool foldConcatOfBoolMasks (Instruction &I);
121121 bool foldPermuteOfBinops (Instruction &I);
122122 bool foldShuffleOfBinops (Instruction &I);
123+ bool foldShuffleOfSelects (Instruction &I);
123124 bool foldShuffleOfCastops (Instruction &I);
124125 bool foldShuffleOfShuffles (Instruction &I);
125126 bool foldShuffleOfIntrinsics (Instruction &I);
@@ -2024,6 +2025,76 @@ bool VectorCombine::foldShuffleOfBinops(Instruction &I) {
20242025 return true ;
20252026}
20262027
2028+ // / Try to convert,
2029+ // / (shuffle(select(c1,t1,f1)), (select(c2,t2,f2)), m) into
2030+ // / (select (shuffle c1,c2,m), (shuffle t1,t2,m), (shuffle f1,f2,m))
2031+ bool VectorCombine::foldShuffleOfSelects (Instruction &I) {
2032+ ArrayRef<int > Mask;
2033+ Value *C1, *T1, *F1, *C2, *T2, *F2;
2034+ if (!match (&I, m_Shuffle (
2035+ m_OneUse (m_Select (m_Value (C1), m_Value (T1), m_Value (F1))),
2036+ m_OneUse (m_Select (m_Value (C2), m_Value (T2), m_Value (F2))),
2037+ m_Mask (Mask))))
2038+ return false ;
2039+
2040+ auto *DstVecTy = dyn_cast<FixedVectorType>(I.getType ());
2041+ auto *C1VecTy = dyn_cast<FixedVectorType>(C1->getType ());
2042+ auto *C2VecTy = dyn_cast<FixedVectorType>(C2->getType ());
2043+ if (!C1VecTy || !C2VecTy || C1VecTy != C2VecTy)
2044+ return false ;
2045+
2046+ auto *SI0FOp = dyn_cast<FPMathOperator>(I.getOperand (0 ));
2047+ auto *SI1FOp = dyn_cast<FPMathOperator>(I.getOperand (1 ));
2048+ // SelectInsts must have the same FMF.
2049+ if (((SI0FOp == nullptr ) != (SI1FOp == nullptr )) ||
2050+ ((SI0FOp != nullptr ) &&
2051+ (SI0FOp->getFastMathFlags () != SI1FOp->getFastMathFlags ())))
2052+ return false ;
2053+
2054+ auto SK = TargetTransformInfo::SK_PermuteTwoSrc;
2055+ auto SelOp = Instruction::Select;
2056+ InstructionCost OldCost = TTI.getCmpSelInstrCost (
2057+ SelOp, T1->getType (), C1VecTy, CmpInst::BAD_ICMP_PREDICATE, CostKind);
2058+ OldCost += TTI.getCmpSelInstrCost (SelOp, T2->getType (), C2VecTy,
2059+ CmpInst::BAD_ICMP_PREDICATE, CostKind);
2060+ OldCost += TTI.getShuffleCost (SK, DstVecTy, Mask, CostKind, 0 , nullptr ,
2061+ {I.getOperand (0 ), I.getOperand (1 )}, &I);
2062+
2063+ auto *C1C2VecTy = cast<FixedVectorType>(
2064+ toVectorTy (Type::getInt1Ty (I.getContext ()), DstVecTy->getNumElements ()));
2065+ InstructionCost NewCost =
2066+ TTI.getShuffleCost (SK, C1C2VecTy, Mask, CostKind, 0 , nullptr , {C1, C2});
2067+ NewCost +=
2068+ TTI.getShuffleCost (SK, DstVecTy, Mask, CostKind, 0 , nullptr , {T1, T2});
2069+ NewCost +=
2070+ TTI.getShuffleCost (SK, DstVecTy, Mask, CostKind, 0 , nullptr , {F1, F2});
2071+ NewCost += TTI.getCmpSelInstrCost (SelOp, DstVecTy, DstVecTy,
2072+ CmpInst::BAD_ICMP_PREDICATE, CostKind);
2073+
2074+ LLVM_DEBUG (dbgs () << " Found a shuffle feeding two selects: " << I
2075+ << " \n OldCost: " << OldCost << " vs NewCost: " << NewCost
2076+ << " \n " );
2077+ if (NewCost > OldCost)
2078+ return false ;
2079+
2080+ Value *ShuffleCmp = Builder.CreateShuffleVector (C1, C2, Mask);
2081+ Value *ShuffleTrue = Builder.CreateShuffleVector (T1, T2, Mask);
2082+ Value *ShuffleFalse = Builder.CreateShuffleVector (F1, F2, Mask);
2083+ Value *NewSel;
2084+ // We presuppose that the SelectInsts have the same FMF.
2085+ if (SI0FOp)
2086+ NewSel = Builder.CreateSelectFMF (ShuffleCmp, ShuffleTrue, ShuffleFalse,
2087+ SI0FOp->getFastMathFlags ());
2088+ else
2089+ NewSel = Builder.CreateSelect (ShuffleCmp, ShuffleTrue, ShuffleFalse);
2090+
2091+ Worklist.pushValue (ShuffleCmp);
2092+ Worklist.pushValue (ShuffleTrue);
2093+ Worklist.pushValue (ShuffleFalse);
2094+ replaceValue (I, *NewSel);
2095+ return true ;
2096+ }
2097+
20272098// / Try to convert "shuffle (castop), (castop)" with a shared castop operand
20282099// / into "castop (shuffle)".
20292100bool VectorCombine::foldShuffleOfCastops (Instruction &I) {
@@ -3475,6 +3546,7 @@ bool VectorCombine::run() {
34753546 case Instruction::ShuffleVector:
34763547 MadeChange |= foldPermuteOfBinops (I);
34773548 MadeChange |= foldShuffleOfBinops (I);
3549+ MadeChange |= foldShuffleOfSelects (I);
34783550 MadeChange |= foldShuffleOfCastops (I);
34793551 MadeChange |= foldShuffleOfShuffles (I);
34803552 MadeChange |= foldShuffleOfIntrinsics (I);
0 commit comments