summaryrefslogtreecommitdiff
path: root/test/lit/passes/signature-pruning.wast
diff options
context:
space:
mode:
Diffstat (limited to 'test/lit/passes/signature-pruning.wast')
-rw-r--r--test/lit/passes/signature-pruning.wast301
1 files changed, 270 insertions, 31 deletions
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
+ )
+ )
+)