Skip to content

Commit

Permalink
Add a pass to propagate global constants to other globals (#6287)
Browse files Browse the repository at this point in the history
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).
  • Loading branch information
kripken authored Feb 8, 2024
1 parent f172920 commit 6e1e53f
Show file tree
Hide file tree
Showing 7 changed files with 140 additions and 4 deletions.
19 changes: 17 additions & 2 deletions src/passes/SimplifyGlobals.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -673,11 +673,12 @@ struct SimplifyGlobals : public Pass {
// go, as well as applying them where possible.
for (auto& global : module->globals) {
if (!global->imported()) {
// Apply globals to this value, which may turn it into a constant we can
// further propagate, or it may already have been one.
applyGlobals(global->init);
if (Properties::isConstantExpression(global->init)) {
constantGlobals[global->name] =
getLiteralsFromConstExpression(global->init);
} else {
applyGlobals(global->init);
}
}
}
Expand Down Expand Up @@ -762,10 +763,24 @@ struct SimplifyGlobals : public Pass {
}
};

// A pass mainly useful for testing that only performs the operation to
// propagate constant values between globals.
struct PropagateGlobalsGlobally : public SimplifyGlobals {
void run(Module* module_) override {
module = module_;

propagateConstantsToGlobals();
}
};

Pass* createSimplifyGlobalsPass() { return new SimplifyGlobals(false); }

Pass* createSimplifyGlobalsOptimizingPass() {
return new SimplifyGlobals(true);
}

Pass* createPropagateGlobalsGloballyPass() {
return new PropagateGlobalsGlobally();
}

} // namespace wasm
3 changes: 3 additions & 0 deletions src/passes/pass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -369,6 +369,9 @@ void PassRegistry::registerPasses() {
registerPass("print-stack-ir",
"print out Stack IR (useful for internal debugging)",
createPrintStackIRPass);
registerPass("propagate-globals-globally",
"propagate global values to other globals (useful for tests)",
createPropagateGlobalsGloballyPass);
registerPass("remove-non-js-ops",
"removes operations incompatible with js",
createRemoveNonJSOpsPass);
Expand Down
1 change: 1 addition & 0 deletions src/passes/passes.h
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ Pass* createPrintCallGraphPass();
Pass* createPrintFeaturesPass();
Pass* createPrintFunctionMapPass();
Pass* createPrintStackIRPass();
Pass* createPropagateGlobalsGloballyPass();
Pass* createRemoveNonJSOpsPass();
Pass* createRemoveImportsPass();
Pass* createRemoveMemoryPass();
Expand Down
3 changes: 3 additions & 0 deletions test/lit/help/wasm-opt.test
Original file line number Diff line number Diff line change
Expand Up @@ -374,6 +374,9 @@
;; CHECK-NEXT: --print-stack-ir print out Stack IR (useful for
;; CHECK-NEXT: internal debugging)
;; CHECK-NEXT:
;; CHECK-NEXT: --propagate-globals-globally propagate global values to other
;; CHECK-NEXT: globals (useful for tests)
;; CHECK-NEXT:
;; CHECK-NEXT: --remove-imports removes imports and replaces
;; CHECK-NEXT: them with nops
;; CHECK-NEXT:
Expand Down
3 changes: 3 additions & 0 deletions test/lit/help/wasm2js.test
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,9 @@
;; CHECK-NEXT: --print-stack-ir print out Stack IR (useful for
;; CHECK-NEXT: internal debugging)
;; CHECK-NEXT:
;; CHECK-NEXT: --propagate-globals-globally propagate global values to other
;; CHECK-NEXT: globals (useful for tests)
;; CHECK-NEXT:
;; CHECK-NEXT: --remove-imports removes imports and replaces
;; CHECK-NEXT: them with nops
;; CHECK-NEXT:
Expand Down
106 changes: 106 additions & 0 deletions test/lit/passes/propagate-globals-globally.wast
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited.

;; RUN: foreach %s %t wasm-opt --propagate-globals-globally -all -S -o - | filecheck %s
;; RUN: foreach %s %t wasm-opt --simplify-globals -all -S -o - | filecheck %s --check-prefix SIMGB

;; Check that propagate-globals-globally propagates constants globally but not
;; to code. Also run simplify-globals for comparison, which does do that.

(module
;; CHECK: (type $struct (struct (field stringref) (field stringref)))
;; SIMGB: (type $struct (struct (field stringref) (field stringref)))
(type $struct (struct stringref stringref))

;; CHECK: (type $1 (func))

;; CHECK: (global $A i32 (i32.const 42))
;; SIMGB: (type $1 (func))

;; SIMGB: (global $A i32 (i32.const 42))
(global $A i32 (i32.const 42))

;; CHECK: (global $B i32 (i32.const 42))
;; SIMGB: (global $B i32 (i32.const 42))
(global $B i32 (global.get $A))

;; CHECK: (global $C i32 (i32.add
;; CHECK-NEXT: (i32.const 42)
;; CHECK-NEXT: (i32.const 42)
;; CHECK-NEXT: ))
;; SIMGB: (global $C i32 (i32.add
;; SIMGB-NEXT: (i32.const 42)
;; SIMGB-NEXT: (i32.const 42)
;; SIMGB-NEXT: ))
(global $C i32 (i32.add
;; Both of these can be optimized, including $B which reads from $A.
(global.get $B)
(global.get $A)
))

;; CHECK: (global $D (ref string) (string.const "foo"))
;; SIMGB: (global $D (ref string) (string.const "foo"))
(global $D (ref string) (string.const "foo"))

;; CHECK: (global $E (ref string) (string.const "bar"))
;; SIMGB: (global $E (ref string) (string.const "bar"))
(global $E (ref string) (string.const "bar"))

;; CHECK: (global $G (ref $struct) (struct.new $struct
;; CHECK-NEXT: (string.const "foo")
;; CHECK-NEXT: (string.const "bar")
;; CHECK-NEXT: ))
;; SIMGB: (global $G (ref $struct) (struct.new $struct
;; SIMGB-NEXT: (string.const "foo")
;; SIMGB-NEXT: (string.const "bar")
;; SIMGB-NEXT: ))
(global $G (ref $struct) (struct.new $struct
(global.get $D)
(global.get $E)
))

;; CHECK: (func $test (type $1)
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (global.get $A)
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (global.get $B)
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (global.get $C)
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (global.get $D)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; SIMGB: (func $test (type $1)
;; SIMGB-NEXT: (drop
;; SIMGB-NEXT: (i32.const 42)
;; SIMGB-NEXT: )
;; SIMGB-NEXT: (drop
;; SIMGB-NEXT: (i32.const 42)
;; SIMGB-NEXT: )
;; SIMGB-NEXT: (drop
;; SIMGB-NEXT: (global.get $C)
;; SIMGB-NEXT: )
;; SIMGB-NEXT: (drop
;; SIMGB-NEXT: (string.const "foo")
;; SIMGB-NEXT: )
;; SIMGB-NEXT: )
(func $test
;; We should not change anything here: this pass propagates globals
;; *globally*, and not to functions. (but simplify-globals does, except for
;; $C which is not constant)
(drop
(global.get $A)
)
(drop
(global.get $B)
)
(drop
(global.get $C)
)
(drop
(global.get $D)
)
)
)
9 changes: 7 additions & 2 deletions test/lit/passes/simplify-globals-nested.wast
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,11 @@
;; Test that we propagate globals into nested children of other globals.

(module
;; CHECK: (type $struct (struct (field i32) (field i32)))
(type $struct (struct i32 i32))
;; CHECK: (type $struct (struct (field i32) (field i32) (field i32)))
(type $struct (struct i32 i32 i32))

;; CHECK: (import "x" "y" (global $no i32))
(import "x" "y" (global $no i32))

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

;; CHECK: (global $struct (ref $struct) (struct.new $struct
;; CHECK-NEXT: (i32.const 42)
;; CHECK-NEXT: (global.get $no)
;; CHECK-NEXT: (i32.const 1337)
;; CHECK-NEXT: ))
(global $struct (ref $struct) (struct.new $struct
(global.get $a)
(global.get $no) ;; the middle item cannot be optimized
(global.get $b)
))
)
Expand Down

0 comments on commit 6e1e53f

Please sign in to comment.