@@ -120,6 +120,7 @@ class VectorCombine {
120
120
bool foldConcatOfBoolMasks (Instruction &I);
121
121
bool foldPermuteOfBinops (Instruction &I);
122
122
bool foldShuffleOfBinops (Instruction &I);
123
+ bool foldShuffleOfSelects (Instruction &I);
123
124
bool foldShuffleOfCastops (Instruction &I);
124
125
bool foldShuffleOfShuffles (Instruction &I);
125
126
bool foldShuffleOfIntrinsics (Instruction &I);
@@ -2024,6 +2025,76 @@ bool VectorCombine::foldShuffleOfBinops(Instruction &I) {
2024
2025
return true ;
2025
2026
}
2026
2027
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
+
2027
2098
// / Try to convert "shuffle (castop), (castop)" with a shared castop operand
2028
2099
// / into "castop (shuffle)".
2029
2100
bool VectorCombine::foldShuffleOfCastops (Instruction &I) {
@@ -3475,6 +3546,7 @@ bool VectorCombine::run() {
3475
3546
case Instruction::ShuffleVector:
3476
3547
MadeChange |= foldPermuteOfBinops (I);
3477
3548
MadeChange |= foldShuffleOfBinops (I);
3549
+ MadeChange |= foldShuffleOfSelects (I);
3478
3550
MadeChange |= foldShuffleOfCastops (I);
3479
3551
MadeChange |= foldShuffleOfShuffles (I);
3480
3552
MadeChange |= foldShuffleOfIntrinsics (I);
0 commit comments