diff options
author | Alon Zakai <alonzakai@gmail.com> | 2017-05-02 13:46:53 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-05-02 13:46:53 -0700 |
commit | 5de55af88eaac818f86eaaec3f686eaede01397e (patch) | |
tree | ed896c1336272efa7e191e3675f883ad85ae3a6f /src/passes/DeadCodeElimination.cpp | |
parent | 1f1018564c472b75335bf4bddbf65cfebb226fb0 (diff) | |
download | binaryen-5de55af88eaac818f86eaaec3f686eaede01397e.tar.gz binaryen-5de55af88eaac818f86eaaec3f686eaede01397e.tar.bz2 binaryen-5de55af88eaac818f86eaaec3f686eaede01397e.zip |
improve dce to handle more cases of nested unreachable code (#989)
* improve dce to handle more cases of nested unreachable code, in particular, when the child is unreachable in type but not an actual Unreachable node, e.g. if it's a br. in that case, we just need to verify that the br is not to us where we are a block or loop
* handle unreachable switch conditions in dce
* handle dce of br condition which is unreachable, and host arguments
* handle dce of block i32 etc. which is actually unreachable
Diffstat (limited to 'src/passes/DeadCodeElimination.cpp')
-rw-r--r-- | src/passes/DeadCodeElimination.cpp | 48 |
1 files changed, 41 insertions, 7 deletions
diff --git a/src/passes/DeadCodeElimination.cpp b/src/passes/DeadCodeElimination.cpp index 41012fccb..33a52a09a 100644 --- a/src/passes/DeadCodeElimination.cpp +++ b/src/passes/DeadCodeElimination.cpp @@ -51,12 +51,20 @@ struct DeadCodeElimination : public WalkerPass<PostWalker<DeadCodeElimination>> std::set<Name> reachableBreaks; void addBreak(Name name) { - assert(reachable); - reachableBreaks.insert(name); + // we normally have already reduced unreachable code into (unreachable) + // nodes, so we would not get to this function at all anyhow, the breaking + // instruction itself would be removed. However, an exception are things + // like (block i32 (call $x) (unreachable)) , which has type i32 + // despite not being exited. + // TODO: optimize such cases + if (reachable) { + reachableBreaks.insert(name); + } } - bool isDead(Expression* curr) { - return curr && curr->is<Unreachable>(); + // if a child is unreachable, we can replace ourselves with it + bool isDead(Expression* child) { + return child && child->type == unreachable; } // things that stop control flow @@ -67,6 +75,19 @@ struct DeadCodeElimination : public WalkerPass<PostWalker<DeadCodeElimination>> replaceCurrent(curr->value); return; } + if (isDead(curr->condition)) { + if (curr->value) { + auto* block = getModule()->allocator.alloc<Block>(); + block->list.resize(2); + block->list[0] = drop(curr->value); + block->list[1] = curr->condition; + block->finalize(); + replaceCurrent(block); + } else { + replaceCurrent(curr->condition); + } + return; + } addBreak(curr->name); if (!curr->condition) { reachable = false; @@ -78,6 +99,19 @@ struct DeadCodeElimination : public WalkerPass<PostWalker<DeadCodeElimination>> replaceCurrent(curr->value); return; } + if (isDead(curr->condition)) { + if (curr->value) { + auto* block = getModule()->allocator.alloc<Block>(); + block->list.resize(2); + block->list[0] = drop(curr->value); + block->list[1] = curr->condition; + block->finalize(); + replaceCurrent(block); + } else { + replaceCurrent(curr->condition); + } + return; + } for (auto target : curr->targets) { addBreak(target); } @@ -137,7 +171,7 @@ struct DeadCodeElimination : public WalkerPass<PostWalker<DeadCodeElimination>> reachable = reachable || reachableBreaks.count(curr->name); reachableBreaks.erase(curr->name); } - if (curr->list.size() == 1 && isDead(curr->list[0])) { + if (curr->list.size() == 1 && isDead(curr->list[0]) && !BreakSeeker::has(curr->list[0], curr->name)) { replaceCurrent(curr->list[0]); } } @@ -146,7 +180,7 @@ struct DeadCodeElimination : public WalkerPass<PostWalker<DeadCodeElimination>> if (curr->name.is()) { reachableBreaks.erase(curr->name); } - if (isDead(curr->body)) { + if (isDead(curr->body) && !BreakSeeker::has(curr->body, curr->name)) { replaceCurrent(curr->body); return; } @@ -360,7 +394,7 @@ struct DeadCodeElimination : public WalkerPass<PostWalker<DeadCodeElimination>> } void visitHost(Host* curr) { - // TODO + handleCall(curr); } void visitFunction(Function* curr) { |