| ;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited. |
| ;; RUN: wasm-opt %s -all --inlining --optimize-level=3 -S -o - | filecheck %s |
| |
| ;; Test that multi-use functions containing call_indirect or call_ref are recognized |
| ;; as having calls and are not inlined at -O3. Single-use functions should still be inlined. |
| |
| (module |
| ;; CHECK: (type $sig-ref (func (param anyref) (result i32))) |
| |
| ;; CHECK: (type $sig-i32 (func (param i32) (result i32))) |
| (type $sig-i32 (func (param i32) (result i32))) |
| (type $sig-ref (func (param (ref null any)) (result i32))) |
| (table 1 1 funcref) |
| |
| ;; CHECK: (export "caller" (func $caller)) |
| (export "caller" (func $caller)) |
| |
| ;; Multi-use function with call_indirect: should NOT be inlined. |
| ;; CHECK: (func $callee-indirect-multi (type $sig-i32) (param $x i32) (result i32) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (call_indirect $0 (type $sig-i32) |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $callee-indirect-multi (param $x i32) (result i32) |
| (drop (local.get $x)) |
| (drop (local.get $x)) |
| (call_indirect (type $sig-i32) |
| (local.get $x) |
| (i32.const 0) |
| ) |
| ) |
| |
| ;; Single-use function with call_indirect: should be inlined. |
| (func $callee-indirect-single (param $x i32) (result i32) |
| (drop (local.get $x)) |
| (drop (local.get $x)) |
| (call_indirect (type $sig-i32) |
| (local.get $x) |
| (i32.const 0) |
| ) |
| ) |
| |
| ;; Multi-use function with call_ref: should NOT be inlined. |
| ;; CHECK: (func $callee-ref-multi (type $2) (param $func (ref $sig-ref)) (param $arg anyref) (result i32) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (ref.is_null |
| ;; CHECK-NEXT: (local.get $arg) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (call_ref $sig-ref |
| ;; CHECK-NEXT: (local.get $arg) |
| ;; CHECK-NEXT: (local.get $func) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $callee-ref-multi (param $func (ref $sig-ref)) (param $arg (ref null any)) (result i32) |
| (drop (ref.is_null (local.get $arg))) |
| (call_ref $sig-ref |
| (local.get $arg) |
| (local.get $func) |
| ) |
| ) |
| |
| ;; Single-use function with call_ref: should be inlined. |
| (func $callee-ref-single (param $func (ref $sig-ref)) (param $arg (ref null any)) (result i32) |
| (drop (ref.is_null (local.get $arg))) |
| (call_ref $sig-ref |
| (local.get $arg) |
| (local.get $func) |
| ) |
| ) |
| |
| ;; CHECK: (func $caller (type $3) (param $x i32) (param $func (ref $sig-ref)) (param $arg anyref) (result i32) |
| ;; CHECK-NEXT: (local $3 i32) |
| ;; CHECK-NEXT: (local $4 (ref $sig-ref)) |
| ;; CHECK-NEXT: (local $5 anyref) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (call $callee-indirect-multi |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (call $callee-indirect-multi |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (block $__inlined_func$callee-indirect-single (result i32) |
| ;; CHECK-NEXT: (local.set $3 |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (block (result i32) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (local.get $3) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (local.get $3) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (call_indirect $0 (type $sig-i32) |
| ;; CHECK-NEXT: (local.get $3) |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (call $callee-ref-multi |
| ;; CHECK-NEXT: (local.get $func) |
| ;; CHECK-NEXT: (local.get $arg) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (call $callee-ref-multi |
| ;; CHECK-NEXT: (local.get $func) |
| ;; CHECK-NEXT: (local.get $arg) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (block $__inlined_func$callee-ref-single$1 (result i32) |
| ;; CHECK-NEXT: (local.set $4 |
| ;; CHECK-NEXT: (local.get $func) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (local.set $5 |
| ;; CHECK-NEXT: (local.get $arg) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (block (result i32) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (ref.is_null |
| ;; CHECK-NEXT: (local.get $5) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (call_ref $sig-ref |
| ;; CHECK-NEXT: (local.get $5) |
| ;; CHECK-NEXT: (local.get $4) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $caller (param $x i32) (param $func (ref $sig-ref)) (param $arg (ref null any)) (result i32) |
| (drop (call $callee-indirect-multi (local.get $x))) |
| (drop (call $callee-indirect-multi (local.get $x))) |
| (drop (call $callee-indirect-single (local.get $x))) |
| (drop (call $callee-ref-multi (local.get $func) (local.get $arg))) |
| (drop (call $callee-ref-multi (local.get $func) (local.get $arg))) |
| (call $callee-ref-single (local.get $func) (local.get $arg)) |
| ) |
| ) |