Skip to content

Commit 518de7c

Browse files
committed
[LifetimeCompletion] Require boundary spec.
Don't default to one boundary or another based on whether the value being completed is lexical.
1 parent c11a2ce commit 518de7c

File tree

7 files changed

+47
-52
lines changed

7 files changed

+47
-52
lines changed

include/swift/SIL/OSSALifetimeCompletion.h

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -66,15 +66,6 @@ class OSSALifetimeCompletion {
6666

6767
Boundary(Value value) : value(value){};
6868
operator Value() const { return value; }
69-
70-
static std::optional<Boundary> getForcingLiveness(bool force) {
71-
if (!force)
72-
return {};
73-
return {Liveness};
74-
}
75-
76-
bool isLiveness() { return value == Liveness; }
77-
bool isAvailable() { return !isLiveness(); }
7869
};
7970

8071
/// Insert a lifetime-ending instruction on every path to complete the OSSA
@@ -95,9 +86,7 @@ class OSSALifetimeCompletion {
9586
/// lifetime.
9687
///
9788
/// TODO: We also need to complete scoped addresses (e.g. store_borrow)!
98-
LifetimeCompletion
99-
completeOSSALifetime(SILValue value,
100-
std::optional<Boundary> maybeBoundary = std::nullopt) {
89+
LifetimeCompletion completeOSSALifetime(SILValue value, Boundary boundary) {
10190
if (value->getOwnershipKind() == OwnershipKind::None)
10291
return LifetimeCompletion::NoLifetime;
10392

@@ -112,9 +101,6 @@ class OSSALifetimeCompletion {
112101
if (!completedValues.insert(value))
113102
return LifetimeCompletion::AlreadyComplete;
114103

115-
Boundary boundary = maybeBoundary.value_or(
116-
value->isLexical() ? Boundary::Availability : Boundary::Liveness);
117-
118104
return analyzeAndUpdateLifetime(value, boundary)
119105
? LifetimeCompletion::WasCompleted
120106
: LifetimeCompletion::AlreadyComplete;

lib/SIL/Utils/OSSALifetimeCompletion.cpp

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -342,8 +342,8 @@ bool OSSALifetimeCompletion::analyzeAndUpdateLifetime(SILValue value,
342342
Boundary boundary) {
343343
// Called for inner borrows, inner adjacent reborrows, inner reborrows, and
344344
// scoped addresses.
345-
auto handleInnerScope = [this](SILValue innerBorrowedValue) {
346-
completeOSSALifetime(innerBorrowedValue);
345+
auto handleInnerScope = [this, boundary](SILValue innerBorrowedValue) {
346+
completeOSSALifetime(innerBorrowedValue, boundary);
347347
};
348348
InteriorLiveness liveness(value);
349349
liveness.compute(domInfo, handleInnerScope);
@@ -374,13 +374,14 @@ static FunctionTest OSSALifetimeCompletionTest(
374374
"ossa_lifetime_completion",
375375
[](auto &function, auto &arguments, auto &test) {
376376
SILValue value = arguments.takeValue();
377-
std::optional<OSSALifetimeCompletion::Boundary> kind = std::nullopt;
378-
if (arguments.hasUntaken()) {
379-
kind = arguments.takeBool()
380-
? OSSALifetimeCompletion::Boundary::Liveness
381-
: OSSALifetimeCompletion::Boundary::Availability;
382-
}
383-
llvm::outs() << "OSSA lifetime completion: " << value;
377+
OSSALifetimeCompletion::Boundary kind =
378+
llvm::StringSwitch<OSSALifetimeCompletion::Boundary>(
379+
arguments.takeString())
380+
.Case("liveness", OSSALifetimeCompletion::Boundary::Liveness)
381+
.Case("availability",
382+
OSSALifetimeCompletion::Boundary::Availability);
383+
llvm::outs() << "OSSA lifetime completion on " << kind
384+
<< " boundary: " << value;
384385
OSSALifetimeCompletion completion(&function, /*domInfo*/ nullptr);
385386
completion.completeOSSALifetime(value, kind);
386387
function.print(llvm::outs());
@@ -462,8 +463,9 @@ bool UnreachableLifetimeCompletion::completeLifetimes() {
462463

463464
bool changed = false;
464465
for (auto value : incompleteValues) {
465-
if (completion.completeOSSALifetime(value)
466-
== LifetimeCompletion::WasCompleted) {
466+
if (completion.completeOSSALifetime(
467+
value, OSSALifetimeCompletion::Boundary::Availability) ==
468+
LifetimeCompletion::WasCompleted) {
467469
changed = true;
468470
}
469471
}

lib/SILOptimizer/Mandatory/MoveOnlyAddressCheckerUtils.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4017,7 +4017,8 @@ bool MoveOnlyAddressChecker::completeLifetimes() {
40174017
[](auto *user) { return isa<BranchInst>(user); })) {
40184018
continue;
40194019
}
4020-
if (completion.completeOSSALifetime(result) ==
4020+
if (completion.completeOSSALifetime(
4021+
result, OSSALifetimeCompletion::Boundary::Availability) ==
40214022
LifetimeCompletion::WasCompleted) {
40224023
changed = true;
40234024
}
@@ -4027,7 +4028,8 @@ bool MoveOnlyAddressChecker::completeLifetimes() {
40274028
if (arg->isReborrow()) {
40284029
continue;
40294030
}
4030-
if (completion.completeOSSALifetime(arg) ==
4031+
if (completion.completeOSSALifetime(
4032+
arg, OSSALifetimeCompletion::Boundary::Availability) ==
40314033
LifetimeCompletion::WasCompleted) {
40324034
changed = true;
40334035
}

lib/SILOptimizer/Mandatory/MoveOnlyChecker.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,8 @@ void MoveOnlyChecker::completeObjectLifetimes(
163163
for (auto result : inst.getResults()) {
164164
if (!transitiveValues.isVisited(result))
165165
continue;
166-
if (completion.completeOSSALifetime(result) ==
166+
if (completion.completeOSSALifetime(
167+
result, OSSALifetimeCompletion::Boundary::Availability) ==
167168
LifetimeCompletion::WasCompleted) {
168169
madeChange = true;
169170
}
@@ -173,7 +174,8 @@ void MoveOnlyChecker::completeObjectLifetimes(
173174
assert(!arg->isReborrow() && "reborrows not legal at this SIL stage");
174175
if (!transitiveValues.isVisited(arg))
175176
continue;
176-
if (completion.completeOSSALifetime(arg) ==
177+
if (completion.completeOSSALifetime(
178+
arg, OSSALifetimeCompletion::Boundary::Availability) ==
177179
LifetimeCompletion::WasCompleted) {
178180
madeChange = true;
179181
}

lib/SILOptimizer/Mandatory/PredictableMemOpt.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2673,8 +2673,9 @@ bool AllocOptimize::tryToRemoveDeadAllocation() {
26732673
// Lexical enums can have incomplete lifetimes in non payload paths that
26742674
// don't end in unreachable. Force their lifetime to end immediately after
26752675
// the last use instead.
2676-
auto boundary = OSSALifetimeCompletion::Boundary::getForcingLiveness(
2677-
v->getType().isOrHasEnum());
2676+
auto boundary = v->getType().isOrHasEnum()
2677+
? OSSALifetimeCompletion::Boundary::Liveness
2678+
: OSSALifetimeCompletion::Boundary::Availability;
26782679
LLVM_DEBUG(llvm::dbgs() << "Completing lifetime of: ");
26792680
LLVM_DEBUG(v->dump());
26802681
completion.completeOSSALifetime(v, boundary);

lib/SILOptimizer/Mandatory/SILGenCleanup.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,15 +117,17 @@ bool SILGenCleanup::completeOSSALifetimes(SILFunction *function) {
117117
for (auto *block : postOrder->getPostOrder()) {
118118
for (SILInstruction &inst : reverse(*block)) {
119119
for (auto result : inst.getResults()) {
120-
if (completion.completeOSSALifetime(result) ==
120+
if (completion.completeOSSALifetime(
121+
result, OSSALifetimeCompletion::Boundary::Availability) ==
121122
LifetimeCompletion::WasCompleted) {
122123
changed = true;
123124
}
124125
}
125126
}
126127
for (SILArgument *arg : block->getArguments()) {
127128
assert(!arg->isReborrow() && "reborrows not legal at this SIL stage");
128-
if (completion.completeOSSALifetime(arg) ==
129+
if (completion.completeOSSALifetime(
130+
arg, OSSALifetimeCompletion::Boundary::Availability) ==
129131
LifetimeCompletion::WasCompleted) {
130132
changed = true;
131133
}

test/SILOptimizer/ossa_lifetime_completion.sil

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -28,14 +28,14 @@ case some(Wrapped)
2828
}
2929

3030
// CHECK-LABEL: begin running test 1 of 1 on eagerConsumneOwnedArg: ossa_lifetime_completion with: @argument
31-
// CHECK-LABEL: OSSA lifetime completion: %0 = argument of bb0 : $C
31+
// CHECK-LABEL: OSSA lifetime completion on liveness boundary: %0 = argument of bb0 : $C
3232
// CHECK: sil [ossa] @eagerConsumneOwnedArg : $@convention(thin) (@owned C) -> () {
3333
// CHECK: bb0(%0 : @_eagerMove @owned $C):
3434
// CHECK-NEXT: destroy_value %0 : $C
3535
// CHECK-LABEL: end running test 1 of 1 on eagerConsumneOwnedArg: ossa_lifetime_completion with: @argument
3636
sil [ossa] @eagerConsumneOwnedArg : $@convention(thin) (@owned C) -> () {
3737
entry(%0 : @_eagerMove @owned $C):
38-
specify_test "ossa_lifetime_completion @argument"
38+
specify_test "ossa_lifetime_completion @argument liveness"
3939
br exit
4040

4141
exit:
@@ -44,7 +44,7 @@ exit:
4444
}
4545

4646
// CHECK-LABEL: begin running test 1 of 1 on lexicalOwnedArg: ossa_lifetime_completion with: @argument
47-
// CHECK: OSSA lifetime completion: %0 = argument of bb0 : $C // user: %4
47+
// CHECK: OSSA lifetime completion on availability boundary: %0 = argument of bb0 : $C // user: %4
4848
// CHECK: sil [ossa] @lexicalOwnedArg : $@convention(thin) (@owned C) -> () {
4949
// CHECK: bb0(%0 : @owned $C):
5050
// CHECK: cond_br undef, bb1, bb2
@@ -55,7 +55,7 @@ exit:
5555
// CHECK-LABEL: end running test 1 of 1 on lexicalOwnedArg: ossa_lifetime_completion with: @argument
5656
sil [ossa] @lexicalOwnedArg : $@convention(thin) (@owned C) -> () {
5757
bb0(%0 : @owned $C):
58-
specify_test "ossa_lifetime_completion @argument"
58+
specify_test "ossa_lifetime_completion @argument availability"
5959
cond_br undef, bb1, bb2
6060
bb1:
6161
br bb3
@@ -74,7 +74,7 @@ bb3:
7474
// CHECK-LABEL: } // end sil function 'borrowTest'
7575
sil [ossa] @borrowTest : $@convention(method) (@owned C) -> () {
7676
bb0(%0 : @owned $C):
77-
specify_test "ossa_lifetime_completion @instruction[0]"
77+
specify_test "ossa_lifetime_completion @instruction[0] availability"
7878
%borrow = begin_borrow %0 : $C
7979
cond_br undef, bb1, bb2
8080

@@ -99,7 +99,7 @@ bb3:
9999
// CHECK-LABEL: } // end sil function 'enumTest'
100100
sil [ossa] @enumTest : $@convention(method) (@guaranteed FakeOptional<C>) -> () {
101101
bb0(%0 : @guaranteed $FakeOptional<C>):
102-
specify_test "ossa_lifetime_completion @instruction[0]"
102+
specify_test "ossa_lifetime_completion @instruction[0] liveness"
103103
%copy = copy_value %0 : $FakeOptional<C>
104104
%borrow = begin_borrow %copy : $FakeOptional<C>
105105
switch_enum %borrow : $FakeOptional<C>, case #FakeOptional.some!enumelt: bb1, case #FakeOptional.none!enumelt: bb2
@@ -122,7 +122,7 @@ sil @use_guaranteed : $@convention(thin) (@guaranteed C) -> ()
122122

123123
sil [ossa] @argTest : $@convention(method) (@owned C) -> () {
124124
bb0(%0 : @owned $C):
125-
specify_test "ossa_lifetime_completion @argument"
125+
specify_test "ossa_lifetime_completion @argument availability"
126126
debug_value %0 : $C
127127
cond_br undef, bb1, bb2
128128

@@ -146,7 +146,7 @@ bb4:
146146
// Ensure no assert fires while inserting dead end blocks to the worklist
147147
sil [ossa] @testLexicalLifetimeCompletion : $@convention(thin) (@owned C) -> () {
148148
bb0(%0 : @owned $C):
149-
specify_test "ossa_lifetime_completion @argument"
149+
specify_test "ossa_lifetime_completion @argument availability"
150150
debug_value %0 : $C, let, name "newElements", argno 1
151151
cond_br undef, bb1, bb2
152152

@@ -189,7 +189,7 @@ sil @foo : $@convention(thin) (@guaranteed C) -> ()
189189
// Ensure no assert fires while handling lifetime end of partial_apply
190190
sil [ossa] @testPartialApplyStack1 : $@convention(thin) (@guaranteed C) -> () {
191191
bb0(%0 : @guaranteed $C):
192-
specify_test "ossa_lifetime_completion @instruction[0]"
192+
specify_test "ossa_lifetime_completion @instruction[0] availability"
193193
%8 = copy_value %0 : $C
194194
%9 = begin_borrow %8 : $C
195195
%80 = function_ref @foo : $@convention(thin) (@guaranteed C) -> ()
@@ -213,7 +213,7 @@ bb3:
213213
// Ensure no assert fires while handling lifetime end of partial_apply
214214
sil [ossa] @testPartialApplyStack2 : $@convention(thin) (@guaranteed C) -> () {
215215
bb0(%0 : @guaranteed $C):
216-
specify_test "ossa_lifetime_completion @instruction[1]"
216+
specify_test "ossa_lifetime_completion @instruction[1] availability"
217217
%2 = alloc_stack $C
218218
%3 = copy_value %0 : $C
219219
%4 = begin_borrow %3 : $C
@@ -253,7 +253,7 @@ sil [ossa] @availability_boundary_1 : $@convention(thin) () -> () {
253253
entry:
254254
%value = apply undef() : $@convention(thin) () -> @owned C
255255
%lexical = move_value [lexical] %value : $C // required (for lexicality)
256-
specify_test "ossa_lifetime_completion %lexical"
256+
specify_test "ossa_lifetime_completion %lexical availability"
257257
br condition_1
258258

259259
condition_1:
@@ -310,7 +310,7 @@ sil [ossa] @availability_boundary_2_after_loop : $@convention(thin) () -> () {
310310
entry:
311311
%value = apply undef() : $@convention(thin) () -> @owned C
312312
%lexical = move_value [lexical] %value : $C // required (for lexicality)
313-
specify_test "ossa_lifetime_completion %lexical"
313+
specify_test "ossa_lifetime_completion %lexical availability"
314314
br condition_1
315315

316316
condition_1:
@@ -375,7 +375,7 @@ sil [ossa] @availability_boundary_3_after_loop : $@convention(thin) () -> () {
375375
entry:
376376
%value = apply undef() : $@convention(thin) () -> @owned C
377377
%lexical = move_value [lexical] %value : $C // required (for lexicality)
378-
specify_test "ossa_lifetime_completion %lexical"
378+
specify_test "ossa_lifetime_completion %lexical availability"
379379
br condition_1
380380

381381
condition_1:
@@ -425,7 +425,7 @@ sil [ossa] @project_box_deadend : $@convention(thin) (@owned C) -> () {
425425
bb0(%0 : @owned $C):
426426
%2 = alloc_box ${ var C }
427427
%3 = begin_borrow %2 : ${ var C }
428-
specify_test "ossa_lifetime_completion %3"
428+
specify_test "ossa_lifetime_completion %3 availability"
429429
%4 = project_box %3 : ${ var C }, 0
430430
store %0 to [init] %4 : $*C
431431
unreachable
@@ -453,7 +453,7 @@ entry(%ie : @owned $IndirectEnumNontrivialPayload):
453453
switch_enum %ie : $IndirectEnumNontrivialPayload, case #IndirectEnumNontrivialPayload.c!enumelt: one_case
454454

455455
one_case(%box : @owned ${ var C }):
456-
specify_test "ossa_lifetime_completion %box"
456+
specify_test "ossa_lifetime_completion %box availability"
457457
%c_addr = project_box %box : ${ var C }, 0
458458
%c = load_borrow %c_addr : $*C
459459
cond_br undef, left, right
@@ -483,7 +483,7 @@ bb0:
483483
%callee_pa = partial_apply [callee_guaranteed] undef() : $@convention(thin) @async @substituted <τ_0_0> () -> (@out τ_0_0, @error any Error) for <()>
484484
%callee_noescape = convert_escape_to_noescape [not_guaranteed] %callee_pa : $@async @callee_guaranteed @substituted <τ_0_0> () -> (@out τ_0_0, @error any Error) for <()>
485485
to $@noescape @async @callee_guaranteed @substituted <τ_0_0> () -> (@out τ_0_0, @error any Error) for <()>
486-
specify_test "ossa_lifetime_completion %callee_noescape"
486+
specify_test "ossa_lifetime_completion %callee_noescape availability"
487487
%async_let = builtin "startAsyncLetWithLocalBuffer"<()>(
488488
%task_options : $Optional<Builtin.RawPointer>,
489489
%callee_noescape : $@noescape @async @callee_guaranteed @substituted <τ_0_0> () -> (@out τ_0_0, @error any Error) for <()>,
@@ -508,7 +508,7 @@ bb0:
508508
sil [ossa] @alloc_box : $@convention(thin) (@owned C) -> () {
509509
entry(%instance : @owned $C):
510510
%box = alloc_box ${ var C }
511-
specify_test "ossa_lifetime_completion %box"
511+
specify_test "ossa_lifetime_completion %box availability"
512512
%addr = project_box %box : ${ var C }, 0
513513
store %instance to [init] %addr : $*C
514514
unreachable
@@ -526,7 +526,7 @@ entry(%instance : @owned $C):
526526
sil [ossa] @begin_apply : $@convention(thin) () -> () {
527527
entry:
528528
(%_, %token) = begin_apply undef() : $@yield_once @convention(thin) () -> (@yields @in_guaranteed ())
529-
specify_test "ossa_lifetime_completion %token"
529+
specify_test "ossa_lifetime_completion %token availability"
530530
cond_br undef, left, right
531531

532532
left:

0 commit comments

Comments
 (0)