blob: ca929a47b39c233236588901aa6f645f2d69f192 [file] [edit]
;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited.
;; Test optimization decisions while varying the minimum benefit percentage
;; parameter. Zero means any benefit, no matter how small, is worthwhile, while
;; higher values demand more benefit before doing any work.
;;
;; Test with --traps-never-happen (tnh) here so that we optimize more, making it
;; easier to show the effects. This is also more realistic for toolchains like
;; Java/Kotlin/Dart, which is good coverage.
;; RUN: foreach %s %t wasm-opt --monomorphize -all -tnh -S -o - | filecheck %s --check-prefix DEFAULT
;; RUN: foreach %s %t wasm-opt --monomorphize --pass-arg=monomorphize-min-benefit@0 -all -tnh -S -o - | filecheck %s --check-prefix ZERO___
;; RUN: foreach %s %t wasm-opt --monomorphize --pass-arg=monomorphize-min-benefit@33 -all -tnh -S -o - | filecheck %s --check-prefix THIRD__
;; RUN: foreach %s %t wasm-opt --monomorphize --pass-arg=monomorphize-min-benefit@66 -all -tnh -S -o - | filecheck %s --check-prefix TWOTRDS
;; RUN: foreach %s %t wasm-opt --monomorphize --pass-arg=monomorphize-min-benefit@100 -all -tnh -S -o - | filecheck %s --check-prefix HUNDRED
(module
(memory 10 20)
;; DEFAULT: (type $0 (func (param i32 i32 i32 i32 i32)))
;; DEFAULT: (type $1 (func (param i32)))
;; DEFAULT: (memory $0 10 20)
;; DEFAULT: (func $target (type $0) (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32) (param $4 i32)
;; DEFAULT-NEXT: (i32.store
;; DEFAULT-NEXT: (i32.const 10)
;; DEFAULT-NEXT: (i32.div_s
;; DEFAULT-NEXT: (local.get $0)
;; DEFAULT-NEXT: (i32.add
;; DEFAULT-NEXT: (local.get $0)
;; DEFAULT-NEXT: (i32.const 1)
;; DEFAULT-NEXT: )
;; DEFAULT-NEXT: )
;; DEFAULT-NEXT: )
;; DEFAULT-NEXT: (i32.store
;; DEFAULT-NEXT: (i32.const 20)
;; DEFAULT-NEXT: (i32.div_s
;; DEFAULT-NEXT: (local.get $1)
;; DEFAULT-NEXT: (i32.add
;; DEFAULT-NEXT: (local.get $1)
;; DEFAULT-NEXT: (i32.const 1)
;; DEFAULT-NEXT: )
;; DEFAULT-NEXT: )
;; DEFAULT-NEXT: )
;; DEFAULT-NEXT: (i32.store
;; DEFAULT-NEXT: (i32.const 30)
;; DEFAULT-NEXT: (i32.div_s
;; DEFAULT-NEXT: (local.get $2)
;; DEFAULT-NEXT: (i32.add
;; DEFAULT-NEXT: (local.get $2)
;; DEFAULT-NEXT: (i32.const 1)
;; DEFAULT-NEXT: )
;; DEFAULT-NEXT: )
;; DEFAULT-NEXT: )
;; DEFAULT-NEXT: (i32.store
;; DEFAULT-NEXT: (i32.const 40)
;; DEFAULT-NEXT: (i32.div_s
;; DEFAULT-NEXT: (local.get $3)
;; DEFAULT-NEXT: (i32.add
;; DEFAULT-NEXT: (local.get $3)
;; DEFAULT-NEXT: (i32.const 1)
;; DEFAULT-NEXT: )
;; DEFAULT-NEXT: )
;; DEFAULT-NEXT: )
;; DEFAULT-NEXT: (i32.store
;; DEFAULT-NEXT: (i32.const 50)
;; DEFAULT-NEXT: (i32.div_s
;; DEFAULT-NEXT: (local.get $4)
;; DEFAULT-NEXT: (i32.add
;; DEFAULT-NEXT: (local.get $4)
;; DEFAULT-NEXT: (i32.const 1)
;; DEFAULT-NEXT: )
;; DEFAULT-NEXT: )
;; DEFAULT-NEXT: )
;; DEFAULT-NEXT: )
;; ZERO___: (type $0 (func (param i32)))
;; ZERO___: (type $1 (func (param i32 i32 i32 i32 i32)))
;; ZERO___: (type $2 (func))
;; ZERO___: (type $3 (func (param i32 i32)))
;; ZERO___: (type $4 (func (param i32 i32 i32)))
;; ZERO___: (type $5 (func (param i32 i32 i32 i32)))
;; ZERO___: (memory $0 10 20)
;; ZERO___: (func $target (type $1) (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32) (param $4 i32)
;; ZERO___-NEXT: (i32.store
;; ZERO___-NEXT: (i32.const 10)
;; ZERO___-NEXT: (i32.div_s
;; ZERO___-NEXT: (local.get $0)
;; ZERO___-NEXT: (i32.add
;; ZERO___-NEXT: (local.get $0)
;; ZERO___-NEXT: (i32.const 1)
;; ZERO___-NEXT: )
;; ZERO___-NEXT: )
;; ZERO___-NEXT: )
;; ZERO___-NEXT: (i32.store
;; ZERO___-NEXT: (i32.const 20)
;; ZERO___-NEXT: (i32.div_s
;; ZERO___-NEXT: (local.get $1)
;; ZERO___-NEXT: (i32.add
;; ZERO___-NEXT: (local.get $1)
;; ZERO___-NEXT: (i32.const 1)
;; ZERO___-NEXT: )
;; ZERO___-NEXT: )
;; ZERO___-NEXT: )
;; ZERO___-NEXT: (i32.store
;; ZERO___-NEXT: (i32.const 30)
;; ZERO___-NEXT: (i32.div_s
;; ZERO___-NEXT: (local.get $2)
;; ZERO___-NEXT: (i32.add
;; ZERO___-NEXT: (local.get $2)
;; ZERO___-NEXT: (i32.const 1)
;; ZERO___-NEXT: )
;; ZERO___-NEXT: )
;; ZERO___-NEXT: )
;; ZERO___-NEXT: (i32.store
;; ZERO___-NEXT: (i32.const 40)
;; ZERO___-NEXT: (i32.div_s
;; ZERO___-NEXT: (local.get $3)
;; ZERO___-NEXT: (i32.add
;; ZERO___-NEXT: (local.get $3)
;; ZERO___-NEXT: (i32.const 1)
;; ZERO___-NEXT: )
;; ZERO___-NEXT: )
;; ZERO___-NEXT: )
;; ZERO___-NEXT: (i32.store
;; ZERO___-NEXT: (i32.const 50)
;; ZERO___-NEXT: (i32.div_s
;; ZERO___-NEXT: (local.get $4)
;; ZERO___-NEXT: (i32.add
;; ZERO___-NEXT: (local.get $4)
;; ZERO___-NEXT: (i32.const 1)
;; ZERO___-NEXT: )
;; ZERO___-NEXT: )
;; ZERO___-NEXT: )
;; ZERO___-NEXT: )
;; THIRD__: (type $0 (func (param i32)))
;; THIRD__: (type $1 (func (param i32 i32 i32 i32 i32)))
;; THIRD__: (type $2 (func))
;; THIRD__: (type $3 (func (param i32 i32)))
;; THIRD__: (memory $0 10 20)
;; THIRD__: (func $target (type $1) (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32) (param $4 i32)
;; THIRD__-NEXT: (i32.store
;; THIRD__-NEXT: (i32.const 10)
;; THIRD__-NEXT: (i32.div_s
;; THIRD__-NEXT: (local.get $0)
;; THIRD__-NEXT: (i32.add
;; THIRD__-NEXT: (local.get $0)
;; THIRD__-NEXT: (i32.const 1)
;; THIRD__-NEXT: )
;; THIRD__-NEXT: )
;; THIRD__-NEXT: )
;; THIRD__-NEXT: (i32.store
;; THIRD__-NEXT: (i32.const 20)
;; THIRD__-NEXT: (i32.div_s
;; THIRD__-NEXT: (local.get $1)
;; THIRD__-NEXT: (i32.add
;; THIRD__-NEXT: (local.get $1)
;; THIRD__-NEXT: (i32.const 1)
;; THIRD__-NEXT: )
;; THIRD__-NEXT: )
;; THIRD__-NEXT: )
;; THIRD__-NEXT: (i32.store
;; THIRD__-NEXT: (i32.const 30)
;; THIRD__-NEXT: (i32.div_s
;; THIRD__-NEXT: (local.get $2)
;; THIRD__-NEXT: (i32.add
;; THIRD__-NEXT: (local.get $2)
;; THIRD__-NEXT: (i32.const 1)
;; THIRD__-NEXT: )
;; THIRD__-NEXT: )
;; THIRD__-NEXT: )
;; THIRD__-NEXT: (i32.store
;; THIRD__-NEXT: (i32.const 40)
;; THIRD__-NEXT: (i32.div_s
;; THIRD__-NEXT: (local.get $3)
;; THIRD__-NEXT: (i32.add
;; THIRD__-NEXT: (local.get $3)
;; THIRD__-NEXT: (i32.const 1)
;; THIRD__-NEXT: )
;; THIRD__-NEXT: )
;; THIRD__-NEXT: )
;; THIRD__-NEXT: (i32.store
;; THIRD__-NEXT: (i32.const 50)
;; THIRD__-NEXT: (i32.div_s
;; THIRD__-NEXT: (local.get $4)
;; THIRD__-NEXT: (i32.add
;; THIRD__-NEXT: (local.get $4)
;; THIRD__-NEXT: (i32.const 1)
;; THIRD__-NEXT: )
;; THIRD__-NEXT: )
;; THIRD__-NEXT: )
;; THIRD__-NEXT: )
;; TWOTRDS: (type $0 (func (param i32 i32 i32 i32 i32)))
;; TWOTRDS: (type $1 (func (param i32)))
;; TWOTRDS: (type $2 (func))
;; TWOTRDS: (memory $0 10 20)
;; TWOTRDS: (func $target (type $0) (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32) (param $4 i32)
;; TWOTRDS-NEXT: (i32.store
;; TWOTRDS-NEXT: (i32.const 10)
;; TWOTRDS-NEXT: (i32.div_s
;; TWOTRDS-NEXT: (local.get $0)
;; TWOTRDS-NEXT: (i32.add
;; TWOTRDS-NEXT: (local.get $0)
;; TWOTRDS-NEXT: (i32.const 1)
;; TWOTRDS-NEXT: )
;; TWOTRDS-NEXT: )
;; TWOTRDS-NEXT: )
;; TWOTRDS-NEXT: (i32.store
;; TWOTRDS-NEXT: (i32.const 20)
;; TWOTRDS-NEXT: (i32.div_s
;; TWOTRDS-NEXT: (local.get $1)
;; TWOTRDS-NEXT: (i32.add
;; TWOTRDS-NEXT: (local.get $1)
;; TWOTRDS-NEXT: (i32.const 1)
;; TWOTRDS-NEXT: )
;; TWOTRDS-NEXT: )
;; TWOTRDS-NEXT: )
;; TWOTRDS-NEXT: (i32.store
;; TWOTRDS-NEXT: (i32.const 30)
;; TWOTRDS-NEXT: (i32.div_s
;; TWOTRDS-NEXT: (local.get $2)
;; TWOTRDS-NEXT: (i32.add
;; TWOTRDS-NEXT: (local.get $2)
;; TWOTRDS-NEXT: (i32.const 1)
;; TWOTRDS-NEXT: )
;; TWOTRDS-NEXT: )
;; TWOTRDS-NEXT: )
;; TWOTRDS-NEXT: (i32.store
;; TWOTRDS-NEXT: (i32.const 40)
;; TWOTRDS-NEXT: (i32.div_s
;; TWOTRDS-NEXT: (local.get $3)
;; TWOTRDS-NEXT: (i32.add
;; TWOTRDS-NEXT: (local.get $3)
;; TWOTRDS-NEXT: (i32.const 1)
;; TWOTRDS-NEXT: )
;; TWOTRDS-NEXT: )
;; TWOTRDS-NEXT: )
;; TWOTRDS-NEXT: (i32.store
;; TWOTRDS-NEXT: (i32.const 50)
;; TWOTRDS-NEXT: (i32.div_s
;; TWOTRDS-NEXT: (local.get $4)
;; TWOTRDS-NEXT: (i32.add
;; TWOTRDS-NEXT: (local.get $4)
;; TWOTRDS-NEXT: (i32.const 1)
;; TWOTRDS-NEXT: )
;; TWOTRDS-NEXT: )
;; TWOTRDS-NEXT: )
;; TWOTRDS-NEXT: )
;; HUNDRED: (type $0 (func (param i32 i32 i32 i32 i32)))
;; HUNDRED: (type $1 (func (param i32)))
;; HUNDRED: (memory $0 10 20)
;; HUNDRED: (func $target (type $0) (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32) (param $4 i32)
;; HUNDRED-NEXT: (i32.store
;; HUNDRED-NEXT: (i32.const 10)
;; HUNDRED-NEXT: (i32.div_s
;; HUNDRED-NEXT: (local.get $0)
;; HUNDRED-NEXT: (i32.add
;; HUNDRED-NEXT: (local.get $0)
;; HUNDRED-NEXT: (i32.const 1)
;; HUNDRED-NEXT: )
;; HUNDRED-NEXT: )
;; HUNDRED-NEXT: )
;; HUNDRED-NEXT: (i32.store
;; HUNDRED-NEXT: (i32.const 20)
;; HUNDRED-NEXT: (i32.div_s
;; HUNDRED-NEXT: (local.get $1)
;; HUNDRED-NEXT: (i32.add
;; HUNDRED-NEXT: (local.get $1)
;; HUNDRED-NEXT: (i32.const 1)
;; HUNDRED-NEXT: )
;; HUNDRED-NEXT: )
;; HUNDRED-NEXT: )
;; HUNDRED-NEXT: (i32.store
;; HUNDRED-NEXT: (i32.const 30)
;; HUNDRED-NEXT: (i32.div_s
;; HUNDRED-NEXT: (local.get $2)
;; HUNDRED-NEXT: (i32.add
;; HUNDRED-NEXT: (local.get $2)
;; HUNDRED-NEXT: (i32.const 1)
;; HUNDRED-NEXT: )
;; HUNDRED-NEXT: )
;; HUNDRED-NEXT: )
;; HUNDRED-NEXT: (i32.store
;; HUNDRED-NEXT: (i32.const 40)
;; HUNDRED-NEXT: (i32.div_s
;; HUNDRED-NEXT: (local.get $3)
;; HUNDRED-NEXT: (i32.add
;; HUNDRED-NEXT: (local.get $3)
;; HUNDRED-NEXT: (i32.const 1)
;; HUNDRED-NEXT: )
;; HUNDRED-NEXT: )
;; HUNDRED-NEXT: )
;; HUNDRED-NEXT: (i32.store
;; HUNDRED-NEXT: (i32.const 50)
;; HUNDRED-NEXT: (i32.div_s
;; HUNDRED-NEXT: (local.get $4)
;; HUNDRED-NEXT: (i32.add
;; HUNDRED-NEXT: (local.get $4)
;; HUNDRED-NEXT: (i32.const 1)
;; HUNDRED-NEXT: )
;; HUNDRED-NEXT: )
;; HUNDRED-NEXT: )
;; HUNDRED-NEXT: )
(func $target (param $a i32) (param $b i32) (param $c i32) (param $d i32) (param $e i32)
;; This function takes five parameters and uses each one to do some work. In
;; Each of the following identical stores, when we know one of the five
;; params, we can compute in full the value stored. (The store offsets
;; differ to guard against a future dead store elimination.)
(i32.store
(i32.const 10)
(i32.div_s
(local.get $a)
(i32.add
(local.get $a)
(i32.const 1)
)
)
)
(i32.store
(i32.const 20)
(i32.div_s
(local.get $b)
(i32.add
(local.get $b)
(i32.const 1)
)
)
)
(i32.store
(i32.const 30)
(i32.div_s
(local.get $c)
(i32.add
(local.get $c)
(i32.const 1)
)
)
)
(i32.store
(i32.const 40)
(i32.div_s
(local.get $d)
(i32.add
(local.get $d)
(i32.const 1)
)
)
)
(i32.store
(i32.const 50)
(i32.div_s
(local.get $e)
(i32.add
(local.get $e)
(i32.const 1)
)
)
)
)
;; DEFAULT: (func $calls (type $1) (param $x i32)
;; DEFAULT-NEXT: (call $target
;; DEFAULT-NEXT: (i32.const 42)
;; DEFAULT-NEXT: (i32.const 42)
;; DEFAULT-NEXT: (i32.const 42)
;; DEFAULT-NEXT: (i32.const 42)
;; DEFAULT-NEXT: (i32.const 42)
;; DEFAULT-NEXT: )
;; DEFAULT-NEXT: (call $target
;; DEFAULT-NEXT: (local.get $x)
;; DEFAULT-NEXT: (i32.const 42)
;; DEFAULT-NEXT: (i32.const 42)
;; DEFAULT-NEXT: (i32.const 42)
;; DEFAULT-NEXT: (i32.const 42)
;; DEFAULT-NEXT: )
;; DEFAULT-NEXT: (call $target
;; DEFAULT-NEXT: (local.get $x)
;; DEFAULT-NEXT: (local.get $x)
;; DEFAULT-NEXT: (i32.const 42)
;; DEFAULT-NEXT: (i32.const 42)
;; DEFAULT-NEXT: (i32.const 42)
;; DEFAULT-NEXT: )
;; DEFAULT-NEXT: (call $target
;; DEFAULT-NEXT: (local.get $x)
;; DEFAULT-NEXT: (local.get $x)
;; DEFAULT-NEXT: (local.get $x)
;; DEFAULT-NEXT: (i32.const 42)
;; DEFAULT-NEXT: (i32.const 42)
;; DEFAULT-NEXT: )
;; DEFAULT-NEXT: (call $target
;; DEFAULT-NEXT: (local.get $x)
;; DEFAULT-NEXT: (local.get $x)
;; DEFAULT-NEXT: (local.get $x)
;; DEFAULT-NEXT: (local.get $x)
;; DEFAULT-NEXT: (i32.const 42)
;; DEFAULT-NEXT: )
;; DEFAULT-NEXT: (call $target
;; DEFAULT-NEXT: (local.get $x)
;; DEFAULT-NEXT: (local.get $x)
;; DEFAULT-NEXT: (local.get $x)
;; DEFAULT-NEXT: (local.get $x)
;; DEFAULT-NEXT: (local.get $x)
;; DEFAULT-NEXT: )
;; DEFAULT-NEXT: )
;; ZERO___: (func $calls (type $0) (param $x i32)
;; ZERO___-NEXT: (call $target_2)
;; ZERO___-NEXT: (call $target_3
;; ZERO___-NEXT: (local.get $x)
;; ZERO___-NEXT: )
;; ZERO___-NEXT: (call $target_4
;; ZERO___-NEXT: (local.get $x)
;; ZERO___-NEXT: (local.get $x)
;; ZERO___-NEXT: )
;; ZERO___-NEXT: (call $target_5
;; ZERO___-NEXT: (local.get $x)
;; ZERO___-NEXT: (local.get $x)
;; ZERO___-NEXT: (local.get $x)
;; ZERO___-NEXT: )
;; ZERO___-NEXT: (call $target_6
;; ZERO___-NEXT: (local.get $x)
;; ZERO___-NEXT: (local.get $x)
;; ZERO___-NEXT: (local.get $x)
;; ZERO___-NEXT: (local.get $x)
;; ZERO___-NEXT: )
;; ZERO___-NEXT: (call $target
;; ZERO___-NEXT: (local.get $x)
;; ZERO___-NEXT: (local.get $x)
;; ZERO___-NEXT: (local.get $x)
;; ZERO___-NEXT: (local.get $x)
;; ZERO___-NEXT: (local.get $x)
;; ZERO___-NEXT: )
;; ZERO___-NEXT: )
;; THIRD__: (func $calls (type $0) (param $x i32)
;; THIRD__-NEXT: (call $target_2)
;; THIRD__-NEXT: (call $target_3
;; THIRD__-NEXT: (local.get $x)
;; THIRD__-NEXT: )
;; THIRD__-NEXT: (call $target_4
;; THIRD__-NEXT: (local.get $x)
;; THIRD__-NEXT: (local.get $x)
;; THIRD__-NEXT: )
;; THIRD__-NEXT: (call $target
;; THIRD__-NEXT: (local.get $x)
;; THIRD__-NEXT: (local.get $x)
;; THIRD__-NEXT: (local.get $x)
;; THIRD__-NEXT: (i32.const 42)
;; THIRD__-NEXT: (i32.const 42)
;; THIRD__-NEXT: )
;; THIRD__-NEXT: (call $target
;; THIRD__-NEXT: (local.get $x)
;; THIRD__-NEXT: (local.get $x)
;; THIRD__-NEXT: (local.get $x)
;; THIRD__-NEXT: (local.get $x)
;; THIRD__-NEXT: (i32.const 42)
;; THIRD__-NEXT: )
;; THIRD__-NEXT: (call $target
;; THIRD__-NEXT: (local.get $x)
;; THIRD__-NEXT: (local.get $x)
;; THIRD__-NEXT: (local.get $x)
;; THIRD__-NEXT: (local.get $x)
;; THIRD__-NEXT: (local.get $x)
;; THIRD__-NEXT: )
;; THIRD__-NEXT: )
;; TWOTRDS: (func $calls (type $1) (param $x i32)
;; TWOTRDS-NEXT: (call $target_2)
;; TWOTRDS-NEXT: (call $target
;; TWOTRDS-NEXT: (local.get $x)
;; TWOTRDS-NEXT: (i32.const 42)
;; TWOTRDS-NEXT: (i32.const 42)
;; TWOTRDS-NEXT: (i32.const 42)
;; TWOTRDS-NEXT: (i32.const 42)
;; TWOTRDS-NEXT: )
;; TWOTRDS-NEXT: (call $target
;; TWOTRDS-NEXT: (local.get $x)
;; TWOTRDS-NEXT: (local.get $x)
;; TWOTRDS-NEXT: (i32.const 42)
;; TWOTRDS-NEXT: (i32.const 42)
;; TWOTRDS-NEXT: (i32.const 42)
;; TWOTRDS-NEXT: )
;; TWOTRDS-NEXT: (call $target
;; TWOTRDS-NEXT: (local.get $x)
;; TWOTRDS-NEXT: (local.get $x)
;; TWOTRDS-NEXT: (local.get $x)
;; TWOTRDS-NEXT: (i32.const 42)
;; TWOTRDS-NEXT: (i32.const 42)
;; TWOTRDS-NEXT: )
;; TWOTRDS-NEXT: (call $target
;; TWOTRDS-NEXT: (local.get $x)
;; TWOTRDS-NEXT: (local.get $x)
;; TWOTRDS-NEXT: (local.get $x)
;; TWOTRDS-NEXT: (local.get $x)
;; TWOTRDS-NEXT: (i32.const 42)
;; TWOTRDS-NEXT: )
;; TWOTRDS-NEXT: (call $target
;; TWOTRDS-NEXT: (local.get $x)
;; TWOTRDS-NEXT: (local.get $x)
;; TWOTRDS-NEXT: (local.get $x)
;; TWOTRDS-NEXT: (local.get $x)
;; TWOTRDS-NEXT: (local.get $x)
;; TWOTRDS-NEXT: )
;; TWOTRDS-NEXT: )
;; HUNDRED: (func $calls (type $1) (param $x i32)
;; HUNDRED-NEXT: (call $target
;; HUNDRED-NEXT: (i32.const 42)
;; HUNDRED-NEXT: (i32.const 42)
;; HUNDRED-NEXT: (i32.const 42)
;; HUNDRED-NEXT: (i32.const 42)
;; HUNDRED-NEXT: (i32.const 42)
;; HUNDRED-NEXT: )
;; HUNDRED-NEXT: (call $target
;; HUNDRED-NEXT: (local.get $x)
;; HUNDRED-NEXT: (i32.const 42)
;; HUNDRED-NEXT: (i32.const 42)
;; HUNDRED-NEXT: (i32.const 42)
;; HUNDRED-NEXT: (i32.const 42)
;; HUNDRED-NEXT: )
;; HUNDRED-NEXT: (call $target
;; HUNDRED-NEXT: (local.get $x)
;; HUNDRED-NEXT: (local.get $x)
;; HUNDRED-NEXT: (i32.const 42)
;; HUNDRED-NEXT: (i32.const 42)
;; HUNDRED-NEXT: (i32.const 42)
;; HUNDRED-NEXT: )
;; HUNDRED-NEXT: (call $target
;; HUNDRED-NEXT: (local.get $x)
;; HUNDRED-NEXT: (local.get $x)
;; HUNDRED-NEXT: (local.get $x)
;; HUNDRED-NEXT: (i32.const 42)
;; HUNDRED-NEXT: (i32.const 42)
;; HUNDRED-NEXT: )
;; HUNDRED-NEXT: (call $target
;; HUNDRED-NEXT: (local.get $x)
;; HUNDRED-NEXT: (local.get $x)
;; HUNDRED-NEXT: (local.get $x)
;; HUNDRED-NEXT: (local.get $x)
;; HUNDRED-NEXT: (i32.const 42)
;; HUNDRED-NEXT: )
;; HUNDRED-NEXT: (call $target
;; HUNDRED-NEXT: (local.get $x)
;; HUNDRED-NEXT: (local.get $x)
;; HUNDRED-NEXT: (local.get $x)
;; HUNDRED-NEXT: (local.get $x)
;; HUNDRED-NEXT: (local.get $x)
;; HUNDRED-NEXT: )
;; HUNDRED-NEXT: )
(func $calls (param $x i32)
;; Call the target with an increasing amount of non-constant params, 0-5.
;;
;; With 5 unknowns, the call context is trivial and we do nothing. All the
;; differences are therefore on 0-4:
;;
;; * ZERO monomorphizes all of 0-4.
;; * THIRD monomorphizes only 0-2.
;; * TWOTRDS monomorphizes just 0.
;; * HUNDRED monomorphizes none at all.
(call $target
(i32.const 42)
(i32.const 42)
(i32.const 42)
(i32.const 42)
(i32.const 42)
)
(call $target
(local.get $x)
(i32.const 42)
(i32.const 42)
(i32.const 42)
(i32.const 42)
)
(call $target
(local.get $x)
(local.get $x)
(i32.const 42)
(i32.const 42)
(i32.const 42)
)
(call $target
(local.get $x)
(local.get $x)
(local.get $x)
(i32.const 42)
(i32.const 42)
)
(call $target
(local.get $x)
(local.get $x)
(local.get $x)
(local.get $x)
(i32.const 42)
)
(call $target
(local.get $x)
(local.get $x)
(local.get $x)
(local.get $x)
(local.get $x)
)
)
)
;; ZERO___: (func $target_2 (type $2)
;; ZERO___-NEXT: (i32.store
;; ZERO___-NEXT: (i32.const 10)
;; ZERO___-NEXT: (i32.const 0)
;; ZERO___-NEXT: )
;; ZERO___-NEXT: (i32.store
;; ZERO___-NEXT: (i32.const 20)
;; ZERO___-NEXT: (i32.const 0)
;; ZERO___-NEXT: )
;; ZERO___-NEXT: (i32.store
;; ZERO___-NEXT: (i32.const 30)
;; ZERO___-NEXT: (i32.const 0)
;; ZERO___-NEXT: )
;; ZERO___-NEXT: (i32.store
;; ZERO___-NEXT: (i32.const 40)
;; ZERO___-NEXT: (i32.const 0)
;; ZERO___-NEXT: )
;; ZERO___-NEXT: (i32.store
;; ZERO___-NEXT: (i32.const 50)
;; ZERO___-NEXT: (i32.const 0)
;; ZERO___-NEXT: )
;; ZERO___-NEXT: )
;; ZERO___: (func $target_3 (type $0) (param $0 i32)
;; ZERO___-NEXT: (i32.store
;; ZERO___-NEXT: (i32.const 10)
;; ZERO___-NEXT: (i32.div_s
;; ZERO___-NEXT: (local.get $0)
;; ZERO___-NEXT: (i32.add
;; ZERO___-NEXT: (local.get $0)
;; ZERO___-NEXT: (i32.const 1)
;; ZERO___-NEXT: )
;; ZERO___-NEXT: )
;; ZERO___-NEXT: )
;; ZERO___-NEXT: (i32.store
;; ZERO___-NEXT: (i32.const 20)
;; ZERO___-NEXT: (i32.const 0)
;; ZERO___-NEXT: )
;; ZERO___-NEXT: (i32.store
;; ZERO___-NEXT: (i32.const 30)
;; ZERO___-NEXT: (i32.const 0)
;; ZERO___-NEXT: )
;; ZERO___-NEXT: (i32.store
;; ZERO___-NEXT: (i32.const 40)
;; ZERO___-NEXT: (i32.const 0)
;; ZERO___-NEXT: )
;; ZERO___-NEXT: (i32.store
;; ZERO___-NEXT: (i32.const 50)
;; ZERO___-NEXT: (i32.const 0)
;; ZERO___-NEXT: )
;; ZERO___-NEXT: )
;; ZERO___: (func $target_4 (type $3) (param $0 i32) (param $1 i32)
;; ZERO___-NEXT: (i32.store
;; ZERO___-NEXT: (i32.const 10)
;; ZERO___-NEXT: (i32.div_s
;; ZERO___-NEXT: (local.get $0)
;; ZERO___-NEXT: (i32.add
;; ZERO___-NEXT: (local.get $0)
;; ZERO___-NEXT: (i32.const 1)
;; ZERO___-NEXT: )
;; ZERO___-NEXT: )
;; ZERO___-NEXT: )
;; ZERO___-NEXT: (i32.store
;; ZERO___-NEXT: (i32.const 20)
;; ZERO___-NEXT: (i32.div_s
;; ZERO___-NEXT: (local.get $1)
;; ZERO___-NEXT: (i32.add
;; ZERO___-NEXT: (local.get $1)
;; ZERO___-NEXT: (i32.const 1)
;; ZERO___-NEXT: )
;; ZERO___-NEXT: )
;; ZERO___-NEXT: )
;; ZERO___-NEXT: (i32.store
;; ZERO___-NEXT: (i32.const 30)
;; ZERO___-NEXT: (i32.const 0)
;; ZERO___-NEXT: )
;; ZERO___-NEXT: (i32.store
;; ZERO___-NEXT: (i32.const 40)
;; ZERO___-NEXT: (i32.const 0)
;; ZERO___-NEXT: )
;; ZERO___-NEXT: (i32.store
;; ZERO___-NEXT: (i32.const 50)
;; ZERO___-NEXT: (i32.const 0)
;; ZERO___-NEXT: )
;; ZERO___-NEXT: )
;; ZERO___: (func $target_5 (type $4) (param $0 i32) (param $1 i32) (param $2 i32)
;; ZERO___-NEXT: (i32.store
;; ZERO___-NEXT: (i32.const 10)
;; ZERO___-NEXT: (i32.div_s
;; ZERO___-NEXT: (local.get $0)
;; ZERO___-NEXT: (i32.add
;; ZERO___-NEXT: (local.get $0)
;; ZERO___-NEXT: (i32.const 1)
;; ZERO___-NEXT: )
;; ZERO___-NEXT: )
;; ZERO___-NEXT: )
;; ZERO___-NEXT: (i32.store
;; ZERO___-NEXT: (i32.const 20)
;; ZERO___-NEXT: (i32.div_s
;; ZERO___-NEXT: (local.get $1)
;; ZERO___-NEXT: (i32.add
;; ZERO___-NEXT: (local.get $1)
;; ZERO___-NEXT: (i32.const 1)
;; ZERO___-NEXT: )
;; ZERO___-NEXT: )
;; ZERO___-NEXT: )
;; ZERO___-NEXT: (i32.store
;; ZERO___-NEXT: (i32.const 30)
;; ZERO___-NEXT: (i32.div_s
;; ZERO___-NEXT: (local.get $2)
;; ZERO___-NEXT: (i32.add
;; ZERO___-NEXT: (local.get $2)
;; ZERO___-NEXT: (i32.const 1)
;; ZERO___-NEXT: )
;; ZERO___-NEXT: )
;; ZERO___-NEXT: )
;; ZERO___-NEXT: (i32.store
;; ZERO___-NEXT: (i32.const 40)
;; ZERO___-NEXT: (i32.const 0)
;; ZERO___-NEXT: )
;; ZERO___-NEXT: (i32.store
;; ZERO___-NEXT: (i32.const 50)
;; ZERO___-NEXT: (i32.const 0)
;; ZERO___-NEXT: )
;; ZERO___-NEXT: )
;; ZERO___: (func $target_6 (type $5) (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32)
;; ZERO___-NEXT: (i32.store
;; ZERO___-NEXT: (i32.const 10)
;; ZERO___-NEXT: (i32.div_s
;; ZERO___-NEXT: (local.get $0)
;; ZERO___-NEXT: (i32.add
;; ZERO___-NEXT: (local.get $0)
;; ZERO___-NEXT: (i32.const 1)
;; ZERO___-NEXT: )
;; ZERO___-NEXT: )
;; ZERO___-NEXT: )
;; ZERO___-NEXT: (i32.store
;; ZERO___-NEXT: (i32.const 20)
;; ZERO___-NEXT: (i32.div_s
;; ZERO___-NEXT: (local.get $1)
;; ZERO___-NEXT: (i32.add
;; ZERO___-NEXT: (local.get $1)
;; ZERO___-NEXT: (i32.const 1)
;; ZERO___-NEXT: )
;; ZERO___-NEXT: )
;; ZERO___-NEXT: )
;; ZERO___-NEXT: (i32.store
;; ZERO___-NEXT: (i32.const 30)
;; ZERO___-NEXT: (i32.div_s
;; ZERO___-NEXT: (local.get $2)
;; ZERO___-NEXT: (i32.add
;; ZERO___-NEXT: (local.get $2)
;; ZERO___-NEXT: (i32.const 1)
;; ZERO___-NEXT: )
;; ZERO___-NEXT: )
;; ZERO___-NEXT: )
;; ZERO___-NEXT: (i32.store
;; ZERO___-NEXT: (i32.const 40)
;; ZERO___-NEXT: (i32.div_s
;; ZERO___-NEXT: (local.get $3)
;; ZERO___-NEXT: (i32.add
;; ZERO___-NEXT: (local.get $3)
;; ZERO___-NEXT: (i32.const 1)
;; ZERO___-NEXT: )
;; ZERO___-NEXT: )
;; ZERO___-NEXT: )
;; ZERO___-NEXT: (i32.store
;; ZERO___-NEXT: (i32.const 50)
;; ZERO___-NEXT: (i32.const 0)
;; ZERO___-NEXT: )
;; ZERO___-NEXT: )
;; THIRD__: (func $target_2 (type $2)
;; THIRD__-NEXT: (i32.store
;; THIRD__-NEXT: (i32.const 10)
;; THIRD__-NEXT: (i32.const 0)
;; THIRD__-NEXT: )
;; THIRD__-NEXT: (i32.store
;; THIRD__-NEXT: (i32.const 20)
;; THIRD__-NEXT: (i32.const 0)
;; THIRD__-NEXT: )
;; THIRD__-NEXT: (i32.store
;; THIRD__-NEXT: (i32.const 30)
;; THIRD__-NEXT: (i32.const 0)
;; THIRD__-NEXT: )
;; THIRD__-NEXT: (i32.store
;; THIRD__-NEXT: (i32.const 40)
;; THIRD__-NEXT: (i32.const 0)
;; THIRD__-NEXT: )
;; THIRD__-NEXT: (i32.store
;; THIRD__-NEXT: (i32.const 50)
;; THIRD__-NEXT: (i32.const 0)
;; THIRD__-NEXT: )
;; THIRD__-NEXT: )
;; THIRD__: (func $target_3 (type $0) (param $0 i32)
;; THIRD__-NEXT: (i32.store
;; THIRD__-NEXT: (i32.const 10)
;; THIRD__-NEXT: (i32.div_s
;; THIRD__-NEXT: (local.get $0)
;; THIRD__-NEXT: (i32.add
;; THIRD__-NEXT: (local.get $0)
;; THIRD__-NEXT: (i32.const 1)
;; THIRD__-NEXT: )
;; THIRD__-NEXT: )
;; THIRD__-NEXT: )
;; THIRD__-NEXT: (i32.store
;; THIRD__-NEXT: (i32.const 20)
;; THIRD__-NEXT: (i32.const 0)
;; THIRD__-NEXT: )
;; THIRD__-NEXT: (i32.store
;; THIRD__-NEXT: (i32.const 30)
;; THIRD__-NEXT: (i32.const 0)
;; THIRD__-NEXT: )
;; THIRD__-NEXT: (i32.store
;; THIRD__-NEXT: (i32.const 40)
;; THIRD__-NEXT: (i32.const 0)
;; THIRD__-NEXT: )
;; THIRD__-NEXT: (i32.store
;; THIRD__-NEXT: (i32.const 50)
;; THIRD__-NEXT: (i32.const 0)
;; THIRD__-NEXT: )
;; THIRD__-NEXT: )
;; THIRD__: (func $target_4 (type $3) (param $0 i32) (param $1 i32)
;; THIRD__-NEXT: (i32.store
;; THIRD__-NEXT: (i32.const 10)
;; THIRD__-NEXT: (i32.div_s
;; THIRD__-NEXT: (local.get $0)
;; THIRD__-NEXT: (i32.add
;; THIRD__-NEXT: (local.get $0)
;; THIRD__-NEXT: (i32.const 1)
;; THIRD__-NEXT: )
;; THIRD__-NEXT: )
;; THIRD__-NEXT: )
;; THIRD__-NEXT: (i32.store
;; THIRD__-NEXT: (i32.const 20)
;; THIRD__-NEXT: (i32.div_s
;; THIRD__-NEXT: (local.get $1)
;; THIRD__-NEXT: (i32.add
;; THIRD__-NEXT: (local.get $1)
;; THIRD__-NEXT: (i32.const 1)
;; THIRD__-NEXT: )
;; THIRD__-NEXT: )
;; THIRD__-NEXT: )
;; THIRD__-NEXT: (i32.store
;; THIRD__-NEXT: (i32.const 30)
;; THIRD__-NEXT: (i32.const 0)
;; THIRD__-NEXT: )
;; THIRD__-NEXT: (i32.store
;; THIRD__-NEXT: (i32.const 40)
;; THIRD__-NEXT: (i32.const 0)
;; THIRD__-NEXT: )
;; THIRD__-NEXT: (i32.store
;; THIRD__-NEXT: (i32.const 50)
;; THIRD__-NEXT: (i32.const 0)
;; THIRD__-NEXT: )
;; THIRD__-NEXT: )
;; TWOTRDS: (func $target_2 (type $2)
;; TWOTRDS-NEXT: (i32.store
;; TWOTRDS-NEXT: (i32.const 10)
;; TWOTRDS-NEXT: (i32.const 0)
;; TWOTRDS-NEXT: )
;; TWOTRDS-NEXT: (i32.store
;; TWOTRDS-NEXT: (i32.const 20)
;; TWOTRDS-NEXT: (i32.const 0)
;; TWOTRDS-NEXT: )
;; TWOTRDS-NEXT: (i32.store
;; TWOTRDS-NEXT: (i32.const 30)
;; TWOTRDS-NEXT: (i32.const 0)
;; TWOTRDS-NEXT: )
;; TWOTRDS-NEXT: (i32.store
;; TWOTRDS-NEXT: (i32.const 40)
;; TWOTRDS-NEXT: (i32.const 0)
;; TWOTRDS-NEXT: )
;; TWOTRDS-NEXT: (i32.store
;; TWOTRDS-NEXT: (i32.const 50)
;; TWOTRDS-NEXT: (i32.const 0)
;; TWOTRDS-NEXT: )
;; TWOTRDS-NEXT: )
(module
;; DEFAULT: (type $A (sub (struct (field i32))))
;; ZERO___: (type $A (sub (struct (field i32))))
;; THIRD__: (type $A (sub (struct (field i32))))
;; TWOTRDS: (type $A (sub (struct (field i32))))
;; HUNDRED: (type $A (sub (struct (field i32))))
(type $A (sub (struct (field i32))))
;; DEFAULT: (type $1 (func))
;; DEFAULT: (type $2 (func (param anyref) (result (ref $A))))
;; DEFAULT: (type $3 (func (param anyref i32)))
;; DEFAULT: (type $4 (func (param (ref $A))))
;; DEFAULT: (type $5 (func (param anyref)))
;; DEFAULT: (type $6 (func (param i32)))
;; DEFAULT: (import "a" "b" (func $import (type $1)))
;; ZERO___: (type $1 (func))
;; ZERO___: (type $2 (func (param anyref) (result (ref $A))))
;; ZERO___: (type $3 (func (param anyref i32)))
;; ZERO___: (type $4 (func (param anyref)))
;; ZERO___: (type $5 (func (param i32) (result (ref $A))))
;; ZERO___: (type $6 (func (param i32)))
;; ZERO___: (type $7 (func (result (ref $A))))
;; ZERO___: (type $8 (func (param (ref $A))))
;; ZERO___: (import "a" "b" (func $import (type $1)))
;; THIRD__: (type $1 (func))
;; THIRD__: (type $2 (func (param anyref) (result (ref $A))))
;; THIRD__: (type $3 (func (param anyref i32)))
;; THIRD__: (type $4 (func (param i32)))
;; THIRD__: (type $5 (func (param (ref $A))))
;; THIRD__: (type $6 (func (param anyref)))
;; THIRD__: (import "a" "b" (func $import (type $1)))
;; TWOTRDS: (type $1 (func))
;; TWOTRDS: (type $2 (func (param anyref) (result (ref $A))))
;; TWOTRDS: (type $3 (func (param anyref i32)))
;; TWOTRDS: (type $4 (func (param i32)))
;; TWOTRDS: (type $5 (func (param (ref $A))))
;; TWOTRDS: (type $6 (func (param anyref)))
;; TWOTRDS: (import "a" "b" (func $import (type $1)))
;; HUNDRED: (type $1 (func (param anyref) (result (ref $A))))
;; HUNDRED: (type $2 (func (param anyref i32)))
;; HUNDRED: (type $3 (func))
;; HUNDRED: (type $4 (func (param (ref $A))))
;; HUNDRED: (import "a" "b" (func $import (type $3)))
(import "a" "b" (func $import))
;; DEFAULT: (import "a" "c" (func $import2 (type $4) (param (ref $A))))
;; ZERO___: (import "a" "c" (func $import2 (type $8) (param (ref $A))))
;; THIRD__: (import "a" "c" (func $import2 (type $5) (param (ref $A))))
;; TWOTRDS: (import "a" "c" (func $import2 (type $5) (param (ref $A))))
;; HUNDRED: (import "a" "c" (func $import2 (type $4) (param (ref $A))))
(import "a" "c" (func $import2 (param (ref $A))))
;; DEFAULT: (func $target-long (type $2) (param $0 anyref) (result (ref $A))
;; DEFAULT-NEXT: (local $1 i32)
;; DEFAULT-NEXT: (local.set $1
;; DEFAULT-NEXT: (i32.const 1000)
;; DEFAULT-NEXT: )
;; DEFAULT-NEXT: (loop $loop
;; DEFAULT-NEXT: (br_if $loop
;; DEFAULT-NEXT: (local.tee $1
;; DEFAULT-NEXT: (i32.add
;; DEFAULT-NEXT: (local.get $1)
;; DEFAULT-NEXT: (local.get $1)
;; DEFAULT-NEXT: )
;; DEFAULT-NEXT: )
;; DEFAULT-NEXT: )
;; DEFAULT-NEXT: )
;; DEFAULT-NEXT: (ref.cast (ref $A)
;; DEFAULT-NEXT: (local.get $0)
;; DEFAULT-NEXT: )
;; DEFAULT-NEXT: )
;; ZERO___: (func $target-long (type $2) (param $0 anyref) (result (ref $A))
;; ZERO___-NEXT: (local $1 i32)
;; ZERO___-NEXT: (local.set $1
;; ZERO___-NEXT: (i32.const 1000)
;; ZERO___-NEXT: )
;; ZERO___-NEXT: (loop $loop
;; ZERO___-NEXT: (br_if $loop
;; ZERO___-NEXT: (local.tee $1
;; ZERO___-NEXT: (i32.add
;; ZERO___-NEXT: (local.get $1)
;; ZERO___-NEXT: (local.get $1)
;; ZERO___-NEXT: )
;; ZERO___-NEXT: )
;; ZERO___-NEXT: )
;; ZERO___-NEXT: )
;; ZERO___-NEXT: (ref.cast (ref $A)
;; ZERO___-NEXT: (local.get $0)
;; ZERO___-NEXT: )
;; ZERO___-NEXT: )
;; THIRD__: (func $target-long (type $2) (param $0 anyref) (result (ref $A))
;; THIRD__-NEXT: (local $1 i32)
;; THIRD__-NEXT: (local.set $1
;; THIRD__-NEXT: (i32.const 1000)
;; THIRD__-NEXT: )
;; THIRD__-NEXT: (loop $loop
;; THIRD__-NEXT: (br_if $loop
;; THIRD__-NEXT: (local.tee $1
;; THIRD__-NEXT: (i32.add
;; THIRD__-NEXT: (local.get $1)
;; THIRD__-NEXT: (local.get $1)
;; THIRD__-NEXT: )
;; THIRD__-NEXT: )
;; THIRD__-NEXT: )
;; THIRD__-NEXT: )
;; THIRD__-NEXT: (ref.cast (ref $A)
;; THIRD__-NEXT: (local.get $0)
;; THIRD__-NEXT: )
;; THIRD__-NEXT: )
;; TWOTRDS: (func $target-long (type $2) (param $0 anyref) (result (ref $A))
;; TWOTRDS-NEXT: (local $1 i32)
;; TWOTRDS-NEXT: (local.set $1
;; TWOTRDS-NEXT: (i32.const 1000)
;; TWOTRDS-NEXT: )
;; TWOTRDS-NEXT: (loop $loop
;; TWOTRDS-NEXT: (br_if $loop
;; TWOTRDS-NEXT: (local.tee $1
;; TWOTRDS-NEXT: (i32.add
;; TWOTRDS-NEXT: (local.get $1)
;; TWOTRDS-NEXT: (local.get $1)
;; TWOTRDS-NEXT: )
;; TWOTRDS-NEXT: )
;; TWOTRDS-NEXT: )
;; TWOTRDS-NEXT: )
;; TWOTRDS-NEXT: (ref.cast (ref $A)
;; TWOTRDS-NEXT: (local.get $0)
;; TWOTRDS-NEXT: )
;; TWOTRDS-NEXT: )
;; HUNDRED: (func $target-long (type $1) (param $0 anyref) (result (ref $A))
;; HUNDRED-NEXT: (local $1 i32)
;; HUNDRED-NEXT: (local.set $1
;; HUNDRED-NEXT: (i32.const 1000)
;; HUNDRED-NEXT: )
;; HUNDRED-NEXT: (loop $loop
;; HUNDRED-NEXT: (br_if $loop
;; HUNDRED-NEXT: (local.tee $1
;; HUNDRED-NEXT: (i32.add
;; HUNDRED-NEXT: (local.get $1)
;; HUNDRED-NEXT: (local.get $1)
;; HUNDRED-NEXT: )
;; HUNDRED-NEXT: )
;; HUNDRED-NEXT: )
;; HUNDRED-NEXT: )
;; HUNDRED-NEXT: (ref.cast (ref $A)
;; HUNDRED-NEXT: (local.get $0)
;; HUNDRED-NEXT: )
;; HUNDRED-NEXT: )
(func $target-long (param $any anyref) (result (ref $A))
(local $temp i32)
;; This function does a cast, aside from a lot of other work. The other work
;; causes us to only optimize when we are ok with getting a very small % of
;; improvement.
;; A silly loop that might in theory end after a long time.
(local.set $temp (i32.const 1000))
(loop $loop
(local.set $temp (i32.add (local.get $temp) (local.get $temp)))
(br_if $loop (local.get $temp))
)
(ref.cast (ref $A)
(local.get $any)
)
)
;; DEFAULT: (func $target-short (type $2) (param $0 anyref) (result (ref $A))
;; DEFAULT-NEXT: (ref.cast (ref $A)
;; DEFAULT-NEXT: (local.get $0)
;; DEFAULT-NEXT: )
;; DEFAULT-NEXT: )
;; ZERO___: (func $target-short (type $2) (param $0 anyref) (result (ref $A))
;; ZERO___-NEXT: (ref.cast (ref $A)
;; ZERO___-NEXT: (local.get $0)
;; ZERO___-NEXT: )
;; ZERO___-NEXT: )
;; THIRD__: (func $target-short (type $2) (param $0 anyref) (result (ref $A))
;; THIRD__-NEXT: (ref.cast (ref $A)
;; THIRD__-NEXT: (local.get $0)
;; THIRD__-NEXT: )
;; THIRD__-NEXT: )
;; TWOTRDS: (func $target-short (type $2) (param $0 anyref) (result (ref $A))
;; TWOTRDS-NEXT: (ref.cast (ref $A)
;; TWOTRDS-NEXT: (local.get $0)
;; TWOTRDS-NEXT: )
;; TWOTRDS-NEXT: )
;; HUNDRED: (func $target-short (type $1) (param $0 anyref) (result (ref $A))
;; HUNDRED-NEXT: (ref.cast (ref $A)
;; HUNDRED-NEXT: (local.get $0)
;; HUNDRED-NEXT: )
;; HUNDRED-NEXT: )
(func $target-short (param $any anyref) (result (ref $A))
;; As above, but without all the work in the middle: this is really just a
;; simple casting function, and we can remove almost all the work here when
;; we remove the cast, meaning we optimize in more cases.
(ref.cast (ref $A)
(local.get $any)
)
)
;; DEFAULT: (func $calls-long (type $3) (param $x anyref) (param $y i32)
;; DEFAULT-NEXT: (call $import2
;; DEFAULT-NEXT: (call $target-long
;; DEFAULT-NEXT: (local.get $x)
;; DEFAULT-NEXT: )
;; DEFAULT-NEXT: )
;; DEFAULT-NEXT: (drop
;; DEFAULT-NEXT: (call $target-long
;; DEFAULT-NEXT: (local.get $x)
;; DEFAULT-NEXT: )
;; DEFAULT-NEXT: )
;; DEFAULT-NEXT: (call $import2
;; DEFAULT-NEXT: (call $target-long
;; DEFAULT-NEXT: (struct.new $A
;; DEFAULT-NEXT: (local.get $y)
;; DEFAULT-NEXT: )
;; DEFAULT-NEXT: )
;; DEFAULT-NEXT: )
;; DEFAULT-NEXT: (drop
;; DEFAULT-NEXT: (call $target-long
;; DEFAULT-NEXT: (struct.new $A
;; DEFAULT-NEXT: (local.get $y)
;; DEFAULT-NEXT: )
;; DEFAULT-NEXT: )
;; DEFAULT-NEXT: )
;; DEFAULT-NEXT: (call $import2
;; DEFAULT-NEXT: (call $target-long
;; DEFAULT-NEXT: (struct.new $A
;; DEFAULT-NEXT: (i32.const 42)
;; DEFAULT-NEXT: )
;; DEFAULT-NEXT: )
;; DEFAULT-NEXT: )
;; DEFAULT-NEXT: (drop
;; DEFAULT-NEXT: (call $target-long
;; DEFAULT-NEXT: (struct.new $A
;; DEFAULT-NEXT: (i32.const 42)
;; DEFAULT-NEXT: )
;; DEFAULT-NEXT: )
;; DEFAULT-NEXT: )
;; DEFAULT-NEXT: )
;; ZERO___: (func $calls-long (type $3) (param $x anyref) (param $y i32)
;; ZERO___-NEXT: (call $import2
;; ZERO___-NEXT: (call $target-long
;; ZERO___-NEXT: (local.get $x)
;; ZERO___-NEXT: )
;; ZERO___-NEXT: )
;; ZERO___-NEXT: (call $target-long_6
;; ZERO___-NEXT: (local.get $x)
;; ZERO___-NEXT: )
;; ZERO___-NEXT: (call $import2
;; ZERO___-NEXT: (call $target-long_7
;; ZERO___-NEXT: (local.get $y)
;; ZERO___-NEXT: )
;; ZERO___-NEXT: )
;; ZERO___-NEXT: (call $target-long_8
;; ZERO___-NEXT: (local.get $y)
;; ZERO___-NEXT: )
;; ZERO___-NEXT: (call $import2
;; ZERO___-NEXT: (call $target-long_9)
;; ZERO___-NEXT: )
;; ZERO___-NEXT: (call $target-long_10)
;; ZERO___-NEXT: )
;; THIRD__: (func $calls-long (type $3) (param $x anyref) (param $y i32)
;; THIRD__-NEXT: (call $import2
;; THIRD__-NEXT: (call $target-long
;; THIRD__-NEXT: (local.get $x)
;; THIRD__-NEXT: )
;; THIRD__-NEXT: )
;; THIRD__-NEXT: (drop
;; THIRD__-NEXT: (call $target-long
;; THIRD__-NEXT: (local.get $x)
;; THIRD__-NEXT: )
;; THIRD__-NEXT: )
;; THIRD__-NEXT: (call $import2
;; THIRD__-NEXT: (call $target-long
;; THIRD__-NEXT: (struct.new $A
;; THIRD__-NEXT: (local.get $y)
;; THIRD__-NEXT: )
;; THIRD__-NEXT: )
;; THIRD__-NEXT: )
;; THIRD__-NEXT: (call $target-long_6
;; THIRD__-NEXT: (local.get $y)
;; THIRD__-NEXT: )
;; THIRD__-NEXT: (call $import2
;; THIRD__-NEXT: (call $target-long
;; THIRD__-NEXT: (struct.new $A
;; THIRD__-NEXT: (i32.const 42)
;; THIRD__-NEXT: )
;; THIRD__-NEXT: )
;; THIRD__-NEXT: )
;; THIRD__-NEXT: (call $target-long_7)
;; THIRD__-NEXT: )
;; TWOTRDS: (func $calls-long (type $3) (param $x anyref) (param $y i32)
;; TWOTRDS-NEXT: (call $import2
;; TWOTRDS-NEXT: (call $target-long
;; TWOTRDS-NEXT: (local.get $x)
;; TWOTRDS-NEXT: )
;; TWOTRDS-NEXT: )
;; TWOTRDS-NEXT: (drop
;; TWOTRDS-NEXT: (call $target-long
;; TWOTRDS-NEXT: (local.get $x)
;; TWOTRDS-NEXT: )
;; TWOTRDS-NEXT: )
;; TWOTRDS-NEXT: (call $import2
;; TWOTRDS-NEXT: (call $target-long
;; TWOTRDS-NEXT: (struct.new $A
;; TWOTRDS-NEXT: (local.get $y)
;; TWOTRDS-NEXT: )
;; TWOTRDS-NEXT: )
;; TWOTRDS-NEXT: )
;; TWOTRDS-NEXT: (call $target-long_6
;; TWOTRDS-NEXT: (local.get $y)
;; TWOTRDS-NEXT: )
;; TWOTRDS-NEXT: (call $import2
;; TWOTRDS-NEXT: (call $target-long
;; TWOTRDS-NEXT: (struct.new $A
;; TWOTRDS-NEXT: (i32.const 42)
;; TWOTRDS-NEXT: )
;; TWOTRDS-NEXT: )
;; TWOTRDS-NEXT: )
;; TWOTRDS-NEXT: (call $target-long_7)
;; TWOTRDS-NEXT: )
;; HUNDRED: (func $calls-long (type $2) (param $x anyref) (param $y i32)
;; HUNDRED-NEXT: (call $import2
;; HUNDRED-NEXT: (call $target-long
;; HUNDRED-NEXT: (local.get $x)
;; HUNDRED-NEXT: )
;; HUNDRED-NEXT: )
;; HUNDRED-NEXT: (drop
;; HUNDRED-NEXT: (call $target-long
;; HUNDRED-NEXT: (local.get $x)
;; HUNDRED-NEXT: )
;; HUNDRED-NEXT: )
;; HUNDRED-NEXT: (call $import2
;; HUNDRED-NEXT: (call $target-long
;; HUNDRED-NEXT: (struct.new $A
;; HUNDRED-NEXT: (local.get $y)
;; HUNDRED-NEXT: )
;; HUNDRED-NEXT: )
;; HUNDRED-NEXT: )
;; HUNDRED-NEXT: (drop
;; HUNDRED-NEXT: (call $target-long
;; HUNDRED-NEXT: (struct.new $A
;; HUNDRED-NEXT: (local.get $y)
;; HUNDRED-NEXT: )
;; HUNDRED-NEXT: )
;; HUNDRED-NEXT: )
;; HUNDRED-NEXT: (call $import2
;; HUNDRED-NEXT: (call $target-long
;; HUNDRED-NEXT: (struct.new $A
;; HUNDRED-NEXT: (i32.const 42)
;; HUNDRED-NEXT: )
;; HUNDRED-NEXT: )
;; HUNDRED-NEXT: )
;; HUNDRED-NEXT: (drop
;; HUNDRED-NEXT: (call $target-long
;; HUNDRED-NEXT: (struct.new $A
;; HUNDRED-NEXT: (i32.const 42)
;; HUNDRED-NEXT: )
;; HUNDRED-NEXT: )
;; HUNDRED-NEXT: )
;; HUNDRED-NEXT: )
(func $calls-long (param $x anyref) (param $y i32)
;; Various calls to $target-long. Because of the large amount of work that
;; cannot be removed there, all we do here is:
;; * Optimize in all cases when the minimum benefit is 0% (except the
;; first call, which is a trivial call context). Removing a cast is
;; enough to justify optimizing.
;; * In 33% and 66% we optimize only two cases. There we remove both a cast
;; and a struct.new, and the struct.new's high cost makes it worthwhile.
;; * In 100% we optimize nothing at all.
;; Call with an unknown input and the output is sent to an import.
(call $import2
(call $target-long
(local.get $x)
)
)
;; Ditto, but drop the output.
(drop
(call $target-long
(local.get $x)
)
)
;; Calls with a struct.new input.
(call $import2
(call $target-long
(struct.new $A
(local.get $y)
)
)
)
(drop
(call $target-long
(struct.new $A
(local.get $y)
)
)
)
;; Now the struct.new has a constant input.
(call $import2
(call $target-long
(struct.new $A
(i32.const 42)
)
)
)
(drop
(call $target-long
(struct.new $A
(i32.const 42)
)
)
)
)
;; DEFAULT: (func $calls-short (type $3) (param $x anyref) (param $y i32)
;; DEFAULT-NEXT: (call $import2
;; DEFAULT-NEXT: (call $target-short
;; DEFAULT-NEXT: (local.get $x)
;; DEFAULT-NEXT: )
;; DEFAULT-NEXT: )
;; DEFAULT-NEXT: (call $target-short_6
;; DEFAULT-NEXT: (local.get $x)
;; DEFAULT-NEXT: )
;; DEFAULT-NEXT: (call $import2
;; DEFAULT-NEXT: (call $target-short
;; DEFAULT-NEXT: (struct.new $A
;; DEFAULT-NEXT: (local.get $y)
;; DEFAULT-NEXT: )
;; DEFAULT-NEXT: )
;; DEFAULT-NEXT: )
;; DEFAULT-NEXT: (call $target-short_7
;; DEFAULT-NEXT: (local.get $y)
;; DEFAULT-NEXT: )
;; DEFAULT-NEXT: (call $import2
;; DEFAULT-NEXT: (call $target-short
;; DEFAULT-NEXT: (struct.new $A
;; DEFAULT-NEXT: (i32.const 42)
;; DEFAULT-NEXT: )
;; DEFAULT-NEXT: )
;; DEFAULT-NEXT: )
;; DEFAULT-NEXT: (call $target-short_8)
;; DEFAULT-NEXT: )
;; ZERO___: (func $calls-short (type $3) (param $x anyref) (param $y i32)
;; ZERO___-NEXT: (call $import2
;; ZERO___-NEXT: (call $target-short
;; ZERO___-NEXT: (local.get $x)
;; ZERO___-NEXT: )
;; ZERO___-NEXT: )
;; ZERO___-NEXT: (call $target-short_11
;; ZERO___-NEXT: (local.get $x)
;; ZERO___-NEXT: )
;; ZERO___-NEXT: (call $import2
;; ZERO___-NEXT: (call $target-short_12
;; ZERO___-NEXT: (local.get $y)
;; ZERO___-NEXT: )
;; ZERO___-NEXT: )
;; ZERO___-NEXT: (call $target-short_13
;; ZERO___-NEXT: (local.get $y)
;; ZERO___-NEXT: )
;; ZERO___-NEXT: (call $import2
;; ZERO___-NEXT: (call $target-short_14)
;; ZERO___-NEXT: )
;; ZERO___-NEXT: (call $target-short_15)
;; ZERO___-NEXT: )
;; THIRD__: (func $calls-short (type $3) (param $x anyref) (param $y i32)
;; THIRD__-NEXT: (call $import2
;; THIRD__-NEXT: (call $target-short
;; THIRD__-NEXT: (local.get $x)
;; THIRD__-NEXT: )
;; THIRD__-NEXT: )
;; THIRD__-NEXT: (call $target-short_8
;; THIRD__-NEXT: (local.get $x)
;; THIRD__-NEXT: )
;; THIRD__-NEXT: (call $import2
;; THIRD__-NEXT: (call $target-short
;; THIRD__-NEXT: (struct.new $A
;; THIRD__-NEXT: (local.get $y)
;; THIRD__-NEXT: )
;; THIRD__-NEXT: )
;; THIRD__-NEXT: )
;; THIRD__-NEXT: (call $target-short_9
;; THIRD__-NEXT: (local.get $y)
;; THIRD__-NEXT: )
;; THIRD__-NEXT: (call $import2
;; THIRD__-NEXT: (call $target-short
;; THIRD__-NEXT: (struct.new $A
;; THIRD__-NEXT: (i32.const 42)
;; THIRD__-NEXT: )
;; THIRD__-NEXT: )
;; THIRD__-NEXT: )
;; THIRD__-NEXT: (call $target-short_10)
;; THIRD__-NEXT: )
;; TWOTRDS: (func $calls-short (type $3) (param $x anyref) (param $y i32)
;; TWOTRDS-NEXT: (call $import2
;; TWOTRDS-NEXT: (call $target-short
;; TWOTRDS-NEXT: (local.get $x)
;; TWOTRDS-NEXT: )
;; TWOTRDS-NEXT: )
;; TWOTRDS-NEXT: (call $target-short_8
;; TWOTRDS-NEXT: (local.get $x)
;; TWOTRDS-NEXT: )
;; TWOTRDS-NEXT: (call $import2
;; TWOTRDS-NEXT: (call $target-short
;; TWOTRDS-NEXT: (struct.new $A
;; TWOTRDS-NEXT: (local.get $y)
;; TWOTRDS-NEXT: )
;; TWOTRDS-NEXT: )
;; TWOTRDS-NEXT: )
;; TWOTRDS-NEXT: (call $target-short_9
;; TWOTRDS-NEXT: (local.get $y)
;; TWOTRDS-NEXT: )
;; TWOTRDS-NEXT: (call $import2
;; TWOTRDS-NEXT: (call $target-short
;; TWOTRDS-NEXT: (struct.new $A
;; TWOTRDS-NEXT: (i32.const 42)
;; TWOTRDS-NEXT: )
;; TWOTRDS-NEXT: )
;; TWOTRDS-NEXT: )
;; TWOTRDS-NEXT: (call $target-short_10)
;; TWOTRDS-NEXT: )
;; HUNDRED: (func $calls-short (type $2) (param $x anyref) (param $y i32)
;; HUNDRED-NEXT: (call $import2
;; HUNDRED-NEXT: (call $target-short
;; HUNDRED-NEXT: (local.get $x)
;; HUNDRED-NEXT: )
;; HUNDRED-NEXT: )
;; HUNDRED-NEXT: (drop
;; HUNDRED-NEXT: (call $target-short
;; HUNDRED-NEXT: (local.get $x)
;; HUNDRED-NEXT: )
;; HUNDRED-NEXT: )
;; HUNDRED-NEXT: (call $import2
;; HUNDRED-NEXT: (call $target-short
;; HUNDRED-NEXT: (struct.new $A
;; HUNDRED-NEXT: (local.get $y)
;; HUNDRED-NEXT: )
;; HUNDRED-NEXT: )
;; HUNDRED-NEXT: )
;; HUNDRED-NEXT: (drop
;; HUNDRED-NEXT: (call $target-short
;; HUNDRED-NEXT: (struct.new $A
;; HUNDRED-NEXT: (local.get $y)
;; HUNDRED-NEXT: )
;; HUNDRED-NEXT: )
;; HUNDRED-NEXT: )
;; HUNDRED-NEXT: (call $import2
;; HUNDRED-NEXT: (call $target-short
;; HUNDRED-NEXT: (struct.new $A
;; HUNDRED-NEXT: (i32.const 42)
;; HUNDRED-NEXT: )
;; HUNDRED-NEXT: )
;; HUNDRED-NEXT: )
;; HUNDRED-NEXT: (drop
;; HUNDRED-NEXT: (call $target-short
;; HUNDRED-NEXT: (struct.new $A
;; HUNDRED-NEXT: (i32.const 42)
;; HUNDRED-NEXT: )
;; HUNDRED-NEXT: )
;; HUNDRED-NEXT: )
;; HUNDRED-NEXT: )
(func $calls-short (param $x anyref) (param $y i32)
;; As above, but now calling the short function:
;; * 0% is the same with the long function: any improvement is enough.
;; * 33% optimizes some, but not all (the first is a trivial call context;
;; some of the others do not optimize because the struct.new is
;; expensive, and if the output goes into another call, we cannot remove
;; it).
;; * 66% optimizes a few less cases: when the output isn't dropped then we
;; can't do enough work to justify it.
;; * 100% optimizes nothing.
(call $import2
(call $target-short
(local.get $x)
)
)
(drop
(call $target-short
(local.get $x)
)
)
(call $import2
(call $target-short
(struct.new $A
(local.get $y)
)
)
)
(drop
(call $target-short
(struct.new $A
(local.get $y)
)
)
)
(call $import2
(call $target-short
(struct.new $A
(i32.const 42)
)
)
)
(drop
(call $target-short
(struct.new $A
(i32.const 42)
)
)
)
)
)
;; DEFAULT: (func $target-short_6 (type $5) (param $0 anyref)
;; DEFAULT-NEXT: (nop)
;; DEFAULT-NEXT: )
;; DEFAULT: (func $target-short_7 (type $6) (param $0 i32)
;; DEFAULT-NEXT: (nop)
;; DEFAULT-NEXT: )
;; DEFAULT: (func $target-short_8 (type $1)
;; DEFAULT-NEXT: (nop)
;; DEFAULT-NEXT: )
;; ZERO___: (func $target-long_6 (type $4) (param $0 anyref)
;; ZERO___-NEXT: (local $1 i32)
;; ZERO___-NEXT: (local.set $1
;; ZERO___-NEXT: (i32.const 1000)
;; ZERO___-NEXT: )
;; ZERO___-NEXT: (loop $loop
;; ZERO___-NEXT: (br_if $loop
;; ZERO___-NEXT: (local.tee $1
;; ZERO___-NEXT: (i32.add
;; ZERO___-NEXT: (local.get $1)
;; ZERO___-NEXT: (local.get $1)
;; ZERO___-NEXT: )
;; ZERO___-NEXT: )
;; ZERO___-NEXT: )
;; ZERO___-NEXT: )
;; ZERO___-NEXT: )
;; ZERO___: (func $target-long_7 (type $5) (param $0 i32) (result (ref $A))
;; ZERO___-NEXT: (local $1 (ref (exact $A)))
;; ZERO___-NEXT: (local.set $1
;; ZERO___-NEXT: (struct.new $A
;; ZERO___-NEXT: (local.get $0)
;; ZERO___-NEXT: )
;; ZERO___-NEXT: )
;; ZERO___-NEXT: (local.set $0
;; ZERO___-NEXT: (i32.const 1000)
;; ZERO___-NEXT: )
;; ZERO___-NEXT: (loop $loop
;; ZERO___-NEXT: (br_if $loop
;; ZERO___-NEXT: (local.tee $0
;; ZERO___-NEXT: (i32.add
;; ZERO___-NEXT: (local.get $0)
;; ZERO___-NEXT: (local.get $0)
;; ZERO___-NEXT: )
;; ZERO___-NEXT: )
;; ZERO___-NEXT: )
;; ZERO___-NEXT: )
;; ZERO___-NEXT: (local.get $1)
;; ZERO___-NEXT: )
;; ZERO___: (func $target-long_8 (type $6) (param $0 i32)
;; ZERO___-NEXT: (local.set $0
;; ZERO___-NEXT: (i32.const 1000)
;; ZERO___-NEXT: )
;; ZERO___-NEXT: (loop $loop
;; ZERO___-NEXT: (br_if $loop
;; ZERO___-NEXT: (local.tee $0
;; ZERO___-NEXT: (i32.add
;; ZERO___-NEXT: (local.get $0)
;; ZERO___-NEXT: (local.get $0)
;; ZERO___-NEXT: )
;; ZERO___-NEXT: )
;; ZERO___-NEXT: )
;; ZERO___-NEXT: )
;; ZERO___-NEXT: )
;; ZERO___: (func $target-long_9 (type $7) (result (ref $A))
;; ZERO___-NEXT: (local $0 i32)
;; ZERO___-NEXT: (local $1 (ref (exact $A)))
;; ZERO___-NEXT: (local.set $0
;; ZERO___-NEXT: (i32.const 1000)
;; ZERO___-NEXT: )
;; ZERO___-NEXT: (loop $loop
;; ZERO___-NEXT: (br_if $loop
;; ZERO___-NEXT: (local.tee $0
;; ZERO___-NEXT: (i32.add
;; ZERO___-NEXT: (local.get $0)
;; ZERO___-NEXT: (local.get $0)
;; ZERO___-NEXT: )
;; ZERO___-NEXT: )
;; ZERO___-NEXT: )
;; ZERO___-NEXT: )
;; ZERO___-NEXT: (local.set $1
;; ZERO___-NEXT: (struct.new $A
;; ZERO___-NEXT: (i32.const 42)
;; ZERO___-NEXT: )
;; ZERO___-NEXT: )
;; ZERO___-NEXT: (local.get $1)
;; ZERO___-NEXT: )
;; ZERO___: (func $target-long_10 (type $1)
;; ZERO___-NEXT: (local $0 i32)
;; ZERO___-NEXT: (local.set $0
;; ZERO___-NEXT: (i32.const 1000)
;; ZERO___-NEXT: )
;; ZERO___-NEXT: (loop $loop
;; ZERO___-NEXT: (br_if $loop
;; ZERO___-NEXT: (local.tee $0
;; ZERO___-NEXT: (i32.add
;; ZERO___-NEXT: (local.get $0)
;; ZERO___-NEXT: (local.get $0)
;; ZERO___-NEXT: )
;; ZERO___-NEXT: )
;; ZERO___-NEXT: )
;; ZERO___-NEXT: )
;; ZERO___-NEXT: )
;; ZERO___: (func $target-short_11 (type $4) (param $0 anyref)
;; ZERO___-NEXT: (nop)
;; ZERO___-NEXT: )
;; ZERO___: (func $target-short_12 (type $5) (param $0 i32) (result (ref $A))
;; ZERO___-NEXT: (struct.new $A
;; ZERO___-NEXT: (local.get $0)
;; ZERO___-NEXT: )
;; ZERO___-NEXT: )
;; ZERO___: (func $target-short_13 (type $6) (param $0 i32)
;; ZERO___-NEXT: (nop)
;; ZERO___-NEXT: )
;; ZERO___: (func $target-short_14 (type $7) (result (ref $A))
;; ZERO___-NEXT: (struct.new $A
;; ZERO___-NEXT: (i32.const 42)
;; ZERO___-NEXT: )
;; ZERO___-NEXT: )
;; ZERO___: (func $target-short_15 (type $1)
;; ZERO___-NEXT: (nop)
;; ZERO___-NEXT: )
;; THIRD__: (func $target-long_6 (type $4) (param $0 i32)
;; THIRD__-NEXT: (local.set $0
;; THIRD__-NEXT: (i32.const 1000)
;; THIRD__-NEXT: )
;; THIRD__-NEXT: (loop $loop
;; THIRD__-NEXT: (br_if $loop
;; THIRD__-NEXT: (local.tee $0
;; THIRD__-NEXT: (i32.add
;; THIRD__-NEXT: (local.get $0)
;; THIRD__-NEXT: (local.get $0)
;; THIRD__-NEXT: )
;; THIRD__-NEXT: )
;; THIRD__-NEXT: )
;; THIRD__-NEXT: )
;; THIRD__-NEXT: )
;; THIRD__: (func $target-long_7 (type $1)
;; THIRD__-NEXT: (local $0 i32)
;; THIRD__-NEXT: (local.set $0
;; THIRD__-NEXT: (i32.const 1000)
;; THIRD__-NEXT: )
;; THIRD__-NEXT: (loop $loop
;; THIRD__-NEXT: (br_if $loop
;; THIRD__-NEXT: (local.tee $0
;; THIRD__-NEXT: (i32.add
;; THIRD__-NEXT: (local.get $0)
;; THIRD__-NEXT: (local.get $0)
;; THIRD__-NEXT: )
;; THIRD__-NEXT: )
;; THIRD__-NEXT: )
;; THIRD__-NEXT: )
;; THIRD__-NEXT: )
;; THIRD__: (func $target-short_8 (type $6) (param $0 anyref)
;; THIRD__-NEXT: (nop)
;; THIRD__-NEXT: )
;; THIRD__: (func $target-short_9 (type $4) (param $0 i32)
;; THIRD__-NEXT: (nop)
;; THIRD__-NEXT: )
;; THIRD__: (func $target-short_10 (type $1)
;; THIRD__-NEXT: (nop)
;; THIRD__-NEXT: )
;; TWOTRDS: (func $target-long_6 (type $4) (param $0 i32)
;; TWOTRDS-NEXT: (local.set $0
;; TWOTRDS-NEXT: (i32.const 1000)
;; TWOTRDS-NEXT: )
;; TWOTRDS-NEXT: (loop $loop
;; TWOTRDS-NEXT: (br_if $loop
;; TWOTRDS-NEXT: (local.tee $0
;; TWOTRDS-NEXT: (i32.add
;; TWOTRDS-NEXT: (local.get $0)
;; TWOTRDS-NEXT: (local.get $0)
;; TWOTRDS-NEXT: )
;; TWOTRDS-NEXT: )
;; TWOTRDS-NEXT: )
;; TWOTRDS-NEXT: )
;; TWOTRDS-NEXT: )
;; TWOTRDS: (func $target-long_7 (type $1)
;; TWOTRDS-NEXT: (local $0 i32)
;; TWOTRDS-NEXT: (local.set $0
;; TWOTRDS-NEXT: (i32.const 1000)
;; TWOTRDS-NEXT: )
;; TWOTRDS-NEXT: (loop $loop
;; TWOTRDS-NEXT: (br_if $loop
;; TWOTRDS-NEXT: (local.tee $0
;; TWOTRDS-NEXT: (i32.add
;; TWOTRDS-NEXT: (local.get $0)
;; TWOTRDS-NEXT: (local.get $0)
;; TWOTRDS-NEXT: )
;; TWOTRDS-NEXT: )
;; TWOTRDS-NEXT: )
;; TWOTRDS-NEXT: )
;; TWOTRDS-NEXT: )
;; TWOTRDS: (func $target-short_8 (type $6) (param $0 anyref)
;; TWOTRDS-NEXT: (nop)
;; TWOTRDS-NEXT: )
;; TWOTRDS: (func $target-short_9 (type $4) (param $0 i32)
;; TWOTRDS-NEXT: (nop)
;; TWOTRDS-NEXT: )
;; TWOTRDS: (func $target-short_10 (type $1)
;; TWOTRDS-NEXT: (nop)
;; TWOTRDS-NEXT: )