diff options
author | Alon Zakai <azakai@google.com> | 2023-01-03 16:31:42 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-01-03 16:31:42 -0800 |
commit | ce267f5b800a906b9556657bf98ad92166d3f431 (patch) | |
tree | 2a96880567c15067e1b6f7879b801e026c8436f2 /test/lit/passes/gsi.wast | |
parent | 6a52a44255d57efd27b3979bd7b2ef3ad132f54a (diff) | |
download | binaryen-ce267f5b800a906b9556657bf98ad92166d3f431.tar.gz binaryen-ce267f5b800a906b9556657bf98ad92166d3f431.tar.bz2 binaryen-ce267f5b800a906b9556657bf98ad92166d3f431.zip |
[Wasm GC] Fix GlobalStructInference reasoning on unoptimizability (#5381)
We have a data structure there, typeGlobals, which maps types to the list of
globals for that type. Previously we used the convention of not having an
entry in the map to mean that a type is unoptimizable. However, this was not
used consistently, and in fact one place could insert to the map in a dangerous
way: a subtype's global is added to the list of globals of the super, and
typeGlobals[super].add(sub-global) would then effectively make an unoptimizable
super into an optimizable one.
To fix that, check for unoptimizability before propagating sub-globals. We do
still use the convention of not keeping data in typeGlobals for unoptimizable
things as it is a minor optimization to avoid wasted work.
Fixes #5379
Diffstat (limited to 'test/lit/passes/gsi.wast')
-rw-r--r-- | test/lit/passes/gsi.wast | 159 |
1 files changed, 159 insertions, 0 deletions
diff --git a/test/lit/passes/gsi.wast b/test/lit/passes/gsi.wast index 4cec6aa3c..6fe4da95a 100644 --- a/test/lit/passes/gsi.wast +++ b/test/lit/passes/gsi.wast @@ -1268,3 +1268,162 @@ ) ) ) + +;; Two subtypes, each with a global. A get of the parent can be optimized into +;; a select, as it must read one of the children. +(module + ;; CHECK: (type $struct (struct (field i32))) + (type $struct (struct_subtype i32 data)) + + ;; CHECK: (type $sub-struct1 (struct_subtype (field i32) $struct)) + (type $sub-struct1 (struct_subtype i32 $struct)) + + ;; CHECK: (type $sub-struct2 (struct_subtype (field i32) $struct)) + (type $sub-struct2 (struct_subtype i32 $struct)) + + ;; CHECK: (type $ref?|$struct|_=>_none (func (param (ref null $struct)))) + + ;; CHECK: (global $global1 (ref $sub-struct1) (struct.new $sub-struct1 + ;; CHECK-NEXT: (i32.const 42) + ;; CHECK-NEXT: )) + (global $global1 (ref $sub-struct1) (struct.new $sub-struct1 + (i32.const 42) + )) + + ;; CHECK: (global $global2 (ref $sub-struct2) (struct.new $sub-struct2 + ;; CHECK-NEXT: (i32.const 1337) + ;; CHECK-NEXT: )) + (global $global2 (ref $sub-struct2) (struct.new $sub-struct2 + (i32.const 1337) + )) + + ;; CHECK: (func $test (type $ref?|$struct|_=>_none) (param $struct (ref null $struct)) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (select + ;; CHECK-NEXT: (i32.const 42) + ;; CHECK-NEXT: (i32.const 1337) + ;; CHECK-NEXT: (ref.eq + ;; CHECK-NEXT: (ref.as_non_null + ;; CHECK-NEXT: (local.get $struct) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (global.get $global1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $test (param $struct (ref null $struct)) + (drop + (struct.get $struct 0 + (local.get $struct) + ) + ) + ) +) + +;; As above, but now the parent is unoptimizable due to a struct.new in a +;; function. We must not optimize here to a select. +(module + ;; CHECK: (type $struct (struct (field i32))) + (type $struct (struct_subtype i32 data)) + + ;; CHECK: (type $sub-struct1 (struct_subtype (field i32) $struct)) + (type $sub-struct1 (struct_subtype i32 $struct)) + + ;; CHECK: (type $sub-struct2 (struct_subtype (field i32) $struct)) + (type $sub-struct2 (struct_subtype i32 $struct)) + + ;; CHECK: (type $ref?|$struct|_=>_none (func (param (ref null $struct)))) + + ;; CHECK: (global $global1 (ref $sub-struct1) (struct.new $sub-struct1 + ;; CHECK-NEXT: (i32.const 42) + ;; CHECK-NEXT: )) + (global $global1 (ref $sub-struct1) (struct.new $sub-struct1 + (i32.const 42) + )) + + ;; CHECK: (global $global2 (ref $sub-struct2) (struct.new $sub-struct2 + ;; CHECK-NEXT: (i32.const 1337) + ;; CHECK-NEXT: )) + (global $global2 (ref $sub-struct2) (struct.new $sub-struct2 + (i32.const 1337) + )) + + ;; CHECK: (func $test (type $ref?|$struct|_=>_none) (param $struct (ref null $struct)) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (struct.new $struct + ;; CHECK-NEXT: (i32.const 999999) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (struct.get $struct 0 + ;; CHECK-NEXT: (local.get $struct) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $test (param $struct (ref null $struct)) + (drop + (struct.new $struct + (i32.const 999999) + ) + ) + (drop + (struct.get $struct 0 + (local.get $struct) + ) + ) + ) +) + +;; As above, the struct.new in a function is of a subtype. Again, we cannot +;; optimize, as unoptimizability spreads to supertypes. +(module + ;; CHECK: (type $struct (struct (field i32))) + (type $struct (struct_subtype i32 data)) + + ;; CHECK: (type $sub-struct1 (struct_subtype (field i32) $struct)) + (type $sub-struct1 (struct_subtype i32 $struct)) + + ;; CHECK: (type $sub-struct2 (struct_subtype (field i32) $struct)) + (type $sub-struct2 (struct_subtype i32 $struct)) + + ;; CHECK: (type $ref?|$struct|_=>_none (func (param (ref null $struct)))) + + ;; CHECK: (global $global1 (ref $sub-struct1) (struct.new $sub-struct1 + ;; CHECK-NEXT: (i32.const 42) + ;; CHECK-NEXT: )) + (global $global1 (ref $sub-struct1) (struct.new $sub-struct1 + (i32.const 42) + )) + + ;; CHECK: (global $global2 (ref $sub-struct2) (struct.new $sub-struct2 + ;; CHECK-NEXT: (i32.const 1337) + ;; CHECK-NEXT: )) + (global $global2 (ref $sub-struct2) (struct.new $sub-struct2 + (i32.const 1337) + )) + + ;; CHECK: (func $test (type $ref?|$struct|_=>_none) (param $struct (ref null $struct)) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (struct.new $sub-struct1 + ;; CHECK-NEXT: (i32.const 999999) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (struct.get $struct 0 + ;; CHECK-NEXT: (local.get $struct) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $test (param $struct (ref null $struct)) + (drop + (struct.new $sub-struct1 + (i32.const 999999) + ) + ) + (drop + (struct.get $struct 0 + (local.get $struct) + ) + ) + ) +) |