2929
3030namespace wasm {
3131
32- static const Name NONSTANDALONE_FLOW (" Binaryen|nonstandalone " );
32+ static const Name NOTPRECOMPUTABLE_FLOW (" Binaryen|notprecomputable " );
3333
3434typedef std::unordered_map<GetLocal*, Literal> GetValues;
3535
36- // Execute an expression by itself. Errors if we hit anything we need anything not in the expression itself standalone.
37- class StandaloneExpressionRunner : public ExpressionRunner <StandaloneExpressionRunner> {
36+ // Precomputes an expression. Errors if we hit anything that can't be precomputed.
37+ class PrecomputingExpressionRunner : public ExpressionRunner <PrecomputingExpressionRunner> {
38+ Module* module ;
39+
3840 // map gets to constant values, if they are known to be constant
3941 GetValues& getValues;
4042
@@ -46,24 +48,24 @@ class StandaloneExpressionRunner : public ExpressionRunner<StandaloneExpressionR
4648 bool replaceExpression;
4749
4850public:
49- StandaloneExpressionRunner ( GetValues& getValues, bool replaceExpression) : getValues(getValues), replaceExpression(replaceExpression) {}
51+ PrecomputingExpressionRunner (Module* module , GetValues& getValues, bool replaceExpression) : module ( module ), getValues(getValues), replaceExpression(replaceExpression) {}
5052
5153 struct NonstandaloneException {}; // TODO: use a flow with a special name, as this is likely very slow
5254
5355 Flow visitLoop (Loop* curr) {
5456 // loops might be infinite, so must be careful
5557 // but we can't tell if non-infinite, since we don't have state, so loops are just impossible to optimize for now
56- return Flow (NONSTANDALONE_FLOW );
58+ return Flow (NOTPRECOMPUTABLE_FLOW );
5759 }
5860
5961 Flow visitCall (Call* curr) {
60- return Flow (NONSTANDALONE_FLOW );
62+ return Flow (NOTPRECOMPUTABLE_FLOW );
6163 }
6264 Flow visitCallImport (CallImport* curr) {
63- return Flow (NONSTANDALONE_FLOW );
65+ return Flow (NOTPRECOMPUTABLE_FLOW );
6466 }
6567 Flow visitCallIndirect (CallIndirect* curr) {
66- return Flow (NONSTANDALONE_FLOW );
68+ return Flow (NOTPRECOMPUTABLE_FLOW );
6769 }
6870 Flow visitGetLocal (GetLocal *curr) {
6971 auto iter = getValues.find (curr);
@@ -73,7 +75,7 @@ class StandaloneExpressionRunner : public ExpressionRunner<StandaloneExpressionR
7375 return Flow (value);
7476 }
7577 }
76- return Flow (NONSTANDALONE_FLOW );
78+ return Flow (NOTPRECOMPUTABLE_FLOW );
7779 }
7880 Flow visitSetLocal (SetLocal *curr) {
7981 // If we don't need to replace the whole expression, see if there
@@ -84,34 +86,40 @@ class StandaloneExpressionRunner : public ExpressionRunner<StandaloneExpressionR
8486 return visit (curr->value );
8587 }
8688 }
87- return Flow (NONSTANDALONE_FLOW );
89+ return Flow (NOTPRECOMPUTABLE_FLOW );
8890 }
8991 Flow visitGetGlobal (GetGlobal *curr) {
90- return Flow (NONSTANDALONE_FLOW);
92+ auto * global = module ->getGlobalOrNull (curr->name );
93+ if (global) {
94+ if (!global->mutable_ ) {
95+ return visit (global->init );
96+ }
97+ }
98+ return Flow (NOTPRECOMPUTABLE_FLOW);
9199 }
92100 Flow visitSetGlobal (SetGlobal *curr) {
93- return Flow (NONSTANDALONE_FLOW );
101+ return Flow (NOTPRECOMPUTABLE_FLOW );
94102 }
95103 Flow visitLoad (Load *curr) {
96- return Flow (NONSTANDALONE_FLOW );
104+ return Flow (NOTPRECOMPUTABLE_FLOW );
97105 }
98106 Flow visitStore (Store *curr) {
99- return Flow (NONSTANDALONE_FLOW );
107+ return Flow (NOTPRECOMPUTABLE_FLOW );
100108 }
101109 Flow visitAtomicRMW (AtomicRMW *curr) {
102- return Flow (NONSTANDALONE_FLOW );
110+ return Flow (NOTPRECOMPUTABLE_FLOW );
103111 }
104112 Flow visitAtomicCmpxchg (AtomicCmpxchg *curr) {
105- return Flow (NONSTANDALONE_FLOW );
113+ return Flow (NOTPRECOMPUTABLE_FLOW );
106114 }
107115 Flow visitAtomicWait (AtomicWait *curr) {
108- return Flow (NONSTANDALONE_FLOW );
116+ return Flow (NOTPRECOMPUTABLE_FLOW );
109117 }
110118 Flow visitAtomicWake (AtomicWake *curr) {
111- return Flow (NONSTANDALONE_FLOW );
119+ return Flow (NOTPRECOMPUTABLE_FLOW );
112120 }
113121 Flow visitHost (Host *curr) {
114- return Flow (NONSTANDALONE_FLOW );
122+ return Flow (NOTPRECOMPUTABLE_FLOW );
115123 }
116124
117125 void trap (const char * why) override {
@@ -156,7 +164,7 @@ struct Precompute : public WalkerPass<PostWalker<Precompute, UnifiedExpressionVi
156164 // try to evaluate this into a const
157165 Flow flow = precomputeExpression (curr);
158166 if (flow.breaking ()) {
159- if (flow.breakTo == NONSTANDALONE_FLOW ) return ;
167+ if (flow.breakTo == NOTPRECOMPUTABLE_FLOW ) return ;
160168 if (flow.breakTo == RETURN_FLOW) {
161169 // this expression causes a return. if it's already a return, reuse the node
162170 if (auto * ret = curr->dynCast <Return>()) {
@@ -223,9 +231,9 @@ struct Precompute : public WalkerPass<PostWalker<Precompute, UnifiedExpressionVi
223231 // (that we can replace the expression with if replaceExpression is set).
224232 Flow precomputeExpression (Expression* curr, bool replaceExpression = true ) {
225233 try {
226- return StandaloneExpressionRunner ( getValues, replaceExpression).visit (curr);
227- } catch (StandaloneExpressionRunner ::NonstandaloneException&) {
228- return Flow (NONSTANDALONE_FLOW );
234+ return PrecomputingExpressionRunner ( getModule (), getValues, replaceExpression).visit (curr);
235+ } catch (PrecomputingExpressionRunner ::NonstandaloneException&) {
236+ return Flow (NOTPRECOMPUTABLE_FLOW );
229237 }
230238 }
231239
0 commit comments