| ;; 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 $0 (func)) | |
| ;; CHECK: (type $1 (func (param i32))) | |
| ;; CHECK: (type $2 (func (param anyref) (result anyref))) | |
| ;; CHECK: (type $3 (func (param anyref))) | |
| ;; CHECK: (type $struct (struct)) | |
| (type $struct (struct)) | |
| ;; CHECK: (type $5 (func (param i64 i32 f64))) | |
| ;; CHECK: (import "out" "func" (func $import (type $0))) | |
| (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) | |
| (then | |
| (return) | |
| ) | |
| ) | |
| (loop $l | |
| (call $import) | |
| (br $l) | |
| ) | |
| ) | |
| ;; CHECK: (func $call-maybe-work-hard (type $0) | |
| ;; CHECK-NEXT: (local $0 i32) | |
| ;; CHECK-NEXT: (local $1 i32) | |
| ;; CHECK-NEXT: (local $2 i32) | |
| ;; 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: (then | |
| ;; 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 $__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: (then | |
| ;; 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 $__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: (then | |
| ;; 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) | |
| (then | |
| (loop $l | |
| (call $import) | |
| (br_if $l | |
| (local.get $x) | |
| ) | |
| ) | |
| ) | |
| ) | |
| ) | |
| ;; CHECK: (func $call-just-if (type $0) | |
| ;; CHECK-NEXT: (local $0 i32) | |
| ;; CHECK-NEXT: (local $1 i32) | |
| ;; 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: (then | |
| ;; 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 $__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: (then | |
| ;; 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 $1) (param $x i32) | |
| ;; CHECK-NEXT: (block $toplevel | |
| ;; CHECK-NEXT: (if | |
| ;; CHECK-NEXT: (local.get $x) | |
| ;; CHECK-NEXT: (then | |
| ;; CHECK-NEXT: (if | |
| ;; CHECK-NEXT: (local.get $x) | |
| ;; CHECK-NEXT: (then | |
| ;; CHECK-NEXT: (br $toplevel) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: (else | |
| ;; CHECK-NEXT: (call $import) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| (func $br-to-toplevel (param $x i32) | |
| (block $toplevel | |
| (if | |
| (local.get $x) | |
| (then | |
| (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. | |
| (then | |
| (br $toplevel) | |
| ) | |
| (else | |
| (call $import) | |
| ) | |
| ) | |
| ) | |
| ) | |
| ) | |
| ) | |
| ) | |
| ;; CHECK: (func $call-br-to-toplevel (type $0) | |
| ;; 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) | |
| (then | |
| (return) | |
| ) | |
| ) | |
| (loop $l | |
| (call $import) | |
| (br $l) | |
| ) | |
| ) | |
| ;; CHECK: (func $call-nondefaultable-param (type $0) | |
| ;; 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: (then | |
| ;; CHECK-NEXT: (br $__inlined_func$nondefaultable-param$5) | |
| ;; CHECK-NEXT: ) | |
| ;; 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) | |
| (then | |
| (return) | |
| ) | |
| ) | |
| (loop $l | |
| (call $import) | |
| (br $l) | |
| ) | |
| ) | |
| ;; CHECK: (func $call-many-params (type $0) | |
| ;; 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 $__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: (then | |
| ;; 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 $__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: (then | |
| ;; 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) | |
| ) | |
| (then | |
| (return) | |
| ) | |
| ) | |
| (loop $l | |
| (call $import) | |
| (br $l) | |
| ) | |
| ) | |
| ;; CHECK: (func $call-condition-eqz (type $0) | |
| ;; CHECK-NEXT: (local $0 i32) | |
| ;; CHECK-NEXT: (local $1 i32) | |
| ;; 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: (then | |
| ;; 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 $__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: (then | |
| ;; 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) | |
| (then | |
| (return) | |
| ) | |
| ) | |
| (loop $l | |
| (call $import) | |
| (br $l) | |
| ) | |
| ) | |
| ;; CHECK: (func $call-condition-global (type $0) | |
| ;; 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: (then | |
| ;; CHECK-NEXT: (call $byn-split-outlined-A$condition-global) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; 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: (then | |
| ;; 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) | |
| ) | |
| (then | |
| (return) | |
| ) | |
| ) | |
| (loop $l | |
| (call $import) | |
| (br $l) | |
| ) | |
| ) | |
| ;; CHECK: (func $call-condition-ref.is (type $0) | |
| ;; CHECK-NEXT: (local $0 anyref) | |
| ;; CHECK-NEXT: (local $1 anyref) | |
| ;; 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: (then | |
| ;; 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 $__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: (then | |
| ;; 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 $1) (param $x i32) | |
| ;; CHECK-NEXT: (if | |
| ;; CHECK-NEXT: (i32.add | |
| ;; CHECK-NEXT: (local.get $x) | |
| ;; CHECK-NEXT: (local.get $x) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: (then | |
| ;; CHECK-NEXT: (return) | |
| ;; CHECK-NEXT: ) | |
| ;; 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) | |
| ) | |
| (then | |
| (return) | |
| ) | |
| ) | |
| (loop $l | |
| (call $import) | |
| (br $l) | |
| ) | |
| ) | |
| ;; CHECK: (func $call-condition-disallow-binary (type $0) | |
| ;; 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 $1) (param $x i32) | |
| ;; CHECK-NEXT: (if | |
| ;; CHECK-NEXT: (i32.eqz | |
| ;; CHECK-NEXT: (unreachable) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: (then | |
| ;; CHECK-NEXT: (return) | |
| ;; CHECK-NEXT: ) | |
| ;; 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) | |
| ) | |
| (then | |
| (return) | |
| ) | |
| ) | |
| (loop $l | |
| (call $import) | |
| (br $l) | |
| ) | |
| ) | |
| ;; CHECK: (func $call-condition-disallow-unreachable (type $0) | |
| ;; 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 $0) | |
| ;; CHECK-NEXT: (if | |
| ;; CHECK-NEXT: (global.get $glob) | |
| ;; CHECK-NEXT: (then | |
| ;; CHECK-NEXT: (return) | |
| ;; CHECK-NEXT: ) | |
| ;; 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) | |
| (then | |
| (return) | |
| ) | |
| ) | |
| (loop $l | |
| (call $import) | |
| (br $l) | |
| ) | |
| ) | |
| ;; CHECK: (func $call-start-used-globally (type $0) | |
| ;; 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: (then | |
| ;; CHECK-NEXT: (call $byn-split-outlined-A$start-used-globally) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; 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: (then | |
| ;; 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) | |
| (then | |
| (return) | |
| ) | |
| ) | |
| ) | |
| ;; CHECK: (func $call-inlineable (type $0) | |
| ;; CHECK-NEXT: (block $__inlined_func$inlineable$16 | |
| ;; CHECK-NEXT: (if | |
| ;; CHECK-NEXT: (global.get $glob) | |
| ;; CHECK-NEXT: (then | |
| ;; CHECK-NEXT: (br $__inlined_func$inlineable$16) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: (block $__inlined_func$inlineable$17 | |
| ;; CHECK-NEXT: (if | |
| ;; CHECK-NEXT: (global.get $glob) | |
| ;; CHECK-NEXT: (then | |
| ;; 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 $1) (param $x i32) | |
| ;; CHECK-NEXT: (nop) | |
| ;; CHECK-NEXT: (if | |
| ;; CHECK-NEXT: (local.get $x) | |
| ;; CHECK-NEXT: (then | |
| ;; CHECK-NEXT: (return) | |
| ;; CHECK-NEXT: ) | |
| ;; 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) | |
| (then | |
| (return) | |
| ) | |
| ) | |
| (loop $l | |
| (call $import) | |
| (br $l) | |
| ) | |
| ) | |
| ;; CHECK: (func $call-if-not-first (type $0) | |
| ;; 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 $1) (param $x i32) | |
| ;; CHECK-NEXT: (if | |
| ;; CHECK-NEXT: (local.get $x) | |
| ;; CHECK-NEXT: (then | |
| ;; CHECK-NEXT: (return) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: (else | |
| ;; CHECK-NEXT: (nop) | |
| ;; CHECK-NEXT: ) | |
| ;; 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) | |
| (then | |
| (return) | |
| ) | |
| (else | |
| (nop) | |
| ) | |
| ) | |
| (loop $l | |
| (call $import) | |
| (br $l) | |
| ) | |
| ) | |
| ;; CHECK: (func $call-if-else (type $0) | |
| ;; 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 $1) (param $x i32) | |
| ;; CHECK-NEXT: (if | |
| ;; CHECK-NEXT: (local.get $x) | |
| ;; CHECK-NEXT: (then | |
| ;; CHECK-NEXT: (unreachable) | |
| ;; CHECK-NEXT: ) | |
| ;; 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) | |
| (then | |
| (unreachable) | |
| ) | |
| ) | |
| (loop $l | |
| (call $import) | |
| (br $l) | |
| ) | |
| ) | |
| ;; CHECK: (func $call-if-non-return (type $0) | |
| ;; 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) | |
| (then | |
| (return) | |
| ) | |
| ) | |
| (loop $l | |
| (call $import) | |
| (br $l) | |
| ) | |
| ) | |
| ;; CHECK: (func $call-colliding-name (type $0) | |
| ;; CHECK-NEXT: (local $0 i32) | |
| ;; CHECK-NEXT: (local $1 i32) | |
| ;; 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: (then | |
| ;; CHECK-NEXT: (call $byn-split-outlined-A$colliding-name_70 | |
| ;; CHECK-NEXT: (local.get $0) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; 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: (then | |
| ;; CHECK-NEXT: (call $byn-split-outlined-A$colliding-name_70 | |
| ;; 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 $0) | |
| ;; 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) | |
| ) | |
| (then | |
| (block | |
| (call $import) | |
| (unreachable) | |
| ) | |
| ) | |
| ) | |
| (local.get $x) | |
| ) | |
| ;; CHECK: (func $call-error-if-null (type $0) | |
| ;; CHECK-NEXT: (local $0 anyref) | |
| ;; CHECK-NEXT: (local $1 anyref) | |
| ;; CHECK-NEXT: (drop | |
| ;; 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: (then | |
| ;; 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: ) | |
| ;; CHECK-NEXT: (local.get $0) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: (drop | |
| ;; 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: (then | |
| ;; 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: ) | |
| ;; CHECK-NEXT: (local.get $1) | |
| ;; 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 $2) (param $x anyref) (result anyref) | |
| ;; CHECK-NEXT: (if | |
| ;; CHECK-NEXT: (ref.is_null | |
| ;; CHECK-NEXT: (local.get $x) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: (then | |
| ;; 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) | |
| ) | |
| (then | |
| (block | |
| (call $import) | |
| (unreachable) | |
| ) | |
| ) | |
| ) | |
| (nop) ;; An extra operation here prevents us from identifying the pattern. | |
| (local.get $x) | |
| ) | |
| ;; CHECK: (func $call-too-many (type $0) | |
| ;; 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 $2) (param $x anyref) (result anyref) | |
| ;; CHECK-NEXT: (if | |
| ;; CHECK-NEXT: (ref.is_null | |
| ;; CHECK-NEXT: (local.get $x) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: (then | |
| ;; 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) | |
| ) | |
| (then | |
| (block | |
| (call $import) | |
| (unreachable) | |
| ) | |
| ) | |
| ) | |
| (unreachable) ;; This prevents us from optimizing | |
| ) | |
| ;; CHECK: (func $call-tail-not-simple (type $0) | |
| ;; 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. | |
| (then | |
| (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 $0) | |
| ;; CHECK-NEXT: (local $0 anyref) | |
| ;; CHECK-NEXT: (local $1 anyref) | |
| ;; CHECK-NEXT: (drop | |
| ;; 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: (then | |
| ;; CHECK-NEXT: (call $byn-split-outlined-B$reachable-if-body | |
| ;; CHECK-NEXT: (local.get $0) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: (local.get $0) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: (drop | |
| ;; 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: (then | |
| ;; CHECK-NEXT: (call $byn-split-outlined-B$reachable-if-body | |
| ;; CHECK-NEXT: (local.get $1) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: (local.get $1) | |
| ;; 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) | |
| ) | |
| (then | |
| (call $import) | |
| ) | |
| ) | |
| (local.get $x) | |
| ) | |
| ;; CHECK: (func $call-reachable-if-body-noloop (type $0) | |
| ;; CHECK-NEXT: (local $0 anyref) | |
| ;; CHECK-NEXT: (local $1 anyref) | |
| ;; CHECK-NEXT: (drop | |
| ;; 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: (then | |
| ;; CHECK-NEXT: (call $import) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: (local.get $0) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: (drop | |
| ;; 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: (then | |
| ;; CHECK-NEXT: (call $import) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: (local.get $1) | |
| ;; 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 $2) (param $x anyref) (result anyref) | |
| ;; CHECK-NEXT: (if | |
| ;; CHECK-NEXT: (ref.is_null | |
| ;; CHECK-NEXT: (local.get $x) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: (then | |
| ;; CHECK-NEXT: (if | |
| ;; CHECK-NEXT: (i32.const 1) | |
| ;; CHECK-NEXT: (then | |
| ;; CHECK-NEXT: (return | |
| ;; CHECK-NEXT: (local.get $x) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: (else | |
| ;; CHECK-NEXT: (call $import) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; 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) | |
| ) | |
| (then | |
| (if | |
| (i32.const 1) | |
| ;; The return here prevents the optimization. | |
| (then | |
| (return | |
| (local.get $x) | |
| ) | |
| ) | |
| (else | |
| (call $import) | |
| ) | |
| ) | |
| ) | |
| ) | |
| (local.get $x) | |
| ) | |
| ;; CHECK: (func $call-reachable-if-body-return (type $0) | |
| ;; 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. | |
| (then | |
| (block | |
| (call $import) | |
| (unreachable) | |
| ) | |
| ) | |
| ) | |
| ) | |
| ;; CHECK: (func $call-unreachable-if-body-no-result (type $0) | |
| ;; CHECK-NEXT: (local $0 anyref) | |
| ;; CHECK-NEXT: (local $1 anyref) | |
| ;; 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: (then | |
| ;; 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 $__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: (then | |
| ;; 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)) | |
| ) | |
| ;; CHECK: (func $nop (type $2) (param $x anyref) (result anyref) | |
| ;; CHECK-NEXT: (loop $loop | |
| ;; CHECK-NEXT: (if | |
| ;; CHECK-NEXT: (ref.is_null | |
| ;; CHECK-NEXT: (local.get $x) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: (then | |
| ;; CHECK-NEXT: (br $loop) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: (return_call $nop | |
| ;; CHECK-NEXT: (local.get $x) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| (func $nop (param $x anyref) (result anyref) | |
| ;; A loop and recursion, to avoid this getting inlined (we want to keep the | |
| ;; return_call to here as a return_call). | |
| (loop $loop | |
| (if | |
| (ref.is_null | |
| (local.get $x) | |
| ) | |
| (then | |
| (br $loop) | |
| ) | |
| ) | |
| (return_call $nop | |
| (local.get $x) | |
| ) | |
| ) | |
| ) | |
| ;; CHECK: (func $reachable-if-body-return_call (type $2) (param $x anyref) (result anyref) | |
| ;; CHECK-NEXT: (if | |
| ;; CHECK-NEXT: (ref.is_null | |
| ;; CHECK-NEXT: (local.get $x) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: (then | |
| ;; CHECK-NEXT: (if | |
| ;; CHECK-NEXT: (i32.const 1) | |
| ;; CHECK-NEXT: (then | |
| ;; CHECK-NEXT: (return_call $nop | |
| ;; CHECK-NEXT: (local.get $x) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: (else | |
| ;; CHECK-NEXT: (call $import) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: (local.get $x) | |
| ;; CHECK-NEXT: ) | |
| (func $reachable-if-body-return_call (param $x anyref) (result anyref) | |
| (if | |
| (ref.is_null | |
| (local.get $x) | |
| ) | |
| (then | |
| (if | |
| (i32.const 1) | |
| ;; The return_call here prevents the optimization (nothing is inlined | |
| ;; in our caller, below), just like the return in the previous | |
| ;; testcase. | |
| (then | |
| (return_call $nop | |
| (local.get $x) | |
| ) | |
| ) | |
| (else | |
| (call $import) | |
| ) | |
| ) | |
| ) | |
| ) | |
| (local.get $x) | |
| ) | |
| ;; CHECK: (func $call-reachable-if-body-return_call (type $0) | |
| ;; CHECK-NEXT: (drop | |
| ;; CHECK-NEXT: (call $reachable-if-body-return_call | |
| ;; CHECK-NEXT: (ref.null none) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: (drop | |
| ;; CHECK-NEXT: (call $reachable-if-body-return_call | |
| ;; CHECK-NEXT: (ref.null none) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| (func $call-reachable-if-body-return_call | |
| ;; We do not inline here. | |
| (drop (call $reachable-if-body-return_call (ref.null any))) | |
| (drop (call $reachable-if-body-return_call (ref.null any))) | |
| ) | |
| (func $multi-if (param $x anyref) (result anyref) | |
| (if | |
| (ref.is_null | |
| (local.get $x) | |
| ) | |
| (then | |
| (call $import) | |
| ) | |
| ) | |
| ;; A second if. We can outline both if bodies. | |
| (if | |
| (ref.is_null | |
| (local.get $x) | |
| ) | |
| (then | |
| (loop $x | |
| (call $import) | |
| (br_if $x | |
| (global.get $glob) | |
| ) | |
| ) | |
| ) | |
| ) | |
| (local.get $x) | |
| ) | |
| ;; CHECK: (func $call-multi-if (type $0) | |
| ;; 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 $__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: (then | |
| ;; 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: ) | |
| ;; CHECK-NEXT: (if | |
| ;; CHECK-NEXT: (ref.is_null | |
| ;; CHECK-NEXT: (local.get $0) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: (then | |
| ;; CHECK-NEXT: (call $byn-split-outlined-B$multi-if_79 | |
| ;; CHECK-NEXT: (local.get $0) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: (local.get $0) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: (drop | |
| ;; 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: (then | |
| ;; 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: ) | |
| ;; CHECK-NEXT: (if | |
| ;; CHECK-NEXT: (ref.is_null | |
| ;; CHECK-NEXT: (local.get $1) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: (then | |
| ;; CHECK-NEXT: (call $byn-split-outlined-B$multi-if_79 | |
| ;; CHECK-NEXT: (local.get $1) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: (local.get $1) | |
| ;; 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 $2) (param $x anyref) (result anyref) | |
| ;; CHECK-NEXT: (if | |
| ;; CHECK-NEXT: (ref.is_null | |
| ;; CHECK-NEXT: (local.get $x) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: (then | |
| ;; CHECK-NEXT: (call $import) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: (if | |
| ;; CHECK-NEXT: (ref.is_null | |
| ;; CHECK-NEXT: (local.get $x) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: (then | |
| ;; CHECK-NEXT: (call $import) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: (if | |
| ;; CHECK-NEXT: (ref.is_null | |
| ;; CHECK-NEXT: (local.get $x) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: (then | |
| ;; CHECK-NEXT: (call $import) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: (if | |
| ;; CHECK-NEXT: (ref.is_null | |
| ;; CHECK-NEXT: (local.get $x) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: (then | |
| ;; CHECK-NEXT: (call $import) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: (if | |
| ;; CHECK-NEXT: (ref.is_null | |
| ;; CHECK-NEXT: (local.get $x) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: (then | |
| ;; CHECK-NEXT: (call $import) | |
| ;; CHECK-NEXT: ) | |
| ;; 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) | |
| ) | |
| (then | |
| (call $import) | |
| ) | |
| ) | |
| (if | |
| (ref.is_null | |
| (local.get $x) | |
| ) | |
| (then | |
| (call $import) | |
| ) | |
| ) | |
| (if | |
| (ref.is_null | |
| (local.get $x) | |
| ) | |
| (then | |
| (call $import) | |
| ) | |
| ) | |
| (if | |
| (ref.is_null | |
| (local.get $x) | |
| ) | |
| (then | |
| (call $import) | |
| ) | |
| ) | |
| (if | |
| (ref.is_null | |
| (local.get $x) | |
| ) | |
| (then | |
| (call $import) | |
| ) | |
| ) | |
| (local.get $x) | |
| ) | |
| ;; CHECK: (func $call-too-many-ifs (type $0) | |
| ;; 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 $1) (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 $1) (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 $5) (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 $1) (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 $0) | |
| ;; 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 $3) (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 $0) | |
| ;; CHECK-NEXT: (loop $l | |
| ;; CHECK-NEXT: (call $import) | |
| ;; CHECK-NEXT: (br $l) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK: (func $byn-split-outlined-A$colliding-name_70 (type $1) (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 $2) (param $x anyref) (result anyref) | |
| ;; CHECK-NEXT: (call $import) | |
| ;; CHECK-NEXT: (unreachable) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK: (func $byn-split-outlined-B$reachable-if-body (type $3) (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 $3) (param $x anyref) | |
| ;; CHECK-NEXT: (call $import) | |
| ;; CHECK-NEXT: (unreachable) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK: (func $byn-split-outlined-B$multi-if_79 (type $3) (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: (then | |
| ;; CHECK-NEXT: (return) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: (block $__inlined_func$1 | |
| ;; CHECK-NEXT: (call $0) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: (block $__inlined_func$1$1 | |
| ;; CHECK-NEXT: (call $0) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| (func $0 | |
| ;; A function that is a good candidate to partially inline. | |
| (if | |
| (global.get $global$0) | |
| (then | |
| (return) | |
| ) | |
| ) | |
| (call $1) | |
| (call $1) | |
| ) | |
| ;; CHECK: (func $1 (type $none_=>_none) | |
| ;; 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: (then | |
| ;; CHECK-NEXT: (block $__inlined_func$byn-split-outlined-A$0$3 | |
| ;; CHECK-NEXT: (block | |
| ;; CHECK-NEXT: (block $__inlined_func$1 | |
| ;; 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: (then | |
| ;; CHECK-NEXT: (call $byn-split-outlined-A$0) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: (block $__inlined_func$1$1 | |
| ;; 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: (then | |
| ;; 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: ) | |
| (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 $__inlined_func$1 | |
| ;; 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: (then | |
| ;; CHECK-NEXT: (call $byn-split-outlined-A$0_21) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: (block $__inlined_func$1$1 | |
| ;; 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: (then | |
| ;; CHECK-NEXT: (call $byn-split-outlined-A$0_21) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK: (func $byn-split-outlined-A$0_21 (type $none_=>_none) | |
| ;; CHECK-NEXT: (block $__inlined_func$1 | |
| ;; 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: (then | |
| ;; CHECK-NEXT: (call $byn-split-outlined-A$0_22) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: (block $__inlined_func$1$1 | |
| ;; 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: (then | |
| ;; CHECK-NEXT: (call $byn-split-outlined-A$0_22) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK: (func $byn-split-outlined-A$0_22 (type $none_=>_none) | |
| ;; CHECK-NEXT: (block $__inlined_func$1 | |
| ;; CHECK-NEXT: (call $0) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: (block $__inlined_func$1$1 | |
| ;; CHECK-NEXT: (call $0) | |
| ;; 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) | |
| (then | |
| (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 $0 (func)) | |
| ;; CHECK: (type $1 (func (param i32))) | |
| ;; CHECK: (type $2 (func (param i32) (result i32))) | |
| ;; CHECK: (func $call-$middle-size-A (type $0) | |
| ;; CHECK-NEXT: (local $0 i32) | |
| ;; CHECK-NEXT: (local $1 i32) | |
| ;; 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: (then | |
| ;; CHECK-NEXT: (br $__inlined_func$middle-size-A) | |
| ;; CHECK-NEXT: ) | |
| ;; 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: (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: (then | |
| ;; CHECK-NEXT: (br $__inlined_func$middle-size-A$1) | |
| ;; CHECK-NEXT: ) | |
| ;; 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: ) | |
| (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) | |
| (then | |
| (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 $0) | |
| ;; CHECK-NEXT: (local $0 i32) | |
| ;; CHECK-NEXT: (local $1 i32) | |
| ;; 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: (then | |
| ;; 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 $__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: (then | |
| ;; 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) | |
| (then | |
| (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 $0) | |
| ;; CHECK-NEXT: (local $0 i32) | |
| ;; CHECK-NEXT: (local $1 i32) | |
| ;; CHECK-NEXT: (drop | |
| ;; 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: (then | |
| ;; 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: (drop | |
| ;; 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: (then | |
| ;; 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: ) | |
| (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) | |
| (then | |
| (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 $0) | |
| ;; CHECK-NEXT: (local $0 i32) | |
| ;; CHECK-NEXT: (local $1 i32) | |
| ;; CHECK-NEXT: (drop | |
| ;; 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: (then | |
| ;; 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: ) | |
| ;; CHECK-NEXT: (local.get $0) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: (drop | |
| ;; 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: (then | |
| ;; 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: ) | |
| ;; CHECK-NEXT: (local.get $1) | |
| ;; 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 $1) (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 $2) (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: ) | |
| (module | |
| ;; Pattern B situations with local value dependencies. | |
| ;; An import, whose calls are work that we want to split out. | |
| ;; CHECK: (type $0 (func)) | |
| ;; CHECK: (type $1 (func (param i32 i32) (result i32))) | |
| ;; CHECK: (type $2 (func (param i32 i32))) | |
| ;; CHECK: (import "out" "func" (func $import (type $0))) | |
| (import "out" "func" (func $import)) | |
| ;; CHECK: (func $bad (type $1) (param $x i32) (param $y i32) (result i32) | |
| ;; CHECK-NEXT: (if | |
| ;; CHECK-NEXT: (local.get $x) | |
| ;; CHECK-NEXT: (then | |
| ;; CHECK-NEXT: (local.set $y | |
| ;; CHECK-NEXT: (i32.const 42) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: (call $import) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: (local.get $y) | |
| ;; CHECK-NEXT: ) | |
| (func $bad (param $x i32) (param $y i32) (result i32) | |
| ;; Check $x, and possibly set $y. $y is read below, so we cannot split out | |
| ;; the set. | |
| (if | |
| (local.get $x) | |
| (then | |
| (block | |
| (local.set $y | |
| (i32.const 42) | |
| ) | |
| (call $import) | |
| ) | |
| ) | |
| ) | |
| (local.get $y) | |
| ) | |
| ;; CHECK: (func $calls-bad (type $0) | |
| ;; CHECK-NEXT: (drop | |
| ;; CHECK-NEXT: (call $bad | |
| ;; CHECK-NEXT: (i32.const 1) | |
| ;; CHECK-NEXT: (i32.const 2) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: (drop | |
| ;; CHECK-NEXT: (call $bad | |
| ;; CHECK-NEXT: (i32.const 1) | |
| ;; CHECK-NEXT: (i32.const 2) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| (func $calls-bad | |
| ;; These should not be inlined/split. | |
| ;; Call twice to avoid single-call inlining. | |
| (drop | |
| (call $bad (i32.const 1) (i32.const 2)) | |
| ) | |
| (drop | |
| (call $bad (i32.const 1) (i32.const 2)) | |
| ) | |
| ) | |
| (func $good (param $x i32) (param $y i32) (result i32) | |
| ;; As above, but set $x in the if body. No problem occurs after the if, so | |
| ;; we can split here. | |
| (if | |
| (local.get $x) | |
| (then | |
| (block | |
| (local.set $x ;; this changed | |
| (i32.const 1337) | |
| ) | |
| (call $import) | |
| ) | |
| ) | |
| ) | |
| (local.get $y) | |
| ) | |
| ;; CHECK: (func $calls-good (type $0) | |
| ;; CHECK-NEXT: (local $0 i32) | |
| ;; CHECK-NEXT: (local $1 i32) | |
| ;; CHECK-NEXT: (local $2 i32) | |
| ;; CHECK-NEXT: (local $3 i32) | |
| ;; CHECK-NEXT: (drop | |
| ;; CHECK-NEXT: (block $__inlined_func$byn-split-inlineable-B$good (result i32) | |
| ;; CHECK-NEXT: (local.set $0 | |
| ;; CHECK-NEXT: (i32.const 2) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: (local.set $1 | |
| ;; CHECK-NEXT: (i32.const 3) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: (block (result i32) | |
| ;; CHECK-NEXT: (if | |
| ;; CHECK-NEXT: (local.get $0) | |
| ;; CHECK-NEXT: (then | |
| ;; CHECK-NEXT: (call $byn-split-outlined-B$good | |
| ;; CHECK-NEXT: (local.get $0) | |
| ;; CHECK-NEXT: (local.get $1) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: (local.get $1) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: (drop | |
| ;; CHECK-NEXT: (block $__inlined_func$byn-split-inlineable-B$good$1 (result i32) | |
| ;; CHECK-NEXT: (local.set $2 | |
| ;; CHECK-NEXT: (i32.const 2) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: (local.set $3 | |
| ;; CHECK-NEXT: (i32.const 3) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: (block (result i32) | |
| ;; CHECK-NEXT: (if | |
| ;; CHECK-NEXT: (local.get $2) | |
| ;; CHECK-NEXT: (then | |
| ;; CHECK-NEXT: (call $byn-split-outlined-B$good | |
| ;; CHECK-NEXT: (local.get $2) | |
| ;; CHECK-NEXT: (local.get $3) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: (local.get $3) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| (func $calls-good | |
| ;; These should be inlined/split. | |
| (drop | |
| (call $good (i32.const 2) (i32.const 3)) | |
| ) | |
| (drop | |
| (call $good (i32.const 2) (i32.const 3)) | |
| ) | |
| ) | |
| ;; CHECK: (func $bad-2 (type $1) (param $x i32) (param $y i32) (result i32) | |
| ;; CHECK-NEXT: (if | |
| ;; CHECK-NEXT: (local.get $x) | |
| ;; CHECK-NEXT: (then | |
| ;; CHECK-NEXT: (local.set $y | |
| ;; CHECK-NEXT: (i32.const 42) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: (call $import) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: (if | |
| ;; CHECK-NEXT: (local.get $y) | |
| ;; CHECK-NEXT: (then | |
| ;; CHECK-NEXT: (local.set $x | |
| ;; CHECK-NEXT: (i32.const 42) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: (call $import) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: (local.get $y) | |
| ;; CHECK-NEXT: ) | |
| (func $bad-2 (param $x i32) (param $y i32) (result i32) | |
| ;; Two ifs, with the problem in the first. | |
| (if | |
| (local.get $x) | |
| (then | |
| (block | |
| (local.set $y ;; this is bad | |
| (i32.const 42) | |
| ) | |
| (call $import) | |
| ) | |
| ) | |
| ) | |
| (if | |
| (local.get $y) | |
| (then | |
| (block | |
| (local.set $x | |
| (i32.const 42) | |
| ) | |
| (call $import) | |
| ) | |
| ) | |
| ) | |
| (local.get $y) | |
| ) | |
| ;; CHECK: (func $calls-bad-2 (type $0) | |
| ;; CHECK-NEXT: (drop | |
| ;; CHECK-NEXT: (call $bad-2 | |
| ;; CHECK-NEXT: (i32.const 1) | |
| ;; CHECK-NEXT: (i32.const 2) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: (drop | |
| ;; CHECK-NEXT: (call $bad-2 | |
| ;; CHECK-NEXT: (i32.const 1) | |
| ;; CHECK-NEXT: (i32.const 2) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| (func $calls-bad-2 | |
| ;; These should not be inlined/split. | |
| (drop | |
| (call $bad-2 (i32.const 1) (i32.const 2)) | |
| ) | |
| (drop | |
| (call $bad-2 (i32.const 1) (i32.const 2)) | |
| ) | |
| ) | |
| ;; CHECK: (func $bad-3 (type $1) (param $x i32) (param $y i32) (result i32) | |
| ;; CHECK-NEXT: (if | |
| ;; CHECK-NEXT: (local.get $x) | |
| ;; CHECK-NEXT: (then | |
| ;; CHECK-NEXT: (local.set $x | |
| ;; CHECK-NEXT: (i32.const 42) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: (call $import) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: (if | |
| ;; CHECK-NEXT: (local.get $y) | |
| ;; CHECK-NEXT: (then | |
| ;; CHECK-NEXT: (local.set $y | |
| ;; CHECK-NEXT: (i32.const 42) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: (call $import) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: (local.get $y) | |
| ;; CHECK-NEXT: ) | |
| (func $bad-3 (param $x i32) (param $y i32) (result i32) | |
| ;; Two ifs, with the problem in the second. | |
| (if | |
| (local.get $x) | |
| (then | |
| (block | |
| (local.set $x ;; this changed | |
| (i32.const 42) | |
| ) | |
| (call $import) | |
| ) | |
| ) | |
| ) | |
| (if | |
| (local.get $y) | |
| (then | |
| (block | |
| (local.set $y ;; this changed | |
| (i32.const 42) | |
| ) | |
| (call $import) | |
| ) | |
| ) | |
| ) | |
| (local.get $y) | |
| ) | |
| ;; CHECK: (func $calls-bad-3 (type $0) | |
| ;; CHECK-NEXT: (drop | |
| ;; CHECK-NEXT: (call $bad-3 | |
| ;; CHECK-NEXT: (i32.const 1) | |
| ;; CHECK-NEXT: (i32.const 2) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: (drop | |
| ;; CHECK-NEXT: (call $bad-3 | |
| ;; CHECK-NEXT: (i32.const 1) | |
| ;; CHECK-NEXT: (i32.const 2) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| (func $calls-bad-3 | |
| ;; These should not be inlined/split. | |
| (drop | |
| (call $bad-3 (i32.const 1) (i32.const 2)) | |
| ) | |
| (drop | |
| (call $bad-3 (i32.const 1) (i32.const 2)) | |
| ) | |
| ) | |
| ;; CHECK: (func $bad-4 (type $1) (param $x i32) (param $y i32) (result i32) | |
| ;; CHECK-NEXT: (if | |
| ;; CHECK-NEXT: (local.get $x) | |
| ;; CHECK-NEXT: (then | |
| ;; CHECK-NEXT: (local.set $y | |
| ;; CHECK-NEXT: (i32.const 42) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: (call $import) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: (if | |
| ;; CHECK-NEXT: (local.get $y) | |
| ;; CHECK-NEXT: (then | |
| ;; CHECK-NEXT: (local.set $y | |
| ;; CHECK-NEXT: (i32.const 42) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: (call $import) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: (local.get $y) | |
| ;; CHECK-NEXT: ) | |
| (func $bad-4 (param $x i32) (param $y i32) (result i32) | |
| ;; Two ifs, with a problem in both. | |
| (if | |
| (local.get $x) | |
| (then | |
| (block | |
| (local.set $y ;; this changed | |
| (i32.const 42) | |
| ) | |
| (call $import) | |
| ) | |
| ) | |
| ) | |
| (if | |
| (local.get $y) | |
| (then | |
| (block | |
| (local.set $y | |
| (i32.const 42) | |
| ) | |
| (call $import) | |
| ) | |
| ) | |
| ) | |
| (local.get $y) | |
| ) | |
| ;; CHECK: (func $calls-bad-4 (type $0) | |
| ;; CHECK-NEXT: (drop | |
| ;; CHECK-NEXT: (call $bad-4 | |
| ;; CHECK-NEXT: (i32.const 1) | |
| ;; CHECK-NEXT: (i32.const 2) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: (drop | |
| ;; CHECK-NEXT: (call $bad-4 | |
| ;; CHECK-NEXT: (i32.const 1) | |
| ;; CHECK-NEXT: (i32.const 2) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| (func $calls-bad-4 | |
| ;; These should not be inlined/split. | |
| (drop | |
| (call $bad-4 (i32.const 1) (i32.const 2)) | |
| ) | |
| (drop | |
| (call $bad-4 (i32.const 1) (i32.const 2)) | |
| ) | |
| ) | |
| (func $good-5 (param $x i32) (param $y i32) (result i32) | |
| ;; Two ifs, with no problem in either. | |
| (if | |
| (local.get $x) | |
| (then | |
| (block | |
| (local.set $x ;; this changed | |
| (i32.const 42) | |
| ) | |
| (call $import) | |
| ) | |
| ) | |
| ) | |
| (if | |
| (local.get $y) | |
| (then | |
| (block | |
| (local.set $x ;; this changed | |
| (i32.const 42) | |
| ) | |
| (call $import) | |
| ) | |
| ) | |
| ) | |
| (local.get $y) | |
| ) | |
| ;; CHECK: (func $calls-good-5 (type $0) | |
| ;; CHECK-NEXT: (local $0 i32) | |
| ;; CHECK-NEXT: (local $1 i32) | |
| ;; CHECK-NEXT: (local $2 i32) | |
| ;; CHECK-NEXT: (local $3 i32) | |
| ;; CHECK-NEXT: (drop | |
| ;; CHECK-NEXT: (block $__inlined_func$byn-split-inlineable-B$good-5$2 (result i32) | |
| ;; CHECK-NEXT: (local.set $0 | |
| ;; CHECK-NEXT: (i32.const 1) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: (local.set $1 | |
| ;; CHECK-NEXT: (i32.const 2) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: (block (result i32) | |
| ;; CHECK-NEXT: (if | |
| ;; CHECK-NEXT: (local.get $0) | |
| ;; CHECK-NEXT: (then | |
| ;; CHECK-NEXT: (call $byn-split-outlined-B$good-5 | |
| ;; CHECK-NEXT: (local.get $0) | |
| ;; CHECK-NEXT: (local.get $1) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: (if | |
| ;; CHECK-NEXT: (local.get $1) | |
| ;; CHECK-NEXT: (then | |
| ;; CHECK-NEXT: (call $byn-split-outlined-B$good-5_17 | |
| ;; CHECK-NEXT: (local.get $0) | |
| ;; CHECK-NEXT: (local.get $1) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: (local.get $1) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: (drop | |
| ;; CHECK-NEXT: (block $__inlined_func$byn-split-inlineable-B$good-5$3 (result i32) | |
| ;; CHECK-NEXT: (local.set $2 | |
| ;; CHECK-NEXT: (i32.const 1) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: (local.set $3 | |
| ;; CHECK-NEXT: (i32.const 2) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: (block (result i32) | |
| ;; CHECK-NEXT: (if | |
| ;; CHECK-NEXT: (local.get $2) | |
| ;; CHECK-NEXT: (then | |
| ;; CHECK-NEXT: (call $byn-split-outlined-B$good-5 | |
| ;; CHECK-NEXT: (local.get $2) | |
| ;; CHECK-NEXT: (local.get $3) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: (if | |
| ;; CHECK-NEXT: (local.get $3) | |
| ;; CHECK-NEXT: (then | |
| ;; CHECK-NEXT: (call $byn-split-outlined-B$good-5_17 | |
| ;; CHECK-NEXT: (local.get $2) | |
| ;; CHECK-NEXT: (local.get $3) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: (local.get $3) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| (func $calls-good-5 | |
| ;; These should be inlined/split. | |
| (drop | |
| (call $good-5 (i32.const 1) (i32.const 2)) | |
| ) | |
| (drop | |
| (call $good-5 (i32.const 1) (i32.const 2)) | |
| ) | |
| ) | |
| ) | |
| ;; CHECK: (func $byn-split-outlined-B$good (type $2) (param $x i32) (param $y i32) | |
| ;; CHECK-NEXT: (local.set $x | |
| ;; CHECK-NEXT: (i32.const 1337) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: (call $import) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK: (func $byn-split-outlined-B$good-5 (type $2) (param $x i32) (param $y i32) | |
| ;; CHECK-NEXT: (local.set $x | |
| ;; CHECK-NEXT: (i32.const 42) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: (call $import) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK: (func $byn-split-outlined-B$good-5_17 (type $2) (param $x i32) (param $y i32) | |
| ;; CHECK-NEXT: (local.set $x | |
| ;; CHECK-NEXT: (i32.const 42) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: (call $import) | |
| ;; CHECK-NEXT: ) |