@@ -9076,14 +9076,14 @@ class BaseShuffleAnalysis {
9076
9076
continue;
9077
9077
ExtMask[Idx] = SV->getMaskValue(I);
9078
9078
}
9079
- bool IsOp1Undef =
9080
- isUndefVector( SV->getOperand(0),
9081
- buildUseMask(LocalVF, ExtMask, UseMask::FirstArg))
9082
- .all();
9083
- bool IsOp2Undef =
9084
- isUndefVector( SV->getOperand(1),
9085
- buildUseMask(LocalVF, ExtMask, UseMask::SecondArg))
9086
- .all();
9079
+ bool IsOp1Undef = isUndefVector</*isPoisonOnly=*/true>(
9080
+ SV->getOperand(0),
9081
+ buildUseMask(LocalVF, ExtMask, UseMask::FirstArg))
9082
+ .all();
9083
+ bool IsOp2Undef = isUndefVector</*isPoisonOnly=*/true>(
9084
+ SV->getOperand(1),
9085
+ buildUseMask(LocalVF, ExtMask, UseMask::SecondArg))
9086
+ .all();
9087
9087
if (!IsOp1Undef && !IsOp2Undef) {
9088
9088
// Update mask and mark undef elems.
9089
9089
for (int &I : Mask) {
@@ -13305,8 +13305,17 @@ Value *BoUpSLP::gather(ArrayRef<Value *> VL, Value *Root, Type *ScalarTy) {
13305
13305
return Vec;
13306
13306
};
13307
13307
auto *VecTy = getWidenedType(ScalarTy, VL.size());
13308
- Value *Vec = Root ? Root : PoisonValue::get(VecTy);
13308
+ Value *Vec = PoisonValue::get(VecTy);
13309
13309
SmallVector<int> NonConsts;
13310
+ SmallVector<int> Mask(VL.size());
13311
+ std::iota(Mask.begin(), Mask.end(), 0);
13312
+ Value *OriginalRoot = Root;
13313
+ if (auto *SV = dyn_cast_or_null<ShuffleVectorInst>(Root);
13314
+ SV && isa<PoisonValue>(SV->getOperand(1)) &&
13315
+ SV->getOperand(0)->getType() == VecTy) {
13316
+ Root = SV->getOperand(0);
13317
+ Mask.assign(SV->getShuffleMask().begin(), SV->getShuffleMask().end());
13318
+ }
13310
13319
// Insert constant values at first.
13311
13320
for (int I = 0, E = VL.size(); I < E; ++I) {
13312
13321
if (PostponedIndices.contains(I))
@@ -13315,19 +13324,20 @@ Value *BoUpSLP::gather(ArrayRef<Value *> VL, Value *Root, Type *ScalarTy) {
13315
13324
NonConsts.push_back(I);
13316
13325
continue;
13317
13326
}
13318
- if (Root) {
13319
- if (!isa<UndefValue>(VL[I])) {
13320
- NonConsts.push_back(I);
13321
- continue;
13322
- }
13323
- if (isa<PoisonValue>(VL[I]))
13324
- continue;
13325
- if (auto *SV = dyn_cast<ShuffleVectorInst>(Root)) {
13326
- if (SV->getMaskValue(I) == PoisonMaskElem)
13327
- continue;
13328
- }
13329
- }
13327
+ if (isa<PoisonValue>(VL[I]))
13328
+ continue;
13330
13329
Vec = CreateInsertElement(Vec, VL[I], I, ScalarTy);
13330
+ Mask[I] = I + E;
13331
+ }
13332
+ if (Root) {
13333
+ if (isa<PoisonValue>(Vec)) {
13334
+ Vec = OriginalRoot;
13335
+ } else {
13336
+ Vec = Builder.CreateShuffleVector(Root, Vec, Mask);
13337
+ if (auto *OI = dyn_cast<Instruction>(OriginalRoot);
13338
+ OI && OI->hasNUses(0))
13339
+ eraseInstruction(OI);
13340
+ }
13331
13341
}
13332
13342
// Insert non-constant values.
13333
13343
for (int I : NonConsts)
@@ -14041,7 +14051,8 @@ ResTy BoUpSLP::processBuildVector(const TreeEntry *E, Type *ScalarTy,
14041
14051
if (!ReorderMask.empty())
14042
14052
reorderScalars(GatheredScalars, ReorderMask);
14043
14053
auto FindReusedSplat = [&](MutableArrayRef<int> Mask, unsigned InputVF,
14044
- unsigned I, unsigned SliceSize) {
14054
+ unsigned I, unsigned SliceSize,
14055
+ bool IsNotPoisonous) {
14045
14056
if (!isSplat(E->Scalars) || none_of(E->Scalars, [](Value *V) {
14046
14057
return isa<UndefValue>(V) && !isa<PoisonValue>(V);
14047
14058
}))
@@ -14050,14 +14061,29 @@ ResTy BoUpSLP::processBuildVector(const TreeEntry *E, Type *ScalarTy,
14050
14061
unsigned EdgeIdx = E->UserTreeIndices.back().EdgeIdx;
14051
14062
if (UserTE->getNumOperands() != 2)
14052
14063
return false;
14053
- auto *It =
14054
- find_if(VectorizableTree, [=](const std::unique_ptr<TreeEntry> &TE) {
14055
- return find_if(TE->UserTreeIndices, [=](const EdgeInfo &EI) {
14056
- return EI.UserTE == UserTE && EI.EdgeIdx != EdgeIdx;
14057
- }) != TE->UserTreeIndices.end();
14058
- });
14059
- if (It == VectorizableTree.end())
14060
- return false;
14064
+ if (!IsNotPoisonous) {
14065
+ auto *It =
14066
+ find_if(VectorizableTree, [=](const std::unique_ptr<TreeEntry> &TE) {
14067
+ return find_if(TE->UserTreeIndices, [=](const EdgeInfo &EI) {
14068
+ return EI.UserTE == UserTE && EI.EdgeIdx != EdgeIdx;
14069
+ }) != TE->UserTreeIndices.end();
14070
+ });
14071
+ if (It == VectorizableTree.end())
14072
+ return false;
14073
+ SmallVector<Value *> GS((*It)->Scalars.begin(), (*It)->Scalars.end());
14074
+ if (!(*It)->ReorderIndices.empty()) {
14075
+ inversePermutation((*It)->ReorderIndices, ReorderMask);
14076
+ reorderScalars(GS, ReorderMask);
14077
+ }
14078
+ if (!all_of(zip(GatheredScalars, GS), [&](const auto &P) {
14079
+ Value *V0 = std::get<0>(P);
14080
+ Value *V1 = std::get<1>(P);
14081
+ return !isa<UndefValue>(V0) || isa<PoisonValue>(V0) ||
14082
+ (isa<UndefValue>(V0) && !isa<PoisonValue>(V0) &&
14083
+ is_contained(E->Scalars, V1));
14084
+ }))
14085
+ return false;
14086
+ }
14061
14087
int Idx;
14062
14088
if ((Mask.size() < InputVF &&
14063
14089
ShuffleVectorInst::isExtractSubvectorMask(Mask, InputVF, Idx) &&
@@ -14330,12 +14356,13 @@ ResTy BoUpSLP::processBuildVector(const TreeEntry *E, Type *ScalarTy,
14330
14356
isGuaranteedNotToBePoison(Vec1) && isGuaranteedNotToBePoison(Vec2);
14331
14357
ShuffleBuilder.add(Vec1, Vec2, ExtractMask);
14332
14358
} else if (Vec1) {
14359
+ bool IsNotPoisonedVec = isGuaranteedNotToBePoison(Vec1);
14333
14360
IsUsedInExpr &= FindReusedSplat(
14334
14361
ExtractMask,
14335
14362
cast<FixedVectorType>(Vec1->getType())->getNumElements(), 0,
14336
- ExtractMask.size());
14363
+ ExtractMask.size(), IsNotPoisonedVec );
14337
14364
ShuffleBuilder.add(Vec1, ExtractMask, /*ForExtracts=*/true);
14338
- IsNonPoisoned &= isGuaranteedNotToBePoison(Vec1) ;
14365
+ IsNonPoisoned &= IsNotPoisonedVec ;
14339
14366
} else {
14340
14367
IsUsedInExpr = false;
14341
14368
ShuffleBuilder.add(PoisonValue::get(VecTy), ExtractMask,
@@ -14358,12 +14385,15 @@ ResTy BoUpSLP::processBuildVector(const TreeEntry *E, Type *ScalarTy,
14358
14385
VecMask.assign(VecMask.size(), PoisonMaskElem);
14359
14386
copy(SubMask, std::next(VecMask.begin(), I * SliceSize));
14360
14387
if (TEs.size() == 1) {
14361
- IsUsedInExpr &= FindReusedSplat(
14362
- VecMask, TEs.front()->getVectorFactor(), I, SliceSize);
14388
+ bool IsNotPoisonedVec =
14389
+ TEs.front()->VectorizedValue
14390
+ ? isGuaranteedNotToBePoison(TEs.front()->VectorizedValue)
14391
+ : true;
14392
+ IsUsedInExpr &=
14393
+ FindReusedSplat(VecMask, TEs.front()->getVectorFactor(), I,
14394
+ SliceSize, IsNotPoisonedVec);
14363
14395
ShuffleBuilder.add(*TEs.front(), VecMask);
14364
- if (TEs.front()->VectorizedValue)
14365
- IsNonPoisoned &=
14366
- isGuaranteedNotToBePoison(TEs.front()->VectorizedValue);
14396
+ IsNonPoisoned &= IsNotPoisonedVec;
14367
14397
} else {
14368
14398
IsUsedInExpr = false;
14369
14399
ShuffleBuilder.add(*TEs.front(), *TEs.back(), VecMask);
0 commit comments