Skip to content

Commit 51bc273

Browse files
authored
Merge pull request #59591 from eeckstein/fix-dead-obj-elim
DeadObjectElimination: fix a bug which caused wrong inserted release instructions.
2 parents 0f0039a + 8fd1776 commit 51bc273

File tree

2 files changed

+85
-12
lines changed

2 files changed

+85
-12
lines changed

lib/SILOptimizer/Transforms/DeadObjectElimination.cpp

Lines changed: 39 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -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.
383373
static 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
//===----------------------------------------------------------------------===//

test/SILOptimizer/dead_alloc_elim.sil

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -669,3 +669,49 @@ bb0:
669669
return %r : $()
670670
}
671671

672+
sil @createit : $@convention(thin) () -> @owned Kl
673+
674+
// Check that we don't crash here.
675+
sil @not_dominating_stores : $@convention(thin) () -> () {
676+
bb0:
677+
%7 = integer_literal $Builtin.Word, 1
678+
%10 = alloc_ref [stack] [tail_elems $Kl * %7 : $Builtin.Word] $_ContiguousArrayStorage<Kl>
679+
%11 = upcast %10 : $_ContiguousArrayStorage<Kl> to $__ContiguousArrayStorageBase
680+
%18 = ref_tail_addr %11 : $__ContiguousArrayStorageBase, $Kl
681+
%35 = function_ref @createit : $@convention(thin) () -> @owned Kl
682+
cond_br undef, bb1, bb2
683+
bb1:
684+
%36 = apply %35() : $@convention(thin) () -> @owned Kl
685+
store %36 to %18 : $*Kl
686+
br bb3
687+
bb2:
688+
%46 = apply %35() : $@convention(thin) () -> @owned Kl
689+
store %46 to %18 : $*Kl
690+
br bb3
691+
bb3:
692+
strong_release %10 : $_ContiguousArrayStorage<Kl>
693+
dealloc_stack_ref %10 : $_ContiguousArrayStorage<Kl>
694+
%1 = tuple()
695+
return %1 : $()
696+
}
697+
698+
sil @$ss23_ContiguousArrayStorageCfD : $@convention(method) <Element> (@owned _ContiguousArrayStorage<Element>) -> () {
699+
bb0(%0 : $_ContiguousArrayStorage<Element>):
700+
%1 = ref_tail_addr %0 : $_ContiguousArrayStorage<Element>, $Element
701+
%2 = address_to_pointer %1 : $*Element to $Builtin.RawPointer
702+
%3 = upcast %0 : $_ContiguousArrayStorage<Element> to $__ContiguousArrayStorageBase
703+
%4 = ref_element_addr %3 : $__ContiguousArrayStorageBase, #__ContiguousArrayStorageBase.countAndCapacity
704+
%5 = struct_element_addr %4 : $*_ArrayBody, #_ArrayBody._storage
705+
%6 = struct_element_addr %5 : $*_SwiftArrayBodyStorage, #_SwiftArrayBodyStorage.count
706+
%7 = struct_element_addr %6 : $*Int, #Int._value
707+
%8 = load %7 : $*Builtin.Int64
708+
%9 = builtin "assumeNonNegative_Int64"(%8 : $Builtin.Int64) : $Builtin.Int64
709+
%10 = metatype $@thick Element.Type
710+
%11 = builtin "truncOrBitCast_Int64_Word"(%9 : $Builtin.Int64) : $Builtin.Word
711+
%12 = builtin "destroyArray"<Element>(%10 : $@thick Element.Type, %2 : $Builtin.RawPointer, %11 : $Builtin.Word) : $()
712+
fix_lifetime %0 : $_ContiguousArrayStorage<Element>
713+
dealloc_ref %0 : $_ContiguousArrayStorage<Element>
714+
%15 = tuple ()
715+
return %15 : $()
716+
}
717+

0 commit comments

Comments
 (0)