Skip to content

Commit 0efb5ec

Browse files
committed
[MoveValueChecker] Complete lifetimes first.
Before move-checking values, complete the lifetimes of all the values derived from them via copy, borrow, and move. Collect all such values and their derived transitive values and then complete the lifetimes of each, visiting the instructions which produce them in post-order. Once OSSALifetimeCommpletion runs as part of SILGenCleanup, this code can be deleted.
1 parent 99a36b3 commit 0efb5ec

File tree

2 files changed

+74
-0
lines changed

2 files changed

+74
-0
lines changed

lib/SILOptimizer/Mandatory/MoveOnlyChecker.cpp

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include "swift/SIL/FieldSensitivePrunedLiveness.h"
3131
#include "swift/SIL/InstructionUtils.h"
3232
#include "swift/SIL/MemAccessUtils.h"
33+
#include "swift/SIL/OSSALifetimeCompletion.h"
3334
#include "swift/SIL/OwnershipUtils.h"
3435
#include "swift/SIL/PrunedLiveness.h"
3536
#include "swift/SIL/SILArgument.h"
@@ -86,6 +87,7 @@ struct MoveOnlyChecker {
8687
}
8788

8889
void checkObjects();
90+
void completeObjectLifetimes(ArrayRef<MarkUnresolvedNonCopyableValueInst *>);
8991
void checkAddresses();
9092
};
9193

@@ -110,10 +112,66 @@ void MoveOnlyChecker::checkObjects() {
110112
return;
111113
}
112114

115+
completeObjectLifetimes(moveIntroducersToProcess.getArrayRef());
116+
113117
MoveOnlyObjectChecker checker{diagnosticEmitter, domTree, poa, allocator};
114118
madeChange |= checker.check(moveIntroducersToProcess);
115119
}
116120

121+
void MoveOnlyChecker::completeObjectLifetimes(
122+
ArrayRef<MarkUnresolvedNonCopyableValueInst *> insts) {
123+
// TODO: Delete once OSSALifetimeCompletion is run as part of SILGenCleanup.
124+
OSSALifetimeCompletion completion(fn, domTree);
125+
126+
// Collect all values derived from each mark_unresolved_non_copyable_value
127+
// instruction via ownership instructions and phis.
128+
ValueWorklist transitiveValues(fn);
129+
for (auto *inst : insts) {
130+
transitiveValues.push(inst);
131+
}
132+
while (auto value = transitiveValues.pop()) {
133+
for (auto *use : value->getUses()) {
134+
auto *user = use->getUser();
135+
switch (user->getKind()) {
136+
case SILInstructionKind::BeginBorrowInst:
137+
case SILInstructionKind::CopyValueInst:
138+
case SILInstructionKind::MoveValueInst:
139+
transitiveValues.pushIfNotVisited(cast<SingleValueInstruction>(user));
140+
break;
141+
case SILInstructionKind::BranchInst: {
142+
PhiOperand po(use);
143+
transitiveValues.pushIfNotVisited(po.getValue());
144+
break;
145+
}
146+
default:
147+
break;
148+
}
149+
}
150+
}
151+
// Complete the lifetime of each collected value. This is a subset of the
152+
// work that SILGenCleanup wil do.
153+
for (auto *block : poa->get(fn)->getPostOrder()) {
154+
for (SILInstruction &inst : reverse(*block)) {
155+
for (auto result : inst.getResults()) {
156+
if (!transitiveValues.isVisited(result))
157+
continue;
158+
if (completion.completeOSSALifetime(result) ==
159+
LifetimeCompletion::WasCompleted) {
160+
madeChange = true;
161+
}
162+
}
163+
}
164+
for (SILArgument *arg : block->getArguments()) {
165+
if (!transitiveValues.isVisited(arg))
166+
continue;
167+
if (completion.completeOSSALifetime(arg) ==
168+
LifetimeCompletion::WasCompleted) {
169+
madeChange = true;
170+
}
171+
}
172+
}
173+
}
174+
117175
void MoveOnlyChecker::checkAddresses() {
118176
unsigned diagCount = diagnosticEmitter.getDiagnosticCount();
119177
SmallSetVector<MarkUnresolvedNonCopyableValueInst *, 32>
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-build-swift %s -o %t/bin
3+
// RUN: %target-run %t/bin 2> %t/out.txt || true
4+
// RUN: %FileCheck %s < %t/out.txt
5+
6+
struct Example: ~Copyable {
7+
private var failureString: String { "Goodbye." }
8+
deinit { fatalError("FATAL ERROR: \(failureString)") }
9+
}
10+
11+
func doit() {
12+
let e = Example()
13+
// CHECK: FATAL ERROR: Goodbye.
14+
}
15+
16+
doit()

0 commit comments

Comments
 (0)