@@ -368,16 +368,6 @@ static bool onlyStoresToTailObjects(BuiltinInst *destroyArray,
368368 return true ;
369369}
370370
371- // / Inserts releases of all stores in \p users.
372- static void insertCompensatingReleases (SILInstruction *before,
373- const UserList &users) {
374- for (SILInstruction *user : users) {
375- if (auto *store = dyn_cast<StoreInst>(user)) {
376- createDecrementBefore (store->getSrc (), before);
377- }
378- }
379- }
380-
381371// / Analyze the use graph of AllocRef for any uses that would prevent us from
382372// / zapping it completely.
383373static bool
@@ -736,6 +726,7 @@ class DeadObjectElimination : public SILFunctionTransform {
736726 llvm::DenseMap<SILType, DestructorEffects> DestructorAnalysisCache;
737727
738728 InstructionDeleter deleter;
729+ DominanceInfo *domInfo = nullptr ;
739730
740731 void removeInstructions (ArrayRef<SILInstruction*> toRemove);
741732
@@ -745,6 +736,9 @@ class DeadObjectElimination : public SILFunctionTransform {
745736 bool processAllocBox (AllocBoxInst *ABI){ return false ;}
746737 bool processAllocApply (ApplyInst *AI, DeadEndBlocks &DEBlocks);
747738
739+ bool insertCompensatingReleases (SILInstruction *before,
740+ const UserList &users);
741+
748742 bool getDeadInstsAfterInitializerRemoved (
749743 ApplyInst *AI, llvm::SmallVectorImpl<SILInstruction *> &ToDestroy);
750744 bool removeAndReleaseArray (
@@ -780,9 +774,12 @@ class DeadObjectElimination : public SILFunctionTransform {
780774 if (getFunction ()->hasOwnership ())
781775 return ;
782776
777+ assert (!domInfo);
778+
783779 if (processFunction (*getFunction ())) {
784780 invalidateAnalysis (SILAnalysis::InvalidationKind::CallsAndInstructions);
785781 }
782+ domInfo = nullptr ;
786783 }
787784
788785};
@@ -841,8 +838,11 @@ bool DeadObjectElimination::processAllocRef(AllocRefInstBase *ARI) {
841838 releaseOfTailElems = user;
842839 }
843840 }
844- if (releaseOfTailElems)
845- insertCompensatingReleases (releaseOfTailElems, UsersToRemove);
841+ if (releaseOfTailElems) {
842+ if (!insertCompensatingReleases (releaseOfTailElems, UsersToRemove)) {
843+ return false ;
844+ }
845+ }
846846
847847 // Remove the AllocRef and all of its users.
848848 removeInstructions (
@@ -1052,6 +1052,33 @@ bool DeadObjectElimination::processAllocApply(ApplyInst *AI,
10521052 return true ;
10531053}
10541054
1055+ // / Inserts releases of all stores in \p users.
1056+ // / Returns false, if this is not possible.
1057+ bool DeadObjectElimination::insertCompensatingReleases (SILInstruction *before,
1058+ const UserList &users) {
1059+
1060+ // First check if all stored values dominate the release-point.
1061+ for (SILInstruction *user : users) {
1062+ if (auto *store = dyn_cast<StoreInst>(user)) {
1063+ if (!domInfo) {
1064+ domInfo = getAnalysis<DominanceAnalysis>()->get (before->getFunction ());
1065+ }
1066+ SILBasicBlock *srcBlock = store->getSrc ()->getParentBlock ();
1067+ if (!domInfo->dominates (srcBlock, before->getParent ()))
1068+ return false ;
1069+ }
1070+ }
1071+
1072+ // Second, create the releases.
1073+ for (SILInstruction *user : users) {
1074+ if (auto *store = dyn_cast<StoreInst>(user)) {
1075+ createDecrementBefore (store->getSrc (), before);
1076+ }
1077+ }
1078+ return true ;
1079+ }
1080+
1081+
10551082// ===----------------------------------------------------------------------===//
10561083// Top Level Driver
10571084// ===----------------------------------------------------------------------===//
0 commit comments