@@ -9076,14 +9076,14 @@ class BaseShuffleAnalysis {
90769076 continue;
90779077 ExtMask[Idx] = SV->getMaskValue(I);
90789078 }
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();
90879087 if (!IsOp1Undef && !IsOp2Undef) {
90889088 // Update mask and mark undef elems.
90899089 for (int &I : Mask) {
@@ -13305,8 +13305,17 @@ Value *BoUpSLP::gather(ArrayRef<Value *> VL, Value *Root, Type *ScalarTy) {
1330513305 return Vec;
1330613306 };
1330713307 auto *VecTy = getWidenedType(ScalarTy, VL.size());
13308- Value *Vec = Root ? Root : PoisonValue::get(VecTy);
13308+ Value *Vec = PoisonValue::get(VecTy);
1330913309 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+ }
1331013319 // Insert constant values at first.
1331113320 for (int I = 0, E = VL.size(); I < E; ++I) {
1331213321 if (PostponedIndices.contains(I))
@@ -13315,19 +13324,20 @@ Value *BoUpSLP::gather(ArrayRef<Value *> VL, Value *Root, Type *ScalarTy) {
1331513324 NonConsts.push_back(I);
1331613325 continue;
1331713326 }
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;
1333013329 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+ }
1333113341 }
1333213342 // Insert non-constant values.
1333313343 for (int I : NonConsts)
@@ -14041,7 +14051,8 @@ ResTy BoUpSLP::processBuildVector(const TreeEntry *E, Type *ScalarTy,
1404114051 if (!ReorderMask.empty())
1404214052 reorderScalars(GatheredScalars, ReorderMask);
1404314053 auto FindReusedSplat = [&](MutableArrayRef<int> Mask, unsigned InputVF,
14044- unsigned I, unsigned SliceSize) {
14054+ unsigned I, unsigned SliceSize,
14055+ bool IsNotPoisonous) {
1404514056 if (!isSplat(E->Scalars) || none_of(E->Scalars, [](Value *V) {
1404614057 return isa<UndefValue>(V) && !isa<PoisonValue>(V);
1404714058 }))
@@ -14050,14 +14061,29 @@ ResTy BoUpSLP::processBuildVector(const TreeEntry *E, Type *ScalarTy,
1405014061 unsigned EdgeIdx = E->UserTreeIndices.back().EdgeIdx;
1405114062 if (UserTE->getNumOperands() != 2)
1405214063 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+ }
1406114087 int Idx;
1406214088 if ((Mask.size() < InputVF &&
1406314089 ShuffleVectorInst::isExtractSubvectorMask(Mask, InputVF, Idx) &&
@@ -14330,12 +14356,13 @@ ResTy BoUpSLP::processBuildVector(const TreeEntry *E, Type *ScalarTy,
1433014356 isGuaranteedNotToBePoison(Vec1) && isGuaranteedNotToBePoison(Vec2);
1433114357 ShuffleBuilder.add(Vec1, Vec2, ExtractMask);
1433214358 } else if (Vec1) {
14359+ bool IsNotPoisonedVec = isGuaranteedNotToBePoison(Vec1);
1433314360 IsUsedInExpr &= FindReusedSplat(
1433414361 ExtractMask,
1433514362 cast<FixedVectorType>(Vec1->getType())->getNumElements(), 0,
14336- ExtractMask.size());
14363+ ExtractMask.size(), IsNotPoisonedVec );
1433714364 ShuffleBuilder.add(Vec1, ExtractMask, /*ForExtracts=*/true);
14338- IsNonPoisoned &= isGuaranteedNotToBePoison(Vec1) ;
14365+ IsNonPoisoned &= IsNotPoisonedVec ;
1433914366 } else {
1434014367 IsUsedInExpr = false;
1434114368 ShuffleBuilder.add(PoisonValue::get(VecTy), ExtractMask,
@@ -14358,12 +14385,15 @@ ResTy BoUpSLP::processBuildVector(const TreeEntry *E, Type *ScalarTy,
1435814385 VecMask.assign(VecMask.size(), PoisonMaskElem);
1435914386 copy(SubMask, std::next(VecMask.begin(), I * SliceSize));
1436014387 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);
1436314395 ShuffleBuilder.add(*TEs.front(), VecMask);
14364- if (TEs.front()->VectorizedValue)
14365- IsNonPoisoned &=
14366- isGuaranteedNotToBePoison(TEs.front()->VectorizedValue);
14396+ IsNonPoisoned &= IsNotPoisonedVec;
1436714397 } else {
1436814398 IsUsedInExpr = false;
1436914399 ShuffleBuilder.add(*TEs.front(), *TEs.back(), VecMask);
0 commit comments