1;;! target = "x86_64"
2;;! test = "optimize"
3
4;; When `call_indirect` is used in a loop with the same table index on every
5;; iteration, we can hoist part of the work out of the loop. This test tracks
6;; how much we're successfully pulling out.
7
8(module
9  (type $fn (func (result i32)))
10  (table $fnptrs 2 2 funcref)
11  (func (param i32)
12        loop
13          local.get 0
14          call_indirect $fnptrs (type $fn)
15          br 0
16        end)
17  (func
18        loop
19          i32.const 1
20          call_indirect $fnptrs (type $fn)
21          br 0
22        end)
23)
24
25;; function u0:0(i64 vmctx, i64, i32) tail {
26;;     gv0 = vmctx
27;;     gv1 = load.i64 notrap aligned readonly gv0+8
28;;     gv2 = load.i64 notrap aligned gv1+24
29;;     gv3 = vmctx
30;;     gv4 = load.i64 notrap aligned readonly can_move gv3+48
31;;     sig0 = (i64 vmctx, i64) -> i32 tail
32;;     sig1 = (i64 vmctx, i32, i64) -> i64 tail
33;;     fn0 = colocated u805306368:9 sig1
34;;     stack_limit = gv2
35;;
36;;                                 block0(v0: i64, v1: i64, v2: i32):
37;; @002b                               v4 = iconst.i32 2
38;; @002b                               v5 = icmp uge v2, v4  ; v4 = 2
39;; @002b                               v10 = iconst.i64 0
40;; @002b                               v7 = load.i64 notrap aligned readonly can_move v0+48
41;; @002b                               v6 = uextend.i64 v2
42;;                                     v29 = iconst.i64 3
43;; @002b                               v8 = ishl v6, v29  ; v29 = 3
44;; @002b                               v9 = iadd v7, v8
45;; @002b                               v11 = select_spectre_guard v5, v10, v9  ; v10 = 0
46;;                                     v28 = iconst.i64 -2
47;; @002b                               v15 = iconst.i32 0
48;; @002b                               v20 = load.i64 notrap aligned readonly can_move v0+40
49;; @002b                               v21 = load.i32 notrap aligned readonly can_move v20
50;; @0027                               jump block2
51;;
52;;                                 block2:
53;; @002b                               v12 = load.i64 user5 aligned table v11
54;;                                     v31 = iconst.i64 -2
55;;                                     v32 = band v12, v31  ; v31 = -2
56;; @002b                               brif v12, block5(v32), block4
57;;
58;;                                 block4 cold:
59;;                                     v33 = iconst.i32 0
60;; @002b                               v18 = call fn0(v0, v33, v6)  ; v33 = 0
61;; @002b                               jump block5(v18)
62;;
63;;                                 block5(v14: i64):
64;; @002b                               v22 = load.i32 user6 aligned readonly v14+16
65;; @002b                               v23 = icmp eq v22, v21
66;; @002b                               trapz v23, user7
67;; @002b                               v24 = load.i64 notrap aligned readonly v14+8
68;; @002b                               v25 = load.i64 notrap aligned readonly v14+24
69;; @002b                               v26 = call_indirect sig0, v24(v25, v0)
70;; @002e                               jump block2
71;; }
72;;
73;; function u0:1(i64 vmctx, i64) tail {
74;;     gv0 = vmctx
75;;     gv1 = load.i64 notrap aligned readonly gv0+8
76;;     gv2 = load.i64 notrap aligned gv1+24
77;;     gv3 = vmctx
78;;     gv4 = load.i64 notrap aligned readonly can_move gv3+48
79;;     sig0 = (i64 vmctx, i64) -> i32 tail
80;;     sig1 = (i64 vmctx, i32, i64) -> i64 tail
81;;     fn0 = colocated u805306368:9 sig1
82;;     stack_limit = gv2
83;;
84;;                                 block0(v0: i64, v1: i64):
85;; @0038                               v6 = load.i64 notrap aligned readonly can_move v0+48
86;;                                     v37 = iconst.i64 8
87;; @0038                               v8 = iadd v6, v37  ; v37 = 8
88;;                                     v26 = iconst.i64 -2
89;; @0038                               v14 = iconst.i32 0
90;;                                     v36 = iconst.i64 1
91;; @0038                               v19 = load.i64 notrap aligned readonly can_move v0+40
92;; @0038                               v20 = load.i32 notrap aligned readonly can_move v19
93;; @0034                               jump block2
94;;
95;;                                 block2:
96;;                                     v38 = iadd.i64 v6, v37  ; v37 = 8
97;; @0038                               v11 = load.i64 user5 aligned table v38
98;;                                     v39 = iconst.i64 -2
99;;                                     v40 = band v11, v39  ; v39 = -2
100;; @0038                               brif v11, block5(v40), block4
101;;
102;;                                 block4 cold:
103;;                                     v41 = iconst.i32 0
104;;                                     v42 = iconst.i64 1
105;; @0038                               v17 = call fn0(v0, v41, v42)  ; v41 = 0, v42 = 1
106;; @0038                               jump block5(v17)
107;;
108;;                                 block5(v13: i64):
109;; @0038                               v21 = load.i32 user6 aligned readonly v13+16
110;; @0038                               v22 = icmp eq v21, v20
111;; @0038                               trapz v22, user7
112;; @0038                               v23 = load.i64 notrap aligned readonly v13+8
113;; @0038                               v24 = load.i64 notrap aligned readonly v13+24
114;; @0038                               v25 = call_indirect sig0, v23(v24, v0)
115;; @003b                               jump block2
116;; }
117