summaryrefslogtreecommitdiff
path: root/src/passes/SimplifyLocals.cpp
diff options
context:
space:
mode:
authorAlon Zakai <alonzakai@gmail.com>2016-04-12 09:54:53 -0700
committerAlon Zakai <alonzakai@gmail.com>2016-04-12 09:54:53 -0700
commitf2753329c4c647cc6950f62f944a39de06ab4c88 (patch)
tree434377c221ca936ddbcdc9b995263535964f65b6 /src/passes/SimplifyLocals.cpp
parent6302b75a023154bad7e11551e27d54bc35b415da (diff)
parent5da280167ac6f3e76d27c109ee08ae1747405b5c (diff)
downloadbinaryen-f2753329c4c647cc6950f62f944a39de06ab4c88.tar.gz
binaryen-f2753329c4c647cc6950f62f944a39de06ab4c88.tar.bz2
binaryen-f2753329c4c647cc6950f62f944a39de06ab4c88.zip
Merge pull request #341 from WebAssembly/opts
More optimization goodies
Diffstat (limited to 'src/passes/SimplifyLocals.cpp')
-rw-r--r--src/passes/SimplifyLocals.cpp64
1 files changed, 41 insertions, 23 deletions
diff --git a/src/passes/SimplifyLocals.cpp b/src/passes/SimplifyLocals.cpp
index 77e4f788a..408fea7ab 100644
--- a/src/passes/SimplifyLocals.cpp
+++ b/src/passes/SimplifyLocals.cpp
@@ -20,6 +20,10 @@
// This "sinks" set_locals, pushing them to the next get_local where possible,
// and removing the set if there are no gets remaining (the latter is
// particularly useful in ssa mode, but not only).
+//
+// After this pass, some locals may be completely unused. reorder-locals
+// can get rid of those (the operation is trivial there after it sorts by use
+// frequency).
#include <wasm.h>
#include <wasm-traversal.h>
@@ -41,6 +45,8 @@ struct SimplifyLocals : public WalkerPass<LinearExecutionWalker<SimplifyLocals>>
// locals in current linear execution trace, which we try to sink
std::map<Name, SinkableInfo> sinkables;
+ bool sunk;
+
// name => # of get_locals for it
std::map<Name, int> numGetLocals;
@@ -60,6 +66,7 @@ struct SimplifyLocals : public WalkerPass<LinearExecutionWalker<SimplifyLocals>>
*found->second.item = curr;
ExpressionManipulator::nop(curr);
sinkables.erase(found);
+ sunk = true;
} else {
numGetLocals[curr->name]++;
}
@@ -150,31 +157,42 @@ struct SimplifyLocals : public WalkerPass<LinearExecutionWalker<SimplifyLocals>>
self->pushTask(visitPre, currp);
}
- void visitFunction(Function *curr) {
- // after optimizing a function, we can see if we have set_locals
- // for a local with no remaining gets, in which case, we can
- // remove the set.
- std::vector<SetLocal*> optimizables;
- for (auto pair : setLocalOrigins) {
- SetLocal* curr = pair.first;
- if (numGetLocals[curr->name] == 0) {
- // no gets, can remove the set and leave just the value
- optimizables.push_back(curr);
+ void startWalk(Function *func) {
+ // multiple passes may be required per function, consider this:
+ // x = load
+ // y = store
+ // c(x, y)
+ // the load cannot cross the store, but y can be sunk, after which so can x
+ do {
+ sunk = false;
+ // main operation
+ walk(func->body);
+ // after optimizing a function, we can see if we have set_locals
+ // for a local with no remaining gets, in which case, we can
+ // remove the set.
+ std::vector<SetLocal*> optimizables;
+ for (auto pair : setLocalOrigins) {
+ SetLocal* curr = pair.first;
+ if (numGetLocals[curr->name] == 0) {
+ // no gets, can remove the set and leave just the value
+ optimizables.push_back(curr);
+ }
}
- }
- for (auto* curr : optimizables) {
- Expression** origin = setLocalOrigins[curr];
- *origin = curr->value;
- // nested set_values need to be handled properly.
- // consider (set_local x (set_local y (..)), where both can be
- // reduced to their values, and we might do it in either
- // order.
- if (curr->value->is<SetLocal>()) {
- setLocalOrigins[curr->value->cast<SetLocal>()] = origin;
+ for (auto* curr : optimizables) {
+ Expression** origin = setLocalOrigins[curr];
+ *origin = curr->value;
+ // nested set_values need to be handled properly.
+ // consider (set_local x (set_local y (..)), where both can be
+ // reduced to their values, and we might do it in either
+ // order.
+ if (curr->value->is<SetLocal>()) {
+ setLocalOrigins[curr->value->cast<SetLocal>()] = origin;
+ }
}
- }
- numGetLocals.clear();
- setLocalOrigins.clear();
+ // clean up
+ numGetLocals.clear();
+ setLocalOrigins.clear();
+ } while (sunk);
}
};