summaryrefslogtreecommitdiff
path: root/src/passes
diff options
context:
space:
mode:
Diffstat (limited to 'src/passes')
-rw-r--r--src/passes/CodePushing.cpp19
-rw-r--r--src/passes/MergeBlocks.cpp10
-rw-r--r--src/passes/OptimizeInstructions.cpp8
-rw-r--r--src/passes/RemoveUnusedBrs.cpp27
-rw-r--r--src/passes/SimplifyLocals.cpp10
-rw-r--r--src/passes/Vacuum.cpp24
6 files changed, 52 insertions, 46 deletions
diff --git a/src/passes/CodePushing.cpp b/src/passes/CodePushing.cpp
index f4beff1a8..55b15ac9d 100644
--- a/src/passes/CodePushing.cpp
+++ b/src/passes/CodePushing.cpp
@@ -83,9 +83,10 @@ class Pusher {
ExpressionList& list;
LocalAnalyzer& analyzer;
std::vector<Index>& numGetsSoFar;
+ PassOptions& passOptions;
public:
- Pusher(Block* block, LocalAnalyzer& analyzer, std::vector<Index>& numGetsSoFar) : list(block->list), analyzer(analyzer), numGetsSoFar(numGetsSoFar) {
+ Pusher(Block* block, LocalAnalyzer& analyzer, std::vector<Index>& numGetsSoFar, PassOptions& passOptions) : list(block->list), analyzer(analyzer), numGetsSoFar(numGetsSoFar), passOptions(passOptions) {
// Find an optimization segment: from the first pushable thing, to the first
// point past which we want to push. We then push in that range before
// continuing forward.
@@ -119,7 +120,7 @@ private:
// but also have no side effects, as it may not execute if pushed.
if (analyzer.isSFA(index) &&
numGetsSoFar[index] == analyzer.getNumGets(index) &&
- !EffectAnalyzer(set->value).hasSideEffects()) {
+ !EffectAnalyzer(passOptions, set->value).hasSideEffects()) {
return set;
}
return nullptr;
@@ -146,8 +147,8 @@ private:
// of earlier ones. Once we know all we can push, we push it all
// in one pass, keeping the order of the pushables intact.
assert(firstPushable != Index(-1) && pushPoint != Index(-1) && firstPushable < pushPoint);
- EffectAnalyzer cumulativeEffects; // everything that matters if you want
- // to be pushed past the pushPoint
+ EffectAnalyzer cumulativeEffects(passOptions); // everything that matters if you want
+ // to be pushed past the pushPoint
cumulativeEffects.analyze(list[pushPoint]);
cumulativeEffects.branches = false; // it is ok to ignore the branching here,
// that is the crucial point of this opt
@@ -158,9 +159,13 @@ private:
if (pushable) {
auto iter = pushableEffects.find(pushable);
if (iter == pushableEffects.end()) {
- pushableEffects.emplace(pushable, pushable);
+ iter = pushableEffects.emplace(
+ std::piecewise_construct,
+ std::forward_as_tuple(pushable),
+ std::forward_as_tuple(passOptions, pushable)
+ ).first;
}
- auto& effects = pushableEffects[pushable];
+ auto& effects = iter->second;
if (cumulativeEffects.invalidates(effects)) {
// we can't push this, so further pushables must pass it
cumulativeEffects.mergeIn(effects);
@@ -248,7 +253,7 @@ struct CodePushing : public WalkerPass<PostWalker<CodePushing, Visitor<CodePushi
// ordering invalidation issue, since if this isn't a loop, it's fine (we're not
// used outside), and if it is, we hit the assign before any use (as we can't
// push it past a use).
- Pusher pusher(curr, analyzer, numGetsSoFar);
+ Pusher pusher(curr, analyzer, numGetsSoFar, getPassOptions());
}
};
diff --git a/src/passes/MergeBlocks.cpp b/src/passes/MergeBlocks.cpp
index 383837beb..f8d044212 100644
--- a/src/passes/MergeBlocks.cpp
+++ b/src/passes/MergeBlocks.cpp
@@ -216,9 +216,9 @@ struct MergeBlocks : public WalkerPass<PostWalker<MergeBlocks, Visitor<MergeBloc
if (!child) return outer;
if ((dependency1 && *dependency1) || (dependency2 && *dependency2)) {
// there are dependencies, things we must be reordered through. make sure no problems there
- EffectAnalyzer childEffects(child);
- if (dependency1 && *dependency1 && EffectAnalyzer(*dependency1).invalidates(childEffects)) return outer;
- if (dependency2 && *dependency2 && EffectAnalyzer(*dependency2).invalidates(childEffects)) return outer;
+ EffectAnalyzer childEffects(getPassOptions(), child);
+ if (dependency1 && *dependency1 && EffectAnalyzer(getPassOptions(), *dependency1).invalidates(childEffects)) return outer;
+ if (dependency2 && *dependency2 && EffectAnalyzer(getPassOptions(), *dependency2).invalidates(childEffects)) return outer;
}
if (auto* block = child->dynCast<Block>()) {
if (!block->name.is() && block->list.size() >= 2) {
@@ -278,7 +278,7 @@ struct MergeBlocks : public WalkerPass<PostWalker<MergeBlocks, Visitor<MergeBloc
void handleCall(T* curr, Block* outer = nullptr) {
for (Index i = 0; i < curr->operands.size(); i++) {
outer = optimize(curr, curr->operands[i], outer);
- if (EffectAnalyzer(curr->operands[i]).hasSideEffects()) return;
+ if (EffectAnalyzer(getPassOptions(), curr->operands[i]).hasSideEffects()) return;
}
}
@@ -292,7 +292,7 @@ struct MergeBlocks : public WalkerPass<PostWalker<MergeBlocks, Visitor<MergeBloc
void visitCallIndirect(CallIndirect* curr) {
auto* outer = optimize(curr, curr->target);
- if (EffectAnalyzer(curr->target).hasSideEffects()) return;
+ if (EffectAnalyzer(getPassOptions(), curr->target).hasSideEffects()) return;
handleCall(curr, outer);
}
};
diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp
index 5c1aa5fc3..f94285930 100644
--- a/src/passes/OptimizeInstructions.cpp
+++ b/src/passes/OptimizeInstructions.cpp
@@ -317,8 +317,8 @@ struct OptimizeInstructions : public WalkerPass<PostWalker<OptimizeInstructions,
auto* condition = select->condition->dynCast<Unary>();
if (condition && condition->op == EqZInt32) {
// flip select to remove eqz, if we can reorder
- EffectAnalyzer ifTrue(select->ifTrue);
- EffectAnalyzer ifFalse(select->ifFalse);
+ EffectAnalyzer ifTrue(getPassOptions(), select->ifTrue);
+ EffectAnalyzer ifFalse(getPassOptions(), select->ifFalse);
if (!ifTrue.invalidates(ifFalse)) {
select->condition = condition->value;
std::swap(select->ifTrue, select->ifFalse);
@@ -408,8 +408,8 @@ private:
auto* left = binary->left;
auto* right = binary->right;
if (!Properties::emitsBoolean(left) || !Properties::emitsBoolean(right)) return nullptr;
- auto leftEffects = EffectAnalyzer(left).hasSideEffects();
- auto rightEffects = EffectAnalyzer(right).hasSideEffects();
+ auto leftEffects = EffectAnalyzer(getPassOptions(), left).hasSideEffects();
+ auto rightEffects = EffectAnalyzer(getPassOptions(), right).hasSideEffects();
if (leftEffects && rightEffects) return nullptr; // both must execute
// canonicalize with side effects, if any, happening on the left
if (rightEffects) {
diff --git a/src/passes/RemoveUnusedBrs.cpp b/src/passes/RemoveUnusedBrs.cpp
index 69a7c4ff1..b4b188416 100644
--- a/src/passes/RemoveUnusedBrs.cpp
+++ b/src/passes/RemoveUnusedBrs.cpp
@@ -28,11 +28,11 @@ namespace wasm {
// to turn an if into a br-if, we must be able to reorder the
// condition and possible value, and the possible value must
// not have side effects (as they would run unconditionally)
-static bool canTurnIfIntoBrIf(Expression* ifCondition, Expression* brValue) {
+static bool canTurnIfIntoBrIf(Expression* ifCondition, Expression* brValue, PassOptions& options) {
if (!brValue) return true;
- EffectAnalyzer value(brValue);
+ EffectAnalyzer value(options, brValue);
if (value.hasSideEffects()) return false;
- return !EffectAnalyzer(ifCondition).invalidates(value);
+ return !EffectAnalyzer(options, ifCondition).invalidates(value);
}
struct RemoveUnusedBrs : public WalkerPass<PostWalker<RemoveUnusedBrs, Visitor<RemoveUnusedBrs>>> {
@@ -146,7 +146,7 @@ struct RemoveUnusedBrs : public WalkerPass<PostWalker<RemoveUnusedBrs, Visitor<R
// if without an else. try to reduce if (condition) br => br_if (condition)
Break* br = curr->ifTrue->dynCast<Break>();
if (br && !br->condition) { // TODO: if there is a condition, join them
- if (canTurnIfIntoBrIf(curr->condition, br->value)) {
+ if (canTurnIfIntoBrIf(curr->condition, br->value, getPassOptions())) {
br->condition = curr->condition;
br->finalize();
replaceCurrent(Builder(*getModule()).dropIfConcretelyTyped(br));
@@ -263,7 +263,7 @@ struct RemoveUnusedBrs : public WalkerPass<PostWalker<RemoveUnusedBrs, Visitor<R
return false;
}
// if there is control flow, we must stop looking
- if (EffectAnalyzer(curr).branches) {
+ if (EffectAnalyzer(getPassOptions(), curr).branches) {
return false;
}
if (i == 0) return false;
@@ -394,6 +394,9 @@ struct RemoveUnusedBrs : public WalkerPass<PostWalker<RemoveUnusedBrs, Visitor<R
// perform some final optimizations
struct FinalOptimizer : public PostWalker<FinalOptimizer, Visitor<FinalOptimizer>> {
bool selectify;
+ PassOptions& passOptions;
+
+ FinalOptimizer(PassOptions& passOptions) : passOptions(passOptions) {}
void visitBlock(Block* curr) {
// if a block has an if br else br, we can un-conditionalize the latter, allowing
@@ -406,7 +409,7 @@ struct RemoveUnusedBrs : public WalkerPass<PostWalker<RemoveUnusedBrs, Visitor<R
auto* iff = list[i]->dynCast<If>();
if (!iff || !iff->ifFalse || isConcreteWasmType(iff->type)) continue; // if it lacked an if-false, it would already be a br_if, as that's the easy case
auto* ifTrueBreak = iff->ifTrue->dynCast<Break>();
- if (ifTrueBreak && !ifTrueBreak->condition && canTurnIfIntoBrIf(iff->condition, ifTrueBreak->value)) {
+ if (ifTrueBreak && !ifTrueBreak->condition && canTurnIfIntoBrIf(iff->condition, ifTrueBreak->value, passOptions)) {
// we are an if-else where the ifTrue is a break without a condition, so we can do this
ifTrueBreak->condition = iff->condition;
ifTrueBreak->finalize();
@@ -416,7 +419,7 @@ struct RemoveUnusedBrs : public WalkerPass<PostWalker<RemoveUnusedBrs, Visitor<R
}
// otherwise, perhaps we can flip the if
auto* ifFalseBreak = iff->ifFalse->dynCast<Break>();
- if (ifFalseBreak && !ifFalseBreak->condition && canTurnIfIntoBrIf(iff->condition, ifFalseBreak->value)) {
+ if (ifFalseBreak && !ifFalseBreak->condition && canTurnIfIntoBrIf(iff->condition, ifFalseBreak->value, passOptions)) {
ifFalseBreak->condition = Builder(*getModule()).makeUnary(EqZInt32, iff->condition);
ifFalseBreak->finalize();
list[i] = Builder(*getModule()).dropIfConcretelyTyped(ifFalseBreak);
@@ -435,7 +438,7 @@ struct RemoveUnusedBrs : public WalkerPass<PostWalker<RemoveUnusedBrs, Visitor<R
if (!br2 || !br2->condition) continue;
if (br1->name == br2->name) {
assert(!br1->value && !br2->value);
- if (!EffectAnalyzer(br2->condition).hasSideEffects()) {
+ if (!EffectAnalyzer(passOptions, br2->condition).hasSideEffects()) {
// it's ok to execute them both, do it
Builder builder(*getModule());
br1->condition = builder.makeBinary(OrInt32, br1->condition, br2->condition);
@@ -480,11 +483,11 @@ struct RemoveUnusedBrs : public WalkerPass<PostWalker<RemoveUnusedBrs, Visitor<R
if (curr->ifFalse && isConcreteWasmType(curr->ifTrue->type) && isConcreteWasmType(curr->ifFalse->type)) {
// if with else, consider turning it into a select if there is no control flow
// TODO: estimate cost
- EffectAnalyzer condition(curr->condition);
+ EffectAnalyzer condition(passOptions, curr->condition);
if (!condition.hasSideEffects()) {
- EffectAnalyzer ifTrue(curr->ifTrue);
+ EffectAnalyzer ifTrue(passOptions, curr->ifTrue);
if (!ifTrue.hasSideEffects()) {
- EffectAnalyzer ifFalse(curr->ifFalse);
+ EffectAnalyzer ifFalse(passOptions, curr->ifFalse);
if (!ifFalse.hasSideEffects()) {
auto* select = getModule()->allocator.alloc<Select>();
select->condition = curr->condition;
@@ -498,7 +501,7 @@ struct RemoveUnusedBrs : public WalkerPass<PostWalker<RemoveUnusedBrs, Visitor<R
}
}
};
- FinalOptimizer finalOptimizer;
+ FinalOptimizer finalOptimizer(getPassOptions());
finalOptimizer.setModule(getModule());
finalOptimizer.selectify = getPassRunner()->options.shrinkLevel > 0;
finalOptimizer.walkFunction(func);
diff --git a/src/passes/SimplifyLocals.cpp b/src/passes/SimplifyLocals.cpp
index 6509c9da5..8590fbe96 100644
--- a/src/passes/SimplifyLocals.cpp
+++ b/src/passes/SimplifyLocals.cpp
@@ -84,9 +84,7 @@ struct SimplifyLocals : public WalkerPass<LinearExecutionWalker<SimplifyLocals,
Expression** item;
EffectAnalyzer effects;
- SinkableInfo(Expression** item) : item(item) {
- effects.walk(*item);
- }
+ SinkableInfo(Expression** item, PassOptions& passOptions) : item(item), effects(passOptions, *item) {}
};
// a list of sinkables in a linear execution trace
@@ -246,7 +244,7 @@ struct SimplifyLocals : public WalkerPass<LinearExecutionWalker<SimplifyLocals,
static void visitPre(SimplifyLocals* self, Expression** currp) {
Expression* curr = *currp;
- EffectAnalyzer effects;
+ EffectAnalyzer effects(self->getPassOptions());
if (effects.checkPre(curr)) {
self->checkInvalidations(effects);
}
@@ -274,7 +272,7 @@ struct SimplifyLocals : public WalkerPass<LinearExecutionWalker<SimplifyLocals,
}
}
- EffectAnalyzer effects;
+ EffectAnalyzer effects(self->getPassOptions());
if (effects.checkPost(*currp)) {
self->checkInvalidations(effects);
}
@@ -282,7 +280,7 @@ struct SimplifyLocals : public WalkerPass<LinearExecutionWalker<SimplifyLocals,
if (set && self->canSink(set)) {
Index index = set->index;
assert(self->sinkables.count(index) == 0);
- self->sinkables.emplace(std::make_pair(index, SinkableInfo(currp)));
+ self->sinkables.emplace(std::make_pair(index, SinkableInfo(currp, self->getPassOptions())));
}
self->expressionStack.pop_back();
diff --git a/src/passes/Vacuum.cpp b/src/passes/Vacuum.cpp
index 8d9bb421c..38e607c24 100644
--- a/src/passes/Vacuum.cpp
+++ b/src/passes/Vacuum.cpp
@@ -74,22 +74,22 @@ struct Vacuum : public WalkerPass<ExpressionStackWalker<Vacuum, Visitor<Vacuum>>
}
// for unary, binary, and select, we need to check their arguments for side effects
if (auto* unary = curr->dynCast<Unary>()) {
- if (EffectAnalyzer(unary->value).hasSideEffects()) {
+ if (EffectAnalyzer(getPassOptions(), unary->value).hasSideEffects()) {
curr = unary->value;
continue;
} else {
return nullptr;
}
} else if (auto* binary = curr->dynCast<Binary>()) {
- if (EffectAnalyzer(binary->left).hasSideEffects()) {
- if (EffectAnalyzer(binary->right).hasSideEffects()) {
+ if (EffectAnalyzer(getPassOptions(), binary->left).hasSideEffects()) {
+ if (EffectAnalyzer(getPassOptions(), binary->right).hasSideEffects()) {
return curr; // leave them
} else {
curr = binary->left;
continue;
}
} else {
- if (EffectAnalyzer(binary->right).hasSideEffects()) {
+ if (EffectAnalyzer(getPassOptions(), binary->right).hasSideEffects()) {
curr = binary->right;
continue;
} else {
@@ -99,11 +99,11 @@ struct Vacuum : public WalkerPass<ExpressionStackWalker<Vacuum, Visitor<Vacuum>>
} else {
// TODO: if two have side effects, we could replace the select with say an add?
auto* select = curr->cast<Select>();
- if (EffectAnalyzer(select->ifTrue).hasSideEffects()) {
- if (EffectAnalyzer(select->ifFalse).hasSideEffects()) {
+ if (EffectAnalyzer(getPassOptions(), select->ifTrue).hasSideEffects()) {
+ if (EffectAnalyzer(getPassOptions(), select->ifFalse).hasSideEffects()) {
return curr; // leave them
} else {
- if (EffectAnalyzer(select->condition).hasSideEffects()) {
+ if (EffectAnalyzer(getPassOptions(), select->condition).hasSideEffects()) {
return curr; // leave them
} else {
curr = select->ifTrue;
@@ -111,15 +111,15 @@ struct Vacuum : public WalkerPass<ExpressionStackWalker<Vacuum, Visitor<Vacuum>>
}
}
} else {
- if (EffectAnalyzer(select->ifFalse).hasSideEffects()) {
- if (EffectAnalyzer(select->condition).hasSideEffects()) {
+ if (EffectAnalyzer(getPassOptions(), select->ifFalse).hasSideEffects()) {
+ if (EffectAnalyzer(getPassOptions(), select->condition).hasSideEffects()) {
return curr; // leave them
} else {
curr = select->ifFalse;
continue;
}
} else {
- if (EffectAnalyzer(select->condition).hasSideEffects()) {
+ if (EffectAnalyzer(getPassOptions(), select->condition).hasSideEffects()) {
curr = select->condition;
continue;
} else {
@@ -174,7 +174,7 @@ struct Vacuum : public WalkerPass<ExpressionStackWalker<Vacuum, Visitor<Vacuum>>
if (!curr->name.is()) {
if (list.size() == 1) {
// just one element. replace the block, either with it or with a nop if it's not needed
- if (isConcreteWasmType(curr->type) || EffectAnalyzer(list[0]).hasSideEffects()) {
+ if (isConcreteWasmType(curr->type) || EffectAnalyzer(getPassOptions(), list[0]).hasSideEffects()) {
replaceCurrent(list[0]);
} else {
if (curr->type == unreachable) {
@@ -307,7 +307,7 @@ struct Vacuum : public WalkerPass<ExpressionStackWalker<Vacuum, Visitor<Vacuum>>
} else {
ExpressionManipulator::nop(curr->body);
}
- if (curr->result == none && !EffectAnalyzer(curr->body).hasSideEffects()) {
+ if (curr->result == none && !EffectAnalyzer(getPassOptions(), curr->body).hasSideEffects()) {
ExpressionManipulator::nop(curr->body);
}
}