diff options
Diffstat (limited to 'test/lit/passes')
-rw-r--r-- | test/lit/passes/gto_and_cfp_in_O.wast | 28 | ||||
-rw-r--r-- | test/lit/passes/remove-unused-module-elements-refs.wast | 184 |
2 files changed, 200 insertions, 12 deletions
diff --git a/test/lit/passes/gto_and_cfp_in_O.wast b/test/lit/passes/gto_and_cfp_in_O.wast index a36bbc4ea..9d385d0f9 100644 --- a/test/lit/passes/gto_and_cfp_in_O.wast +++ b/test/lit/passes/gto_and_cfp_in_O.wast @@ -1,18 +1,37 @@ ;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. -;; RUN: foreach %s %t wasm-opt -O -all --nominal -S -o - | filecheck %s +;; RUN: foreach %s %t wasm-opt -O -all --nominal --closed-world -S -o - | filecheck %s +;; RUN: foreach %s %t wasm-opt -O -all --nominal -S -o - | filecheck %s --check-prefix OPEN_WORLD ;; Test that -O, with nominal typing + GC enabled, will run global type -;; optimization in conjunction with constant field propagation etc. +;; optimization in conjunction with constant field propagation etc. But, in an +;; open world we do not run them. (module + ;; OPEN_WORLD: (type $struct (struct (field (mut funcref)) (field (mut i32)))) (type $struct (struct_subtype (field (mut funcref)) (field (mut i32)) data)) + ;; OPEN_WORLD: (type $none_=>_none (func)) + + ;; OPEN_WORLD: (type $none_=>_i32 (func (result i32))) + + ;; OPEN_WORLD: (global $glob (ref $struct) (struct.new $struct + ;; OPEN_WORLD-NEXT: (ref.func $by-ref) + ;; OPEN_WORLD-NEXT: (i32.const 100) + ;; OPEN_WORLD-NEXT: )) (global $glob (ref $struct) (struct.new $struct (ref.func $by-ref) (i32.const 100) )) + ;; OPEN_WORLD: (export "main" (func $main)) + + ;; OPEN_WORLD: (func $by-ref (type $none_=>_none) (; has Stack IR ;) + ;; OPEN_WORLD-NEXT: (struct.set $struct 1 + ;; OPEN_WORLD-NEXT: (global.get $glob) + ;; OPEN_WORLD-NEXT: (i32.const 200) + ;; OPEN_WORLD-NEXT: ) + ;; OPEN_WORLD-NEXT: ) (func $by-ref ;; This function is kept alive by the reference in $glob. After we remove ;; the field that the funcref is written to, we remove the funcref, which @@ -33,6 +52,11 @@ ;; CHECK: (func $main (type $none_=>_i32) (; has Stack IR ;) (result i32) ;; CHECK-NEXT: (i32.const 100) ;; CHECK-NEXT: ) + ;; OPEN_WORLD: (func $main (type $none_=>_i32) (; has Stack IR ;) (result i32) + ;; OPEN_WORLD-NEXT: (struct.get $struct 1 + ;; OPEN_WORLD-NEXT: (global.get $glob) + ;; OPEN_WORLD-NEXT: ) + ;; OPEN_WORLD-NEXT: ) (func $main (export "main") (result i32) ;; After all the above optimizations, we can infer that $main should simply ;; return 100. diff --git a/test/lit/passes/remove-unused-module-elements-refs.wast b/test/lit/passes/remove-unused-module-elements-refs.wast index 1e23099b9..8e4ed70a7 100644 --- a/test/lit/passes/remove-unused-module-elements-refs.wast +++ b/test/lit/passes/remove-unused-module-elements-refs.wast @@ -1,12 +1,22 @@ ;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. -;; RUN: foreach %s %t wasm-opt --remove-unused-module-elements --nominal -all -S -o - | filecheck %s +;; RUN: foreach %s %t wasm-opt --remove-unused-module-elements --closed-world --nominal -all -S -o - | filecheck %s +;; RUN: foreach %s %t wasm-opt --remove-unused-module-elements --nominal -all -S -o - | filecheck %s --check-prefix OPEN_WORLD + +;; Test both open world (default) and closed world. In a closed world we can do +;; more with function refs, as we assume nothing calls them on the outside, so +;; if no calls exist to the right type, the function is not reached. (module ;; CHECK: (type $A (func)) + ;; OPEN_WORLD: (type $A (func)) (type $A (func)) + ;; CHECK: (type $ref?|$A|_=>_none (func (param (ref null $A)))) ;; CHECK: (type $B (func)) + ;; OPEN_WORLD: (type $ref?|$A|_=>_none (func (param (ref null $A)))) + + ;; OPEN_WORLD: (type $B (func)) (type $B (func)) ;; CHECK: (elem declare func $target-A $target-B) @@ -30,6 +40,27 @@ ;; CHECK-NEXT: (unreachable) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) + ;; OPEN_WORLD: (elem declare func $target-A $target-B) + + ;; OPEN_WORLD: (export "foo" (func $foo)) + + ;; OPEN_WORLD: (func $foo (type $ref?|$A|_=>_none) (param $A (ref null $A)) + ;; OPEN_WORLD-NEXT: (drop + ;; OPEN_WORLD-NEXT: (ref.func $target-A) + ;; OPEN_WORLD-NEXT: ) + ;; OPEN_WORLD-NEXT: (drop + ;; OPEN_WORLD-NEXT: (ref.func $target-B) + ;; OPEN_WORLD-NEXT: ) + ;; OPEN_WORLD-NEXT: (call_ref $A + ;; OPEN_WORLD-NEXT: (local.get $A) + ;; OPEN_WORLD-NEXT: ) + ;; OPEN_WORLD-NEXT: (block ;; (replaces something unreachable we can't emit) + ;; OPEN_WORLD-NEXT: (drop + ;; OPEN_WORLD-NEXT: (unreachable) + ;; OPEN_WORLD-NEXT: ) + ;; OPEN_WORLD-NEXT: (unreachable) + ;; OPEN_WORLD-NEXT: ) + ;; OPEN_WORLD-NEXT: ) (func $foo (export "foo") (param $A (ref null $A)) ;; This export has two RefFuncs, and one CallRef. (drop @@ -51,6 +82,9 @@ ;; CHECK: (func $target-A (type $A) ;; CHECK-NEXT: (nop) ;; CHECK-NEXT: ) + ;; OPEN_WORLD: (func $target-A (type $A) + ;; OPEN_WORLD-NEXT: (nop) + ;; OPEN_WORLD-NEXT: ) (func $target-A (type $A) ;; This function is reachable from the export "foo": there is a RefFunc and ;; a CallRef for it there. @@ -64,6 +98,9 @@ ;; CHECK: (func $target-B (type $B) ;; CHECK-NEXT: (unreachable) ;; CHECK-NEXT: ) + ;; OPEN_WORLD: (func $target-B (type $B) + ;; OPEN_WORLD-NEXT: (nop) + ;; OPEN_WORLD-NEXT: ) (func $target-B (type $B) ;; This function is not reachable. We have a RefFunc in "foo" but no ;; suitable CallRef. @@ -71,33 +108,51 @@ ;; Note that we cannot remove the function, as the RefFunc must refer to ;; something in order to validate. But we can clear out the body of this ;; function with an unreachable. + ;; + ;; As mentioned above, in an open world we cannot optimize here, so the + ;; function body will remain empty as a nop, and not turn into an + ;; unreachable. ) ) ;; As above, but reverse the order inside $foo, so we see the CallRef first. (module ;; CHECK: (type $A (func)) + ;; OPEN_WORLD: (type $A (func)) (type $A (func)) (type $B (func)) + ;; CHECK: (type $ref?|$A|_=>_none (func (param (ref null $A)))) + ;; CHECK: (elem declare func $target-A) ;; CHECK: (export "foo" (func $foo)) - ;; CHECK: (func $foo (type $A) - ;; CHECK-NEXT: (block ;; (replaces something unreachable we can't emit) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.null nofunc) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) + ;; CHECK: (func $foo (type $ref?|$A|_=>_none) (param $A (ref null $A)) + ;; CHECK-NEXT: (call_ref $A + ;; CHECK-NEXT: (local.get $A) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (ref.func $target-A) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - (func $foo (export "foo") + ;; OPEN_WORLD: (type $ref?|$A|_=>_none (func (param (ref null $A)))) + + ;; OPEN_WORLD: (elem declare func $target-A) + + ;; OPEN_WORLD: (export "foo" (func $foo)) + + ;; OPEN_WORLD: (func $foo (type $ref?|$A|_=>_none) (param $A (ref null $A)) + ;; OPEN_WORLD-NEXT: (call_ref $A + ;; OPEN_WORLD-NEXT: (local.get $A) + ;; OPEN_WORLD-NEXT: ) + ;; OPEN_WORLD-NEXT: (drop + ;; OPEN_WORLD-NEXT: (ref.func $target-A) + ;; OPEN_WORLD-NEXT: ) + ;; OPEN_WORLD-NEXT: ) + (func $foo (export "foo") (param $A (ref null $A)) (call_ref $A - (ref.null $A) + (local.get $A) ) (drop (ref.func $target-A) @@ -105,8 +160,11 @@ ) ;; CHECK: (func $target-A (type $A) - ;; CHECK-NEXT: (unreachable) + ;; CHECK-NEXT: (nop) ;; CHECK-NEXT: ) + ;; OPEN_WORLD: (func $target-A (type $A) + ;; OPEN_WORLD-NEXT: (nop) + ;; OPEN_WORLD-NEXT: ) (func $target-A (type $A) ;; This function is reachable. ) @@ -119,6 +177,7 @@ ;; As above, but interleave CallRefs with RefFuncs. (module ;; CHECK: (type $A (func)) + ;; OPEN_WORLD: (type $A (func)) (type $A (func)) (type $B (func)) @@ -142,6 +201,26 @@ ;; CHECK-NEXT: (ref.func $target-A-2) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) + ;; OPEN_WORLD: (type $ref?|$A|_=>_none (func (param (ref null $A)))) + + ;; OPEN_WORLD: (elem declare func $target-A-1 $target-A-2) + + ;; OPEN_WORLD: (export "foo" (func $foo)) + + ;; OPEN_WORLD: (func $foo (type $ref?|$A|_=>_none) (param $A (ref null $A)) + ;; OPEN_WORLD-NEXT: (call_ref $A + ;; OPEN_WORLD-NEXT: (local.get $A) + ;; OPEN_WORLD-NEXT: ) + ;; OPEN_WORLD-NEXT: (drop + ;; OPEN_WORLD-NEXT: (ref.func $target-A-1) + ;; OPEN_WORLD-NEXT: ) + ;; OPEN_WORLD-NEXT: (call_ref $A + ;; OPEN_WORLD-NEXT: (local.get $A) + ;; OPEN_WORLD-NEXT: ) + ;; OPEN_WORLD-NEXT: (drop + ;; OPEN_WORLD-NEXT: (ref.func $target-A-2) + ;; OPEN_WORLD-NEXT: ) + ;; OPEN_WORLD-NEXT: ) (func $foo (export "foo") (param $A (ref null $A)) (call_ref $A (local.get $A) @@ -160,6 +239,9 @@ ;; CHECK: (func $target-A-1 (type $A) ;; CHECK-NEXT: (nop) ;; CHECK-NEXT: ) + ;; OPEN_WORLD: (func $target-A-1 (type $A) + ;; OPEN_WORLD-NEXT: (nop) + ;; OPEN_WORLD-NEXT: ) (func $target-A-1 (type $A) ;; This function is reachable. ) @@ -167,6 +249,9 @@ ;; CHECK: (func $target-A-2 (type $A) ;; CHECK-NEXT: (nop) ;; CHECK-NEXT: ) + ;; OPEN_WORLD: (func $target-A-2 (type $A) + ;; OPEN_WORLD-NEXT: (nop) + ;; OPEN_WORLD-NEXT: ) (func $target-A-2 (type $A) ;; This function is reachable. ) @@ -180,6 +265,7 @@ ;; same. (module ;; CHECK: (type $A (func)) + ;; OPEN_WORLD: (type $A (func)) (type $A (func)) (type $B (func)) @@ -203,6 +289,26 @@ ;; CHECK-NEXT: (local.get $A) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) + ;; OPEN_WORLD: (type $ref?|$A|_=>_none (func (param (ref null $A)))) + + ;; OPEN_WORLD: (elem declare func $target-A-1 $target-A-2) + + ;; OPEN_WORLD: (export "foo" (func $foo)) + + ;; OPEN_WORLD: (func $foo (type $ref?|$A|_=>_none) (param $A (ref null $A)) + ;; OPEN_WORLD-NEXT: (drop + ;; OPEN_WORLD-NEXT: (ref.func $target-A-1) + ;; OPEN_WORLD-NEXT: ) + ;; OPEN_WORLD-NEXT: (call_ref $A + ;; OPEN_WORLD-NEXT: (local.get $A) + ;; OPEN_WORLD-NEXT: ) + ;; OPEN_WORLD-NEXT: (drop + ;; OPEN_WORLD-NEXT: (ref.func $target-A-2) + ;; OPEN_WORLD-NEXT: ) + ;; OPEN_WORLD-NEXT: (call_ref $A + ;; OPEN_WORLD-NEXT: (local.get $A) + ;; OPEN_WORLD-NEXT: ) + ;; OPEN_WORLD-NEXT: ) (func $foo (export "foo") (param $A (ref null $A)) (drop (ref.func $target-A-1) @@ -221,6 +327,9 @@ ;; CHECK: (func $target-A-1 (type $A) ;; CHECK-NEXT: (nop) ;; CHECK-NEXT: ) + ;; OPEN_WORLD: (func $target-A-1 (type $A) + ;; OPEN_WORLD-NEXT: (nop) + ;; OPEN_WORLD-NEXT: ) (func $target-A-1 (type $A) ;; This function is reachable. ) @@ -228,6 +337,9 @@ ;; CHECK: (func $target-A-2 (type $A) ;; CHECK-NEXT: (nop) ;; CHECK-NEXT: ) + ;; OPEN_WORLD: (func $target-A-2 (type $A) + ;; OPEN_WORLD-NEXT: (nop) + ;; OPEN_WORLD-NEXT: ) (func $target-A-2 (type $A) ;; This function is reachable. ) @@ -241,15 +353,20 @@ ;; but for now other imports do not (until we add a flag for closed-world). (module ;; CHECK: (type $A (func)) + ;; OPEN_WORLD: (type $A (func)) (type $A (func)) ;; CHECK: (type $funcref_=>_none (func (param funcref))) ;; CHECK: (import "binaryen-intrinsics" "call.without.effects" (func $call-without-effects (param funcref))) + ;; OPEN_WORLD: (type $funcref_=>_none (func (param funcref))) + + ;; OPEN_WORLD: (import "binaryen-intrinsics" "call.without.effects" (func $call-without-effects (param funcref))) (import "binaryen-intrinsics" "call.without.effects" (func $call-without-effects (param funcref))) ;; CHECK: (import "other" "import" (func $other-import (param funcref))) + ;; OPEN_WORLD: (import "other" "import" (func $other-import (param funcref))) (import "other" "import" (func $other-import (param funcref))) @@ -265,6 +382,18 @@ ;; CHECK-NEXT: (ref.func $target-drop) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) + ;; OPEN_WORLD: (elem declare func $target-drop $target-keep) + + ;; OPEN_WORLD: (export "foo" (func $foo)) + + ;; OPEN_WORLD: (func $foo (type $A) + ;; OPEN_WORLD-NEXT: (call $call-without-effects + ;; OPEN_WORLD-NEXT: (ref.func $target-keep) + ;; OPEN_WORLD-NEXT: ) + ;; OPEN_WORLD-NEXT: (call $other-import + ;; OPEN_WORLD-NEXT: (ref.func $target-drop) + ;; OPEN_WORLD-NEXT: ) + ;; OPEN_WORLD-NEXT: ) (func $foo (export "foo") ;; Calling the intrinsic with a reference is considered a call of the ;; reference, so we will not remove $target-keep. @@ -280,13 +409,20 @@ ;; CHECK: (func $target-keep (type $A) ;; CHECK-NEXT: (nop) ;; CHECK-NEXT: ) + ;; OPEN_WORLD: (func $target-keep (type $A) + ;; OPEN_WORLD-NEXT: (nop) + ;; OPEN_WORLD-NEXT: ) (func $target-keep (type $A) ) ;; CHECK: (func $target-drop (type $A) ;; CHECK-NEXT: (unreachable) ;; CHECK-NEXT: ) + ;; OPEN_WORLD: (func $target-drop (type $A) + ;; OPEN_WORLD-NEXT: (nop) + ;; OPEN_WORLD-NEXT: ) (func $target-drop (type $A) + ;; In a closed world we can turn this body into unreachable. ) ) @@ -294,6 +430,7 @@ ;; function being called. (module ;; CHECK: (type $A (func)) + ;; OPEN_WORLD: (type $A (func)) (type $A (func)) ;; CHECK: (type $funcref_=>_none (func (param funcref))) @@ -301,10 +438,16 @@ ;; CHECK: (type $ref?|$A|_=>_none (func (param (ref null $A)))) ;; CHECK: (import "binaryen-intrinsics" "call.without.effects" (func $call-without-effects (param funcref))) + ;; OPEN_WORLD: (type $funcref_=>_none (func (param funcref))) + + ;; OPEN_WORLD: (type $ref?|$A|_=>_none (func (param (ref null $A)))) + + ;; OPEN_WORLD: (import "binaryen-intrinsics" "call.without.effects" (func $call-without-effects (param funcref))) (import "binaryen-intrinsics" "call.without.effects" (func $call-without-effects (param funcref))) ;; CHECK: (import "other" "import" (func $other-import (param funcref))) + ;; OPEN_WORLD: (import "other" "import" (func $other-import (param funcref))) (import "other" "import" (func $other-import (param funcref))) @@ -323,6 +466,21 @@ ;; CHECK-NEXT: (ref.func $target-keep-2) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) + ;; OPEN_WORLD: (elem declare func $target-keep $target-keep-2) + + ;; OPEN_WORLD: (export "foo" (func $foo)) + + ;; OPEN_WORLD: (func $foo (type $ref?|$A|_=>_none) (param $A (ref null $A)) + ;; OPEN_WORLD-NEXT: (call $call-without-effects + ;; OPEN_WORLD-NEXT: (local.get $A) + ;; OPEN_WORLD-NEXT: ) + ;; OPEN_WORLD-NEXT: (drop + ;; OPEN_WORLD-NEXT: (ref.func $target-keep) + ;; OPEN_WORLD-NEXT: ) + ;; OPEN_WORLD-NEXT: (call $other-import + ;; OPEN_WORLD-NEXT: (ref.func $target-keep-2) + ;; OPEN_WORLD-NEXT: ) + ;; OPEN_WORLD-NEXT: ) (func $foo (export "foo") (param $A (ref null $A)) ;; Call the intrinsic without a RefFunc. All we infer here is the type, ;; which means we must assume anything with type $A (and a reference) can be @@ -341,12 +499,18 @@ ;; CHECK: (func $target-keep (type $A) ;; CHECK-NEXT: (nop) ;; CHECK-NEXT: ) + ;; OPEN_WORLD: (func $target-keep (type $A) + ;; OPEN_WORLD-NEXT: (nop) + ;; OPEN_WORLD-NEXT: ) (func $target-keep (type $A) ) ;; CHECK: (func $target-keep-2 (type $A) ;; CHECK-NEXT: (nop) ;; CHECK-NEXT: ) + ;; OPEN_WORLD: (func $target-keep-2 (type $A) + ;; OPEN_WORLD-NEXT: (nop) + ;; OPEN_WORLD-NEXT: ) (func $target-keep-2 (type $A) ) ) |