optimize global.gets
diff --git a/src/passes/ConstantFieldPropagation.cpp b/src/passes/ConstantFieldPropagation.cpp index 5689f52..8bed4f8 100644 --- a/src/passes/ConstantFieldPropagation.cpp +++ b/src/passes/ConstantFieldPropagation.cpp
@@ -580,6 +580,13 @@ } return structInference; + } else if (auto* get = curr->dynCast<GlobalGet>()) { + // If a global is immutable, we can use information about its value, + // including even a precise type since it likely is a struct.new. + auto* global = getModule()->getGlobal(get->name); + if (!global->mutable_) { + return inferType(global->init); + } } // We didn't manage to do any better than the declared type.
diff --git a/test/lit/passes/cfp_local.wast b/test/lit/passes/cfp_local.wast index aa25108..46e8e0b 100644 --- a/test/lit/passes/cfp_local.wast +++ b/test/lit/passes/cfp_local.wast
@@ -1486,12 +1486,11 @@ ;; As before, but the vtables are in immutable globals. (module ;; A function type that receives |this| and returns an i32. - ;; CHECK: (type $parent (struct (field (ref $parent.vtable)))) - ;; CHECK: (type $func (func (param anyref) (result i32))) (type $func (func (param anyref) (result i32))) ;; A parent struct type, with a vtable. + ;; CHECK: (type $parent (struct (field (ref $parent.vtable)))) (type $parent (struct (field (ref $parent.vtable)))) ;; CHECK: (type $parent.vtable (struct (field (ref $func)))) @@ -1602,18 +1601,28 @@ ;; CHECK-NEXT: (i32.add ;; CHECK-NEXT: (call_ref ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (struct.get $parent.vtable 0 - ;; CHECK-NEXT: (struct.get $parent 0 - ;; CHECK-NEXT: (local.get $x) + ;; CHECK-NEXT: (block (result (ref $func)) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (ref.as_non_null + ;; CHECK-NEXT: (struct.get $parent 0 + ;; CHECK-NEXT: (local.get $x) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (ref.func $parent.func) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (call_ref ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (struct.get $parent.vtable 0 - ;; CHECK-NEXT: (struct.get $parent 0 - ;; CHECK-NEXT: (local.get $x) + ;; CHECK-NEXT: (block (result (ref $func)) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (ref.as_non_null + ;; CHECK-NEXT: (struct.get $parent 0 + ;; CHECK-NEXT: (local.get $x) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (ref.func $parent.func) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: )