diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/passes/SimplifyGlobals.cpp | 61 |
1 files changed, 54 insertions, 7 deletions
diff --git a/src/passes/SimplifyGlobals.cpp b/src/passes/SimplifyGlobals.cpp index a111f31b5..fce9df964 100644 --- a/src/passes/SimplifyGlobals.cpp +++ b/src/passes/SimplifyGlobals.cpp @@ -23,11 +23,15 @@ // to allow removal of the copies later. // * Apply the constant values of immutable globals. // +// Some globals may not have uses after these changes, which we leave +// to other passes to optimize. +// #include <atomic> #include "ir/utils.h" #include "pass.h" +#include "wasm-builder.h" #include "wasm.h" namespace wasm { @@ -105,9 +109,26 @@ private: } // anonymous namespace struct SimplifyGlobals : public Pass { - void run(PassRunner* runner, Module* module) override { + PassRunner* runner; + Module* module; + + GlobalInfoMap map; + + void run(PassRunner* runner_, Module* module_) override { + runner = runner_; + module = module_; + + analyze(); + + preferEarlierImports(); + + propagateConstantsToGlobals(); + + propagateConstantsToCode(); + } + + void analyze() { // First, find out all the relevant info. - GlobalInfoMap map; for (auto& global : module->globals) { auto& info = map[global->name]; if (global->imported()) { @@ -128,6 +149,9 @@ struct SimplifyGlobals : public Pass { global->mutable_ = false; } } + } + + void preferEarlierImports() { // Optimize uses of immutable globals, prefer the earlier import when // there is a copy. NameNameMap copiedParentMap; @@ -155,9 +179,34 @@ struct SimplifyGlobals : public Pass { // Apply to the gets. GlobalUseModifier(&copiedParentMap).run(runner, module); } - // If any immutable globals have constant values, we can just apply them - // (the global itself will be removed by another pass, as it/ won't have - // any uses). + } + + // Constant propagation part 1: even an mutable global with a constant + // value can have that value propagated to another global that reads it, + // since we do know the value during startup, it can't be modified until + // code runs. + void propagateConstantsToGlobals() { + // Go over the list of globals in order, which is the order of + // initialization as well, tracking their constant values. + std::map<Name, Literal> constantGlobals; + for (auto& global : module->globals) { + if (!global->imported()) { + if (auto* c = global->init->dynCast<Const>()) { + constantGlobals[global->name] = c->value; + } else if (auto* get = global->init->dynCast<GlobalGet>()) { + auto iter = constantGlobals.find(get->name); + if (iter != constantGlobals.end()) { + Builder builder(*module); + global->init = builder.makeConst(iter->second); + } + } + } + } + } + + // Constant propagation part 2: apply the values of immutable globals + // with constant values to to global.gets in the code. + void propagateConstantsToCode() { NameSet constantGlobals; for (auto& global : module->globals) { if (!global->mutable_ && !global->imported() && @@ -168,8 +217,6 @@ struct SimplifyGlobals : public Pass { if (!constantGlobals.empty()) { ConstantGlobalApplier(&constantGlobals).run(runner, module); } - // TODO a mutable global's initial value can be applied to another global - // after it, as the mutable one can't mutate during instance startup } }; |