diff options
Diffstat (limited to 'test/lit')
-rw-r--r-- | test/lit/passes/signature-pruning.wast | 195 |
1 files changed, 193 insertions, 2 deletions
diff --git a/test/lit/passes/signature-pruning.wast b/test/lit/passes/signature-pruning.wast index 86a26130c..3c27ee874 100644 --- a/test/lit/passes/signature-pruning.wast +++ b/test/lit/passes/signature-pruning.wast @@ -356,11 +356,14 @@ ) ;; CHECK: (func $caller (type $none_=>_none) + ;; CHECK-NEXT: (local $x i32) ;; CHECK-NEXT: (call $foo) ;; CHECK-NEXT: ) (func $caller + (local $x i32) (call $foo - (i32.const 0) + ;; (avoid passing in a constant value to avoid other opts kicking in) + (local.get $x) ) ) ) @@ -556,18 +559,40 @@ ) ) -;; Exports cannot be optimized. +;; Exports cannot be optimized in any way: we cannot remove parameters from +;; them, and also we cannot apply constant parameter values either. (module ;; CHECK: (type $sig (func_subtype (param i32) func)) (type $sig (func_subtype (param i32) func)) + ;; CHECK: (type $none_=>_none (func_subtype func)) + ;; CHECK: (export "foo" (func $foo)) + ;; CHECK: (export "bar" (func $bar)) + ;; CHECK: (func $foo (type $sig) (param $i32 i32) ;; CHECK-NEXT: (nop) ;; CHECK-NEXT: ) (func $foo (export "foo") (type $sig) (param $i32 i32) ) + + ;; CHECK: (func $bar (type $sig) (param $i32 i32) + ;; CHECK-NEXT: (nop) + ;; CHECK-NEXT: ) + (func $bar (export "bar") (type $sig) (param $i32 i32) + ) + + ;; CHECK: (func $call-bar (type $none_=>_none) + ;; CHECK-NEXT: (call $bar + ;; CHECK-NEXT: (i32.const 42) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $call-bar + (call $bar + (i32.const 42) + ) + ) ) ;; Two functions with two different types have an unused parameter. After @@ -595,3 +620,169 @@ ) ) +(module + ;; CHECK: (type $sig-foo (func_subtype func)) + (type $sig-foo (func_subtype (param i32) func)) + ;; CHECK: (type $sig-bar (func_subtype (param i32) func)) + (type $sig-bar (func_subtype (param i32) func)) + + (memory 1 1) + + ;; CHECK: (memory $0 1 1) + + ;; CHECK: (func $foo (type $sig-foo) + ;; CHECK-NEXT: (local $0 i32) + ;; CHECK-NEXT: (local.set $0 + ;; CHECK-NEXT: (i32.const 42) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (block + ;; CHECK-NEXT: (i32.store + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: (local.get $0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (call $foo) + ;; CHECK-NEXT: (call $foo) + ;; CHECK-NEXT: (call $foo) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $foo (type $sig-foo) (param $i32 i32) + ;; This function is always called with the same constant, and we can + ;; apply that constant here and prune the param. + (i32.store + (i32.const 0) + (local.get $i32) + ) + (call $foo (i32.const 42)) + (call $foo (i32.const 42)) + (call $foo (i32.const 42)) + ) + + ;; CHECK: (func $bar (type $sig-bar) (param $i32 i32) + ;; CHECK-NEXT: (i32.store + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: (local.get $i32) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (call $bar + ;; CHECK-NEXT: (i32.const 42) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (call $bar + ;; CHECK-NEXT: (i32.const 43) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $bar (type $sig-bar) (param $i32 i32) + ;; This function is called with various values, and cannot be optimized like + ;; the previous one. + (i32.store + (i32.const 0) + (local.get $i32) + ) + (call $bar (i32.const 42)) + (call $bar (i32.const 43)) + ) +) + +;; As above, but $foo's parameter is a ref.func, which is also a constant +;; value that we can optimize in the case of $foo (but not $bar, again, as $bar +;; is not always sent a constant value). +(module + ;; CHECK: (type $sig-foo (func_subtype func)) + (type $sig-foo (func_subtype (param funcref) func)) + ;; CHECK: (type $sig-bar (func_subtype (param funcref) func)) + (type $sig-bar (func_subtype (param funcref) func)) + + (memory 1 1) + + ;; CHECK: (memory $0 1 1) + + ;; CHECK: (elem declare func $bar $foo) + + ;; CHECK: (func $foo (type $sig-foo) + ;; CHECK-NEXT: (local $0 funcref) + ;; CHECK-NEXT: (local.set $0 + ;; CHECK-NEXT: (ref.func $foo) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (block + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (local.get $0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (call $foo) + ;; CHECK-NEXT: (call $foo) + ;; CHECK-NEXT: (call $foo) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $foo (type $sig-foo) (param $funcref funcref) + (drop (local.get $funcref)) + (call $foo (ref.func $foo)) + (call $foo (ref.func $foo)) + (call $foo (ref.func $foo)) + ) + + ;; CHECK: (func $bar (type $sig-bar) (param $funcref funcref) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (local.get $funcref) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (call $bar + ;; CHECK-NEXT: (ref.func $foo) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (call $bar + ;; CHECK-NEXT: (ref.func $bar) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $bar (type $sig-bar) (param $funcref funcref) + (drop (local.get $funcref)) + (call $bar (ref.func $foo)) + (call $bar (ref.func $bar)) + ) +) + +;; As above, but the values are now ref.nulls. All nulls compare equal, so we +;; can still optimize even though the types differ. +(module + ;; CHECK: (type $sig-foo (func_subtype func)) + (type $sig-foo (func_subtype (param anyref) func)) + ;; CHECK: (type $sig-bar (func_subtype (param anyref) func)) + (type $sig-bar (func_subtype (param anyref) func)) + + (memory 1 1) + + ;; CHECK: (memory $0 1 1) + + ;; CHECK: (elem declare func $foo) + + ;; CHECK: (func $foo (type $sig-foo) + ;; CHECK-NEXT: (local $0 anyref) + ;; CHECK-NEXT: (local.set $0 + ;; CHECK-NEXT: (ref.null any) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (block + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (local.get $0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (call $foo) + ;; CHECK-NEXT: (call $foo) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $foo (type $sig-foo) (param $anyref anyref) + (drop (local.get $anyref)) + (call $foo (ref.null any)) + (call $foo (ref.null func)) + ) + + ;; CHECK: (func $bar (type $sig-bar) (param $anyref anyref) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (local.get $anyref) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (call $bar + ;; CHECK-NEXT: (ref.func $foo) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (call $bar + ;; CHECK-NEXT: (ref.null func) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $bar (type $sig-bar) (param $anyref anyref) + (drop (local.get $anyref)) + ;; Mixing a null with something else prevents optimization, of course. + (call $bar (ref.func $foo)) + (call $bar (ref.null func)) + ) +) |