Skip to content

Commit 5aa94e0

Browse files
authored
Add a mechanism to skip a pass by name (#5448)
For example, -O3 --skip-pass=vacuum will run -O3 normally but it will not run the vacuum pass at all (which normally runs more than once in -O3).
1 parent dd3091c commit 5aa94e0

File tree

7 files changed

+120
-0
lines changed

7 files changed

+120
-0
lines changed

src/pass.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,8 @@ struct PassOptions {
226226
// Arbitrary string arguments from the commandline, which we forward to
227227
// passes.
228228
std::unordered_map<std::string, std::string> arguments;
229+
// Passes to skip and not run.
230+
std::unordered_set<std::string> passesToSkip;
229231

230232
// Effect info computed for functions. One pass can generate this and then
231233
// other passes later can benefit from it. It is up to the sequence of passes
@@ -386,6 +388,9 @@ struct PassRunner {
386388
// Whether this pass runner has run. A pass runner should only be run once.
387389
bool ran = false;
388390

391+
// Passes in |options.passesToSkip| that we have seen and skipped.
392+
std::unordered_set<std::string> skippedPasses;
393+
389394
void runPass(Pass* pass);
390395
void runPassOnFunction(Pass* pass, Function* func);
391396

src/passes/pass.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -692,6 +692,9 @@ void PassRunner::run() {
692692
assert(!ran);
693693
ran = true;
694694

695+
// As we run passes, we'll notice which we skip.
696+
skippedPasses.clear();
697+
695698
static const int passDebug = getPassDebug();
696699
// Emit logging information when asked for. At passDebug level 1+ we log
697700
// the main passes, while in 2 we also log nested ones. Note that for
@@ -812,6 +815,16 @@ void PassRunner::run() {
812815
}
813816
flush();
814817
}
818+
819+
// All the passes the user requested to skip should have been seen, and
820+
// skipped. If not, the user may have had a typo in the name of a pass to
821+
// skip, and we will warn.
822+
for (auto pass : options.passesToSkip) {
823+
if (!skippedPasses.count(pass)) {
824+
std::cerr << "warning: --" << pass << " was requested to be skipped, "
825+
<< "but it was not found in the passes that were run.\n";
826+
}
827+
}
815828
}
816829

817830
void PassRunner::runOnFunction(Function* func) {
@@ -930,6 +943,13 @@ struct AfterEffectModuleChecker {
930943
};
931944

932945
void PassRunner::runPass(Pass* pass) {
946+
assert(!pass->isFunctionParallel());
947+
948+
if (options.passesToSkip.count(pass->name)) {
949+
skippedPasses.insert(pass->name);
950+
return;
951+
}
952+
933953
std::unique_ptr<AfterEffectModuleChecker> checker;
934954
if (getPassDebug()) {
935955
checker = std::unique_ptr<AfterEffectModuleChecker>(
@@ -949,6 +969,11 @@ void PassRunner::runPass(Pass* pass) {
949969
void PassRunner::runPassOnFunction(Pass* pass, Function* func) {
950970
assert(pass->isFunctionParallel());
951971

972+
if (options.passesToSkip.count(pass->name)) {
973+
skippedPasses.insert(pass->name);
974+
return;
975+
}
976+
952977
auto passDebug = getPassDebug();
953978

954979
// Add extra validation logic in pass-debug mode 2. The main logic in

src/tools/optimization-options.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,14 @@ struct OptimizationOptions : public ToolOptions {
277277
Options::Arguments::Zero,
278278
[this](Options*, const std::string&) {
279279
passOptions.zeroFilledMemory = true;
280+
})
281+
.add("--skip-pass",
282+
"-sp",
283+
"Skip a pass (do not run it)",
284+
OptimizationOptionsCategory,
285+
Options::Arguments::One,
286+
[this](Options*, const std::string& pass) {
287+
passOptions.passesToSkip.insert(pass);
280288
});
281289

282290
// add passes in registry

test/lit/help/wasm-opt.test

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -567,6 +567,8 @@
567567
;; CHECK-NEXT: --zero-filled-memory,-uim Assume that an imported memory
568568
;; CHECK-NEXT: will be zero-initialized
569569
;; CHECK-NEXT:
570+
;; CHECK-NEXT: --skip-pass,-sp Skip a pass (do not run it)
571+
;; CHECK-NEXT:
570572
;; CHECK-NEXT:
571573
;; CHECK-NEXT: Tool options:
572574
;; CHECK-NEXT: -------------

test/lit/help/wasm2js.test

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -526,6 +526,8 @@
526526
;; CHECK-NEXT: --zero-filled-memory,-uim Assume that an imported memory
527527
;; CHECK-NEXT: will be zero-initialized
528528
;; CHECK-NEXT:
529+
;; CHECK-NEXT: --skip-pass,-sp Skip a pass (do not run it)
530+
;; CHECK-NEXT:
529531
;; CHECK-NEXT:
530532
;; CHECK-NEXT: Tool options:
531533
;; CHECK-NEXT: -------------

test/lit/passes/O1_skip.wast

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited.
2+
;; NOTE: This test was ported using port_passes_tests_to_lit.py and could be cleaned up.
3+
4+
;; RUN: foreach %s %t wasm-opt -O2 --coalesce-locals --skip-pass=coalesce-locals -S -o - | filecheck %s
5+
6+
;; We should skip coalese-locals even though it is run in -O2 and also we ask to
7+
;; run it directly: the skip instruction overrides everything else.
8+
9+
(module
10+
;; CHECK: (type $i32_i32_=>_none (func (param i32 i32)))
11+
12+
;; CHECK: (type $i32_=>_none (func (param i32)))
13+
14+
;; CHECK: (import "a" "b" (func $log (param i32 i32)))
15+
(import "a" "b" (func $log (param i32 i32)))
16+
17+
(func "foo" (param $p i32)
18+
;; The locals $x and $y can be coalesced into a single local, but as we do not
19+
;; run that pass, they will not be. Other minor optimizations will occur here,
20+
;; such as using a tee.
21+
(local $x i32)
22+
(local $y i32)
23+
24+
(local.set $x
25+
(i32.add
26+
(local.get $p)
27+
(i32.const 1)
28+
)
29+
)
30+
(call $log
31+
(local.get $x)
32+
(local.get $x)
33+
)
34+
35+
(local.set $y
36+
(i32.add
37+
(local.get $p)
38+
(i32.const 1)
39+
)
40+
)
41+
(call $log
42+
(local.get $y)
43+
(local.get $y)
44+
)
45+
)
46+
)
47+
;; CHECK: (export "foo" (func $0))
48+
49+
;; CHECK: (func $0 (; has Stack IR ;) (param $p i32)
50+
;; CHECK-NEXT: (local $x i32)
51+
;; CHECK-NEXT: (local $y i32)
52+
;; CHECK-NEXT: (call $log
53+
;; CHECK-NEXT: (local.tee $x
54+
;; CHECK-NEXT: (i32.add
55+
;; CHECK-NEXT: (local.get $p)
56+
;; CHECK-NEXT: (i32.const 1)
57+
;; CHECK-NEXT: )
58+
;; CHECK-NEXT: )
59+
;; CHECK-NEXT: (local.get $x)
60+
;; CHECK-NEXT: )
61+
;; CHECK-NEXT: (call $log
62+
;; CHECK-NEXT: (local.tee $y
63+
;; CHECK-NEXT: (i32.add
64+
;; CHECK-NEXT: (local.get $p)
65+
;; CHECK-NEXT: (i32.const 1)
66+
;; CHECK-NEXT: )
67+
;; CHECK-NEXT: )
68+
;; CHECK-NEXT: (local.get $y)
69+
;; CHECK-NEXT: )
70+
;; CHECK-NEXT: )

test/lit/passes/skip-missing.wast

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
;; We should warn on a pass called "waka" not having been run and skipped.
2+
3+
;; RUN: wasm-opt %s -O1 --skip-pass=waka 2>&1 | filecheck %s
4+
5+
;; CHECK: warning: --waka was requested to be skipped, but it was not found in the passes that were run.
6+
7+
(module
8+
)

0 commit comments

Comments
 (0)