Skip to content

Commit 25890f5

Browse files
dcodeIOkripken
authored andcommitted
Support constant globals in precompute pass (#1622)
This PR includes non-mutable globals in precompute, which will allow me to continue removing manual inlining of constants in AssemblyScript without breaking something. Related: #1621, i.e. enum Animal { CAT = 0, DOG = CAT + 1 // requires that `Animal.CAT` is evaluated to // precompute the constant value for `Animal.DOG` }
1 parent e601522 commit 25890f5

18 files changed

+140
-108
lines changed

src/passes/Precompute.cpp

Lines changed: 31 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,14 @@
2929

3030
namespace wasm {
3131

32-
static const Name NONSTANDALONE_FLOW("Binaryen|nonstandalone");
32+
static const Name NOTPRECOMPUTABLE_FLOW("Binaryen|notprecomputable");
3333

3434
typedef 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

4850
public:
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

src/tools/wasm-opt.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ int main(int argc, const char* argv[]) {
149149
p.dump(std::cerr);
150150
std::cerr << '\n';
151151
Fatal() << "error in parsing wasm source map";
152-
} catch (std::bad_alloc& b) {
152+
} catch (std::bad_alloc&) {
153153
Fatal() << "error in building module, std::bad_alloc (possibly invalid request for silly amounts of memory)";
154154
}
155155

test/merge/basics.wast

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
(global $global-collide i32 (i32.const 0))
1111
(global $global-collide-mut (mut i32) (i32.const 0))
1212
(global $global-a i32 (i32.const 1))
13+
(global $global-a-mut (mut i32) (i32.const 1))
1314
(elem (get_global $tableBase) $only-a $willCollide $some-func $some-collide $only-a)
1415
(export "exp-a" (func $only-a))
1516
(export "exp-collide" (func $only-a))
@@ -26,6 +27,7 @@
2627
)
2728
(drop (get_global $global-collide))
2829
(drop (get_global $global-a))
30+
(drop (get_global $global-a-mut))
2931
(drop (get_global $memoryBase))
3032
(drop (get_global $tableBase))
3133
(set_global $global-collide-mut (i32.const 1234))

test/merge/basics.wast.combined

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,11 @@
1616
(global $global-collide i32 (i32.const 0))
1717
(global $global-collide-mut (mut i32) (i32.const 0))
1818
(global $global-a i32 (i32.const 1))
19+
(global $global-a-mut (mut i32) (i32.const 1))
1920
(global $global-collide$0 i32 (i32.const 0))
2021
(global $global-collide-mut$0 (mut i32) (i32.const 0))
2122
(global $global-b i32 (i32.const 1))
23+
(global $global-b-mut (mut i32) (i32.const 1))
2224
(elem (get_global $tableBase) $only-a $willCollide $some-func $some-collide $only-a $only-a $only-b $willCollide$0 $some-func-b $some-collide$0)
2325
(data (get_global $memoryBase) "hello, A!\n\00\00\00\00\00\00hello, B!\n\00\00\00\00\00\00")
2426
(export "exp-a" (func $only-a))
@@ -44,6 +46,9 @@
4446
(drop
4547
(get_global $global-a)
4648
)
49+
(drop
50+
(get_global $global-a-mut)
51+
)
4752
(drop
4853
(get_global $memoryBase)
4954
)
@@ -78,6 +83,9 @@
7883
(drop
7984
(get_global $global-b)
8085
)
86+
(drop
87+
(get_global $global-b-mut)
88+
)
8189
(drop
8290
(i32.add
8391
(get_global $memoryBase$0)

test/merge/basics.wast.combined.finalized

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,11 @@
1616
(global $global-collide i32 (i32.const 0))
1717
(global $global-collide-mut (mut i32) (i32.const 0))
1818
(global $global-a i32 (i32.const 1))
19+
(global $global-a-mut (mut i32) (i32.const 1))
1920
(global $global-collide$0 i32 (i32.const 0))
2021
(global $global-collide-mut$0 (mut i32) (i32.const 0))
2122
(global $global-b i32 (i32.const 1))
23+
(global $global-b-mut (mut i32) (i32.const 1))
2224
(elem (i32.const 8) $only-a $willCollide $some-func $some-collide $only-a $only-a $only-b $willCollide$0 $some-func-b $some-collide$0)
2325
(data (i32.const 1024) "hello, A!\n\00\00\00\00\00\00hello, B!\n\00\00\00\00\00\00")
2426
(export "exp-a" (func $only-a))
@@ -44,6 +46,9 @@
4446
(drop
4547
(get_global $global-a)
4648
)
49+
(drop
50+
(get_global $global-a-mut)
51+
)
4752
(drop
4853
(i32.const 1024)
4954
)
@@ -78,6 +83,9 @@
7883
(drop
7984
(get_global $global-b)
8085
)
86+
(drop
87+
(get_global $global-b-mut)
88+
)
8189
(drop
8290
(i32.add
8391
(i32.const 1024)

test/merge/basics.wast.combined.finalized.opt

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,10 @@
77
(import "env" "some-collide" (func $some-collide))
88
(import "env" "some-func-b" (func $some-func-b))
99
(import "env" "some-collide" (func $some-collide$0))
10-
(global $global-collide i32 (i32.const 0))
1110
(global $global-collide-mut (mut i32) (i32.const 0))
12-
(global $global-a i32 (i32.const 1))
13-
(global $global-collide$0 i32 (i32.const 0))
11+
(global $global-a-mut (mut i32) (i32.const 1))
1412
(global $global-collide-mut$0 (mut i32) (i32.const 0))
15-
(global $global-b i32 (i32.const 1))
13+
(global $global-b-mut (mut i32) (i32.const 1))
1614
(elem (i32.const 8) $only-a $willCollide $some-func $some-collide $only-a $only-a $only-b $willCollide$0 $some-func-b $some-collide$0)
1715
(data (i32.const 1024) "hello, A!\n\00\00\00\00\00\00hello, B!\n")
1816
(export "exp-a" (func $only-a))
@@ -30,11 +28,10 @@
3028
(i32.const 456)
3129
(i32.const 789)
3230
)
31+
(nop)
32+
(nop)
3333
(drop
34-
(get_global $global-collide)
35-
)
36-
(drop
37-
(get_global $global-a)
34+
(get_global $global-a-mut)
3835
)
3936
(nop)
4037
(nop)
@@ -56,11 +53,10 @@
5653
(i32.const 34)
5754
(i32.const 56)
5855
)
56+
(nop)
57+
(nop)
5958
(drop
60-
(get_global $global-collide$0)
61-
)
62-
(drop
63-
(get_global $global-b)
59+
(get_global $global-b-mut)
6460
)
6561
(nop)
6662
(nop)

test/merge/basics.wast.combined.opt

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,10 @@
1111
(import "env" "tableBase" (global $tableBase$0 i32))
1212
(import "env" "some-func-b" (func $some-func-b))
1313
(import "env" "some-collide" (func $some-collide$0))
14-
(global $global-collide i32 (i32.const 0))
1514
(global $global-collide-mut (mut i32) (i32.const 0))
16-
(global $global-a i32 (i32.const 1))
17-
(global $global-collide$0 i32 (i32.const 0))
15+
(global $global-a-mut (mut i32) (i32.const 1))
1816
(global $global-collide-mut$0 (mut i32) (i32.const 0))
19-
(global $global-b i32 (i32.const 1))
17+
(global $global-b-mut (mut i32) (i32.const 1))
2018
(elem (get_global $tableBase) $only-a $willCollide $some-func $some-collide $only-a $only-a $only-b $willCollide$0 $some-func-b $some-collide$0)
2119
(data (get_global $memoryBase) "hello, A!\n\00\00\00\00\00\00hello, B!\n")
2220
(export "exp-a" (func $only-a))
@@ -34,11 +32,10 @@
3432
(i32.const 456)
3533
(i32.const 789)
3634
)
35+
(nop)
36+
(nop)
3737
(drop
38-
(get_global $global-collide)
39-
)
40-
(drop
41-
(get_global $global-a)
38+
(get_global $global-a-mut)
4239
)
4340
(drop
4441
(get_global $memoryBase)
@@ -64,11 +61,10 @@
6461
(i32.const 34)
6562
(i32.const 56)
6663
)
64+
(nop)
65+
(nop)
6766
(drop
68-
(get_global $global-collide$0)
69-
)
70-
(drop
71-
(get_global $global-b)
67+
(get_global $global-b-mut)
7268
)
7369
(drop
7470
(i32.add

test/merge/basics.wast.toMerge

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
(global $global-collide i32 (i32.const 0))
1111
(global $global-collide-mut (mut i32) (i32.const 0))
1212
(global $global-b i32 (i32.const 1))
13+
(global $global-b-mut (mut i32) (i32.const 1))
1314
(elem (get_global $tableBase) $only-b $willCollide $some-func-b $some-collide)
1415
(export "exp-b" (func $only-b))
1516
(export "exp-collide" (func $only-b))
@@ -27,6 +28,7 @@
2728
)
2829
(drop (get_global $global-collide))
2930
(drop (get_global $global-b))
31+
(drop (get_global $global-b-mut))
3032
(drop (get_global $memoryBase))
3133
(drop (get_global $tableBase))
3234
(drop

test/merge/fusing.wast.combined.finalized.opt

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,20 +11,10 @@
1111
(func $foo-func (; 0 ;) (type $FUNCSIG$v)
1212
(nop)
1313
(call $bar-func)
14-
(drop
15-
(get_global $a-global)
16-
)
17-
(drop
18-
(get_global $b-global)
19-
)
14+
(nop)
15+
(nop)
2016
)
2117
(func $bar-func (; 1 ;) (type $FUNCSIG$v)
2218
(nop)
23-
(drop
24-
(get_global $a-global)
25-
)
26-
(drop
27-
(get_global $b-global)
28-
)
2919
)
3020
)

test/merge/fusing.wast.combined.opt

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -14,20 +14,10 @@
1414
(func $foo-func (; 0 ;) (type $FUNCSIG$v)
1515
(nop)
1616
(call $bar-func)
17-
(drop
18-
(get_global $a-global)
19-
)
20-
(drop
21-
(get_global $b-global)
22-
)
17+
(nop)
18+
(nop)
2319
)
2420
(func $bar-func (; 1 ;) (type $FUNCSIG$v)
2521
(nop)
26-
(drop
27-
(get_global $a-global)
28-
)
29-
(drop
30-
(get_global $b-global)
31-
)
3222
)
3323
)

0 commit comments

Comments
 (0)