diff options
author | Alon Zakai <alonzakai@gmail.com> | 2016-04-25 15:48:07 -0700 |
---|---|---|
committer | Alon Zakai <alonzakai@gmail.com> | 2016-04-25 15:48:07 -0700 |
commit | b48cfe91be0381a049a413e1c6d7d1ba83514a95 (patch) | |
tree | 3362195f3170f943d8d35db6b2afbde99f51ec6d /src | |
parent | 27ef6de772ca90824018819b91b8a230136f56c3 (diff) | |
download | binaryen-b48cfe91be0381a049a413e1c6d7d1ba83514a95.tar.gz binaryen-b48cfe91be0381a049a413e1c6d7d1ba83514a95.tar.bz2 binaryen-b48cfe91be0381a049a413e1c6d7d1ba83514a95.zip |
optimize breaks with values in RemoveUnusedBrs, check if their value can flow to the target anyhow
Diffstat (limited to 'src')
-rw-r--r-- | src/passes/RemoveUnusedBrs.cpp | 46 |
1 files changed, 32 insertions, 14 deletions
diff --git a/src/passes/RemoveUnusedBrs.cpp b/src/passes/RemoveUnusedBrs.cpp index 3d6d6973f..58c765d83 100644 --- a/src/passes/RemoveUnusedBrs.cpp +++ b/src/passes/RemoveUnusedBrs.cpp @@ -29,7 +29,11 @@ struct RemoveUnusedBrs : public WalkerPass<PostWalker<RemoveUnusedBrs, Visitor<R bool anotherCycle; - typedef std::vector<Break*> Flows; + // Whether a value can flow in the current path. If so, then a br with value + // can be turned into a value, which will flow through blocks/ifs to the right place + bool valueCanFlow; + + typedef std::vector<Expression**> Flows; // list of breaks that are currently flowing. if they reach their target without // interference, they can be removed (or their value forwarded TODO) @@ -45,12 +49,13 @@ struct RemoveUnusedBrs : public WalkerPass<PostWalker<RemoveUnusedBrs, Visitor<R if (curr->is<Break>()) { flows.clear(); auto* br = curr->cast<Break>(); - if (!br->condition && !br->value) { // TODO: optimize in those cases? + if (!br->condition) { // TODO: optimize? // a break, let's see where it flows to - flows.push_back(br); + flows.push_back(currp); + self->valueCanFlow = true; // start optimistic + } else { + self->valueCanFlow = false; } - } else if (curr->is<Switch>()) { - flows.clear(); } else if (curr->is<If>()) { auto* iff = curr->cast<If>(); if (iff->ifFalse) { @@ -62,15 +67,25 @@ struct RemoveUnusedBrs : public WalkerPass<PostWalker<RemoveUnusedBrs, Visitor<R } } else if (curr->is<Block>()) { // any breaks flowing to here are unnecessary, as we get here anyhow - auto name = curr->cast<Block>()->name; + auto* block = curr->cast<Block>(); + auto name = block->name; if (name.is()) { size_t size = flows.size(); size_t skip = 0; for (size_t i = 0; i < size; i++) { - if (flows[i]->name == name) { - ExpressionManipulator::nop(flows[i]); - skip++; - self->anotherCycle = true; + auto* flow = (*flows[i])->cast<Break>(); + if (flow->name == name) { + if (!flow->value || self->valueCanFlow) { + if (!flow->value) { + // br => nop + ExpressionManipulator::nop(flow); + } else { + // br with value => value + *flows[i] = flow->value; + } + skip++; + self->anotherCycle = true; + } } else if (skip > 0) { flows[i - skip] = flows[i]; } @@ -78,15 +93,18 @@ struct RemoveUnusedBrs : public WalkerPass<PostWalker<RemoveUnusedBrs, Visitor<R if (skip > 0) { flows.resize(size - skip); } + // drop a nop at the end of a block, which prevents a value flowing + while (block->list.size() > 0 && block->list.back()->is<Nop>()) { + block->list.resize(block->list.size() - 1); + } } - } else if (curr->is<Loop>()) { - // TODO we might optimize branches out of here - flows.clear(); } else if (curr->is<Nop>()) { // ignore (could be result of a previous cycle) + self->valueCanFlow = false; } else { - // anything else stops the flow + // anything else stops the flow TODO: optimize loops? flows.clear(); + self->valueCanFlow = false; } } |