Skip to content

Commit 6499dc0

Browse files
committed
[LifetimeCompletion] Add extend_lifetimes.
The new instructions are inserted after every "user" (according to InteriorLiveness' SSAPrunedLiveness instance) outside the linear liveness boundary.
1 parent 2120c81 commit 6499dc0

File tree

4 files changed

+105
-0
lines changed

4 files changed

+105
-0
lines changed

include/swift/SIL/OSSALifetimeCompletion.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,8 @@ class OSSALifetimeCompletion {
123123
enum class LifetimeEnd : uint8_t {
124124
/// The lifetime ends at the boundary.
125125
Boundary,
126+
/// The lifetime "ends" in a loop.
127+
Loop,
126128
};
127129

128130
static void visitAvailabilityBoundary(

lib/SIL/Utils/OSSALifetimeCompletion.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,9 @@ static SILInstruction *endOSSALifetime(SILValue value,
6363
SILBuilder &builder) {
6464
auto loc =
6565
RegularLocation::getAutoGeneratedLocation(builder.getInsertionPointLoc());
66+
if (end == OSSALifetimeCompletion::LifetimeEnd::Loop) {
67+
return builder.createExtendLifetime(loc, value);
68+
}
6669
if (value->getOwnershipKind() == OwnershipKind::Owned) {
6770
if (value->getType().is<SILBoxType>()) {
6871
return builder.createDeallocBox(loc, value);
@@ -389,6 +392,14 @@ void OSSALifetimeCompletion::visitAvailabilityBoundary(
389392
visitor.propagateAvailablity(result);
390393

391394
visitor.visitAvailabilityBoundary(result, visit);
395+
396+
visitUsersOutsideLinearLivenessBoundary(
397+
value, liveness, [&](auto *instruction) {
398+
instruction->visitSubsequentInstructions([&](auto *next) {
399+
visit(next, LifetimeEnd::Loop);
400+
return true;
401+
});
402+
});
392403
}
393404

394405
static bool endLifetimeAtAvailabilityBoundary(

lib/SILOptimizer/Utils/CanonicalizeOSSALifetime.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,9 @@ void CanonicalizeOSSALifetime::extendLivenessToDeinitBarriers() {
276276
OSSALifetimeCompletion::visitAvailabilityBoundary(
277277
getCurrentDef(), OSSALifetimeCompletion::DoNotAllowLeaks,
278278
completeLiveness, [&](auto *unreachable, auto end) {
279+
if (end == OSSALifetimeCompletion::LifetimeEnd::Boundary) {
280+
recordUnreachableLifetimeEnd(unreachable);
281+
}
279282
unreachable->visitPriorInstructions([&](auto *inst) {
280283
liveness->extendToNonUse(inst);
281284
return true;

test/SILOptimizer/ossa_lifetime_completion.sil

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -545,15 +545,104 @@ right:
545545
// CHECK-LABEL: begin running test {{.*}} on loopy: liveness_partial_boundary_outside_users with: %o
546546
// CHECK: end_borrow
547547
// CHECK-LABEL: end running test {{.*}} on loopy: liveness_partial_boundary_outside_users with: %o
548+
// CHECK-LABEL: begin running test {{.*}} on loopy: ossa_lifetime_completion
549+
// CHECK-LABEL: sil [ossa] @loopy : {{.*}} {
550+
// CHECK: [[O:%[^,]+]] = apply undef
551+
// CHECK: [[B:%[^,]+]] = begin_borrow [[O]]
552+
// CHECK: end_borrow [[B]]
553+
// CHECK: extend_lifetime [[O]]
554+
// CHECK: br bb1
555+
// CHECK: bb1:
556+
// CHECK: br bb1
557+
// CHECK-LABEL: } // end sil function 'loopy'
558+
// CHECK-LABEL: end running test {{.*}} on loopy: ossa_lifetime_completion
559+
// CHECK-LABEL: begin running test {{.*}} on loopy: liveness_partial_boundary_outside_users with: %o
560+
// CHECK-NEXT: end running test {{.*}} on loopy: liveness_partial_boundary_outside_users with: %o
548561
sil [ossa] @loopy : $@convention(thin) () -> () {
549562
%o = apply undef() : $@convention(thin) () -> (@owned C)
550563
specify_test "liveness_partial_boundary_outside_users %o"
564+
specify_test "ossa_lifetime_completion %o availability"
565+
specify_test "liveness_partial_boundary_outside_users %o"
566+
%b = begin_borrow %o : $C
567+
end_borrow %b : $C
568+
br loop
569+
570+
loop:
571+
br loop
572+
}
573+
574+
sil [ossa] @loopyComplete : $@convention(thin) () -> () {
575+
%o = apply undef() : $@convention(thin) () -> (@owned C)
576+
specify_test "ossa_lifetime_completion %o availability"
577+
specify_test "liveness_partial_boundary_outside_users %o"
551578
%b = begin_borrow %o : $C
552579
end_borrow %b : $C
580+
extend_lifetime %o : $C
581+
br loop
582+
583+
loop:
584+
br loop
585+
}
586+
587+
// When there are no users in the loop, do not extend the lifetime into it.
588+
// CHECK-LABEL: begin running test {{.*}} on loopy_sometimes: ossa_lifetime_completion with: %c, availability
589+
// CHECK-LABEL: sil [ossa] @loopy_sometimes : {{.*}} {
590+
// CHECK-NOT: extend_lifetime
591+
// CHECK-LABEL: } // end sil function 'loopy_sometimes'
592+
// CHECK-LABEL: end running test {{.*}} on loopy_sometimes: ossa_lifetime_completion with: %c, availability
593+
// CHECK-LABEL: begin running test {{.*}} on loopy_sometimes: liveness_partial_boundary_outside_users with: %c
594+
// CHECK-NEXT: end running test {{.*}} on loopy_sometimes: liveness_partial_boundary_outside_users with: %c
595+
sil [ossa] @loopy_sometimes : $@convention(thin) (@owned C) -> () {
596+
entry(%c : @owned $C):
597+
specify_test "ossa_lifetime_completion %c availability"
598+
specify_test "liveness_partial_boundary_outside_users %c"
599+
cond_br undef, header, exit
600+
601+
header:
553602
br loop
554603

555604
loop:
556605
br loop
606+
607+
exit:
608+
destroy_value %c : $C
609+
%retval = tuple ()
610+
return %retval : $()
611+
}
612+
613+
// CHECK-LABEL: begin running test {{.*}} on loopy_sometimes_2: ossa_lifetime_completion with: %c, availability
614+
// CHECK-LABEL: sil [ossa] @loopy_sometimes_2 : {{.*}} {
615+
// CHECK: bb0([[O:%[^,]+]] :
616+
// CHECK: cond_br undef, [[HEADER:bb[0-9]+]], [[EXIT:bb[0-9]+]]
617+
// CHECK: [[HEADER]]:
618+
// CHECK: br [[LOOP:bb[0-9]+]]
619+
// CHECK: [[LOOP]]:
620+
// CHECK: [[B:%[^,]+]] = begin_borrow [[O]]
621+
// CHECK: end_borrow [[B]]
622+
// CHECK: extend_lifetime [[O]]
623+
// CHECK: br [[LOOP]]
624+
// CHECK: [[EXIT]]:
625+
// CHECK: destroy_value [[O]]
626+
// CHECK-LABEL: } // end sil function 'loopy_sometimes_2'
627+
// CHECK-LABEL: end running test {{.*}} on loopy_sometimes_2: ossa_lifetime_completion with: %c, availability
628+
sil [ossa] @loopy_sometimes_2 : $@convention(thin) (@owned C) -> () {
629+
entry(%c : @owned $C):
630+
specify_test "ossa_lifetime_completion %c availability"
631+
specify_test "liveness_partial_boundary_outside_users %c"
632+
cond_br undef, header, exit
633+
634+
header:
635+
br loop
636+
637+
loop:
638+
%b = begin_borrow %c : $C
639+
end_borrow %b : $C
640+
br loop
641+
642+
exit:
643+
destroy_value %c : $C
644+
%retval = tuple ()
645+
return %retval : $()
557646
}
558647

559648
// CHECK-LABEL: begin running test {{.*}} on type_dependent_operand: liveness_partial_boundary_outside_users

0 commit comments

Comments
 (0)