blob: 97216ae8f45d2fbc5b5b5c383ed68f4216c3021f [file] [log] [blame] [edit]
;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited.
;; RUN: foreach %s %t wasm-opt -all --dae -S -o - | filecheck %s
(module
;; CHECK: (type ${} (struct ))
(type ${} (struct))
;; CHECK: (func $foo (type $none_=>_none)
;; CHECK-NEXT: (call $bar)
;; CHECK-NEXT: )
(func $foo
(call $bar
(i31.new
(i32.const 1)
)
)
)
;; CHECK: (func $bar (type $none_=>_none)
;; CHECK-NEXT: (local $0 i31ref)
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (local.tee $0
;; CHECK-NEXT: (i31.new
;; CHECK-NEXT: (i32.const 2)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (local.tee $0
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $bar (param $0 i31ref)
(drop
;; after the parameter is removed, we create a nullable local to replace it,
;; and must update the tee's type accordingly to avoid a validation error,
;; and also add a ref.as_non_null so that the outside still receives the
;; same type as before
(local.tee $0
(i31.new
(i32.const 2)
)
)
)
;; test for an unreachable tee, whose type must be unreachable even after
;; the change (the tee would need to be dropped if it were not unreachable,
;; so the correctness in this case is visible in the output)
(local.tee $0
(unreachable)
)
)
;; A function that gets a non-nullable reference that is never used. We can
;; still create a non-nullable local for that parameter.
;; CHECK: (func $get-nonnull (type $none_=>_none)
;; CHECK-NEXT: (local $0 (ref ${}))
;; CHECK-NEXT: (nop)
;; CHECK-NEXT: )
(func $get-nonnull (param $0 (ref ${}))
(nop)
)
;; CHECK: (func $send-nonnull (type $none_=>_none)
;; CHECK-NEXT: (call $get-nonnull)
;; CHECK-NEXT: )
(func $send-nonnull
(call $get-nonnull
(struct.new ${})
)
)
)
;; Test ref.func and ref.null optimization of constant parameter values.
(module
;; CHECK: (func $foo (type $ref|none_->_none|_=>_none) (param $0 (ref $none_=>_none))
;; CHECK-NEXT: (local $1 (ref $none_=>_none))
;; CHECK-NEXT: (local.set $1
;; CHECK-NEXT: (ref.func $a)
;; CHECK-NEXT: )
;; CHECK-NEXT: (block
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (local.get $1)
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (local.get $0)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $foo (param $x (ref func)) (param $y (ref func))
;; "Use" the params to avoid other optimizations kicking in.
(drop (local.get $x))
(drop (local.get $y))
)
;; CHECK: (func $call-foo (type $none_=>_none)
;; CHECK-NEXT: (call $foo
;; CHECK-NEXT: (ref.func $b)
;; CHECK-NEXT: )
;; CHECK-NEXT: (call $foo
;; CHECK-NEXT: (ref.func $c)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $call-foo
;; Call $foo with a constant function in the first param, which we
;; can optimize, but different ones in the second.
(call $foo
(ref.func $a)
(ref.func $b)
)
(call $foo
(ref.func $a)
(ref.func $c)
)
)
;; CHECK: (func $bar (type $i31ref_=>_none) (param $0 i31ref)
;; CHECK-NEXT: (local $1 nullref)
;; CHECK-NEXT: (local.set $1
;; CHECK-NEXT: (ref.null none)
;; CHECK-NEXT: )
;; CHECK-NEXT: (block
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (local.get $1)
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (local.get $0)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $bar (param $x (ref null any)) (param $y (ref null any))
;; "Use" the params to avoid other optimizations kicking in.
(drop (local.get $x))
(drop (local.get $y))
)
;; CHECK: (func $call-bar (type $none_=>_none)
;; CHECK-NEXT: (call $bar
;; CHECK-NEXT: (ref.null none)
;; CHECK-NEXT: )
;; CHECK-NEXT: (call $bar
;; CHECK-NEXT: (i31.new
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $call-bar
;; Call with nulls. Mixing nulls is fine as they all have the same type and
;; value. However, mixing a null with a reference stops us in the second
;; param.
(call $bar
(ref.null none)
(ref.null none)
)
(call $bar
(ref.null none)
(i31.new (i32.const 0))
)
)
;; Helper functions so we have something to take the reference of.
;; CHECK: (func $a (type $none_=>_none)
;; CHECK-NEXT: (nop)
;; CHECK-NEXT: )
(func $a)
;; CHECK: (func $b (type $none_=>_none)
;; CHECK-NEXT: (nop)
;; CHECK-NEXT: )
(func $b)
;; CHECK: (func $c (type $none_=>_none)
;; CHECK-NEXT: (nop)
;; CHECK-NEXT: )
(func $c)
)
;; Test that string constants can be applied.
(module
;; CHECK: (func $0 (type $none_=>_none)
;; CHECK-NEXT: (call $1)
;; CHECK-NEXT: )
(func $0
(call $1
(string.const "310")
(string.const "929")
)
)
;; CHECK: (func $1 (type $none_=>_none)
;; CHECK-NEXT: (local $0 (ref string))
;; CHECK-NEXT: (local $1 (ref string))
;; CHECK-NEXT: (local.set $0
;; CHECK-NEXT: (string.const "929")
;; CHECK-NEXT: )
;; CHECK-NEXT: (block
;; CHECK-NEXT: (local.set $1
;; CHECK-NEXT: (string.const "310")
;; CHECK-NEXT: )
;; CHECK-NEXT: (nop)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $1 (param $0 (ref string)) (param $1 (ref string))
;; The parameters here will be removed, and the constant values placed in the
;; function.
(nop)
)
)