@@ -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
}
@@ -11516,17 +11514,6 @@ Value *BoUpSLP::vectorizeTree(TreeEntry *E, bool PostponedPHIs) {
11516
11514
Value *PO = LI->getPointerOperand();
11517
11515
if (E->State == TreeEntry::Vectorize) {
11518
11516
NewLI = Builder.CreateAlignedLoad(VecTy, PO, LI->getAlign());
11519
-
11520
- // The pointer operand uses an in-tree scalar so we add the new
11521
- // LoadInst to ExternalUses list to make sure that an extract will
11522
- // be generated in the future.
11523
- if (isa<Instruction>(PO)) {
11524
- if (TreeEntry *Entry = getTreeEntry(PO)) {
11525
- // Find which lane we need to extract.
11526
- unsigned FoundLane = Entry->findLaneForValue(PO);
11527
- ExternalUses.emplace_back(PO, NewLI, FoundLane);
11528
- }
11529
- }
11530
11517
} else {
11531
11518
assert((E->State == TreeEntry::ScatterVectorize ||
11532
11519
E->State == TreeEntry::PossibleStridedVectorize) &&
@@ -11562,17 +11549,6 @@ Value *BoUpSLP::vectorizeTree(TreeEntry *E, bool PostponedPHIs) {
11562
11549
StoreInst *ST =
11563
11550
Builder.CreateAlignedStore(VecValue, Ptr, SI->getAlign());
11564
11551
11565
- // The pointer operand uses an in-tree scalar, so add the new StoreInst to
11566
- // ExternalUses to make sure that an extract will be generated in the
11567
- // future.
11568
- if (isa<Instruction>(Ptr)) {
11569
- if (TreeEntry *Entry = getTreeEntry(Ptr)) {
11570
- // Find which lane we need to extract.
11571
- unsigned FoundLane = Entry->findLaneForValue(Ptr);
11572
- ExternalUses.push_back(ExternalUser(Ptr, ST, FoundLane));
11573
- }
11574
- }
11575
-
11576
11552
Value *V = propagateMetadata(ST, E->Scalars);
11577
11553
11578
11554
E->VectorizedValue = V;
@@ -11677,18 +11653,6 @@ Value *BoUpSLP::vectorizeTree(TreeEntry *E, bool PostponedPHIs) {
11677
11653
CI->getOperandBundlesAsDefs(OpBundles);
11678
11654
Value *V = Builder.CreateCall(CF, OpVecs, OpBundles);
11679
11655
11680
- // The scalar argument uses an in-tree scalar so we add the new vectorized
11681
- // call to ExternalUses list to make sure that an extract will be
11682
- // generated in the future.
11683
- if (isa_and_present<Instruction>(ScalarArg)) {
11684
- if (TreeEntry *Entry = getTreeEntry(ScalarArg)) {
11685
- // Find which lane we need to extract.
11686
- unsigned FoundLane = Entry->findLaneForValue(ScalarArg);
11687
- ExternalUses.push_back(
11688
- ExternalUser(ScalarArg, cast<User>(V), FoundLane));
11689
- }
11690
- }
11691
-
11692
11656
propagateIRFlags(V, E->Scalars, VL0);
11693
11657
V = FinalShuffle(V, E, VecTy, IsSigned);
11694
11658
@@ -11900,6 +11864,7 @@ Value *BoUpSLP::vectorizeTree(
11900
11864
DenseMap<Value *, DenseMap<BasicBlock *, Instruction *>> ScalarToEEs;
11901
11865
SmallDenseSet<Value *, 4> UsedInserts;
11902
11866
DenseMap<Value *, Value *> VectorCasts;
11867
+ SmallDenseSet<Value *, 4> ScalarsWithNullptrUser;
11903
11868
// Extract all of the elements with the external uses.
11904
11869
for (const auto &ExternalUse : ExternalUses) {
11905
11870
Value *Scalar = ExternalUse.Scalar;
@@ -11970,13 +11935,27 @@ Value *BoUpSLP::vectorizeTree(
11970
11935
VectorToInsertElement.try_emplace(Vec, IE);
11971
11936
return Vec;
11972
11937
};
11973
- // If User == nullptr, the Scalar is used as extra arg. Generate
11974
- // ExtractElement instruction and update the record for this scalar in
11975
- // ExternallyUsedValues.
11938
+ // If User == nullptr, the Scalar remains as scalar in vectorized
11939
+ // instructions or is used as extra arg. Generate ExtractElement instruction
11940
+ // and update the record for this scalar in ExternallyUsedValues.
11976
11941
if (!User) {
11977
- assert(ExternallyUsedValues.count(Scalar) &&
11978
- "Scalar with nullptr as an external user must be registered in "
11979
- "ExternallyUsedValues map");
11942
+ if (!ScalarsWithNullptrUser.insert(Scalar).second)
11943
+ continue;
11944
+ assert((ExternallyUsedValues.count(Scalar) ||
11945
+ any_of(Scalar->users(),
11946
+ [&](llvm::User *U) {
11947
+ TreeEntry *UseEntry = getTreeEntry(U);
11948
+ return UseEntry &&
11949
+ UseEntry->State == TreeEntry::Vectorize &&
11950
+ E->State == TreeEntry::Vectorize &&
11951
+ doesInTreeUserNeedToExtract(
11952
+ Scalar,
11953
+ cast<Instruction>(UseEntry->Scalars.front()),
11954
+ TLI);
11955
+ })) &&
11956
+ "Scalar with nullptr User must be registered in "
11957
+ "ExternallyUsedValues map or remain as scalar in vectorized "
11958
+ "instructions");
11980
11959
if (auto *VecI = dyn_cast<Instruction>(Vec)) {
11981
11960
if (auto *PHI = dyn_cast<PHINode>(VecI))
11982
11961
Builder.SetInsertPoint(PHI->getParent(),
0 commit comments