Skip to content

Commit be7518b

Browse files
committed
[OSSACompleteLifetime] Handle scoped addresses.
Complete scopes of scoped addresses (introduced by `store_borrow` and `begin_access`) in dead end blocks via `ScopedAddressValue::computeTransitiveLiveness`. rdar://141037060
1 parent 7fb5d31 commit be7518b

File tree

4 files changed

+123
-4
lines changed

4 files changed

+123
-4
lines changed

include/swift/SIL/OSSALifetimeCompletion.h

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -90,12 +90,14 @@ class OSSALifetimeCompletion {
9090
///
9191
/// Returns true if any new instructions were created to complete the
9292
/// lifetime.
93-
///
94-
/// TODO: We also need to complete scoped addresses (e.g. store_borrow)!
9593
LifetimeCompletion completeOSSALifetime(SILValue value, Boundary boundary) {
9694
switch (value->getOwnershipKind()) {
97-
case OwnershipKind::None:
98-
return LifetimeCompletion::NoLifetime;
95+
case OwnershipKind::None: {
96+
auto scopedAddress = ScopedAddressValue(value);
97+
if (!scopedAddress)
98+
return LifetimeCompletion::NoLifetime;
99+
break;
100+
}
99101
case OwnershipKind::Owned:
100102
break;
101103
case OwnershipKind::Any:

lib/SIL/Utils/OSSALifetimeCompletion.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,9 @@ static SILInstruction *endOSSALifetime(SILValue value,
7676
}
7777
return builder.createDestroyValue(loc, value, DontPoisonRefs, isDeadEnd);
7878
}
79+
if (auto scopedAddress = ScopedAddressValue(value)) {
80+
return scopedAddress.createScopeEnd(builder.getInsertionPoint(), loc);
81+
}
7982
return builder.createEndBorrow(loc, lookThroughBorrowedFromUser(value));
8083
}
8184

@@ -441,6 +444,13 @@ static bool endLifetimeAtBoundary(SILValue value,
441444
/// Returns true if any new instructions were created to complete the lifetime.
442445
bool OSSALifetimeCompletion::analyzeAndUpdateLifetime(SILValue value,
443446
Boundary boundary) {
447+
if (auto scopedAddress = ScopedAddressValue(value)) {
448+
SmallVector<SILBasicBlock *, 8> discoveredBlocks;
449+
SSAPrunedLiveness liveness(value->getFunction(), &discoveredBlocks);
450+
scopedAddress.computeTransitiveLiveness(liveness);
451+
return endLifetimeAtBoundary(value, liveness, boundary, deadEndBlocks);
452+
}
453+
444454
// Called for inner borrows, inner adjacent reborrows, inner reborrows, and
445455
// scoped addresses.
446456
auto handleInnerScope = [this, boundary](SILValue innerBorrowedValue) {

test/SILOptimizer/ossa_lifetime_completion.sil

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -792,3 +792,52 @@ bb3:
792792
return %0 : $C
793793
}
794794

795+
// CHECK-LABEL: begin running test {{.*}} on store_borrow: ossa_lifetime_completion
796+
// CHECK-LABEL: sil [ossa] @store_borrow : {{.*}} {
797+
// CHECK: [[TOKEN:%[^,]+]] = store_borrow
798+
// CHECK: cond_br undef, {{bb[0-9]+}}, [[DIE:bb[0-9]+]]
799+
// CHECK: [[DIE]]:
800+
// CHECK-NEXT: end_borrow [[TOKEN]]
801+
// CHECK-NEXT: unreachable
802+
// CHECK-LABEL: } // end sil function 'store_borrow'
803+
// CHECK-LABEL: end running test {{.*}} on store_borrow: ossa_lifetime_completion
804+
sil [ossa] @store_borrow : $@convention(thin) (@guaranteed C) -> () {
805+
entry(%instance : @guaranteed $C):
806+
specify_test "ossa_lifetime_completion %token availability"
807+
%addr = alloc_stack $C
808+
%token = store_borrow %instance to %addr : $*C
809+
cond_br undef, exit, die
810+
811+
exit:
812+
end_borrow %token : $*C
813+
dealloc_stack %addr : $*C
814+
%retval = tuple ()
815+
return %retval : $()
816+
die:
817+
unreachable
818+
}
819+
820+
// CHECK-LABEL: begin running test {{.*}} on begin_access: ossa_lifetime_completion
821+
// CHECK-LABEL: sil [ossa] @begin_access : {{.*}} {
822+
// CHECK: [[TOKEN:%[^,]+]] = begin_access
823+
// CHECK: cond_br undef, {{bb[0-9]+}}, [[DIE:bb[0-9]+]]
824+
// CHECK: [[DIE]]:
825+
// CHECK-NEXT: end_access [[TOKEN]]
826+
// CHECK-NEXT: unreachable
827+
// CHECK-LABEL: } // end sil function 'begin_access'
828+
// CHECK-LABEL: end running test {{.*}} on begin_access: ossa_lifetime_completion
829+
sil [ossa] @begin_access : $@convention(thin) (@guaranteed C) -> () {
830+
entry(%instance : @guaranteed $C):
831+
specify_test "ossa_lifetime_completion %access availability"
832+
%addr = alloc_stack $C
833+
%access = begin_access [static] [read] %addr : $*C
834+
cond_br undef, exit, die
835+
836+
exit:
837+
end_access %access : $*C
838+
dealloc_stack %addr : $*C
839+
%retval = tuple ()
840+
return %retval : $()
841+
die:
842+
unreachable
843+
}

test/SILOptimizer/silgen_cleanup_complete_ossa.sil

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ class Klass {
1111
}
1212
class SubKlass : Klass {}
1313

14+
class C {}
15+
1416
enum FakeOptional<T> {
1517
case none
1618
case some(T)
@@ -83,3 +85,59 @@ bb0(%0 : @owned $any P):
8385
%2 = init_existential_ref %1 : $@opened("34B79428-2E49-11ED-901A-8AC134504E1C", any P) Self : $@opened("34B79428-2E49-11ED-901A-8AC134504E1C", any P) Self, $AnyObject
8486
return %2 : $AnyObject
8587
}
88+
89+
// CHECK-LABEL: sil [ossa] @store_borrow : {{.*}} {
90+
// CHECK: bb0([[INSTANCE:%[^,]+]] :
91+
// CHECK: [[ADDR:%[^,]+]] = alloc_stack $C
92+
// CHECK: [[TOKEN:%[^,]+]] = store_borrow [[INSTANCE]] to [[ADDR]]
93+
// CHECK: [[LOAD:%[^,]+]] = load_borrow [[TOKEN]]
94+
// CHECK: cond_br undef, {{bb[0-9]+}}, [[DIE:bb[0-9]+]]
95+
// CHECK: [[DIE]]:
96+
// CHECK: end_borrow [[LOAD]]
97+
// CHECK: end_borrow [[TOKEN]]
98+
// CHECK: destroy_value [dead_end] [[INSTANCE]]
99+
// CHECK: unreachable
100+
// CHECK-LABEL: } // end sil function 'store_borrow'
101+
sil [ossa] @store_borrow : $@convention(thin) (@owned C) -> () {
102+
entry(%instance : @owned $C):
103+
%addr = alloc_stack $C
104+
%token = store_borrow %instance to %addr : $*C
105+
%load = load_borrow %token : $*C
106+
cond_br undef, exit, die
107+
exit:
108+
end_borrow %load : $C
109+
end_borrow %token : $*C
110+
dealloc_stack %addr : $*C
111+
apply undef(%instance) : $@convention(thin) (@guaranteed C) -> ()
112+
destroy_value %instance : $C
113+
%retval = tuple ()
114+
return %retval : $()
115+
die:
116+
unreachable
117+
}
118+
119+
// CHECK-LABEL: sil [ossa] @begin_access : {{.*}} {
120+
// CHECK: [[ADDR:%[^,]+]] = alloc_stack $C
121+
// CHECK: [[ACCESS:%[^,]+]] = begin_access [modify] [static] [[ADDR]]
122+
// CHECK: cond_br undef, {{bb[0-9]+}}, [[DIE:bb[0-9]+]]
123+
// CHECK: [[DIE]]:
124+
// CHECK: end_access [[ACCESS]]
125+
// CHECK: unreachable
126+
// CHECK-LABEL: } // end sil function 'begin_access'
127+
sil [ossa] @begin_access : $@convention(thin) () -> () {
128+
entry:
129+
%addr2 = alloc_stack $C
130+
%access = begin_access [static] [modify] %addr2 : $*C
131+
apply undef(%access) : $@convention(thin) () -> (@out C)
132+
destroy_addr %access : $*C
133+
cond_br undef, exit, die
134+
135+
exit:
136+
end_access %access : $*C
137+
dealloc_stack %addr2 : $*C
138+
%retval = tuple ()
139+
return %retval : $()
140+
141+
die:
142+
unreachable
143+
}

0 commit comments

Comments
 (0)