blob: d2709cf3a4dce0fc7b2e743787df4a2b73a067a8 [file] [log] [blame] [edit]
;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited.
;; RUN: wasm-opt %s --remove-unused-names --precompute-propagate --fuzz-exec -all -S -o - \
;; RUN: | filecheck %s
(module
;; CHECK: (global $g (mut i32) (i32.const 10))
(global $g (mut i32) (i32.const 10))
;; CHECK: (func $loop (type $1)
;; CHECK-NEXT: (local $temp i32)
;; CHECK-NEXT: (local.set $temp
;; CHECK-NEXT: (i32.const 10)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $loop
(local $temp i32)
;; We should not try to precompute this loop. If we attempted to replace it
;; with its children, we'd need to handle the effects of chidren properly,
;; which we do not do in this pass.
(loop
(local.set $temp
(i32.const 10)
)
)
)
;; CHECK: (func $local.set (type $1)
;; CHECK-NEXT: (local $temp i32)
;; CHECK-NEXT: (local.set $temp
;; CHECK-NEXT: (i32.const 10)
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (local.tee $temp
;; CHECK-NEXT: (i32.const 20)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $local.set
(local $temp i32)
;; We should not try to precompute a set or tee.
(local.set $temp
(i32.const 10)
)
(drop
(local.tee $temp
(i32.const 20)
)
)
)
;; CHECK: (func $global.set (type $1)
;; CHECK-NEXT: (global.set $g
;; CHECK-NEXT: (i32.const 20)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $global.set
;; We should not try to precompute a global set.
(global.set $g
(i32.const 20)
)
)
;; CHECK: (func $binary-tee (type $0) (result i32)
;; CHECK-NEXT: (local $temp i32)
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (local.tee $temp
;; CHECK-NEXT: (i32.const 10)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (i32.const 20)
;; CHECK-NEXT: )
(func $binary-tee (result i32)
(local $temp i32)
;; We can precompute this and remove the add, but must keep the tee.
(i32.add
(local.tee $temp
(i32.const 10)
)
(local.get $temp)
)
)
;; CHECK: (func $binary-tee-2 (type $0) (result i32)
;; CHECK-NEXT: (local $temp i32)
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (local.tee $temp
;; CHECK-NEXT: (i32.const 10)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (i32.const 10)
;; CHECK-NEXT: )
(func $binary-tee-2 (result i32)
(local $temp i32)
;; A tee on the other side.
(i32.add
(local.get $temp)
(local.tee $temp
(i32.const 10)
)
)
)
;; CHECK: (func $binary-both (type $0) (result i32)
;; CHECK-NEXT: (local $temp i32)
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (local.tee $temp
;; CHECK-NEXT: (i32.const 10)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (local.tee $temp
;; CHECK-NEXT: (i32.const 20)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (i32.const 30)
;; CHECK-NEXT: )
(func $binary-both (result i32)
(local $temp i32)
;; Now we must keep both tees.
(i32.add
(local.tee $temp
(i32.const 10)
)
(local.tee $temp
(i32.const 20)
)
)
)
;; CHECK: (func $nested-global (type $0) (result i32)
;; CHECK-NEXT: (local $temp i32)
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (block (result i32)
;; CHECK-NEXT: (local.set $temp
;; CHECK-NEXT: (i32.const 10)
;; CHECK-NEXT: )
;; CHECK-NEXT: (i32.const 20)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (block (result i32)
;; CHECK-NEXT: (global.set $g
;; CHECK-NEXT: (i32.const 30)
;; CHECK-NEXT: )
;; CHECK-NEXT: (i32.const 40)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (i32.const 60)
;; CHECK-NEXT: )
(func $nested-global (result i32)
(local $temp i32)
;; Nested effects inside arms, and one is a global effect.
(i32.add
(block (result i32)
(local.set $temp
(i32.const 10)
)
(i32.const 20)
)
(block (result i32)
(global.set $g
(i32.const 30)
)
(i32.const 40)
)
)
)
;; CHECK: (func $if (type $0) (result i32)
;; CHECK-NEXT: (i32.const 2)
;; CHECK-NEXT: )
(func $if (result i32)
;; We precompute simple ifs.
(if (result i32)
(i32.const 1)
(then
(i32.const 2)
)
(else
(i32.const 3)
)
)
)
;; CHECK: (func $if-no (type $0) (result i32)
;; CHECK-NEXT: (if (result i32)
;; CHECK-NEXT: (i32.const 1)
;; CHECK-NEXT: (then
;; CHECK-NEXT: (global.set $g
;; CHECK-NEXT: (i32.const 20)
;; CHECK-NEXT: )
;; CHECK-NEXT: (i32.const 2)
;; CHECK-NEXT: )
;; CHECK-NEXT: (else
;; CHECK-NEXT: (i32.const 3)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $if-no (result i32)
;; We do not precompute ifs with effects.
(if (result i32)
(i32.const 1)
(then
(block (result i32)
(global.set $g
(i32.const 20)
)
(i32.const 2)
)
)
(else
(i32.const 3)
)
)
)
;; CHECK: (func $try (type $0) (result i32)
;; CHECK-NEXT: (try (result i32)
;; CHECK-NEXT: (do
;; CHECK-NEXT: (i32.const 1)
;; CHECK-NEXT: )
;; CHECK-NEXT: (catch_all
;; CHECK-NEXT: (i32.const 2)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $try (result i32)
;; We don't precompute trys.
(try (result i32)
(do
(i32.const 1)
)
(catch_all
(i32.const 2)
)
)
)
;; CHECK: (func $ordering (type $0) (result i32)
;; CHECK-NEXT: (local $temp i32)
;; CHECK-NEXT: (block $out (result i32)
;; CHECK-NEXT: (select
;; CHECK-NEXT: (block (result i32)
;; CHECK-NEXT: (local.set $temp
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: (i32.const 20)
;; CHECK-NEXT: )
;; CHECK-NEXT: (br $out
;; CHECK-NEXT: (i32.const 10)
;; CHECK-NEXT: )
;; CHECK-NEXT: (block (result i32)
;; CHECK-NEXT: (global.set $g
;; CHECK-NEXT: (i32.const 30)
;; CHECK-NEXT: )
;; CHECK-NEXT: (i32.const 40)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $ordering (result i32)
(local $temp i32)
;; Nested effects inside arms. The br in the middle arm will execute, so we
;; want to precompute the entire select into a br, but we must keep alive the
;; children before and after. While doing so, we must not *reorder* the middle
;; child against them: if we just remove the middle child (and add a br at the
;; end) then we are changing the order of execution, as the global.set would
;; happen, when before it did not. For simplicity, we do not optimize here.
(block $out (result i32)
(select
(block (result i32)
(local.set $temp
(i32.const 0)
)
(i32.const 20)
)
(block (result i32)
(br $out
(i32.const 10)
)
(i32.const 20)
)
(block (result i32)
(global.set $g
(i32.const 30)
)
(i32.const 40)
)
)
)
)
)