Skip to content

Commit 94db617

Browse files
committedJun 17, 2017
Add TopDownClosureFunctionOrder based on ClosureScopeAnalysis.
Simple utility for transfersing functions such that parent scopes are always visited before noescape closures. Note that recursion is disallowed. Noescape closures are not reentrant.
1 parent 3bec7d8 commit 94db617

File tree

2 files changed

+60
-0
lines changed

2 files changed

+60
-0
lines changed
 

‎include/swift/SILOptimizer/Analysis/ClosureScope.h

+21
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
#ifndef SWIFT_SILOPTIMIZER_ANALYSIS_CLOSURESCOPE_H
4949
#define SWIFT_SILOPTIMIZER_ANALYSIS_CLOSURESCOPE_H
5050

51+
#include "swift/Basic/BlotSetVector.h"
5152
#include "swift/SIL/SILFunction.h"
5253
#include "swift/SILOptimizer/Analysis/Analysis.h"
5354
#include "llvm/ADT/SmallSet.h"
@@ -120,6 +121,8 @@ class ClosureScopeAnalysis : public SILAnalysis {
120121
return S->getKind() == AnalysisKind::ClosureScope;
121122
}
122123

124+
SILModule *getModule() const { return M; }
125+
123126
// Return true if the given function is the parent scope for any closures.
124127
bool isClosureScope(SILFunction *scopeFunc);
125128

@@ -157,6 +160,24 @@ class ClosureScopeAnalysis : public SILAnalysis {
157160
ClosureScopeData *getOrComputeScopeData();
158161
};
159162

163+
// ClosureScopeAnalysis utility for visiting functions top down in closure scope
164+
// order.
165+
class TopDownClosureFunctionOrder {
166+
ClosureScopeAnalysis *CSA;
167+
168+
llvm::SmallSet<SILFunction *, 16> visited;
169+
170+
BlotSetVector<SILFunction *> closureWorklist;
171+
172+
public:
173+
TopDownClosureFunctionOrder(ClosureScopeAnalysis *CSA) : CSA(CSA) {}
174+
175+
// Visit all functions in a module, visiting each closure scope function
176+
// before
177+
// the closure function itself.
178+
void visitFunctions(std::function<void(SILFunction *)> visitor);
179+
};
180+
160181
} // end namespace swift
161182

162183
#endif

‎lib/SILOptimizer/Analysis/ClosureScope.cpp

+39
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
#define DEBUG_TYPE "closure-scope"
1616

17+
#include "swift/SIL/SILModule.h"
1718
#include "swift/SILOptimizer/Analysis/ClosureScope.h"
1819

1920
namespace swift {
@@ -154,4 +155,42 @@ SILAnalysis *createClosureScopeAnalysis(SILModule *M) {
154155
return new ClosureScopeAnalysis(M);
155156
}
156157

158+
void TopDownClosureFunctionOrder::visitFunctions(
159+
std::function<void(SILFunction *)> visitor) {
160+
auto markVisited = [&](SILFunction *F) {
161+
bool visitOnce = visited.insert(F).second;
162+
assert(visitOnce);
163+
(void)visitOnce;
164+
};
165+
auto allScopesVisited = [&](SILFunction *closureF) {
166+
return llvm::all_of(CSA->getClosureScopes(closureF),
167+
[this](SILFunction *F) { return visited.count(F); });
168+
};
169+
for (auto &F : *CSA->getModule()) {
170+
if (!allScopesVisited(&F)) {
171+
closureWorklist.insert(&F);
172+
continue;
173+
}
174+
markVisited(&F);
175+
visitor(&F);
176+
}
177+
unsigned numClosures = closureWorklist.size();
178+
while (numClosures) {
179+
for (auto &closureNode : closureWorklist) {
180+
// skip erased closures.
181+
if (!closureNode)
182+
continue;
183+
184+
auto closureF = closureNode.getValue();
185+
if (!allScopesVisited(closureF))
186+
continue;
187+
188+
markVisited(closureF);
189+
visitor(closureF);
190+
closureWorklist.erase(closureF);
191+
--numClosures;
192+
}
193+
}
194+
}
195+
157196
} // namespace swift

0 commit comments

Comments
 (0)
Please sign in to comment.