Browse Source
I found these tests useful in thinking about #8195, #8197, and #8200, so I thought we should track our codegen for these specific cases over time.pull/8203/head
Jamey Sharp
8 months ago
committed by
GitHub
2 changed files with 228 additions and 0 deletions
@ -0,0 +1,137 @@ |
|||
;;! target = "x86_64" |
|||
;;! test = "optimize" |
|||
|
|||
;; When `call_indirect` is used in a loop with the same table index on every |
|||
;; iteration, we can hoist part of the work out of the loop. This test tracks |
|||
;; how much we're successfully pulling out. |
|||
|
|||
(module |
|||
(type $fn (func (result i32))) |
|||
(table $fnptrs 2 2 funcref) |
|||
(func (param i32) |
|||
loop |
|||
local.get 0 |
|||
call_indirect $fnptrs (type $fn) |
|||
br 0 |
|||
end) |
|||
(func |
|||
loop |
|||
i32.const 1 |
|||
call_indirect $fnptrs (type $fn) |
|||
br 0 |
|||
end) |
|||
) |
|||
|
|||
;; function u0:0(i64 vmctx, i64, i32) fast { |
|||
;; gv0 = vmctx |
|||
;; gv1 = load.i64 notrap aligned readonly gv0+8 |
|||
;; gv2 = load.i64 notrap aligned gv1 |
|||
;; gv3 = vmctx |
|||
;; gv4 = load.i64 notrap aligned gv3+72 |
|||
;; sig0 = (i64 vmctx, i64) -> i32 fast |
|||
;; sig1 = (i64 vmctx, i32 uext, i32 uext) -> i64 system_v |
|||
;; stack_limit = gv2 |
|||
;; |
|||
;; block0(v0: i64, v1: i64, v2: i32): |
|||
;; v16 -> v0 |
|||
;; v20 -> v0 |
|||
;; v29 -> v0 |
|||
;; v3 -> v2 |
|||
;; v28 -> v3 |
|||
;; @002b v4 = iconst.i32 2 |
|||
;; @002b v5 = icmp uge v2, v4 ; v4 = 2 |
|||
;; @002b v10 = iconst.i64 0 |
|||
;; @002b v6 = uextend.i64 v2 |
|||
;; v30 = iconst.i64 3 |
|||
;; @002b v8 = ishl v6, v30 ; v30 = 3 |
|||
;; v31 = iconst.i64 -2 |
|||
;; @002b v17 = load.i64 notrap aligned readonly v0+56 |
|||
;; @002b v18 = load.i64 notrap aligned readonly v17+72 |
|||
;; @002b v15 = iconst.i32 0 |
|||
;; @002b v21 = load.i64 notrap aligned readonly v0+64 |
|||
;; @002b v22 = load.i32 notrap aligned readonly v21 |
|||
;; @0027 jump block2 |
|||
;; |
|||
;; block2: |
|||
;; @002b v7 = load.i64 notrap aligned v0+72 |
|||
;; @002b v9 = iadd v7, v8 |
|||
;; v32 = iconst.i64 0 |
|||
;; v33 = select_spectre_guard v5, v32, v9 ; v32 = 0 |
|||
;; @002b v12 = load.i64 table_oob aligned table v33 |
|||
;; v34 = iconst.i64 -2 |
|||
;; v35 = band v12, v34 ; v34 = -2 |
|||
;; @002b brif v12, block5(v35), block4 |
|||
;; |
|||
;; block4 cold: |
|||
;; v36 = iconst.i32 0 |
|||
;; @002b v19 = call_indirect.i64 sig1, v18(v0, v36, v2) ; v36 = 0 |
|||
;; @002b jump block5(v19) |
|||
;; |
|||
;; block5(v14: i64): |
|||
;; @002b v23 = load.i32 icall_null aligned readonly v14+24 |
|||
;; @002b v24 = icmp eq v23, v22 |
|||
;; @002b brif v24, block7, block6 |
|||
;; |
|||
;; block6 cold: |
|||
;; @002b trap bad_sig |
|||
;; |
|||
;; block7: |
|||
;; @002b v25 = load.i64 notrap aligned readonly v14+16 |
|||
;; @002b v26 = load.i64 notrap aligned readonly v14+32 |
|||
;; @002b v27 = call_indirect sig0, v25(v26, v0) |
|||
;; @002e jump block2 |
|||
;; } |
|||
;; |
|||
;; function u0:1(i64 vmctx, i64) fast { |
|||
;; gv0 = vmctx |
|||
;; gv1 = load.i64 notrap aligned readonly gv0+8 |
|||
;; gv2 = load.i64 notrap aligned gv1 |
|||
;; gv3 = vmctx |
|||
;; gv4 = load.i64 notrap aligned gv3+72 |
|||
;; sig0 = (i64 vmctx, i64) -> i32 fast |
|||
;; sig1 = (i64 vmctx, i32 uext, i32 uext) -> i64 system_v |
|||
;; stack_limit = gv2 |
|||
;; |
|||
;; block0(v0: i64, v1: i64): |
|||
;; v15 -> v0 |
|||
;; v19 -> v0 |
|||
;; v27 -> v0 |
|||
;; v38 = iconst.i64 8 |
|||
;; v29 = iconst.i64 -2 |
|||
;; @0038 v16 = load.i64 notrap aligned readonly v0+56 |
|||
;; @0038 v17 = load.i64 notrap aligned readonly v16+72 |
|||
;; @0038 v14 = iconst.i32 0 |
|||
;; @0036 v2 = iconst.i32 1 |
|||
;; @0038 v20 = load.i64 notrap aligned readonly v0+64 |
|||
;; @0038 v21 = load.i32 notrap aligned readonly v20 |
|||
;; @0034 jump block2 |
|||
;; |
|||
;; block2: |
|||
;; @0038 v6 = load.i64 notrap aligned v0+72 |
|||
;; v39 = iconst.i64 8 |
|||
;; v40 = iadd v6, v39 ; v39 = 8 |
|||
;; @0038 v11 = load.i64 table_oob aligned table v40 |
|||
;; v41 = iconst.i64 -2 |
|||
;; v42 = band v11, v41 ; v41 = -2 |
|||
;; @0038 brif v11, block5(v42), block4 |
|||
;; |
|||
;; block4 cold: |
|||
;; v43 = iconst.i32 0 |
|||
;; v44 = iconst.i32 1 |
|||
;; @0038 v18 = call_indirect.i64 sig1, v17(v0, v43, v44) ; v43 = 0, v44 = 1 |
|||
;; @0038 jump block5(v18) |
|||
;; |
|||
;; block5(v13: i64): |
|||
;; @0038 v22 = load.i32 icall_null aligned readonly v13+24 |
|||
;; @0038 v23 = icmp eq v22, v21 |
|||
;; @0038 brif v23, block7, block6 |
|||
;; |
|||
;; block6 cold: |
|||
;; @0038 trap bad_sig |
|||
;; |
|||
;; block7: |
|||
;; @0038 v24 = load.i64 notrap aligned readonly v13+16 |
|||
;; @0038 v25 = load.i64 notrap aligned readonly v13+32 |
|||
;; @0038 v26 = call_indirect sig0, v24(v25, v0) |
|||
;; @003b jump block2 |
|||
;; } |
@ -0,0 +1,91 @@ |
|||
;;! target = "x86_64" |
|||
;;! test = "optimize" |
|||
|
|||
;; Current WebAssembly toolchains represent source-language function pointers |
|||
;; by constructing a single WebAssembly funcref table, initializing it with an |
|||
;; element section, and never writing to it again. This test tracks what code |
|||
;; we generate for that pattern. |
|||
|
|||
;; Motivated by https://github.com/bytecodealliance/wasmtime/issues/8195 |
|||
|
|||
(module |
|||
(type $fn (func)) |
|||
(table $fnptrs 2 2 funcref) |
|||
(func $callee) |
|||
(func $caller (param i32) |
|||
local.get 0 |
|||
call_indirect $fnptrs (type $fn)) |
|||
(elem $fnptrs (i32.const 1) func $callee) |
|||
) |
|||
|
|||
;; function u0:0(i64 vmctx, i64) fast { |
|||
;; gv0 = vmctx |
|||
;; gv1 = load.i64 notrap aligned readonly gv0+8 |
|||
;; gv2 = load.i64 notrap aligned gv1 |
|||
;; sig0 = (i64 vmctx, i32 uext, i32 uext) -> i32 uext system_v |
|||
;; sig1 = (i64 vmctx, i32 uext) -> i32 uext system_v |
|||
;; stack_limit = gv2 |
|||
;; |
|||
;; block0(v0: i64, v1: i64): |
|||
;; @002c jump block1 |
|||
;; |
|||
;; block1: |
|||
;; @002c return |
|||
;; } |
|||
;; |
|||
;; function u0:1(i64 vmctx, i64, i32) fast { |
|||
;; gv0 = vmctx |
|||
;; gv1 = load.i64 notrap aligned readonly gv0+8 |
|||
;; gv2 = load.i64 notrap aligned gv1 |
|||
;; gv3 = vmctx |
|||
;; gv4 = load.i64 notrap aligned gv3+72 |
|||
;; sig0 = (i64 vmctx, i64) fast |
|||
;; sig1 = (i64 vmctx, i32 uext, i32 uext) -> i64 system_v |
|||
;; sig2 = (i64 vmctx, i32 uext, i32 uext) -> i32 uext system_v |
|||
;; sig3 = (i64 vmctx, i32 uext) -> i32 uext system_v |
|||
;; stack_limit = gv2 |
|||
;; |
|||
;; block0(v0: i64, v1: i64, v2: i32): |
|||
;; v15 -> v0 |
|||
;; v19 -> v0 |
|||
;; v26 -> v0 |
|||
;; @0031 v6 = load.i64 notrap aligned v0+72 |
|||
;; @0031 v3 = iconst.i32 2 |
|||
;; @0031 v4 = icmp uge v2, v3 ; v3 = 2 |
|||
;; @0031 v9 = iconst.i64 0 |
|||
;; @0031 v5 = uextend.i64 v2 |
|||
;; v27 = iconst.i64 3 |
|||
;; @0031 v7 = ishl v5, v27 ; v27 = 3 |
|||
;; @0031 v8 = iadd v6, v7 |
|||
;; @0031 v10 = select_spectre_guard v4, v9, v8 ; v9 = 0 |
|||
;; @0031 v11 = load.i64 table_oob aligned table v10 |
|||
;; v28 = iconst.i64 -2 |
|||
;; @0031 v12 = band v11, v28 ; v28 = -2 |
|||
;; @0031 brif v11, block3(v12), block2 |
|||
;; |
|||
;; block2 cold: |
|||
;; @0031 v16 = load.i64 notrap aligned readonly v0+56 |
|||
;; @0031 v17 = load.i64 notrap aligned readonly v16+72 |
|||
;; @0031 v14 = iconst.i32 0 |
|||
;; @0031 v18 = call_indirect sig1, v17(v0, v14, v2) ; v14 = 0 |
|||
;; @0031 jump block3(v18) |
|||
;; |
|||
;; block3(v13: i64): |
|||
;; @0031 v22 = load.i32 icall_null aligned readonly v13+24 |
|||
;; @0031 v20 = load.i64 notrap aligned readonly v0+64 |
|||
;; @0031 v21 = load.i32 notrap aligned readonly v20 |
|||
;; @0031 v23 = icmp eq v22, v21 |
|||
;; @0031 brif v23, block5, block4 |
|||
;; |
|||
;; block4 cold: |
|||
;; @0031 trap bad_sig |
|||
;; |
|||
;; block5: |
|||
;; @0031 v24 = load.i64 notrap aligned readonly v13+16 |
|||
;; @0031 v25 = load.i64 notrap aligned readonly v13+32 |
|||
;; @0031 call_indirect sig0, v24(v25, v0) |
|||
;; @0034 jump block1 |
|||
;; |
|||
;; block1: |
|||
;; @0034 return |
|||
;; } |
Loading…
Reference in new issue