diff options
author | Alon Zakai <azakai@google.com> | 2019-07-20 18:09:18 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-07-20 18:09:18 -0700 |
commit | c8101d1b67ffcce38718f07ba560ce56ddb3f240 (patch) | |
tree | aae6831e6dd7ce004ab4ef2f317059329f0c07f7 | |
parent | beef3e931fd776baa025cd58345b644b47481aa7 (diff) | |
download | binaryen-c8101d1b67ffcce38718f07ba560ce56ddb3f240.tar.gz binaryen-c8101d1b67ffcce38718f07ba560ce56ddb3f240.tar.bz2 binaryen-c8101d1b67ffcce38718f07ba560ce56ddb3f240.zip |
SimplifyGlobals: Propagate constants in global initializers (#2238)
(global $g1 (mut i32) (i32.const 42))
(global $g2 i32 (global.get $g1))
can be optimized to
(global $g1 (mut i32) (i32.const 42))
(global $g2 i32 (i32.const 42))
even though $g1 is mutable - because it can't be mutated during module instantiation.
-rw-r--r-- | src/passes/SimplifyGlobals.cpp | 61 | ||||
-rw-r--r-- | test/passes/simplify-globals_enable-mutable-globals.txt | 12 |
2 files changed, 60 insertions, 13 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 } }; diff --git a/test/passes/simplify-globals_enable-mutable-globals.txt b/test/passes/simplify-globals_enable-mutable-globals.txt index 010259d07..346161f14 100644 --- a/test/passes/simplify-globals_enable-mutable-globals.txt +++ b/test/passes/simplify-globals_enable-mutable-globals.txt @@ -54,17 +54,17 @@ (module (type $FUNCSIG$v (func)) (global $g1 i32 (i32.const 1)) - (global $g2 i32 (global.get $g1)) + (global $g2 i32 (i32.const 1)) (global $g3 f64 (f64.const -3.4)) (global $g4 f64 (f64.const -2.8)) (global $g5 i32 (i32.const 2)) - (global $g6 i32 (global.get $g5)) + (global $g6 i32 (i32.const 2)) (global $g7 i32 (i32.const 3)) - (global $g8 i32 (global.get $g7)) + (global $g8 i32 (i32.const 3)) (global $g9 i32 (i32.const 4)) - (global $ga (mut i32) (global.get $g9)) + (global $ga (mut i32) (i32.const 4)) (global $gb (mut i32) (i32.const 5)) - (global $gc i32 (global.get $gb)) + (global $gc i32 (i32.const 5)) (func $foo (; 0 ;) (type $FUNCSIG$v) (drop (i32.const 1) @@ -100,7 +100,7 @@ (global.get $gb) ) (drop - (global.get $gc) + (i32.const 5) ) (global.set $ga (i32.const 6) |