diff --git a/tests/disas/icall-loop.wat b/tests/disas/icall-loop.wat new file mode 100644 index 000000000000..96a3a09f7a99 --- /dev/null +++ b/tests/disas/icall-loop.wat @@ -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 +;; } diff --git a/tests/disas/readonly-funcrefs.wat b/tests/disas/readonly-funcrefs.wat new file mode 100644 index 000000000000..c3d3826162ff --- /dev/null +++ b/tests/disas/readonly-funcrefs.wat @@ -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 +;; }