Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions src/passes/SimplifyGlobals.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -738,10 +738,11 @@ struct SimplifyGlobals : public Pass {

void visitGlobalGet(GlobalGet* curr) {
// If this is a get of a global with a single get and no sets, then we
// can fold that code into here.
// can fold that code into here. We must also avoid an export, as it can
// have additional gets and sets that we do not see.
auto name = curr->name;
auto& info = infos[name];
if (info.written == 0 && info.read == 1) {
if (info.written == 0 && info.read == 1 && !info.exported) {
auto* global = wasm.getGlobal(name);
if (global->init) {
// Copy that global's code. For simplicity we copy it as we have to
Expand Down
31 changes: 31 additions & 0 deletions test/lit/passes/simplify-globals-gc.wast
Original file line number Diff line number Diff line change
Expand Up @@ -55,3 +55,34 @@
)
)

;; One global reads another, and should contain the same value. We should not
;; erroneously optimize the global.get to a struct.new, as struct.new generates
;; a new value each time, and the export allows that difference to be noticed.
;; TODO: We could flip the export to read $B instead, basically considering it
;; a use that we can modify, like global.gets that we already do.
(module
;; CHECK: (type $struct (struct))
(type $struct (struct))

;; CHECK: (global $A (ref $struct) (struct.new_default $struct))
(global $A (ref $struct) (struct.new_default $struct))

;; CHECK: (global $B (ref $struct) (global.get $A))
(global $B (ref $struct) (global.get $A))

;; CHECK: (export "A" (global $A))
(export "A" (global $A))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could still optimize by exporting $B instead. Maybe worth considering as a follow-up?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a TODO, that might be possible, not sure offhand about corner cases though.

)

;; Without that export, we only use $A once, and can fold it into that use.
(module
;; CHECK: (type $struct (struct))
(type $struct (struct))

;; CHECK: (global $A (ref $struct) (struct.new_default $struct))
(global $A (ref $struct) (struct.new_default $struct))

;; CHECK: (global $B (ref $struct) (struct.new_default $struct))
(global $B (ref $struct) (global.get $A))
)

Loading