Skip to content

[PrunedLiveness] Branch summary merges to ending. #74815

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jun 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion include/swift/SIL/PrunedLiveness.h
Original file line number Diff line number Diff line change
Expand Up @@ -402,7 +402,7 @@ class PrunedLiveness {
bool isEnding() const { return value == Value::Ending; }

LifetimeEnding meet(LifetimeEnding const other) const {
return value < other.value ? *this : other;
return std::min(value, other.value);
}
void meetInPlace(LifetimeEnding const other) { *this = meet(other); }
};
Expand Down
46 changes: 44 additions & 2 deletions lib/SIL/Utils/PrunedLiveness.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,43 @@ static FunctionTest
// PrunedLiveRange
//===----------------------------------------------------------------------===//

static PrunedLiveness::LifetimeEnding
branchMeet(PrunedLiveness::LifetimeEnding const lhs,
PrunedLiveness::LifetimeEnding const rhs) {
enum BranchLifetimeEnding {
Ending,
NonEnding,
NonUse,
};
auto toBranch =
[](PrunedLiveness::LifetimeEnding const ending) -> BranchLifetimeEnding {
switch (ending) {
case PrunedLiveness::LifetimeEnding::Value::NonEnding:
return NonEnding;
case PrunedLiveness::LifetimeEnding::Value::Ending:
return Ending;
case PrunedLiveness::LifetimeEnding::Value::NonUse:
return NonUse;
}
};
auto toRegular =
[](BranchLifetimeEnding const ending) -> PrunedLiveness::LifetimeEnding {
switch (ending) {
case NonEnding:
return PrunedLiveness::LifetimeEnding::Value::NonEnding;
case Ending:
return PrunedLiveness::LifetimeEnding::Value::Ending;
case NonUse:
return PrunedLiveness::LifetimeEnding::Value::NonUse;
}
};
return toRegular(std::min(toBranch(lhs), toBranch(rhs)));
}
static void branchMeetInPlace(PrunedLiveness::LifetimeEnding &that,
PrunedLiveness::LifetimeEnding const other) {
that = branchMeet(that, other);
}

template <typename LivenessWithDefs>
void PrunedLiveRange<LivenessWithDefs>::updateForUse(
SILInstruction *user,
Expand All @@ -211,8 +248,13 @@ void PrunedLiveRange<LivenessWithDefs>::updateForUse(
// This call is not considered the end of %val's lifetime. The @owned
// argument must be copied.
auto iterAndSuccess = users.insert({user, lifetimeEnding});
if (!iterAndSuccess.second)
iterAndSuccess.first->second.meetInPlace(lifetimeEnding);
if (!iterAndSuccess.second) {
if (isa<BranchInst>(user)) {
branchMeetInPlace(iterAndSuccess.first->second, lifetimeEnding);
} else {
iterAndSuccess.first->second.meetInPlace(lifetimeEnding);
}
}
}
template <typename LivenessWithDefs>
void PrunedLiveRange<LivenessWithDefs>::updateForUse(SILInstruction *user,
Expand Down
2 changes: 1 addition & 1 deletion test/SILOptimizer/liveness_unit.sil
Original file line number Diff line number Diff line change
Expand Up @@ -382,7 +382,7 @@ bb1(%reborrow : @guaranteed $C, %phi : @guaranteed $PairC):
// CHECK-LABEL: testSSAReborrowedPhi: ssa_liveness
// CHECK: SSA lifetime analysis: %{{.*}} = begin_borrow
// CHECK-NEXT: bb0: LiveWithin
// CHECK-NEXT: regular user: br bb1
// CHECK-NEXT: lifetime-ending user: br bb1
// CHECK-NEXT: regular user: %{{.*}} = struct
// CHECK-NEXT: last user: br bb1
// CHECK-NEXT: end running
Expand Down
39 changes: 39 additions & 0 deletions test/SILOptimizer/ossa_lifetime_completion.sil
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ public enum FakeOptional<T> {

sil @swift_asyncLet_finish : $@convention(thin) @async (Builtin.RawPointer, Builtin.RawPointer) -> ()
sil @swift_asyncLet_get : $@convention(thin) @async (Builtin.RawPointer, Builtin.RawPointer) -> ()
sil @getC : $@convention(thin) () -> (@owned C)

protocol Error {}

Expand Down Expand Up @@ -724,3 +725,41 @@ bb0(%existential : @owned $any P):
%ref_existential = init_existential_ref %opened : $@opened("00000000-0000-0000-0000-000000000000", any P) Self : $@opened("00000000-0000-0000-0000-000000000000", any P) Self, $AnyObject
return %ref_existential : $AnyObject
}

// CHECK-LABEL: begin running test {{.*}} on root_of_reborrow: ossa_lifetime_completion
// Verify that no instructions were inserted after backedge2's terminator. (In
// fact, if they were, the test would crash.)
// CHECK-LABEL: sil [ossa] @root_of_reborrow : {{.*}} {
// CHECK: bb1([[C0:%[^,]+]] : @owned $C, [[B0:%[^,]+]] : @reborrow @guaranteed $C):
// CHECK-NEXT: [[B0F:%[^,]+]] = borrowed [[B0]] : $C from ([[C0]] : $C)
// CHECK-NEXT: end_borrow [[B0F]]
// CHECK-NEXT: destroy_value [[C0]]
// CHECK-NEXT: br
// CHECK-LABEL: } // end sil function 'root_of_reborrow'
// CHECK-LABEL: end running test {{.*}} on root_of_reborrow: ossa_lifetime_completion
sil [ossa] @root_of_reborrow : $@convention(thin) () -> () {
entry:
%getC = function_ref @getC : $@convention(thin) () -> (@owned C)
%c = apply %getC() : $@convention(thin) () -> (@owned C)
%b = begin_borrow %c : $C
br header(%c : $C, %b : $C)
header(%c0 : @owned $C, %b0 : @reborrow @guaranteed $C):
%b0f = borrowed %b0 : $C from (%c0 : $C)
end_borrow %b0f : $C
destroy_value %c0 : $C
br body
body:
br latch
latch:
cond_br undef, backedge, exit
backedge:
%c1 = apply %getC() : $@convention(thin) () -> (@owned C)
%b1 = begin_borrow %c1 : $C
br backedge2(%c1 : $C, %b1 : $C)
backedge2(%c2 : @owned $C, %b2 : @reborrow @guaranteed $C):
%b2f = borrowed %b2 : $C from (%c2 : $C)
specify_test "ossa_lifetime_completion %c2 availability"
br header(%c2 : $C, %b2f : $C)
exit:
unreachable
}
2 changes: 1 addition & 1 deletion test/SILOptimizer/ownership_liveness_unit.sil
Original file line number Diff line number Diff line change
Expand Up @@ -606,7 +606,7 @@ bb1(%reborrow : @guaranteed $C):
// CHECK: Interior liveness: %{{.*}} = begin_borrow %0 : $C
// CHECK-NEXT: Inner scope: %{{.*}} = begin_borrow %{{.*}} : $D
// CHECK-NEXT: bb0: LiveWithin
// CHECK-NEXT: regular user: br bb1(%{{.*}} : $C, %{{.*}} : $D)
// CHECK-NEXT: lifetime-ending user: br bb1(%{{.*}} : $C, %{{.*}} : $D)
// CHECK-NEXT: regular user: %{{.*}} = unchecked_ref_cast %{{.*}} : $C to $D
// CHECK-NEXT: Complete liveness
// CHECK-NEXT: Unenclosed phis {
Expand Down