Skip to content

Commit f1bc3b5

Browse files
committed
[OSSACanOwned] Dead-end extend base lifetime.
Regardless of consumes of copies, if the original lexical value is not consumed on a dead-end path, it must remain live to that dead-end. rdar://145226757
1 parent 5ffe092 commit f1bc3b5

File tree

3 files changed

+53
-0
lines changed

3 files changed

+53
-0
lines changed

include/swift/SILOptimizer/Utils/CanonicalizeOSSALifetime.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -499,6 +499,7 @@ class CanonicalizeOSSALifetime final {
499499
PrunedLivenessBoundary &boundary);
500500

501501
void extendLivenessToDeadEnds();
502+
void extendLexicalLivenessToDeadEnds();
502503
void extendLivenessToDeinitBarriers();
503504

504505
void extendUnconsumedLiveness(PrunedLivenessBoundary const &boundary);

lib/SILOptimizer/Utils/CanonicalizeOSSALifetime.cpp

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,37 @@ bool CanonicalizeOSSALifetime::computeCanonicalLiveness() {
274274
return true;
275275
}
276276

277+
/// Extend liveness to the availability boundary of currentDef. Even if a copy
278+
/// is consumed on a path to the dead-end, if the def stays live through to the
279+
/// dead-end, its lifetime must not be shrunk back from it (eventually we'll
280+
/// support shrinking it back to deinit barriers).
281+
///
282+
/// Example:
283+
/// %def is lexical
284+
/// %copy = copy_value %def
285+
/// consume %copy
286+
/// apply %foo() // deinit barrier
287+
/// // Must extend lifetime of %def up to this point per language rules.
288+
/// unreachable
289+
void CanonicalizeOSSALifetime::extendLexicalLivenessToDeadEnds() {
290+
// TODO: OSSALifetimeCompletion: Once lifetimes are always complete, delete
291+
// this method.
292+
SmallVector<SILBasicBlock *, 32> directDiscoverdBlocks;
293+
SSAPrunedLiveness directLiveness(function, &directDiscoverdBlocks);
294+
directLiveness.initializeDef(getCurrentDef());
295+
directLiveness.computeSimple();
296+
OSSALifetimeCompletion::visitAvailabilityBoundary(
297+
getCurrentDef(), directLiveness, [&](auto *unreachable, auto end) {
298+
if (end == OSSALifetimeCompletion::LifetimeEnd::Boundary) {
299+
recordUnreachableLifetimeEnd(unreachable);
300+
}
301+
unreachable->visitPriorInstructions([&](auto *inst) {
302+
liveness->extendToNonUse(inst);
303+
return true;
304+
});
305+
});
306+
}
307+
277308
/// Extend liveness to the copy-extended availability boundary of currentDef.
278309
/// Prevents destroys from being inserted between borrows of (copies of) the
279310
/// def and dead-ends.
@@ -1368,6 +1399,9 @@ bool CanonicalizeOSSALifetime::computeLiveness() {
13681399
clear();
13691400
return false;
13701401
}
1402+
if (respectsDeinitBarriers()) {
1403+
extendLexicalLivenessToDeadEnds();
1404+
}
13711405
extendLivenessToDeadEnds();
13721406
if (respectsDeinitBarriers()) {
13731407
extendLivenessToDeinitBarriers();

test/SILOptimizer/canonicalize_ossa_lifetime_unit.sil

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33
import Swift
44

55
class C {}
6+
7+
enum Never {}
8+
sil @run : $@convention(thin) () -> Never
69
sil @getOwned : $@convention(thin) () -> @owned C
710
sil @barrier : $@convention(thin) () -> ()
811
sil [ossa] @getC : $@convention(thin) () -> @owned C
@@ -945,3 +948,18 @@ entry(%a: @owned $C):
945948
%retval = tuple ()
946949
return %retval
947950
}
951+
952+
// CHECK-LABEL: begin running test {{.*}} on extend_lifetime_to_deadend_despite_copy_consume
953+
// CHECK-LABEL: sil [ossa] @extend_lifetime_to_deadend_despite_copy_consume : {{.*}} {
954+
// CHECK: copy_value
955+
// CHECK-LABEL: } // end sil function 'extend_lifetime_to_deadend_despite_copy_consume'
956+
// CHECK-LABEL: end running test {{.*}} on extend_lifetime_to_deadend_despite_copy_consume
957+
sil [ossa] @extend_lifetime_to_deadend_despite_copy_consume : $@convention(thin) (@owned C) -> () {
958+
entry(%c : @owned $C):
959+
specify_test "canonicalize_ossa_lifetime true false true @argument"
960+
%cc = copy_value %c
961+
%takeC = function_ref @takeC : $@convention(thin) (@owned C) -> ()
962+
apply %takeC(%cc) : $@convention(thin) (@owned C) -> ()
963+
%run = function_ref @run : $@convention(thin) () -> Never
964+
unreachable
965+
}

0 commit comments

Comments
 (0)