From 67ec35424aad434b51486a3b1ac43cec19137f8b Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Mon, 23 May 2016 18:56:04 -0700 Subject: [PATCH] add a pass to drop return values in set_local and store --- src/passes/CMakeLists.txt | 1 + src/passes/DropReturnValues.cpp | 79 +++++++++++++++++++++++++++++ test/passes/drop-return-values.txt | 31 +++++++++++ test/passes/drop-return-values.wast | 9 ++++ 4 files changed, 120 insertions(+) create mode 100644 src/passes/DropReturnValues.cpp create mode 100644 test/passes/drop-return-values.txt create mode 100644 test/passes/drop-return-values.wast diff --git a/src/passes/CMakeLists.txt b/src/passes/CMakeLists.txt index 1c2a63da46e..2b70fb9d404 100644 --- a/src/passes/CMakeLists.txt +++ b/src/passes/CMakeLists.txt @@ -2,6 +2,7 @@ SET(passes_SOURCES pass.cpp CoalesceLocals.cpp DeadCodeElimination.cpp + DropReturnValues.cpp LowerIfElse.cpp MergeBlocks.cpp Metrics.cpp diff --git a/src/passes/DropReturnValues.cpp b/src/passes/DropReturnValues.cpp new file mode 100644 index 00000000000..b89de30110e --- /dev/null +++ b/src/passes/DropReturnValues.cpp @@ -0,0 +1,79 @@ +/* + * Copyright 2016 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. + */ + +// +// Stops using return values from set_local and store nodes. +// + +#include +#include +#include +#include + +namespace wasm { + +struct DropReturnValues : public WalkerPass>> { + bool isFunctionParallel() { return true; } + + std::vector expressionStack; + + void visitSetLocal(SetLocal* curr) { + if (ExpressionAnalyzer::isResultUsed(expressionStack, getFunction())) { + Builder builder(*getModule()); + replaceCurrent(builder.makeSequence( + curr, + builder.makeGetLocal(curr->index, curr->type) + )); + } + } + + void visitStore(Store* curr) { + if (ExpressionAnalyzer::isResultUsed(expressionStack, getFunction())) { + Index index = getFunction()->getNumLocals(); + getFunction()->vars.emplace_back(curr->type); + Builder builder(*getModule()); + replaceCurrent(builder.makeSequence( + builder.makeSequence( + builder.makeSetLocal(index, curr->value), + curr + ), + builder.makeGetLocal(index, curr->type) + )); + curr->value = builder.makeGetLocal(index, curr->type); + } + } + + static void visitPre(DropReturnValues* self, Expression** currp) { + self->expressionStack.push_back(*currp); + } + + static void visitPost(DropReturnValues* self, Expression** currp) { + self->expressionStack.pop_back(); + } + + static void scan(DropReturnValues* self, Expression** currp) { + self->pushTask(visitPost, currp); + + WalkerPass>>::scan(self, currp); + + self->pushTask(visitPre, currp); + } +}; + +static RegisterPass registerPass("drop-return-values", "stops relying on return values from set_local and store"); + +} // namespace wasm + diff --git a/test/passes/drop-return-values.txt b/test/passes/drop-return-values.txt new file mode 100644 index 00000000000..8f372ea2408 --- /dev/null +++ b/test/passes/drop-return-values.txt @@ -0,0 +1,31 @@ +(module + (memory 10) + (func $0 + (local $x i32) + (local $1 i32) + (i32.add + (block + (set_local $x + (i32.const 10) + ) + (get_local $x) + ) + (i32.const 20) + ) + (i32.add + (block + (block + (set_local $1 + (i32.const 40) + ) + (i32.store + (i32.const 30) + (get_local $1) + ) + ) + (get_local $1) + ) + (i32.const 50) + ) + ) +) diff --git a/test/passes/drop-return-values.wast b/test/passes/drop-return-values.wast new file mode 100644 index 00000000000..76463cc8ec2 --- /dev/null +++ b/test/passes/drop-return-values.wast @@ -0,0 +1,9 @@ +(module + (memory 10) + (func + (local $x i32) + (i32.add (set_local $x (i32.const 10)) (i32.const 20)) + (i32.add (i32.store (i32.const 30) (i32.const 40)) (i32.const 50)) + ) +) +