Skip to content

Commit 63e3ca7

Browse files
committed
[CanOSSALifetime] Xfer lexical value to callees.
When canonicalizing a lexical lifetime, don't treat applies which consume a copy of the value as deinit barriers. Doing so forces another copy of the def being canonicalized to remain after the apply. Instead, allow the lifetime to be transferred into the callee. This is the same behavior that already exists for lexical lifetimes represented with the `begin_borrow [lexical]` + `copy_value` instruction sequence.
1 parent 9886ff6 commit 63e3ca7

File tree

2 files changed

+48
-1
lines changed

2 files changed

+48
-1
lines changed

lib/SILOptimizer/Utils/CanonicalizeOSSALifetime.cpp

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,23 @@ void CanonicalizeOSSALifetime::extendLivenessToDeinitBarriers() {
257257
[&](auto *inst) {
258258
if (inst == def)
259259
return true;
260-
return isDeinitBarrier(inst, calleeAnalysis);
260+
if (!isDeinitBarrier(inst, calleeAnalysis))
261+
return false;
262+
// For the most part, instructions that are deinit
263+
// barriers in the abstract are also deinit barriers
264+
// for the purposes of canonicalizing def's lifetime.
265+
//
266+
// There is an important exception: transferring an
267+
// owned lexical lifetime into a callee. If the
268+
// instruction is a full apply which consumes def,
269+
// then it isn't a deinit barrier. Keep looking for
270+
// barriers above it.
271+
auto apply = FullApplySite::isa(inst);
272+
if (!apply)
273+
return true;
274+
return liveness->isInterestingUser(inst) !=
275+
PrunedLiveness::IsInterestingUser::
276+
LifetimeEndingUse;
261277
});
262278
for (auto *barrier : barriers.instructions) {
263279
liveness->updateForUse(barrier, /*lifetimeEnding*/ false);

test/SILOptimizer/copy_propagation.sil

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ sil [ossa] @getOwnedC : $@convention(thin) () -> (@owned C)
2222
sil [ossa] @getOwnedB : $@convention(thin) () -> (@owned B)
2323
sil [ossa] @takeOwnedC : $@convention(thin) (@owned C) -> ()
2424
sil [ossa] @takeOwnedCTwice : $@convention(thin) (@owned C, @owned C) -> ()
25+
sil [ossa] @takeOwnedCAndGuaranteedC : $@convention(thin) (@owned C, @guaranteed C) -> ()
2526
sil [ossa] @takeGuaranteedC : $@convention(thin) (@guaranteed C) -> ()
2627
sil [ossa] @borrowB : $@convention(thin) (@guaranteed B) -> ()
2728
sil [ossa] @takeGuaranteedAnyObject : $@convention(thin) (@guaranteed AnyObject) -> ()
@@ -1016,3 +1017,33 @@ entry(%instance : @owned $C):
10161017
%retval = tuple ()
10171018
return %retval : $()
10181019
}
1020+
1021+
// CHECK-LABEL: sil [ossa] @forward_owned_lexical_value_to_callee : {{.*}} {
1022+
// CHECK-NOT: copy_value
1023+
// CHECK-LABEL: } // end sil function 'forward_owned_lexical_value_to_callee'
1024+
sil [ossa] @forward_owned_lexical_value_to_callee : $@convention(thin) (@owned C) -> () {
1025+
entry(%instance : @owned $C):
1026+
%copy = copy_value %instance : $C
1027+
%consume = function_ref @takeOwnedC : $@convention(thin) (@owned C) -> ()
1028+
apply %consume(%copy) : $@convention(thin) (@owned C) -> ()
1029+
destroy_value %instance : $C
1030+
%retval = tuple ()
1031+
return %retval : $()
1032+
}
1033+
1034+
// CHECK-LABEL: sil [ossa] @cantForwardBecauseBorrowing : {{.*}} {
1035+
// CHECK: {{bb[0-9]+}}([[INSTANCE:%[^,]+]] :
1036+
// CHECK: [[COPY:%[^,]+]] = copy_value [[INSTANCE]]
1037+
// CHECK: [[CONSUME_AND_BORROW:%[^,]+]] = function_ref @takeOwnedCAndGuaranteedC
1038+
// CHECK: apply [[CONSUME_AND_BORROW]]([[COPY]], [[INSTANCE]])
1039+
// CHECK: destroy_value [[INSTANCE]]
1040+
// CHECK-LABEL: } // end sil function 'cantForwardBecauseBorrowing'
1041+
sil [ossa] @cantForwardBecauseBorrowing :$@convention(thin) (@owned C) -> () {
1042+
entry(%instance : @owned $C):
1043+
%copy = copy_value %instance : $C
1044+
%consumeAndBorrow = function_ref @takeOwnedCAndGuaranteedC : $@convention(thin) (@owned C, @guaranteed C) -> ()
1045+
apply %consumeAndBorrow(%copy, %instance) : $@convention(thin) (@owned C, @guaranteed C) -> ()
1046+
destroy_value %instance : $C
1047+
%retval = tuple ()
1048+
return %retval : $()
1049+
}

0 commit comments

Comments
 (0)