Skip to content

Commit 61dbf7e

Browse files
committed
[CanOSSALifetime] Record "unreachable" insts.
OSSALifetimeCompletion needs to insert not at unreachable instructions that appear after the non-lifetime-ending boundary of a value but rather at the terminators of the availability boundary of the value within that region. Once it does so, it will no longer be sufficient to check whether the insertion point is an unreachable because such terminators may be another terminator that appears on the availability boundary. Prepare for that by recording the instructions that were found and checking whether the destroy insertion point is such an instruction before bailing rather than specifically checking for `unreachable`.
1 parent de2e526 commit 61dbf7e

File tree

2 files changed

+22
-3
lines changed

2 files changed

+22
-3
lines changed

include/swift/SILOptimizer/Utils/CanonicalizeOSSALifetime.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,10 @@ class CanonicalOSSAConsumeInfo final {
136136
/// Map blocks on the lifetime boundary to the last consuming instruction.
137137
llvm::SmallDenseMap<SILBasicBlock *, SILInstruction *, 4> finalBlockConsumes;
138138

139+
/// The instructions on the availability boundary of the dead-end region where
140+
/// this value is not consumed.
141+
SmallPtrSet<SILInstruction *, 4> unreachableLifetimeEnds;
142+
139143
public:
140144
void clear() { finalBlockConsumes.clear(); }
141145

@@ -161,6 +165,14 @@ class CanonicalOSSAConsumeInfo final {
161165
return false;
162166
}
163167

168+
void recordUnreachableLifetimeEnd(SILInstruction *inst) {
169+
unreachableLifetimeEnds.insert(inst);
170+
}
171+
172+
bool isUnreachableLifetimeEnd(SILInstruction *inst) {
173+
return unreachableLifetimeEnds.contains(inst);
174+
}
175+
164176
CanonicalOSSAConsumeInfo() {}
165177
CanonicalOSSAConsumeInfo(CanonicalOSSAConsumeInfo const &) = delete;
166178
CanonicalOSSAConsumeInfo &
@@ -409,6 +421,10 @@ class CanonicalizeOSSALifetime final {
409421
void recordConsumingUser(SILInstruction *user) {
410422
consumingBlocks.insert(user->getParent());
411423
}
424+
void recordUnreachableLifetimeEnd(SILInstruction *user) {
425+
recordConsumingUser(user);
426+
consumes.recordUnreachableLifetimeEnd(user);
427+
}
412428
bool computeCanonicalLiveness();
413429

414430
bool endsAccessOverlappingPrunedBoundary(SILInstruction *inst);

lib/SILOptimizer/Utils/CanonicalizeOSSALifetime.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,7 @@ void CanonicalizeOSSALifetime::extendLivenessToDeinitBarriers() {
261261

262262
OSSALifetimeCompletion::visitUnreachableLifetimeEnds(
263263
getCurrentDef(), completeLiveness, [&](auto *unreachable) {
264-
recordConsumingUser(unreachable);
264+
recordUnreachableLifetimeEnd(unreachable);
265265
unreachable->visitPriorInstructions([&](auto *inst) {
266266
liveness->extendToNonUse(inst);
267267
return true;
@@ -905,8 +905,11 @@ static void insertDestroyBeforeInstruction(SILInstruction *nextInstruction,
905905
InstModCallbacks &callbacks) {
906906
// OSSALifetimeCompletion: This conditional clause can be deleted with
907907
// complete lifetimes.
908-
if (isa<UnreachableInst>(nextInstruction)) {
909-
// Don't create a destroy_value if the next instruction is an unreachable.
908+
if (consumes.isUnreachableLifetimeEnd(nextInstruction)) {
909+
// Don't create a destroy_value if the next instruction is an unreachable
910+
// (or a terminator on the availability boundary of the dead-end region
911+
// starting from the non-lifetime-ending boundary of `currentDef`).
912+
//
910913
// If there was a destroy here already, it would be reused. Avoids
911914
// creating an explicit destroy of a value which might have an unclosed
912915
// borrow scope. Doing so would result in

0 commit comments

Comments
 (0)