Skip to content

Commit c977ef7

Browse files
authored
Refactor optimization opts (#1023)
* refactor optimization opts helper code to a class
1 parent dd621a6 commit c977ef7

File tree

3 files changed

+129
-98
lines changed

3 files changed

+129
-98
lines changed

src/tools/asm2wasm.cpp

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -25,22 +25,21 @@
2525
#include "wasm-printing.h"
2626
#include "wasm-io.h"
2727
#include "wasm-validator.h"
28+
#include "optimization-options.h"
2829

2930
#include "asm2wasm.h"
3031

3132
using namespace cashew;
3233
using namespace wasm;
3334

3435
int main(int argc, const char *argv[]) {
35-
PassOptions passOptions;
3636
bool legalizeJavaScriptFFI = true;
37-
bool runOptimizationPasses = false;
3837
Asm2WasmBuilder::TrapMode trapMode = Asm2WasmBuilder::TrapMode::JS;
3938
bool wasmOnly = false;
4039
std::string symbolMap;
4140
bool emitBinary = true;
4241

43-
Options options("asm2wasm", "Translate asm.js files to .wast files");
42+
OptimizationOptions options("asm2wasm", "Translate asm.js files to .wast files");
4443
options
4544
.add("--output", "-o", "Output file (stdout if not specified)",
4645
Options::Arguments::One,
@@ -72,7 +71,6 @@ int main(int argc, const char *argv[]) {
7271
[](Options *o, const std::string &argument) {
7372
o->extra["table max"] = argument;
7473
})
75-
#include "optimization-options.h"
7674
.add("--no-opts", "-n", "Disable optimization passes (deprecated)", Options::Arguments::Zero,
7775
[](Options *o, const std::string &) {
7876
std::cerr << "--no-opts is deprecated (use -O0, etc.)\n";
@@ -103,7 +101,7 @@ int main(int argc, const char *argv[]) {
103101
})
104102
.add("--debuginfo", "-g", "Emit names section and debug info (for debug info you must emit text, -S, for this to work)",
105103
Options::Arguments::Zero,
106-
[&](Options *o, const std::string &arguments) { passOptions.debugInfo = true; })
104+
[&](Options *o, const std::string &arguments) { options.passOptions.debugInfo = true; })
107105
.add("--symbolmap", "-s", "Emit a symbol map (indexes => names)",
108106
Options::Arguments::One,
109107
[&](Options *o, const std::string &argument) { symbolMap = argument; })
@@ -122,6 +120,12 @@ int main(int argc, const char *argv[]) {
122120
emitBinary = false;
123121
}
124122

123+
if (options.runningDefaultOptimizationPasses()) {
124+
if (options.passes.size() > 1) {
125+
Fatal() << "asm2wasm can only run default optimization passes (-O, -Ox, etc.), and not specific additional passes";
126+
}
127+
}
128+
125129
const auto &tm_it = options.extra.find("total memory");
126130
size_t totalMemory =
127131
tm_it == options.extra.end() ? 16 * 1024 * 1024 : atoi(tm_it->second.c_str());
@@ -133,7 +137,7 @@ int main(int argc, const char *argv[]) {
133137

134138
Asm2WasmPreProcessor pre;
135139
// wasm binaries can contain a names section, but not full debug info
136-
pre.debugInfo = passOptions.debugInfo && !emitBinary;
140+
pre.debugInfo = options.passOptions.debugInfo && !emitBinary;
137141
auto input(
138142
read_file<std::vector<char>>(options.extra["infile"], Flags::Text, options.debug ? Flags::Debug : Flags::Release));
139143
char *start = pre.process(input.data());
@@ -145,7 +149,7 @@ int main(int argc, const char *argv[]) {
145149
if (options.debug) std::cerr << "wasming..." << std::endl;
146150
Module wasm;
147151
wasm.memory.initial = wasm.memory.max = totalMemory / Memory::kPageSize;
148-
Asm2WasmBuilder asm2wasm(wasm, pre, options.debug, trapMode, passOptions, legalizeJavaScriptFFI, runOptimizationPasses, wasmOnly);
152+
Asm2WasmBuilder asm2wasm(wasm, pre, options.debug, trapMode, options.passOptions, legalizeJavaScriptFFI, options.runningDefaultOptimizationPasses(), wasmOnly);
149153
asm2wasm.processAsm(asmjs);
150154

151155
// import mem init file, if provided
@@ -162,7 +166,7 @@ int main(int argc, const char *argv[]) {
162166
init = Builder(wasm).makeConst(Literal(int32_t(atoi(memBase->second.c_str()))));
163167
}
164168
wasm.memory.segments.emplace_back(init, data);
165-
if (runOptimizationPasses) {
169+
if (options.runningDefaultOptimizationPasses()) {
166170
PassRunner runner(&wasm);
167171
runner.add("memory-packing");
168172
runner.run();
@@ -197,7 +201,7 @@ int main(int argc, const char *argv[]) {
197201
if (options.debug) std::cerr << "emitting..." << std::endl;
198202
ModuleWriter writer;
199203
writer.setDebug(options.debug);
200-
writer.setDebugInfo(passOptions.debugInfo);
204+
writer.setDebugInfo(options.passOptions.debugInfo);
201205
writer.setSymbolMap(symbolMap);
202206
writer.setBinary(emitBinary);
203207
writer.write(wasm, options.extra["output"]);

src/tools/optimization-options.h

Lines changed: 112 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -18,67 +18,116 @@
1818
// Shared optimization options for commandline tools
1919
//
2020

21-
.add("", "-O", "execute default optimization passes",
22-
Options::Arguments::Zero,
23-
[&runOptimizationPasses, &passOptions](Options*, const std::string&) {
24-
passOptions.optimizeLevel = 2;
25-
passOptions.shrinkLevel = 1;
26-
runOptimizationPasses = true;
27-
})
28-
.add("", "-O0", "execute no optimization passes",
29-
Options::Arguments::Zero,
30-
[&passOptions](Options*, const std::string&) {
31-
passOptions.optimizeLevel = 0;
32-
passOptions.shrinkLevel = 0;
33-
})
34-
.add("", "-O1", "execute -O1 optimization passes",
35-
Options::Arguments::Zero,
36-
[&runOptimizationPasses, &passOptions](Options*, const std::string&) {
37-
passOptions.optimizeLevel = 1;
38-
passOptions.shrinkLevel = 0;
39-
runOptimizationPasses = true;
40-
})
41-
.add("", "-O2", "execute -O2 optimization passes",
42-
Options::Arguments::Zero,
43-
[&runOptimizationPasses, &passOptions](Options*, const std::string&) {
44-
passOptions.optimizeLevel = 2;
45-
passOptions.shrinkLevel = 0;
46-
runOptimizationPasses = true;
47-
})
48-
.add("", "-O3", "execute -O3 optimization passes",
49-
Options::Arguments::Zero,
50-
[&runOptimizationPasses, &passOptions](Options*, const std::string&) {
51-
passOptions.optimizeLevel = 3;
52-
passOptions.shrinkLevel = 0;
53-
runOptimizationPasses = true;
54-
})
55-
.add("", "-Os", "execute default optimization passes, focusing on code size",
56-
Options::Arguments::Zero,
57-
[&runOptimizationPasses, &passOptions](Options*, const std::string&) {
58-
passOptions.optimizeLevel = 2;
59-
passOptions.shrinkLevel = 1;
60-
runOptimizationPasses = true;
61-
})
62-
.add("", "-Oz", "execute default optimization passes, super-focusing on code size",
63-
Options::Arguments::Zero,
64-
[&runOptimizationPasses, &passOptions](Options*, const std::string&) {
65-
passOptions.optimizeLevel = 2;
66-
passOptions.shrinkLevel = 2;
67-
runOptimizationPasses = true;
68-
})
69-
.add("--optimize-level", "-ol", "How much to focus on optimizing code",
70-
Options::Arguments::One,
71-
[&passOptions](Options* o, const std::string& argument) {
72-
passOptions.optimizeLevel = atoi(argument.c_str());
73-
})
74-
.add("--shrink-level", "-s", "How much to focus on shrinking code size",
75-
Options::Arguments::One,
76-
[&passOptions](Options* o, const std::string& argument) {
77-
passOptions.shrinkLevel = atoi(argument.c_str());
78-
})
79-
.add("--ignore-implicit-traps", "-iit", "Optimize under the helpful assumption that no surprising traps occur (from load, div/mod, etc.)",
80-
Options::Arguments::Zero,
81-
[&passOptions](Options*, const std::string&) {
82-
passOptions.ignoreImplicitTraps = true;
83-
})
21+
namespace wasm {
22+
23+
struct OptimizationOptions : public Options {
24+
static constexpr const char* DEFAULT_OPT_PASSES = "O";
25+
26+
std::vector<std::string> passes;
27+
PassOptions passOptions;
28+
29+
OptimizationOptions(const std::string &command, const std::string &description) : Options(command, description) {
30+
(*this).add("", "-O", "execute default optimization passes",
31+
Options::Arguments::Zero,
32+
[this](Options*, const std::string&) {
33+
passOptions.optimizeLevel = 2;
34+
passOptions.shrinkLevel = 1;
35+
passes.push_back(DEFAULT_OPT_PASSES);
36+
})
37+
.add("", "-O0", "execute no optimization passes",
38+
Options::Arguments::Zero,
39+
[this](Options*, const std::string&) {
40+
passOptions.optimizeLevel = 0;
41+
passOptions.shrinkLevel = 0;
42+
})
43+
.add("", "-O1", "execute -O1 optimization passes",
44+
Options::Arguments::Zero,
45+
[this](Options*, const std::string&) {
46+
passOptions.optimizeLevel = 1;
47+
passOptions.shrinkLevel = 0;
48+
passes.push_back(DEFAULT_OPT_PASSES);
49+
})
50+
.add("", "-O2", "execute -O2 optimization passes",
51+
Options::Arguments::Zero,
52+
[this](Options*, const std::string&) {
53+
passOptions.optimizeLevel = 2;
54+
passOptions.shrinkLevel = 0;
55+
passes.push_back(DEFAULT_OPT_PASSES);
56+
})
57+
.add("", "-O3", "execute -O3 optimization passes",
58+
Options::Arguments::Zero,
59+
[this](Options*, const std::string&) {
60+
passOptions.optimizeLevel = 3;
61+
passOptions.shrinkLevel = 0;
62+
passes.push_back(DEFAULT_OPT_PASSES);
63+
})
64+
.add("", "-Os", "execute default optimization passes, focusing on code size",
65+
Options::Arguments::Zero,
66+
[this](Options*, const std::string&) {
67+
passOptions.optimizeLevel = 2;
68+
passOptions.shrinkLevel = 1;
69+
passes.push_back(DEFAULT_OPT_PASSES);
70+
})
71+
.add("", "-Oz", "execute default optimization passes, super-focusing on code size",
72+
Options::Arguments::Zero,
73+
[this](Options*, const std::string&) {
74+
passOptions.optimizeLevel = 2;
75+
passOptions.shrinkLevel = 2;
76+
passes.push_back(DEFAULT_OPT_PASSES);
77+
})
78+
.add("--optimize-level", "-ol", "How much to focus on optimizing code",
79+
Options::Arguments::One,
80+
[this](Options* o, const std::string& argument) {
81+
passOptions.optimizeLevel = atoi(argument.c_str());
82+
})
83+
.add("--shrink-level", "-s", "How much to focus on shrinking code size",
84+
Options::Arguments::One,
85+
[this](Options* o, const std::string& argument) {
86+
passOptions.shrinkLevel = atoi(argument.c_str());
87+
})
88+
.add("--ignore-implicit-traps", "-iit", "Optimize under the helpful assumption that no surprising traps occur (from load, div/mod, etc.)",
89+
Options::Arguments::Zero,
90+
[this](Options*, const std::string&) {
91+
passOptions.ignoreImplicitTraps = true;
92+
});
93+
// add passes in registry
94+
for (const auto& p : PassRegistry::get()->getRegisteredNames()) {
95+
(*this).add(
96+
std::string("--") + p, "", PassRegistry::get()->getPassDescription(p),
97+
Options::Arguments::Zero,
98+
[this, p](Options*, const std::string&) {
99+
passes.push_back(p);
100+
}
101+
);
102+
}
103+
}
104+
105+
bool runningDefaultOptimizationPasses() {
106+
for (auto& pass : passes) {
107+
if (pass == DEFAULT_OPT_PASSES) {
108+
return true;
109+
}
110+
}
111+
return false;
112+
}
113+
114+
bool runningPasses() {
115+
return passes.size() > 0;
116+
}
117+
118+
PassRunner getPassRunner(Module& wasm) {
119+
PassRunner passRunner(&wasm, passOptions);
120+
if (debug) passRunner.setDebug(true);
121+
for (auto& pass : passes) {
122+
if (pass == DEFAULT_OPT_PASSES) {
123+
passRunner.addDefaultOptimizationPasses();
124+
} else {
125+
passRunner.add(pass);
126+
}
127+
}
128+
return passRunner;
129+
}
130+
};
131+
132+
} // namespace wasm
84133

src/tools/wasm-opt.cpp

Lines changed: 4 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include "wasm-io.h"
3131
#include "wasm-interpreter.h"
3232
#include "shell-interface.h"
33+
#include "optimization-options.h"
3334

3435
using namespace wasm;
3536

@@ -93,21 +94,18 @@ struct ExecutionResults {
9394
int main(int argc, const char* argv[]) {
9495
Name entry;
9596
std::vector<std::string> passes;
96-
bool runOptimizationPasses = false;
97-
PassOptions passOptions;
9897
bool emitBinary = true;
9998
bool debugInfo = false;
10099
bool fuzzExec = false;
101100

102-
Options options("wasm-opt", "Optimize .wast files");
101+
OptimizationOptions options("wasm-opt", "Optimize .wast files");
103102
options
104103
.add("--output", "-o", "Output file (stdout if not specified)",
105104
Options::Arguments::One,
106105
[](Options* o, const std::string& argument) {
107106
o->extra["output"] = argument;
108107
Colors::disable();
109108
})
110-
#include "optimization-options.h"
111109
.add("--emit-text", "-S", "Emit text instead of binary for the output file",
112110
Options::Arguments::Zero,
113111
[&](Options *o, const std::string &argument) { emitBinary = false; })
@@ -121,20 +119,8 @@ int main(int argc, const char* argv[]) {
121119
[](Options* o, const std::string& argument) {
122120
o->extra["infile"] = argument;
123121
});
124-
for (const auto& p : PassRegistry::get()->getRegisteredNames()) {
125-
options.add(
126-
std::string("--") + p, "", PassRegistry::get()->getPassDescription(p),
127-
Options::Arguments::Zero,
128-
[&passes, p](Options*, const std::string&) { passes.push_back(p); });
129-
}
130122
options.parse(argc, argv);
131123

132-
if (runOptimizationPasses) {
133-
passes.resize(passes.size() + 1);
134-
std::move_backward(passes.begin(), passes.begin() + passes.size() - 1, passes.end());
135-
passes[0] = "O";
136-
}
137-
138124
auto input(read_file<std::string>(options.extra["infile"], Flags::Text, options.debug ? Flags::Debug : Flags::Release));
139125

140126
Module wasm;
@@ -163,17 +149,9 @@ int main(int argc, const char* argv[]) {
163149
results.get(wasm);
164150
}
165151

166-
if (passes.size() > 0) {
152+
if (options.runningPasses()) {
167153
if (options.debug) std::cerr << "running passes...\n";
168-
PassRunner passRunner(&wasm, passOptions);
169-
if (options.debug) passRunner.setDebug(true);
170-
for (auto& passName : passes) {
171-
if (passName == "O") {
172-
passRunner.addDefaultOptimizationPasses();
173-
} else {
174-
passRunner.add(passName);
175-
}
176-
}
154+
PassRunner passRunner = options.getPassRunner(wasm);
177155
passRunner.run();
178156
assert(WasmValidator().validate(wasm));
179157
}

0 commit comments

Comments
 (0)