summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlon Zakai <alonzakai@gmail.com>2016-05-22 21:23:18 -0700
committerAlon Zakai <alonzakai@gmail.com>2016-05-22 21:23:18 -0700
commitf5aad6d1614ca32e7ade296dc9bce8c7c74d3f63 (patch)
tree140fde94e420070c2461fa1541f0ab9b53af8077
parent5d16d4b3b344aa1dbe07deff0d282adea6f8c369 (diff)
downloadbinaryen-f5aad6d1614ca32e7ade296dc9bce8c7c74d3f63.tar.gz
binaryen-f5aad6d1614ca32e7ade296dc9bce8c7c74d3f63.tar.bz2
binaryen-f5aad6d1614ca32e7ade296dc9bce8c7c74d3f63.zip
dead code elimination pass (#536)
-rw-r--r--src/passes/CMakeLists.txt1
-rw-r--r--src/passes/DeadCodeElimination.cpp351
-rw-r--r--src/passes/pass.cpp1
-rw-r--r--test/emcc_hello_world.fromasm577
-rw-r--r--test/emcc_hello_world.fromasm.imprecise577
-rw-r--r--test/passes/dce.txt239
-rw-r--r--test/passes/dce.wast197
-rw-r--r--test/two_sides.fromasm65
-rw-r--r--test/two_sides.fromasm.imprecise65
9 files changed, 1419 insertions, 654 deletions
diff --git a/src/passes/CMakeLists.txt b/src/passes/CMakeLists.txt
index 2e830d991..1c2a63da4 100644
--- a/src/passes/CMakeLists.txt
+++ b/src/passes/CMakeLists.txt
@@ -1,6 +1,7 @@
SET(passes_SOURCES
pass.cpp
CoalesceLocals.cpp
+ DeadCodeElimination.cpp
LowerIfElse.cpp
MergeBlocks.cpp
Metrics.cpp
diff --git a/src/passes/DeadCodeElimination.cpp b/src/passes/DeadCodeElimination.cpp
new file mode 100644
index 000000000..e6669fdd9
--- /dev/null
+++ b/src/passes/DeadCodeElimination.cpp
@@ -0,0 +1,351 @@
+/*
+ * 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.
+ */
+
+//
+// Removes dead, i.e. unreachable, code.
+//
+// We keep a record of when control flow is reachable. When it isn't, we
+// kill (turn into unreachable). We then fold away entire unreachable
+// expressions.
+//
+// When dead code causes an operation to not happen, like a store, a call
+// or an add, we replace with a block with a list of what does happen.
+// That isn't necessarily smaller, but blocks are friendlier to other
+// optimizations: blocks can be merged and eliminated, and they clearly
+// have no side effects.
+//
+
+#include <wasm.h>
+#include <pass.h>
+#include <ast_utils.h>
+
+namespace wasm {
+
+struct DeadCodeElimination : public WalkerPass<PostWalker<DeadCodeElimination, Visitor<DeadCodeElimination>>> {
+ bool isFunctionParallel() { return true; }
+
+ // whether the current code is actually reachable
+ bool reachable = true;
+
+ std::set<Name> reachableBreaks;
+
+ void addBreak(Name name) {
+ assert(reachable);
+ reachableBreaks.insert(name);
+ }
+
+ bool isDead(Expression* curr) {
+ return curr && curr->is<Unreachable>();
+ }
+
+ // things that stop control flow
+
+ void visitBreak(Break* curr) {
+ if (isDead(curr->value)) {
+ // the condition is evaluated last, so if the value was unreachable, the whole thing is
+ replaceCurrent(curr->value);
+ return;
+ }
+ addBreak(curr->name);
+ if (!curr->condition) {
+ reachable = false;
+ }
+ }
+
+ void visitSwitch(Switch* curr) {
+ if (isDead(curr->value)) {
+ replaceCurrent(curr->value);
+ return;
+ }
+ for (auto target : curr->targets) {
+ addBreak(target);
+ }
+ addBreak(curr->default_);
+ reachable = false;
+ }
+
+ void visitReturn(Return* curr) {
+ if (isDead(curr->value)) {
+ replaceCurrent(curr->value);
+ return;
+ }
+ reachable = false;
+ }
+
+ void visitUnreachable(Unreachable* curr) {
+ reachable = false;
+ }
+
+ // we maintain a stack for blocks, as we visit each item, and the parameter is the index
+
+ std::vector<Index> blockStack; // index in current block
+
+ static void doPreBlock(DeadCodeElimination* self, Expression** currp) {
+ self->blockStack.push_back(0);
+ }
+
+ static void doAfterBlockElement(DeadCodeElimination* self, Expression** currp) {
+ auto* block = (*currp)->cast<Block>();
+ Index i = self->blockStack.back();
+ self->blockStack.back()++;
+ if (!self->reachable) {
+ // control flow ended in the middle of the block
+ // note that we still visit the rest, so if we already truncated, do not lengthen.
+ // note that it is ok that we visit the others even though the list was shortened;
+ // our arena vectors leave things as they are when shrinking.
+ if (block->list.size() > i + 1) {
+ block->list.resize(i + 1);
+ }
+ }
+ }
+
+ void visitBlock(Block* curr) {
+ blockStack.pop_back();
+ if (curr->name.is()) {
+ reachable = reachable || reachableBreaks.count(curr->name);
+ reachableBreaks.erase(curr->name);
+ }
+ if (curr->list.size() == 1 && isDead(curr->list[0])) {
+ replaceCurrent(curr->list[0]);
+ }
+ }
+
+ void visitLoop(Loop* curr) {
+ if (curr->in.is()) {
+ reachableBreaks.erase(curr->in);
+ }
+ if (curr->out.is()) {
+ reachable = reachable || reachableBreaks.count(curr->out);
+ reachableBreaks.erase(curr->out);
+ }
+ if (isDead(curr->body)) {
+ replaceCurrent(curr->body);
+ return;
+ }
+ }
+
+ // ifs need special handling
+
+ std::vector<bool> ifStack; // stack of reachable state, for forking and joining
+
+ static void doAfterIfCondition(DeadCodeElimination* self, Expression** currp) {
+ self->ifStack.push_back(self->reachable);
+ }
+
+ static void doAfterIfElseTrue(DeadCodeElimination* self, Expression** currp) {
+ auto* curr = (*currp)->cast<If>();
+ assert(curr->ifFalse);
+ bool reachableBefore = self->ifStack.back();
+ self->ifStack.pop_back();
+ self->ifStack.push_back(self->reachable);
+ self->reachable = reachableBefore;
+ }
+
+ void visitIf(If* curr) {
+ // the ifStack has the branch that joins us, either from before if just an if, or the ifTrue if an if-else
+ reachable = reachable || ifStack.back();
+ ifStack.pop_back();
+ if (isDead(curr->condition)) {
+ replaceCurrent(curr->condition);
+ }
+ }
+
+ static void scan(DeadCodeElimination* self, Expression** currp) {
+ if (!self->reachable) {
+ // convert to an unreachable. do this without UB, even though we have no destructors on AST nodes
+ #define DELEGATE(CLASS_TO_VISIT) \
+ { ExpressionManipulator::convert<CLASS_TO_VISIT, Unreachable>(static_cast<CLASS_TO_VISIT*>(*currp)); break; }
+ switch ((*currp)->_id) {
+ case Expression::Id::BlockId: DELEGATE(Block);
+ case Expression::Id::IfId: DELEGATE(If);
+ case Expression::Id::LoopId: DELEGATE(Loop);
+ case Expression::Id::BreakId: DELEGATE(Break);
+ case Expression::Id::SwitchId: DELEGATE(Switch);
+ case Expression::Id::CallId: DELEGATE(Call);
+ case Expression::Id::CallImportId: DELEGATE(CallImport);
+ case Expression::Id::CallIndirectId: DELEGATE(CallIndirect);
+ case Expression::Id::GetLocalId: DELEGATE(GetLocal);
+ case Expression::Id::SetLocalId: DELEGATE(SetLocal);
+ case Expression::Id::LoadId: DELEGATE(Load);
+ case Expression::Id::StoreId: DELEGATE(Store);
+ case Expression::Id::ConstId: DELEGATE(Const);
+ case Expression::Id::UnaryId: DELEGATE(Unary);
+ case Expression::Id::BinaryId: DELEGATE(Binary);
+ case Expression::Id::SelectId: DELEGATE(Select);
+ case Expression::Id::ReturnId: DELEGATE(Return);
+ case Expression::Id::HostId: DELEGATE(Host);
+ case Expression::Id::NopId: DELEGATE(Nop);
+ case Expression::Id::UnreachableId: DELEGATE(Unreachable);
+ case Expression::Id::InvalidId:
+ default: WASM_UNREACHABLE();
+ }
+ #undef DELEGATE
+ return;
+ }
+ auto* curr =* currp;
+ if (curr->is<If>()) {
+ self->pushTask(DeadCodeElimination::doVisitIf, currp);
+ if (curr->cast<If>()->ifFalse) {
+ self->pushTask(DeadCodeElimination::scan, &curr->cast<If>()->ifFalse);
+ self->pushTask(DeadCodeElimination::doAfterIfElseTrue, currp);
+ }
+ self->pushTask(DeadCodeElimination::scan, &curr->cast<If>()->ifTrue);
+ self->pushTask(DeadCodeElimination::doAfterIfCondition, currp);
+ self->pushTask(DeadCodeElimination::scan, &curr->cast<If>()->condition);
+ } else if (curr->is<Block>()) {
+ self->pushTask(DeadCodeElimination::doVisitBlock, currp);
+ auto& list = curr->cast<Block>()->list;
+ for (int i = int(list.size()) - 1; i >= 0; i--) {
+ self->pushTask(DeadCodeElimination::doAfterBlockElement, currp);
+ self->pushTask(DeadCodeElimination::scan, &list[i]);
+ }
+ self->pushTask(DeadCodeElimination::doPreBlock, currp);
+ } else {
+ WalkerPass<PostWalker<DeadCodeElimination, Visitor<DeadCodeElimination>>>::scan(self, currp);
+ }
+ }
+
+ // other things
+
+ template<typename T>
+ void handleCall(T* curr, Expression* initial) {
+ for (Index i = 0; i < curr->operands.size(); i++) {
+ if (isDead(curr->operands[i])) {
+ if (i > 0 || initial != nullptr) {
+ auto* block = getModule()->allocator.alloc<Block>();
+ Index newSize = i + 1 + (initial ? 1 : 0);
+ block->list.resize(newSize);
+ Index j = 0;
+ if (initial) {
+ block->list[j] = initial;
+ j++;
+ }
+ for (; j < newSize; j++) {
+ block->list[j] = curr->operands[j - (initial ? 1 : 0)];
+ }
+ block->finalize();
+ replaceCurrent(block);
+ } else {
+ replaceCurrent(curr->operands[i]);
+ }
+ return;
+ }
+ }
+ }
+
+ void visitCall(Call* curr) {
+ handleCall(curr, nullptr);
+ }
+
+ void visitCallImport(CallImport* curr) {
+ handleCall(curr, nullptr);
+ }
+
+ void visitCallIndirect(CallIndirect* curr) {
+ if (isDead(curr->target)) {
+ replaceCurrent(curr->target);
+ return;
+ }
+ handleCall(curr, curr->target);
+ }
+
+ void visitSetLocal(SetLocal* curr) {
+ if (isDead(curr->value)) {
+ replaceCurrent(curr->value);
+ }
+ }
+
+ void visitLoad(Load* curr) {
+ if (isDead(curr->ptr)) {
+ replaceCurrent(curr->ptr);
+ }
+ }
+
+ void visitStore(Store* curr) {
+ if (isDead(curr->ptr)) {
+ replaceCurrent(curr->ptr);
+ return;
+ }
+ if (isDead(curr->value)) {
+ auto* block = getModule()->allocator.alloc<Block>();
+ block->list.resize(2);
+ block->list[0] = curr->ptr;
+ block->list[1] = curr->value;
+ block->finalize();
+ replaceCurrent(block);
+ }
+ }
+
+ void visitUnary(Unary* curr) {
+ if (isDead(curr->value)) {
+ replaceCurrent(curr->value);
+ }
+ }
+
+ void visitBinary(Binary* curr) {
+ if (isDead(curr->left)) {
+ replaceCurrent(curr->left);
+ return;
+ }
+ if (isDead(curr->right)) {
+ auto* block = getModule()->allocator.alloc<Block>();
+ block->list.resize(2);
+ block->list[0] = curr->left;
+ block->list[1] = curr->right;
+ block->finalize();
+ replaceCurrent(block);
+ }
+ }
+
+ void visitSelect(Select* curr) {
+ if (isDead(curr->ifTrue)) {
+ replaceCurrent(curr->ifTrue);
+ return;
+ }
+ if (isDead(curr->ifFalse)) {
+ auto* block = getModule()->allocator.alloc<Block>();
+ block->list.resize(2);
+ block->list[0] = curr->ifTrue;
+ block->list[1] = curr->ifFalse;
+ block->finalize();
+ replaceCurrent(block);
+ return;
+ }
+ if (isDead(curr->condition)) {
+ auto* block = getModule()->allocator.alloc<Block>();
+ block->list.resize(3);
+ block->list[0] = curr->ifTrue;
+ block->list[1] = curr->ifFalse;
+ block->list[2] = curr->condition;
+ block->finalize();
+ replaceCurrent(block);
+ return;
+ }
+ }
+
+ void visitHost(Host* curr) {
+ // TODO
+ }
+
+ void visitFunction(Function* curr) {
+ assert(reachableBreaks.size() == 0);
+ }
+};
+
+static RegisterPass<DeadCodeElimination> registerPass("dce", "removes unreachable code");
+
+} // namespace wasm
+
diff --git a/src/passes/pass.cpp b/src/passes/pass.cpp
index 1ff277902..b358243f7 100644
--- a/src/passes/pass.cpp
+++ b/src/passes/pass.cpp
@@ -58,6 +58,7 @@ std::string PassRegistry::getPassDescription(std::string name) {
// PassRunner
void PassRunner::addDefaultOptimizationPasses() {
+ add("dce");
add("remove-unused-brs");
add("remove-unused-names");
add("optimize-instructions");
diff --git a/test/emcc_hello_world.fromasm b/test/emcc_hello_world.fromasm
index 820ad6dd1..6f6da8ed3 100644
--- a/test/emcc_hello_world.fromasm
+++ b/test/emcc_hello_world.fromasm
@@ -3236,43 +3236,41 @@
)
)
(loop $label$break$L9 $label$continue$L9
- (block $switch$2
+ (block $switch-default$5
(block $switch-default$5
- (block $switch-default$5
- (block $switch-case$4
- (block $switch-case$3
- (br_table $switch-case$4 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-case$3 $switch-default$5
- (i32.sub
- (i32.shr_s
- (i32.shl
- (get_local $1)
- (i32.const 24)
- )
+ (block $switch-case$4
+ (block $switch-case$3
+ (br_table $switch-case$4 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-case$3 $switch-default$5
+ (i32.sub
+ (i32.shr_s
+ (i32.shl
+ (get_local $1)
(i32.const 24)
)
- (i32.const 0)
+ (i32.const 24)
)
+ (i32.const 0)
)
)
- (set_local $56
- (get_local $5)
- )
- (set_local $70
- (get_local $5)
- )
- (set_local $12
- (i32.const 9)
- )
- (br $label$break$L9)
)
- (set_local $41
+ (set_local $56
(get_local $5)
)
- (set_local $62
+ (set_local $70
(get_local $5)
)
+ (set_local $12
+ (i32.const 9)
+ )
(br $label$break$L9)
)
+ (set_local $41
+ (get_local $5)
+ )
+ (set_local $62
+ (get_local $5)
+ )
+ (br $label$break$L9)
)
)
(set_local $1
@@ -4519,42 +4517,21 @@
)
)
)
- (block $switch$25
+ (block $switch-default$33
(block $switch-default$33
- (block $switch-default$33
- (block $switch-case$32
- (block $switch-case$31
- (block $switch-case$30
- (block $switch-case$29
- (block $switch-case$28
- (block $switch-case$27
- (block $switch-case$26
- (br_table $switch-case$26 $switch-case$27 $switch-case$28 $switch-case$29 $switch-case$30 $switch-default$33 $switch-case$31 $switch-case$32 $switch-default$33
- (i32.sub
- (get_local $19)
- (i32.const 0)
- )
- )
- )
- (i32.store
- (i32.load
- (get_local $18)
+ (block $switch-case$32
+ (block $switch-case$31
+ (block $switch-case$30
+ (block $switch-case$29
+ (block $switch-case$28
+ (block $switch-case$27
+ (block $switch-case$26
+ (br_table $switch-case$26 $switch-case$27 $switch-case$28 $switch-case$29 $switch-case$30 $switch-default$33 $switch-case$31 $switch-case$32 $switch-default$33
+ (i32.sub
+ (get_local $19)
+ (i32.const 0)
)
- (get_local $8)
- )
- (set_local $19
- (get_local $8)
)
- (set_local $20
- (get_local $9)
- )
- (set_local $1
- (get_local $16)
- )
- (set_local $11
- (get_local $22)
- )
- (br $label$continue$L1)
)
(i32.store
(i32.load
@@ -4577,26 +4554,11 @@
(br $label$continue$L1)
)
(i32.store
- (set_local $1
- (i32.load
- (get_local $18)
- )
+ (i32.load
+ (get_local $18)
)
(get_local $8)
)
- (i32.store offset=4
- (get_local $1)
- (i32.shr_s
- (i32.shl
- (i32.lt_s
- (get_local $8)
- (i32.const 0)
- )
- (i32.const 31)
- )
- (i32.const 31)
- )
- )
(set_local $19
(get_local $8)
)
@@ -4611,13 +4573,25 @@
)
(br $label$continue$L1)
)
- (i32.store16
- (i32.load
- (get_local $18)
+ (i32.store
+ (set_local $1
+ (i32.load
+ (get_local $18)
+ )
)
- (i32.and
- (get_local $8)
- (i32.const 65535)
+ (get_local $8)
+ )
+ (i32.store offset=4
+ (get_local $1)
+ (i32.shr_s
+ (i32.shl
+ (i32.lt_s
+ (get_local $8)
+ (i32.const 0)
+ )
+ (i32.const 31)
+ )
+ (i32.const 31)
)
)
(set_local $19
@@ -4634,13 +4608,13 @@
)
(br $label$continue$L1)
)
- (i32.store8
+ (i32.store16
(i32.load
(get_local $18)
)
(i32.and
(get_local $8)
- (i32.const 255)
+ (i32.const 65535)
)
)
(set_local $19
@@ -4657,11 +4631,14 @@
)
(br $label$continue$L1)
)
- (i32.store
+ (i32.store8
(i32.load
(get_local $18)
)
- (get_local $8)
+ (i32.and
+ (get_local $8)
+ (i32.const 255)
+ )
)
(set_local $19
(get_local $8)
@@ -4678,26 +4655,11 @@
(br $label$continue$L1)
)
(i32.store
- (set_local $1
- (i32.load
- (get_local $18)
- )
+ (i32.load
+ (get_local $18)
)
(get_local $8)
)
- (i32.store offset=4
- (get_local $1)
- (i32.shr_s
- (i32.shl
- (i32.lt_s
- (get_local $8)
- (i32.const 0)
- )
- (i32.const 31)
- )
- (i32.const 31)
- )
- )
(set_local $19
(get_local $8)
)
@@ -4712,6 +4674,27 @@
)
(br $label$continue$L1)
)
+ (i32.store
+ (set_local $1
+ (i32.load
+ (get_local $18)
+ )
+ )
+ (get_local $8)
+ )
+ (i32.store offset=4
+ (get_local $1)
+ (i32.shr_s
+ (i32.shl
+ (i32.lt_s
+ (get_local $8)
+ (i32.const 0)
+ )
+ (i32.const 31)
+ )
+ (i32.const 31)
+ )
+ )
(set_local $19
(get_local $8)
)
@@ -4726,8 +4709,20 @@
)
(br $label$continue$L1)
)
+ (set_local $19
+ (get_local $8)
+ )
+ (set_local $20
+ (get_local $9)
+ )
+ (set_local $1
+ (get_local $16)
+ )
+ (set_local $11
+ (get_local $22)
+ )
+ (br $label$continue$L1)
)
- (br $switch$24)
)
(set_local $49
(i32.or
@@ -9015,68 +9010,24 @@
(get_local $1)
(i32.const 20)
)
- (block $switch$3
+ (block $switch-default$14
(block $switch-default$14
- (block $switch-default$14
- (block $switch-case$13
- (block $switch-case$12
- (block $switch-case$11
- (block $switch-case$10
- (block $switch-case$9
- (block $switch-case$8
- (block $switch-case$7
- (block $switch-case$6
- (block $switch-case$5
- (block $switch-case$4
- (br_table $switch-case$4 $switch-case$5 $switch-case$6 $switch-case$7 $switch-case$8 $switch-case$9 $switch-case$10 $switch-case$11 $switch-case$12 $switch-case$13 $switch-default$14
- (i32.sub
- (get_local $1)
- (i32.const 9)
- )
- )
- )
- (set_local $3
- (i32.load
- (set_local $1
- (i32.and
- (i32.add
- (i32.load
- (get_local $2)
- )
- (i32.sub
- (i32.add
- (i32.const 0)
- (i32.const 4)
- )
- (i32.const 1)
- )
- )
- (i32.xor
- (i32.sub
- (i32.add
- (i32.const 0)
- (i32.const 4)
- )
- (i32.const 1)
- )
- (i32.const -1)
- )
- )
- )
- )
- )
- (i32.store
- (get_local $2)
- (i32.add
+ (block $switch-case$13
+ (block $switch-case$12
+ (block $switch-case$11
+ (block $switch-case$10
+ (block $switch-case$9
+ (block $switch-case$8
+ (block $switch-case$7
+ (block $switch-case$6
+ (block $switch-case$5
+ (block $switch-case$4
+ (br_table $switch-case$4 $switch-case$5 $switch-case$6 $switch-case$7 $switch-case$8 $switch-case$9 $switch-case$10 $switch-case$11 $switch-case$12 $switch-case$13 $switch-default$14
+ (i32.sub
(get_local $1)
- (i32.const 4)
+ (i32.const 9)
)
)
- (i32.store
- (get_local $0)
- (get_local $3)
- )
- (br $label$break$L1)
)
(set_local $3
(i32.load
@@ -9119,19 +9070,6 @@
(get_local $0)
(get_local $3)
)
- (i32.store offset=4
- (get_local $0)
- (i32.shr_s
- (i32.shl
- (i32.lt_s
- (get_local $3)
- (i32.const 0)
- )
- (i32.const 31)
- )
- (i32.const 31)
- )
- )
(br $label$break$L1)
)
(set_local $3
@@ -9177,131 +9115,117 @@
)
(i32.store offset=4
(get_local $0)
- (i32.const 0)
+ (i32.shr_s
+ (i32.shl
+ (i32.lt_s
+ (get_local $3)
+ (i32.const 0)
+ )
+ (i32.const 31)
+ )
+ (i32.const 31)
+ )
)
(br $label$break$L1)
)
- (set_local $5
+ (set_local $3
(i32.load
- (set_local $3
- (set_local $1
- (i32.and
- (i32.add
- (i32.load
- (get_local $2)
- )
- (i32.sub
- (i32.add
- (i32.const 0)
- (i32.const 8)
- )
- (i32.const 1)
+ (set_local $1
+ (i32.and
+ (i32.add
+ (i32.load
+ (get_local $2)
+ )
+ (i32.sub
+ (i32.add
+ (i32.const 0)
+ (i32.const 4)
)
+ (i32.const 1)
)
- (i32.xor
- (i32.sub
- (i32.add
- (i32.const 0)
- (i32.const 8)
- )
- (i32.const 1)
+ )
+ (i32.xor
+ (i32.sub
+ (i32.add
+ (i32.const 0)
+ (i32.const 4)
)
- (i32.const -1)
+ (i32.const 1)
)
+ (i32.const -1)
)
)
)
)
)
- (set_local $3
- (i32.load offset=4
- (get_local $3)
- )
- )
(i32.store
(get_local $2)
(i32.add
(get_local $1)
- (i32.const 8)
+ (i32.const 4)
)
)
(i32.store
(get_local $0)
- (get_local $5)
+ (get_local $3)
)
(i32.store offset=4
(get_local $0)
- (get_local $3)
+ (i32.const 0)
)
(br $label$break$L1)
)
- (set_local $3
+ (set_local $5
(i32.load
- (set_local $1
- (i32.and
- (i32.add
- (i32.load
- (get_local $2)
- )
- (i32.sub
- (i32.add
- (i32.const 0)
- (i32.const 4)
+ (set_local $3
+ (set_local $1
+ (i32.and
+ (i32.add
+ (i32.load
+ (get_local $2)
+ )
+ (i32.sub
+ (i32.add
+ (i32.const 0)
+ (i32.const 8)
+ )
+ (i32.const 1)
)
- (i32.const 1)
)
- )
- (i32.xor
- (i32.sub
- (i32.add
- (i32.const 0)
- (i32.const 4)
+ (i32.xor
+ (i32.sub
+ (i32.add
+ (i32.const 0)
+ (i32.const 8)
+ )
+ (i32.const 1)
)
- (i32.const 1)
+ (i32.const -1)
)
- (i32.const -1)
)
)
)
)
)
+ (set_local $3
+ (i32.load offset=4
+ (get_local $3)
+ )
+ )
(i32.store
(get_local $2)
(i32.add
(get_local $1)
- (i32.const 4)
- )
- )
- (set_local $2
- (i32.shr_s
- (i32.shl
- (i32.lt_s
- (set_local $1
- (i32.shr_s
- (i32.shl
- (i32.and
- (get_local $3)
- (i32.const 65535)
- )
- (i32.const 16)
- )
- (i32.const 16)
- )
- )
- (i32.const 0)
- )
- (i32.const 31)
- )
- (i32.const 31)
+ (i32.const 8)
)
)
(i32.store
(get_local $0)
- (get_local $1)
+ (get_local $5)
)
(i32.store offset=4
(get_local $0)
- (get_local $2)
+ (get_local $3)
)
(br $label$break$L1)
)
@@ -9342,16 +9266,36 @@
(i32.const 4)
)
)
+ (set_local $2
+ (i32.shr_s
+ (i32.shl
+ (i32.lt_s
+ (set_local $1
+ (i32.shr_s
+ (i32.shl
+ (i32.and
+ (get_local $3)
+ (i32.const 65535)
+ )
+ (i32.const 16)
+ )
+ (i32.const 16)
+ )
+ )
+ (i32.const 0)
+ )
+ (i32.const 31)
+ )
+ (i32.const 31)
+ )
+ )
(i32.store
(get_local $0)
- (i32.and
- (get_local $3)
- (i32.const 65535)
- )
+ (get_local $1)
)
(i32.store offset=4
(get_local $0)
- (i32.const 0)
+ (get_local $2)
)
(br $label$break$L1)
)
@@ -9392,36 +9336,16 @@
(i32.const 4)
)
)
- (set_local $2
- (i32.shr_s
- (i32.shl
- (i32.lt_s
- (set_local $1
- (i32.shr_s
- (i32.shl
- (i32.and
- (get_local $3)
- (i32.const 255)
- )
- (i32.const 24)
- )
- (i32.const 24)
- )
- )
- (i32.const 0)
- )
- (i32.const 31)
- )
- (i32.const 31)
- )
- )
(i32.store
(get_local $0)
- (get_local $1)
+ (i32.and
+ (get_local $3)
+ (i32.const 65535)
+ )
)
(i32.store offset=4
(get_local $0)
- (get_local $2)
+ (i32.const 0)
)
(br $label$break$L1)
)
@@ -9462,21 +9386,41 @@
(i32.const 4)
)
)
+ (set_local $2
+ (i32.shr_s
+ (i32.shl
+ (i32.lt_s
+ (set_local $1
+ (i32.shr_s
+ (i32.shl
+ (i32.and
+ (get_local $3)
+ (i32.const 255)
+ )
+ (i32.const 24)
+ )
+ (i32.const 24)
+ )
+ )
+ (i32.const 0)
+ )
+ (i32.const 31)
+ )
+ (i32.const 31)
+ )
+ )
(i32.store
(get_local $0)
- (i32.and
- (get_local $3)
- (i32.const 255)
- )
+ (get_local $1)
)
(i32.store offset=4
(get_local $0)
- (i32.const 0)
+ (get_local $2)
)
(br $label$break$L1)
)
- (set_local $4
- (f64.load
+ (set_local $3
+ (i32.load
(set_local $1
(i32.and
(i32.add
@@ -9486,7 +9430,7 @@
(i32.sub
(i32.add
(i32.const 0)
- (i32.const 8)
+ (i32.const 4)
)
(i32.const 1)
)
@@ -9495,7 +9439,7 @@
(i32.sub
(i32.add
(i32.const 0)
- (i32.const 8)
+ (i32.const 4)
)
(i32.const 1)
)
@@ -9509,12 +9453,19 @@
(get_local $2)
(i32.add
(get_local $1)
- (i32.const 8)
+ (i32.const 4)
)
)
- (f64.store
+ (i32.store
(get_local $0)
- (get_local $4)
+ (i32.and
+ (get_local $3)
+ (i32.const 255)
+ )
+ )
+ (i32.store offset=4
+ (get_local $0)
+ (i32.const 0)
)
(br $label$break$L1)
)
@@ -9559,6 +9510,48 @@
(get_local $0)
(get_local $4)
)
+ (br $label$break$L1)
+ )
+ (set_local $4
+ (f64.load
+ (set_local $1
+ (i32.and
+ (i32.add
+ (i32.load
+ (get_local $2)
+ )
+ (i32.sub
+ (i32.add
+ (i32.const 0)
+ (i32.const 8)
+ )
+ (i32.const 1)
+ )
+ )
+ (i32.xor
+ (i32.sub
+ (i32.add
+ (i32.const 0)
+ (i32.const 8)
+ )
+ (i32.const 1)
+ )
+ (i32.const -1)
+ )
+ )
+ )
+ )
+ )
+ (i32.store
+ (get_local $2)
+ (i32.add
+ (get_local $1)
+ (i32.const 8)
+ )
+ )
+ (f64.store
+ (get_local $0)
+ (get_local $4)
)
)
)
diff --git a/test/emcc_hello_world.fromasm.imprecise b/test/emcc_hello_world.fromasm.imprecise
index 84e725768..fac02cca9 100644
--- a/test/emcc_hello_world.fromasm.imprecise
+++ b/test/emcc_hello_world.fromasm.imprecise
@@ -3234,43 +3234,41 @@
)
)
(loop $label$break$L9 $label$continue$L9
- (block $switch$2
+ (block $switch-default$5
(block $switch-default$5
- (block $switch-default$5
- (block $switch-case$4
- (block $switch-case$3
- (br_table $switch-case$4 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-case$3 $switch-default$5
- (i32.sub
- (i32.shr_s
- (i32.shl
- (get_local $1)
- (i32.const 24)
- )
+ (block $switch-case$4
+ (block $switch-case$3
+ (br_table $switch-case$4 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-default$5 $switch-case$3 $switch-default$5
+ (i32.sub
+ (i32.shr_s
+ (i32.shl
+ (get_local $1)
(i32.const 24)
)
- (i32.const 0)
+ (i32.const 24)
)
+ (i32.const 0)
)
)
- (set_local $56
- (get_local $5)
- )
- (set_local $70
- (get_local $5)
- )
- (set_local $12
- (i32.const 9)
- )
- (br $label$break$L9)
)
- (set_local $41
+ (set_local $56
(get_local $5)
)
- (set_local $62
+ (set_local $70
(get_local $5)
)
+ (set_local $12
+ (i32.const 9)
+ )
(br $label$break$L9)
)
+ (set_local $41
+ (get_local $5)
+ )
+ (set_local $62
+ (get_local $5)
+ )
+ (br $label$break$L9)
)
)
(set_local $1
@@ -4517,42 +4515,21 @@
)
)
)
- (block $switch$25
+ (block $switch-default$33
(block $switch-default$33
- (block $switch-default$33
- (block $switch-case$32
- (block $switch-case$31
- (block $switch-case$30
- (block $switch-case$29
- (block $switch-case$28
- (block $switch-case$27
- (block $switch-case$26
- (br_table $switch-case$26 $switch-case$27 $switch-case$28 $switch-case$29 $switch-case$30 $switch-default$33 $switch-case$31 $switch-case$32 $switch-default$33
- (i32.sub
- (get_local $19)
- (i32.const 0)
- )
- )
- )
- (i32.store
- (i32.load
- (get_local $18)
+ (block $switch-case$32
+ (block $switch-case$31
+ (block $switch-case$30
+ (block $switch-case$29
+ (block $switch-case$28
+ (block $switch-case$27
+ (block $switch-case$26
+ (br_table $switch-case$26 $switch-case$27 $switch-case$28 $switch-case$29 $switch-case$30 $switch-default$33 $switch-case$31 $switch-case$32 $switch-default$33
+ (i32.sub
+ (get_local $19)
+ (i32.const 0)
)
- (get_local $8)
- )
- (set_local $19
- (get_local $8)
)
- (set_local $20
- (get_local $9)
- )
- (set_local $1
- (get_local $16)
- )
- (set_local $11
- (get_local $22)
- )
- (br $label$continue$L1)
)
(i32.store
(i32.load
@@ -4575,26 +4552,11 @@
(br $label$continue$L1)
)
(i32.store
- (set_local $1
- (i32.load
- (get_local $18)
- )
+ (i32.load
+ (get_local $18)
)
(get_local $8)
)
- (i32.store offset=4
- (get_local $1)
- (i32.shr_s
- (i32.shl
- (i32.lt_s
- (get_local $8)
- (i32.const 0)
- )
- (i32.const 31)
- )
- (i32.const 31)
- )
- )
(set_local $19
(get_local $8)
)
@@ -4609,13 +4571,25 @@
)
(br $label$continue$L1)
)
- (i32.store16
- (i32.load
- (get_local $18)
+ (i32.store
+ (set_local $1
+ (i32.load
+ (get_local $18)
+ )
)
- (i32.and
- (get_local $8)
- (i32.const 65535)
+ (get_local $8)
+ )
+ (i32.store offset=4
+ (get_local $1)
+ (i32.shr_s
+ (i32.shl
+ (i32.lt_s
+ (get_local $8)
+ (i32.const 0)
+ )
+ (i32.const 31)
+ )
+ (i32.const 31)
)
)
(set_local $19
@@ -4632,13 +4606,13 @@
)
(br $label$continue$L1)
)
- (i32.store8
+ (i32.store16
(i32.load
(get_local $18)
)
(i32.and
(get_local $8)
- (i32.const 255)
+ (i32.const 65535)
)
)
(set_local $19
@@ -4655,11 +4629,14 @@
)
(br $label$continue$L1)
)
- (i32.store
+ (i32.store8
(i32.load
(get_local $18)
)
- (get_local $8)
+ (i32.and
+ (get_local $8)
+ (i32.const 255)
+ )
)
(set_local $19
(get_local $8)
@@ -4676,26 +4653,11 @@
(br $label$continue$L1)
)
(i32.store
- (set_local $1
- (i32.load
- (get_local $18)
- )
+ (i32.load
+ (get_local $18)
)
(get_local $8)
)
- (i32.store offset=4
- (get_local $1)
- (i32.shr_s
- (i32.shl
- (i32.lt_s
- (get_local $8)
- (i32.const 0)
- )
- (i32.const 31)
- )
- (i32.const 31)
- )
- )
(set_local $19
(get_local $8)
)
@@ -4710,6 +4672,27 @@
)
(br $label$continue$L1)
)
+ (i32.store
+ (set_local $1
+ (i32.load
+ (get_local $18)
+ )
+ )
+ (get_local $8)
+ )
+ (i32.store offset=4
+ (get_local $1)
+ (i32.shr_s
+ (i32.shl
+ (i32.lt_s
+ (get_local $8)
+ (i32.const 0)
+ )
+ (i32.const 31)
+ )
+ (i32.const 31)
+ )
+ )
(set_local $19
(get_local $8)
)
@@ -4724,8 +4707,20 @@
)
(br $label$continue$L1)
)
+ (set_local $19
+ (get_local $8)
+ )
+ (set_local $20
+ (get_local $9)
+ )
+ (set_local $1
+ (get_local $16)
+ )
+ (set_local $11
+ (get_local $22)
+ )
+ (br $label$continue$L1)
)
- (br $switch$24)
)
(set_local $49
(i32.or
@@ -9013,68 +9008,24 @@
(get_local $1)
(i32.const 20)
)
- (block $switch$3
+ (block $switch-default$14
(block $switch-default$14
- (block $switch-default$14
- (block $switch-case$13
- (block $switch-case$12
- (block $switch-case$11
- (block $switch-case$10
- (block $switch-case$9
- (block $switch-case$8
- (block $switch-case$7
- (block $switch-case$6
- (block $switch-case$5
- (block $switch-case$4
- (br_table $switch-case$4 $switch-case$5 $switch-case$6 $switch-case$7 $switch-case$8 $switch-case$9 $switch-case$10 $switch-case$11 $switch-case$12 $switch-case$13 $switch-default$14
- (i32.sub
- (get_local $1)
- (i32.const 9)
- )
- )
- )
- (set_local $3
- (i32.load
- (set_local $1
- (i32.and
- (i32.add
- (i32.load
- (get_local $2)
- )
- (i32.sub
- (i32.add
- (i32.const 0)
- (i32.const 4)
- )
- (i32.const 1)
- )
- )
- (i32.xor
- (i32.sub
- (i32.add
- (i32.const 0)
- (i32.const 4)
- )
- (i32.const 1)
- )
- (i32.const -1)
- )
- )
- )
- )
- )
- (i32.store
- (get_local $2)
- (i32.add
+ (block $switch-case$13
+ (block $switch-case$12
+ (block $switch-case$11
+ (block $switch-case$10
+ (block $switch-case$9
+ (block $switch-case$8
+ (block $switch-case$7
+ (block $switch-case$6
+ (block $switch-case$5
+ (block $switch-case$4
+ (br_table $switch-case$4 $switch-case$5 $switch-case$6 $switch-case$7 $switch-case$8 $switch-case$9 $switch-case$10 $switch-case$11 $switch-case$12 $switch-case$13 $switch-default$14
+ (i32.sub
(get_local $1)
- (i32.const 4)
+ (i32.const 9)
)
)
- (i32.store
- (get_local $0)
- (get_local $3)
- )
- (br $label$break$L1)
)
(set_local $3
(i32.load
@@ -9117,19 +9068,6 @@
(get_local $0)
(get_local $3)
)
- (i32.store offset=4
- (get_local $0)
- (i32.shr_s
- (i32.shl
- (i32.lt_s
- (get_local $3)
- (i32.const 0)
- )
- (i32.const 31)
- )
- (i32.const 31)
- )
- )
(br $label$break$L1)
)
(set_local $3
@@ -9175,131 +9113,117 @@
)
(i32.store offset=4
(get_local $0)
- (i32.const 0)
+ (i32.shr_s
+ (i32.shl
+ (i32.lt_s
+ (get_local $3)
+ (i32.const 0)
+ )
+ (i32.const 31)
+ )
+ (i32.const 31)
+ )
)
(br $label$break$L1)
)
- (set_local $5
+ (set_local $3
(i32.load
- (set_local $3
- (set_local $1
- (i32.and
- (i32.add
- (i32.load
- (get_local $2)
- )
- (i32.sub
- (i32.add
- (i32.const 0)
- (i32.const 8)
- )
- (i32.const 1)
+ (set_local $1
+ (i32.and
+ (i32.add
+ (i32.load
+ (get_local $2)
+ )
+ (i32.sub
+ (i32.add
+ (i32.const 0)
+ (i32.const 4)
)
+ (i32.const 1)
)
- (i32.xor
- (i32.sub
- (i32.add
- (i32.const 0)
- (i32.const 8)
- )
- (i32.const 1)
+ )
+ (i32.xor
+ (i32.sub
+ (i32.add
+ (i32.const 0)
+ (i32.const 4)
)
- (i32.const -1)
+ (i32.const 1)
)
+ (i32.const -1)
)
)
)
)
)
- (set_local $3
- (i32.load offset=4
- (get_local $3)
- )
- )
(i32.store
(get_local $2)
(i32.add
(get_local $1)
- (i32.const 8)
+ (i32.const 4)
)
)
(i32.store
(get_local $0)
- (get_local $5)
+ (get_local $3)
)
(i32.store offset=4
(get_local $0)
- (get_local $3)
+ (i32.const 0)
)
(br $label$break$L1)
)
- (set_local $3
+ (set_local $5
(i32.load
- (set_local $1
- (i32.and
- (i32.add
- (i32.load
- (get_local $2)
- )
- (i32.sub
- (i32.add
- (i32.const 0)
- (i32.const 4)
+ (set_local $3
+ (set_local $1
+ (i32.and
+ (i32.add
+ (i32.load
+ (get_local $2)
+ )
+ (i32.sub
+ (i32.add
+ (i32.const 0)
+ (i32.const 8)
+ )
+ (i32.const 1)
)
- (i32.const 1)
)
- )
- (i32.xor
- (i32.sub
- (i32.add
- (i32.const 0)
- (i32.const 4)
+ (i32.xor
+ (i32.sub
+ (i32.add
+ (i32.const 0)
+ (i32.const 8)
+ )
+ (i32.const 1)
)
- (i32.const 1)
+ (i32.const -1)
)
- (i32.const -1)
)
)
)
)
)
+ (set_local $3
+ (i32.load offset=4
+ (get_local $3)
+ )
+ )
(i32.store
(get_local $2)
(i32.add
(get_local $1)
- (i32.const 4)
- )
- )
- (set_local $2
- (i32.shr_s
- (i32.shl
- (i32.lt_s
- (set_local $1
- (i32.shr_s
- (i32.shl
- (i32.and
- (get_local $3)
- (i32.const 65535)
- )
- (i32.const 16)
- )
- (i32.const 16)
- )
- )
- (i32.const 0)
- )
- (i32.const 31)
- )
- (i32.const 31)
+ (i32.const 8)
)
)
(i32.store
(get_local $0)
- (get_local $1)
+ (get_local $5)
)
(i32.store offset=4
(get_local $0)
- (get_local $2)
+ (get_local $3)
)
(br $label$break$L1)
)
@@ -9340,16 +9264,36 @@
(i32.const 4)
)
)
+ (set_local $2
+ (i32.shr_s
+ (i32.shl
+ (i32.lt_s
+ (set_local $1
+ (i32.shr_s
+ (i32.shl
+ (i32.and
+ (get_local $3)
+ (i32.const 65535)
+ )
+ (i32.const 16)
+ )
+ (i32.const 16)
+ )
+ )
+ (i32.const 0)
+ )
+ (i32.const 31)
+ )
+ (i32.const 31)
+ )
+ )
(i32.store
(get_local $0)
- (i32.and
- (get_local $3)
- (i32.const 65535)
- )
+ (get_local $1)
)
(i32.store offset=4
(get_local $0)
- (i32.const 0)
+ (get_local $2)
)
(br $label$break$L1)
)
@@ -9390,36 +9334,16 @@
(i32.const 4)
)
)
- (set_local $2
- (i32.shr_s
- (i32.shl
- (i32.lt_s
- (set_local $1
- (i32.shr_s
- (i32.shl
- (i32.and
- (get_local $3)
- (i32.const 255)
- )
- (i32.const 24)
- )
- (i32.const 24)
- )
- )
- (i32.const 0)
- )
- (i32.const 31)
- )
- (i32.const 31)
- )
- )
(i32.store
(get_local $0)
- (get_local $1)
+ (i32.and
+ (get_local $3)
+ (i32.const 65535)
+ )
)
(i32.store offset=4
(get_local $0)
- (get_local $2)
+ (i32.const 0)
)
(br $label$break$L1)
)
@@ -9460,21 +9384,41 @@
(i32.const 4)
)
)
+ (set_local $2
+ (i32.shr_s
+ (i32.shl
+ (i32.lt_s
+ (set_local $1
+ (i32.shr_s
+ (i32.shl
+ (i32.and
+ (get_local $3)
+ (i32.const 255)
+ )
+ (i32.const 24)
+ )
+ (i32.const 24)
+ )
+ )
+ (i32.const 0)
+ )
+ (i32.const 31)
+ )
+ (i32.const 31)
+ )
+ )
(i32.store
(get_local $0)
- (i32.and
- (get_local $3)
- (i32.const 255)
- )
+ (get_local $1)
)
(i32.store offset=4
(get_local $0)
- (i32.const 0)
+ (get_local $2)
)
(br $label$break$L1)
)
- (set_local $4
- (f64.load
+ (set_local $3
+ (i32.load
(set_local $1
(i32.and
(i32.add
@@ -9484,7 +9428,7 @@
(i32.sub
(i32.add
(i32.const 0)
- (i32.const 8)
+ (i32.const 4)
)
(i32.const 1)
)
@@ -9493,7 +9437,7 @@
(i32.sub
(i32.add
(i32.const 0)
- (i32.const 8)
+ (i32.const 4)
)
(i32.const 1)
)
@@ -9507,12 +9451,19 @@
(get_local $2)
(i32.add
(get_local $1)
- (i32.const 8)
+ (i32.const 4)
)
)
- (f64.store
+ (i32.store
(get_local $0)
- (get_local $4)
+ (i32.and
+ (get_local $3)
+ (i32.const 255)
+ )
+ )
+ (i32.store offset=4
+ (get_local $0)
+ (i32.const 0)
)
(br $label$break$L1)
)
@@ -9557,6 +9508,48 @@
(get_local $0)
(get_local $4)
)
+ (br $label$break$L1)
+ )
+ (set_local $4
+ (f64.load
+ (set_local $1
+ (i32.and
+ (i32.add
+ (i32.load
+ (get_local $2)
+ )
+ (i32.sub
+ (i32.add
+ (i32.const 0)
+ (i32.const 8)
+ )
+ (i32.const 1)
+ )
+ )
+ (i32.xor
+ (i32.sub
+ (i32.add
+ (i32.const 0)
+ (i32.const 8)
+ )
+ (i32.const 1)
+ )
+ (i32.const -1)
+ )
+ )
+ )
+ )
+ )
+ (i32.store
+ (get_local $2)
+ (i32.add
+ (get_local $1)
+ (i32.const 8)
+ )
+ )
+ (f64.store
+ (get_local $0)
+ (get_local $4)
)
)
)
diff --git a/test/passes/dce.txt b/test/passes/dce.txt
new file mode 100644
index 000000000..3d32d9bed
--- /dev/null
+++ b/test/passes/dce.txt
@@ -0,0 +1,239 @@
+(module
+ (memory 10)
+ (type $ii (func (param i32 i32)))
+ (table $call-me)
+ (func $call-me (param $0 i32) (param $1 i32)
+ (nop)
+ )
+ (func $code-to-kill
+ (local $x i32)
+ (block $out
+ (br $out)
+ )
+ (if
+ (i32.const 0)
+ (unreachable)
+ )
+ (if
+ (i32.const 0)
+ (block $out
+ (return)
+ )
+ )
+ (block $out
+ (br_table $out $out $out $out
+ (i32.const 4)
+ )
+ )
+ (block $out
+ (br_if $out
+ (i32.const 3)
+ )
+ (i32.const 0)
+ )
+ (if
+ (i32.const 0)
+ (block $block4
+ (if
+ (i32.const 0)
+ (unreachable)
+ (unreachable)
+ )
+ )
+ )
+ (if
+ (i32.const 0)
+ (unreachable)
+ )
+ (if
+ (i32.const 0)
+ (unreachable)
+ )
+ (if
+ (i32.const 0)
+ (unreachable)
+ )
+ (block $out
+ (block $in
+ (br_if $out
+ (i32.const 1)
+ )
+ )
+ (unreachable)
+ )
+ (if
+ (i32.const 0)
+ (block $block11
+ (block $out
+ (block $in
+ (br_if $in
+ (i32.const 1)
+ )
+ )
+ (unreachable)
+ )
+ )
+ )
+ (block $out
+ (block $in
+ (br_table $out $in
+ (i32.const 1)
+ )
+ )
+ (unreachable)
+ )
+ (block $out
+ (block $in
+ (br_table $in $out
+ (i32.const 1)
+ )
+ )
+ (unreachable)
+ )
+ (if
+ (i32.const 0)
+ (block $block13
+ (block $out
+ (block $in
+ (br_table $in $in
+ (i32.const 1)
+ )
+ )
+ (unreachable)
+ )
+ )
+ )
+ (if
+ (i32.const 0)
+ (block $block15
+ (i32.const 10)
+ (i32.const 42)
+ (unreachable)
+ )
+ )
+ (if
+ (i32.const 0)
+ (unreachable)
+ )
+ (loop $out $in
+ (br_if $out
+ (i32.const 1)
+ )
+ (unreachable)
+ )
+ (if
+ (i32.const 0)
+ (block $block20
+ (loop $out $in
+ (br_if $in
+ (i32.const 1)
+ )
+ (unreachable)
+ )
+ )
+ )
+ (if
+ (i32.const 1)
+ (block
+ (i32.const 123)
+ (unreachable)
+ )
+ )
+ (if
+ (i32.const 2)
+ (unreachable)
+ )
+ (if
+ (i32.const 3)
+ (unreachable)
+ )
+ (if
+ (i32.const -1)
+ (block
+ (i32.const 123)
+ (i32.const 456)
+ (unreachable)
+ )
+ )
+ (if
+ (i32.const -2)
+ (block
+ (i32.const 139)
+ (unreachable)
+ )
+ )
+ (if
+ (i32.const -3)
+ (block
+ (i32.const 246)
+ (unreachable)
+ )
+ )
+ (if
+ (i32.const -4)
+ (unreachable)
+ )
+ (if
+ (i32.const 11)
+ (unreachable)
+ )
+ (if
+ (i32.const 22)
+ (unreachable)
+ )
+ (if
+ (i32.const 33)
+ (block
+ (i32.const 0)
+ (unreachable)
+ )
+ )
+ (if
+ (i32.const 44)
+ (unreachable)
+ )
+ (if
+ (i32.const 55)
+ (unreachable)
+ )
+ (if
+ (i32.const 66)
+ (unreachable)
+ )
+ (if
+ (i32.const 77)
+ (unreachable)
+ )
+ (if
+ (i32.const 88)
+ (block
+ (i32.const 0)
+ (unreachable)
+ )
+ )
+ (if
+ (i32.const 99)
+ (unreachable)
+ )
+ (if
+ (i32.const 100)
+ (block
+ (i32.const 123)
+ (i32.const 456)
+ (unreachable)
+ )
+ )
+ (if
+ (i32.const 101)
+ (block
+ (i32.const 123)
+ (unreachable)
+ )
+ )
+ (if
+ (i32.const 102)
+ (unreachable)
+ )
+ (i32.const 1337)
+ )
+)
diff --git a/test/passes/dce.wast b/test/passes/dce.wast
new file mode 100644
index 000000000..e76607ecd
--- /dev/null
+++ b/test/passes/dce.wast
@@ -0,0 +1,197 @@
+(module
+ (memory 10)
+ (type $ii (func (param i32) (param i32)))
+ (table $call-me)
+ (func $call-me (param i32) (param i32)
+ )
+ (func $code-to-kill
+ (local $x i32)
+ (block $out
+ (br $out) ;; kill everything after this
+ (i32.const 0)
+ (if (i32.const 1)
+ (i32.const 2)
+ )
+ (br_table $out $out $out $out (i32.const 3))
+ (call $code-to-kill)
+ )
+ (if (i32.const 0)
+ (block $out
+ (unreachable)
+ (i32.const 0)
+ )
+ )
+ (if (i32.const 0)
+ (block $out
+ (return)
+ (i32.const 0)
+ )
+ )
+ (block $out
+ (br_table $out $out $out $out (i32.const 4))
+ (i32.const 0)
+ )
+ (block $out
+ (br_if $out (i32.const 3)) ;; but not after this
+ (i32.const 0)
+ )
+ (if (i32.const 0)
+ (block
+ (if (i32.const 0) ;; if that is unreachable both ways
+ (block $out
+ (unreachable)
+ (i32.const 0)
+ )
+ (block $out
+ (unreachable)
+ (i32.const 0)
+ )
+ )
+ (i32.const 0)
+ )
+ )
+ (if (i32.const 0)
+ (block $out
+ (br $out (unreachable))
+ (i32.const 0)
+ )
+ )
+ (if (i32.const 0)
+ (block $out
+ (br_if $out (unreachable) (i32.const 0))
+ (i32.const 0)
+ )
+ )
+ (if (i32.const 0)
+ (block $out
+ (br_if $out (unreachable) (unreachable))
+ (i32.const 0)
+ )
+ )
+ (block $out
+ (block $in
+ (br_if $out (i32.const 1))
+ )
+ (unreachable)
+ )
+ (if (i32.const 0)
+ (block
+ (block $out
+ (block $in
+ (br_if $in (i32.const 1))
+ )
+ (unreachable)
+ )
+ (i32.const 10)
+ )
+ )
+ (block $out
+ (block $in
+ (br_table $out $in (i32.const 1))
+ )
+ (unreachable)
+ )
+ (block $out
+ (block $in
+ (br_table $in $out (i32.const 1))
+ )
+ (unreachable)
+ )
+ (if (i32.const 0)
+ (block
+ (block $out
+ (block $in
+ (br_table $in $in (i32.const 1))
+ )
+ (unreachable)
+ )
+ (i32.const 10)
+ )
+ )
+ (if (i32.const 0)
+ (block
+ (i32.const 10)
+ (i32.const 42)
+ (unreachable)
+ (return (unreachable))
+ (unreachable)
+ (return)
+ )
+ )
+ (if (i32.const 0)
+ (loop (unreachable))
+ )
+ (loop $out $in
+ (br_if $out (i32.const 1))
+ (unreachable)
+ )
+ (if (i32.const 0)
+ (block
+ (loop $out $in
+ (br_if $in (i32.const 1))
+ (unreachable)
+ )
+ (i32.const 10)
+ )
+ )
+ (if (i32.const 1)
+ (call $call-me (i32.const 123) (unreachable))
+ )
+ (if (i32.const 2)
+ (call $call-me (unreachable) (i32.const 0))
+ )
+ (if (i32.const 3)
+ (call $call-me (unreachable) (unreachable))
+ )
+ (if (i32.const -1)
+ (call_indirect $ii (i32.const 123) (i32.const 456) (unreachable))
+ )
+ (if (i32.const -2)
+ (call_indirect $ii (i32.const 139) (unreachable) (i32.const 0))
+ )
+ (if (i32.const -3)
+ (call_indirect $ii (i32.const 246) (unreachable) (unreachable))
+ )
+ (if (i32.const -4)
+ (call_indirect $ii (unreachable) (unreachable) (unreachable))
+ )
+ (if (i32.const 11)
+ (set_local $x (unreachable))
+ )
+ (if (i32.const 22)
+ (i32.load (unreachable))
+ )
+ (if (i32.const 33)
+ (i32.store (i32.const 0) (unreachable))
+ )
+ (if (i32.const 44)
+ (i32.store (unreachable) (i32.const 0))
+ )
+ (if (i32.const 55)
+ (i32.store (unreachable) (unreachable))
+ )
+ (if (i32.const 66)
+ (i32.eqz (unreachable))
+ )
+ (if (i32.const 77)
+ (i32.add (unreachable) (i32.const 0))
+ )
+ (if (i32.const 88)
+ (i32.add (i32.const 0) (unreachable))
+ )
+ (if (i32.const 99)
+ (i32.add (unreachable) (unreachable))
+ )
+ (if (i32.const 100)
+ (select (i32.const 123) (i32.const 456) (unreachable))
+ )
+ (if (i32.const 101)
+ (select (i32.const 123) (unreachable) (i32.const 456))
+ )
+ (if (i32.const 102)
+ (select (unreachable) (i32.const 123) (i32.const 456))
+ )
+ (i32.const 1337)
+ )
+)
+
diff --git a/test/two_sides.fromasm b/test/two_sides.fromasm
index 972f9819e..98ca149e1 100644
--- a/test/two_sides.fromasm
+++ b/test/two_sides.fromasm
@@ -8,57 +8,52 @@
(local $5 f64)
(if
(get_local $4)
- (return
- (call_import $f64-to-int
- (f64.mul
- (f64.add
+ (call_import $f64-to-int
+ (f64.mul
+ (f64.add
+ (f64.convert_s/i32
+ (get_local $2)
+ )
+ (set_local $5
(f64.convert_s/i32
- (get_local $2)
- )
- (set_local $5
- (f64.convert_s/i32
- (i32.mul
- (get_local $1)
- (get_local $0)
- )
+ (i32.mul
+ (get_local $1)
+ (get_local $0)
)
)
)
- (f64.add
- (get_local $5)
- (f64.convert_s/i32
- (get_local $3)
- )
+ )
+ (f64.add
+ (get_local $5)
+ (f64.convert_s/i32
+ (get_local $3)
)
)
)
)
- (return
- (call_import $f64-to-int
- (f64.mul
- (f64.add
+ (call_import $f64-to-int
+ (f64.mul
+ (f64.add
+ (f64.convert_s/i32
+ (get_local $2)
+ )
+ (set_local $5
(f64.convert_s/i32
- (get_local $2)
- )
- (set_local $5
- (f64.convert_s/i32
- (i32.mul
- (get_local $3)
- (get_local $2)
- )
+ (i32.mul
+ (get_local $3)
+ (get_local $2)
)
)
)
- (f64.add
- (f64.convert_s/i32
- (get_local $3)
- )
- (get_local $5)
+ )
+ (f64.add
+ (f64.convert_s/i32
+ (get_local $3)
)
+ (get_local $5)
)
)
)
)
- (i32.const 0)
)
)
diff --git a/test/two_sides.fromasm.imprecise b/test/two_sides.fromasm.imprecise
index bc6b7217d..ad7e9e61a 100644
--- a/test/two_sides.fromasm.imprecise
+++ b/test/two_sides.fromasm.imprecise
@@ -6,57 +6,52 @@
(local $5 f64)
(if
(get_local $4)
- (return
- (i32.trunc_s/f64
- (f64.mul
- (f64.add
+ (i32.trunc_s/f64
+ (f64.mul
+ (f64.add
+ (f64.convert_s/i32
+ (get_local $2)
+ )
+ (set_local $5
(f64.convert_s/i32
- (get_local $2)
- )
- (set_local $5
- (f64.convert_s/i32
- (i32.mul
- (get_local $1)
- (get_local $0)
- )
+ (i32.mul
+ (get_local $1)
+ (get_local $0)
)
)
)
- (f64.add
- (get_local $5)
- (f64.convert_s/i32
- (get_local $3)
- )
+ )
+ (f64.add
+ (get_local $5)
+ (f64.convert_s/i32
+ (get_local $3)
)
)
)
)
- (return
- (i32.trunc_s/f64
- (f64.mul
- (f64.add
+ (i32.trunc_s/f64
+ (f64.mul
+ (f64.add
+ (f64.convert_s/i32
+ (get_local $2)
+ )
+ (set_local $5
(f64.convert_s/i32
- (get_local $2)
- )
- (set_local $5
- (f64.convert_s/i32
- (i32.mul
- (get_local $3)
- (get_local $2)
- )
+ (i32.mul
+ (get_local $3)
+ (get_local $2)
)
)
)
- (f64.add
- (f64.convert_s/i32
- (get_local $3)
- )
- (get_local $5)
+ )
+ (f64.add
+ (f64.convert_s/i32
+ (get_local $3)
)
+ (get_local $5)
)
)
)
)
- (i32.const 0)
)
)