Skip to content

Commit 6e1e53f

Browse files
authored
Add a pass to propagate global constants to other globals (#6287)
SimplifyGlobals already does this, so this is a subset of that pass, and does not add anything new. It is useful for testing, however. In particular it allows testing that we propagate subsequent globals in a single pass, that is if one global reads from another and becomes constant, then it can be propagated as well. SimplifyGlobals runs multiple passes so this always worked, but with this pass we can test that we do it efficiently in one pass. This will also be useful for comparing stringref to imported strings, as it allows gathered strings to be propagated to other globals (possible with stringref, but not imported strings) but not anywhere else (which might have downsides as it could lead to more allocations). Also add an additional test for simplify-globals that we do not get confused by an unoptimizable global.get in the middle (see last part).
1 parent f172920 commit 6e1e53f

File tree

7 files changed

+140
-4
lines changed

7 files changed

+140
-4
lines changed

src/passes/SimplifyGlobals.cpp

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -673,11 +673,12 @@ struct SimplifyGlobals : public Pass {
673673
// go, as well as applying them where possible.
674674
for (auto& global : module->globals) {
675675
if (!global->imported()) {
676+
// Apply globals to this value, which may turn it into a constant we can
677+
// further propagate, or it may already have been one.
678+
applyGlobals(global->init);
676679
if (Properties::isConstantExpression(global->init)) {
677680
constantGlobals[global->name] =
678681
getLiteralsFromConstExpression(global->init);
679-
} else {
680-
applyGlobals(global->init);
681682
}
682683
}
683684
}
@@ -762,10 +763,24 @@ struct SimplifyGlobals : public Pass {
762763
}
763764
};
764765

766+
// A pass mainly useful for testing that only performs the operation to
767+
// propagate constant values between globals.
768+
struct PropagateGlobalsGlobally : public SimplifyGlobals {
769+
void run(Module* module_) override {
770+
module = module_;
771+
772+
propagateConstantsToGlobals();
773+
}
774+
};
775+
765776
Pass* createSimplifyGlobalsPass() { return new SimplifyGlobals(false); }
766777

767778
Pass* createSimplifyGlobalsOptimizingPass() {
768779
return new SimplifyGlobals(true);
769780
}
770781

782+
Pass* createPropagateGlobalsGloballyPass() {
783+
return new PropagateGlobalsGlobally();
784+
}
785+
771786
} // namespace wasm

src/passes/pass.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -369,6 +369,9 @@ void PassRegistry::registerPasses() {
369369
registerPass("print-stack-ir",
370370
"print out Stack IR (useful for internal debugging)",
371371
createPrintStackIRPass);
372+
registerPass("propagate-globals-globally",
373+
"propagate global values to other globals (useful for tests)",
374+
createPropagateGlobalsGloballyPass);
372375
registerPass("remove-non-js-ops",
373376
"removes operations incompatible with js",
374377
createRemoveNonJSOpsPass);

src/passes/passes.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ Pass* createPrintCallGraphPass();
123123
Pass* createPrintFeaturesPass();
124124
Pass* createPrintFunctionMapPass();
125125
Pass* createPrintStackIRPass();
126+
Pass* createPropagateGlobalsGloballyPass();
126127
Pass* createRemoveNonJSOpsPass();
127128
Pass* createRemoveImportsPass();
128129
Pass* createRemoveMemoryPass();

test/lit/help/wasm-opt.test

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -374,6 +374,9 @@
374374
;; CHECK-NEXT: --print-stack-ir print out Stack IR (useful for
375375
;; CHECK-NEXT: internal debugging)
376376
;; CHECK-NEXT:
377+
;; CHECK-NEXT: --propagate-globals-globally propagate global values to other
378+
;; CHECK-NEXT: globals (useful for tests)
379+
;; CHECK-NEXT:
377380
;; CHECK-NEXT: --remove-imports removes imports and replaces
378381
;; CHECK-NEXT: them with nops
379382
;; CHECK-NEXT:

test/lit/help/wasm2js.test

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -324,6 +324,9 @@
324324
;; CHECK-NEXT: --print-stack-ir print out Stack IR (useful for
325325
;; CHECK-NEXT: internal debugging)
326326
;; CHECK-NEXT:
327+
;; CHECK-NEXT: --propagate-globals-globally propagate global values to other
328+
;; CHECK-NEXT: globals (useful for tests)
329+
;; CHECK-NEXT:
327330
;; CHECK-NEXT: --remove-imports removes imports and replaces
328331
;; CHECK-NEXT: them with nops
329332
;; CHECK-NEXT:
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited.
2+
3+
;; RUN: foreach %s %t wasm-opt --propagate-globals-globally -all -S -o - | filecheck %s
4+
;; RUN: foreach %s %t wasm-opt --simplify-globals -all -S -o - | filecheck %s --check-prefix SIMGB
5+
6+
;; Check that propagate-globals-globally propagates constants globally but not
7+
;; to code. Also run simplify-globals for comparison, which does do that.
8+
9+
(module
10+
;; CHECK: (type $struct (struct (field stringref) (field stringref)))
11+
;; SIMGB: (type $struct (struct (field stringref) (field stringref)))
12+
(type $struct (struct stringref stringref))
13+
14+
;; CHECK: (type $1 (func))
15+
16+
;; CHECK: (global $A i32 (i32.const 42))
17+
;; SIMGB: (type $1 (func))
18+
19+
;; SIMGB: (global $A i32 (i32.const 42))
20+
(global $A i32 (i32.const 42))
21+
22+
;; CHECK: (global $B i32 (i32.const 42))
23+
;; SIMGB: (global $B i32 (i32.const 42))
24+
(global $B i32 (global.get $A))
25+
26+
;; CHECK: (global $C i32 (i32.add
27+
;; CHECK-NEXT: (i32.const 42)
28+
;; CHECK-NEXT: (i32.const 42)
29+
;; CHECK-NEXT: ))
30+
;; SIMGB: (global $C i32 (i32.add
31+
;; SIMGB-NEXT: (i32.const 42)
32+
;; SIMGB-NEXT: (i32.const 42)
33+
;; SIMGB-NEXT: ))
34+
(global $C i32 (i32.add
35+
;; Both of these can be optimized, including $B which reads from $A.
36+
(global.get $B)
37+
(global.get $A)
38+
))
39+
40+
;; CHECK: (global $D (ref string) (string.const "foo"))
41+
;; SIMGB: (global $D (ref string) (string.const "foo"))
42+
(global $D (ref string) (string.const "foo"))
43+
44+
;; CHECK: (global $E (ref string) (string.const "bar"))
45+
;; SIMGB: (global $E (ref string) (string.const "bar"))
46+
(global $E (ref string) (string.const "bar"))
47+
48+
;; CHECK: (global $G (ref $struct) (struct.new $struct
49+
;; CHECK-NEXT: (string.const "foo")
50+
;; CHECK-NEXT: (string.const "bar")
51+
;; CHECK-NEXT: ))
52+
;; SIMGB: (global $G (ref $struct) (struct.new $struct
53+
;; SIMGB-NEXT: (string.const "foo")
54+
;; SIMGB-NEXT: (string.const "bar")
55+
;; SIMGB-NEXT: ))
56+
(global $G (ref $struct) (struct.new $struct
57+
(global.get $D)
58+
(global.get $E)
59+
))
60+
61+
;; CHECK: (func $test (type $1)
62+
;; CHECK-NEXT: (drop
63+
;; CHECK-NEXT: (global.get $A)
64+
;; CHECK-NEXT: )
65+
;; CHECK-NEXT: (drop
66+
;; CHECK-NEXT: (global.get $B)
67+
;; CHECK-NEXT: )
68+
;; CHECK-NEXT: (drop
69+
;; CHECK-NEXT: (global.get $C)
70+
;; CHECK-NEXT: )
71+
;; CHECK-NEXT: (drop
72+
;; CHECK-NEXT: (global.get $D)
73+
;; CHECK-NEXT: )
74+
;; CHECK-NEXT: )
75+
;; SIMGB: (func $test (type $1)
76+
;; SIMGB-NEXT: (drop
77+
;; SIMGB-NEXT: (i32.const 42)
78+
;; SIMGB-NEXT: )
79+
;; SIMGB-NEXT: (drop
80+
;; SIMGB-NEXT: (i32.const 42)
81+
;; SIMGB-NEXT: )
82+
;; SIMGB-NEXT: (drop
83+
;; SIMGB-NEXT: (global.get $C)
84+
;; SIMGB-NEXT: )
85+
;; SIMGB-NEXT: (drop
86+
;; SIMGB-NEXT: (string.const "foo")
87+
;; SIMGB-NEXT: )
88+
;; SIMGB-NEXT: )
89+
(func $test
90+
;; We should not change anything here: this pass propagates globals
91+
;; *globally*, and not to functions. (but simplify-globals does, except for
92+
;; $C which is not constant)
93+
(drop
94+
(global.get $A)
95+
)
96+
(drop
97+
(global.get $B)
98+
)
99+
(drop
100+
(global.get $C)
101+
)
102+
(drop
103+
(global.get $D)
104+
)
105+
)
106+
)

test/lit/passes/simplify-globals-nested.wast

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,11 @@
66
;; Test that we propagate globals into nested children of other globals.
77

88
(module
9-
;; CHECK: (type $struct (struct (field i32) (field i32)))
10-
(type $struct (struct i32 i32))
9+
;; CHECK: (type $struct (struct (field i32) (field i32) (field i32)))
10+
(type $struct (struct i32 i32 i32))
11+
12+
;; CHECK: (import "x" "y" (global $no i32))
13+
(import "x" "y" (global $no i32))
1114

1215
;; CHECK: (global $a i32 (i32.const 42))
1316
(global $a i32 (i32.const 42))
@@ -17,10 +20,12 @@
1720

1821
;; CHECK: (global $struct (ref $struct) (struct.new $struct
1922
;; CHECK-NEXT: (i32.const 42)
23+
;; CHECK-NEXT: (global.get $no)
2024
;; CHECK-NEXT: (i32.const 1337)
2125
;; CHECK-NEXT: ))
2226
(global $struct (ref $struct) (struct.new $struct
2327
(global.get $a)
28+
(global.get $no) ;; the middle item cannot be optimized
2429
(global.get $b)
2530
))
2631
)

0 commit comments

Comments
 (0)