@@ -368,16 +368,6 @@ static bool onlyStoresToTailObjects(BuiltinInst *destroyArray,
368
368
return true ;
369
369
}
370
370
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
-
381
371
// / Analyze the use graph of AllocRef for any uses that would prevent us from
382
372
// / zapping it completely.
383
373
static bool
@@ -736,6 +726,7 @@ class DeadObjectElimination : public SILFunctionTransform {
736
726
llvm::DenseMap<SILType, DestructorEffects> DestructorAnalysisCache;
737
727
738
728
InstructionDeleter deleter;
729
+ DominanceInfo *domInfo = nullptr ;
739
730
740
731
void removeInstructions (ArrayRef<SILInstruction*> toRemove);
741
732
@@ -745,6 +736,9 @@ class DeadObjectElimination : public SILFunctionTransform {
745
736
bool processAllocBox (AllocBoxInst *ABI){ return false ;}
746
737
bool processAllocApply (ApplyInst *AI, DeadEndBlocks &DEBlocks);
747
738
739
+ bool insertCompensatingReleases (SILInstruction *before,
740
+ const UserList &users);
741
+
748
742
bool getDeadInstsAfterInitializerRemoved (
749
743
ApplyInst *AI, llvm::SmallVectorImpl<SILInstruction *> &ToDestroy);
750
744
bool removeAndReleaseArray (
@@ -780,9 +774,12 @@ class DeadObjectElimination : public SILFunctionTransform {
780
774
if (getFunction ()->hasOwnership ())
781
775
return ;
782
776
777
+ assert (!domInfo);
778
+
783
779
if (processFunction (*getFunction ())) {
784
780
invalidateAnalysis (SILAnalysis::InvalidationKind::CallsAndInstructions);
785
781
}
782
+ domInfo = nullptr ;
786
783
}
787
784
788
785
};
@@ -841,8 +838,11 @@ bool DeadObjectElimination::processAllocRef(AllocRefInstBase *ARI) {
841
838
releaseOfTailElems = user;
842
839
}
843
840
}
844
- if (releaseOfTailElems)
845
- insertCompensatingReleases (releaseOfTailElems, UsersToRemove);
841
+ if (releaseOfTailElems) {
842
+ if (!insertCompensatingReleases (releaseOfTailElems, UsersToRemove)) {
843
+ return false ;
844
+ }
845
+ }
846
846
847
847
// Remove the AllocRef and all of its users.
848
848
removeInstructions (
@@ -1052,6 +1052,33 @@ bool DeadObjectElimination::processAllocApply(ApplyInst *AI,
1052
1052
return true ;
1053
1053
}
1054
1054
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
+
1055
1082
// ===----------------------------------------------------------------------===//
1056
1083
// Top Level Driver
1057
1084
// ===----------------------------------------------------------------------===//
0 commit comments