diff options
author | Thomas Lively <tlively@google.com> | 2023-08-09 17:18:13 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-08-09 21:18:13 +0000 |
commit | c003a01aa855bfa1377237eb2ce788b9fa96e839 (patch) | |
tree | 454d2b6de36ea56de5d3e310d81f02155aa73db1 /test/lit/passes | |
parent | d0bdf202463323a0b9f3be95fe2c64765a84a4b7 (diff) | |
download | binaryen-c003a01aa855bfa1377237eb2ce788b9fa96e839.tar.gz binaryen-c003a01aa855bfa1377237eb2ce788b9fa96e839.tar.bz2 binaryen-c003a01aa855bfa1377237eb2ce788b9fa96e839.zip |
Remove legacy WasmGC instructions (#5861)
Remove old, experimental instructions and type encodings that will not be
shipped as part of WasmGC. Updating the encodings and text format to match the
final spec is left as future work.
Diffstat (limited to 'test/lit/passes')
-rw-r--r-- | test/lit/passes/abstract-type-refining.wast | 15 | ||||
-rw-r--r-- | test/lit/passes/code-pushing-gc.wast | 18 | ||||
-rw-r--r-- | test/lit/passes/gufa-refs.wast | 2 | ||||
-rw-r--r-- | test/lit/passes/merge-blocks.wast | 2 | ||||
-rw-r--r-- | test/lit/passes/optimize-instructions-gc-tnh.wast | 58 | ||||
-rw-r--r-- | test/lit/passes/optimize-instructions-gc.wast | 42 | ||||
-rw-r--r-- | test/lit/passes/remove-unused-brs-gc.wast | 101 | ||||
-rw-r--r-- | test/lit/passes/remove-unused-brs_all-features.wast | 135 | ||||
-rw-r--r-- | test/lit/passes/vacuum-gc.wast | 6 | ||||
-rw-r--r-- | test/lit/passes/vacuum-tnh.wast | 6 |
10 files changed, 148 insertions, 237 deletions
diff --git a/test/lit/passes/abstract-type-refining.wast b/test/lit/passes/abstract-type-refining.wast index 220de9656..af2b210fd 100644 --- a/test/lit/passes/abstract-type-refining.wast +++ b/test/lit/passes/abstract-type-refining.wast @@ -217,11 +217,6 @@ ;; YESTNH-NEXT: (local.get $x) ;; YESTNH-NEXT: ) ;; YESTNH-NEXT: ) - ;; YESTNH-NEXT: (drop - ;; YESTNH-NEXT: (ref.cast i31 - ;; YESTNH-NEXT: (local.get $x) - ;; YESTNH-NEXT: ) - ;; YESTNH-NEXT: ) ;; YESTNH-NEXT: ) ;; NO_TNH: (func $basic (type $anyref_=>_none) (param $x anyref) ;; NO_TNH-NEXT: (drop @@ -229,11 +224,6 @@ ;; NO_TNH-NEXT: (local.get $x) ;; NO_TNH-NEXT: ) ;; NO_TNH-NEXT: ) - ;; NO_TNH-NEXT: (drop - ;; NO_TNH-NEXT: (ref.cast i31 - ;; NO_TNH-NEXT: (local.get $x) - ;; NO_TNH-NEXT: ) - ;; NO_TNH-NEXT: ) ;; NO_TNH-NEXT: ) (func $basic (param $x anyref) ;; Casts to basic types should not be modified. @@ -242,11 +232,6 @@ (local.get $x) ) ) - (drop - (ref.as_i31 - (local.get $x) - ) - ) ) ;; YESTNH: (func $locals (type $none_=>_none) diff --git a/test/lit/passes/code-pushing-gc.wast b/test/lit/passes/code-pushing-gc.wast index 56cfc8777..9587d5ab7 100644 --- a/test/lit/passes/code-pushing-gc.wast +++ b/test/lit/passes/code-pushing-gc.wast @@ -7,8 +7,8 @@ ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (block $out (result (ref func)) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (br_on_cast $out (ref $none_=>_none) (ref func) - ;; CHECK-NEXT: (ref.func $br_on) + ;; CHECK-NEXT: (br_on_cast $out nullfuncref (ref func) + ;; CHECK-NEXT: (ref.null nofunc) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (local.set $x @@ -28,8 +28,8 @@ ;; We can push the local.set past the br_on. (local.set $x (ref.func $br_on)) (drop - (br_on_func $out - (ref.func $br_on) + (br_on_cast $out funcref (ref func) + (ref.null nofunc) ) ) (drop @@ -48,8 +48,8 @@ ;; CHECK-NEXT: (ref.func $br_on_no) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (br_on_cast $out (ref $none_=>_none) (ref func) - ;; CHECK-NEXT: (ref.func $br_on_no) + ;; CHECK-NEXT: (br_on_cast $out nullfuncref (ref func) + ;; CHECK-NEXT: (ref.null nofunc) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (ref.func $br_on_no) @@ -61,13 +61,13 @@ ;; CHECK-NEXT: ) (func $br_on_no (local $x (ref null func)) - ;; We can't push here since the local.get is outside of the loop. + ;; We can't push here since the local.get is outside of the block. (drop (block $out (result (ref func)) (local.set $x (ref.func $br_on_no)) (drop - (br_on_func $out - (ref.func $br_on_no) + (br_on_cast $out funcref (ref func) + (ref.null nofunc) ) ) (ref.func $br_on_no) diff --git a/test/lit/passes/gufa-refs.wast b/test/lit/passes/gufa-refs.wast index 7c7aa8c40..b82fbf148 100644 --- a/test/lit/passes/gufa-refs.wast +++ b/test/lit/passes/gufa-refs.wast @@ -54,7 +54,7 @@ (ref.is_null (loop $loop (result (ref func)) (nop) - (ref.as_func + (ref.cast func (ref.as_non_null (ref.null func) ) diff --git a/test/lit/passes/merge-blocks.wast b/test/lit/passes/merge-blocks.wast index 2b3afa771..02772c9b6 100644 --- a/test/lit/passes/merge-blocks.wast +++ b/test/lit/passes/merge-blocks.wast @@ -34,7 +34,7 @@ (block $label$1 (result (ref null i31)) ;; this block type must stay, we ;; cannot remove it due to the br_on (drop - (br_on_i31 $label$1 + (br_on_cast $label$1 anyref (ref i31) (ref.null any) ) ) diff --git a/test/lit/passes/optimize-instructions-gc-tnh.wast b/test/lit/passes/optimize-instructions-gc-tnh.wast index 831d229a2..155ac82cf 100644 --- a/test/lit/passes/optimize-instructions-gc-tnh.wast +++ b/test/lit/passes/optimize-instructions-gc-tnh.wast @@ -146,7 +146,7 @@ ;; NO_TNH-NEXT: ) ;; NO_TNH-NEXT: ) (func $ref.is_b (param $a eqref) (param $f funcref) (result i32) - ;; Here we only have a cast, and no ref.as operations that force the value + ;; Here we only have a cast, and no cast operations that force the value ;; to be non-nullable. That means we cannot remove the ref.is, but we can ;; remove the cast in TNH. (drop @@ -164,28 +164,56 @@ ) ) - ;; TNH: (func $ref.is_func (type $funcref_=>_i32) (param $a funcref) (result i32) + ;; TNH: (func $ref.test (type $eqref_=>_i32) (param $a eqref) (result i32) ;; TNH-NEXT: (drop - ;; TNH-NEXT: (ref.as_non_null - ;; TNH-NEXT: (local.get $a) + ;; TNH-NEXT: (block (result i32) + ;; TNH-NEXT: (drop + ;; TNH-NEXT: (ref.cast null i31 + ;; TNH-NEXT: (local.get $a) + ;; TNH-NEXT: ) + ;; TNH-NEXT: ) + ;; TNH-NEXT: (i32.const 1) ;; TNH-NEXT: ) ;; TNH-NEXT: ) - ;; TNH-NEXT: (i32.const 1) + ;; TNH-NEXT: (block (result i32) + ;; TNH-NEXT: (drop + ;; TNH-NEXT: (ref.as_non_null + ;; TNH-NEXT: (local.get $a) + ;; TNH-NEXT: ) + ;; TNH-NEXT: ) + ;; TNH-NEXT: (i32.const 1) + ;; TNH-NEXT: ) ;; TNH-NEXT: ) - ;; NO_TNH: (func $ref.is_func (type $funcref_=>_i32) (param $a funcref) (result i32) + ;; NO_TNH: (func $ref.test (type $eqref_=>_i32) (param $a eqref) (result i32) ;; NO_TNH-NEXT: (drop - ;; NO_TNH-NEXT: (ref.as_non_null - ;; NO_TNH-NEXT: (local.get $a) + ;; NO_TNH-NEXT: (block (result i32) + ;; NO_TNH-NEXT: (drop + ;; NO_TNH-NEXT: (ref.cast null i31 + ;; NO_TNH-NEXT: (local.get $a) + ;; NO_TNH-NEXT: ) + ;; NO_TNH-NEXT: ) + ;; NO_TNH-NEXT: (i32.const 1) + ;; NO_TNH-NEXT: ) + ;; NO_TNH-NEXT: ) + ;; NO_TNH-NEXT: (block (result i32) + ;; NO_TNH-NEXT: (drop + ;; NO_TNH-NEXT: (ref.as_non_null + ;; NO_TNH-NEXT: (local.get $a) + ;; NO_TNH-NEXT: ) ;; NO_TNH-NEXT: ) + ;; NO_TNH-NEXT: (i32.const 1) ;; NO_TNH-NEXT: ) - ;; NO_TNH-NEXT: (i32.const 1) ;; NO_TNH-NEXT: ) - (func $ref.is_func (param $a funcref) (result i32) - ;; The check must succeed. We can return 1 here, and drop the rest, with or - ;; without TNH (in particular, TNH should not just remove the cast but not - ;; return a 1). - (ref.is_func - (ref.as_func + (func $ref.test (param $a eqref) (result i32) + (drop + (ref.test null i31 + (ref.cast null i31 + (local.get $a) + ) + ) + ) + (ref.test eq + (ref.cast eq (local.get $a) ) ) diff --git a/test/lit/passes/optimize-instructions-gc.wast b/test/lit/passes/optimize-instructions-gc.wast index 34070487b..9f33c55a3 100644 --- a/test/lit/passes/optimize-instructions-gc.wast +++ b/test/lit/passes/optimize-instructions-gc.wast @@ -122,8 +122,8 @@ ) ;; ref.is_null is not needed on a non-nullable value, and if something is - ;; a func we don't need that either etc. if we know the result - ;; CHECK: (func $unneeded_is (type $ref|$struct|_ref|func|_ref|i31|_=>_none) (param $struct (ref $struct)) (param $func (ref func)) (param $i31 (ref i31)) + ;; cast to its own type, we don't need that either, etc. + ;; CHECK: (func $unneeded_test (type $ref|$struct|_ref|func|_ref|i31|_=>_none) (param $struct (ref $struct)) (param $func (ref func)) (param $i31 (ref i31)) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (block (result i32) ;; CHECK-NEXT: (drop @@ -149,7 +149,7 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - (func $unneeded_is + (func $unneeded_test (param $struct (ref $struct)) (param $func (ref func)) (param $i31 (ref i31)) @@ -157,16 +157,16 @@ (ref.is_null (local.get $struct)) ) (drop - (ref.is_func (local.get $func)) + (ref.test func (local.get $func)) ) (drop - (ref.is_i31 (local.get $i31)) + (ref.test i31 (local.get $i31)) ) ) ;; similar to $unneeded_is, but the values are nullable. we can at least ;; leave just the null check. - ;; CHECK: (func $unneeded_is_null (type $ref?|$struct|_funcref_i31ref_=>_none) (param $struct (ref null $struct)) (param $func funcref) (param $i31 i31ref) + ;; CHECK: (func $unneeded_test_null (type $ref?|$struct|_funcref_i31ref_=>_none) (param $struct (ref null $struct)) (param $func funcref) (param $i31 i31ref) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (ref.is_null ;; CHECK-NEXT: (local.get $struct) @@ -187,7 +187,7 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - (func $unneeded_is_null + (func $unneeded_test_null (param $struct (ref null $struct)) (param $func (ref null func)) (param $i31 (ref null i31)) @@ -197,17 +197,17 @@ ;; This can be optimized to !is_null rather than ref.test func, since we ;; know the heap type is what we want, so the only possible issue is a null. (drop - (ref.is_func (local.get $func)) + (ref.test func (local.get $func)) ) ;; This can be optimized similarly. (drop - (ref.is_i31 (local.get $i31)) + (ref.test i31 (local.get $i31)) ) ) ;; ref.as_non_null is not needed on a non-nullable value, and if something is ;; a func we don't need that either etc., and can just return the value. - ;; CHECK: (func $unneeded_as (type $ref|$struct|_ref|func|_ref|i31|_=>_none) (param $struct (ref $struct)) (param $func (ref func)) (param $i31 (ref i31)) + ;; CHECK: (func $unneeded_cast (type $ref|$struct|_ref|func|_ref|i31|_=>_none) (param $struct (ref $struct)) (param $func (ref func)) (param $i31 (ref i31)) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (local.get $struct) ;; CHECK-NEXT: ) @@ -218,7 +218,7 @@ ;; CHECK-NEXT: (local.get $i31) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - (func $unneeded_as + (func $unneeded_cast (param $struct (ref $struct)) (param $func (ref func)) (param $i31 (ref i31)) @@ -226,16 +226,16 @@ (ref.as_non_null (local.get $struct)) ) (drop - (ref.as_func (local.get $func)) + (ref.cast func (local.get $func)) ) (drop - (ref.as_i31 (local.get $i31)) + (ref.cast i31 (local.get $i31)) ) ) - ;; similar to $unneeded_as, but the values are nullable. we can turn the + ;; similar to $unneeded_cast, but the values are nullable. we can turn the ;; more specific things into ref.as_non_null. - ;; CHECK: (func $unneeded_as_null (type $ref?|$struct|_funcref_i31ref_=>_none) (param $struct (ref null $struct)) (param $func funcref) (param $i31 i31ref) + ;; CHECK: (func $unneeded_cast_null (type $ref?|$struct|_funcref_i31ref_=>_none) (param $struct (ref null $struct)) (param $func funcref) (param $i31 i31ref) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (ref.as_non_null ;; CHECK-NEXT: (local.get $struct) @@ -252,7 +252,7 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - (func $unneeded_as_null + (func $unneeded_cast_null (param $struct (ref null $struct)) (param $func (ref null func)) (param $i31 (ref null i31)) @@ -260,10 +260,10 @@ (ref.as_non_null (local.get $struct)) ) (drop - (ref.as_func (local.get $func)) + (ref.cast func (local.get $func)) ) (drop - (ref.as_i31 (local.get $i31)) + (ref.cast i31 (local.get $i31)) ) ) @@ -285,10 +285,10 @@ (func $unneeded_unreachability ;; unreachable instructions can simply be ignored (drop - (ref.is_func (unreachable)) + (ref.test func (unreachable)) ) (drop - (ref.as_func (unreachable)) + (ref.cast func (unreachable)) ) ) @@ -617,7 +617,7 @@ ;; This will trap, so we can emit an unreachable. (drop (ref.cast $struct - (ref.as_i31 + (ref.cast i31 (local.get $x) ) ) diff --git a/test/lit/passes/remove-unused-brs-gc.wast b/test/lit/passes/remove-unused-brs-gc.wast index e063fa482..50ffd9583 100644 --- a/test/lit/passes/remove-unused-brs-gc.wast +++ b/test/lit/passes/remove-unused-brs-gc.wast @@ -11,57 +11,6 @@ (type $struct2 (struct)) ) - ;; CHECK: (func $br_on_non_i31-1 (type $none_=>_none) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block $any (result (ref null $struct)) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (br $any - ;; CHECK-NEXT: (struct.new_default $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (ref.null none) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $br_on_non_i31-1 - (drop - (block $any (result anyref) - (drop - ;; An struct is not an i31, and so we should branch. - (br_on_non_i31 $any - (struct.new $struct) - ) - ) - (ref.null any) - ) - ) - ) - ;; CHECK: (func $br_on_non_i31-2 (type $none_=>_none) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block $any (result nullref) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i31.new - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (ref.null none) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $br_on_non_i31-2 - (drop - (block $any (result anyref) - (drop - ;; An i31 is provided here, and so we will not branch. - (br_on_non_i31 $any - (i31.new (i32.const 0)) - ) - ) - (ref.null any) - ) - ) - ) - ;; CHECK: (func $br_on-if (type $ref|struct|_=>_none) (param $0 (ref struct)) ;; CHECK-NEXT: (block $label ;; CHECK-NEXT: (drop @@ -93,51 +42,51 @@ ) ) - ;; CHECK: (func $nested_br_on (type $none_=>_i31ref) (result i31ref) - ;; CHECK-NEXT: (block $label$1 (result (ref i31)) + ;; CHECK: (func $br_on_cast (type $none_=>_ref|$struct|) (result (ref $struct)) + ;; CHECK-NEXT: (block $block (result (ref $struct)) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (br $label$1 - ;; CHECK-NEXT: (i31.new - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (br $block + ;; CHECK-NEXT: (struct.new_default $struct) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (unreachable) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - (func $nested_br_on (result i31ref) - (block $label$1 (result i31ref) + (func $br_on_cast (result (ref $struct)) + (block $block (result (ref $struct)) (drop - ;; The inner br_on_i31 will become a direct br since the type proves it - ;; is in fact data. That then becomes unreachable, and the parent must - ;; handle that properly (do nothing without hitting an assertion). - (br_on_i31 $label$1 - (br_on_i31 $label$1 - (i31.new (i32.const 0)) - ) + ;; This static cast can be computed at compile time: it will definitely be + ;; taken, so we can turn it into a normal br. + (br_on_cast $block anyref (ref $struct) + (struct.new $struct) ) ) (unreachable) ) ) - ;; CHECK: (func $br_on_cast (type $none_=>_ref|$struct|) (result (ref $struct)) - ;; CHECK-NEXT: (block $block (result (ref $struct)) + ;; CHECK: (func $nested_br_on_cast (type $none_=>_i31ref) (result i31ref) + ;; CHECK-NEXT: (block $label$1 (result (ref i31)) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (br $block - ;; CHECK-NEXT: (struct.new_default $struct) + ;; CHECK-NEXT: (br $label$1 + ;; CHECK-NEXT: (i31.new + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (unreachable) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - (func $br_on_cast (result (ref $struct)) - (block $block (result (ref $struct)) + (func $nested_br_on_cast (result i31ref) + (block $label$1 (result i31ref) (drop - ;; This static cast can be computed at compile time: it will definitely be - ;; taken, so we can turn it into a normal br. - (br_on_cast $block anyref (ref $struct) - (struct.new $struct) + ;; The inner br_on_cast will become a direct br since the type proves it + ;; is in fact i31. That then becomes unreachable, and the parent must + ;; handle that properly (do nothing without hitting an assertion). + (br_on_cast $label$1 (ref any) (ref i31) + (br_on_cast $label$1 (ref any) (ref i31) + (i31.new (i32.const 0)) + ) ) ) (unreachable) diff --git a/test/lit/passes/remove-unused-brs_all-features.wast b/test/lit/passes/remove-unused-brs_all-features.wast index 8ca632040..c93f25df2 100644 --- a/test/lit/passes/remove-unused-brs_all-features.wast +++ b/test/lit/passes/remove-unused-brs_all-features.wast @@ -8,10 +8,10 @@ (type $vector (array (mut i32))) ;; CHECK: (type $struct (struct (field (ref null $vector)))) (type $struct (struct (field (ref null $vector)))) - ;; CHECK: (type $ref|func|_=>_none (func (param (ref func)))) - ;; CHECK: (type $i32_=>_none (func (param i32))) + ;; CHECK: (type $none_=>_funcref (func (result funcref))) + ;; CHECK: (type $none_=>_ref?|$struct| (func (result (ref null $struct)))) ;; CHECK: (type $none_=>_f64 (func (result f64))) @@ -20,9 +20,11 @@ ;; CHECK: (type $i32_=>_funcref (func (param i32) (result funcref))) + ;; CHECK: (type $none_=>_none (func)) + ;; CHECK: (import "out" "log" (func $log (type $i32_=>_none) (param i32))) (import "out" "log" (func $log (param i32))) - ;; CHECK: (elem declare func $br_on-to-br $i32_=>_none $none_=>_i32) + ;; CHECK: (elem declare func $br_on_non_null $br_on_null $i32_=>_none $none_=>_i32) ;; CHECK: (func $foo (type $none_=>_ref?|$struct|) (result (ref null $struct)) ;; CHECK-NEXT: (if (result (ref null $struct)) @@ -116,110 +118,57 @@ ) ) - ;; CHECK: (func $br_on-to-br (type $ref|func|_=>_none) (param $func (ref func)) - ;; CHECK-NEXT: (call $log - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) + ;; CHECK: (func $br_on_null (type $none_=>_none) ;; CHECK-NEXT: (block $null ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.func $br_on-to-br) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $log - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $log - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block $func (result (ref $ref|func|_=>_none)) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (br $func - ;; CHECK-NEXT: (ref.func $br_on-to-br) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $log - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (ref.func $br_on-to-br) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $log - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block $i31 (result (ref i31)) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (br $i31 - ;; CHECK-NEXT: (i31.new - ;; CHECK-NEXT: (i32.const 42) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $log - ;; CHECK-NEXT: (i32.const 5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i31.new - ;; CHECK-NEXT: (i32.const 1337) + ;; CHECK-NEXT: (br_on_null $null + ;; CHECK-NEXT: (ref.null nofunc) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $log - ;; CHECK-NEXT: (i32.const 6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block $non-null (result (ref $ref|func|_=>_none)) - ;; CHECK-NEXT: (br $non-null - ;; CHECK-NEXT: (ref.func $br_on-to-br) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $log - ;; CHECK-NEXT: (i32.const 7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (ref.func $br_on-to-br) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (ref.func $br_on_null) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - (func $br_on-to-br (param $func (ref func)) - (call $log (i32.const 0)) + (func $br_on_null (block $null - ;; a non-null reference is not null, and the br is never taken + ;; A null reference to bottom is definitely null, and the br is always taken. + ;; TODO: Optimize this. (drop - (br_on_null $null (ref.func $br_on-to-br)) + (br_on_null $null (ref.null nofunc)) ) - (call $log (i32.const 1)) - ) - (call $log (i32.const 2)) - (drop - (block $func (result funcref) - ;; a non-null function reference means we always take the br - (drop - (br_on_func $func (ref.func $br_on-to-br)) - ) - (call $log (i32.const 3)) - (ref.func $br_on-to-br) + ;; On the other hand, if we know the input is not null, the branch will never + ;; be taken. + (drop + (br_on_null $null (ref.func $br_on_null)) ) ) - (call $log (i32.const 4)) - (drop - (block $i31 (result i31ref) - ;; a non-null i31 reference means we always take the br - (drop - (br_on_i31 $i31 - (i31.new (i32.const 42)) - ) - ) - (call $log (i32.const 5)) - (i31.new (i32.const 1337)) + ) + + ;; CHECK: (func $br_on_non_null (type $none_=>_funcref) (result funcref) + ;; CHECK-NEXT: (block $non-null (result (ref $none_=>_funcref)) + ;; CHECK-NEXT: (br $non-null + ;; CHECK-NEXT: (ref.func $br_on_non_null) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (br_on_non_null $non-null + ;; CHECK-NEXT: (ref.null nofunc) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (ref.func $br_on_non_null) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $br_on_non_null (result funcref) + (block $non-null (result (ref func)) + ;; A non-null reference is not null, and the br is always taken. + (br_on_non_null $non-null + (ref.func $br_on_non_null) ) - ) - (call $log (i32.const 6)) - (drop - (block $non-null (result (ref func)) - ;; a non-null reference is not null, and the br is always taken - (br_on_non_null $non-null (ref.func $br_on-to-br)) - (call $log (i32.const 7)) - (ref.func $br_on-to-br) + ;; On the other hand, if we know the input is null, the branch will never be + ;; taken. + ;; TODO: Optimize this. + (br_on_non_null $non-null + (ref.null nofunc) ) + (ref.func $br_on_non_null) ) ) ) diff --git a/test/lit/passes/vacuum-gc.wast b/test/lit/passes/vacuum-gc.wast index 69dbe0b89..fcdeb8cd2 100644 --- a/test/lit/passes/vacuum-gc.wast +++ b/test/lit/passes/vacuum-gc.wast @@ -18,13 +18,13 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.cast i31 + ;; CHECK-NEXT: (ref.cast null i31 ;; CHECK-NEXT: (local.get $x) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $drop-ref-as (param $x anyref) - ;; Without -tnh, we must assume all ref_as* can have a trap effect, and so + ;; Without -tnh, we must assume all casts can have a trap effect, and so ;; we cannot remove anything here. (drop (ref.as_non_null @@ -32,7 +32,7 @@ ) ) (drop - (ref.as_i31 + (ref.cast null i31 (local.get $x) ) ) diff --git a/test/lit/passes/vacuum-tnh.wast b/test/lit/passes/vacuum-tnh.wast index f60c4c5cb..c3de8c21c 100644 --- a/test/lit/passes/vacuum-tnh.wast +++ b/test/lit/passes/vacuum-tnh.wast @@ -33,7 +33,7 @@ ;; NO_TNH-NEXT: ) ;; NO_TNH-NEXT: ) ;; NO_TNH-NEXT: (drop - ;; NO_TNH-NEXT: (ref.cast i31 + ;; NO_TNH-NEXT: (ref.cast null i31 ;; NO_TNH-NEXT: (local.get $y) ;; NO_TNH-NEXT: ) ;; NO_TNH-NEXT: ) @@ -55,9 +55,9 @@ ) ) - ;; Other ref.as* as well. + ;; Other casts as well. (drop - (ref.as_i31 + (ref.cast null i31 (local.get $y) ) ) |