Skip to content

Commit 6d0903a

Browse files
committed
AllocBoxToStack: handle begin_borrow when checking if a partial_apply escapes.
1 parent 079369f commit 6d0903a

File tree

4 files changed

+55
-7
lines changed

4 files changed

+55
-7
lines changed

lib/SILOptimizer/Transforms/AllocBoxToStack.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,8 @@ static bool useCaptured(Operand *UI) {
7070
// These instructions do not cause the address to escape.
7171
if (isa<DebugValueInst>(User)
7272
|| isa<StrongReleaseInst>(User) || isa<StrongRetainInst>(User)
73-
|| isa<DestroyValueInst>(User))
73+
|| isa<DestroyValueInst>(User)
74+
|| isa<EndBorrowInst>(User))
7475
return false;
7576

7677
if (auto *Store = dyn_cast<StoreInst>(User)) {
@@ -254,8 +255,9 @@ static bool partialApplyEscapes(SILValue V, bool examineApply) {
254255
// If we have a copy_value, the copy value does not cause an escape, but its
255256
// uses might do so... so add the copy_value's uses to the worklist and
256257
// continue.
257-
if (auto CVI = dyn_cast<CopyValueInst>(User)) {
258-
llvm::copy(CVI->getUses(), std::back_inserter(Worklist));
258+
if (isa<CopyValueInst>(User) || isa<BeginBorrowInst>(User)) {
259+
llvm::copy(cast<SingleValueInstruction>(User)->getUses(),
260+
std::back_inserter(Worklist));
259261
continue;
260262
}
261263

test/IRGen/alloc_box.swift

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,17 @@
22

33
func f() -> Bool? { return nil }
44

5+
var gb = false
6+
var gc: () -> () = {}
7+
58
({
69
guard var b = f() else { return }
710
let c = { b = true }
8-
_ = (b, c)
11+
gb = b
12+
gc = c
913
})()
1014

11-
// CHECK-LABEL: @"$s9alloc_boxyyXEfU_"
15+
// CHECK-LABEL: @"$s9alloc_boxyyXEfU0_"
1216
// CHECK-NOT: call void @swift_setDeallocating
1317
// CHECK: call void @swift_deallocUninitializedObject
1418
// CHECK-NOT: call void @swift_setDeallocating

test/SILOptimizer/allocbox_to_stack_ownership.sil

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -469,6 +469,38 @@ bb0(%0 : $Int):
469469
unreachable
470470
}
471471

472+
// CHECK-LABEL: sil [ossa] @test_copy_and_borrow_of_closure
473+
// CHECK-NOT: alloc_box
474+
// CHECK: alloc_stack
475+
// CHECK-NOT: alloc_box
476+
// CHECK: } // end sil function 'test_copy_and_borrow_of_closure'
477+
sil [ossa] @test_copy_and_borrow_of_closure : $@convention(thin) (Int) -> () {
478+
bb0(%0 : $Int):
479+
// This is not destroyed, but the unreachable makes the verifier not trip.
480+
%1 = alloc_box $<τ_0_0> { var τ_0_0 } <Int>
481+
%1a = project_box %1 : $<τ_0_0> { var τ_0_0 } <Int>, 0
482+
store %0 to [trivial] %1a : $*Int
483+
%3 = function_ref @closure3 : $@convention(thin) (@owned <τ_0_0> { var τ_0_0 } <Int>) -> ()
484+
%4 = copy_value %1 : $<τ_0_0> { var τ_0_0 } <Int>
485+
%5 = partial_apply %3(%4) : $@convention(thin) (@owned <τ_0_0> { var τ_0_0 } <Int>) -> ()
486+
%6 = begin_borrow %5 : $@callee_owned () -> ()
487+
%7 = copy_value %6 : $@callee_owned () -> ()
488+
apply %7() : $@callee_owned () -> ()
489+
end_borrow %6 : $@callee_owned () -> ()
490+
destroy_value %5 : $@callee_owned () -> ()
491+
destroy_value %1 : $<τ_0_0> { var τ_0_0 } <Int>
492+
%r = tuple ()
493+
return %r : $()
494+
}
495+
496+
sil [ossa] @closure3 : $@convention(thin) (@owned <τ_0_0> { var τ_0_0 } <Int>) -> () {
497+
bb0(%0 : @owned $<τ_0_0> { var τ_0_0 } <Int>):
498+
%1 = project_box %0 : $<τ_0_0> { var τ_0_0 } <Int>, 0
499+
destroy_value %0 : $<τ_0_0> { var τ_0_0 } <Int> // id: %7
500+
%r = tuple ()
501+
return %r : $()
502+
}
503+
472504
sil [ossa] @closureWithBoxArg : $@convention(thin) (@guaranteed { var SomeClass }) -> () {
473505
bb0(%0 : @guaranteed ${ var SomeClass }):
474506
%r = tuple ()

test/SILOptimizer/move_function_kills_copyable_addressonly_vars.swift

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -574,15 +574,25 @@ public func castAccess2<T : P>(_ x : __owned T) {
574574
// Partial Apply Tests //
575575
/////////////////////////
576576

577+
public func nonEscapingpartialApplyTest<T : P>(_ x: __owned T) {
578+
var x2 = x // expected-error {{'x2' used after being moved}}
579+
x2 = x
580+
let _ = _move x2 // expected-note {{move here}}
581+
let f = { // expected-note {{use here}}
582+
print(x2)
583+
}
584+
f()
585+
}
586+
577587
// This makes sure we always fail if we are asked to check in a partial apply.
578-
public func partialApplyTest<T : P>(_ x: __owned T) {
588+
public func partialApplyTest<T : P>(_ x: __owned T) -> () -> () {
579589
var x2 = x
580590
x2 = x
581591
let _ = _move x2 // expected-error {{move applied to value that the compiler does not support checking}}
582592
let f = {
583593
print(x2)
584594
}
585-
f()
595+
return f
586596
}
587597

588598
////////////////////////

0 commit comments

Comments
 (0)