summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/passes/OptimizeInstructions.cpp8
-rw-r--r--src/passes/SimplifyLocals.cpp61
-rw-r--r--src/passes/pass.cpp9
-rw-r--r--src/passes/passes.h3
4 files changed, 64 insertions, 17 deletions
diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp
index 6ba34990f..1970cf08f 100644
--- a/src/passes/OptimizeInstructions.cpp
+++ b/src/passes/OptimizeInstructions.cpp
@@ -363,8 +363,12 @@ private:
}
}
} else if (auto* binary = boolean->dynCast<Binary>()) {
- // x != 0 is just x if it's used as a bool
- if (binary->op == NeInt32) {
+ if (binary->op == OrInt32) {
+ // an or flowing into a boolean context can consider each input as boolean
+ binary->left = optimizeBoolean(binary->left);
+ binary->right = optimizeBoolean(binary->right);
+ } else if (binary->op == NeInt32) {
+ // x != 0 is just x if it's used as a bool
if (auto* num = binary->right->dynCast<Const>()) {
if (num->value.geti32() == 0) {
return binary->left;
diff --git a/src/passes/SimplifyLocals.cpp b/src/passes/SimplifyLocals.cpp
index 7fef53dcc..6509c9da5 100644
--- a/src/passes/SimplifyLocals.cpp
+++ b/src/passes/SimplifyLocals.cpp
@@ -31,6 +31,15 @@
// 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).
+//
+// This pass has two main options:
+//
+// * Tee: allow teeing, i.e., sinking a local with more than one use,
+// and so after sinking we have a tee for the first use.
+// * Structure: create block and if return values, by merging the
+// internal set_locals into one on the outside,
+// that can itself then be sunk further.
+//
#include <wasm.h>
#include <wasm-builder.h>
@@ -64,7 +73,11 @@ struct SetLocalRemover : public PostWalker<SetLocalRemover, Visitor<SetLocalRemo
struct SimplifyLocals : public WalkerPass<LinearExecutionWalker<SimplifyLocals, Visitor<SimplifyLocals>>> {
bool isFunctionParallel() override { return true; }
- Pass* create() override { return new SimplifyLocals; }
+ Pass* create() override { return new SimplifyLocals(allowTee, allowStructure); }
+
+ bool allowTee, allowStructure;
+
+ SimplifyLocals(bool allowTee, bool allowStructure) : allowTee(allowTee), allowStructure(allowStructure) {}
// information for a set_local we can sink
struct SinkableInfo {
@@ -107,11 +120,11 @@ struct SimplifyLocals : public WalkerPass<LinearExecutionWalker<SimplifyLocals,
// whether we need to run an additional cycle
bool anotherCycle;
- // whether this is the first cycle
+ // whether this is the first cycle, in which we always disallow teeing
bool firstCycle;
// local => # of get_locals for it
- GetLocalCounter counter;
+ GetLocalCounter getCounter;
static void doNoteNonLinear(SimplifyLocals* self, Expression** currp) {
auto* curr = *currp;
@@ -156,7 +169,9 @@ struct SimplifyLocals : public WalkerPass<LinearExecutionWalker<SimplifyLocals,
// mere with the ifTrue side and optimize a return value, if possible
auto* iff = (*currp)->cast<If>();
assert(iff->ifFalse);
- self->optimizeIfReturn(iff, currp, self->ifStack.back());
+ if (self->allowStructure) {
+ self->optimizeIfReturn(iff, currp, self->ifStack.back());
+ }
self->ifStack.pop_back();
self->sinkables.clear();
}
@@ -164,7 +179,9 @@ struct SimplifyLocals : public WalkerPass<LinearExecutionWalker<SimplifyLocals,
void visitBlock(Block* curr) {
bool hasBreaks = curr->name.is() && blockBreaks[curr->name].size() > 0;
- optimizeBlockReturn(curr); // can modify blockBreaks
+ if (allowStructure) {
+ optimizeBlockReturn(curr); // can modify blockBreaks
+ }
// post-block cleanups
if (curr->name.is()) {
@@ -186,9 +203,7 @@ struct SimplifyLocals : public WalkerPass<LinearExecutionWalker<SimplifyLocals,
if (found != sinkables.end()) {
// sink it, and nop the origin
auto* set = (*found->second.item)->cast<SetLocal>();
- if (firstCycle) {
- // just one get_local of this, so just sink the value
- assert(counter.num[curr->index] == 1);
+ if (firstCycle || getCounter.num[curr->index] == 1) {
replaceCurrent(set->value);
} else {
replaceCurrent(set);
@@ -264,7 +279,7 @@ struct SimplifyLocals : public WalkerPass<LinearExecutionWalker<SimplifyLocals,
self->checkInvalidations(effects);
}
- if (set && !set->isTee() && (!self->firstCycle || self->counter.num[set->index] == 1)) {
+ if (set && self->canSink(set)) {
Index index = set->index;
assert(self->sinkables.count(index) == 0);
self->sinkables.emplace(std::make_pair(index, SinkableInfo(currp)));
@@ -273,6 +288,14 @@ struct SimplifyLocals : public WalkerPass<LinearExecutionWalker<SimplifyLocals,
self->expressionStack.pop_back();
}
+ bool canSink(SetLocal* set) {
+ // we can never move a tee
+ if (set->isTee()) return false;
+ // if in the first cycle, or not allowing tees, then we cannot sink if >1 use as that would make a tee
+ if ((firstCycle || !allowTee) && getCounter.num[set->index] > 1) return false;
+ return true;
+ }
+
std::vector<Block*> blocksToEnlarge;
std::vector<If*> ifsToEnlarge;
@@ -415,7 +438,7 @@ struct SimplifyLocals : public WalkerPass<LinearExecutionWalker<SimplifyLocals,
void doWalkFunction(Function* func) {
// scan get_locals
- counter.analyze(func);
+ getCounter.analyze(func);
// multiple passes may be required per function, consider this:
// x = load
// y = store
@@ -468,16 +491,28 @@ struct SimplifyLocals : public WalkerPass<LinearExecutionWalker<SimplifyLocals,
// for a local with no remaining gets, in which case, we can
// remove the set.
// First, recount get_locals
- counter.analyze(func);
+ getCounter.analyze(func);
// Second, remove unneeded sets
SetLocalRemover remover;
- remover.numGetLocals = &counter.num;
+ remover.numGetLocals = &getCounter.num;
remover.walkFunction(func);
}
};
Pass *createSimplifyLocalsPass() {
- return new SimplifyLocals();
+ return new SimplifyLocals(true, true);
+}
+
+Pass *createSimplifyLocalsNoTeePass() {
+ return new SimplifyLocals(false, true);
+}
+
+Pass *createSimplifyLocalsNoStructurePass() {
+ return new SimplifyLocals(true, false);
+}
+
+Pass *createSimplifyLocalsNoTeeNoStructurePass() {
+ return new SimplifyLocals(false, false);
}
} // namespace wasm
diff --git a/src/passes/pass.cpp b/src/passes/pass.cpp
index c307fea46..20e002f4b 100644
--- a/src/passes/pass.cpp
+++ b/src/passes/pass.cpp
@@ -91,6 +91,9 @@ void PassRegistry::registerPasses() {
registerPass("reorder-functions", "sorts functions by access frequency", createReorderFunctionsPass);
registerPass("reorder-locals", "sorts locals by access frequency", createReorderLocalsPass);
registerPass("simplify-locals", "miscellaneous locals-related optimizations", createSimplifyLocalsPass);
+ registerPass("simplify-locals-notee", "miscellaneous locals-related optimizations", createSimplifyLocalsNoTeePass);
+ registerPass("simplify-locals-nostructure", "miscellaneous locals-related optimizations", createSimplifyLocalsNoStructurePass);
+ registerPass("simplify-locals-notee-nostructure", "miscellaneous locals-related optimizations", createSimplifyLocalsNoTeeNoStructurePass);
registerPass("vacuum", "removes obviously unneeded code", createVacuumPass);
registerPass("precompute", "computes compile-time evaluatable expressions", createPrecomputePass);
// registerPass("lower-i64", "lowers i64 into pairs of i32s", createLowerInt64Pass);
@@ -113,13 +116,15 @@ void PassRunner::addDefaultFunctionOptimizationPasses() {
if (options.optimizeLevel >= 2 || options.shrinkLevel >= 2) {
add("code-pushing");
}
- add("simplify-locals");
+ add("simplify-locals-nostructure"); // don't create if/block return values yet, as coalesce can remove copies that that could inhibit
add("vacuum"); // previous pass creates garbage
add("reorder-locals");
- add("remove-unused-brs"); // simplify-locals opens opportunities for phi optimizations
+ add("remove-unused-brs"); // simplify-locals opens opportunities for optimizations
add("coalesce-locals");
+ add("simplify-locals");
add("vacuum"); // previous pass creates garbage
add("reorder-locals");
+ add("remove-unused-brs"); // coalesce-locals opens opportunities for optimizations
add("merge-blocks");
add("optimize-instructions");
add("precompute");
diff --git a/src/passes/passes.h b/src/passes/passes.h
index c71831e73..98f99654e 100644
--- a/src/passes/passes.h
+++ b/src/passes/passes.h
@@ -51,6 +51,9 @@ Pass *createRemoveUnusedNamesPass();
Pass *createReorderFunctionsPass();
Pass *createReorderLocalsPass();
Pass *createSimplifyLocalsPass();
+Pass *createSimplifyLocalsNoTeePass();
+Pass *createSimplifyLocalsNoStructurePass();
+Pass *createSimplifyLocalsNoTeeNoStructurePass();
Pass *createVacuumPass();
Pass *createPrecomputePass();
//Pass *createLowerInt64Pass();