Skip to content

Commit 5d1029b

Browse files
authored
[VectorCombine] Handle shuffle of selects (llvm#128032)
(shuffle(select(c1,t1,f1)), (select(c2,t2,f2)), m) -> (select (shuffle c1,c2,m), (shuffle t1,t2,m), (shuffle f1,f2,m)) The behaviour of SelectInst on vectors is the same as for `V'select[i] = Condition[i] ? V'True[i] : V'False[i]`. If a ShuffleVector is performed on two selects, it will be like: `V'[mask] = (V'select[i] = Condition[i] ? V'True[i] : V'False[i])` That's why a ShuffleVector with two SelectInst is equivalent to first ShuffleVector Condition/True/False and then SelectInst that result. This patch implements the transforming described above. Proof: https://alive2.llvm.org/ce/z/97wfHp Fixes llvm#120775
1 parent 8c61ef1 commit 5d1029b

File tree

2 files changed

+653
-0
lines changed

2 files changed

+653
-0
lines changed

llvm/lib/Transforms/Vectorize/VectorCombine.cpp

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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)".
20292100
bool 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

Comments
 (0)