Skip to content

Commit c8101d1

Browse files
authored
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.
1 parent beef3e9 commit c8101d1

2 files changed

Lines changed: 60 additions & 13 deletions

File tree

src/passes/SimplifyGlobals.cpp

Lines changed: 54 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,15 @@
2323
// to allow removal of the copies later.
2424
// * Apply the constant values of immutable globals.
2525
//
26+
// Some globals may not have uses after these changes, which we leave
27+
// to other passes to optimize.
28+
//
2629

2730
#include <atomic>
2831

2932
#include "ir/utils.h"
3033
#include "pass.h"
34+
#include "wasm-builder.h"
3135
#include "wasm.h"
3236

3337
namespace wasm {
@@ -105,9 +109,26 @@ struct ConstantGlobalApplier
105109
} // anonymous namespace
106110

107111
struct SimplifyGlobals : public Pass {
108-
void run(PassRunner* runner, Module* module) override {
112+
PassRunner* runner;
113+
Module* module;
114+
115+
GlobalInfoMap map;
116+
117+
void run(PassRunner* runner_, Module* module_) override {
118+
runner = runner_;
119+
module = module_;
120+
121+
analyze();
122+
123+
preferEarlierImports();
124+
125+
propagateConstantsToGlobals();
126+
127+
propagateConstantsToCode();
128+
}
129+
130+
void analyze() {
109131
// First, find out all the relevant info.
110-
GlobalInfoMap map;
111132
for (auto& global : module->globals) {
112133
auto& info = map[global->name];
113134
if (global->imported()) {
@@ -128,6 +149,9 @@ struct SimplifyGlobals : public Pass {
128149
global->mutable_ = false;
129150
}
130151
}
152+
}
153+
154+
void preferEarlierImports() {
131155
// Optimize uses of immutable globals, prefer the earlier import when
132156
// there is a copy.
133157
NameNameMap copiedParentMap;
@@ -155,9 +179,34 @@ struct SimplifyGlobals : public Pass {
155179
// Apply to the gets.
156180
GlobalUseModifier(&copiedParentMap).run(runner, module);
157181
}
158-
// If any immutable globals have constant values, we can just apply them
159-
// (the global itself will be removed by another pass, as it/ won't have
160-
// any uses).
182+
}
183+
184+
// Constant propagation part 1: even an mutable global with a constant
185+
// value can have that value propagated to another global that reads it,
186+
// since we do know the value during startup, it can't be modified until
187+
// code runs.
188+
void propagateConstantsToGlobals() {
189+
// Go over the list of globals in order, which is the order of
190+
// initialization as well, tracking their constant values.
191+
std::map<Name, Literal> constantGlobals;
192+
for (auto& global : module->globals) {
193+
if (!global->imported()) {
194+
if (auto* c = global->init->dynCast<Const>()) {
195+
constantGlobals[global->name] = c->value;
196+
} else if (auto* get = global->init->dynCast<GlobalGet>()) {
197+
auto iter = constantGlobals.find(get->name);
198+
if (iter != constantGlobals.end()) {
199+
Builder builder(*module);
200+
global->init = builder.makeConst(iter->second);
201+
}
202+
}
203+
}
204+
}
205+
}
206+
207+
// Constant propagation part 2: apply the values of immutable globals
208+
// with constant values to to global.gets in the code.
209+
void propagateConstantsToCode() {
161210
NameSet constantGlobals;
162211
for (auto& global : module->globals) {
163212
if (!global->mutable_ && !global->imported() &&
@@ -168,8 +217,6 @@ struct SimplifyGlobals : public Pass {
168217
if (!constantGlobals.empty()) {
169218
ConstantGlobalApplier(&constantGlobals).run(runner, module);
170219
}
171-
// TODO a mutable global's initial value can be applied to another global
172-
// after it, as the mutable one can't mutate during instance startup
173220
}
174221
};
175222

test/passes/simplify-globals_enable-mutable-globals.txt

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -54,17 +54,17 @@
5454
(module
5555
(type $FUNCSIG$v (func))
5656
(global $g1 i32 (i32.const 1))
57-
(global $g2 i32 (global.get $g1))
57+
(global $g2 i32 (i32.const 1))
5858
(global $g3 f64 (f64.const -3.4))
5959
(global $g4 f64 (f64.const -2.8))
6060
(global $g5 i32 (i32.const 2))
61-
(global $g6 i32 (global.get $g5))
61+
(global $g6 i32 (i32.const 2))
6262
(global $g7 i32 (i32.const 3))
63-
(global $g8 i32 (global.get $g7))
63+
(global $g8 i32 (i32.const 3))
6464
(global $g9 i32 (i32.const 4))
65-
(global $ga (mut i32) (global.get $g9))
65+
(global $ga (mut i32) (i32.const 4))
6666
(global $gb (mut i32) (i32.const 5))
67-
(global $gc i32 (global.get $gb))
67+
(global $gc i32 (i32.const 5))
6868
(func $foo (; 0 ;) (type $FUNCSIG$v)
6969
(drop
7070
(i32.const 1)
@@ -100,7 +100,7 @@
100100
(global.get $gb)
101101
)
102102
(drop
103-
(global.get $gc)
103+
(i32.const 5)
104104
)
105105
(global.set $ga
106106
(i32.const 6)

0 commit comments

Comments
 (0)