Skip to content

Commit 88ef839

Browse files
authored
Simpify PassRunner.add() and automatically parallelize parallel functions (#2242)
Main change here is in pass.h, everything else is changes to work with the new API. The add("name") remains as before, while the weird variadic add(..) which constructed the pass now just gets a std::unique_ptr of a pass. This also makes the memory management internally fully automatic. And it makes it trivial to parallelize WalkerPass::run on parallel passes. As a benefit, this allows removing a lot of code since in many cases there is no need to create a new pass runner, and running a pass can be just a single line.
1 parent 7bc5f18 commit 88ef839

21 files changed

Lines changed: 63 additions & 116 deletions

src/asm2wasm.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1068,10 +1068,10 @@ void Asm2WasmBuilder::processAsm(Ref ast) {
10681068
passRunner.setValidateGlobally(false);
10691069
}
10701070
// run autodrop first, before optimizations
1071-
passRunner.add<AutoDrop>();
1071+
passRunner.add(make_unique<AutoDrop>());
10721072
if (preprocessor.debugInfo) {
10731073
// fix up debug info to better survive optimization
1074-
passRunner.add<AdjustDebugInfo>();
1074+
passRunner.add(make_unique<AdjustDebugInfo>());
10751075
}
10761076
// optimize relooper label variable usage at the wasm level, where it is
10771077
// easy
@@ -1680,7 +1680,7 @@ void Asm2WasmBuilder::processAsm(Ref ast) {
16801680
}
16811681
// finalizeCalls also does autoDrop, which is crucial for the non-optimizing
16821682
// case, so that the output of the first pass is valid
1683-
passRunner.add<FinalizeCalls>(this);
1683+
passRunner.add(make_unique<FinalizeCalls>(this));
16841684
passRunner.add(ABI::getLegalizationPass(legalizeJavaScriptFFI
16851685
? ABI::LegalizationLevel::Full
16861686
: ABI::LegalizationLevel::Minimal));
@@ -1697,11 +1697,11 @@ void Asm2WasmBuilder::processAsm(Ref ast) {
16971697
if (preprocessor.debugInfo) {
16981698
// we would have run this before if optimizing, do it now otherwise. must
16991699
// precede ApplyDebugInfo
1700-
passRunner.add<AdjustDebugInfo>();
1700+
passRunner.add(make_unique<AdjustDebugInfo>());
17011701
}
17021702
}
17031703
if (preprocessor.debugInfo) {
1704-
passRunner.add<ApplyDebugInfo>();
1704+
passRunner.add(make_unique<ApplyDebugInfo>());
17051705
// FIXME maybe just remove the nops that were debuginfo nodes, if not
17061706
// optimizing?
17071707
passRunner.add("vacuum");

src/binaryen-c.cpp

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3390,10 +3390,8 @@ void BinaryenModuleAutoDrop(BinaryenModuleRef module) {
33903390
}
33913391

33923392
Module* wasm = (Module*)module;
3393-
PassRunner passRunner(wasm);
3394-
passRunner.options = globalPassOptions;
3395-
passRunner.add<AutoDrop>();
3396-
passRunner.run();
3393+
PassRunner runner(wasm, globalPassOptions);
3394+
AutoDrop().run(&runner, wasm);
33973395
}
33983396

33993397
static BinaryenBufferSizes writeModule(BinaryenModuleRef module,

src/ir/flat.h

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -114,9 +114,7 @@ inline void verifyFlatness(Module* module) {
114114
};
115115

116116
PassRunner runner(module);
117-
runner.setIsNested(true);
118-
runner.add<VerifyFlatness>();
119-
runner.run();
117+
VerifyFlatness().run(&runner, module);
120118
}
121119

122120
} // namespace Flat

src/ir/module-utils.h

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -319,7 +319,6 @@ template<typename T> struct ParallelFunctionMap {
319319

320320
// Run on the implemented functions.
321321
struct Mapper : public WalkerPass<PostWalker<Mapper>> {
322-
323322
bool isFunctionParallel() override { return true; }
324323

325324
Mapper(Info* info) : info(info) {}
@@ -338,9 +337,7 @@ template<typename T> struct ParallelFunctionMap {
338337
Info info = {&map, work};
339338

340339
PassRunner runner(&wasm);
341-
runner.setIsNested(true);
342-
runner.add<Mapper>(&info);
343-
runner.run();
340+
Mapper(&info).run(&runner, &wasm);
344341
}
345342
};
346343

src/pass.h

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ struct PassRegistry {
3939
typedef std::function<Pass*()> Creator;
4040

4141
void registerPass(const char* name, const char* description, Creator create);
42-
Pass* createPass(std::string name);
42+
std::unique_ptr<Pass> createPass(std::string name);
4343
std::vector<std::string> getRegisteredNames();
4444
std::string getPassDescription(std::string name);
4545

@@ -142,7 +142,7 @@ struct PassOptions {
142142
struct PassRunner {
143143
Module* wasm;
144144
MixedArena* allocator;
145-
std::vector<Pass*> passes;
145+
std::vector<std::unique_ptr<Pass>> passes;
146146
PassOptions options;
147147

148148
PassRunner(Module* wasm) : wasm(wasm), allocator(&wasm->allocator) {}
@@ -163,16 +163,18 @@ struct PassRunner {
163163
options.validateGlobally = validate;
164164
}
165165

166+
// Add a pass using its name.
166167
void add(std::string passName) {
167168
auto pass = PassRegistry::get()->createPass(passName);
168169
if (!pass) {
169170
Fatal() << "Could not find pass: " << passName << "\n";
170171
}
171-
doAdd(pass);
172+
doAdd(std::move(pass));
172173
}
173174

174-
template<class P, class... Args> void add(Args&&... args) {
175-
doAdd(new P(std::forward<Args>(args)...));
175+
// Add a pass given an instance.
176+
template<class P> void add(std::unique_ptr<P> pass) {
177+
doAdd(std::move(pass));
176178
}
177179

178180
// Adds the default set of optimization passes; this is
@@ -205,8 +207,6 @@ struct PassRunner {
205207
// Get the last pass that was already executed of a certain type.
206208
template<class P> P* getLast();
207209

208-
~PassRunner();
209-
210210
// When running a pass runner within another pass runner, this
211211
// flag should be set. This influences how pass debugging works,
212212
// and may influence other things in the future too.
@@ -227,7 +227,7 @@ struct PassRunner {
227227
bool isNested = false;
228228

229229
private:
230-
void doAdd(Pass* pass);
230+
void doAdd(std::unique_ptr<Pass> pass);
231231

232232
void runPass(Pass* pass);
233233
void runPassOnFunction(Pass* pass, Function* func);
@@ -315,6 +315,17 @@ class WalkerPass : public Pass, public WalkerType {
315315

316316
public:
317317
void run(PassRunner* runner, Module* module) override {
318+
// Parallel pass running is implemented in the PassRunner.
319+
if (isFunctionParallel()) {
320+
PassRunner runner(module);
321+
runner.setIsNested(true);
322+
std::unique_ptr<Pass> copy;
323+
copy.reset(create());
324+
runner.add(std::move(copy));
325+
runner.run();
326+
return;
327+
}
328+
// Single-thread running just calls the walkModule traversal.
318329
setPassRunner(runner);
319330
WalkerType::setModule(module);
320331
WalkerType::walkModule(module);

src/passes/Asyncify.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1025,7 +1025,7 @@ struct Asyncify : public Pass {
10251025
runner.add("reorder-locals");
10261026
runner.add("merge-blocks");
10271027
}
1028-
runner.add<AsyncifyFlow>(&analyzer);
1028+
runner.add(make_unique<AsyncifyFlow>(&analyzer));
10291029
runner.setIsNested(true);
10301030
runner.setValidateGlobally(false);
10311031
runner.run();
@@ -1040,7 +1040,7 @@ struct Asyncify : public Pass {
10401040
if (optimize) {
10411041
runner.addDefaultFunctionOptimizationPasses();
10421042
}
1043-
runner.add<AsyncifyLocals>(&analyzer);
1043+
runner.add(make_unique<AsyncifyLocals>(&analyzer));
10441044
if (optimize) {
10451045
runner.addDefaultFunctionOptimizationPasses();
10461046
}

src/passes/DeadArgumentElimination.cpp

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -236,12 +236,7 @@ struct DAE : public Pass {
236236
}
237237
}
238238
// Scan all the functions.
239-
{
240-
PassRunner runner(module);
241-
runner.setIsNested(true);
242-
runner.add<DAEScanner>(&infoMap);
243-
runner.run();
244-
}
239+
DAEScanner(&infoMap).run(runner, module);
245240
// Combine all the info.
246241
std::unordered_map<Name, std::vector<Call*>> allCalls;
247242
for (auto& pair : infoMap) {

src/passes/Directize.cpp

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -109,12 +109,7 @@ struct Directize : public Pass {
109109
return;
110110
}
111111
// The table exists and is constant, so this is possible.
112-
{
113-
PassRunner runner(module);
114-
runner.setIsNested(true);
115-
runner.add<FunctionDirectizer>(&flatTable);
116-
runner.run();
117-
}
112+
FunctionDirectizer(&flatTable).run(runner, module);
118113
}
119114
};
120115

src/passes/DuplicateFunctionElimination.cpp

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -70,10 +70,7 @@ struct DuplicateFunctionElimination : public Pass {
7070
limit--;
7171
// Hash all the functions
7272
auto hashes = FunctionHasher::createMap(module);
73-
PassRunner hasherRunner(module);
74-
hasherRunner.setIsNested(true);
75-
hasherRunner.add<FunctionHasher>(&hashes);
76-
hasherRunner.run();
73+
FunctionHasher(&hashes).run(runner, module);
7774
// Find hash-equal groups
7875
std::map<uint32_t, std::vector<Function*>> hashGroups;
7976
ModuleUtils::iterDefinedFunctions(*module, [&](Function* func) {
@@ -121,10 +118,7 @@ struct DuplicateFunctionElimination : public Pass {
121118
v.end());
122119
module->updateMaps();
123120
// replace direct calls
124-
PassRunner replacerRunner(module);
125-
replacerRunner.setIsNested(true);
126-
replacerRunner.add<FunctionReplacer>(&replacements);
127-
replacerRunner.run();
121+
FunctionReplacer(&replacements).run(runner, module);
128122
// replace in table
129123
for (auto& segment : module->table.segments) {
130124
for (auto& name : segment.data) {

src/passes/FuncCastEmulation.cpp

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -185,10 +185,7 @@ struct FuncCastEmulation : public Pass {
185185
}
186186
}
187187
// update call_indirects
188-
PassRunner subRunner(module, runner->options);
189-
subRunner.setIsNested(true);
190-
subRunner.add<ParallelFuncCastEmulation>(ABIType);
191-
subRunner.run();
188+
ParallelFuncCastEmulation(ABIType).run(runner, module);
192189
}
193190

194191
private:

0 commit comments

Comments
 (0)