diff options
Diffstat (limited to 'src/passes')
-rw-r--r-- | src/passes/CodePushing.cpp | 19 | ||||
-rw-r--r-- | src/passes/MergeBlocks.cpp | 10 | ||||
-rw-r--r-- | src/passes/OptimizeInstructions.cpp | 8 | ||||
-rw-r--r-- | src/passes/RemoveUnusedBrs.cpp | 27 | ||||
-rw-r--r-- | src/passes/SimplifyLocals.cpp | 10 | ||||
-rw-r--r-- | src/passes/Vacuum.cpp | 24 |
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); } } |