diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/passes/SimplifyGlobals.cpp | 86 | ||||
-rw-r--r-- | src/passes/pass.cpp | 10 | ||||
-rw-r--r-- | src/passes/passes.h | 1 |
3 files changed, 83 insertions, 14 deletions
diff --git a/src/passes/SimplifyGlobals.cpp b/src/passes/SimplifyGlobals.cpp index fce9df964..88f27f8be 100644 --- a/src/passes/SimplifyGlobals.cpp +++ b/src/passes/SimplifyGlobals.cpp @@ -22,13 +22,21 @@ // * If an immutable global is a copy of another, use the earlier one, // to allow removal of the copies later. // * Apply the constant values of immutable globals. +// * Apply the constant values of previous global.sets, in a linear +// execution trace. // // Some globals may not have uses after these changes, which we leave // to other passes to optimize. // +// This pass has a "optimize" variant (similar to inlining and DAE) +// that also runs general function optimizations where we managed to replace +// a constant value. That is helpful as such a replacement often opens up +// further optimization opportunities. +// #include <atomic> +#include "ir/effects.h" #include "ir/utils.h" #include "pass.h" #include "wasm-builder.h" @@ -84,26 +92,73 @@ private: }; struct ConstantGlobalApplier - : public WalkerPass<PostWalker<ConstantGlobalApplier>> { + : public WalkerPass< + LinearExecutionWalker<ConstantGlobalApplier, + UnifiedExpressionVisitor<ConstantGlobalApplier>>> { bool isFunctionParallel() override { return true; } - ConstantGlobalApplier(NameSet* constantGlobals) - : constantGlobals(constantGlobals) {} + ConstantGlobalApplier(NameSet* constantGlobals, bool optimize) + : constantGlobals(constantGlobals), optimize(optimize) {} ConstantGlobalApplier* create() override { - return new ConstantGlobalApplier(constantGlobals); + return new ConstantGlobalApplier(constantGlobals, optimize); } - void visitGlobalGet(GlobalGet* curr) { - if (constantGlobals->count(curr->name)) { - auto* global = getModule()->getGlobal(curr->name); - assert(global->init->is<Const>()); - replaceCurrent(ExpressionManipulator::copy(global->init, *getModule())); + void visitExpression(Expression* curr) { + if (auto* set = curr->dynCast<GlobalSet>()) { + if (auto* c = set->value->dynCast<Const>()) { + currConstantGlobals[set->name] = c->value; + } else { + currConstantGlobals.erase(set->name); + } + return; + } else if (auto* get = curr->dynCast<GlobalGet>()) { + // Check if the global is known to be constant all the time. + if (constantGlobals->count(get->name)) { + auto* global = getModule()->getGlobal(get->name); + assert(global->init->is<Const>()); + replaceCurrent(ExpressionManipulator::copy(global->init, *getModule())); + replaced = true; + return; + } + // Check if the global has a known value in this linear trace. + auto iter = currConstantGlobals.find(get->name); + if (iter != currConstantGlobals.end()) { + Builder builder(*getModule()); + replaceCurrent(builder.makeConst(iter->second)); + replaced = true; + } + return; + } + // Otherwise, invalidate if we need to. + EffectAnalyzer effects(getPassOptions()); + effects.visit(curr); + assert(effects.globalsWritten.empty()); // handled above + if (effects.calls) { + currConstantGlobals.clear(); + } + } + + static void doNoteNonLinear(ConstantGlobalApplier* self, Expression** currp) { + self->currConstantGlobals.clear(); + } + + void visitFunction(Function* curr) { + if (replaced && optimize) { + PassRunner runner(getModule(), getPassRunner()->options); + runner.setIsNested(true); + runner.addDefaultFunctionOptimizationPasses(); + runner.runOnFunction(curr); } } private: NameSet* constantGlobals; + bool optimize; + bool replaced = false; + + // The globals currently constant in the linear trace. + std::map<Name, Literal> currConstantGlobals; }; } // anonymous namespace @@ -113,6 +168,9 @@ struct SimplifyGlobals : public Pass { Module* module; GlobalInfoMap map; + bool optimize; + + SimplifyGlobals(bool optimize = false) : optimize(optimize) {} void run(PassRunner* runner_, Module* module_) override { runner = runner_; @@ -214,12 +272,14 @@ struct SimplifyGlobals : public Pass { constantGlobals.insert(global->name); } } - if (!constantGlobals.empty()) { - ConstantGlobalApplier(&constantGlobals).run(runner, module); - } + ConstantGlobalApplier(&constantGlobals, optimize).run(runner, module); } }; -Pass* createSimplifyGlobalsPass() { return new SimplifyGlobals(); } +Pass* createSimplifyGlobalsPass() { return new SimplifyGlobals(false); } + +Pass* createSimplifyGlobalsOptimizingPass() { + return new SimplifyGlobals(true); +} } // namespace wasm diff --git a/src/passes/pass.cpp b/src/passes/pass.cpp index daa575c6d..7d17510fc 100644 --- a/src/passes/pass.cpp +++ b/src/passes/pass.cpp @@ -267,6 +267,10 @@ void PassRegistry::registerPasses() { registerPass("simplify-globals", "miscellaneous globals-related optimizations", createSimplifyGlobalsPass); + registerPass("simplify-globals-optimizing", + "miscellaneous globals-related optimizations, and optimizes " + "where we replaced global.gets with constants", + createSimplifyGlobalsOptimizingPass); registerPass("simplify-locals", "miscellaneous locals-related optimizations", createSimplifyLocalsPass); @@ -416,7 +420,11 @@ void PassRunner::addDefaultGlobalOptimizationPostPasses() { // optimizations show more functions as duplicate add("duplicate-function-elimination"); add("duplicate-import-elimination"); - add("simplify-globals"); + if (options.optimizeLevel >= 2 || options.shrinkLevel >= 2) { + add("simplify-globals-optimizing"); + } else { + add("simplify-globals"); + } add("remove-unused-module-elements"); add("memory-packing"); // may allow more inlining/dae/etc., need --converge for that diff --git a/src/passes/passes.h b/src/passes/passes.h index 115e9bab6..6342ea15b 100644 --- a/src/passes/passes.h +++ b/src/passes/passes.h @@ -92,6 +92,7 @@ Pass* createRedundantSetEliminationPass(); Pass* createSafeHeapPass(); Pass* createSimplifyLocalsPass(); Pass* createSimplifyGlobalsPass(); +Pass* createSimplifyGlobalsOptimizingPass(); Pass* createSimplifyLocalsNoNestingPass(); Pass* createSimplifyLocalsNoTeePass(); Pass* createSimplifyLocalsNoStructurePass(); |