diff options
-rw-r--r-- | src/passes/CMakeLists.txt | 1 | ||||
-rw-r--r-- | src/passes/Untee.cpp | 61 | ||||
-rw-r--r-- | src/passes/pass.cpp | 3 | ||||
-rw-r--r-- | src/passes/passes.h | 4 | ||||
-rw-r--r-- | test/passes/untee.txt | 48 | ||||
-rw-r--r-- | test/passes/untee.wast | 12 |
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))) + ) +) + |