diff options
author | Alon Zakai <alonzakai@gmail.com> | 2016-07-20 20:05:28 -0700 |
---|---|---|
committer | Alon Zakai <alonzakai@gmail.com> | 2016-07-20 20:05:28 -0700 |
commit | fa60ade30e03c6a13bbce26ff81c03ed1ae4da0b (patch) | |
tree | d45b2b08645ac004645dde875d22d1c66b15187d /src | |
parent | 56901f8cb6fb6db4622937479d3a375744289ff0 (diff) | |
download | binaryen-fa60ade30e03c6a13bbce26ff81c03ed1ae4da0b.tar.gz binaryen-fa60ade30e03c6a13bbce26ff81c03ed1ae4da0b.tar.bz2 binaryen-fa60ade30e03c6a13bbce26ff81c03ed1ae4da0b.zip |
more RemoveUnusedName opts: merge names when possible, and do block/loop merging based on their names
Diffstat (limited to 'src')
-rw-r--r-- | src/passes/RemoveUnusedNames.cpp | 47 |
1 files changed, 42 insertions, 5 deletions
diff --git a/src/passes/RemoveUnusedNames.cpp b/src/passes/RemoveUnusedNames.cpp index 5145cc744..9c6743479 100644 --- a/src/passes/RemoveUnusedNames.cpp +++ b/src/passes/RemoveUnusedNames.cpp @@ -15,7 +15,8 @@ */ // -// Removes names from locations that are never branched to. +// Removes names from locations that are never branched to, and +// merge names when possible (by merging their blocks) // #include <wasm.h> @@ -30,17 +31,17 @@ struct RemoveUnusedNames : public WalkerPass<PostWalker<RemoveUnusedNames, Visit // We maintain a list of branches that we saw in children, then when we reach // a parent block, we know if it was branched to - std::set<Name> branchesSeen; + std::map<Name, std::set<Expression*>> branchesSeen; void visitBreak(Break *curr) { - branchesSeen.insert(curr->name); + branchesSeen[curr->name].insert(curr); } void visitSwitch(Switch *curr) { for (auto name : curr->targets) { - branchesSeen.insert(name); + branchesSeen[name].insert(curr); } - branchesSeen.insert(curr->default_); + branchesSeen[curr->default_].insert(curr); } void handleBreakTarget(Name& name) { @@ -54,7 +55,35 @@ struct RemoveUnusedNames : public WalkerPass<PostWalker<RemoveUnusedNames, Visit } void visitBlock(Block *curr) { + if (curr->name.is() && curr->list.size() == 1) { + auto* child = curr->list[0]->dynCast<Block>(); + if (child && child->name.is()) { + // we have just one child, this block, so breaking out of it goes to the same place as breaking out of us, we just need one name (and block) + auto& branches = branchesSeen[curr->name]; + for (auto* branch : branches) { + if (Break* br = branch->dynCast<Break>()) { + if (br->name == curr->name) br->name = child->name; + } else if (Switch* sw = branch->dynCast<Switch>()) { + for (auto& target : sw->targets) { + if (target == curr->name) target = child->name; + } + if (sw->default_ == curr->name) sw->default_ = child->name; + } else { + WASM_UNREACHABLE(); + } + } + replaceCurrent(child); + } + } handleBreakTarget(curr->name); + if (curr->name.is() && curr->list.size() == 1) { + auto* child = curr->list[0]->dynCast<Loop>(); + if (child && !child->out.is()) { + // we have just one child, this loop, and it lacks an out label. So this block's name is doing just that! + child->out = curr->name; + replaceCurrent(child); + } + } } void visitLoop(Loop *curr) { @@ -68,6 +97,14 @@ struct RemoveUnusedNames : public WalkerPass<PostWalker<RemoveUnusedNames, Visit block->list.push_back(curr->body); replaceCurrent(block); } + if (curr->in.is() && !curr->out.is()) { + auto* child = curr->body->dynCast<Block>(); + if (child && child->name.is()) { + // we have just one child, this block, and we lack an out label. So we can take the block's! + curr->out = child->name; + child->name = Name(); + } + } } void visitFunction(Function *curr) { |