Skip to content

Commit 66a9b77

Browse files
committed
[SIL] Fix visitAccessedAddress @ end_borrow
`end_borrow` instructions may end the scopes introduced by `load_borrow` or `store_borrow` instructions, or those introduced by `begin_borrow` whose operand's guaranteed root includes a `load_borrow`. Previously, such scope ending instructions which end the scope associated with a borrowing load or store were not regarded as accessing the loaded-from or stored-to address. One consequence of this is that they were not regarded as accessing pointers and thus not as deinit barriers; that in turn resulted in `destroy_addr`s being hoisted into such borrow scopes. Here this is fixed by regarding such `end_borrow`s to access the loaded-from or stored-to address of the scope-introducing `load_borrow` or `store_borrow` respectively. rdar://157772187
1 parent 573607f commit 66a9b77

File tree

2 files changed

+41
-1
lines changed

2 files changed

+41
-1
lines changed

lib/SIL/Utils/MemAccessUtils.cpp

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2796,6 +2796,23 @@ void swift::visitAccessedAddress(SILInstruction *I,
27962796
visitor(singleOperand);
27972797
return;
27982798
}
2799+
case SILInstructionKind::EndBorrowInst: {
2800+
auto *ebi = cast<EndBorrowInst>(I);
2801+
SmallVector<SILValue, 4> roots;
2802+
findGuaranteedReferenceRoots(ebi->getOperand(),
2803+
/*lookThroughNestedBorrows=*/true, roots);
2804+
for (auto root : roots) {
2805+
if (auto *lbi = dyn_cast<LoadBorrowInst>(root)) {
2806+
visitor(&lbi->getOperandRef());
2807+
return;
2808+
}
2809+
if (auto *sbi = dyn_cast<StoreBorrowInst>(root)) {
2810+
visitor(&sbi->getOperandRef(StoreInst::Dest));
2811+
return;
2812+
}
2813+
}
2814+
break;
2815+
}
27992816
// Non-access cases: these are marked with memory side effects, but, by
28002817
// themselves, do not access formal memory.
28012818
#define UNCHECKED_REF_STORAGE(Name, ...) \
@@ -2828,7 +2845,6 @@ void swift::visitAccessedAddress(SILInstruction *I,
28282845
case SILInstructionKind::DropDeinitInst:
28292846
case SILInstructionKind::EndAccessInst:
28302847
case SILInstructionKind::EndApplyInst:
2831-
case SILInstructionKind::EndBorrowInst:
28322848
case SILInstructionKind::EndUnpairedAccessInst:
28332849
case SILInstructionKind::EndLifetimeInst:
28342850
case SILInstructionKind::ExistentialMetatypeInst:

test/SILOptimizer/hoist_destroy_addr.sil

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,10 @@ struct STXXITXXII {
8484
struct MoS: ~Copyable {}
8585
struct MoE: ~Copyable {}
8686

87+
struct UnsafeMutablePointer<T> {
88+
var _rawValue: Builtin.RawPointer
89+
}
90+
8791
sil @unknown : $@convention(thin) () -> ()
8892
sil @use_S : $@convention(thin) (@in_guaranteed S) -> ()
8993

@@ -1346,3 +1350,23 @@ entry(%c_addr : $*X):
13461350
%retval = tuple ()
13471351
return %retval
13481352
}
1353+
1354+
// CHECK-LABEL: sil [ossa] @no_hoist_into_load_borrow_scope : {{.*}} {
1355+
// CHECK: end_borrow
1356+
// CHECK-NEXT: destroy_addr
1357+
// CHECK-LABEL: } // end sil function 'no_hoist_into_load_borrow_scope'
1358+
sil [ossa] @no_hoist_into_load_borrow_scope : $@convention(thin) (@in X) -> () {
1359+
entry(%c_addr_in : $*X):
1360+
%c_ptr = address_to_pointer [stack_protection] %c_addr_in to $Builtin.RawPointer
1361+
%c_up = struct $UnsafeMutablePointer<X> (%c_ptr)
1362+
%c_ptr_2 = struct_extract %c_up, #UnsafeMutablePointer._rawValue // user: %45
1363+
%c_addr = pointer_to_address %c_ptr_2 to [strict] $*X
1364+
%c_borrow = load_borrow %c_addr
1365+
apply undef(%c_borrow) : $@convention(thin) (@guaranteed X) -> ()
1366+
%c_copy = load [copy] %c_addr_in
1367+
end_borrow %c_borrow
1368+
%retval = tuple ()
1369+
destroy_addr %c_addr_in
1370+
destroy_value %c_copy
1371+
return %retval
1372+
}

0 commit comments

Comments
 (0)