@@ -4925,36 +4925,34 @@ void BoUpSLP::buildExternalUses(
4925
4925
LLVM_DEBUG(dbgs() << "SLP: Checking user:" << *U << ".\n");
4926
4926
4927
4927
Instruction *UserInst = dyn_cast<Instruction>(U);
4928
- if (!UserInst)
4928
+ if (!UserInst || isDeleted(UserInst) )
4929
4929
continue;
4930
4930
4931
- if (isDeleted(UserInst))
4931
+ // Ignore users in the user ignore list.
4932
+ if (UserIgnoreList && UserIgnoreList->contains(UserInst))
4932
4933
continue;
4933
4934
4934
4935
// Skip in-tree scalars that become vectors
4935
4936
if (TreeEntry *UseEntry = getTreeEntry(U)) {
4936
- Value *UseScalar = UseEntry->Scalars[0];
4937
4937
// Some in-tree scalars will remain as scalar in vectorized
4938
- // instructions. If that is the case, the one in Lane 0 will
4938
+ // instructions. If that is the case, the one in FoundLane will
4939
4939
// be used.
4940
- if (UseScalar != U ||
4941
- UseEntry->State == TreeEntry::ScatterVectorize ||
4940
+ if (UseEntry->State == TreeEntry::ScatterVectorize ||
4942
4941
UseEntry->State == TreeEntry::PossibleStridedVectorize ||
4943
- !doesInTreeUserNeedToExtract(Scalar, UserInst, TLI)) {
4942
+ !doesInTreeUserNeedToExtract(
4943
+ Scalar, cast<Instruction>(UseEntry->Scalars.front()), TLI)) {
4944
4944
LLVM_DEBUG(dbgs() << "SLP: \tInternal user will be removed:" << *U
4945
4945
<< ".\n");
4946
4946
assert(UseEntry->State != TreeEntry::NeedToGather && "Bad state");
4947
4947
continue;
4948
4948
}
4949
+ U = nullptr;
4949
4950
}
4950
4951
4951
- // Ignore users in the user ignore list.
4952
- if (UserIgnoreList && UserIgnoreList->contains(UserInst))
4953
- continue;
4954
-
4955
- LLVM_DEBUG(dbgs() << "SLP: Need to extract:" << *U << " from lane "
4956
- << Lane << " from " << *Scalar << ".\n");
4957
- ExternalUses.push_back(ExternalUser(Scalar, U, FoundLane));
4952
+ LLVM_DEBUG(dbgs() << "SLP: Need to extract:" << *UserInst
4953
+ << " from lane " << Lane << " from " << *Scalar
4954
+ << ".\n");
4955
+ ExternalUses.emplace_back(Scalar, U, FoundLane);
4958
4956
}
4959
4957
}
4960
4958
}
@@ -11493,17 +11491,6 @@ Value *BoUpSLP::vectorizeTree(TreeEntry *E, bool PostponedPHIs) {
11493
11491
Value *PO = LI->getPointerOperand();
11494
11492
if (E->State == TreeEntry::Vectorize) {
11495
11493
NewLI = Builder.CreateAlignedLoad(VecTy, PO, LI->getAlign());
11496
-
11497
- // The pointer operand uses an in-tree scalar so we add the new
11498
- // LoadInst to ExternalUses list to make sure that an extract will
11499
- // be generated in the future.
11500
- if (isa<Instruction>(PO)) {
11501
- if (TreeEntry *Entry = getTreeEntry(PO)) {
11502
- // Find which lane we need to extract.
11503
- unsigned FoundLane = Entry->findLaneForValue(PO);
11504
- ExternalUses.emplace_back(PO, NewLI, FoundLane);
11505
- }
11506
- }
11507
11494
} else {
11508
11495
assert((E->State == TreeEntry::ScatterVectorize ||
11509
11496
E->State == TreeEntry::PossibleStridedVectorize) &&
@@ -11539,17 +11526,6 @@ Value *BoUpSLP::vectorizeTree(TreeEntry *E, bool PostponedPHIs) {
11539
11526
StoreInst *ST =
11540
11527
Builder.CreateAlignedStore(VecValue, Ptr, SI->getAlign());
11541
11528
11542
- // The pointer operand uses an in-tree scalar, so add the new StoreInst to
11543
- // ExternalUses to make sure that an extract will be generated in the
11544
- // future.
11545
- if (isa<Instruction>(Ptr)) {
11546
- if (TreeEntry *Entry = getTreeEntry(Ptr)) {
11547
- // Find which lane we need to extract.
11548
- unsigned FoundLane = Entry->findLaneForValue(Ptr);
11549
- ExternalUses.push_back(ExternalUser(Ptr, ST, FoundLane));
11550
- }
11551
- }
11552
-
11553
11529
Value *V = propagateMetadata(ST, E->Scalars);
11554
11530
11555
11531
E->VectorizedValue = V;
@@ -11654,18 +11630,6 @@ Value *BoUpSLP::vectorizeTree(TreeEntry *E, bool PostponedPHIs) {
11654
11630
CI->getOperandBundlesAsDefs(OpBundles);
11655
11631
Value *V = Builder.CreateCall(CF, OpVecs, OpBundles);
11656
11632
11657
- // The scalar argument uses an in-tree scalar so we add the new vectorized
11658
- // call to ExternalUses list to make sure that an extract will be
11659
- // generated in the future.
11660
- if (isa_and_present<Instruction>(ScalarArg)) {
11661
- if (TreeEntry *Entry = getTreeEntry(ScalarArg)) {
11662
- // Find which lane we need to extract.
11663
- unsigned FoundLane = Entry->findLaneForValue(ScalarArg);
11664
- ExternalUses.push_back(
11665
- ExternalUser(ScalarArg, cast<User>(V), FoundLane));
11666
- }
11667
- }
11668
-
11669
11633
propagateIRFlags(V, E->Scalars, VL0);
11670
11634
V = FinalShuffle(V, E, VecTy, IsSigned);
11671
11635
@@ -11877,6 +11841,7 @@ Value *BoUpSLP::vectorizeTree(
11877
11841
DenseMap<Value *, DenseMap<BasicBlock *, Instruction *>> ScalarToEEs;
11878
11842
SmallDenseSet<Value *, 4> UsedInserts;
11879
11843
DenseMap<Value *, Value *> VectorCasts;
11844
+ SmallDenseSet<Value *, 4> ScalarsWithNullptrUser;
11880
11845
// Extract all of the elements with the external uses.
11881
11846
for (const auto &ExternalUse : ExternalUses) {
11882
11847
Value *Scalar = ExternalUse.Scalar;
@@ -11947,13 +11912,25 @@ Value *BoUpSLP::vectorizeTree(
11947
11912
VectorToInsertElement.try_emplace(Vec, IE);
11948
11913
return Vec;
11949
11914
};
11950
- // If User == nullptr, the Scalar is used as extra arg. Generate
11951
- // ExtractElement instruction and update the record for this scalar in
11952
- // ExternallyUsedValues.
11915
+ // If User == nullptr, the Scalar remains as scalar in vectorized
11916
+ // instructions or is used as extra arg. Generate ExtractElement instruction
11917
+ // and update the record for this scalar in ExternallyUsedValues.
11953
11918
if (!User) {
11954
- assert(ExternallyUsedValues.count(Scalar) &&
11955
- "Scalar with nullptr as an external user must be registered in "
11956
- "ExternallyUsedValues map");
11919
+ if (!ScalarsWithNullptrUser.insert(Scalar).second)
11920
+ continue;
11921
+ assert((ExternallyUsedValues.count(Scalar) ||
11922
+ any_of(Scalar->users(),
11923
+ [this, Scalar](llvm::User *U) {
11924
+ TreeEntry *UseEntry = getTreeEntry(U);
11925
+ return UseEntry &&
11926
+ doesInTreeUserNeedToExtract(
11927
+ Scalar,
11928
+ cast<Instruction>(UseEntry->Scalars.front()),
11929
+ TLI);
11930
+ })) &&
11931
+ "Scalar with nullptr User must be registered in "
11932
+ "ExternallyUsedValues map or remain as scalar in vectorized "
11933
+ "instructions");
11957
11934
if (auto *VecI = dyn_cast<Instruction>(Vec)) {
11958
11935
if (auto *PHI = dyn_cast<PHINode>(VecI))
11959
11936
Builder.SetInsertPoint(PHI->getParent(),
0 commit comments