Skip to content

Commit 0d8866c

Browse files
committed
[SSADestroyHoisting] Don't fold into unrelated scopes.
If a load [copy] appears near the end of the scope protecting access to another address and a destroy_addr of the loaded address appears afterwards, don't fold the destroy into the scope. The reason is that doing so could allow a deinit which previously executed outside the exclusivity scope to subsequently execute within it.
1 parent be1ebe0 commit 0d8866c

File tree

2 files changed

+34
-1
lines changed

2 files changed

+34
-1
lines changed

lib/SILOptimizer/Transforms/SSADestroyHoisting.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -634,9 +634,13 @@ bool HoistDestroys::foldBarrier(SILInstruction *barrier,
634634
const KnownStorageUses &knownUses,
635635
const DeinitBarriers &deinitBarriers) {
636636
if (auto *eai = dyn_cast<EndAccessInst>(barrier)) {
637+
auto *bai = eai->getBeginAccess();
638+
// Don't hoist a destroy into an unrelated access scope.
639+
if (stripAccessMarkers(bai) != stripAccessMarkers(storageRoot))
640+
return false;
637641
SILInstruction *instruction = eai;
638642
while ((instruction = instruction->getPreviousInstruction())) {
639-
if (instruction == eai->getBeginAccess())
643+
if (instruction == bai)
640644
return false;
641645
if (foldBarrier(instruction, storageRoot))
642646
return true;

test/SILOptimizer/hoist_destroy_addr.sil

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -398,3 +398,32 @@ entry(%instance : @owned $X):
398398

399399
return %loaded : $X
400400
}
401+
402+
// Don't fold a destroy_addr with a load [copy] that occurs within the scope of
403+
// an access to unrelated storage.
404+
//
405+
// CHECK-LABEL: sil [ossa] @nofold_into_unrelated_barrier_scope : {{.*}} {
406+
// CHECK: load [copy]
407+
// CHECK-LABEL: } // end sil function 'nofold_into_unrelated_barrier_scope'
408+
sil [ossa] @nofold_into_unrelated_barrier_scope : $@convention(thin) (@owned X) -> (@owned X) {
409+
entry(%instance : @owned $X):
410+
%copy = copy_value %instance : $X
411+
%addr_outer = alloc_stack $X
412+
%addr_inner = alloc_stack $X
413+
store %copy to [init] %addr_outer : $*X
414+
store %instance to [init] %addr_inner : $*X
415+
416+
%access = begin_access [modify] [static] %addr_outer : $*X
417+
apply undef(%access) : $@convention(thin) (@inout X) -> ()
418+
%unknown = function_ref @unknown : $@convention(thin) () -> ()
419+
destroy_addr %access : $*X
420+
apply %unknown() : $@convention(thin) () -> ()
421+
%value = load [copy] %addr_inner : $*X
422+
end_access %access : $*X
423+
destroy_addr %addr_inner : $*X
424+
425+
dealloc_stack %addr_inner : $*X
426+
dealloc_stack %addr_outer : $*X
427+
return %value : $X
428+
}
429+

0 commit comments

Comments
 (0)