blob: 5ea442357dbe3429de8f3f639ae5a4301c3a8e62 [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 --precompute --all-features -S -o - | filecheck %s
(module
;; CHECK: (type $1 (func))
;; CHECK: (type $2 (func (result i32)))
;; CHECK: (type $3 (func (result f64)))
;; CHECK: (type $0 (func (param i32)))
;; CHECK: (type $5 (func (result v128)))
;; CHECK: (type $6 (func (result i32 i64)))
;; CHECK: (type $7 (func (result externref)))
;; CHECK: (global $global i32 (i32.const 1))
;; CHECK: (global $global-mut (mut i32) (i32.const 2))
;; CHECK: (memory $m 512 512)
(memory $m 512 512)
(data (memory $m) (i32.const 0) "hello!")
(type $0 (func (param i32)))
(global $global i32 (i32.const 1))
(global $global-mut (mut i32) (i32.const 2))
;; CHECK: (data $0 (i32.const 0) "hello!")
;; CHECK: (elem declare func $dummy)
;; CHECK: (func $x (type $0) (param $x i32)
;; CHECK-NEXT: (call $x
;; CHECK-NEXT: (i32.const 2300)
;; CHECK-NEXT: )
;; CHECK-NEXT: (nop)
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (i32.add
;; CHECK-NEXT: (i32.const 1)
;; CHECK-NEXT: (local.get $x)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (nop)
;; CHECK-NEXT: (nop)
;; CHECK-NEXT: (nop)
;; CHECK-NEXT: (nop)
;; CHECK-NEXT: (loop $in
;; CHECK-NEXT: (br $in)
;; CHECK-NEXT: )
;; CHECK-NEXT: (nop)
;; CHECK-NEXT: (block $c
;; CHECK-NEXT: (nop)
;; CHECK-NEXT: (call $x
;; CHECK-NEXT: (i32.const 4)
;; CHECK-NEXT: )
;; CHECK-NEXT: (br $c)
;; CHECK-NEXT: (br $c)
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (block $val (result i32)
;; CHECK-NEXT: (nop)
;; CHECK-NEXT: (call $x
;; CHECK-NEXT: (i32.const 4)
;; CHECK-NEXT: )
;; CHECK-NEXT: (br $val
;; CHECK-NEXT: (i32.const 101)
;; CHECK-NEXT: )
;; CHECK-NEXT: (br $val
;; CHECK-NEXT: (i32.const 102)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (nop)
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (block $d0 (result i32)
;; CHECK-NEXT: (call $x
;; CHECK-NEXT: (i32.const 5)
;; CHECK-NEXT: )
;; CHECK-NEXT: (nop)
;; CHECK-NEXT: (i32.const 1)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (block $d1 (result i32)
;; CHECK-NEXT: (call $x
;; CHECK-NEXT: (i32.const 6)
;; CHECK-NEXT: )
;; CHECK-NEXT: (nop)
;; CHECK-NEXT: (i32.const 1)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (block $d2 (result i32)
;; CHECK-NEXT: (call $x
;; CHECK-NEXT: (i32.const 7)
;; CHECK-NEXT: )
;; CHECK-NEXT: (nop)
;; CHECK-NEXT: (i32.const 2)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (call $x
;; CHECK-NEXT: (i32.const 2)
;; CHECK-NEXT: )
;; CHECK-NEXT: (call $x
;; CHECK-NEXT: (i32.const 1)
;; CHECK-NEXT: )
;; CHECK-NEXT: (call $x
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: (call $x
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $x (type $0) (param $x i32)
(call $x
(i32.add
(i32.const 100)
(i32.const 2200)
)
)
(drop
(i32.add
(i32.const 1)
(i32.const 2)
)
)
(drop
(i32.add
(i32.const 1)
(local.get $x)
)
)
(drop
(i32.add
(i32.const 1)
(i32.add
(i32.const 2)
(i32.const 3)
)
)
)
(drop
(i32.sub
(i32.const 1)
(i32.const 2)
)
)
(drop
(i32.sub
(i32.add
(i32.const 0)
(i32.const 4)
)
(i32.const 1)
)
)
(tuple.drop 2
(tuple.make 2
(tuple.extract 2 0
(tuple.make 2
(i32.const 42)
(i32.const 0)
)
)
(tuple.extract 2 1
(tuple.make 2
(i64.const 0)
(i64.const 42)
)
)
)
)
(loop $in
(br $in)
)
(block $b
(br_if $b (i32.const 0))
(br_if $b (i32.const 1))
(call $x (i32.const 4))
)
(block $c
(br_if $c (i32.const 0))
(call $x (i32.const 4))
(br_if $c (i32.const 1))
(br $c)
)
(drop
(block $val (result i32)
(drop (br_if $val (i32.const 100) (i32.const 0)))
(call $x (i32.const 4))
(drop (br_if $val (i32.const 101) (i32.const 1)))
(br $val (i32.const 102))
)
)
(block $d
(block $e
(br_if $d (br $e))
(call $x (i32.const 4))
(br_if $e (br $d))
)
)
(drop
(block $d (result i32)
(call $x (i32.const 5))
(block $e
(drop (br_if $d (br $e) (i32.const 1)))
(drop (br_if $d (br $e) (i32.const 0)))
(drop (br_if $d (i32.const 1) (br $e)))
(drop (br_if $d (i32.const 0) (br $e)))
(unreachable)
)
(i32.const 1)
)
)
(drop
(block $d (result i32)
(call $x (i32.const 6))
(block $e
(drop (br_if $d (br $e) (i32.const 0)))
(drop (br_if $d (i32.const 1) (br $e)))
(drop (br_if $d (i32.const 0) (br $e)))
(unreachable)
)
(i32.const 1)
)
)
(drop
(block $d (result i32)
(call $x (i32.const 7))
(block $e
(drop (br_if $d (i32.const 1) (br $e)))
)
(i32.const 2)
)
)
(call $x
(block $out (result i32)
(block $waka1
(block $waka2
(block $waka3
(br_table $waka1 $waka2 $waka3
(i32.const 0)
)
)
(br $out (i32.const 0))
)
(br $out (i32.const 1))
)
(br $out (i32.const 2))
)
)
(call $x
(block $out (result i32)
(block $waka1
(block $waka2
(block $waka3
(br_table $waka1 $waka2 $waka3
(i32.const 1)
)
)
(br $out (i32.const 0))
)
(br $out (i32.const 1))
)
(br $out (i32.const 2))
)
)
(call $x
(block $out (result i32)
(block $waka1
(block $waka2
(block $waka3
(br_table $waka1 $waka2 $waka3
(i32.const 2)
)
)
(br $out (i32.const 0))
)
(br $out (i32.const 1))
)
(br $out (i32.const 2))
)
)
(call $x
(block $out (result i32)
(block $waka1
(block $waka2
(block $waka3
(br_table $waka1 $waka2 $waka3
(i32.const 3)
)
)
(br $out (i32.const 0))
)
(br $out (i32.const 1))
)
(br $out (i32.const 2))
)
)
)
;; CHECK: (func $ret (type $2) (result i32)
;; CHECK-NEXT: (if
;; CHECK-NEXT: (call $ret)
;; CHECK-NEXT: (then
;; CHECK-NEXT: (return
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (if
;; CHECK-NEXT: (call $ret)
;; CHECK-NEXT: (then
;; CHECK-NEXT: (return
;; CHECK-NEXT: (return
;; CHECK-NEXT: (i32.const 1)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (i32.const 1)
;; CHECK-NEXT: )
(func $ret (result i32)
(if (call $ret)
(then
(return (i32.const 0))
)
)
(if (call $ret)
(then
(return (return (i32.const 1)))
)
)
(i32.const 1)
)
;; CHECK: (func $noret (type $1)
;; CHECK-NEXT: (if
;; CHECK-NEXT: (call $ret)
;; CHECK-NEXT: (then
;; CHECK-NEXT: (return)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $noret
(if (call $ret)
(then
(return)
)
)
)
;; CHECK: (func $refinalize-br-condition-unreachable (type $1)
;; CHECK-NEXT: (block $label$1
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $refinalize-br-condition-unreachable
(block $label$1
(drop
(br_if $label$1
(unreachable)
)
)
)
)
;; CHECK: (func $br_if-condition-is-block-i32-but-unreachable-so-refinalize-tricky (type $1)
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (block $label$1 (result i32)
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (block
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (i32.const 100)
;; CHECK-NEXT: )
;; CHECK-NEXT: (block $label$3
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $br_if-condition-is-block-i32-but-unreachable-so-refinalize-tricky
(drop
(block $label$1 (result i32)
(drop
(br_if $label$1
(i32.const 100)
(block $label$3 (result i32)
(unreachable)
)
)
)
(i32.const 0)
)
)
)
;; CHECK: (func $reuse-br-value (type $3) (result f64)
;; CHECK-NEXT: (block $label$0 (result f64)
;; CHECK-NEXT: (i32.store8
;; CHECK-NEXT: (i32.const 1919623207)
;; CHECK-NEXT: (if (result i32)
;; CHECK-NEXT: (i32.const 1)
;; CHECK-NEXT: (then
;; CHECK-NEXT: (block $label$2
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (i64.and
;; CHECK-NEXT: (i64.trunc_f32_u
;; CHECK-NEXT: (f32.const 70847791997969805621592064)
;; CHECK-NEXT: )
;; CHECK-NEXT: (i64.const 729618461987467893)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (br $label$0
;; CHECK-NEXT: (f64.const 6.134856208230095e-154)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (else
;; CHECK-NEXT: (i32.load offset=3 align=2
;; CHECK-NEXT: (i32.const 169901344)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (f64.const 4776014875438170098655851e156)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $reuse-br-value (result f64)
(block $label$0 (result f64)
(i32.store8
(i32.const 1919623207)
(if (result i32)
(i32.const 1)
(then
(block $label$2 (result i32)
(drop
(i64.and
(i64.trunc_f32_u
(f32.const 70847791997969805621592064)
)
(i64.const 729618461987467893)
)
)
(br_if $label$2
(i32.const 2049535349)
(f32.eq
(f32.demote_f64
(f64.mul
(br_if $label$0 ;; this br is optimized, and br *and* values reused
(f64.const 6.134856208230095e-154)
(i32.const 690910817)
)
(f64.const 1.515470884183969e-152)
)
)
(f32.const 66524025679377434935296)
)
)
)
)
(else
(i32.load offset=3 align=2
(i32.const 169901344)
)
)
)
)
(f64.const 4776014875438170098655851e156)
)
)
;; CHECK: (func $refinalize-two-breaks-one-unreachable (type $1)
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (block $label$0 (result i64)
;; CHECK-NEXT: (block
;; CHECK-NEXT: (select
;; CHECK-NEXT: (i64.const 1)
;; CHECK-NEXT: (block
;; CHECK-NEXT: (global.set $global-mut
;; CHECK-NEXT: (i32.const 1)
;; CHECK-NEXT: )
;; CHECK-NEXT: (br $label$0
;; CHECK-NEXT: (i64.const -22)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (i32.const 1)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $refinalize-two-breaks-one-unreachable
(drop
(block $label$0 (result i64)
(br_if $label$0
(select
(i64.const 1)
(block (result i64)
(global.set $global-mut
(i32.const 1)
)
(br_if $label$0
(i64.const -22)
(i32.const -1)
)
)
(i32.const 0)
)
(i32.const 1)
)
)
)
)
;; CHECK: (func $one-break-value-and-it-is-unreachable (type $3) (result f64)
;; CHECK-NEXT: (local $var$0 i32)
;; CHECK-NEXT: (block $label$6
;; CHECK-NEXT: (block
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $one-break-value-and-it-is-unreachable (result f64)
(local $var$0 i32)
(block $label$6 (result f64)
(br_if $label$6
(unreachable)
(i32.const 0)
)
)
)
;; CHECK: (func $global-notprecomputable (type $2) (result i32)
;; CHECK-NEXT: (i32.add
;; CHECK-NEXT: (i32.const 1)
;; CHECK-NEXT: (global.get $global-mut)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $global-notprecomputable (result i32)
(i32.add
(i32.const 1)
(global.get $global-mut)
)
)
;; CHECK: (func $global-precomputable (type $2) (result i32)
;; CHECK-NEXT: (i32.const 2)
;; CHECK-NEXT: )
(func $global-precomputable (result i32)
(i32.add
(i32.const 1)
(global.get $global)
)
)
;; CHECK: (func $global-partiallyprecomputable (type $2) (result i32)
;; CHECK-NEXT: (i32.sub
;; CHECK-NEXT: (i32.add
;; CHECK-NEXT: (i32.const 1)
;; CHECK-NEXT: (global.get $global-mut)
;; CHECK-NEXT: )
;; CHECK-NEXT: (i32.const 2)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $global-partiallyprecomputable (result i32)
(i32.sub
(i32.add
(i32.const 1)
(global.get $global-mut)
)
(i32.add
(i32.const 1)
(global.get $global)
)
)
)
;; CHECK: (func $simd-precompute (type $5) (result v128)
;; CHECK-NEXT: (v128.const i32x4 0x00000000 0x00000000 0x00000000 0x00000000)
;; CHECK-NEXT: )
(func $simd-precompute (result v128)
(i32x4.splat
(i32.const 0)
)
)
;; CHECK: (func $no-memory-init-precompute (type $1)
;; CHECK-NEXT: (memory.init $0
;; CHECK-NEXT: (i32.const 512)
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: (i32.const 12)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $no-memory-init-precompute
(memory.init 0
(i32.const 512)
(i32.const 0)
(i32.const 12)
)
)
;; CHECK: (func $no-data-drop-precompute (type $1)
;; CHECK-NEXT: (data.drop $0)
;; CHECK-NEXT: )
(func $no-data-drop-precompute
(data.drop 0)
)
;; CHECK: (func $no-memory-copy-precompute (type $1)
;; CHECK-NEXT: (memory.copy
;; CHECK-NEXT: (i32.const 512)
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: (i32.const 12)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $no-memory-copy-precompute
(memory.copy
(i32.const 512)
(i32.const 0)
(i32.const 12)
)
)
;; CHECK: (func $no-memory-fill-precompute (type $1)
;; CHECK-NEXT: (memory.fill
;; CHECK-NEXT: (i32.const 512)
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: (i32.const 12)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $no-memory-fill-precompute
(memory.fill
(i32.const 512)
(i32.const 0)
(i32.const 12)
)
)
;; CHECK: (func $tuple-precompute (type $6) (result i32 i64)
;; CHECK-NEXT: (tuple.make 2
;; CHECK-NEXT: (i32.const 42)
;; CHECK-NEXT: (i64.const 42)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $tuple-precompute (result i32 i64)
(tuple.make 2
(tuple.extract 2 0
(tuple.make 2
(i32.const 42)
(i32.const 0)
)
)
(tuple.extract 2 1
(tuple.make 2
(i64.const 0)
(i64.const 42)
)
)
)
)
;; CHECK: (func $loop-precompute (type $2) (result i32)
;; CHECK-NEXT: (i32.const 1)
;; CHECK-NEXT: )
(func $loop-precompute (result i32)
(block $block (result i32)
(loop $loop
(br $block (i32.const 1))
)
)
)
;; Check if Precompute pass does not crash on reference types
;; CHECK: (func $reftype-test (type $7) (result externref)
;; CHECK-NEXT: (ref.null noextern)
;; CHECK-NEXT: )
(func $reftype-test (result externref)
(ref.null extern)
)
;; Check if constant nodes (const, ref.null, and ref.func) are correctly
;; reused. (We shouldn't reuse a const node for something like ref.null, which
;; will incorrectly cause an expression like 'someref.const'.)
;; CHECK: (func $dummy (type $1)
;; CHECK-NEXT: (nop)
;; CHECK-NEXT: )
(func $dummy)
;; CHECK: (func $br_reuse_node (type $1)
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (block $l0 (result f32)
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (block $l1
;; CHECK-NEXT: (global.set $global-mut
;; CHECK-NEXT: (i32.const 1)
;; CHECK-NEXT: )
;; CHECK-NEXT: (br $l0
;; CHECK-NEXT: (f32.const 3.5)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (f32.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (block $l2 (result nullexternref)
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (block $l3
;; CHECK-NEXT: (global.set $global-mut
;; CHECK-NEXT: (i32.const 1)
;; CHECK-NEXT: )
;; CHECK-NEXT: (br $l2
;; CHECK-NEXT: (ref.null noextern)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (ref.null noextern)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (block $l4 (result (ref null (exact $1)))
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (block $l5
;; CHECK-NEXT: (global.set $global-mut
;; CHECK-NEXT: (i32.const 1)
;; CHECK-NEXT: )
;; CHECK-NEXT: (br $l4
;; CHECK-NEXT: (ref.func $dummy)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (ref.null nofunc)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $br_reuse_node
(drop
(block $l0 (result f32)
(drop
(block $l1 (result i32)
(global.set $global-mut
(i32.const 1)
)
(br_if $l1
(i32.const 1)
(f32.lt
(br_if $l0
(f32.const 3.5)
(i32.const 1)
)
(f32.const 3)
)
)
)
)
(f32.const 0)
)
)
(drop
(block $l2 (result externref)
(drop
(block $l3 (result i32)
(global.set $global-mut
(i32.const 1)
)
(br_if $l3
(i32.const 1)
(ref.is_null
(br_if $l2
(ref.null extern)
(i32.const 3)
)
)
)
)
)
(ref.null extern)
)
)
(drop
(block $l4 (result funcref)
(drop
(block $l5 (result i32)
(global.set $global-mut
(i32.const 1)
)
(br_if $l5
(i32.const 1)
(ref.is_null
(br_if $l4
(ref.func $dummy)
(i32.const 3)
)
)
)
)
)
(ref.null func)
)
)
)
)