blob: da61f51e3385235d32ec7756b7952acd263b5b33 [file] [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-propagate --all-features -S -o - | filecheck %s
(module
(memory 10 10)
;; CHECK: (type $0 (func (param i32)))
;; CHECK: (type $1 (func (param i32) (result i32)))
;; CHECK: (type $2 (func (param i32 i32) (result i32)))
;; CHECK: (type $3 (func (result i32 i64)))
;; CHECK: (type $4 (func (param i32 i32 i32) (result i32)))
;; CHECK: (type $5 (func (result v128)))
;; CHECK: (memory $0 10 10)
;; CHECK: (func $basic (type $0) (param $p i32)
;; CHECK-NEXT: (local $x i32)
;; CHECK-NEXT: (local.set $x
;; CHECK-NEXT: (i32.const 10)
;; CHECK-NEXT: )
;; CHECK-NEXT: (call $basic
;; CHECK-NEXT: (i32.const 20)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $basic (param $p i32)
(local $x i32)
(local.set $x (i32.const 10))
(call $basic (i32.add (local.get $x) (local.get $x)))
)
;; CHECK: (func $split (type $0) (param $p i32)
;; CHECK-NEXT: (local $x i32)
;; CHECK-NEXT: (if
;; CHECK-NEXT: (i32.const 1)
;; CHECK-NEXT: (then
;; CHECK-NEXT: (local.set $x
;; CHECK-NEXT: (i32.const 10)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (call $basic
;; CHECK-NEXT: (i32.add
;; CHECK-NEXT: (local.get $x)
;; CHECK-NEXT: (local.get $x)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $split (param $p i32)
(local $x i32)
(if (i32.const 1)
(then
(local.set $x (i32.const 10))
)
)
(call $basic (i32.add (local.get $x) (local.get $x)))
)
;; CHECK: (func $split-but-join (type $0) (param $p i32)
;; CHECK-NEXT: (local $x i32)
;; CHECK-NEXT: (if
;; CHECK-NEXT: (i32.const 1)
;; CHECK-NEXT: (then
;; CHECK-NEXT: (local.set $x
;; CHECK-NEXT: (i32.const 10)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (else
;; CHECK-NEXT: (local.set $x
;; CHECK-NEXT: (i32.const 10)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (call $basic
;; CHECK-NEXT: (i32.const 20)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $split-but-join (param $p i32)
(local $x i32)
(if (i32.const 1)
(then
(local.set $x (i32.const 10))
)
(else
(local.set $x (i32.const 10))
)
)
(call $basic (i32.add (local.get $x) (local.get $x)))
)
;; CHECK: (func $split-but-join-different (type $0) (param $p i32)
;; CHECK-NEXT: (local $x i32)
;; CHECK-NEXT: (if
;; CHECK-NEXT: (i32.const 1)
;; CHECK-NEXT: (then
;; CHECK-NEXT: (local.set $x
;; CHECK-NEXT: (i32.const 10)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (else
;; CHECK-NEXT: (local.set $x
;; CHECK-NEXT: (i32.const 20)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (call $basic
;; CHECK-NEXT: (i32.add
;; CHECK-NEXT: (local.get $x)
;; CHECK-NEXT: (local.get $x)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $split-but-join-different (param $p i32)
(local $x i32)
(if (i32.const 1)
(then
(local.set $x (i32.const 10))
)
(else
(local.set $x (i32.const 20))
)
)
(call $basic (i32.add (local.get $x) (local.get $x)))
)
;; CHECK: (func $split-but-join-different-b (type $0) (param $p i32)
;; CHECK-NEXT: (local $x i32)
;; CHECK-NEXT: (if
;; CHECK-NEXT: (i32.const 1)
;; CHECK-NEXT: (then
;; CHECK-NEXT: (local.set $x
;; CHECK-NEXT: (i32.const 10)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (else
;; CHECK-NEXT: (local.set $x
;; CHECK-NEXT: (local.get $p)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (call $basic
;; CHECK-NEXT: (i32.add
;; CHECK-NEXT: (local.get $x)
;; CHECK-NEXT: (local.get $x)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $split-but-join-different-b (param $p i32)
(local $x i32)
(if (i32.const 1)
(then
(local.set $x (i32.const 10))
)
(else
(local.set $x (local.get $p))
)
)
(call $basic (i32.add (local.get $x) (local.get $x)))
)
;; CHECK: (func $split-but-join-init0 (type $0) (param $p i32)
;; CHECK-NEXT: (local $x i32)
;; CHECK-NEXT: (if
;; CHECK-NEXT: (i32.const 1)
;; CHECK-NEXT: (then
;; CHECK-NEXT: (local.set $x
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (call $basic
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $split-but-join-init0 (param $p i32)
(local $x i32)
(if (i32.const 1)
(then
(local.set $x (i32.const 0))
)
)
(call $basic (i32.add (local.get $x) (local.get $x)))
)
;; CHECK: (func $later (type $0) (param $p i32)
;; CHECK-NEXT: (local $x i32)
;; CHECK-NEXT: (local.set $x
;; CHECK-NEXT: (i32.const 10)
;; CHECK-NEXT: )
;; CHECK-NEXT: (call $basic
;; CHECK-NEXT: (i32.const 20)
;; CHECK-NEXT: )
;; CHECK-NEXT: (local.set $x
;; CHECK-NEXT: (i32.const 22)
;; CHECK-NEXT: )
;; CHECK-NEXT: (call $basic
;; CHECK-NEXT: (i32.const 44)
;; CHECK-NEXT: )
;; CHECK-NEXT: (local.set $x
;; CHECK-NEXT: (i32.const 39)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $later (param $p i32)
(local $x i32)
(local.set $x (i32.const 10))
(call $basic (i32.add (local.get $x) (local.get $x)))
(local.set $x (i32.const 22))
(call $basic (i32.add (local.get $x) (local.get $x)))
(local.set $x (i32.const 39))
)
;; CHECK: (func $later2 (type $1) (param $p i32) (result i32)
;; CHECK-NEXT: (local $x i32)
;; CHECK-NEXT: (local.set $x
;; CHECK-NEXT: (i32.const 10)
;; CHECK-NEXT: )
;; CHECK-NEXT: (local.set $x
;; CHECK-NEXT: (i32.const 20)
;; CHECK-NEXT: )
;; CHECK-NEXT: (i32.const 20)
;; CHECK-NEXT: )
(func $later2 (param $p i32) (result i32)
(local $x i32)
(local.set $x (i32.const 10))
(local.set $x (i32.add (local.get $x) (local.get $x)))
(local.get $x)
)
;; CHECK: (func $two-ways-but-identical (type $1) (param $p i32) (result i32)
;; CHECK-NEXT: (local $x i32)
;; CHECK-NEXT: (local $y i32)
;; CHECK-NEXT: (local.set $x
;; CHECK-NEXT: (i32.const 10)
;; CHECK-NEXT: )
;; CHECK-NEXT: (if
;; CHECK-NEXT: (i32.const 1)
;; CHECK-NEXT: (then
;; CHECK-NEXT: (local.set $y
;; CHECK-NEXT: (i32.const 11)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (else
;; CHECK-NEXT: (local.set $y
;; CHECK-NEXT: (i32.const 11)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (local.set $y
;; CHECK-NEXT: (i32.const 21)
;; CHECK-NEXT: )
;; CHECK-NEXT: (i32.const 21)
;; CHECK-NEXT: )
(func $two-ways-but-identical (param $p i32) (result i32)
(local $x i32)
(local $y i32)
(local.set $x (i32.const 10))
(if (i32.const 1)
(then
(local.set $y (i32.const 11))
)
(else
(local.set $y (i32.add (local.get $x) (i32.const 1)))
)
)
(local.set $y (i32.add (local.get $x) (local.get $y)))
(local.get $y)
)
;; CHECK: (func $two-ways-but-almost-identical (type $1) (param $p i32) (result i32)
;; CHECK-NEXT: (local $x i32)
;; CHECK-NEXT: (local $y i32)
;; CHECK-NEXT: (local.set $x
;; CHECK-NEXT: (i32.const 10)
;; CHECK-NEXT: )
;; CHECK-NEXT: (if
;; CHECK-NEXT: (i32.const 1)
;; CHECK-NEXT: (then
;; CHECK-NEXT: (local.set $y
;; CHECK-NEXT: (i32.const 12)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (else
;; CHECK-NEXT: (local.set $y
;; CHECK-NEXT: (i32.const 11)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (local.set $y
;; CHECK-NEXT: (i32.add
;; CHECK-NEXT: (i32.const 10)
;; CHECK-NEXT: (local.get $y)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (local.get $y)
;; CHECK-NEXT: )
(func $two-ways-but-almost-identical (param $p i32) (result i32)
(local $x i32)
(local $y i32)
(local.set $x (i32.const 10))
(if (i32.const 1)
(then
(local.set $y (i32.const 12)) ;; 12, not 11...
)
(else
(local.set $y (i32.add (local.get $x) (i32.const 1)))
)
)
(local.set $y (i32.add (local.get $x) (local.get $y)))
(local.get $y)
)
;; CHECK: (func $deadloop (type $1) (param $p i32) (result i32)
;; CHECK-NEXT: (local $x i32)
;; CHECK-NEXT: (local $y i32)
;; CHECK-NEXT: (loop $loop
;; CHECK-NEXT: (local.set $x
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: (local.set $y
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: (br $loop)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $deadloop (param $p i32) (result i32)
(local $x i32)
(local $y i32)
(loop $loop ;; we look like we depend on the other, but we don't actually
(local.set $x (if (result i32) (i32.const 1) (then (i32.const 0) )(else (local.get $y))))
(local.set $y (if (result i32) (i32.const 1) (then (i32.const 0) )(else (local.get $x))))
(br $loop)
)
)
;; CHECK: (func $deadloop2 (type $0) (param $p i32)
;; CHECK-NEXT: (local $x i32)
;; CHECK-NEXT: (local $y i32)
;; CHECK-NEXT: (loop $loop
;; CHECK-NEXT: (local.set $x
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: (local.set $y
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: (call $deadloop2
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: (call $deadloop2
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: (br $loop)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $deadloop2 (param $p i32)
(local $x i32)
(local $y i32)
(loop $loop ;; we look like we depend on the other, but we don't actually
(local.set $x (if (result i32) (i32.const 1) (then (i32.const 0) )(else (local.get $y))))
(local.set $y (if (result i32) (i32.const 1) (then (i32.const 0) )(else (local.get $x))))
(call $deadloop2 (local.get $x))
(call $deadloop2 (local.get $y))
(br $loop)
)
)
;; CHECK: (func $deadloop3 (type $0) (param $p i32)
;; CHECK-NEXT: (local $x i32)
;; CHECK-NEXT: (local $y i32)
;; CHECK-NEXT: (loop $loop
;; CHECK-NEXT: (local.set $x
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: (local.set $y
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: (call $deadloop2
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: (call $deadloop2
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: (br $loop)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $deadloop3 (param $p i32)
(local $x i32)
(local $y i32)
(loop $loop ;; we look like we depend on the other, but we don't actually
(local.set $x (if (result i32) (i32.const 1) (then (i32.const 0) )(else (local.get $x))))
(local.set $y (if (result i32) (i32.const 1) (then (i32.const 0) )(else (local.get $y))))
(call $deadloop2 (local.get $x))
(call $deadloop2 (local.get $y))
(br $loop)
)
)
;; CHECK: (func $through-tee (type $2) (param $x i32) (param $y i32) (result i32)
;; CHECK-NEXT: (local.set $x
;; CHECK-NEXT: (local.tee $y
;; CHECK-NEXT: (i32.const 7)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (return
;; CHECK-NEXT: (i32.const 14)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $through-tee (param $x i32) (param $y i32) (result i32)
(local.set $x
(local.tee $y
(i32.const 7)
)
)
(return
(i32.add
(local.get $x)
(local.get $y)
)
)
)
;; CHECK: (func $through-tee-more (type $2) (param $x i32) (param $y i32) (result i32)
;; CHECK-NEXT: (local.set $x
;; CHECK-NEXT: (block (result i32)
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (local.tee $y
;; CHECK-NEXT: (i32.const 7)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (return
;; CHECK-NEXT: (i32.const 7)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $through-tee-more (param $x i32) (param $y i32) (result i32)
(local.set $x
(i32.eqz
(local.tee $y
(i32.const 7)
)
)
)
(return
(i32.add
(local.get $x)
(local.get $y)
)
)
)
;; CHECK: (func $multipass (type $4) (param $0 i32) (param $1 i32) (param $2 i32) (result i32)
;; CHECK-NEXT: (local $3 i32)
;; CHECK-NEXT: (nop)
;; CHECK-NEXT: (if
;; CHECK-NEXT: (local.get $3)
;; CHECK-NEXT: (then
;; CHECK-NEXT: (local.set $2
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (local.get $2)
;; CHECK-NEXT: )
(func $multipass (param $0 i32) (param $1 i32) (param $2 i32) (result i32)
(local $3 i32)
(if
(local.get $3) ;; this will be precomputed to 0. after that, the if will be
;; precomputed to not exist at all. removing the set in the
;; if body then allows us to optimize the value of $3 in the
;; if lower down, but we do not do an additional cycle of
;; this pass automatically as such things are fairly rare,
;; so that opportunity remains unoptimized in this test.
(then
(local.set $3 ;; this set is completely removed, allowing later opts
(i32.const 24)
)
)
)
(if
(local.get $3)
(then
(local.set $2
(i32.const 0)
)
)
)
(local.get $2)
)
;; CHECK: (func $through-fallthrough (type $2) (param $x i32) (param $y i32) (result i32)
;; CHECK-NEXT: (local.set $x
;; CHECK-NEXT: (block (result i32)
;; CHECK-NEXT: (nop)
;; CHECK-NEXT: (local.tee $y
;; CHECK-NEXT: (i32.const 7)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (return
;; CHECK-NEXT: (i32.const 14)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $through-fallthrough (param $x i32) (param $y i32) (result i32)
(local.set $x
(block (result i32)
(nop)
(local.tee $y
(i32.const 7)
)
)
)
(return
(i32.add
(local.get $x)
(local.get $y)
)
)
)
;; CHECK: (func $simd-load (type $5) (result v128)
;; CHECK-NEXT: (local $x v128)
;; CHECK-NEXT: (local.set $x
;; CHECK-NEXT: (v128.load8_splat
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (local.get $x)
;; CHECK-NEXT: )
(func $simd-load (result v128)
(local $x v128)
(local.set $x (v128.load8_splat (i32.const 0)))
(local.get $x)
)
;; CHECK: (func $tuple-local (type $3) (result i32 i64)
;; CHECK-NEXT: (local $i32s (tuple i32 i32))
;; CHECK-NEXT: (local $i64s (tuple i64 i64))
;; CHECK-NEXT: (local.set $i32s
;; CHECK-NEXT: (tuple.make 2
;; CHECK-NEXT: (i32.const 42)
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (local.set $i64s
;; CHECK-NEXT: (tuple.make 2
;; CHECK-NEXT: (i64.const 42)
;; CHECK-NEXT: (i64.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (tuple.make 2
;; CHECK-NEXT: (i32.const 42)
;; CHECK-NEXT: (i64.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $tuple-local (result i32 i64)
(local $i32s (tuple i32 i32))
(local $i64s (tuple i64 i64))
(local.set $i32s
(tuple.make 2
(i32.const 42)
(i32.const 0)
)
)
(local.set $i64s
(tuple.make 2
(i64.const 42)
(i64.const 0)
)
)
(tuple.make 2
(tuple.extract 2 0
(local.get $i32s)
)
(tuple.extract 2 1
(local.get $i64s)
)
)
)
)