Skip to content

Commit 1922a90

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 9996ac4 commit 1922a90

File tree

3 files changed

+51
-1
lines changed

3 files changed

+51
-1
lines changed

include/swift/SILOptimizer/Utils/CanonicalizeOSSALifetime.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,8 @@ class CanonicalizeOSSALifetime final {
237237
/// copies.
238238
const MaximizeLifetime_t maximizeLifetime;
239239

240+
SILFunction *function;
241+
240242
// If present, will be used to ensure that the lifetime is not shortened to
241243
// end inside an access scope which it previously enclosed. (Note that ending
242244
// before such an access scope is fine regardless.)
@@ -354,7 +356,7 @@ class CanonicalizeOSSALifetime final {
354356
DeadEndBlocksAnalysis *deadEndBlocksAnalysis, DominanceInfo *domTree,
355357
BasicCalleeAnalysis *calleeAnalysis, InstructionDeleter &deleter)
356358
: pruneDebugMode(pruneDebugMode), maximizeLifetime(maximizeLifetime),
357-
accessBlockAnalysis(accessBlockAnalysis),
359+
function(function), accessBlockAnalysis(accessBlockAnalysis),
358360
deadEndBlocksAnalysis(deadEndBlocksAnalysis), domTree(domTree),
359361
calleeAnalysis(calleeAnalysis), deleter(deleter) {}
360362

@@ -497,6 +499,7 @@ class CanonicalizeOSSALifetime final {
497499
PrunedLivenessBoundary &boundary);
498500

499501
void extendLivenessToDeadEnds();
502+
void extendLexicalLivenessToDeadEnds();
500503
void extendLivenessToDeinitBarriers();
501504

502505
void extendUnconsumedLiveness(PrunedLivenessBoundary const &boundary);

lib/SILOptimizer/Utils/CanonicalizeOSSALifetime.cpp

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,32 @@ 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+
void CanonicalizeOSSALifetime::extendLexicalLivenessToDeadEnds() {
282+
// TODO: OSSALifetimeCompletion: Once lifetimes are always complete, delete
283+
// this method.
284+
SmallVector<SILBasicBlock *, 32> lexicalDiscoverdBlocks;
285+
SSAPrunedLiveness lexicalLiveness(function, &lexicalDiscoverdBlocks);
286+
lexicalLiveness.initializeDef(getCurrentDef());
287+
lexicalLiveness.computeSimple();
288+
OSSALifetimeCompletion::visitAvailabilityBoundary(
289+
getCurrentDef(), lexicalLiveness, [&](auto *unreachable, auto end) {
290+
if (end == OSSALifetimeCompletion::LifetimeEnd::Boundary) {
291+
recordUnreachableLifetimeEnd(unreachable);
292+
}
293+
unreachable->visitPriorInstructions([&](auto *inst) {
294+
liveness->extendToNonUse(inst);
295+
return true;
296+
});
297+
});
298+
}
299+
300+
/// Extend liveness to the availability boundary of the copy-extended
301+
/// availability boundary of currentDef. Prevents destroys from being inserted
302+
/// between borrows of (copies of) the def and dead-ends.
277303
void CanonicalizeOSSALifetime::extendLivenessToDeadEnds() {
278304
// TODO: OSSALifetimeCompletion: Once lifetimes are always complete, delete
279305
// this method.
@@ -1356,6 +1382,9 @@ bool CanonicalizeOSSALifetime::computeLiveness() {
13561382
clear();
13571383
return false;
13581384
}
1385+
if (respectsDeinitBarriers()) {
1386+
extendLexicalLivenessToDeadEnds();
1387+
}
13591388
extendLivenessToDeadEnds();
13601389
if (respectsDeinitBarriers()) {
13611390
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)