blob: 8b9c30daf9a126379ffe2f39648f0559637cf58b [file] [log] [blame] [edit]
;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited.
;; RUN: foreach %s %t wasm-opt --inlining --optimize-level=3 --partial-inlining-ifs=4 --all-features -S -o - | filecheck %s
(module
;; CHECK: (type $none_=>_none (func))
;; CHECK: (type $i32_=>_none (func (param i32)))
;; CHECK: (type $anyref_=>_anyref (func (param anyref) (result anyref)))
;; CHECK: (type $anyref_=>_none (func (param anyref)))
;; CHECK: (type $struct (struct ))
(type $struct (struct))
;; CHECK: (type $i64_i32_f64_=>_none (func (param i64 i32 f64)))
;; CHECK: (import "out" "func" (func $import (type $none_=>_none)))
(import "out" "func" (func $import))
;; CHECK: (global $glob i32 (i32.const 1))
(global $glob i32 (i32.const 1))
;; CHECK: (start $start-used-globally)
(start $start-used-globally)
;; Pattern A: functions beginning with
;;
;; if (simple) return;
(func $maybe-work-hard (param $x i32)
;; A function that does a quick check before any heavy work. We can outline
;; the heavy work, so that the condition can be inlined.
;;
;; This function (and others lower down that we also optimize) will vanish
;; in the output. Part of it will be inlined into its caller, below, and
;; the rest will be outlined into a new function with suffix "outlined".
(if
(local.get $x)
(return)
)
(loop $l
(call $import)
(br $l)
)
)
;; CHECK: (func $call-maybe-work-hard (type $none_=>_none)
;; CHECK-NEXT: (local $0 i32)
;; CHECK-NEXT: (local $1 i32)
;; CHECK-NEXT: (local $2 i32)
;; CHECK-NEXT: (block
;; CHECK-NEXT: (block $__inlined_func$byn-split-inlineable-A$maybe-work-hard
;; CHECK-NEXT: (local.set $0
;; CHECK-NEXT: (i32.const 1)
;; CHECK-NEXT: )
;; CHECK-NEXT: (if
;; CHECK-NEXT: (i32.eqz
;; CHECK-NEXT: (local.get $0)
;; CHECK-NEXT: )
;; CHECK-NEXT: (call $byn-split-outlined-A$maybe-work-hard
;; CHECK-NEXT: (local.get $0)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (block
;; CHECK-NEXT: (block $__inlined_func$byn-split-inlineable-A$maybe-work-hard$1
;; CHECK-NEXT: (local.set $1
;; CHECK-NEXT: (i32.const 2)
;; CHECK-NEXT: )
;; CHECK-NEXT: (if
;; CHECK-NEXT: (i32.eqz
;; CHECK-NEXT: (local.get $1)
;; CHECK-NEXT: )
;; CHECK-NEXT: (call $byn-split-outlined-A$maybe-work-hard
;; CHECK-NEXT: (local.get $1)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (block
;; CHECK-NEXT: (block $__inlined_func$byn-split-inlineable-A$maybe-work-hard$2
;; CHECK-NEXT: (local.set $2
;; CHECK-NEXT: (i32.const 3)
;; CHECK-NEXT: )
;; CHECK-NEXT: (if
;; CHECK-NEXT: (i32.eqz
;; CHECK-NEXT: (local.get $2)
;; CHECK-NEXT: )
;; CHECK-NEXT: (call $byn-split-outlined-A$maybe-work-hard
;; CHECK-NEXT: (local.get $2)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $call-maybe-work-hard
;; Call the above function to verify that we can in fact inline it after
;; splitting. We should see each of these three calls replaced by inlined
;; code performing the if from $maybe-work-hard, and depending on that
;; result they each call the outlined code that must *not* be inlined.
;;
;; Note that we must call more than once, otherwise given a single use we
;; will always inline the entire thing.
(call $maybe-work-hard (i32.const 1))
(call $maybe-work-hard (i32.const 2))
(call $maybe-work-hard (i32.const 3))
)
(func $just-if (param $x i32)
;; As above, but all we have is an if.
(if
(local.get $x)
(loop $l
(call $import)
(br_if $l
(local.get $x)
)
)
)
)
;; CHECK: (func $call-just-if (type $none_=>_none)
;; CHECK-NEXT: (local $0 i32)
;; CHECK-NEXT: (local $1 i32)
;; CHECK-NEXT: (block
;; CHECK-NEXT: (block $__inlined_func$byn-split-inlineable-B$just-if$3
;; CHECK-NEXT: (local.set $0
;; CHECK-NEXT: (i32.const 1)
;; CHECK-NEXT: )
;; CHECK-NEXT: (if
;; CHECK-NEXT: (local.get $0)
;; CHECK-NEXT: (call $byn-split-outlined-B$just-if
;; CHECK-NEXT: (local.get $0)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (block
;; CHECK-NEXT: (block $__inlined_func$byn-split-inlineable-B$just-if$4
;; CHECK-NEXT: (local.set $1
;; CHECK-NEXT: (i32.const 2)
;; CHECK-NEXT: )
;; CHECK-NEXT: (if
;; CHECK-NEXT: (local.get $1)
;; CHECK-NEXT: (call $byn-split-outlined-B$just-if
;; CHECK-NEXT: (local.get $1)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $call-just-if
(call $just-if (i32.const 1))
(call $just-if (i32.const 2))
)
;; CHECK: (func $br-to-toplevel (type $i32_=>_none) (param $x i32)
;; CHECK-NEXT: (block $toplevel
;; CHECK-NEXT: (if
;; CHECK-NEXT: (local.get $x)
;; CHECK-NEXT: (if
;; CHECK-NEXT: (local.get $x)
;; CHECK-NEXT: (br $toplevel)
;; CHECK-NEXT: (call $import)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $br-to-toplevel (param $x i32)
(block $toplevel
(if
(local.get $x)
(block
(if
(local.get $x)
;; A br to the toplevel block prevents us from outlining this code,
;; as we can't outline a br without its target.
(br $toplevel)
(call $import)
)
)
)
)
)
;; CHECK: (func $call-br-to-toplevel (type $none_=>_none)
;; CHECK-NEXT: (call $br-to-toplevel
;; CHECK-NEXT: (i32.const 1)
;; CHECK-NEXT: )
;; CHECK-NEXT: (call $br-to-toplevel
;; CHECK-NEXT: (i32.const 2)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $call-br-to-toplevel
(call $br-to-toplevel (i32.const 1))
(call $br-to-toplevel (i32.const 2))
)
(func $nondefaultable-param (param $x i32) (param $y (ref $struct))
;; We can inline despite the non-initial, non-defaultable param.
(if
(local.get $x)
(return)
)
(loop $l
(call $import)
(br $l)
)
)
;; CHECK: (func $call-nondefaultable-param (type $none_=>_none)
;; CHECK-NEXT: (local $0 i32)
;; CHECK-NEXT: (local $1 (ref $struct))
;; CHECK-NEXT: (block $__inlined_func$nondefaultable-param$5
;; CHECK-NEXT: (local.set $0
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: (local.set $1
;; CHECK-NEXT: (struct.new_default $struct)
;; CHECK-NEXT: )
;; CHECK-NEXT: (block
;; CHECK-NEXT: (if
;; CHECK-NEXT: (local.get $0)
;; CHECK-NEXT: (br $__inlined_func$nondefaultable-param$5)
;; CHECK-NEXT: )
;; CHECK-NEXT: (loop $l
;; CHECK-NEXT: (call $import)
;; CHECK-NEXT: (br $l)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $call-nondefaultable-param
(call $nondefaultable-param (i32.const 0) (struct.new $struct))
)
(func $many-params (param $x i64) (param $y i32) (param $z f64)
;; Test that we can optimize this function even though it has multiple
;; parameters, and it is not the very first one that we use in the
;; condition.
(if
(local.get $y)
(return)
)
(loop $l
(call $import)
(br $l)
)
)
;; CHECK: (func $call-many-params (type $none_=>_none)
;; CHECK-NEXT: (local $0 i64)
;; CHECK-NEXT: (local $1 i32)
;; CHECK-NEXT: (local $2 f64)
;; CHECK-NEXT: (local $3 i64)
;; CHECK-NEXT: (local $4 i32)
;; CHECK-NEXT: (local $5 f64)
;; CHECK-NEXT: (block
;; CHECK-NEXT: (block $__inlined_func$byn-split-inlineable-A$many-params$6
;; CHECK-NEXT: (local.set $0
;; CHECK-NEXT: (i64.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: (local.set $1
;; CHECK-NEXT: (i32.const 1)
;; CHECK-NEXT: )
;; CHECK-NEXT: (local.set $2
;; CHECK-NEXT: (f64.const 3.14159)
;; CHECK-NEXT: )
;; CHECK-NEXT: (if
;; CHECK-NEXT: (i32.eqz
;; CHECK-NEXT: (local.get $1)
;; CHECK-NEXT: )
;; CHECK-NEXT: (call $byn-split-outlined-A$many-params
;; CHECK-NEXT: (local.get $0)
;; CHECK-NEXT: (local.get $1)
;; CHECK-NEXT: (local.get $2)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (block
;; CHECK-NEXT: (block $__inlined_func$byn-split-inlineable-A$many-params$7
;; CHECK-NEXT: (local.set $3
;; CHECK-NEXT: (i64.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: (local.set $4
;; CHECK-NEXT: (i32.const 1)
;; CHECK-NEXT: )
;; CHECK-NEXT: (local.set $5
;; CHECK-NEXT: (f64.const 3.14159)
;; CHECK-NEXT: )
;; CHECK-NEXT: (if
;; CHECK-NEXT: (i32.eqz
;; CHECK-NEXT: (local.get $4)
;; CHECK-NEXT: )
;; CHECK-NEXT: (call $byn-split-outlined-A$many-params
;; CHECK-NEXT: (local.get $3)
;; CHECK-NEXT: (local.get $4)
;; CHECK-NEXT: (local.get $5)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $call-many-params
;; Call the above function to verify that we can in fact inline it after
;; splitting. We should see each of these three calls replaced by inlined
;; code performing the if from $maybe-work-hard, and depending on that
;; result they each call the outlined code that must *not* be inlined.
(call $many-params (i64.const 0) (i32.const 1) (f64.const 3.14159))
(call $many-params (i64.const 0) (i32.const 1) (f64.const 3.14159))
)
(func $condition-eqz (param $x i32)
(if
;; More work in the condition, but work that we still consider worth
;; optimizing: a unary op.
(i32.eqz
(local.get $x)
)
(return)
)
(loop $l
(call $import)
(br $l)
)
)
;; CHECK: (func $call-condition-eqz (type $none_=>_none)
;; CHECK-NEXT: (local $0 i32)
;; CHECK-NEXT: (local $1 i32)
;; CHECK-NEXT: (block
;; CHECK-NEXT: (block $__inlined_func$byn-split-inlineable-A$condition-eqz$8
;; CHECK-NEXT: (local.set $0
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: (if
;; CHECK-NEXT: (i32.eqz
;; CHECK-NEXT: (i32.eqz
;; CHECK-NEXT: (local.get $0)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (call $byn-split-outlined-A$condition-eqz
;; CHECK-NEXT: (local.get $0)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (block
;; CHECK-NEXT: (block $__inlined_func$byn-split-inlineable-A$condition-eqz$9
;; CHECK-NEXT: (local.set $1
;; CHECK-NEXT: (i32.const 1)
;; CHECK-NEXT: )
;; CHECK-NEXT: (if
;; CHECK-NEXT: (i32.eqz
;; CHECK-NEXT: (i32.eqz
;; CHECK-NEXT: (local.get $1)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (call $byn-split-outlined-A$condition-eqz
;; CHECK-NEXT: (local.get $1)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $call-condition-eqz
(call $condition-eqz (i32.const 0))
(call $condition-eqz (i32.const 1))
)
(func $condition-global
(if
;; A global read, also worth splitting.
(global.get $glob)
(return)
)
(loop $l
(call $import)
(br $l)
)
)
;; CHECK: (func $call-condition-global (type $none_=>_none)
;; CHECK-NEXT: (block
;; CHECK-NEXT: (block $__inlined_func$byn-split-inlineable-A$condition-global$10
;; CHECK-NEXT: (if
;; CHECK-NEXT: (i32.eqz
;; CHECK-NEXT: (global.get $glob)
;; CHECK-NEXT: )
;; CHECK-NEXT: (call $byn-split-outlined-A$condition-global)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (block
;; CHECK-NEXT: (block $__inlined_func$byn-split-inlineable-A$condition-global$11
;; CHECK-NEXT: (if
;; CHECK-NEXT: (i32.eqz
;; CHECK-NEXT: (global.get $glob)
;; CHECK-NEXT: )
;; CHECK-NEXT: (call $byn-split-outlined-A$condition-global)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $call-condition-global
(call $condition-global)
(call $condition-global)
)
(func $condition-ref.is (param $x anyref)
(if
;; A ref.is operation.
(ref.is_null
(local.get $x)
)
(return)
)
(loop $l
(call $import)
(br $l)
)
)
;; CHECK: (func $call-condition-ref.is (type $none_=>_none)
;; CHECK-NEXT: (local $0 anyref)
;; CHECK-NEXT: (local $1 anyref)
;; CHECK-NEXT: (block
;; CHECK-NEXT: (block $__inlined_func$byn-split-inlineable-A$condition-ref.is$12
;; CHECK-NEXT: (local.set $0
;; CHECK-NEXT: (ref.null none)
;; CHECK-NEXT: )
;; CHECK-NEXT: (if
;; CHECK-NEXT: (i32.eqz
;; CHECK-NEXT: (ref.is_null
;; CHECK-NEXT: (local.get $0)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (call $byn-split-outlined-A$condition-ref.is
;; CHECK-NEXT: (local.get $0)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (block
;; CHECK-NEXT: (block $__inlined_func$byn-split-inlineable-A$condition-ref.is$13
;; CHECK-NEXT: (local.set $1
;; CHECK-NEXT: (ref.null none)
;; CHECK-NEXT: )
;; CHECK-NEXT: (if
;; CHECK-NEXT: (i32.eqz
;; CHECK-NEXT: (ref.is_null
;; CHECK-NEXT: (local.get $1)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (call $byn-split-outlined-A$condition-ref.is
;; CHECK-NEXT: (local.get $1)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $call-condition-ref.is
(call $condition-ref.is (ref.null any))
(call $condition-ref.is (ref.null any))
)
;; CHECK: (func $condition-disallow-binary (type $i32_=>_none) (param $x i32)
;; CHECK-NEXT: (if
;; CHECK-NEXT: (i32.add
;; CHECK-NEXT: (local.get $x)
;; CHECK-NEXT: (local.get $x)
;; CHECK-NEXT: )
;; CHECK-NEXT: (return)
;; CHECK-NEXT: )
;; CHECK-NEXT: (loop $l
;; CHECK-NEXT: (call $import)
;; CHECK-NEXT: (br $l)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $condition-disallow-binary (param $x i32)
(if
;; Work we do *not* allow (at least for now), a binary.
(i32.add
(local.get $x)
(local.get $x)
)
(return)
)
(loop $l
(call $import)
(br $l)
)
)
;; CHECK: (func $call-condition-disallow-binary (type $none_=>_none)
;; CHECK-NEXT: (call $condition-disallow-binary
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: (call $condition-disallow-binary
;; CHECK-NEXT: (i32.const 1)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $call-condition-disallow-binary
(call $condition-disallow-binary (i32.const 0))
(call $condition-disallow-binary (i32.const 1))
)
;; CHECK: (func $condition-disallow-unreachable (type $i32_=>_none) (param $x i32)
;; CHECK-NEXT: (if
;; CHECK-NEXT: (i32.eqz
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
;; CHECK-NEXT: (return)
;; CHECK-NEXT: )
;; CHECK-NEXT: (loop $l
;; CHECK-NEXT: (call $import)
;; CHECK-NEXT: (br $l)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $condition-disallow-unreachable (param $x i32)
(if
;; Work we do *not* allow (at least for now), an unreachable.
(i32.eqz
(unreachable)
)
(return)
)
(loop $l
(call $import)
(br $l)
)
)
;; CHECK: (func $call-condition-disallow-unreachable (type $none_=>_none)
;; CHECK-NEXT: (call $condition-disallow-unreachable
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: (call $condition-disallow-unreachable
;; CHECK-NEXT: (i32.const 1)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $call-condition-disallow-unreachable
(call $condition-disallow-unreachable (i32.const 0))
(call $condition-disallow-unreachable (i32.const 1))
)
;; CHECK: (func $start-used-globally (type $none_=>_none)
;; CHECK-NEXT: (if
;; CHECK-NEXT: (global.get $glob)
;; CHECK-NEXT: (return)
;; CHECK-NEXT: )
;; CHECK-NEXT: (loop $l
;; CHECK-NEXT: (call $import)
;; CHECK-NEXT: (br $l)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $start-used-globally
;; This is optimizable even though it is the start function, that is is,
;; having global uses of a function are not a problem for partial inlining
;; (since we do not modify this function - we create new split pieces of
;; it).
(if
(global.get $glob)
(return)
)
(loop $l
(call $import)
(br $l)
)
)
;; CHECK: (func $call-start-used-globally (type $none_=>_none)
;; CHECK-NEXT: (block
;; CHECK-NEXT: (block $__inlined_func$byn-split-inlineable-A$start-used-globally$14
;; CHECK-NEXT: (if
;; CHECK-NEXT: (i32.eqz
;; CHECK-NEXT: (global.get $glob)
;; CHECK-NEXT: )
;; CHECK-NEXT: (call $byn-split-outlined-A$start-used-globally)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (block
;; CHECK-NEXT: (block $__inlined_func$byn-split-inlineable-A$start-used-globally$15
;; CHECK-NEXT: (if
;; CHECK-NEXT: (i32.eqz
;; CHECK-NEXT: (global.get $glob)
;; CHECK-NEXT: )
;; CHECK-NEXT: (call $byn-split-outlined-A$start-used-globally)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $call-start-used-globally
(call $start-used-globally)
(call $start-used-globally)
)
(func $inlineable
;; This looks optimizable, but it is also inlineable - so we do not need to
;; split it. It will just be inlined directly, without any $outlined part
;; that is split out.
(if
(global.get $glob)
(return)
)
)
;; CHECK: (func $call-inlineable (type $none_=>_none)
;; CHECK-NEXT: (block
;; CHECK-NEXT: (block $__inlined_func$inlineable$16
;; CHECK-NEXT: (if
;; CHECK-NEXT: (global.get $glob)
;; CHECK-NEXT: (br $__inlined_func$inlineable$16)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (block
;; CHECK-NEXT: (block $__inlined_func$inlineable$17
;; CHECK-NEXT: (if
;; CHECK-NEXT: (global.get $glob)
;; CHECK-NEXT: (br $__inlined_func$inlineable$17)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $call-inlineable
(call $inlineable)
(call $inlineable)
)
;; CHECK: (func $if-not-first (type $i32_=>_none) (param $x i32)
;; CHECK-NEXT: (nop)
;; CHECK-NEXT: (if
;; CHECK-NEXT: (local.get $x)
;; CHECK-NEXT: (return)
;; CHECK-NEXT: )
;; CHECK-NEXT: (loop $l
;; CHECK-NEXT: (call $import)
;; CHECK-NEXT: (br $l)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $if-not-first (param $x i32)
;; Except for the initial nop, we should outline this. As the if is not
;; first any more, we ignore it.
(nop)
(if
(local.get $x)
(return)
)
(loop $l
(call $import)
(br $l)
)
)
;; CHECK: (func $call-if-not-first (type $none_=>_none)
;; CHECK-NEXT: (call $if-not-first
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: (call $if-not-first
;; CHECK-NEXT: (i32.const 1)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $call-if-not-first
(call $if-not-first (i32.const 0))
(call $if-not-first (i32.const 1))
)
;; CHECK: (func $if-else (type $i32_=>_none) (param $x i32)
;; CHECK-NEXT: (if
;; CHECK-NEXT: (local.get $x)
;; CHECK-NEXT: (return)
;; CHECK-NEXT: (nop)
;; CHECK-NEXT: )
;; CHECK-NEXT: (loop $l
;; CHECK-NEXT: (call $import)
;; CHECK-NEXT: (br $l)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $if-else (param $x i32)
;; An else in the if prevents us from recognizing the pattern we want.
(if
(local.get $x)
(return)
(nop)
)
(loop $l
(call $import)
(br $l)
)
)
;; CHECK: (func $call-if-else (type $none_=>_none)
;; CHECK-NEXT: (call $if-else
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: (call $if-else
;; CHECK-NEXT: (i32.const 1)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $call-if-else
(call $if-else (i32.const 0))
(call $if-else (i32.const 1))
)
;; CHECK: (func $if-non-return (type $i32_=>_none) (param $x i32)
;; CHECK-NEXT: (if
;; CHECK-NEXT: (local.get $x)
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
;; CHECK-NEXT: (loop $l
;; CHECK-NEXT: (call $import)
;; CHECK-NEXT: (br $l)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $if-non-return (param $x i32)
;; Something other than a return in the if body prevents us from outlining.
(if
(local.get $x)
(unreachable)
)
(loop $l
(call $import)
(br $l)
)
)
;; CHECK: (func $call-if-non-return (type $none_=>_none)
;; CHECK-NEXT: (call $if-non-return
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: (call $if-non-return
;; CHECK-NEXT: (i32.const 1)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $call-if-non-return
(call $if-non-return (i32.const 0))
(call $if-non-return (i32.const 1))
)
(func $colliding-name (param $x i32)
;; When we outline this, the name should not collide with that of the
;; function after us.
(if
(local.get $x)
(return)
)
(loop $l
(call $import)
(br $l)
)
)
;; CHECK: (func $call-colliding-name (type $none_=>_none)
;; CHECK-NEXT: (local $0 i32)
;; CHECK-NEXT: (local $1 i32)
;; CHECK-NEXT: (block
;; CHECK-NEXT: (block $__inlined_func$byn-split-inlineable-A$colliding-name$18
;; CHECK-NEXT: (local.set $0
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: (if
;; CHECK-NEXT: (i32.eqz
;; CHECK-NEXT: (local.get $0)
;; CHECK-NEXT: )
;; CHECK-NEXT: (call $byn-split-outlined-A$colliding-name_67
;; CHECK-NEXT: (local.get $0)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (block
;; CHECK-NEXT: (block $__inlined_func$byn-split-inlineable-A$colliding-name$19
;; CHECK-NEXT: (local.set $1
;; CHECK-NEXT: (i32.const 1)
;; CHECK-NEXT: )
;; CHECK-NEXT: (if
;; CHECK-NEXT: (i32.eqz
;; CHECK-NEXT: (local.get $1)
;; CHECK-NEXT: )
;; CHECK-NEXT: (call $byn-split-outlined-A$colliding-name_67
;; CHECK-NEXT: (local.get $1)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $call-colliding-name
(call $colliding-name (i32.const 0))
(call $colliding-name (i32.const 1))
)
;; CHECK: (func $byn-split-outlined-A$colliding-name (type $none_=>_none)
;; CHECK-NEXT: (nop)
;; CHECK-NEXT: )
(func $byn-split-outlined-A$colliding-name
;; This function's name might collide with the split function we create for
;; the above function; the split function's name must be fixed up.
)
;; Pattern B: functions containing
;;
;; if (simple1) heavy-work-that-is-unreachable;
;; if (simple..) heavy-work-that-is-unreachable;
;; simplek
(func $error-if-null (param $x anyref) (result anyref)
;; A "as non null" function: If the input is null, issue an error somehow
;; (here, by calling an import, but could also be a throwing of an
;; exception). If not null, return the value.
(if
(ref.is_null
(local.get $x)
)
(block
(call $import)
(unreachable)
)
)
(local.get $x)
)
;; CHECK: (func $call-error-if-null (type $none_=>_none)
;; CHECK-NEXT: (local $0 anyref)
;; CHECK-NEXT: (local $1 anyref)
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (block (result anyref)
;; CHECK-NEXT: (block $__inlined_func$byn-split-inlineable-B$error-if-null$20 (result anyref)
;; CHECK-NEXT: (local.set $0
;; CHECK-NEXT: (ref.null none)
;; CHECK-NEXT: )
;; CHECK-NEXT: (block (result anyref)
;; CHECK-NEXT: (if
;; CHECK-NEXT: (ref.is_null
;; CHECK-NEXT: (local.get $0)
;; CHECK-NEXT: )
;; CHECK-NEXT: (br $__inlined_func$byn-split-inlineable-B$error-if-null$20
;; CHECK-NEXT: (call $byn-split-outlined-B$error-if-null
;; CHECK-NEXT: (local.get $0)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (local.get $0)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (block (result anyref)
;; CHECK-NEXT: (block $__inlined_func$byn-split-inlineable-B$error-if-null$21 (result anyref)
;; CHECK-NEXT: (local.set $1
;; CHECK-NEXT: (ref.null none)
;; CHECK-NEXT: )
;; CHECK-NEXT: (block (result anyref)
;; CHECK-NEXT: (if
;; CHECK-NEXT: (ref.is_null
;; CHECK-NEXT: (local.get $1)
;; CHECK-NEXT: )
;; CHECK-NEXT: (br $__inlined_func$byn-split-inlineable-B$error-if-null$21
;; CHECK-NEXT: (call $byn-split-outlined-B$error-if-null
;; CHECK-NEXT: (local.get $1)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (local.get $1)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $call-error-if-null
(drop (call $error-if-null (ref.null any)))
(drop (call $error-if-null (ref.null any)))
)
;; CHECK: (func $too-many (type $anyref_=>_anyref) (param $x anyref) (result anyref)
;; CHECK-NEXT: (if
;; CHECK-NEXT: (ref.is_null
;; CHECK-NEXT: (local.get $x)
;; CHECK-NEXT: )
;; CHECK-NEXT: (block
;; CHECK-NEXT: (call $import)
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (nop)
;; CHECK-NEXT: (local.get $x)
;; CHECK-NEXT: )
(func $too-many (param $x anyref) (result anyref)
(if
(ref.is_null
(local.get $x)
)
(block
(call $import)
(unreachable)
)
)
(nop) ;; An extra operation here prevents us from identifying the pattern.
(local.get $x)
)
;; CHECK: (func $call-too-many (type $none_=>_none)
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (call $too-many
;; CHECK-NEXT: (ref.null none)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (call $too-many
;; CHECK-NEXT: (ref.null none)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $call-too-many
(drop (call $too-many (ref.null any)))
(drop (call $too-many (ref.null any)))
)
;; CHECK: (func $tail-not-simple (type $anyref_=>_anyref) (param $x anyref) (result anyref)
;; CHECK-NEXT: (if
;; CHECK-NEXT: (ref.is_null
;; CHECK-NEXT: (local.get $x)
;; CHECK-NEXT: )
;; CHECK-NEXT: (block
;; CHECK-NEXT: (call $import)
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
(func $tail-not-simple (param $x anyref) (result anyref)
(if
(ref.is_null
(local.get $x)
)
(block
(call $import)
(unreachable)
)
)
(unreachable) ;; This prevents us from optimizing
)
;; CHECK: (func $call-tail-not-simple (type $none_=>_none)
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (call $tail-not-simple
;; CHECK-NEXT: (ref.null none)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (call $tail-not-simple
;; CHECK-NEXT: (ref.null none)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $call-tail-not-simple
(drop (call $tail-not-simple (ref.null any)))
(drop (call $tail-not-simple (ref.null any)))
)
(func $reachable-if-body (param $x anyref) (result anyref)
(if
(ref.is_null
(local.get $x)
)
;; It is ok if the body is not unreachable (so long as it contains no
;; returns). We will optimize this, and just do a call to the outlined
;; code, without a return of a value here.
(block
;; We need to have a loop here to avoid normal inlining from kicking in
;; on the outlined code.
(loop $loop
(call $import)
)
)
)
(local.get $x)
)
;; CHECK: (func $call-reachable-if-body (type $none_=>_none)
;; CHECK-NEXT: (local $0 anyref)
;; CHECK-NEXT: (local $1 anyref)
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (block (result anyref)
;; CHECK-NEXT: (block $__inlined_func$byn-split-inlineable-B$reachable-if-body$22 (result anyref)
;; CHECK-NEXT: (local.set $0
;; CHECK-NEXT: (ref.null none)
;; CHECK-NEXT: )
;; CHECK-NEXT: (block (result anyref)
;; CHECK-NEXT: (if
;; CHECK-NEXT: (ref.is_null
;; CHECK-NEXT: (local.get $0)
;; CHECK-NEXT: )
;; CHECK-NEXT: (call $byn-split-outlined-B$reachable-if-body
;; CHECK-NEXT: (local.get $0)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (local.get $0)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (block (result anyref)
;; CHECK-NEXT: (block $__inlined_func$byn-split-inlineable-B$reachable-if-body$23 (result anyref)
;; CHECK-NEXT: (local.set $1
;; CHECK-NEXT: (ref.null none)
;; CHECK-NEXT: )
;; CHECK-NEXT: (block (result anyref)
;; CHECK-NEXT: (if
;; CHECK-NEXT: (ref.is_null
;; CHECK-NEXT: (local.get $1)
;; CHECK-NEXT: )
;; CHECK-NEXT: (call $byn-split-outlined-B$reachable-if-body
;; CHECK-NEXT: (local.get $1)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (local.get $1)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $call-reachable-if-body
(drop (call $reachable-if-body (ref.null any)))
(drop (call $reachable-if-body (ref.null any)))
)
(func $reachable-if-body-noloop (param $x anyref) (result anyref)
;; As above, but without a loop.
(if
(ref.is_null
(local.get $x)
)
(call $import)
)
(local.get $x)
)
;; CHECK: (func $call-reachable-if-body-noloop (type $none_=>_none)
;; CHECK-NEXT: (local $0 anyref)
;; CHECK-NEXT: (local $1 anyref)
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (block (result anyref)
;; CHECK-NEXT: (block $__inlined_func$reachable-if-body-noloop$24 (result anyref)
;; CHECK-NEXT: (local.set $0
;; CHECK-NEXT: (ref.null none)
;; CHECK-NEXT: )
;; CHECK-NEXT: (block (result anyref)
;; CHECK-NEXT: (if
;; CHECK-NEXT: (ref.is_null
;; CHECK-NEXT: (local.get $0)
;; CHECK-NEXT: )
;; CHECK-NEXT: (call $import)
;; CHECK-NEXT: )
;; CHECK-NEXT: (local.get $0)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (block (result anyref)
;; CHECK-NEXT: (block $__inlined_func$reachable-if-body-noloop$25 (result anyref)
;; CHECK-NEXT: (local.set $1
;; CHECK-NEXT: (ref.null none)
;; CHECK-NEXT: )
;; CHECK-NEXT: (block (result anyref)
;; CHECK-NEXT: (if
;; CHECK-NEXT: (ref.is_null
;; CHECK-NEXT: (local.get $1)
;; CHECK-NEXT: )
;; CHECK-NEXT: (call $import)
;; CHECK-NEXT: )
;; CHECK-NEXT: (local.get $1)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $call-reachable-if-body-noloop
;; As above, but the called function has no loop. In that case, even though
;; it fits the pattern for partial inlining we can just inline the entire
;; thing normally.
(drop (call $reachable-if-body-noloop (ref.null any)))
(drop (call $reachable-if-body-noloop (ref.null any)))
)
;; CHECK: (func $reachable-if-body-return (type $anyref_=>_anyref) (param $x anyref) (result anyref)
;; CHECK-NEXT: (if
;; CHECK-NEXT: (ref.is_null
;; CHECK-NEXT: (local.get $x)
;; CHECK-NEXT: )
;; CHECK-NEXT: (if
;; CHECK-NEXT: (i32.const 1)
;; CHECK-NEXT: (return
;; CHECK-NEXT: (local.get $x)
;; CHECK-NEXT: )
;; CHECK-NEXT: (call $import)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (local.get $x)
;; CHECK-NEXT: )
(func $reachable-if-body-return (param $x anyref) (result anyref)
(if
(ref.is_null
(local.get $x)
)
(if
(i32.const 1)
;; The return here prevents the optimization.
(return
(local.get $x)
)
(call $import)
)
)
(local.get $x)
)
;; CHECK: (func $call-reachable-if-body-return (type $none_=>_none)
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (call $reachable-if-body-return
;; CHECK-NEXT: (ref.null none)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (call $reachable-if-body-return
;; CHECK-NEXT: (ref.null none)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $call-reachable-if-body-return
(drop (call $reachable-if-body-return (ref.null any)))
(drop (call $reachable-if-body-return (ref.null any)))
)
(func $unreachable-if-body-no-result (param $x anyref)
(if
(ref.is_null
(local.get $x)
)
;; The if body is unreachable, but the function has no returned value.
;; When we outline this code, we should not try to return a value.
(block
(call $import)
(unreachable)
)
)
)
;; CHECK: (func $call-unreachable-if-body-no-result (type $none_=>_none)
;; CHECK-NEXT: (local $0 anyref)
;; CHECK-NEXT: (local $1 anyref)
;; CHECK-NEXT: (block
;; CHECK-NEXT: (block $__inlined_func$byn-split-inlineable-B$unreachable-if-body-no-result$26
;; CHECK-NEXT: (local.set $0
;; CHECK-NEXT: (ref.null none)
;; CHECK-NEXT: )
;; CHECK-NEXT: (if
;; CHECK-NEXT: (ref.is_null
;; CHECK-NEXT: (local.get $0)
;; CHECK-NEXT: )
;; CHECK-NEXT: (call $byn-split-outlined-B$unreachable-if-body-no-result
;; CHECK-NEXT: (local.get $0)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (block
;; CHECK-NEXT: (block $__inlined_func$byn-split-inlineable-B$unreachable-if-body-no-result$27
;; CHECK-NEXT: (local.set $1
;; CHECK-NEXT: (ref.null none)
;; CHECK-NEXT: )
;; CHECK-NEXT: (if
;; CHECK-NEXT: (ref.is_null
;; CHECK-NEXT: (local.get $1)
;; CHECK-NEXT: )
;; CHECK-NEXT: (call $byn-split-outlined-B$unreachable-if-body-no-result
;; CHECK-NEXT: (local.get $1)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $call-unreachable-if-body-no-result
(call $unreachable-if-body-no-result (ref.null any))
(call $unreachable-if-body-no-result (ref.null any))
)
(func $multi-if (param $x anyref) (result anyref)
(if
(ref.is_null
(local.get $x)
)
(call $import)
)
;; A second if. We can outline both if bodies.
(if
(ref.is_null
(local.get $x)
)
(loop $x
(call $import)
(br_if $x
(global.get $glob)
)
)
)
(local.get $x)
)
;; CHECK: (func $call-multi-if (type $none_=>_none)
;; CHECK-NEXT: (local $0 anyref)
;; CHECK-NEXT: (local $1 anyref)
;; CHECK-NEXT: (local $2 anyref)
;; CHECK-NEXT: (local $3 anyref)
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (block (result anyref)
;; CHECK-NEXT: (block $__inlined_func$byn-split-inlineable-B$multi-if$28 (result anyref)
;; CHECK-NEXT: (local.set $0
;; CHECK-NEXT: (ref.null none)
;; CHECK-NEXT: )
;; CHECK-NEXT: (block (result anyref)
;; CHECK-NEXT: (if
;; CHECK-NEXT: (ref.is_null
;; CHECK-NEXT: (local.get $0)
;; CHECK-NEXT: )
;; CHECK-NEXT: (block $__inlined_func$byn-split-outlined-B$multi-if$30
;; CHECK-NEXT: (local.set $2
;; CHECK-NEXT: (local.get $0)
;; CHECK-NEXT: )
;; CHECK-NEXT: (call $import)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (if
;; CHECK-NEXT: (ref.is_null
;; CHECK-NEXT: (local.get $0)
;; CHECK-NEXT: )
;; CHECK-NEXT: (call $byn-split-outlined-B$multi-if_76
;; CHECK-NEXT: (local.get $0)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (local.get $0)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (block (result anyref)
;; CHECK-NEXT: (block $__inlined_func$byn-split-inlineable-B$multi-if$29 (result anyref)
;; CHECK-NEXT: (local.set $1
;; CHECK-NEXT: (ref.null none)
;; CHECK-NEXT: )
;; CHECK-NEXT: (block (result anyref)
;; CHECK-NEXT: (if
;; CHECK-NEXT: (ref.is_null
;; CHECK-NEXT: (local.get $1)
;; CHECK-NEXT: )
;; CHECK-NEXT: (block $__inlined_func$byn-split-outlined-B$multi-if$31
;; CHECK-NEXT: (local.set $3
;; CHECK-NEXT: (local.get $1)
;; CHECK-NEXT: )
;; CHECK-NEXT: (call $import)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (if
;; CHECK-NEXT: (ref.is_null
;; CHECK-NEXT: (local.get $1)
;; CHECK-NEXT: )
;; CHECK-NEXT: (call $byn-split-outlined-B$multi-if_76
;; CHECK-NEXT: (local.get $1)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (local.get $1)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $call-multi-if
(drop (call $multi-if (ref.null none)))
(drop (call $multi-if (ref.null none)))
)
;; CHECK: (func $too-many-ifs (type $anyref_=>_anyref) (param $x anyref) (result anyref)
;; CHECK-NEXT: (if
;; CHECK-NEXT: (ref.is_null
;; CHECK-NEXT: (local.get $x)
;; CHECK-NEXT: )
;; CHECK-NEXT: (call $import)
;; CHECK-NEXT: )
;; CHECK-NEXT: (if
;; CHECK-NEXT: (ref.is_null
;; CHECK-NEXT: (local.get $x)
;; CHECK-NEXT: )
;; CHECK-NEXT: (call $import)
;; CHECK-NEXT: )
;; CHECK-NEXT: (if
;; CHECK-NEXT: (ref.is_null
;; CHECK-NEXT: (local.get $x)
;; CHECK-NEXT: )
;; CHECK-NEXT: (call $import)
;; CHECK-NEXT: )
;; CHECK-NEXT: (if
;; CHECK-NEXT: (ref.is_null
;; CHECK-NEXT: (local.get $x)
;; CHECK-NEXT: )
;; CHECK-NEXT: (call $import)
;; CHECK-NEXT: )
;; CHECK-NEXT: (if
;; CHECK-NEXT: (ref.is_null
;; CHECK-NEXT: (local.get $x)
;; CHECK-NEXT: )
;; CHECK-NEXT: (call $import)
;; CHECK-NEXT: )
;; CHECK-NEXT: (local.get $x)
;; CHECK-NEXT: )
(func $too-many-ifs (param $x anyref) (result anyref)
;; 5 ifs, which is too many.
(if
(ref.is_null
(local.get $x)
)
(call $import)
)
(if
(ref.is_null
(local.get $x)
)
(call $import)
)
(if
(ref.is_null
(local.get $x)
)
(call $import)
)
(if
(ref.is_null
(local.get $x)
)
(call $import)
)
(if
(ref.is_null
(local.get $x)
)
(call $import)
)
(local.get $x)
)
;; CHECK: (func $call-too-many-ifs (type $none_=>_none)
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (call $too-many-ifs
;; CHECK-NEXT: (ref.null none)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (call $too-many-ifs
;; CHECK-NEXT: (ref.null none)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $call-too-many-ifs
(drop (call $too-many-ifs (ref.null none)))
(drop (call $too-many-ifs (ref.null none)))
)
)
;; CHECK: (func $byn-split-outlined-A$maybe-work-hard (type $i32_=>_none) (param $x i32)
;; CHECK-NEXT: (loop $l
;; CHECK-NEXT: (call $import)
;; CHECK-NEXT: (br $l)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK: (func $byn-split-outlined-B$just-if (type $i32_=>_none) (param $x i32)
;; CHECK-NEXT: (loop $l
;; CHECK-NEXT: (call $import)
;; CHECK-NEXT: (br_if $l
;; CHECK-NEXT: (local.get $x)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK: (func $byn-split-outlined-A$many-params (type $i64_i32_f64_=>_none) (param $x i64) (param $y i32) (param $z f64)
;; CHECK-NEXT: (loop $l
;; CHECK-NEXT: (call $import)
;; CHECK-NEXT: (br $l)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK: (func $byn-split-outlined-A$condition-eqz (type $i32_=>_none) (param $x i32)
;; CHECK-NEXT: (loop $l
;; CHECK-NEXT: (call $import)
;; CHECK-NEXT: (br $l)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK: (func $byn-split-outlined-A$condition-global (type $none_=>_none)
;; CHECK-NEXT: (loop $l
;; CHECK-NEXT: (call $import)
;; CHECK-NEXT: (br $l)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK: (func $byn-split-outlined-A$condition-ref.is (type $anyref_=>_none) (param $x anyref)
;; CHECK-NEXT: (loop $l
;; CHECK-NEXT: (call $import)
;; CHECK-NEXT: (br $l)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK: (func $byn-split-outlined-A$start-used-globally (type $none_=>_none)
;; CHECK-NEXT: (loop $l
;; CHECK-NEXT: (call $import)
;; CHECK-NEXT: (br $l)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK: (func $byn-split-outlined-A$colliding-name_67 (type $i32_=>_none) (param $x i32)
;; CHECK-NEXT: (loop $l
;; CHECK-NEXT: (call $import)
;; CHECK-NEXT: (br $l)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK: (func $byn-split-outlined-B$error-if-null (type $anyref_=>_anyref) (param $x anyref) (result anyref)
;; CHECK-NEXT: (call $import)
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
;; CHECK: (func $byn-split-outlined-B$reachable-if-body (type $anyref_=>_none) (param $x anyref)
;; CHECK-NEXT: (loop $loop
;; CHECK-NEXT: (call $import)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK: (func $byn-split-outlined-B$unreachable-if-body-no-result (type $anyref_=>_none) (param $x anyref)
;; CHECK-NEXT: (call $import)
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
;; CHECK: (func $byn-split-outlined-B$multi-if_76 (type $anyref_=>_none) (param $x anyref)
;; CHECK-NEXT: (loop $x
;; CHECK-NEXT: (call $import)
;; CHECK-NEXT: (br_if $x
;; CHECK-NEXT: (global.get $glob)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(module
;; CHECK: (type $none_=>_none (func))
(type $none_=>_none (func))
;; CHECK: (global $global$0 (mut i32) (i32.const 10))
(global $global$0 (mut i32) (i32.const 10))
;; CHECK: (export "0" (func $0))
(export "0" (func $0))
;; CHECK: (export "1" (func $1))
(export "1" (func $1))
;; CHECK: (func $0 (type $none_=>_none)
;; CHECK-NEXT: (if
;; CHECK-NEXT: (global.get $global$0)
;; CHECK-NEXT: (return)
;; CHECK-NEXT: )
;; CHECK-NEXT: (block
;; CHECK-NEXT: (block $__inlined_func$1
;; CHECK-NEXT: (block
;; CHECK-NEXT: (call $0)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (block
;; CHECK-NEXT: (block $__inlined_func$1$1
;; CHECK-NEXT: (block
;; CHECK-NEXT: (call $0)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $0
;; A function that is a good candidate to partially inline.
(if
(global.get $global$0)
(return)
)
(call $1)
(call $1)
)
;; CHECK: (func $1 (type $none_=>_none)
;; CHECK-NEXT: (block
;; CHECK-NEXT: (block $__inlined_func$byn-split-inlineable-A$0$2
;; CHECK-NEXT: (if
;; CHECK-NEXT: (i32.eqz
;; CHECK-NEXT: (global.get $global$0)
;; CHECK-NEXT: )
;; CHECK-NEXT: (block $__inlined_func$byn-split-outlined-A$0$3
;; CHECK-NEXT: (block
;; CHECK-NEXT: (block
;; CHECK-NEXT: (block $__inlined_func$1
;; CHECK-NEXT: (block
;; CHECK-NEXT: (block
;; CHECK-NEXT: (block
;; CHECK-NEXT: (block $__inlined_func$byn-split-inlineable-A$0$4
;; CHECK-NEXT: (if
;; CHECK-NEXT: (i32.eqz
;; CHECK-NEXT: (global.get $global$0)
;; CHECK-NEXT: )
;; CHECK-NEXT: (call $byn-split-outlined-A$0)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (block
;; CHECK-NEXT: (block $__inlined_func$1$1
;; CHECK-NEXT: (block
;; CHECK-NEXT: (block
;; CHECK-NEXT: (block
;; CHECK-NEXT: (block $__inlined_func$byn-split-inlineable-A$0$5
;; CHECK-NEXT: (if
;; CHECK-NEXT: (i32.eqz
;; CHECK-NEXT: (global.get $global$0)
;; CHECK-NEXT: )
;; CHECK-NEXT: (call $byn-split-outlined-A$0)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $1
;; This and the previous function are mutually recursive. As a result, we
;; can keep partially inlining between them, creating new functions as we
;; go, even though that is not very useful.
(call $0)
)
;; Add a lot more functions, so the # of functions is high which would
;; otherwise limit the # of iterations that we run.
;; CHECK: (func $2 (type $none_=>_none)
;; CHECK-NEXT: (nop)
;; CHECK-NEXT: )
(func $2
(nop)
)
;; CHECK: (func $3 (type $none_=>_none)
;; CHECK-NEXT: (nop)
;; CHECK-NEXT: )
(func $3
(nop)
)
;; CHECK: (func $4 (type $none_=>_none)
;; CHECK-NEXT: (nop)
;; CHECK-NEXT: )
(func $4
(nop)
)
;; CHECK: (func $5 (type $none_=>_none)
;; CHECK-NEXT: (nop)
;; CHECK-NEXT: )
(func $5
(nop)
)
;; CHECK: (func $6 (type $none_=>_none)
;; CHECK-NEXT: (nop)
;; CHECK-NEXT: )
(func $6
(nop)
)
;; CHECK: (func $7 (type $none_=>_none)
;; CHECK-NEXT: (nop)
;; CHECK-NEXT: )
(func $7
(nop)
)
;; CHECK: (func $8 (type $none_=>_none)
;; CHECK-NEXT: (nop)
;; CHECK-NEXT: )
(func $8
(nop)
)
;; CHECK: (func $9 (type $none_=>_none)
;; CHECK-NEXT: (nop)
;; CHECK-NEXT: )
(func $9
(nop)
)
;; CHECK: (func $10 (type $none_=>_none)
;; CHECK-NEXT: (nop)
;; CHECK-NEXT: )
(func $10
(nop)
)
;; CHECK: (func $11 (type $none_=>_none)
;; CHECK-NEXT: (nop)
;; CHECK-NEXT: )
(func $11
(nop)
)
;; CHECK: (func $12 (type $none_=>_none)
;; CHECK-NEXT: (nop)
;; CHECK-NEXT: )
(func $12
(nop)
)
;; CHECK: (func $13 (type $none_=>_none)
;; CHECK-NEXT: (nop)
;; CHECK-NEXT: )
(func $13
(nop)
)
;; CHECK: (func $14 (type $none_=>_none)
;; CHECK-NEXT: (nop)
;; CHECK-NEXT: )
(func $14
(nop)
)
;; CHECK: (func $15 (type $none_=>_none)
;; CHECK-NEXT: (nop)
;; CHECK-NEXT: )
(func $15
(nop)
)
;; CHECK: (func $16 (type $none_=>_none)
;; CHECK-NEXT: (nop)
;; CHECK-NEXT: )
(func $16
(nop)
)
;; CHECK: (func $17 (type $none_=>_none)
;; CHECK-NEXT: (nop)
;; CHECK-NEXT: )
(func $17
(nop)
)
;; CHECK: (func $18 (type $none_=>_none)
;; CHECK-NEXT: (nop)
;; CHECK-NEXT: )
(func $18
(nop)
)
)
;; CHECK: (func $byn-split-outlined-A$0 (type $none_=>_none)
;; CHECK-NEXT: (block
;; CHECK-NEXT: (block $__inlined_func$1
;; CHECK-NEXT: (block
;; CHECK-NEXT: (block
;; CHECK-NEXT: (block $__inlined_func$byn-split-inlineable-A$0$6
;; CHECK-NEXT: (if
;; CHECK-NEXT: (i32.eqz
;; CHECK-NEXT: (global.get $global$0)
;; CHECK-NEXT: )
;; CHECK-NEXT: (call $byn-split-outlined-A$0_21)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (block
;; CHECK-NEXT: (block $__inlined_func$1$1
;; CHECK-NEXT: (block
;; CHECK-NEXT: (block
;; CHECK-NEXT: (block $__inlined_func$byn-split-inlineable-A$0$7
;; CHECK-NEXT: (if
;; CHECK-NEXT: (i32.eqz
;; CHECK-NEXT: (global.get $global$0)
;; CHECK-NEXT: )
;; CHECK-NEXT: (call $byn-split-outlined-A$0_21)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK: (func $byn-split-outlined-A$0_21 (type $none_=>_none)
;; CHECK-NEXT: (block
;; CHECK-NEXT: (block $__inlined_func$1
;; CHECK-NEXT: (block
;; CHECK-NEXT: (block
;; CHECK-NEXT: (block $__inlined_func$byn-split-inlineable-A$0$8
;; CHECK-NEXT: (if
;; CHECK-NEXT: (i32.eqz
;; CHECK-NEXT: (global.get $global$0)
;; CHECK-NEXT: )
;; CHECK-NEXT: (call $byn-split-outlined-A$0_22)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (block
;; CHECK-NEXT: (block $__inlined_func$1$1
;; CHECK-NEXT: (block
;; CHECK-NEXT: (block
;; CHECK-NEXT: (block $__inlined_func$byn-split-inlineable-A$0$9
;; CHECK-NEXT: (if
;; CHECK-NEXT: (i32.eqz
;; CHECK-NEXT: (global.get $global$0)
;; CHECK-NEXT: )
;; CHECK-NEXT: (call $byn-split-outlined-A$0_22)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK: (func $byn-split-outlined-A$0_22 (type $none_=>_none)
;; CHECK-NEXT: (block
;; CHECK-NEXT: (block $__inlined_func$1
;; CHECK-NEXT: (block
;; CHECK-NEXT: (call $0)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (block
;; CHECK-NEXT: (block $__inlined_func$1$1
;; CHECK-NEXT: (block
;; CHECK-NEXT: (call $0)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(module
(func $middle-size-A (param $x i32)
;; This function is too big for normal inlining with the default size limit.
;; However, if we partially inline it then the outlined code becomes small
;; enough to be normally inlined. We should just inline it normally in that
;; case, to avoid wasted work.
(if
(local.get $x)
(return)
)
;; 6x3 = 18 items, close to the default size limit of 20. With the if, we
;; hit that limit and are too big. But if we did partial inlining then the
;; lines below us are small enough to then be inlined normally.
(drop (i32.const 0)) (drop (i32.const 0)) (drop (i32.const 0))
(drop (i32.const 0)) (drop (i32.const 0)) (drop (i32.const 0))
(drop (i32.const 0)) (drop (i32.const 0)) (drop (i32.const 0))
)
;; CHECK: (type $none_=>_none (func))
;; CHECK: (type $i32_=>_none (func (param i32)))
;; CHECK: (type $i32_=>_i32 (func (param i32) (result i32)))
;; CHECK: (func $call-$middle-size-A (type $none_=>_none)
;; CHECK-NEXT: (local $0 i32)
;; CHECK-NEXT: (local $1 i32)
;; CHECK-NEXT: (block
;; CHECK-NEXT: (block $__inlined_func$middle-size-A
;; CHECK-NEXT: (local.set $0
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: (block
;; CHECK-NEXT: (if
;; CHECK-NEXT: (local.get $0)
;; CHECK-NEXT: (br $__inlined_func$middle-size-A)
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (block
;; CHECK-NEXT: (block $__inlined_func$middle-size-A$1
;; CHECK-NEXT: (local.set $1
;; CHECK-NEXT: (i32.const 1)
;; CHECK-NEXT: )
;; CHECK-NEXT: (block
;; CHECK-NEXT: (if
;; CHECK-NEXT: (local.get $1)
;; CHECK-NEXT: (br $__inlined_func$middle-size-A$1)
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $call-$middle-size-A
;; This will be normally inlined, see the comment in the above function.
;; We can see it is normally inlined and not partially from the string
;; "__inlined_func" in the code (instead of "split" appearing anywhere).
(call $middle-size-A
(i32.const 0)
)
(call $middle-size-A
(i32.const 1)
)
)
(func $big-size-A (param $x i32)
;; As above, but a little larger - so large that we won't normally inline
;; it.
(if
(local.get $x)
(return)
)
;; 6x4 = 24 items, which is more than the inlining limit.
(drop (i32.const 0)) (drop (i32.const 0)) (drop (i32.const 0))
(drop (i32.const 0)) (drop (i32.const 0)) (drop (i32.const 0))
(drop (i32.const 0)) (drop (i32.const 0)) (drop (i32.const 0))
(drop (i32.const 0)) (drop (i32.const 0)) (drop (i32.const 0))
)
;; CHECK: (func $call-$big-size-A (type $none_=>_none)
;; CHECK-NEXT: (local $0 i32)
;; CHECK-NEXT: (local $1 i32)
;; CHECK-NEXT: (block
;; CHECK-NEXT: (block $__inlined_func$byn-split-inlineable-A$big-size-A$2
;; CHECK-NEXT: (local.set $0
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: (if
;; CHECK-NEXT: (i32.eqz
;; CHECK-NEXT: (local.get $0)
;; CHECK-NEXT: )
;; CHECK-NEXT: (call $byn-split-outlined-A$big-size-A
;; CHECK-NEXT: (local.get $0)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (block
;; CHECK-NEXT: (block $__inlined_func$byn-split-inlineable-A$big-size-A$3
;; CHECK-NEXT: (local.set $1
;; CHECK-NEXT: (i32.const 1)
;; CHECK-NEXT: )
;; CHECK-NEXT: (if
;; CHECK-NEXT: (i32.eqz
;; CHECK-NEXT: (local.get $1)
;; CHECK-NEXT: )
;; CHECK-NEXT: (call $byn-split-outlined-A$big-size-A
;; CHECK-NEXT: (local.get $1)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $call-$big-size-A
;; Normal inlining can't work here, so we'll just do partial inlining.
(call $big-size-A
(i32.const 0)
)
(call $big-size-A
(i32.const 1)
)
)
(func $middle-size-B (param $x i32) (result i32)
;; As above, but for pattern B and not A.
(if
(local.get $x)
(block
(drop (i32.const 0)) (drop (i32.const 0)) (drop (i32.const 0))
(drop (i32.const 0)) (drop (i32.const 0)) (drop (i32.const 0))
(drop (i32.const 0)) (drop (i32.const 0)) (drop (i32.const 0))
(unreachable)
)
)
(local.get $x)
)
;; CHECK: (func $call-$middle-size-B (type $none_=>_none)
;; CHECK-NEXT: (local $0 i32)
;; CHECK-NEXT: (local $1 i32)
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (block (result i32)
;; CHECK-NEXT: (block $__inlined_func$middle-size-B$4 (result i32)
;; CHECK-NEXT: (local.set $0
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: (block (result i32)
;; CHECK-NEXT: (if
;; CHECK-NEXT: (local.get $0)
;; CHECK-NEXT: (block
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (local.get $0)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (block (result i32)
;; CHECK-NEXT: (block $__inlined_func$middle-size-B$5 (result i32)
;; CHECK-NEXT: (local.set $1
;; CHECK-NEXT: (i32.const 1)
;; CHECK-NEXT: )
;; CHECK-NEXT: (block (result i32)
;; CHECK-NEXT: (if
;; CHECK-NEXT: (local.get $1)
;; CHECK-NEXT: (block
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (local.get $1)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $call-$middle-size-B
;; We will normally inline here.
(drop
(call $middle-size-B
(i32.const 0)
)
)
(drop
(call $middle-size-B
(i32.const 1)
)
)
)
(func $big-size-B (param $x i32) (result i32)
;; As above, but a little larger - so large that we won't normally inline
;; it.
(if
(local.get $x)
(block
(drop (i32.const 0)) (drop (i32.const 0)) (drop (i32.const 0))
(drop (i32.const 0)) (drop (i32.const 0)) (drop (i32.const 0))
(drop (i32.const 0)) (drop (i32.const 0)) (drop (i32.const 0))
(drop (i32.const 0)) (drop (i32.const 0)) (drop (i32.const 0))
(unreachable)
)
)
(local.get $x)
)
;; CHECK: (func $call-$big-size-B (type $none_=>_none)
;; CHECK-NEXT: (local $0 i32)
;; CHECK-NEXT: (local $1 i32)
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (block (result i32)
;; CHECK-NEXT: (block $__inlined_func$byn-split-inlineable-B$big-size-B$6 (result i32)
;; CHECK-NEXT: (local.set $0
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: (block (result i32)
;; CHECK-NEXT: (if
;; CHECK-NEXT: (local.get $0)
;; CHECK-NEXT: (br $__inlined_func$byn-split-inlineable-B$big-size-B$6
;; CHECK-NEXT: (call $byn-split-outlined-B$big-size-B
;; CHECK-NEXT: (local.get $0)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (local.get $0)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (block (result i32)
;; CHECK-NEXT: (block $__inlined_func$byn-split-inlineable-B$big-size-B$7 (result i32)
;; CHECK-NEXT: (local.set $1
;; CHECK-NEXT: (i32.const 1)
;; CHECK-NEXT: )
;; CHECK-NEXT: (block (result i32)
;; CHECK-NEXT: (if
;; CHECK-NEXT: (local.get $1)
;; CHECK-NEXT: (br $__inlined_func$byn-split-inlineable-B$big-size-B$7
;; CHECK-NEXT: (call $byn-split-outlined-B$big-size-B
;; CHECK-NEXT: (local.get $1)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (local.get $1)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $call-$big-size-B
;; We'll partially inline here.
(drop
(call $big-size-B
(i32.const 0)
)
)
(drop
(call $big-size-B
(i32.const 1)
)
)
)
)
;; CHECK: (func $byn-split-outlined-A$big-size-A (type $i32_=>_none) (param $x i32)
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK: (func $byn-split-outlined-B$big-size-B (type $i32_=>_i32) (param $x i32) (result i32)
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )