diff options
Diffstat (limited to 'test')
-rw-r--r-- | test/lit/passes/dae_all-features.wast | 255 | ||||
-rw-r--r-- | test/lit/passes/dae_tnh.wast | 52 | ||||
-rw-r--r-- | test/lit/passes/signature-pruning.wast | 301 |
3 files changed, 545 insertions, 63 deletions
diff --git a/test/lit/passes/dae_all-features.wast b/test/lit/passes/dae_all-features.wast index d4390351f..17ea77942 100644 --- a/test/lit/passes/dae_all-features.wast +++ b/test/lit/passes/dae_all-features.wast @@ -109,25 +109,31 @@ (func $b33 (call $a3 (i32.const 4)) ) - ;; CHECK: (func $a4 (type $1) (param $x i32) + ;; CHECK: (func $a4 (type $0) + ;; CHECK-NEXT: (local $0 i32) + ;; CHECK-NEXT: (local.set $0 + ;; CHECK-NEXT: (i32.const 4) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: (nop) ;; CHECK-NEXT: ) - (func $a4 (param $x i32) ;; diff value, but with effects + (func $a4 (param $x i32) + ;; This function is called with one constant and one unreachable. We can + ;; remove the param despite the unreachable's effects. ) ;; CHECK: (func $b4 (type $0) - ;; CHECK-NEXT: (call $a4 - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (unreachable) ;; CHECK-NEXT: ) (func $b4 + ;; This call will vanish entirely, because the unreachable child executes + ;; first (so we cannot see here that we removed the parameter from $a4, but + ;; that can be confirmed in $a4 itself). (call $a4 (unreachable)) ) ;; CHECK: (func $b43 (type $0) - ;; CHECK-NEXT: (call $a4 - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (call $a4) ;; CHECK-NEXT: ) (func $b43 + ;; We will remove the parameter here. (call $a4 (i32.const 4)) ) ;; CHECK: (func $a5 (type $0) @@ -659,27 +665,33 @@ ) (module - ;; CHECK: (type $0 (func (param i32))) + ;; CHECK: (type $0 (func)) - ;; CHECK: (func $0 (type $0) (param $0 i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $0 + ;; CHECK: (func $0 (type $0) + ;; CHECK-NEXT: (local $0 i32) + ;; CHECK-NEXT: (local.set $0 + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (block + ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: (block + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (return) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (return) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return) ;; CHECK-NEXT: ) (func $0 (param $0 i32) (result i32) - ;; The result of this function can be removed, which makes us modify the - ;; returns (we should not return a value any more) and also the calls (the - ;; calls must be dropped). The returns here are nested in each other, and one - ;; is a recursive call to this function itself, which makes this a corner case - ;; we might emit invalid code for. + ;; The returns here are nested in each other, and one is a recursive call to + ;; this function itself, which makes this a corner case we might emit invalid + ;; code for. We end up removing the parameter, and then the call vanishes as + ;; it was unreachable; we also remove the return as well as it is dropped in + ;; the other caller, below. (return (drop (call $0 @@ -690,6 +702,17 @@ ) ) ) + + ;; CHECK: (func $other-call (type $0) + ;; CHECK-NEXT: (call $0) + ;; CHECK-NEXT: ) + (func $other-call + (drop + (call $0 + (i32.const 1) + ) + ) + ) ) (module @@ -727,3 +750,193 @@ ) ) ) + +(module + ;; CHECK: (type $0 (func (param f64) (result i32))) + + ;; CHECK: (func $target (type $0) (param $0 f64) (result i32) + ;; CHECK-NEXT: (local $1 i32) + ;; CHECK-NEXT: (local $2 i32) + ;; CHECK-NEXT: (local $3 i32) + ;; CHECK-NEXT: (local $4 i32) + ;; CHECK-NEXT: (local.set $1 + ;; CHECK-NEXT: (call $target + ;; CHECK-NEXT: (f64.const 1.1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (local.set $2 + ;; CHECK-NEXT: (call $target + ;; CHECK-NEXT: (f64.const 4.4) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (call $target + ;; CHECK-NEXT: (local.get $0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $target (param $a i32) (param $b f64) (param $c i32) (result i32) + ;; Test removing a parameter despite calls having interesting non-unreachable + ;; effects. This also tests recursion of such calls. We can remove all the i32 + ;; parameters here. + (call $target + (call $target + (i32.const 0) + (f64.const 1.1) + (i32.const 2) + ) + (local.get $b) + (call $target + (i32.const 3) + (f64.const 4.4) + (i32.const 5) + ) + ) + ) +) + +(module + ;; CHECK: (type $0 (func)) + + ;; CHECK: (type $v128 (func (result v128))) + (type $v128 (func (result v128))) + + ;; CHECK: (type $2 (func (result f32))) + + ;; CHECK: (table $0 10 funcref) + (table $0 10 funcref) + + ;; CHECK: (func $caller-effects (type $0) + ;; CHECK-NEXT: (local $0 v128) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (block (result f32) + ;; CHECK-NEXT: (local.set $0 + ;; CHECK-NEXT: (call_indirect $0 (type $v128) + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (call $target) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $caller-effects + (drop + (call $target + (i64.const 0) + ;; We'd like to remove this unused parameter, but it has effects, so we'll + ;; move it to a local first. + (call_indirect $0 (type $v128) + (i32.const 0) + ) + (i64.const 0) + ) + ) + ) + + ;; CHECK: (func $target (type $2) (result f32) + ;; CHECK-NEXT: (local $0 i64) + ;; CHECK-NEXT: (local $1 i64) + ;; CHECK-NEXT: (local $2 v128) + ;; CHECK-NEXT: (local.set $0 + ;; CHECK-NEXT: (i64.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (block + ;; CHECK-NEXT: (local.set $1 + ;; CHECK-NEXT: (i64.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (unreachable) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $target (param $0 i64) (param $1 v128) (param $2 i64) (result f32) + ;; All parameters here should vanish. + (unreachable) + ) +) + +(module + ;; CHECK: (type $0 (func (param i32 i64))) + + ;; CHECK: (type $1 (func (param i64 i64))) + + ;; CHECK: (func $caller-later-br (type $0) (param $x i32) (param $y i64) + ;; CHECK-NEXT: (local $2 i32) + ;; CHECK-NEXT: (block $block + ;; CHECK-NEXT: (block + ;; CHECK-NEXT: (local.set $2 + ;; CHECK-NEXT: (block (result i32) + ;; CHECK-NEXT: (if + ;; CHECK-NEXT: (local.get $x) + ;; CHECK-NEXT: (then + ;; CHECK-NEXT: (return) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 42) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (br $block) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (call $target + ;; CHECK-NEXT: (local.get $y) + ;; CHECK-NEXT: (local.get $y) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $caller-later-br (param $x i32) (param $y i64) + (block $block + (drop + (call $target + (i64.const 0) + ;; We'd like to remove this unused parameter, and we can do so by moving + ;; it to a local, but we need to be careful: the br right after us must be + ;; kept around, as it is the only thing that makes the outer block have + ;; type none and not unreachable. + (block (result i32) + (if + (local.get $x) + (then + (return) + ) + ) + (i32.const 42) + ) + ;; We'll move this around, but won't remove it, as explained above. + (br $block) + ) + ) + ) + ;; Another call, to show the effect of removing the i32 parameter (also, if + ;; no calls remain after removing the unreachable one before us, then the pass + ;; would stop before removing parameters in $target - we don't remove params + ;; from functions that look dead). + (drop + (call $target + (local.get $y) + (local.get $x) + (local.get $y) + ) + ) + ) + + ;; CHECK: (func $target (type $1) (param $0 i64) (param $1 i64) + ;; CHECK-NEXT: (local $2 i32) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (block (result f32) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (local.get $0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (local.get $1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (unreachable) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $target (param $0 i64) (param $1 i32) (param $2 i64) (result f32) + ;; The i32 parameter should vanish. + (drop + (local.get $0) + ) + (drop + (local.get $2) + ) + (unreachable) + ) +) diff --git a/test/lit/passes/dae_tnh.wast b/test/lit/passes/dae_tnh.wast index 33e6eb09b..6d75aed30 100644 --- a/test/lit/passes/dae_tnh.wast +++ b/test/lit/passes/dae_tnh.wast @@ -39,14 +39,18 @@ ;; CHECK: (type $1 (func (param i32))) ;; CHECK: (func $caller (type $0) - ;; CHECK-NEXT: (call $target - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (unreachable) ;; CHECK-NEXT: ) (func $caller - ;; Removing this parameter would require the type of the call to change from - ;; unreachable to none. We don't handle such complexity and ignore such - ;; cases. + ;; Removing this parameter would make the type of the call change from + ;; unreachable to none. But the call itself is in unreachable code, so we + ;; will replace it with an unreachable (and then, once the call is gone, the + ;; target can be better optimized; however, no other calls remain here, so + ;; the pass does nothing as it considers it dead at that point). + ;; + ;; This test verifies we do the proper thing even in TNH mode, as in TNH + ;; mode |unreachable| seems to have no effects, but for validation reasons + ;; we must still replace the call here. (call $target (unreachable) ) @@ -59,13 +63,40 @@ ) ) -;; As above, but use a return_call. We can optimize that, since return_calls -;; have type unreachable anyhow, and the optimization would not change the type. +;; As above but the called target has a result. +(module + ;; CHECK: (type $0 (func (result i32))) + + ;; CHECK: (type $1 (func (param i32) (result i32))) + + ;; CHECK: (func $caller (type $0) (result i32) + ;; CHECK-NEXT: (unreachable) + ;; CHECK-NEXT: ) + (func $caller (result i32) + ;; Again, the call is replaced by an unreachable. + (call $target + (unreachable) + ) + ) + + ;; CHECK: (func $target (type $1) (param $0 i32) (result i32) + ;; CHECK-NEXT: (i32.const 42) + ;; CHECK-NEXT: ) + (func $target (param i32) (result i32) + (i32.const 42) + ) +) + +;; As above, but use a return_call. We can optimize that too (return_calls have +;; type unreachable anyhow, and the optimization would not change the type, so +;; it is even simpler). (module ;; CHECK: (type $0 (func)) + ;; CHECK: (type $1 (func (param i32))) + ;; CHECK: (func $caller (type $0) - ;; CHECK-NEXT: (return_call $target) + ;; CHECK-NEXT: (unreachable) ;; CHECK-NEXT: ) (func $caller (return_call $target @@ -73,8 +104,7 @@ ) ) - ;; CHECK: (func $target (type $0) - ;; CHECK-NEXT: (local $0 i32) + ;; CHECK: (func $target (type $1) (param $0 i32) ;; CHECK-NEXT: (nop) ;; CHECK-NEXT: ) (func $target (param i32) diff --git a/test/lit/passes/signature-pruning.wast b/test/lit/passes/signature-pruning.wast index 4d22ef619..cad9af82b 100644 --- a/test/lit/passes/signature-pruning.wast +++ b/test/lit/passes/signature-pruning.wast @@ -136,7 +136,7 @@ ;; CHECK: (rec ;; CHECK-NEXT: (type $0 (func)) - ;; CHECK: (type $sig (sub (func (param i32 i64 f32)))) + ;; CHECK: (type $sig (sub (func (param i64 f32)))) (type $sig (sub (func (param i32) (param i64) (param f32) (param f64)))) (memory 1 1) @@ -145,19 +145,20 @@ ;; CHECK: (elem declare func $foo) - ;; CHECK: (func $foo (type $sig) (param $0 i32) (param $1 i64) (param $2 f32) - ;; CHECK-NEXT: (local $3 f64) + ;; CHECK: (func $foo (type $sig) (param $0 i64) (param $1 f32) + ;; CHECK-NEXT: (local $2 f64) + ;; CHECK-NEXT: (local $3 i32) ;; CHECK-NEXT: (i64.store ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (local.get $1) + ;; CHECK-NEXT: (local.get $0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (f32.store ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (local.get $2) + ;; CHECK-NEXT: (local.get $1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $foo (type $sig) (param $i32 i32) (param $i64 i64) (param $f32 f32) (param $f64 f64) - ;; Use the middle two parameters. + ;; Use the middle two parameters. The other two vanish. (i64.store (i32.const 0) (local.get $i64) @@ -169,25 +170,29 @@ ) ;; CHECK: (func $caller (type $0) - ;; CHECK-NEXT: (call $foo - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (call $caller) - ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: (local $0 i32) + ;; CHECK-NEXT: (block + ;; CHECK-NEXT: (local.set $0 + ;; CHECK-NEXT: (block (result i32) + ;; CHECK-NEXT: (call $caller) + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (call $foo + ;; CHECK-NEXT: (i64.const 1) + ;; CHECK-NEXT: (f32.const 2) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.const 1) - ;; CHECK-NEXT: (f32.const 2) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (call_ref $sig - ;; CHECK-NEXT: (i32.const 4) ;; CHECK-NEXT: (i64.const 5) ;; CHECK-NEXT: (f32.const 6) ;; CHECK-NEXT: (ref.func $foo) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $caller - ;; As above, but now one of the unused parameters has a side effect which - ;; prevents us from removing it (flattening the IR first would avoid this - ;; limitation). We only end up removing a single unused param, the last. + ;; As above, but now one of the unused parameters has a side effect. We + ;; move it to a local, which allows us to remove it (and also the last, + ;; which is trivial). (call $foo (block (result i32) (call $caller) @@ -207,13 +212,13 @@ ) ) -;; As above, but with the effects on a call_ref. Once more, we can only optimize -;; away the very last param. +;; As above, but with the effects on a call_ref. Once more, we can optimize +;; even with effects on a param, using locals. (module ;; CHECK: (rec ;; CHECK-NEXT: (type $0 (func)) - ;; CHECK: (type $sig (sub (func (param i32 i64 f32)))) + ;; CHECK: (type $sig (sub (func (param i64 f32)))) (type $sig (sub (func (param i32) (param i64) (param f32) (param f64)))) (memory 1 1) @@ -222,15 +227,16 @@ ;; CHECK: (elem declare func $foo) - ;; CHECK: (func $foo (type $sig) (param $0 i32) (param $1 i64) (param $2 f32) - ;; CHECK-NEXT: (local $3 f64) + ;; CHECK: (func $foo (type $sig) (param $0 i64) (param $1 f32) + ;; CHECK-NEXT: (local $2 f64) + ;; CHECK-NEXT: (local $3 i32) ;; CHECK-NEXT: (i64.store ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (local.get $1) + ;; CHECK-NEXT: (local.get $0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (f32.store ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (local.get $2) + ;; CHECK-NEXT: (local.get $1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $foo (type $sig) (param $i32 i32) (param $i64 i64) (param $f32 f32) (param $f64 f64) @@ -245,19 +251,23 @@ ) ;; CHECK: (func $caller (type $0) + ;; CHECK-NEXT: (local $0 i32) ;; CHECK-NEXT: (call $foo - ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: (i64.const 1) ;; CHECK-NEXT: (f32.const 2) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call_ref $sig - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (call $caller) - ;; CHECK-NEXT: (i32.const 4) + ;; CHECK-NEXT: (block + ;; CHECK-NEXT: (local.set $0 + ;; CHECK-NEXT: (block (result i32) + ;; CHECK-NEXT: (call $caller) + ;; CHECK-NEXT: (i32.const 4) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (call_ref $sig + ;; CHECK-NEXT: (i64.const 5) + ;; CHECK-NEXT: (f32.const 6) + ;; CHECK-NEXT: (ref.func $foo) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.const 5) - ;; CHECK-NEXT: (f32.const 6) - ;; CHECK-NEXT: (ref.func $foo) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $caller @@ -912,3 +922,232 @@ (unreachable) ) ) + +;; Test corner cases with var updating. To remove the parameter of $func we +;; must move the parameter to a local first. We must then adjust local types +;; properly while adjusting the signature (when the signature loses a parameter, +;; local indexes change, which is a delicate dance handled by +;; GlobalTypeRewriter::updateSignatures and ParamUtils::removeParameters; +;; moving the parameter to a local first should not get in the way there). +(module + ;; CHECK: (rec + ;; CHECK-NEXT: (type $struct (sub (struct (field v128)))) + (type $struct (sub (struct (field v128)))) + ;; CHECK: (type $1 (func)) + + ;; CHECK: (type $func (func)) + (type $func (func (param v128))) + + ;; CHECK: (elem declare func $func) + + ;; CHECK: (func $func (type $func) + ;; CHECK-NEXT: (local $0 v128) + ;; CHECK-NEXT: (nop) + ;; CHECK-NEXT: ) + (func $func (type $func) (param $0 v128) + ;; The parameter will be removed. + (nop) + ) + + ;; CHECK: (func $caller (type $1) + ;; CHECK-NEXT: (local $0 (ref $struct)) + ;; CHECK-NEXT: (local $1 externref) + ;; CHECK-NEXT: (local $2 v128) + ;; CHECK-NEXT: (local.set $2 + ;; CHECK-NEXT: (struct.get $struct 0 + ;; CHECK-NEXT: (local.tee $0 + ;; CHECK-NEXT: (struct.new_default $struct) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (call_ref $func + ;; CHECK-NEXT: (ref.func $func) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $caller (param $param externref) + (local $var (ref $struct)) + ;; The parameter of this call_ref will be removed. + (call_ref $func + ;; Use a struct.get, which would error if the type the nested tee were + ;; incorrect (it asserts on it being a struct type). + (struct.get $struct 0 + ;; Use a tee to test the updating of tee'd vars, as mentioned above. + (local.tee $var + (struct.new_default $struct) + ) + ) + (ref.func $func) + ) + ) +) + +(module + ;; CHECK: (type $0 (func (param i32))) + + ;; CHECK: (rec + ;; CHECK-NEXT: (type $1 (func (param i32))) + + ;; CHECK: (type $2 (func (result i32))) + + ;; CHECK: (type $3 (func (param i32))) + + ;; CHECK: (tag $tag (param i32)) + (tag $tag (param i32)) + + ;; CHECK: (func $catch-pop (type $2) (result i32) + ;; CHECK-NEXT: (local $0 i32) + ;; CHECK-NEXT: (local $1 i32) + ;; CHECK-NEXT: (local $2 i32) + ;; CHECK-NEXT: (block $block (result i32) + ;; CHECK-NEXT: (try $try + ;; CHECK-NEXT: (do + ;; CHECK-NEXT: (nop) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (catch $tag + ;; CHECK-NEXT: (local.set $2 + ;; CHECK-NEXT: (pop i32) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (block + ;; CHECK-NEXT: (block + ;; CHECK-NEXT: (local.set $0 + ;; CHECK-NEXT: (local.get $2) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (local.set $1 + ;; CHECK-NEXT: (br_if $block + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: (i32.const 2) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (call $target + ;; CHECK-NEXT: (local.get $0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (nop) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 3) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $catch-pop (result i32) + (block $block (result i32) + (try $try + (do + (nop) + ) + (catch $tag + (call $target + (pop i32) + ;; We can remove this parameter by moving it to a local first, which + ;; also moves the pop, which then needs to be fixed up. + (br_if $block + (i32.const 1) + (i32.const 2) + ) + ) + ;; This nop causes the call to be in a block. When we add another + ;; block to hold the code that we move, we'd get an error if we don't + ;; apply fixups. + (nop) + ) + ) + (i32.const 3) + ) + ) + + ;; CHECK: (func $target (type $1) (param $0 i32) + ;; CHECK-NEXT: (local $1 i32) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (local.get $0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $target (param $x i32) (param $y i32) + ;; Use only the first param. The second will be removed. + (drop + (local.get $x) + ) + ) +) + +;; As above, but remove the other parameter (the pop). +(module + ;; CHECK: (type $0 (func (param i32))) + + ;; CHECK: (rec + ;; CHECK-NEXT: (type $1 (func (param i32))) + + ;; CHECK: (type $2 (func (result i32))) + + ;; CHECK: (type $3 (func (param i32))) + + ;; CHECK: (tag $tag (param i32)) + (tag $tag (param i32)) + + ;; CHECK: (func $catch-pop (type $2) (result i32) + ;; CHECK-NEXT: (local $0 i32) + ;; CHECK-NEXT: (local $1 i32) + ;; CHECK-NEXT: (local $2 i32) + ;; CHECK-NEXT: (block $block (result i32) + ;; CHECK-NEXT: (try $try + ;; CHECK-NEXT: (do + ;; CHECK-NEXT: (nop) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (catch $tag + ;; CHECK-NEXT: (local.set $2 + ;; CHECK-NEXT: (pop i32) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (block + ;; CHECK-NEXT: (block + ;; CHECK-NEXT: (local.set $0 + ;; CHECK-NEXT: (local.get $2) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (local.set $1 + ;; CHECK-NEXT: (br_if $block + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: (i32.const 2) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (call $target + ;; CHECK-NEXT: (local.get $1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (nop) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 3) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $catch-pop (result i32) + (block $block (result i32) + (try $try + (do + (nop) + ) + (catch $tag + (call $target + (pop i32) + (br_if $block + (i32.const 1) + (i32.const 2) + ) + ) + (nop) + ) + ) + (i32.const 3) + ) + ) + + ;; CHECK: (func $target (type $1) (param $0 i32) + ;; CHECK-NEXT: (local $1 i32) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (local.get $0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $target (param $x i32) (param $y i32) + (drop + (local.get $y) ;; this changed from $x to $y + ) + ) +) |