;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. ;; As in monomorphize-types.wast, test in both "always" mode, which always ;; monomorphizes, and in "careful" mode which does it only when it appears to ;; actually help. ;; RUN: foreach %s %t wasm-opt --monomorphize-always -all -S -o - | filecheck %s --check-prefix ALWAYS ;; RUN: foreach %s %t wasm-opt --monomorphize -all -S -o - | filecheck %s --check-prefix CAREFUL (module ;; ALWAYS: (type $0 (func)) ;; ALWAYS: (type $1 (func (param i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32))) ;; ALWAYS: (func $caller-consts (type $0) ;; ALWAYS-NEXT: (call $many-params_3) ;; ALWAYS-NEXT: ) ;; CAREFUL: (type $0 (func)) ;; CAREFUL: (type $1 (func (param i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32))) ;; CAREFUL: (func $caller-consts (type $0) ;; CAREFUL-NEXT: (call $many-params_3) ;; CAREFUL-NEXT: ) (func $caller-consts ;; The called func has a large number of params, in fact too many for us to ;; allow in monomorphized functions. However, all the params are constant, ;; so they go into the call context and are no longer params, and we can ;; optimize. (call $many-params (i32.const 0) (i32.const 0) (i32.const 0) (i32.const 0) (i32.const 0) (i32.const 5) (i32.const 5) (i32.const 5) (i32.const 5) (i32.const 5) (i32.const 15) (i32.const 15) (i32.const 15) (i32.const 15) (i32.const 15) (i32.const 20) (i32.const 20) (i32.const 20) (i32.const 20) (i32.const 20) (i32.const 25) (i32.const 25) (i32.const 25) (i32.const 25) (i32.const 25) ) ) ;; ALWAYS: (func $caller-locals (type $1) (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32) (param $4 i32) (param $5 i32) (param $6 i32) (param $7 i32) (param $8 i32) (param $9 i32) (param $10 i32) (param $11 i32) (param $12 i32) (param $13 i32) (param $14 i32) (param $15 i32) (param $16 i32) (param $17 i32) (param $18 i32) (param $19 i32) (param $20 i32) (param $21 i32) (param $22 i32) (param $23 i32) (param $24 i32) ;; ALWAYS-NEXT: (call $many-params ;; ALWAYS-NEXT: (local.get $0) ;; ALWAYS-NEXT: (local.get $1) ;; ALWAYS-NEXT: (local.get $2) ;; ALWAYS-NEXT: (local.get $3) ;; ALWAYS-NEXT: (local.get $4) ;; ALWAYS-NEXT: (local.get $5) ;; ALWAYS-NEXT: (local.get $6) ;; ALWAYS-NEXT: (local.get $7) ;; ALWAYS-NEXT: (local.get $8) ;; ALWAYS-NEXT: (local.get $9) ;; ALWAYS-NEXT: (local.get $10) ;; ALWAYS-NEXT: (local.get $11) ;; ALWAYS-NEXT: (local.get $12) ;; ALWAYS-NEXT: (local.get $13) ;; ALWAYS-NEXT: (local.get $14) ;; ALWAYS-NEXT: (local.get $15) ;; ALWAYS-NEXT: (local.get $16) ;; ALWAYS-NEXT: (local.get $17) ;; ALWAYS-NEXT: (local.get $18) ;; ALWAYS-NEXT: (local.get $19) ;; ALWAYS-NEXT: (local.get $20) ;; ALWAYS-NEXT: (local.get $21) ;; ALWAYS-NEXT: (local.get $22) ;; ALWAYS-NEXT: (local.get $23) ;; ALWAYS-NEXT: (local.get $24) ;; ALWAYS-NEXT: ) ;; ALWAYS-NEXT: ) ;; CAREFUL: (func $caller-locals (type $1) (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32) (param $4 i32) (param $5 i32) (param $6 i32) (param $7 i32) (param $8 i32) (param $9 i32) (param $10 i32) (param $11 i32) (param $12 i32) (param $13 i32) (param $14 i32) (param $15 i32) (param $16 i32) (param $17 i32) (param $18 i32) (param $19 i32) (param $20 i32) (param $21 i32) (param $22 i32) (param $23 i32) (param $24 i32) ;; CAREFUL-NEXT: (call $many-params ;; CAREFUL-NEXT: (local.get $0) ;; CAREFUL-NEXT: (local.get $1) ;; CAREFUL-NEXT: (local.get $2) ;; CAREFUL-NEXT: (local.get $3) ;; CAREFUL-NEXT: (local.get $4) ;; CAREFUL-NEXT: (local.get $5) ;; CAREFUL-NEXT: (local.get $6) ;; CAREFUL-NEXT: (local.get $7) ;; CAREFUL-NEXT: (local.get $8) ;; CAREFUL-NEXT: (local.get $9) ;; CAREFUL-NEXT: (local.get $10) ;; CAREFUL-NEXT: (local.get $11) ;; CAREFUL-NEXT: (local.get $12) ;; CAREFUL-NEXT: (local.get $13) ;; CAREFUL-NEXT: (local.get $14) ;; CAREFUL-NEXT: (local.get $15) ;; CAREFUL-NEXT: (local.get $16) ;; CAREFUL-NEXT: (local.get $17) ;; CAREFUL-NEXT: (local.get $18) ;; CAREFUL-NEXT: (local.get $19) ;; CAREFUL-NEXT: (local.get $20) ;; CAREFUL-NEXT: (local.get $21) ;; CAREFUL-NEXT: (local.get $22) ;; CAREFUL-NEXT: (local.get $23) ;; CAREFUL-NEXT: (local.get $24) ;; CAREFUL-NEXT: ) ;; CAREFUL-NEXT: ) (func $caller-locals (param i32) (param i32) (param i32) (param i32) (param i32) (param i32) (param i32) (param i32) (param i32) (param i32) (param i32) (param i32) (param i32) (param i32) (param i32) (param i32) (param i32) (param i32) (param i32) (param i32) (param i32) (param i32) (param i32) (param i32) (param i32) ;; As above, but now we send unknown local values. These would remain as ;; parameters, so we do not optimize. (call $many-params (local.get 0) (local.get 1) (local.get 2) (local.get 3) (local.get 4) (local.get 5) (local.get 6) (local.get 7) (local.get 8) (local.get 9) (local.get 10) (local.get 11) (local.get 12) (local.get 13) (local.get 14) (local.get 15) (local.get 16) (local.get 17) (local.get 18) (local.get 19) (local.get 20) (local.get 21) (local.get 22) (local.get 23) (local.get 24) ) ) ;; ALWAYS: (func $many-params (type $1) (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32) (param $4 i32) (param $5 i32) (param $6 i32) (param $7 i32) (param $8 i32) (param $9 i32) (param $10 i32) (param $11 i32) (param $12 i32) (param $13 i32) (param $14 i32) (param $15 i32) (param $16 i32) (param $17 i32) (param $18 i32) (param $19 i32) (param $20 i32) (param $21 i32) (param $22 i32) (param $23 i32) (param $24 i32) ;; ALWAYS-NEXT: ) ;; CAREFUL: (func $many-params (type $1) (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32) (param $4 i32) (param $5 i32) (param $6 i32) (param $7 i32) (param $8 i32) (param $9 i32) (param $10 i32) (param $11 i32) (param $12 i32) (param $13 i32) (param $14 i32) (param $15 i32) (param $16 i32) (param $17 i32) (param $18 i32) (param $19 i32) (param $20 i32) (param $21 i32) (param $22 i32) (param $23 i32) (param $24 i32) ;; CAREFUL-NEXT: (nop) ;; CAREFUL-NEXT: ) (func $many-params (param i32) (param i32) (param i32) (param i32) (param i32) (param i32) (param i32) (param i32) (param i32) (param i32) (param i32) (param i32) (param i32) (param i32) (param i32) (param i32) (param i32) (param i32) (param i32) (param i32) (param i32) (param i32) (param i32) (param i32) (param i32) ) ) ;; ALWAYS: (func $many-params_3 (type $0) ;; ALWAYS-NEXT: (local $0 i32) ;; ALWAYS-NEXT: (local $1 i32) ;; ALWAYS-NEXT: (local $2 i32) ;; ALWAYS-NEXT: (local $3 i32) ;; ALWAYS-NEXT: (local $4 i32) ;; ALWAYS-NEXT: (local $5 i32) ;; ALWAYS-NEXT: (local $6 i32) ;; ALWAYS-NEXT: (local $7 i32) ;; ALWAYS-NEXT: (local $8 i32) ;; ALWAYS-NEXT: (local $9 i32) ;; ALWAYS-NEXT: (local $10 i32) ;; ALWAYS-NEXT: (local $11 i32) ;; ALWAYS-NEXT: (local $12 i32) ;; ALWAYS-NEXT: (local $13 i32) ;; ALWAYS-NEXT: (local $14 i32) ;; ALWAYS-NEXT: (local $15 i32) ;; ALWAYS-NEXT: (local $16 i32) ;; ALWAYS-NEXT: (local $17 i32) ;; ALWAYS-NEXT: (local $18 i32) ;; ALWAYS-NEXT: (local $19 i32) ;; ALWAYS-NEXT: (local $20 i32) ;; ALWAYS-NEXT: (local $21 i32) ;; ALWAYS-NEXT: (local $22 i32) ;; ALWAYS-NEXT: (local $23 i32) ;; ALWAYS-NEXT: (local $24 i32) ;; ALWAYS-NEXT: (local.set $0 ;; ALWAYS-NEXT: (i32.const 0) ;; ALWAYS-NEXT: ) ;; ALWAYS-NEXT: (local.set $1 ;; ALWAYS-NEXT: (i32.const 0) ;; ALWAYS-NEXT: ) ;; ALWAYS-NEXT: (local.set $2 ;; ALWAYS-NEXT: (i32.const 0) ;; ALWAYS-NEXT: ) ;; ALWAYS-NEXT: (local.set $3 ;; ALWAYS-NEXT: (i32.const 0) ;; ALWAYS-NEXT: ) ;; ALWAYS-NEXT: (local.set $4 ;; ALWAYS-NEXT: (i32.const 0) ;; ALWAYS-NEXT: ) ;; ALWAYS-NEXT: (local.set $5 ;; ALWAYS-NEXT: (i32.const 5) ;; ALWAYS-NEXT: ) ;; ALWAYS-NEXT: (local.set $6 ;; ALWAYS-NEXT: (i32.const 5) ;; ALWAYS-NEXT: ) ;; ALWAYS-NEXT: (local.set $7 ;; ALWAYS-NEXT: (i32.const 5) ;; ALWAYS-NEXT: ) ;; ALWAYS-NEXT: (local.set $8 ;; ALWAYS-NEXT: (i32.const 5) ;; ALWAYS-NEXT: ) ;; ALWAYS-NEXT: (local.set $9 ;; ALWAYS-NEXT: (i32.const 5) ;; ALWAYS-NEXT: ) ;; ALWAYS-NEXT: (local.set $10 ;; ALWAYS-NEXT: (i32.const 15) ;; ALWAYS-NEXT: ) ;; ALWAYS-NEXT: (local.set $11 ;; ALWAYS-NEXT: (i32.const 15) ;; ALWAYS-NEXT: ) ;; ALWAYS-NEXT: (local.set $12 ;; ALWAYS-NEXT: (i32.const 15) ;; ALWAYS-NEXT: ) ;; ALWAYS-NEXT: (local.set $13 ;; ALWAYS-NEXT: (i32.const 15) ;; ALWAYS-NEXT: ) ;; ALWAYS-NEXT: (local.set $14 ;; ALWAYS-NEXT: (i32.const 15) ;; ALWAYS-NEXT: ) ;; ALWAYS-NEXT: (local.set $15 ;; ALWAYS-NEXT: (i32.const 20) ;; ALWAYS-NEXT: ) ;; ALWAYS-NEXT: (local.set $16 ;; ALWAYS-NEXT: (i32.const 20) ;; ALWAYS-NEXT: ) ;; ALWAYS-NEXT: (local.set $17 ;; ALWAYS-NEXT: (i32.const 20) ;; ALWAYS-NEXT: ) ;; ALWAYS-NEXT: (local.set $18 ;; ALWAYS-NEXT: (i32.const 20) ;; ALWAYS-NEXT: ) ;; ALWAYS-NEXT: (local.set $19 ;; ALWAYS-NEXT: (i32.const 20) ;; ALWAYS-NEXT: ) ;; ALWAYS-NEXT: (local.set $20 ;; ALWAYS-NEXT: (i32.const 25) ;; ALWAYS-NEXT: ) ;; ALWAYS-NEXT: (local.set $21 ;; ALWAYS-NEXT: (i32.const 25) ;; ALWAYS-NEXT: ) ;; ALWAYS-NEXT: (local.set $22 ;; ALWAYS-NEXT: (i32.const 25) ;; ALWAYS-NEXT: ) ;; ALWAYS-NEXT: (local.set $23 ;; ALWAYS-NEXT: (i32.const 25) ;; ALWAYS-NEXT: ) ;; ALWAYS-NEXT: (local.set $24 ;; ALWAYS-NEXT: (i32.const 25) ;; ALWAYS-NEXT: ) ;; ALWAYS-NEXT: (block ;; ALWAYS-NEXT: ) ;; ALWAYS-NEXT: ) ;; CAREFUL: (func $many-params_3 (type $0) ;; CAREFUL-NEXT: (nop) ;; CAREFUL-NEXT: ) (module ;; ALWAYS: (type $array (array (mut i32))) ;; CAREFUL: (type $array (array (mut i32))) (type $array (array (mut i32))) ;; ALWAYS: (type $1 (func)) ;; ALWAYS: (type $2 (func (param i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32))) ;; ALWAYS: (type $3 (func (param (ref $array)))) ;; ALWAYS: (func $caller-consts (type $1) ;; ALWAYS-NEXT: (call $target_3) ;; ALWAYS-NEXT: ) ;; CAREFUL: (type $1 (func)) ;; CAREFUL: (type $2 (func (param i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32))) ;; CAREFUL: (type $3 (func (param (ref $array)))) ;; CAREFUL: (func $caller-consts (type $1) ;; CAREFUL-NEXT: (call $target_3) ;; CAREFUL-NEXT: ) (func $caller-consts ;; The called function has just one param, but the value sent has many ;; children of its own. Here the children are constant, so they go into the ;; call context, and we can optimize. (call $target (array.new_fixed $array 25 (i32.const 0) (i32.const 0) (i32.const 0) (i32.const 0) (i32.const 0) (i32.const 5) (i32.const 5) (i32.const 5) (i32.const 5) (i32.const 5) (i32.const 15) (i32.const 15) (i32.const 15) (i32.const 15) (i32.const 15) (i32.const 20) (i32.const 20) (i32.const 20) (i32.const 20) (i32.const 20) (i32.const 25) (i32.const 25) (i32.const 25) (i32.const 25) (i32.const 25) ) ) ) ;; ALWAYS: (func $caller-locals (type $2) (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32) (param $4 i32) (param $5 i32) (param $6 i32) (param $7 i32) (param $8 i32) (param $9 i32) (param $10 i32) (param $11 i32) (param $12 i32) (param $13 i32) (param $14 i32) (param $15 i32) (param $16 i32) (param $17 i32) (param $18 i32) (param $19 i32) (param $20 i32) (param $21 i32) (param $22 i32) (param $23 i32) (param $24 i32) ;; ALWAYS-NEXT: (call $target ;; ALWAYS-NEXT: (array.new_fixed $array 25 ;; ALWAYS-NEXT: (local.get $0) ;; ALWAYS-NEXT: (local.get $1) ;; ALWAYS-NEXT: (local.get $2) ;; ALWAYS-NEXT: (local.get $3) ;; ALWAYS-NEXT: (local.get $4) ;; ALWAYS-NEXT: (local.get $5) ;; ALWAYS-NEXT: (local.get $6) ;; ALWAYS-NEXT: (local.get $7) ;; ALWAYS-NEXT: (local.get $8) ;; ALWAYS-NEXT: (local.get $9) ;; ALWAYS-NEXT: (local.get $10) ;; ALWAYS-NEXT: (local.get $11) ;; ALWAYS-NEXT: (local.get $12) ;; ALWAYS-NEXT: (local.get $13) ;; ALWAYS-NEXT: (local.get $14) ;; ALWAYS-NEXT: (local.get $15) ;; ALWAYS-NEXT: (local.get $16) ;; ALWAYS-NEXT: (local.get $17) ;; ALWAYS-NEXT: (local.get $18) ;; ALWAYS-NEXT: (local.get $19) ;; ALWAYS-NEXT: (local.get $20) ;; ALWAYS-NEXT: (local.get $21) ;; ALWAYS-NEXT: (local.get $22) ;; ALWAYS-NEXT: (local.get $23) ;; ALWAYS-NEXT: (local.get $24) ;; ALWAYS-NEXT: ) ;; ALWAYS-NEXT: ) ;; ALWAYS-NEXT: ) ;; CAREFUL: (func $caller-locals (type $2) (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32) (param $4 i32) (param $5 i32) (param $6 i32) (param $7 i32) (param $8 i32) (param $9 i32) (param $10 i32) (param $11 i32) (param $12 i32) (param $13 i32) (param $14 i32) (param $15 i32) (param $16 i32) (param $17 i32) (param $18 i32) (param $19 i32) (param $20 i32) (param $21 i32) (param $22 i32) (param $23 i32) (param $24 i32) ;; CAREFUL-NEXT: (call $target ;; CAREFUL-NEXT: (array.new_fixed $array 25 ;; CAREFUL-NEXT: (local.get $0) ;; CAREFUL-NEXT: (local.get $1) ;; CAREFUL-NEXT: (local.get $2) ;; CAREFUL-NEXT: (local.get $3) ;; CAREFUL-NEXT: (local.get $4) ;; CAREFUL-NEXT: (local.get $5) ;; CAREFUL-NEXT: (local.get $6) ;; CAREFUL-NEXT: (local.get $7) ;; CAREFUL-NEXT: (local.get $8) ;; CAREFUL-NEXT: (local.get $9) ;; CAREFUL-NEXT: (local.get $10) ;; CAREFUL-NEXT: (local.get $11) ;; CAREFUL-NEXT: (local.get $12) ;; CAREFUL-NEXT: (local.get $13) ;; CAREFUL-NEXT: (local.get $14) ;; CAREFUL-NEXT: (local.get $15) ;; CAREFUL-NEXT: (local.get $16) ;; CAREFUL-NEXT: (local.get $17) ;; CAREFUL-NEXT: (local.get $18) ;; CAREFUL-NEXT: (local.get $19) ;; CAREFUL-NEXT: (local.get $20) ;; CAREFUL-NEXT: (local.get $21) ;; CAREFUL-NEXT: (local.get $22) ;; CAREFUL-NEXT: (local.get $23) ;; CAREFUL-NEXT: (local.get $24) ;; CAREFUL-NEXT: ) ;; CAREFUL-NEXT: ) ;; CAREFUL-NEXT: ) (func $caller-locals (param i32) (param i32) (param i32) (param i32) (param i32) (param i32) (param i32) (param i32) (param i32) (param i32) (param i32) (param i32) (param i32) (param i32) (param i32) (param i32) (param i32) (param i32) (param i32) (param i32) (param i32) (param i32) (param i32) (param i32) (param i32) ;; As above, but now we send unknown local values in the nested child. Those ;; would remain as parameters, so we do not optimize. (call $target (array.new_fixed $array 25 (local.get 0) (local.get 1) (local.get 2) (local.get 3) (local.get 4) (local.get 5) (local.get 6) (local.get 7) (local.get 8) (local.get 9) (local.get 10) (local.get 11) (local.get 12) (local.get 13) (local.get 14) (local.get 15) (local.get 16) (local.get 17) (local.get 18) (local.get 19) (local.get 20) (local.get 21) (local.get 22) (local.get 23) (local.get 24) ) ) ) ;; ALWAYS: (func $target (type $3) (param $array (ref $array)) ;; ALWAYS-NEXT: ) ;; CAREFUL: (func $target (type $3) (param $0 (ref $array)) ;; CAREFUL-NEXT: (nop) ;; CAREFUL-NEXT: ) (func $target (param $array (ref $array)) ) ) ;; ALWAYS: (func $target_3 (type $1) ;; ALWAYS-NEXT: (local $array (ref $array)) ;; ALWAYS-NEXT: (local.set $array ;; ALWAYS-NEXT: (array.new_fixed $array 25 ;; ALWAYS-NEXT: (i32.const 0) ;; ALWAYS-NEXT: (i32.const 0) ;; ALWAYS-NEXT: (i32.const 0) ;; ALWAYS-NEXT: (i32.const 0) ;; ALWAYS-NEXT: (i32.const 0) ;; ALWAYS-NEXT: (i32.const 5) ;; ALWAYS-NEXT: (i32.const 5) ;; ALWAYS-NEXT: (i32.const 5) ;; ALWAYS-NEXT: (i32.const 5) ;; ALWAYS-NEXT: (i32.const 5) ;; ALWAYS-NEXT: (i32.const 15) ;; ALWAYS-NEXT: (i32.const 15) ;; ALWAYS-NEXT: (i32.const 15) ;; ALWAYS-NEXT: (i32.const 15) ;; ALWAYS-NEXT: (i32.const 15) ;; ALWAYS-NEXT: (i32.const 20) ;; ALWAYS-NEXT: (i32.const 20) ;; ALWAYS-NEXT: (i32.const 20) ;; ALWAYS-NEXT: (i32.const 20) ;; ALWAYS-NEXT: (i32.const 20) ;; ALWAYS-NEXT: (i32.const 25) ;; ALWAYS-NEXT: (i32.const 25) ;; ALWAYS-NEXT: (i32.const 25) ;; ALWAYS-NEXT: (i32.const 25) ;; ALWAYS-NEXT: (i32.const 25) ;; ALWAYS-NEXT: ) ;; ALWAYS-NEXT: ) ;; ALWAYS-NEXT: (block ;; ALWAYS-NEXT: ) ;; ALWAYS-NEXT: ) ;; CAREFUL: (func $target_3 (type $1) ;; CAREFUL-NEXT: (nop) ;; CAREFUL-NEXT: )