summaryrefslogtreecommitdiff
path: root/src/passes/SimplifyLocals.cpp
diff options
context:
space:
mode:
authorAlon Zakai <alonzakai@gmail.com>2016-04-11 20:27:35 -0700
committerAlon Zakai <alonzakai@gmail.com>2016-04-11 20:40:12 -0700
commit3c961d1383629e9907bc8d4c5b6f1f566d13a3f2 (patch)
tree5fa0079a54f37791a1694e6612a67d645a925bf7 /src/passes/SimplifyLocals.cpp
parentcfa616dffc11e82390070315cc2e4635e42c437e (diff)
downloadbinaryen-3c961d1383629e9907bc8d4c5b6f1f566d13a3f2.tar.gz
binaryen-3c961d1383629e9907bc8d4c5b6f1f566d13a3f2.tar.bz2
binaryen-3c961d1383629e9907bc8d4c5b6f1f566d13a3f2.zip
continue simplifying locals while opportunities present themselves
Diffstat (limited to 'src/passes/SimplifyLocals.cpp')
-rw-r--r--src/passes/SimplifyLocals.cpp60
1 files changed, 37 insertions, 23 deletions
diff --git a/src/passes/SimplifyLocals.cpp b/src/passes/SimplifyLocals.cpp
index 77e4f788a..faf6e3a6e 100644
--- a/src/passes/SimplifyLocals.cpp
+++ b/src/passes/SimplifyLocals.cpp
@@ -41,6 +41,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 +62,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 +153,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);
}
};