diff --git a/src/passes/SimplifyGlobals.cpp b/src/passes/SimplifyGlobals.cpp index 294e70fd7a4..84cf29be89f 100644 --- a/src/passes/SimplifyGlobals.cpp +++ b/src/passes/SimplifyGlobals.cpp @@ -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 diff --git a/test/lit/passes/simplify-globals-gc.wast b/test/lit/passes/simplify-globals-gc.wast index 71a36ae79d8..a30015825e7 100644 --- a/test/lit/passes/simplify-globals-gc.wast +++ b/test/lit/passes/simplify-globals-gc.wast @@ -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)) +) + +;; 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)) +) +