diff options
author | Alon Zakai <alonzakai@gmail.com> | 2016-04-11 19:43:58 -0700 |
---|---|---|
committer | Alon Zakai <alonzakai@gmail.com> | 2016-04-11 19:43:58 -0700 |
commit | 73c606a04d01dc7018d028eed3216a507ab03ee9 (patch) | |
tree | bf4255d2fead5fdf721ea178607abfc408cd6ac8 /src/passes/SimplifyLocals.cpp | |
parent | 65d9334b3066bae667e729f3202f7aa2d7c11530 (diff) | |
parent | 1044d6cbca6d279d457cdd1cf7000671ec48e841 (diff) | |
download | binaryen-73c606a04d01dc7018d028eed3216a507ab03ee9.tar.gz binaryen-73c606a04d01dc7018d028eed3216a507ab03ee9.tar.bz2 binaryen-73c606a04d01dc7018d028eed3216a507ab03ee9.zip |
Merge pull request #334 from WebAssembly/opts2
More optimizations
Diffstat (limited to 'src/passes/SimplifyLocals.cpp')
-rw-r--r-- | src/passes/SimplifyLocals.cpp | 57 |
1 files changed, 52 insertions, 5 deletions
diff --git a/src/passes/SimplifyLocals.cpp b/src/passes/SimplifyLocals.cpp index 53e77eb22..77e4f788a 100644 --- a/src/passes/SimplifyLocals.cpp +++ b/src/passes/SimplifyLocals.cpp @@ -17,7 +17,9 @@ // // Locals-related optimizations // -// This "sinks" set_locals, pushing them to the next get_local where possible +// 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). #include <wasm.h> #include <wasm-traversal.h> @@ -39,6 +41,12 @@ struct SimplifyLocals : public WalkerPass<LinearExecutionWalker<SimplifyLocals>> // locals in current linear execution trace, which we try to sink std::map<Name, SinkableInfo> sinkables; + // name => # of get_locals for it + std::map<Name, int> numGetLocals; + + // for each set_local, its origin pointer + std::map<SetLocal*, Expression**> setLocalOrigins; + void noteNonLinear() { sinkables.clear(); } @@ -52,6 +60,8 @@ struct SimplifyLocals : public WalkerPass<LinearExecutionWalker<SimplifyLocals>> *found->second.item = curr; ExpressionManipulator::nop(curr); sinkables.erase(found); + } else { + numGetLocals[curr->name]++; } } @@ -79,21 +89,32 @@ struct SimplifyLocals : public WalkerPass<LinearExecutionWalker<SimplifyLocals>> } static void visitPre(SimplifyLocals* self, Expression** currp) { + Expression* curr = *currp; + EffectAnalyzer effects; - if (effects.checkPre(*currp)) { + if (effects.checkPre(curr)) { self->checkInvalidations(effects); } } static void visitPost(SimplifyLocals* self, Expression** currp) { + Expression* curr = *currp; + EffectAnalyzer effects; - if (effects.checkPost(*currp)) { + if (effects.checkPost(curr)) { self->checkInvalidations(effects); } + + // noting origins in the post means it happens after a + // get_local was replaced by a set_local in a sinking + // operation, so we track those movements properly. + if (curr->is<SetLocal>()) { + self->setLocalOrigins[curr->cast<SetLocal>()] = currp; + } } static void tryMarkSinkable(SimplifyLocals* self, Expression** currp) { - auto* curr = (*currp)->dyn_cast<SetLocal>(); + auto* curr = (*currp)->dynCast<SetLocal>(); if (curr) { Name name = curr->name; assert(self->sinkables.count(name) == 0); @@ -107,7 +128,6 @@ struct SimplifyLocals : public WalkerPass<LinearExecutionWalker<SimplifyLocals>> auto* curr = *currp; - if (curr->is<Block>()) { // special-case blocks, by marking their children as locals. // TODO sink from elsewhere? (need to make sure value is not used) @@ -129,6 +149,33 @@ 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); + } + } + 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(); + } }; static RegisterPass<SimplifyLocals> registerPass("simplify-locals", "miscellaneous locals-related optimizations"); |