Skip to content

Commit 32baaf7

Browse files
committed
Add SILGenCleanup::completeOSSLifetimes
Presently under -enable-ossa-complete-lifetimes. This allows SILGen to skip OSSA cleanups, for example at dead-end blocks. Long term, we may remove OSSA cleanups from SILGen entirely (except for lexical borrow scopes). This changes lets us experiment with that option.
1 parent 7f916ba commit 32baaf7

File tree

1 file changed

+44
-1
lines changed

1 file changed

+44
-1
lines changed

lib/SILOptimizer/Mandatory/SILGenCleanup.cpp

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,11 @@
1818

1919
#include "swift/Basic/Defer.h"
2020
#include "swift/SIL/BasicBlockUtils.h"
21+
#include "swift/SIL/OSSALifetimeCompletion.h"
22+
#include "swift/SIL/PrettyStackTrace.h"
23+
#include "swift/SIL/PrunedLiveness.h"
2124
#include "swift/SIL/SILInstruction.h"
25+
#include "swift/SILOptimizer/Analysis/PostOrderAnalysis.h"
2226
#include "swift/SILOptimizer/PassManager/Transforms.h"
2327
#include "swift/SILOptimizer/Utils/CanonicalizeInstruction.h"
2428
#include "swift/SILOptimizer/Utils/InstOptUtils.h"
@@ -96,14 +100,52 @@ namespace {
96100
// pipeline runs in bottom-up closure order.
97101
struct SILGenCleanup : SILModuleTransform {
98102
void run() override;
103+
104+
bool completeOSSALifetimes(SILFunction *function);
99105
};
100106

107+
bool SILGenCleanup::completeOSSALifetimes(SILFunction *function) {
108+
if (!getModule()->getOptions().OSSACompleteLifetimes)
109+
return false;
110+
111+
bool changed = false;
112+
113+
// Lifetimes must be completed inside out (bottom-up in the CFG).
114+
PostOrderFunctionInfo *postOrder =
115+
getAnalysis<PostOrderAnalysis>()->get(function);
116+
OSSALifetimeCompletion completion(function, /*DomInfo*/nullptr);
117+
for (auto *block : postOrder->getPostOrder()) {
118+
for (SILInstruction &inst : reverse(*block)) {
119+
for (auto result : inst.getResults()) {
120+
if (completion.completeOSSALifetime(result) ==
121+
LifetimeCompletion::WasCompleted) {
122+
changed = true;
123+
}
124+
}
125+
}
126+
for (SILArgument *arg : block->getArguments()) {
127+
if (completion.completeOSSALifetime(arg) ==
128+
LifetimeCompletion::WasCompleted) {
129+
changed = true;
130+
}
131+
}
132+
}
133+
function->verifyOwnership(/*deadEndBlocks=*/nullptr);
134+
return changed;
135+
}
136+
101137
void SILGenCleanup::run() {
102138
auto &module = *getModule();
103139
for (auto &function : module) {
140+
if (!function.isDefinition())
141+
continue;
142+
143+
PrettyStackTraceSILFunction stackTrace("silgen cleanup", &function);
144+
104145
LLVM_DEBUG(llvm::dbgs()
105146
<< "\nRunning SILGenCleanup on " << function.getName() << "\n");
106147

148+
bool changed = completeOSSALifetimes(&function);
107149
DeadEndBlocks deadEndBlocks(&function);
108150
SILGenCanonicalize sgCanonicalize(deadEndBlocks);
109151

@@ -116,7 +158,8 @@ void SILGenCleanup::run() {
116158
ii = sgCanonicalize.deleteDeadOperands(ii, ie);
117159
}
118160
}
119-
if (sgCanonicalize.changed) {
161+
changed |= sgCanonicalize.changed;
162+
if (changed) {
120163
auto invalidKind = SILAnalysis::InvalidationKind::Instructions;
121164
invalidateAnalysis(&function, invalidKind);
122165
}

0 commit comments

Comments
 (0)