diff options
author | Alon Zakai <alonzakai@gmail.com> | 2016-05-22 21:23:18 -0700 |
---|---|---|
committer | Alon Zakai <alonzakai@gmail.com> | 2016-05-22 21:23:18 -0700 |
commit | f5aad6d1614ca32e7ade296dc9bce8c7c74d3f63 (patch) | |
tree | 140fde94e420070c2461fa1541f0ab9b53af8077 | |
parent | 5d16d4b3b344aa1dbe07deff0d282adea6f8c369 (diff) | |
download | binaryen-f5aad6d1614ca32e7ade296dc9bce8c7c74d3f63.tar.gz binaryen-f5aad6d1614ca32e7ade296dc9bce8c7c74d3f63.tar.bz2 binaryen-f5aad6d1614ca32e7ade296dc9bce8c7c74d3f63.zip |
dead code elimination pass (#536)
-rw-r--r-- | src/passes/CMakeLists.txt | 1 | ||||
-rw-r--r-- | src/passes/DeadCodeElimination.cpp | 351 | ||||
-rw-r--r-- | src/passes/pass.cpp | 1 | ||||
-rw-r--r-- | test/emcc_hello_world.fromasm | 577 | ||||
-rw-r--r-- | test/emcc_hello_world.fromasm.imprecise | 577 | ||||
-rw-r--r-- | test/passes/dce.txt | 239 | ||||
-rw-r--r-- | test/passes/dce.wast | 197 | ||||
-rw-r--r-- | test/two_sides.fromasm | 65 | ||||
-rw-r--r-- | test/two_sides.fromasm.imprecise | 65 |
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) ) ) |