diff options
author | Alon Zakai <azakai@google.com> | 2022-11-15 11:21:44 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-11-15 11:21:44 -0800 |
commit | 0ffafa5d4f4bca8a6ab77e193caacc5292218a5d (patch) | |
tree | b0ea0aa88f03e231ec746f2ad18f394106ac6c3e /test/lit/passes | |
parent | 59cbdd818dc3397a823a37e9821fd32f4522b2fc (diff) | |
download | binaryen-0ffafa5d4f4bca8a6ab77e193caacc5292218a5d.tar.gz binaryen-0ffafa5d4f4bca8a6ab77e193caacc5292218a5d.tar.bz2 binaryen-0ffafa5d4f4bca8a6ab77e193caacc5292218a5d.zip |
GlobalStructInference: Handle the case of just 1 value (#5259)
#5253 handled the case of just one possible global. It is also possible we have
multiple globals but just one value. This handles that case. (It slightly overlaps
with other passes, but as this pass actually identifies the creations of the objects
in globals, it has a guarantee of success that the others don't, and it is very easy
to just do given all the work done to handle the case of 2 values).
Also fix a minor bug in #5253 - we need to trap if the old reference were null.
That is, we know the reference must point to the only object ever created of
that type, but that is only if it is not null; if it's null we need to trap.
Diffstat (limited to 'test/lit/passes')
-rw-r--r-- | test/lit/passes/gsi.wast | 63 | ||||
-rw-r--r-- | test/lit/passes/gsi_vacuum_precompute.wast | 4 |
2 files changed, 61 insertions, 6 deletions
diff --git a/test/lit/passes/gsi.wast b/test/lit/passes/gsi.wast index ae54796d6..66ca43de8 100644 --- a/test/lit/passes/gsi.wast +++ b/test/lit/passes/gsi.wast @@ -121,7 +121,9 @@ ;; CHECK-NEXT: (struct.get $struct1 0 ;; CHECK-NEXT: (block (result (ref $struct1)) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $struct1) + ;; CHECK-NEXT: (ref.as_non_null + ;; CHECK-NEXT: (local.get $struct1) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (global.get $global1) ;; CHECK-NEXT: ) @@ -131,7 +133,9 @@ ;; CHECK-NEXT: (struct.get $struct2 0 ;; CHECK-NEXT: (block (result (ref $struct2)) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $struct2) + ;; CHECK-NEXT: (ref.as_non_null + ;; CHECK-NEXT: (local.get $struct2) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (global.get $global2) ;; CHECK-NEXT: ) @@ -846,7 +850,9 @@ ;; CHECK-NEXT: (struct.get $struct 0 ;; CHECK-NEXT: (block (result (ref $struct)) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $struct) + ;; CHECK-NEXT: (ref.as_non_null + ;; CHECK-NEXT: (local.get $struct) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (global.get $global2) ;; CHECK-NEXT: ) @@ -975,7 +981,9 @@ ;; CHECK-NEXT: (struct.get $struct1 0 ;; CHECK-NEXT: (block (result (ref $struct1)) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $struct1) + ;; CHECK-NEXT: (ref.as_non_null + ;; CHECK-NEXT: (local.get $struct1) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (global.get $global1) ;; CHECK-NEXT: ) @@ -985,7 +993,9 @@ ;; CHECK-NEXT: (struct.get $struct2 0 ;; CHECK-NEXT: (block (result (ref $struct2)) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $struct2) + ;; CHECK-NEXT: (ref.as_non_null + ;; CHECK-NEXT: (local.get $struct2) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (global.get $global2) ;; CHECK-NEXT: ) @@ -1123,3 +1133,46 @@ ) ) ) + +;; Multiple globals, but all the same value, so we do not even need a select and +;; can just apply the value. +(module + ;; CHECK: (type $struct (struct_subtype (field i32) data)) + (type $struct (struct i32)) + + ;; CHECK: (type $ref?|$struct|_=>_none (func_subtype (param (ref null $struct)) func)) + + ;; CHECK: (global $global1 (ref $struct) (struct.new $struct + ;; CHECK-NEXT: (i32.const 42) + ;; CHECK-NEXT: )) + (global $global1 (ref $struct) (struct.new $struct + (i32.const 42) + )) + + ;; CHECK: (global $global2 (ref $struct) (struct.new $struct + ;; CHECK-NEXT: (i32.const 42) + ;; CHECK-NEXT: )) + (global $global2 (ref $struct) (struct.new $struct + (i32.const 42) + )) + + ;; CHECK: (func $test (type $ref?|$struct|_=>_none) (param $struct (ref null $struct)) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (block (result i32) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (ref.as_non_null + ;; CHECK-NEXT: (local.get $struct) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 42) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $test (param $struct (ref null $struct)) + (drop + (struct.get $struct 0 + (local.get $struct) + ) + ) + ) +) diff --git a/test/lit/passes/gsi_vacuum_precompute.wast b/test/lit/passes/gsi_vacuum_precompute.wast index 404de1a7e..856499ba8 100644 --- a/test/lit/passes/gsi_vacuum_precompute.wast +++ b/test/lit/passes/gsi_vacuum_precompute.wast @@ -1,5 +1,5 @@ ;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. -;; RUN: foreach %s %t wasm-opt --nominal --gsi --vacuum --precompute -all -S -o - | filecheck %s +;; RUN: foreach %s %t wasm-opt --nominal --gsi --vacuum --precompute -tnh -all -S -o - | filecheck %s ;; Test a common pattern in j2wasm where itables are differentiated by type, but ;; vtables are not. For example, the vtable might be "hashable" and provide a @@ -16,6 +16,8 @@ ;; from a global.get of an itable, get a vtable, and get a ;; field in the vtable, and we end up optimizing to produce ;; the final value in that vtable. +;; * -tnh : This is needed for vacuum to successfully remove the dropped stuff +;; that could prevent later opts. (module ;; CHECK: (type $vtable (struct_subtype (field funcref) data)) |