2121// globals immutable.
2222// * If an immutable global is a copy of another, use the earlier one,
2323// to allow removal of the copies later.
24+ // * Apply the constant values of immutable globals.
2425//
2526
2627#include < atomic>
2728
29+ #include " ir/utils.h"
2830#include " pass.h"
2931#include " wasm.h"
3032
@@ -54,6 +56,7 @@ struct GlobalUseScanner : public WalkerPass<PostWalker<GlobalUseScanner>> {
5456};
5557
5658using NameNameMap = std::map<Name, Name>;
59+ using NameSet = std::set<Name>;
5760
5861struct GlobalUseModifier : public WalkerPass <PostWalker<GlobalUseModifier>> {
5962 bool isFunctionParallel () override { return true ; }
@@ -76,6 +79,29 @@ struct GlobalUseModifier : public WalkerPass<PostWalker<GlobalUseModifier>> {
7679 NameNameMap* copiedParentMap;
7780};
7881
82+ struct ConstantGlobalApplier
83+ : public WalkerPass<PostWalker<ConstantGlobalApplier>> {
84+ bool isFunctionParallel () override { return true ; }
85+
86+ ConstantGlobalApplier (NameSet* constantGlobals)
87+ : constantGlobals(constantGlobals) {}
88+
89+ ConstantGlobalApplier* create () override {
90+ return new ConstantGlobalApplier (constantGlobals);
91+ }
92+
93+ void visitGlobalGet (GlobalGet* curr) {
94+ if (constantGlobals->count (curr->name )) {
95+ auto * global = getModule ()->getGlobal (curr->name );
96+ assert (global->init ->is <Const>());
97+ replaceCurrent (ExpressionManipulator::copy (global->init , *getModule ()));
98+ }
99+ }
100+
101+ private:
102+ NameSet* constantGlobals;
103+ };
104+
79105} // anonymous namespace
80106
81107struct SimplifyGlobals : public Pass {
@@ -135,6 +161,23 @@ struct SimplifyGlobals : public Pass {
135161 subRunner.add <GlobalUseModifier>(&copiedParentMap);
136162 subRunner.run ();
137163 }
164+ // If any immutable globals have constant values, we can just apply them
165+ // (the global itself will be removed by another pass, as it/ won't have
166+ // any uses).
167+ NameSet constantGlobals;
168+ for (auto & global : module ->globals ) {
169+ if (!global->mutable_ && !global->imported () &&
170+ global->init ->is <Const>()) {
171+ constantGlobals.insert (global->name );
172+ }
173+ }
174+ if (!constantGlobals.empty ()) {
175+ PassRunner subRunner (module , runner->options );
176+ subRunner.add <ConstantGlobalApplier>(&constantGlobals);
177+ subRunner.run ();
178+ }
179+ // TODO a mutable global's initial value can be applied to another global
180+ // after it, as the mutable one can't mutate during instance startup
138181 }
139182};
140183
0 commit comments