summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/passes/CMakeLists.txt1
-rw-r--r--src/passes/Untee.cpp61
-rw-r--r--src/passes/pass.cpp3
-rw-r--r--src/passes/passes.h4
-rw-r--r--test/passes/untee.txt48
-rw-r--r--test/passes/untee.wast12
6 files changed, 126 insertions, 3 deletions
diff --git a/src/passes/CMakeLists.txt b/src/passes/CMakeLists.txt
index f1411f190..d05390d45 100644
--- a/src/passes/CMakeLists.txt
+++ b/src/passes/CMakeLists.txt
@@ -34,6 +34,7 @@ SET(passes_SOURCES
ReorderFunctions.cpp
SimplifyLocals.cpp
SSAify.cpp
+ Untee.cpp
Vacuum.cpp
)
ADD_LIBRARY(passes STATIC ${passes_SOURCES})
diff --git a/src/passes/Untee.cpp b/src/passes/Untee.cpp
new file mode 100644
index 000000000..b61875243
--- /dev/null
+++ b/src/passes/Untee.cpp
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2017 WebAssembly Community Group participants
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//
+// Removes tee_locals, replacing them with gets and sets.
+//
+// This makes the code "flatter", with less nested side
+// effects. That can make some passes, like CodePushing,
+// more effective.
+//
+
+#include <wasm.h>
+#include <pass.h>
+#include <wasm-builder.h>
+
+namespace wasm {
+
+struct Untee : public WalkerPass<PostWalker<Untee>> {
+ bool isFunctionParallel() override { return true; }
+
+ Pass* create() override { return new Untee; }
+
+ void visitSetLocal(SetLocal *curr) {
+ if (curr->isTee()) {
+ if (curr->value->type == unreachable) {
+ // we don't reach the tee, just remove it
+ replaceCurrent(curr->value);
+ } else {
+ // a normal tee. replace with set and get
+ Builder builder(*getModule());
+ replaceCurrent(
+ builder.makeSequence(
+ curr,
+ builder.makeGetLocal(curr->index, curr->value->type)
+ )
+ );
+ curr->setTee(false);
+ }
+ }
+ }
+};
+
+Pass *createUnteePass() {
+ return new Untee();
+}
+
+} // namespace wasm
+
diff --git a/src/passes/pass.cpp b/src/passes/pass.cpp
index f494378cb..903675b8c 100644
--- a/src/passes/pass.cpp
+++ b/src/passes/pass.cpp
@@ -85,6 +85,7 @@ void PassRegistry::registerPasses() {
registerPass("optimize-instructions", "optimizes instruction combinations", createOptimizeInstructionsPass);
registerPass("pick-load-signs", "pick load signs based on their uses", createPickLoadSignsPass);
registerPass("post-emscripten", "miscellaneous optimizations for Emscripten-generated code", createPostEmscriptenPass);
+ registerPass("precompute", "computes compile-time evaluatable expressions", createPrecomputePass);
registerPass("print", "print in s-expression format", createPrinterPass);
registerPass("print-minified", "print in minified s-expression format", createMinifiedPrinterPass);
registerPass("print-full", "print in full s-expression format", createFullPrinterPass);
@@ -103,8 +104,8 @@ void PassRegistry::registerPasses() {
registerPass("simplify-locals-nostructure", "miscellaneous locals-related optimizations", createSimplifyLocalsNoStructurePass);
registerPass("simplify-locals-notee-nostructure", "miscellaneous locals-related optimizations", createSimplifyLocalsNoTeeNoStructurePass);
registerPass("ssa", "ssa-ify variables so that they have a single assignment", createSSAifyPass);
+ registerPass("untee", "removes tee_locals, replacing them with sets and gets", createUnteePass);
registerPass("vacuum", "removes obviously unneeded code", createVacuumPass);
- registerPass("precompute", "computes compile-time evaluatable expressions", createPrecomputePass);
// registerPass("lower-i64", "lowers i64 into pairs of i32s", createLowerInt64Pass);
}
diff --git a/src/passes/passes.h b/src/passes/passes.h
index e1ba286ad..43bdd3efe 100644
--- a/src/passes/passes.h
+++ b/src/passes/passes.h
@@ -45,6 +45,7 @@ Pass *createNameManagerPass();
Pass *createOptimizeInstructionsPass();
Pass *createPickLoadSignsPass();
Pass *createPostEmscriptenPass();
+Pass *createPrecomputePass();
Pass *createPrinterPass();
Pass *createPrintCallGraphPass();
Pass *createRelooperJumpThreadingPass();
@@ -61,9 +62,8 @@ Pass *createSimplifyLocalsNoTeePass();
Pass *createSimplifyLocalsNoStructurePass();
Pass *createSimplifyLocalsNoTeeNoStructurePass();
Pass *createSSAifyPass();
+Pass *createUnteePass();
Pass *createVacuumPass();
-Pass *createPrecomputePass();
-//Pass *createLowerInt64Pass();
}
diff --git a/test/passes/untee.txt b/test/passes/untee.txt
new file mode 100644
index 000000000..f174da801
--- /dev/null
+++ b/test/passes/untee.txt
@@ -0,0 +1,48 @@
+(module
+ (type $0 (func))
+ (memory $0 0)
+ (func $tee (type $0)
+ (local $x i32)
+ (local $y f64)
+ (drop
+ (block (result i32)
+ (set_local $x
+ (i32.const 1)
+ )
+ (get_local $x)
+ )
+ )
+ (drop
+ (block (result f64)
+ (set_local $y
+ (f64.const 2)
+ )
+ (get_local $y)
+ )
+ )
+ (set_local $x
+ (block (result i32)
+ (set_local $x
+ (i32.const 3)
+ )
+ (get_local $x)
+ )
+ )
+ (set_local $x
+ (block (result i32)
+ (set_local $x
+ (block (result i32)
+ (set_local $x
+ (i32.const 3)
+ )
+ (get_local $x)
+ )
+ )
+ (get_local $x)
+ )
+ )
+ (drop
+ (unreachable)
+ )
+ )
+)
diff --git a/test/passes/untee.wast b/test/passes/untee.wast
new file mode 100644
index 000000000..5a16a1c71
--- /dev/null
+++ b/test/passes/untee.wast
@@ -0,0 +1,12 @@
+(module
+ (func $tee
+ (local $x i32)
+ (local $y f64)
+ (drop (tee_local $x (i32.const 1)))
+ (drop (tee_local $y (f64.const 2)))
+ (set_local $x (tee_local $x (i32.const 3)))
+ (set_local $x (tee_local $x (tee_local $x (i32.const 3))))
+ (drop (tee_local $x (unreachable)))
+ )
+)
+