summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlon Zakai <alonzakai@gmail.com>2016-05-23 19:59:06 -0700
committerAlon Zakai <alonzakai@gmail.com>2016-05-23 19:59:06 -0700
commit3a993f98daefc9a851824f5099b76b4a427f81ed (patch)
tree045fdedd5b5fab72f5ae5de135297b3fe2faa39f
parent57ec2122cf0971d7869e56699b768026268745ea (diff)
downloadbinaryen-3a993f98daefc9a851824f5099b76b4a427f81ed.tar.gz
binaryen-3a993f98daefc9a851824f5099b76b4a427f81ed.tar.bz2
binaryen-3a993f98daefc9a851824f5099b76b4a427f81ed.zip
add a pass to drop return values in set_local and store (#539)
-rw-r--r--src/passes/CMakeLists.txt1
-rw-r--r--src/passes/DropReturnValues.cpp79
-rw-r--r--test/passes/drop-return-values.txt31
-rw-r--r--test/passes/drop-return-values.wast9
4 files changed, 120 insertions, 0 deletions
diff --git a/src/passes/CMakeLists.txt b/src/passes/CMakeLists.txt
index 1c2a63da4..2b70fb9d4 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 000000000..b89de3011
--- /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 <wasm.h>
+#include <pass.h>
+#include <ast_utils.h>
+#include <wasm-builder.h>
+
+namespace wasm {
+
+struct DropReturnValues : public WalkerPass<PostWalker<DropReturnValues, Visitor<DropReturnValues>>> {
+ bool isFunctionParallel() { return true; }
+
+ std::vector<Expression*> 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<PostWalker<DropReturnValues, Visitor<DropReturnValues>>>::scan(self, currp);
+
+ self->pushTask(visitPre, currp);
+ }
+};
+
+static RegisterPass<DropReturnValues> 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 000000000..8f372ea24
--- /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 000000000..76463cc8e
--- /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))
+ )
+)
+