@@ -702,7 +702,8 @@ static SmallBitVector isUndefVector(const Value *V,
702
702
/// TODO: Can we split off and reuse the shuffle mask detection from
703
703
/// ShuffleVectorInst/getShuffleCost?
704
704
static std::optional<TargetTransformInfo::ShuffleKind>
705
- isFixedVectorShuffle(ArrayRef<Value *> VL, SmallVectorImpl<int> &Mask) {
705
+ isFixedVectorShuffle(ArrayRef<Value *> VL, SmallVectorImpl<int> &Mask,
706
+ AssumptionCache *AC) {
706
707
const auto *It = find_if(VL, IsaPred<ExtractElementInst>);
707
708
if (It == VL.end())
708
709
return std::nullopt;
@@ -719,14 +720,14 @@ isFixedVectorShuffle(ArrayRef<Value *> VL, SmallVectorImpl<int> &Mask) {
719
720
720
721
Value *Vec1 = nullptr;
721
722
Value *Vec2 = nullptr;
722
- bool HasNonUndefVec = any_of(VL, [](Value *V) {
723
+ bool HasNonUndefVec = any_of(VL, [& ](Value *V) {
723
724
auto *EE = dyn_cast<ExtractElementInst>(V);
724
725
if (!EE)
725
726
return false;
726
727
Value *Vec = EE->getVectorOperand();
727
728
if (isa<UndefValue>(Vec))
728
729
return false;
729
- return isGuaranteedNotToBePoison(Vec);
730
+ return isGuaranteedNotToBePoison(Vec, AC );
730
731
});
731
732
enum ShuffleMode { Unknown, Select, Permute };
732
733
ShuffleMode CommonShuffleMode = Unknown;
@@ -11875,7 +11876,7 @@ bool BoUpSLP::isFullyVectorizableTinyTree(bool ForReduction) const {
11875
11876
TE->Scalars.size() < Limit ||
11876
11877
((TE->getOpcode() == Instruction::ExtractElement ||
11877
11878
all_of(TE->Scalars, IsaPred<ExtractElementInst, UndefValue>)) &&
11878
- isFixedVectorShuffle(TE->Scalars, Mask)) ||
11879
+ isFixedVectorShuffle(TE->Scalars, Mask, AC )) ||
11879
11880
(TE->getOpcode() == Instruction::Load && !TE->isAltShuffle()) ||
11880
11881
any_of(TE->Scalars, IsaPred<LoadInst>));
11881
11882
};
@@ -12940,7 +12941,7 @@ BoUpSLP::tryToGatherSingleRegisterExtractElements(
12940
12941
// Check that gather of extractelements can be represented as just a
12941
12942
// shuffle of a single/two vectors the scalars are extracted from.
12942
12943
std::optional<TTI::ShuffleKind> Res =
12943
- isFixedVectorShuffle(GatheredExtracts, Mask);
12944
+ isFixedVectorShuffle(GatheredExtracts, Mask, AC );
12944
12945
if (!Res || all_of(Mask, [](int Idx) { return Idx == PoisonMaskElem; })) {
12945
12946
// TODO: try to check other subsets if possible.
12946
12947
// Restore the original VL if attempt was not successful.
@@ -14828,7 +14829,7 @@ ResTy BoUpSLP::processBuildVector(const TreeEntry *E, Type *ScalarTy,
14828
14829
// non-poisonous, or by freezing the incoming scalar value first.
14829
14830
auto *It = find_if(Scalars, [this, E](Value *V) {
14830
14831
return !isa<UndefValue>(V) &&
14831
- (getTreeEntry(V) || isGuaranteedNotToBePoison(V) ||
14832
+ (getTreeEntry(V) || isGuaranteedNotToBePoison(V, AC ) ||
14832
14833
(E->UserTreeIndices.size() == 1 &&
14833
14834
any_of(V->uses(), [E](const Use &U) {
14834
14835
// Check if the value already used in the same operation in
@@ -14900,11 +14901,11 @@ ResTy BoUpSLP::processBuildVector(const TreeEntry *E, Type *ScalarTy,
14900
14901
}
14901
14902
if (Vec2) {
14902
14903
IsUsedInExpr = false;
14903
- IsNonPoisoned &=
14904
- isGuaranteedNotToBePoison(Vec1) && isGuaranteedNotToBePoison(Vec2);
14904
+ IsNonPoisoned &= isGuaranteedNotToBePoison(Vec1, AC) &&
14905
+ isGuaranteedNotToBePoison(Vec2, AC );
14905
14906
ShuffleBuilder.add(Vec1, Vec2, ExtractMask);
14906
14907
} else if (Vec1) {
14907
- bool IsNotPoisonedVec = isGuaranteedNotToBePoison(Vec1);
14908
+ bool IsNotPoisonedVec = isGuaranteedNotToBePoison(Vec1, AC );
14908
14909
IsUsedInExpr &= FindReusedSplat(
14909
14910
ExtractMask,
14910
14911
cast<FixedVectorType>(Vec1->getType())->getNumElements(), 0,
@@ -14935,7 +14936,7 @@ ResTy BoUpSLP::processBuildVector(const TreeEntry *E, Type *ScalarTy,
14935
14936
if (TEs.size() == 1) {
14936
14937
bool IsNotPoisonedVec =
14937
14938
TEs.front()->VectorizedValue
14938
- ? isGuaranteedNotToBePoison(TEs.front()->VectorizedValue)
14939
+ ? isGuaranteedNotToBePoison(TEs.front()->VectorizedValue, AC )
14939
14940
: true;
14940
14941
IsUsedInExpr &=
14941
14942
FindReusedSplat(VecMask, TEs.front()->getVectorFactor(), I,
@@ -14947,8 +14948,8 @@ ResTy BoUpSLP::processBuildVector(const TreeEntry *E, Type *ScalarTy,
14947
14948
ShuffleBuilder.add(*TEs.front(), *TEs.back(), VecMask);
14948
14949
if (TEs.front()->VectorizedValue && TEs.back()->VectorizedValue)
14949
14950
IsNonPoisoned &=
14950
- isGuaranteedNotToBePoison(TEs.front()->VectorizedValue) &&
14951
- isGuaranteedNotToBePoison(TEs.back()->VectorizedValue);
14951
+ isGuaranteedNotToBePoison(TEs.front()->VectorizedValue, AC ) &&
14952
+ isGuaranteedNotToBePoison(TEs.back()->VectorizedValue, AC );
14952
14953
}
14953
14954
}
14954
14955
}
@@ -15283,7 +15284,8 @@ Value *BoUpSLP::vectorizeTree(TreeEntry *E, bool PostponedPHIs) {
15283
15284
}
15284
15285
if (!IsIdentity || NumElts != NumScalars) {
15285
15286
Value *V2 = nullptr;
15286
- bool IsVNonPoisonous = isGuaranteedNotToBePoison(V) && !isConstant(V);
15287
+ bool IsVNonPoisonous =
15288
+ !isConstant(V) && isGuaranteedNotToBePoison(V, AC);
15287
15289
SmallVector<int> InsertMask(Mask);
15288
15290
if (NumElts != NumScalars && Offset == 0) {
15289
15291
// Follow all insert element instructions from the current buildvector
@@ -19638,7 +19640,7 @@ class HorizontalReduction {
19638
19640
19639
19641
/// Attempt to vectorize the tree found by matchAssociativeReduction.
19640
19642
Value *tryToReduce(BoUpSLP &V, const DataLayout &DL, TargetTransformInfo *TTI,
19641
- const TargetLibraryInfo &TLI) {
19643
+ const TargetLibraryInfo &TLI, AssumptionCache *AC ) {
19642
19644
const unsigned ReductionLimit = VectorizeNonPowerOf2 ? 3 : 4;
19643
19645
constexpr unsigned RegMaxNumber = 4;
19644
19646
constexpr unsigned RedValsMaxNumber = 128;
@@ -19695,15 +19697,15 @@ class HorizontalReduction {
19695
19697
19696
19698
if (auto It = ReducedValsToOps.find(VectorizedTree);
19697
19699
It == ReducedValsToOps.end() ||
19698
- isGuaranteedNotToBePoison(VectorizedTree) ||
19700
+ isGuaranteedNotToBePoison(VectorizedTree, AC ) ||
19699
19701
any_of(It->getSecond(), [&](Instruction *I) {
19700
19702
return isBoolLogicOp(I) &&
19701
19703
getRdxOperand(I, 0) == VectorizedTree;
19702
19704
})) {
19703
19705
;
19704
19706
} else if (auto It = ReducedValsToOps.find(Res);
19705
19707
It == ReducedValsToOps.end() ||
19706
- isGuaranteedNotToBePoison(Res) ||
19708
+ isGuaranteedNotToBePoison(Res, AC ) ||
19707
19709
any_of(It->getSecond(), [&](Instruction *I) {
19708
19710
return isBoolLogicOp(I) && getRdxOperand(I, 0) == Res;
19709
19711
})) {
@@ -19795,7 +19797,7 @@ class HorizontalReduction {
19795
19797
TrackedToOrig.try_emplace(RdxVal, RV);
19796
19798
}
19797
19799
SmallVector<int> Mask;
19798
- if (isFixedVectorShuffle(CommonCandidates, Mask)) {
19800
+ if (isFixedVectorShuffle(CommonCandidates, Mask, AC )) {
19799
19801
++I;
19800
19802
Candidates.swap(CommonCandidates);
19801
19803
ShuffledExtracts = true;
@@ -20110,7 +20112,7 @@ class HorizontalReduction {
20110
20112
// To prevent poison from leaking across what used to be sequential,
20111
20113
// safe, scalar boolean logic operations, the reduction operand must be
20112
20114
// frozen.
20113
- if (AnyBoolLogicOp && !isGuaranteedNotToBePoison(VectorizedRoot))
20115
+ if (AnyBoolLogicOp && !isGuaranteedNotToBePoison(VectorizedRoot, AC ))
20114
20116
VectorizedRoot = Builder.CreateFreeze(VectorizedRoot);
20115
20117
20116
20118
// Emit code to correctly handle reused reduced values, if required.
@@ -20217,13 +20219,13 @@ class HorizontalReduction {
20217
20219
bool InitStep) {
20218
20220
if (!AnyBoolLogicOp)
20219
20221
return;
20220
- if (isBoolLogicOp(RedOp1) &&
20221
- ((!InitStep && LHS == VectorizedTree) ||
20222
- getRdxOperand(RedOp1, 0) == LHS || isGuaranteedNotToBePoison(LHS)))
20222
+ if (isBoolLogicOp(RedOp1) && ((!InitStep && LHS == VectorizedTree) ||
20223
+ getRdxOperand(RedOp1, 0) == LHS ||
20224
+ isGuaranteedNotToBePoison(LHS, AC )))
20223
20225
return;
20224
20226
if (isBoolLogicOp(RedOp2) && ((!InitStep && RHS == VectorizedTree) ||
20225
20227
getRdxOperand(RedOp2, 0) == RHS ||
20226
- isGuaranteedNotToBePoison(RHS))) {
20228
+ isGuaranteedNotToBePoison(RHS, AC ))) {
20227
20229
std::swap(LHS, RHS);
20228
20230
return;
20229
20231
}
@@ -20871,7 +20873,7 @@ bool SLPVectorizerPass::vectorizeHorReduction(
20871
20873
HorizontalReduction HorRdx;
20872
20874
if (!HorRdx.matchAssociativeReduction(R, Inst, *SE, *DL, *TLI))
20873
20875
return nullptr;
20874
- return HorRdx.tryToReduce(R, *DL, TTI, *TLI);
20876
+ return HorRdx.tryToReduce(R, *DL, TTI, *TLI, AC );
20875
20877
};
20876
20878
auto TryAppendToPostponedInsts = [&](Instruction *FutureSeed) {
20877
20879
if (TryOperandsAsNewSeeds && FutureSeed == Root) {
@@ -20977,8 +20979,8 @@ bool SLPVectorizerPass::vectorizeInsertElementInst(InsertElementInst *IEI,
20977
20979
SmallVector<Value *, 16> BuildVectorOpds;
20978
20980
SmallVector<int> Mask;
20979
20981
if (!findBuildAggregate(IEI, TTI, BuildVectorOpds, BuildVectorInsts, R) ||
20980
- (llvm:: all_of(BuildVectorOpds, IsaPred<ExtractElementInst, UndefValue>) &&
20981
- isFixedVectorShuffle(BuildVectorOpds, Mask)))
20982
+ (all_of(BuildVectorOpds, IsaPred<ExtractElementInst, UndefValue>) &&
20983
+ isFixedVectorShuffle(BuildVectorOpds, Mask, AC )))
20982
20984
return false;
20983
20985
20984
20986
if (MaxVFOnly && BuildVectorInsts.size() == 2) {
0 commit comments