blob: e5e0f9ca4e8b2b60d47637269d8756197fbd3aa2 [file] [log] [blame] [edit]
;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited.
;; NOTE: This test was ported using port_passes_tests_to_lit.py and could be cleaned up.
;; RUN: foreach %s %t wasm-opt --dce --all-features -S -o - | filecheck %s
(module
(memory 10)
;; CHECK: (type $0 (func (result i32)))
;; CHECK: (type $1 (func))
;; CHECK: (type $2 (func (param i32) (result i32)))
;; CHECK: (type $ii (func (param i32 i32)))
(type $ii (func (param i32 i32)))
(type $1 (func))
(table 1 1 funcref)
(elem (i32.const 0) $call-me)
;; CHECK: (type $4 (func (param i64 i64) (result i64)))
;; CHECK: (type $5 (func (param f32 i64)))
;; CHECK: (type $6 (func (param f32 i64) (result i32)))
;; CHECK: (global $x (mut i32) (i32.const 0))
(global $x (mut i32) (i32.const 0))
;; CHECK: (memory $0 10)
;; CHECK: (table $0 1 1 funcref)
;; CHECK: (elem $0 (i32.const 0) $call-me)
;; CHECK: (func $call-me (type $ii) (param $0 i32) (param $1 i32)
;; CHECK-NEXT: (nop)
;; CHECK-NEXT: )
(func $call-me (type $ii) (param $0 i32) (param $1 i32)
(nop)
)
;; CHECK: (func $code-to-kill (type $1)
;; CHECK-NEXT: (local $x i32)
;; CHECK-NEXT: (block $out
;; CHECK-NEXT: (br $out)
;; CHECK-NEXT: )
;; CHECK-NEXT: (if
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: (then
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (if
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: (then
;; CHECK-NEXT: (block $out1
;; CHECK-NEXT: (return)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (block $out2
;; CHECK-NEXT: (br_table $out2 $out2 $out2 $out2
;; CHECK-NEXT: (i32.const 4)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (block $out3
;; CHECK-NEXT: (br_if $out3
;; CHECK-NEXT: (i32.const 3)
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (if
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: (then
;; CHECK-NEXT: (block $block4
;; CHECK-NEXT: (if
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: (then
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
;; CHECK-NEXT: (else
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (if
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: (then
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (if
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: (then
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (if
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: (then
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (block $out9
;; CHECK-NEXT: (block $in
;; CHECK-NEXT: (br_if $out9
;; CHECK-NEXT: (i32.const 1)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
;; CHECK-NEXT: (if
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: (then
;; CHECK-NEXT: (block $block11
;; CHECK-NEXT: (block $out10
;; CHECK-NEXT: (block $in0
;; CHECK-NEXT: (br_if $in0
;; CHECK-NEXT: (i32.const 1)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (block $out11
;; CHECK-NEXT: (block $in1
;; CHECK-NEXT: (br_table $out11 $in1
;; CHECK-NEXT: (i32.const 1)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
;; CHECK-NEXT: (block $out12
;; CHECK-NEXT: (block $in2
;; CHECK-NEXT: (br_table $in2 $out12
;; CHECK-NEXT: (i32.const 1)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
;; CHECK-NEXT: (if
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: (then
;; CHECK-NEXT: (block $block13
;; CHECK-NEXT: (block $out13
;; CHECK-NEXT: (block $in3
;; CHECK-NEXT: (br_table $in3 $in3
;; CHECK-NEXT: (i32.const 1)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (if
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: (then
;; CHECK-NEXT: (block $block15
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (i32.const 10)
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (i32.const 42)
;; CHECK-NEXT: )
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (if
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: (then
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (block $out14
;; CHECK-NEXT: (loop $in4
;; CHECK-NEXT: (br_if $out14
;; CHECK-NEXT: (i32.const 1)
;; CHECK-NEXT: )
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (if
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: (then
;; CHECK-NEXT: (block $block20
;; CHECK-NEXT: (loop $in5
;; CHECK-NEXT: (br_if $in5
;; CHECK-NEXT: (i32.const 1)
;; CHECK-NEXT: )
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (if
;; CHECK-NEXT: (i32.const 1)
;; CHECK-NEXT: (then
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (i32.const 123)
;; CHECK-NEXT: )
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (if
;; CHECK-NEXT: (i32.const 2)
;; CHECK-NEXT: (then
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (if
;; CHECK-NEXT: (i32.const 3)
;; CHECK-NEXT: (then
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (if
;; CHECK-NEXT: (i32.const -1)
;; CHECK-NEXT: (then
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (i32.const 123)
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (i32.const 456)
;; CHECK-NEXT: )
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (if
;; CHECK-NEXT: (i32.const -2)
;; CHECK-NEXT: (then
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (i32.const 139)
;; CHECK-NEXT: )
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (if
;; CHECK-NEXT: (i32.const -3)
;; CHECK-NEXT: (then
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (i32.const 246)
;; CHECK-NEXT: )
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (if
;; CHECK-NEXT: (i32.const -4)
;; CHECK-NEXT: (then
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (if
;; CHECK-NEXT: (i32.const 11)
;; CHECK-NEXT: (then
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (if
;; CHECK-NEXT: (i32.const 22)
;; CHECK-NEXT: (then
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (if
;; CHECK-NEXT: (i32.const 33)
;; CHECK-NEXT: (then
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (if
;; CHECK-NEXT: (i32.const 44)
;; CHECK-NEXT: (then
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (if
;; CHECK-NEXT: (i32.const 55)
;; CHECK-NEXT: (then
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (if
;; CHECK-NEXT: (i32.const 66)
;; CHECK-NEXT: (then
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (if
;; CHECK-NEXT: (i32.const 77)
;; CHECK-NEXT: (then
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (if
;; CHECK-NEXT: (i32.const 88)
;; CHECK-NEXT: (then
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (if
;; CHECK-NEXT: (i32.const 99)
;; CHECK-NEXT: (then
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (if
;; CHECK-NEXT: (i32.const 100)
;; CHECK-NEXT: (then
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (i32.const 123)
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (i32.const 456)
;; CHECK-NEXT: )
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (if
;; CHECK-NEXT: (i32.const 101)
;; CHECK-NEXT: (then
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (i32.const 123)
;; CHECK-NEXT: )
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (if
;; CHECK-NEXT: (i32.const 102)
;; CHECK-NEXT: (then
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (i32.const 1337)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $code-to-kill (type $1)
(local $x i32)
(block $out
(br $out)
(drop
(i32.const 0)
)
(if
(i32.const 1)
(then
(drop
(i32.const 2)
)
)
)
(br_table $out $out $out $out
(i32.const 3)
)
(call $code-to-kill)
)
(if
(i32.const 0)
(then
(block $out
(unreachable)
(drop
(i32.const 0)
)
)
)
)
(if
(i32.const 0)
(then
(block $out
(return)
(drop
(i32.const 0)
)
)
)
)
(block $out
(br_table $out $out $out $out
(i32.const 4)
)
(drop
(i32.const 0)
)
)
(block $out
(br_if $out
(i32.const 3)
)
(drop
(i32.const 0)
)
)
(if
(i32.const 0)
(then
(block $block4
(if
(i32.const 0)
(then
(block $out
(unreachable)
(drop
(i32.const 0)
)
)
)
(else
(block $out
(unreachable)
(drop
(i32.const 0)
)
)
)
)
(drop
(i32.const 0)
)
)
)
)
(if
(i32.const 0)
(then
(drop
(block $out (result i32)
(br $out
(unreachable)
)
(drop
(i32.const 0)
)
(unreachable)
)
)
)
)
(if
(i32.const 0)
(then
(drop
(block $out (result i32)
(br_if $out
(unreachable)
(i32.const 0)
)
(drop
(i32.const 0)
)
(unreachable)
)
)
)
)
(if
(i32.const 0)
(then
(drop
(block $out (result i32)
(br_if $out
(unreachable)
(unreachable)
)
(drop
(i32.const 0)
)
(unreachable)
)
)
)
)
(block $out
(block $in
(br_if $out
(i32.const 1)
)
)
(unreachable)
)
(if
(i32.const 0)
(then
(block $block11
(block $out
(block $in
(br_if $in
(i32.const 1)
)
)
(unreachable)
)
(drop
(i32.const 10)
)
)
)
)
(block $out
(block $in
(br_table $out $in
(i32.const 1)
)
)
(unreachable)
)
(block $out
(block $in
(br_table $in $out
(i32.const 1)
)
)
(unreachable)
)
(if
(i32.const 0)
(then
(block $block13
(block $out
(block $in
(br_table $in $in
(i32.const 1)
)
)
(unreachable)
)
(drop
(i32.const 10)
)
)
)
)
(if
(i32.const 0)
(then
(block $block15
(drop
(i32.const 10)
)
(drop
(i32.const 42)
)
(unreachable)
(return
(unreachable)
)
(unreachable)
(return)
)
)
)
(if
(i32.const 0)
(then
(loop $loop-in18
(unreachable)
)
)
)
(block $out
(loop $in
(br_if $out
(i32.const 1)
)
(unreachable)
)
)
(if
(i32.const 0)
(then
(block $block20
(loop $in
(br_if $in
(i32.const 1)
)
(unreachable)
)
(drop
(i32.const 10)
)
)
)
)
(if
(i32.const 1)
(then
(call $call-me
(i32.const 123)
(unreachable)
)
)
)
(if
(i32.const 2)
(then
(call $call-me
(unreachable)
(i32.const 0)
)
)
)
(if
(i32.const 3)
(then
(call $call-me
(unreachable)
(unreachable)
)
)
)
(if
(i32.const -1)
(then
(call_indirect (type $ii)
(i32.const 123)
(i32.const 456)
(unreachable)
)
)
)
(if
(i32.const -2)
(then
(call_indirect (type $ii)
(i32.const 139)
(unreachable)
(i32.const 0)
)
)
)
(if
(i32.const -3)
(then
(call_indirect (type $ii)
(i32.const 246)
(unreachable)
(unreachable)
)
)
)
(if
(i32.const -4)
(then
(call_indirect (type $ii)
(unreachable)
(unreachable)
(unreachable)
)
)
)
(if
(i32.const 11)
(then
(local.set $x
(unreachable)
)
)
)
(if
(i32.const 22)
(then
(drop
(i32.load
(unreachable)
)
)
)
)
(if
(i32.const 33)
(then
(i32.store
(i32.const 0)
(unreachable)
)
)
)
(if
(i32.const 44)
(then
(i32.store
(unreachable)
(i32.const 0)
)
)
)
(if
(i32.const 55)
(then
(i32.store
(unreachable)
(unreachable)
)
)
)
(if
(i32.const 66)
(then
(drop
(i32.eqz
(unreachable)
)
)
)
)
(if
(i32.const 77)
(then
(drop
(i32.add
(unreachable)
(i32.const 0)
)
)
)
)
(if
(i32.const 88)
(then
(drop
(i32.add
(i32.const 0)
(unreachable)
)
)
)
)
(if
(i32.const 99)
(then
(i32.add
(unreachable)
(unreachable)
)
)
)
(if
(i32.const 100)
(then
(drop
(select
(i32.const 123)
(i32.const 456)
(unreachable)
)
)
)
)
(if
(i32.const 101)
(then
(drop
(select
(i32.const 123)
(unreachable)
(i32.const 456)
)
)
)
)
(if
(i32.const 102)
(then
(drop
(select
(unreachable)
(i32.const 123)
(i32.const 456)
)
)
)
)
(drop
(i32.const 1337)
)
)
;; CHECK: (func $killer (type $1)
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
(func $killer (type $1)
(unreachable)
(drop
(i32.const 1000)
)
)
;; CHECK: (func $target (type $1)
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (i32.const 2000)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $target (type $1)
(drop
(i32.const 2000)
)
)
;; CHECK: (func $typed-block-none-then-unreachable (type $0) (result i32)
;; CHECK-NEXT: (block $top-typed
;; CHECK-NEXT: (block $switch$0
;; CHECK-NEXT: (return
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $typed-block-none-then-unreachable (result i32)
(block $top-typed (result i32)
(block $switch$0 ;; this looks like it can be broken to, so it gets type 'none'
(return
(i32.const 0)
)
(br $switch$0) ;; this is not reachable, so dce cleans it up, changing $switch$0's type
)
(return ;; and this is cleaned up as well, leaving $top-typed in need of a type change
(i32.const 1)
)
)
)
;; CHECK: (func $typed-block-remove-br-changes-type (type $2) (param $$$0 i32) (result i32)
;; CHECK-NEXT: (block $switch$7
;; CHECK-NEXT: (block $switch-default$10
;; CHECK-NEXT: (block $switch-case$9
;; CHECK-NEXT: (block $switch-case$8
;; CHECK-NEXT: (br_table $switch-case$9 $switch-case$8 $switch-default$10
;; CHECK-NEXT: (i32.const -1)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (return
;; CHECK-NEXT: (local.get $$$0)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (return
;; CHECK-NEXT: (local.get $$$0)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $typed-block-remove-br-changes-type (param $$$0 i32) (result i32)
(block $switch$7
(block $switch-default$10
(block $switch-case$9
(block $switch-case$8
(br_table $switch-case$9 $switch-case$8 $switch-default$10
(i32.const -1)
)
)
)
(return
(local.get $$$0)
)
(br $switch$7)
)
(return
(local.get $$$0)
)
)
(return
(i32.const 0)
)
)
;; CHECK: (func $global (type $1)
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
(func $global
(unreachable)
(drop (global.get $x))
(global.set $x (i32.const 1))
)
;; CHECK: (func $ret (type $0) (result i32)
;; CHECK-NEXT: (return
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $ret (result i32)
(return
(i32.const 0)
)
(nop)
(i32.const 0)
)
;; CHECK: (func $unreachable-br (type $0) (result i32)
;; CHECK-NEXT: (block $out (result i32)
;; CHECK-NEXT: (br $out
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $unreachable-br (result i32)
(block $out (result i32)
(br $out
(br $out (i32.const 0))
)
)
)
;; CHECK: (func $unreachable-br-loop (type $0) (result i32)
;; CHECK-NEXT: (loop $out
;; CHECK-NEXT: (br $out)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $unreachable-br-loop (result i32)
(loop $out
(br $out)
)
)
;; CHECK: (func $unreachable-block-ends-switch (type $0) (result i32)
;; CHECK-NEXT: (block $label$0
;; CHECK-NEXT: (block $label$3
;; CHECK-NEXT: (nop)
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $unreachable-block-ends-switch (result i32)
(block $label$0 (result i32)
(block $label$3
(nop)
(br_table $label$3
(unreachable)
)
(unreachable)
)
(i32.const 19)
)
)
;; CHECK: (func $unreachable-block-ends-br_if (type $0) (result i32)
;; CHECK-NEXT: (block $label$0
;; CHECK-NEXT: (block $label$2
;; CHECK-NEXT: (nop)
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $unreachable-block-ends-br_if (result i32)
(block $label$0 (result i32)
(block $label$2
(nop)
(br_if $label$2
(unreachable)
)
(unreachable)
)
(i32.const 19)
)
)
;; CHECK: (func $unreachable-brs-3 (type $0) (result i32)
;; CHECK-NEXT: (block $label$0 (result i32)
;; CHECK-NEXT: (br $label$0
;; CHECK-NEXT: (i32.const 18)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $unreachable-brs-3 (result i32)
(block $label$0 (result i32)
(br $label$0
(memory.grow
(br $label$0
(i32.const 18)
)
)
)
(i32.const 21)
)
)
;; CHECK: (func $unreachable-brs-4 (type $2) (param $var$0 i32) (result i32)
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (i32.const 1)
;; CHECK-NEXT: )
;; CHECK-NEXT: (block $label$0
;; CHECK-NEXT: (block $label$1
;; CHECK-NEXT: (block
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (i32.const 4104)
;; CHECK-NEXT: )
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $unreachable-brs-4 (param $var$0 i32) (result i32)
(i32.add
(i32.const 1)
(block $label$0 (result i32)
(br $label$0
(block $label$1 (result i32) ;; this block is declared i32, but we can see it is unreachable
(drop
(br_if $label$0
(i32.const 4104)
(unreachable)
)
)
(i32.const 4)
)
)
(i32.const 16)
)
)
)
;; CHECK: (func $call-unreach (type $4) (param $var$0 i64) (param $var$1 i64) (result i64)
;; CHECK-NEXT: (local $2 i64)
;; CHECK-NEXT: (if (result i64)
;; CHECK-NEXT: (i64.eqz
;; CHECK-NEXT: (local.get $var$0)
;; CHECK-NEXT: )
;; CHECK-NEXT: (then
;; CHECK-NEXT: (block $label$0 (result i64)
;; CHECK-NEXT: (local.get $var$1)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (else
;; CHECK-NEXT: (block $label$1
;; CHECK-NEXT: (block
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (i64.sub
;; CHECK-NEXT: (local.get $var$0)
;; CHECK-NEXT: (i64.const 1)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (block
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (block (result i64)
;; CHECK-NEXT: (local.set $2
;; CHECK-NEXT: (local.get $var$0)
;; CHECK-NEXT: )
;; CHECK-NEXT: (nop)
;; CHECK-NEXT: (local.get $2)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $call-unreach (param $var$0 i64) (param $var$1 i64) (result i64)
(local $2 i64)
(if (result i64)
(i64.eqz
(local.get $var$0)
)
(then
(block $label$0 (result i64)
(local.get $var$1)
)
)
(else
(block $label$1 (result i64)
(call $call-unreach
(i64.sub
(local.get $var$0)
(i64.const 1)
)
(i64.mul
(block (result i64)
(local.set $2
(local.get $var$0)
)
(nop)
(local.get $2)
)
(unreachable)
)
)
)
)
)
)
;; CHECK: (func $br-gone-means-block-type-changes-then-refinalize-at-end-is-too-late (type $2) (param $var$0 i32) (result i32)
;; CHECK-NEXT: (block $label$0
;; CHECK-NEXT: (block
;; CHECK-NEXT: (nop)
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $br-gone-means-block-type-changes-then-refinalize-at-end-is-too-late (param $var$0 i32) (result i32)
(block $label$0 (result i32)
(br $label$0
(block (result i32)
(nop)
(drop
(br_if $label$0
(unreachable)
(local.get $var$0)
)
)
(i32.const 4)
)
)
)
)
;; CHECK: (func $br-with-unreachable-value-should-not-give-a-block-a-value (type $2) (param $var$0 i32) (result i32)
;; CHECK-NEXT: (block $label$0 (result i32)
;; CHECK-NEXT: (block
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (br_if $label$0
;; CHECK-NEXT: (i32.const 8)
;; CHECK-NEXT: (local.get $var$0)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $br-with-unreachable-value-should-not-give-a-block-a-value (param $var$0 i32) (result i32)
(block $label$0 (result i32)
(br $label$0
(block (result i32) ;; turns into unreachable when refinalized
(drop
(br_if $label$0
(i32.const 8)
(local.get $var$0)
)
)
(unreachable)
)
)
(i32.const 16)
)
)
;; CHECK: (func $replace-br-value-of-i32-with-unreachable (type $0) (result i32)
;; CHECK-NEXT: (block $label$0
;; CHECK-NEXT: (block $label$1
;; CHECK-NEXT: (nop)
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $replace-br-value-of-i32-with-unreachable (result i32)
(block $label$0 (result i32)
(br $label$0
(block $label$1 (result i32)
(nop)
(unreachable)
)
)
)
)
;; CHECK: (func $shorten-block-requires-sync-refinalize (type $ii) (param $var$0 i32) (param $var$1 i32)
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
(func $shorten-block-requires-sync-refinalize (param $var$0 i32) (param $var$1 i32)
(block $label$0
(unreachable)
(if
(unreachable)
(then
(br_if $label$0
(local.get $var$1)
)
)
)
)
)
;; CHECK: (func $block-with-type-but-is-unreachable (type $2) (param $var$0 i32) (result i32)
;; CHECK-NEXT: (block $label$0
;; CHECK-NEXT: (block $block
;; CHECK-NEXT: (nop)
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $block-with-type-but-is-unreachable (param $var$0 i32) (result i32)
(block $label$0 (result i32)
(br $label$0
(block $block (result i32)
(nop)
(unreachable)
)
)
)
)
;; CHECK: (func $if-with-type-but-is-unreachable (type $2) (param $var$0 i32) (result i32)
;; CHECK-NEXT: (block $label$0
;; CHECK-NEXT: (if
;; CHECK-NEXT: (local.get $var$0)
;; CHECK-NEXT: (then
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
;; CHECK-NEXT: (else
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $if-with-type-but-is-unreachable (param $var$0 i32) (result i32)
(block $label$0 (result i32)
(br $label$0
(if (result i32)
(local.get $var$0)
(then
(unreachable)
)
(else
(unreachable)
)
)
)
)
)
;; CHECK: (func $unreachable-loop (type $1)
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
(func $unreachable-loop
(loop $label$2
(unreachable)
(br $label$2)
)
)
;; CHECK: (func $br-block-from-unary (type $0) (result i32)
;; CHECK-NEXT: (block $label$6 (result i32)
;; CHECK-NEXT: (block $label$7
;; CHECK-NEXT: (br $label$6
;; CHECK-NEXT: (i32.const 8)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $br-block-from-unary (result i32)
(block $label$6 (result i32)
(i32.ctz
(block $label$7 (result i32)
(br $label$6
(i32.const 8)
)
)
)
)
)
;; CHECK: (func $replace-unary-with-br-child (type $1)
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (block $label$6 (result i32)
;; CHECK-NEXT: (br $label$6
;; CHECK-NEXT: (i32.const 8)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $replace-unary-with-br-child
(drop
(block $label$6 (result i32)
(i32.ctz
(br $label$6
(i32.const 8)
)
)
)
)
)
;; CHECK: (func $br_if-unreach-then-br_if-normal (type $1)
;; CHECK-NEXT: (block $out
;; CHECK-NEXT: (nop)
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $br_if-unreach-then-br_if-normal
(block $out
(nop)
(br_if $out
(unreachable)
)
(br_if $out
(i32.const 1)
)
)
)
;; CHECK: (func $replace-with-unreachable-affects-parent (type $5) (param $var$0 f32) (param $var$1 i64)
;; CHECK-NEXT: (block $top
;; CHECK-NEXT: (block
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (i64.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: (if
;; CHECK-NEXT: (block (result i32)
;; CHECK-NEXT: (call $replace-with-unreachable-affects-parent
;; CHECK-NEXT: (f32.const 1)
;; CHECK-NEXT: (i64.const -15917430362925035)
;; CHECK-NEXT: )
;; CHECK-NEXT: (i32.const 1)
;; CHECK-NEXT: )
;; CHECK-NEXT: (then
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
;; CHECK-NEXT: (else
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $replace-with-unreachable-affects-parent (param $var$0 f32) (param $var$1 i64)
(block $top
(drop
(f32.load offset=4
(i64.ne
(i64.const 0)
(if (result i64)
(block (result i32)
(call $replace-with-unreachable-affects-parent
(f32.const 1)
(i64.const -15917430362925035)
)
(i32.const 1)
)
(then
(unreachable)
)
(else
(unreachable)
)
)
)
)
)
(nop) ;; this is not reachable due to the above code, so we replace it with unreachable. type should go to parent
)
)
;; CHECK: (func $replace-block-changes-later-when-if-goes (type $1)
;; CHECK-NEXT: (block $top
;; CHECK-NEXT: (global.set $x
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: (block $inner
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (call $helper
;; CHECK-NEXT: (f32.const 1)
;; CHECK-NEXT: (i64.const -15917430362925035)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $replace-block-changes-later-when-if-goes
(block $top ;; and so should this
(global.set $x
(i32.const 0)
)
(drop
(f32.load offset=4
(i64.ne
(block $inner (result i64) ;; this becomes unreachable
(drop
(call $helper
(f32.const 1)
(i64.const -15917430362925035)
)
)
(unreachable)
)
(i64.const 0)
)
)
)
(if
(i32.load16_s offset=22 align=1
(i32.const 0)
)
(then
(br $top) ;; this keeps the block none after the inner block gets unreachable. but it will vanish into unreachable itself
)
(else
(unreachable)
)
)
)
)
;; CHECK: (func $helper (type $6) (param $var$0 f32) (param $var$1 i64) (result i32)
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
(func $helper (param $var$0 f32) (param $var$1 i64) (result i32)
(i32.const 0)
)
)
;; if goes to unreachable, need to propagate that up to the global.set
(module
;; CHECK: (type $0 (func))
;; CHECK: (global $global (mut f64) (f64.const 0))
(global $global (mut f64) (f64.const 0))
;; CHECK: (func $0 (type $0)
;; CHECK-NEXT: (if
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: (then
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
;; CHECK-NEXT: (else
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $0
(global.set $global
(if (result f64)
(i32.const 0)
(then
(unreachable)
)
(else
(unreachable)
)
)
)
)
)
(module
;; CHECK: (type $0 (func))
;; CHECK: (func $0 (type $0)
;; CHECK-NEXT: (local $local f64)
;; CHECK-NEXT: (if
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: (then
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
;; CHECK-NEXT: (else
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $0
(local $local f64)
(local.set $local
(if (result f64)
(i32.const 0)
(then
(unreachable)
)
(else
(unreachable)
)
)
)
)
)
(module
;; CHECK: (type $0 (func (result i32)))
;; CHECK: (type $1 (func))
;; CHECK: (func $unnecessary-concrete-block (type $0) (result i32)
;; CHECK-NEXT: (block $foo
;; CHECK-NEXT: (nop)
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $unnecessary-concrete-block (result i32)
(block $foo (result i32) ;; unnecessary type
(nop)
(unreachable)
)
)
;; CHECK: (func $necessary-concrete-block (type $0) (result i32)
;; CHECK-NEXT: (block $foo (result i32)
;; CHECK-NEXT: (br $foo
;; CHECK-NEXT: (i32.const 1)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $necessary-concrete-block (result i32)
(block $foo (result i32)
(br $foo (i32.const 1))
(unreachable)
)
)
;; CHECK: (func $unnecessary-concrete-if (type $0) (result i32)
;; CHECK-NEXT: (if
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: (then
;; CHECK-NEXT: (return
;; CHECK-NEXT: (i32.const 1)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (else
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $unnecessary-concrete-if (result i32)
(if (result i32) ;; unnecessary type
(i32.const 0)
(then
(return (i32.const 1))
)
(else
(unreachable)
)
)
)
;; CHECK: (func $unnecessary-concrete-try (type $0) (result i32)
;; CHECK-NEXT: (try
;; CHECK-NEXT: (do
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
;; CHECK-NEXT: (catch_all
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $unnecessary-concrete-try (result i32)
(try (result i32)
(do
(unreachable)
)
(catch_all
(unreachable)
)
)
)
;; CHECK: (func $note-loss-of-if-children (type $1)
;; CHECK-NEXT: (block $label$1
;; CHECK-NEXT: (block $label$2
;; CHECK-NEXT: (nop)
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $note-loss-of-if-children
(block $label$1
(if ;; begins unreachable - type never changes - but after the condition
;; becomes unreachable, it will lose the children, which means no more
;; br to the outer block, changing that type.
(block $label$2 (result i32)
(nop)
(unreachable)
)
(then
(unreachable)
)
(else
(br $label$1)
)
)
)
)
;; CHECK: (func $note-loss-of-non-control-flow-children (type $1)
;; CHECK-NEXT: (block $out
;; CHECK-NEXT: (block
;; CHECK-NEXT: (nop)
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $note-loss-of-non-control-flow-children
(block $out
(drop
(i32.add
(block (result i32)
(nop)
(unreachable)
)
(br $out) ;; when this is removed as dead, the block becomes unreachable
)
)
)
)
)
(module
;; CHECK: (type $0 (func (result (ref any))))
;; CHECK: (func $br_on_non_null (type $0) (result (ref any))
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
(func $br_on_non_null (result (ref any))
(block $label$1 (result (ref any))
;; this break has an unreachable input, and so it does not have a heap type
;; there, and no heap type to send on the branch. this tests we do not hit
;; the assertion in getHeapType() if we call that.
(br_on_non_null $label$1
(block (result anyref)
(unreachable)
)
)
(unreachable)
)
)
;; CHECK: (func $br_on_cast_fail (type $0) (result (ref any))
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
(func $br_on_cast_fail (result (ref any))
(block $label$1 (result (ref none))
;; Similar to the above, but using br_on_cast_fail.
(br_on_cast_fail $label$1 anyref structref
(unreachable)
)
(unreachable)
)
)
)
(module
;; CHECK: (type $0 (func (result anyref)))
;; CHECK: (func $if (type $0) (result anyref)
;; CHECK-NEXT: (ref.cast i31ref
;; CHECK-NEXT: (if (result i31ref)
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: (then
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
;; CHECK-NEXT: (else
;; CHECK-NEXT: (ref.i31
;; CHECK-NEXT: (i32.const 42)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $if (result anyref)
;; We should not refinalize while doing DCE. The cast should remain a
;; nullable one, and the if should keep returning a nullable value. (If we
;; refinalized only the if then the cast would be invalid, since we cannot
;; have a nullable cast of a non-nullable input.)
;;
;; In other words, we can propagate unreachability in DCE, but should cause
;; no other type changes.
(ref.cast i31ref
(if (result i31ref)
(i32.const 0)
(then
(block (result i31ref)
(unreachable)
)
)
(else
(ref.i31
(i32.const 42)
)
)
)
)
)
;; CHECK: (func $try (type $0) (result anyref)
;; CHECK-NEXT: (try (result i31ref)
;; CHECK-NEXT: (do
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (call $try)
;; CHECK-NEXT: )
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
;; CHECK-NEXT: (catch_all
;; CHECK-NEXT: (ref.i31
;; CHECK-NEXT: (i32.const 42)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $try (result anyref)
;; As above, but for try.
(try (result i31ref)
(do
(block (result i31ref)
(drop
(call $try)
)
(unreachable)
)
)
(catch_all
(ref.i31
(i32.const 42)
)
)
)
)
)
(module
;; CHECK: (type $0 (func))
;; CHECK: (func $string.new-start (type $0)
;; CHECK-NEXT: (local $nn (ref any))
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (ref.null none)
;; CHECK-NEXT: )
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
(func $string.new-start
(local $nn (ref any))
(drop
;; This should have unreachable type because a child is unreachable. If we
;; do not detect that then we will end up removing the tee but not the
;; code after it, which means we'd fail to validate due to a non-nullable
;; local used without a set.
(string.new_wtf16_array
(ref.null any)
(local.tee $nn
(unreachable)
)
(block (result i32)
(drop
(local.get $nn)
)
(i32.const 10)
)
)
)
)
;; CHECK: (func $string.new-end (type $0)
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (ref.null none)
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (i32.const 10)
;; CHECK-NEXT: )
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
(func $string.new-end
(drop
;; Now the unreachable is at the end. We should still remove the
;; string.new.
(string.new_wtf16_array
(ref.null any)
(i32.const 10)
(unreachable)
)
)
)
)