summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/pass.h5
-rw-r--r--src/passes/pass.cpp25
-rw-r--r--src/tools/optimization-options.h8
-rw-r--r--test/lit/help/wasm-opt.test2
-rw-r--r--test/lit/help/wasm2js.test2
-rw-r--r--test/lit/passes/O1_skip.wast70
-rw-r--r--test/lit/passes/skip-missing.wast8
7 files changed, 120 insertions, 0 deletions
diff --git a/src/pass.h b/src/pass.h
index 36d49f7b7..973773c49 100644
--- a/src/pass.h
+++ b/src/pass.h
@@ -226,6 +226,8 @@ struct PassOptions {
// Arbitrary string arguments from the commandline, which we forward to
// passes.
std::unordered_map<std::string, std::string> arguments;
+ // Passes to skip and not run.
+ std::unordered_set<std::string> passesToSkip;
// Effect info computed for functions. One pass can generate this and then
// other passes later can benefit from it. It is up to the sequence of passes
@@ -386,6 +388,9 @@ private:
// Whether this pass runner has run. A pass runner should only be run once.
bool ran = false;
+ // Passes in |options.passesToSkip| that we have seen and skipped.
+ std::unordered_set<std::string> skippedPasses;
+
void runPass(Pass* pass);
void runPassOnFunction(Pass* pass, Function* func);
diff --git a/src/passes/pass.cpp b/src/passes/pass.cpp
index 373322a51..593023c7c 100644
--- a/src/passes/pass.cpp
+++ b/src/passes/pass.cpp
@@ -692,6 +692,9 @@ void PassRunner::run() {
assert(!ran);
ran = true;
+ // As we run passes, we'll notice which we skip.
+ skippedPasses.clear();
+
static const int passDebug = getPassDebug();
// Emit logging information when asked for. At passDebug level 1+ we log
// the main passes, while in 2 we also log nested ones. Note that for
@@ -812,6 +815,16 @@ void PassRunner::run() {
}
flush();
}
+
+ // All the passes the user requested to skip should have been seen, and
+ // skipped. If not, the user may have had a typo in the name of a pass to
+ // skip, and we will warn.
+ for (auto pass : options.passesToSkip) {
+ if (!skippedPasses.count(pass)) {
+ std::cerr << "warning: --" << pass << " was requested to be skipped, "
+ << "but it was not found in the passes that were run.\n";
+ }
+ }
}
void PassRunner::runOnFunction(Function* func) {
@@ -930,6 +943,13 @@ struct AfterEffectModuleChecker {
};
void PassRunner::runPass(Pass* pass) {
+ assert(!pass->isFunctionParallel());
+
+ if (options.passesToSkip.count(pass->name)) {
+ skippedPasses.insert(pass->name);
+ return;
+ }
+
std::unique_ptr<AfterEffectModuleChecker> checker;
if (getPassDebug()) {
checker = std::unique_ptr<AfterEffectModuleChecker>(
@@ -949,6 +969,11 @@ void PassRunner::runPass(Pass* pass) {
void PassRunner::runPassOnFunction(Pass* pass, Function* func) {
assert(pass->isFunctionParallel());
+ if (options.passesToSkip.count(pass->name)) {
+ skippedPasses.insert(pass->name);
+ return;
+ }
+
auto passDebug = getPassDebug();
// Add extra validation logic in pass-debug mode 2. The main logic in
diff --git a/src/tools/optimization-options.h b/src/tools/optimization-options.h
index 698d3305e..c87530536 100644
--- a/src/tools/optimization-options.h
+++ b/src/tools/optimization-options.h
@@ -277,6 +277,14 @@ struct OptimizationOptions : public ToolOptions {
Options::Arguments::Zero,
[this](Options*, const std::string&) {
passOptions.zeroFilledMemory = true;
+ })
+ .add("--skip-pass",
+ "-sp",
+ "Skip a pass (do not run it)",
+ OptimizationOptionsCategory,
+ Options::Arguments::One,
+ [this](Options*, const std::string& pass) {
+ passOptions.passesToSkip.insert(pass);
});
// add passes in registry
diff --git a/test/lit/help/wasm-opt.test b/test/lit/help/wasm-opt.test
index 8e04a756c..186382fd4 100644
--- a/test/lit/help/wasm-opt.test
+++ b/test/lit/help/wasm-opt.test
@@ -567,6 +567,8 @@
;; CHECK-NEXT: --zero-filled-memory,-uim Assume that an imported memory
;; CHECK-NEXT: will be zero-initialized
;; CHECK-NEXT:
+;; CHECK-NEXT: --skip-pass,-sp Skip a pass (do not run it)
+;; CHECK-NEXT:
;; CHECK-NEXT:
;; CHECK-NEXT: Tool options:
;; CHECK-NEXT: -------------
diff --git a/test/lit/help/wasm2js.test b/test/lit/help/wasm2js.test
index e023c2af5..501504027 100644
--- a/test/lit/help/wasm2js.test
+++ b/test/lit/help/wasm2js.test
@@ -526,6 +526,8 @@
;; CHECK-NEXT: --zero-filled-memory,-uim Assume that an imported memory
;; CHECK-NEXT: will be zero-initialized
;; CHECK-NEXT:
+;; CHECK-NEXT: --skip-pass,-sp Skip a pass (do not run it)
+;; CHECK-NEXT:
;; CHECK-NEXT:
;; CHECK-NEXT: Tool options:
;; CHECK-NEXT: -------------
diff --git a/test/lit/passes/O1_skip.wast b/test/lit/passes/O1_skip.wast
new file mode 100644
index 000000000..c57d052b4
--- /dev/null
+++ b/test/lit/passes/O1_skip.wast
@@ -0,0 +1,70 @@
+;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited.
+;; NOTE: This test was ported using port_passes_tests_to_lit.py and could be cleaned up.
+
+;; RUN: foreach %s %t wasm-opt -O2 --coalesce-locals --skip-pass=coalesce-locals -S -o - | filecheck %s
+
+;; We should skip coalese-locals even though it is run in -O2 and also we ask to
+;; run it directly: the skip instruction overrides everything else.
+
+(module
+ ;; CHECK: (type $i32_i32_=>_none (func (param i32 i32)))
+
+ ;; CHECK: (type $i32_=>_none (func (param i32)))
+
+ ;; CHECK: (import "a" "b" (func $log (param i32 i32)))
+ (import "a" "b" (func $log (param i32 i32)))
+
+ (func "foo" (param $p i32)
+ ;; The locals $x and $y can be coalesced into a single local, but as we do not
+ ;; run that pass, they will not be. Other minor optimizations will occur here,
+ ;; such as using a tee.
+ (local $x i32)
+ (local $y i32)
+
+ (local.set $x
+ (i32.add
+ (local.get $p)
+ (i32.const 1)
+ )
+ )
+ (call $log
+ (local.get $x)
+ (local.get $x)
+ )
+
+ (local.set $y
+ (i32.add
+ (local.get $p)
+ (i32.const 1)
+ )
+ )
+ (call $log
+ (local.get $y)
+ (local.get $y)
+ )
+ )
+)
+;; CHECK: (export "foo" (func $0))
+
+;; CHECK: (func $0 (; has Stack IR ;) (param $p i32)
+;; CHECK-NEXT: (local $x i32)
+;; CHECK-NEXT: (local $y i32)
+;; CHECK-NEXT: (call $log
+;; CHECK-NEXT: (local.tee $x
+;; CHECK-NEXT: (i32.add
+;; CHECK-NEXT: (local.get $p)
+;; CHECK-NEXT: (i32.const 1)
+;; CHECK-NEXT: )
+;; CHECK-NEXT: )
+;; CHECK-NEXT: (local.get $x)
+;; CHECK-NEXT: )
+;; CHECK-NEXT: (call $log
+;; CHECK-NEXT: (local.tee $y
+;; CHECK-NEXT: (i32.add
+;; CHECK-NEXT: (local.get $p)
+;; CHECK-NEXT: (i32.const 1)
+;; CHECK-NEXT: )
+;; CHECK-NEXT: )
+;; CHECK-NEXT: (local.get $y)
+;; CHECK-NEXT: )
+;; CHECK-NEXT: )
diff --git a/test/lit/passes/skip-missing.wast b/test/lit/passes/skip-missing.wast
new file mode 100644
index 000000000..02778dab0
--- /dev/null
+++ b/test/lit/passes/skip-missing.wast
@@ -0,0 +1,8 @@
+;; We should warn on a pass called "waka" not having been run and skipped.
+
+;; RUN: wasm-opt %s -O1 --skip-pass=waka 2>&1 | filecheck %s
+
+;; CHECK: warning: --waka was requested to be skipped, but it was not found in the passes that were run.
+
+(module
+)