1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2; RUN: llc -amdgpu-fixed-function-abi -mtriple=amdgcn-amd-amdhsa --amdhsa-code-object-version=2 -verify-machineinstrs < %s | FileCheck -check-prefix=GCN %s
3
4@gv.fptr0 = external hidden unnamed_addr addrspace(4) constant void()*, align 4
5@gv.fptr1 = external hidden unnamed_addr addrspace(4) constant void(i32)*, align 4
6
7define amdgpu_kernel void @test_indirect_call_sgpr_ptr() {
8; GCN-LABEL: test_indirect_call_sgpr_ptr:
9; GCN:         .amd_kernel_code_t
10; GCN-NEXT:     amd_code_version_major = 1
11; GCN-NEXT:     amd_code_version_minor = 2
12; GCN-NEXT:     amd_machine_kind = 1
13; GCN-NEXT:     amd_machine_version_major = 7
14; GCN-NEXT:     amd_machine_version_minor = 0
15; GCN-NEXT:     amd_machine_version_stepping = 0
16; GCN-NEXT:     kernel_code_entry_byte_offset = 256
17; GCN-NEXT:     kernel_code_prefetch_byte_size = 0
18; GCN-NEXT:     granulated_workitem_vgpr_count = 7
19; GCN-NEXT:     granulated_wavefront_sgpr_count = 4
20; GCN-NEXT:     priority = 0
21; GCN-NEXT:     float_mode = 240
22; GCN-NEXT:     priv = 0
23; GCN-NEXT:     enable_dx10_clamp = 1
24; GCN-NEXT:     debug_mode = 0
25; GCN-NEXT:     enable_ieee_mode = 1
26; GCN-NEXT:     enable_wgp_mode = 0
27; GCN-NEXT:     enable_mem_ordered = 0
28; GCN-NEXT:     enable_fwd_progress = 0
29; GCN-NEXT:     enable_sgpr_private_segment_wave_byte_offset = 1
30; GCN-NEXT:     user_sgpr_count = 14
31; GCN-NEXT:     enable_trap_handler = 0
32; GCN-NEXT:     enable_sgpr_workgroup_id_x = 1
33; GCN-NEXT:     enable_sgpr_workgroup_id_y = 1
34; GCN-NEXT:     enable_sgpr_workgroup_id_z = 1
35; GCN-NEXT:     enable_sgpr_workgroup_info = 0
36; GCN-NEXT:     enable_vgpr_workitem_id = 2
37; GCN-NEXT:     enable_exception_msb = 0
38; GCN-NEXT:     granulated_lds_size = 0
39; GCN-NEXT:     enable_exception = 0
40; GCN-NEXT:     enable_sgpr_private_segment_buffer = 1
41; GCN-NEXT:     enable_sgpr_dispatch_ptr = 1
42; GCN-NEXT:     enable_sgpr_queue_ptr = 1
43; GCN-NEXT:     enable_sgpr_kernarg_segment_ptr = 1
44; GCN-NEXT:     enable_sgpr_dispatch_id = 1
45; GCN-NEXT:     enable_sgpr_flat_scratch_init = 1
46; GCN-NEXT:     enable_sgpr_private_segment_size = 0
47; GCN-NEXT:     enable_sgpr_grid_workgroup_count_x = 0
48; GCN-NEXT:     enable_sgpr_grid_workgroup_count_y = 0
49; GCN-NEXT:     enable_sgpr_grid_workgroup_count_z = 0
50; GCN-NEXT:     enable_wavefront_size32 = 0
51; GCN-NEXT:     enable_ordered_append_gds = 0
52; GCN-NEXT:     private_element_size = 1
53; GCN-NEXT:     is_ptr64 = 1
54; GCN-NEXT:     is_dynamic_callstack = 1
55; GCN-NEXT:     is_debug_enabled = 0
56; GCN-NEXT:     is_xnack_enabled = 0
57; GCN-NEXT:     workitem_private_segment_byte_size = 16384
58; GCN-NEXT:     workgroup_group_segment_byte_size = 0
59; GCN-NEXT:     gds_segment_byte_size = 0
60; GCN-NEXT:     kernarg_segment_byte_size = 0
61; GCN-NEXT:     workgroup_fbarrier_count = 0
62; GCN-NEXT:     wavefront_sgpr_count = 37
63; GCN-NEXT:     workitem_vgpr_count = 32
64; GCN-NEXT:     reserved_vgpr_first = 0
65; GCN-NEXT:     reserved_vgpr_count = 0
66; GCN-NEXT:     reserved_sgpr_first = 0
67; GCN-NEXT:     reserved_sgpr_count = 0
68; GCN-NEXT:     debug_wavefront_private_segment_offset_sgpr = 0
69; GCN-NEXT:     debug_private_segment_buffer_sgpr = 0
70; GCN-NEXT:     kernarg_segment_alignment = 4
71; GCN-NEXT:     group_segment_alignment = 4
72; GCN-NEXT:     private_segment_alignment = 4
73; GCN-NEXT:     wavefront_size = 6
74; GCN-NEXT:     call_convention = -1
75; GCN-NEXT:     runtime_loader_kernel_symbol = 0
76; GCN-NEXT:    .end_amd_kernel_code_t
77; GCN-NEXT:  ; %bb.0:
78; GCN-NEXT:    s_mov_b32 s32, 0
79; GCN-NEXT:    s_mov_b32 flat_scratch_lo, s13
80; GCN-NEXT:    s_add_i32 s12, s12, s17
81; GCN-NEXT:    s_lshr_b32 flat_scratch_hi, s12, 8
82; GCN-NEXT:    s_add_u32 s0, s0, s17
83; GCN-NEXT:    s_addc_u32 s1, s1, 0
84; GCN-NEXT:    s_mov_b32 s13, s15
85; GCN-NEXT:    s_mov_b32 s12, s14
86; GCN-NEXT:    s_getpc_b64 s[14:15]
87; GCN-NEXT:    s_add_u32 s14, s14, gv.fptr0@rel32@lo+4
88; GCN-NEXT:    s_addc_u32 s15, s15, gv.fptr0@rel32@hi+12
89; GCN-NEXT:    s_load_dwordx2 s[18:19], s[14:15], 0x0
90; GCN-NEXT:    v_lshlrev_b32_e32 v2, 20, v2
91; GCN-NEXT:    v_lshlrev_b32_e32 v1, 10, v1
92; GCN-NEXT:    v_or_b32_e32 v0, v0, v1
93; GCN-NEXT:    v_or_b32_e32 v31, v0, v2
94; GCN-NEXT:    s_mov_b32 s14, s16
95; GCN-NEXT:    s_waitcnt lgkmcnt(0)
96; GCN-NEXT:    s_swappc_b64 s[30:31], s[18:19]
97; GCN-NEXT:    s_endpgm
98  %fptr = load void()*, void()* addrspace(4)* @gv.fptr0
99  call void %fptr()
100  ret void
101}
102
103define amdgpu_kernel void @test_indirect_call_sgpr_ptr_arg() {
104; GCN-LABEL: test_indirect_call_sgpr_ptr_arg:
105; GCN:         .amd_kernel_code_t
106; GCN-NEXT:     amd_code_version_major = 1
107; GCN-NEXT:     amd_code_version_minor = 2
108; GCN-NEXT:     amd_machine_kind = 1
109; GCN-NEXT:     amd_machine_version_major = 7
110; GCN-NEXT:     amd_machine_version_minor = 0
111; GCN-NEXT:     amd_machine_version_stepping = 0
112; GCN-NEXT:     kernel_code_entry_byte_offset = 256
113; GCN-NEXT:     kernel_code_prefetch_byte_size = 0
114; GCN-NEXT:     granulated_workitem_vgpr_count = 7
115; GCN-NEXT:     granulated_wavefront_sgpr_count = 4
116; GCN-NEXT:     priority = 0
117; GCN-NEXT:     float_mode = 240
118; GCN-NEXT:     priv = 0
119; GCN-NEXT:     enable_dx10_clamp = 1
120; GCN-NEXT:     debug_mode = 0
121; GCN-NEXT:     enable_ieee_mode = 1
122; GCN-NEXT:     enable_wgp_mode = 0
123; GCN-NEXT:     enable_mem_ordered = 0
124; GCN-NEXT:     enable_fwd_progress = 0
125; GCN-NEXT:     enable_sgpr_private_segment_wave_byte_offset = 1
126; GCN-NEXT:     user_sgpr_count = 14
127; GCN-NEXT:     enable_trap_handler = 0
128; GCN-NEXT:     enable_sgpr_workgroup_id_x = 1
129; GCN-NEXT:     enable_sgpr_workgroup_id_y = 1
130; GCN-NEXT:     enable_sgpr_workgroup_id_z = 1
131; GCN-NEXT:     enable_sgpr_workgroup_info = 0
132; GCN-NEXT:     enable_vgpr_workitem_id = 2
133; GCN-NEXT:     enable_exception_msb = 0
134; GCN-NEXT:     granulated_lds_size = 0
135; GCN-NEXT:     enable_exception = 0
136; GCN-NEXT:     enable_sgpr_private_segment_buffer = 1
137; GCN-NEXT:     enable_sgpr_dispatch_ptr = 1
138; GCN-NEXT:     enable_sgpr_queue_ptr = 1
139; GCN-NEXT:     enable_sgpr_kernarg_segment_ptr = 1
140; GCN-NEXT:     enable_sgpr_dispatch_id = 1
141; GCN-NEXT:     enable_sgpr_flat_scratch_init = 1
142; GCN-NEXT:     enable_sgpr_private_segment_size = 0
143; GCN-NEXT:     enable_sgpr_grid_workgroup_count_x = 0
144; GCN-NEXT:     enable_sgpr_grid_workgroup_count_y = 0
145; GCN-NEXT:     enable_sgpr_grid_workgroup_count_z = 0
146; GCN-NEXT:     enable_wavefront_size32 = 0
147; GCN-NEXT:     enable_ordered_append_gds = 0
148; GCN-NEXT:     private_element_size = 1
149; GCN-NEXT:     is_ptr64 = 1
150; GCN-NEXT:     is_dynamic_callstack = 1
151; GCN-NEXT:     is_debug_enabled = 0
152; GCN-NEXT:     is_xnack_enabled = 0
153; GCN-NEXT:     workitem_private_segment_byte_size = 16384
154; GCN-NEXT:     workgroup_group_segment_byte_size = 0
155; GCN-NEXT:     gds_segment_byte_size = 0
156; GCN-NEXT:     kernarg_segment_byte_size = 0
157; GCN-NEXT:     workgroup_fbarrier_count = 0
158; GCN-NEXT:     wavefront_sgpr_count = 37
159; GCN-NEXT:     workitem_vgpr_count = 32
160; GCN-NEXT:     reserved_vgpr_first = 0
161; GCN-NEXT:     reserved_vgpr_count = 0
162; GCN-NEXT:     reserved_sgpr_first = 0
163; GCN-NEXT:     reserved_sgpr_count = 0
164; GCN-NEXT:     debug_wavefront_private_segment_offset_sgpr = 0
165; GCN-NEXT:     debug_private_segment_buffer_sgpr = 0
166; GCN-NEXT:     kernarg_segment_alignment = 4
167; GCN-NEXT:     group_segment_alignment = 4
168; GCN-NEXT:     private_segment_alignment = 4
169; GCN-NEXT:     wavefront_size = 6
170; GCN-NEXT:     call_convention = -1
171; GCN-NEXT:     runtime_loader_kernel_symbol = 0
172; GCN-NEXT:    .end_amd_kernel_code_t
173; GCN-NEXT:  ; %bb.0:
174; GCN-NEXT:    s_mov_b32 s32, 0
175; GCN-NEXT:    s_mov_b32 flat_scratch_lo, s13
176; GCN-NEXT:    s_add_i32 s12, s12, s17
177; GCN-NEXT:    s_lshr_b32 flat_scratch_hi, s12, 8
178; GCN-NEXT:    s_add_u32 s0, s0, s17
179; GCN-NEXT:    s_addc_u32 s1, s1, 0
180; GCN-NEXT:    s_mov_b32 s13, s15
181; GCN-NEXT:    s_mov_b32 s12, s14
182; GCN-NEXT:    s_getpc_b64 s[14:15]
183; GCN-NEXT:    s_add_u32 s14, s14, gv.fptr1@rel32@lo+4
184; GCN-NEXT:    s_addc_u32 s15, s15, gv.fptr1@rel32@hi+12
185; GCN-NEXT:    v_lshlrev_b32_e32 v2, 20, v2
186; GCN-NEXT:    s_load_dwordx2 s[18:19], s[14:15], 0x0
187; GCN-NEXT:    v_lshlrev_b32_e32 v1, 10, v1
188; GCN-NEXT:    v_or_b32_e32 v0, v0, v1
189; GCN-NEXT:    v_or_b32_e32 v31, v0, v2
190; GCN-NEXT:    v_mov_b32_e32 v0, 0x7b
191; GCN-NEXT:    s_mov_b32 s14, s16
192; GCN-NEXT:    s_waitcnt lgkmcnt(0)
193; GCN-NEXT:    s_swappc_b64 s[30:31], s[18:19]
194; GCN-NEXT:    s_endpgm
195  %fptr = load void(i32)*, void(i32)* addrspace(4)* @gv.fptr1
196  call void %fptr(i32 123)
197  ret void
198}
199
200define void @test_indirect_call_vgpr_ptr(void()* %fptr) {
201; GCN-LABEL: test_indirect_call_vgpr_ptr:
202; GCN:       ; %bb.0:
203; GCN-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
204; GCN-NEXT:    s_or_saveexec_b64 s[16:17], -1
205; GCN-NEXT:    buffer_store_dword v40, off, s[0:3], s32 ; 4-byte Folded Spill
206; GCN-NEXT:    s_mov_b64 exec, s[16:17]
207; GCN-NEXT:    v_writelane_b32 v40, s33, 17
208; GCN-NEXT:    s_mov_b32 s33, s32
209; GCN-NEXT:    s_addk_i32 s32, 0x400
210; GCN-NEXT:    v_writelane_b32 v40, s34, 0
211; GCN-NEXT:    v_writelane_b32 v40, s35, 1
212; GCN-NEXT:    v_writelane_b32 v40, s36, 2
213; GCN-NEXT:    v_writelane_b32 v40, s38, 3
214; GCN-NEXT:    v_writelane_b32 v40, s39, 4
215; GCN-NEXT:    v_writelane_b32 v40, s40, 5
216; GCN-NEXT:    v_writelane_b32 v40, s41, 6
217; GCN-NEXT:    v_writelane_b32 v40, s42, 7
218; GCN-NEXT:    v_writelane_b32 v40, s43, 8
219; GCN-NEXT:    v_writelane_b32 v40, s44, 9
220; GCN-NEXT:    v_writelane_b32 v40, s45, 10
221; GCN-NEXT:    v_writelane_b32 v40, s46, 11
222; GCN-NEXT:    v_writelane_b32 v40, s47, 12
223; GCN-NEXT:    v_writelane_b32 v40, s48, 13
224; GCN-NEXT:    v_writelane_b32 v40, s49, 14
225; GCN-NEXT:    v_writelane_b32 v40, s30, 15
226; GCN-NEXT:    v_writelane_b32 v40, s31, 16
227; GCN-NEXT:    s_mov_b32 s34, s14
228; GCN-NEXT:    s_mov_b32 s35, s13
229; GCN-NEXT:    s_mov_b32 s36, s12
230; GCN-NEXT:    s_mov_b64 s[38:39], s[10:11]
231; GCN-NEXT:    s_mov_b64 s[40:41], s[8:9]
232; GCN-NEXT:    s_mov_b64 s[42:43], s[6:7]
233; GCN-NEXT:    s_mov_b64 s[44:45], s[4:5]
234; GCN-NEXT:    s_mov_b64 s[46:47], exec
235; GCN-NEXT:  BB2_1: ; =>This Inner Loop Header: Depth=1
236; GCN-NEXT:    v_readfirstlane_b32 s16, v0
237; GCN-NEXT:    v_readfirstlane_b32 s17, v1
238; GCN-NEXT:    v_cmp_eq_u64_e32 vcc, s[16:17], v[0:1]
239; GCN-NEXT:    s_and_saveexec_b64 s[48:49], vcc
240; GCN-NEXT:    s_mov_b64 s[4:5], s[44:45]
241; GCN-NEXT:    s_mov_b64 s[6:7], s[42:43]
242; GCN-NEXT:    s_mov_b64 s[8:9], s[40:41]
243; GCN-NEXT:    s_mov_b64 s[10:11], s[38:39]
244; GCN-NEXT:    s_mov_b32 s12, s36
245; GCN-NEXT:    s_mov_b32 s13, s35
246; GCN-NEXT:    s_mov_b32 s14, s34
247; GCN-NEXT:    s_swappc_b64 s[30:31], s[16:17]
248; GCN-NEXT:    ; implicit-def: $vgpr0_vgpr1
249; GCN-NEXT:    ; implicit-def: $vgpr31
250; GCN-NEXT:    s_xor_b64 exec, exec, s[48:49]
251; GCN-NEXT:    s_cbranch_execnz BB2_1
252; GCN-NEXT:  ; %bb.2:
253; GCN-NEXT:    s_mov_b64 exec, s[46:47]
254; GCN-NEXT:    v_readlane_b32 s4, v40, 15
255; GCN-NEXT:    v_readlane_b32 s5, v40, 16
256; GCN-NEXT:    v_readlane_b32 s49, v40, 14
257; GCN-NEXT:    v_readlane_b32 s48, v40, 13
258; GCN-NEXT:    v_readlane_b32 s47, v40, 12
259; GCN-NEXT:    v_readlane_b32 s46, v40, 11
260; GCN-NEXT:    v_readlane_b32 s45, v40, 10
261; GCN-NEXT:    v_readlane_b32 s44, v40, 9
262; GCN-NEXT:    v_readlane_b32 s43, v40, 8
263; GCN-NEXT:    v_readlane_b32 s42, v40, 7
264; GCN-NEXT:    v_readlane_b32 s41, v40, 6
265; GCN-NEXT:    v_readlane_b32 s40, v40, 5
266; GCN-NEXT:    v_readlane_b32 s39, v40, 4
267; GCN-NEXT:    v_readlane_b32 s38, v40, 3
268; GCN-NEXT:    v_readlane_b32 s36, v40, 2
269; GCN-NEXT:    v_readlane_b32 s35, v40, 1
270; GCN-NEXT:    v_readlane_b32 s34, v40, 0
271; GCN-NEXT:    s_addk_i32 s32, 0xfc00
272; GCN-NEXT:    v_readlane_b32 s33, v40, 17
273; GCN-NEXT:    s_or_saveexec_b64 s[6:7], -1
274; GCN-NEXT:    buffer_load_dword v40, off, s[0:3], s32 ; 4-byte Folded Reload
275; GCN-NEXT:    s_mov_b64 exec, s[6:7]
276; GCN-NEXT:    s_waitcnt vmcnt(0)
277; GCN-NEXT:    s_setpc_b64 s[4:5]
278  call void %fptr()
279  ret void
280}
281
282define void @test_indirect_call_vgpr_ptr_arg(void(i32)* %fptr) {
283; GCN-LABEL: test_indirect_call_vgpr_ptr_arg:
284; GCN:       ; %bb.0:
285; GCN-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
286; GCN-NEXT:    s_or_saveexec_b64 s[16:17], -1
287; GCN-NEXT:    buffer_store_dword v40, off, s[0:3], s32 ; 4-byte Folded Spill
288; GCN-NEXT:    s_mov_b64 exec, s[16:17]
289; GCN-NEXT:    v_writelane_b32 v40, s33, 17
290; GCN-NEXT:    s_mov_b32 s33, s32
291; GCN-NEXT:    s_addk_i32 s32, 0x400
292; GCN-NEXT:    v_writelane_b32 v40, s34, 0
293; GCN-NEXT:    v_writelane_b32 v40, s35, 1
294; GCN-NEXT:    v_writelane_b32 v40, s36, 2
295; GCN-NEXT:    v_writelane_b32 v40, s38, 3
296; GCN-NEXT:    v_writelane_b32 v40, s39, 4
297; GCN-NEXT:    v_writelane_b32 v40, s40, 5
298; GCN-NEXT:    v_writelane_b32 v40, s41, 6
299; GCN-NEXT:    v_writelane_b32 v40, s42, 7
300; GCN-NEXT:    v_writelane_b32 v40, s43, 8
301; GCN-NEXT:    v_writelane_b32 v40, s44, 9
302; GCN-NEXT:    v_writelane_b32 v40, s45, 10
303; GCN-NEXT:    v_writelane_b32 v40, s46, 11
304; GCN-NEXT:    v_writelane_b32 v40, s47, 12
305; GCN-NEXT:    v_writelane_b32 v40, s48, 13
306; GCN-NEXT:    v_writelane_b32 v40, s49, 14
307; GCN-NEXT:    v_writelane_b32 v40, s30, 15
308; GCN-NEXT:    v_writelane_b32 v40, s31, 16
309; GCN-NEXT:    s_mov_b32 s34, s14
310; GCN-NEXT:    s_mov_b32 s35, s13
311; GCN-NEXT:    s_mov_b32 s36, s12
312; GCN-NEXT:    s_mov_b64 s[38:39], s[10:11]
313; GCN-NEXT:    s_mov_b64 s[40:41], s[8:9]
314; GCN-NEXT:    s_mov_b64 s[42:43], s[6:7]
315; GCN-NEXT:    s_mov_b64 s[44:45], s[4:5]
316; GCN-NEXT:    s_mov_b64 s[46:47], exec
317; GCN-NEXT:  BB3_1: ; =>This Inner Loop Header: Depth=1
318; GCN-NEXT:    v_readfirstlane_b32 s16, v0
319; GCN-NEXT:    v_readfirstlane_b32 s17, v1
320; GCN-NEXT:    v_cmp_eq_u64_e32 vcc, s[16:17], v[0:1]
321; GCN-NEXT:    s_and_saveexec_b64 s[48:49], vcc
322; GCN-NEXT:    v_mov_b32_e32 v0, 0x7b
323; GCN-NEXT:    s_mov_b64 s[4:5], s[44:45]
324; GCN-NEXT:    s_mov_b64 s[6:7], s[42:43]
325; GCN-NEXT:    s_mov_b64 s[8:9], s[40:41]
326; GCN-NEXT:    s_mov_b64 s[10:11], s[38:39]
327; GCN-NEXT:    s_mov_b32 s12, s36
328; GCN-NEXT:    s_mov_b32 s13, s35
329; GCN-NEXT:    s_mov_b32 s14, s34
330; GCN-NEXT:    s_swappc_b64 s[30:31], s[16:17]
331; GCN-NEXT:    ; implicit-def: $vgpr0_vgpr1
332; GCN-NEXT:    ; implicit-def: $vgpr31
333; GCN-NEXT:    s_xor_b64 exec, exec, s[48:49]
334; GCN-NEXT:    s_cbranch_execnz BB3_1
335; GCN-NEXT:  ; %bb.2:
336; GCN-NEXT:    s_mov_b64 exec, s[46:47]
337; GCN-NEXT:    v_readlane_b32 s4, v40, 15
338; GCN-NEXT:    v_readlane_b32 s5, v40, 16
339; GCN-NEXT:    v_readlane_b32 s49, v40, 14
340; GCN-NEXT:    v_readlane_b32 s48, v40, 13
341; GCN-NEXT:    v_readlane_b32 s47, v40, 12
342; GCN-NEXT:    v_readlane_b32 s46, v40, 11
343; GCN-NEXT:    v_readlane_b32 s45, v40, 10
344; GCN-NEXT:    v_readlane_b32 s44, v40, 9
345; GCN-NEXT:    v_readlane_b32 s43, v40, 8
346; GCN-NEXT:    v_readlane_b32 s42, v40, 7
347; GCN-NEXT:    v_readlane_b32 s41, v40, 6
348; GCN-NEXT:    v_readlane_b32 s40, v40, 5
349; GCN-NEXT:    v_readlane_b32 s39, v40, 4
350; GCN-NEXT:    v_readlane_b32 s38, v40, 3
351; GCN-NEXT:    v_readlane_b32 s36, v40, 2
352; GCN-NEXT:    v_readlane_b32 s35, v40, 1
353; GCN-NEXT:    v_readlane_b32 s34, v40, 0
354; GCN-NEXT:    s_addk_i32 s32, 0xfc00
355; GCN-NEXT:    v_readlane_b32 s33, v40, 17
356; GCN-NEXT:    s_or_saveexec_b64 s[6:7], -1
357; GCN-NEXT:    buffer_load_dword v40, off, s[0:3], s32 ; 4-byte Folded Reload
358; GCN-NEXT:    s_mov_b64 exec, s[6:7]
359; GCN-NEXT:    s_waitcnt vmcnt(0)
360; GCN-NEXT:    s_setpc_b64 s[4:5]
361  call void %fptr(i32 123)
362  ret void
363}
364
365define i32 @test_indirect_call_vgpr_ptr_ret(i32()* %fptr) {
366; GCN-LABEL: test_indirect_call_vgpr_ptr_ret:
367; GCN:       ; %bb.0:
368; GCN-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
369; GCN-NEXT:    s_or_saveexec_b64 s[16:17], -1
370; GCN-NEXT:    buffer_store_dword v40, off, s[0:3], s32 ; 4-byte Folded Spill
371; GCN-NEXT:    s_mov_b64 exec, s[16:17]
372; GCN-NEXT:    v_writelane_b32 v40, s33, 17
373; GCN-NEXT:    s_mov_b32 s33, s32
374; GCN-NEXT:    s_addk_i32 s32, 0x400
375; GCN-NEXT:    v_writelane_b32 v40, s34, 0
376; GCN-NEXT:    v_writelane_b32 v40, s35, 1
377; GCN-NEXT:    v_writelane_b32 v40, s36, 2
378; GCN-NEXT:    v_writelane_b32 v40, s38, 3
379; GCN-NEXT:    v_writelane_b32 v40, s39, 4
380; GCN-NEXT:    v_writelane_b32 v40, s40, 5
381; GCN-NEXT:    v_writelane_b32 v40, s41, 6
382; GCN-NEXT:    v_writelane_b32 v40, s42, 7
383; GCN-NEXT:    v_writelane_b32 v40, s43, 8
384; GCN-NEXT:    v_writelane_b32 v40, s44, 9
385; GCN-NEXT:    v_writelane_b32 v40, s45, 10
386; GCN-NEXT:    v_writelane_b32 v40, s46, 11
387; GCN-NEXT:    v_writelane_b32 v40, s47, 12
388; GCN-NEXT:    v_writelane_b32 v40, s48, 13
389; GCN-NEXT:    v_writelane_b32 v40, s49, 14
390; GCN-NEXT:    v_writelane_b32 v40, s30, 15
391; GCN-NEXT:    v_writelane_b32 v40, s31, 16
392; GCN-NEXT:    s_mov_b32 s34, s14
393; GCN-NEXT:    s_mov_b32 s35, s13
394; GCN-NEXT:    s_mov_b32 s36, s12
395; GCN-NEXT:    s_mov_b64 s[38:39], s[10:11]
396; GCN-NEXT:    s_mov_b64 s[40:41], s[8:9]
397; GCN-NEXT:    s_mov_b64 s[42:43], s[6:7]
398; GCN-NEXT:    s_mov_b64 s[44:45], s[4:5]
399; GCN-NEXT:    s_mov_b64 s[46:47], exec
400; GCN-NEXT:  BB4_1: ; =>This Inner Loop Header: Depth=1
401; GCN-NEXT:    v_readfirstlane_b32 s16, v0
402; GCN-NEXT:    v_readfirstlane_b32 s17, v1
403; GCN-NEXT:    v_cmp_eq_u64_e32 vcc, s[16:17], v[0:1]
404; GCN-NEXT:    s_and_saveexec_b64 s[48:49], vcc
405; GCN-NEXT:    s_mov_b64 s[4:5], s[44:45]
406; GCN-NEXT:    s_mov_b64 s[6:7], s[42:43]
407; GCN-NEXT:    s_mov_b64 s[8:9], s[40:41]
408; GCN-NEXT:    s_mov_b64 s[10:11], s[38:39]
409; GCN-NEXT:    s_mov_b32 s12, s36
410; GCN-NEXT:    s_mov_b32 s13, s35
411; GCN-NEXT:    s_mov_b32 s14, s34
412; GCN-NEXT:    s_swappc_b64 s[30:31], s[16:17]
413; GCN-NEXT:    v_mov_b32_e32 v2, v0
414; GCN-NEXT:    ; implicit-def: $vgpr0_vgpr1
415; GCN-NEXT:    ; implicit-def: $vgpr31
416; GCN-NEXT:    s_xor_b64 exec, exec, s[48:49]
417; GCN-NEXT:    s_cbranch_execnz BB4_1
418; GCN-NEXT:  ; %bb.2:
419; GCN-NEXT:    s_mov_b64 exec, s[46:47]
420; GCN-NEXT:    v_add_i32_e32 v0, vcc, 1, v2
421; GCN-NEXT:    v_readlane_b32 s4, v40, 15
422; GCN-NEXT:    v_readlane_b32 s5, v40, 16
423; GCN-NEXT:    v_readlane_b32 s49, v40, 14
424; GCN-NEXT:    v_readlane_b32 s48, v40, 13
425; GCN-NEXT:    v_readlane_b32 s47, v40, 12
426; GCN-NEXT:    v_readlane_b32 s46, v40, 11
427; GCN-NEXT:    v_readlane_b32 s45, v40, 10
428; GCN-NEXT:    v_readlane_b32 s44, v40, 9
429; GCN-NEXT:    v_readlane_b32 s43, v40, 8
430; GCN-NEXT:    v_readlane_b32 s42, v40, 7
431; GCN-NEXT:    v_readlane_b32 s41, v40, 6
432; GCN-NEXT:    v_readlane_b32 s40, v40, 5
433; GCN-NEXT:    v_readlane_b32 s39, v40, 4
434; GCN-NEXT:    v_readlane_b32 s38, v40, 3
435; GCN-NEXT:    v_readlane_b32 s36, v40, 2
436; GCN-NEXT:    v_readlane_b32 s35, v40, 1
437; GCN-NEXT:    v_readlane_b32 s34, v40, 0
438; GCN-NEXT:    s_addk_i32 s32, 0xfc00
439; GCN-NEXT:    v_readlane_b32 s33, v40, 17
440; GCN-NEXT:    s_or_saveexec_b64 s[6:7], -1
441; GCN-NEXT:    buffer_load_dword v40, off, s[0:3], s32 ; 4-byte Folded Reload
442; GCN-NEXT:    s_mov_b64 exec, s[6:7]
443; GCN-NEXT:    s_waitcnt vmcnt(0)
444; GCN-NEXT:    s_setpc_b64 s[4:5]
445  %a = call i32 %fptr()
446  %b = add i32 %a, 1
447  ret i32 %b
448}
449
450define void @test_indirect_call_vgpr_ptr_in_branch(void()* %fptr, i1 %cond) {
451; GCN-LABEL: test_indirect_call_vgpr_ptr_in_branch:
452; GCN:       ; %bb.0: ; %bb0
453; GCN-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
454; GCN-NEXT:    s_or_saveexec_b64 s[16:17], -1
455; GCN-NEXT:    buffer_store_dword v40, off, s[0:3], s32 ; 4-byte Folded Spill
456; GCN-NEXT:    s_mov_b64 exec, s[16:17]
457; GCN-NEXT:    v_writelane_b32 v40, s33, 19
458; GCN-NEXT:    s_mov_b32 s33, s32
459; GCN-NEXT:    s_addk_i32 s32, 0x400
460; GCN-NEXT:    v_writelane_b32 v40, s34, 0
461; GCN-NEXT:    v_writelane_b32 v40, s35, 1
462; GCN-NEXT:    v_writelane_b32 v40, s36, 2
463; GCN-NEXT:    v_writelane_b32 v40, s38, 3
464; GCN-NEXT:    v_writelane_b32 v40, s39, 4
465; GCN-NEXT:    v_writelane_b32 v40, s40, 5
466; GCN-NEXT:    v_writelane_b32 v40, s41, 6
467; GCN-NEXT:    v_writelane_b32 v40, s42, 7
468; GCN-NEXT:    v_writelane_b32 v40, s43, 8
469; GCN-NEXT:    v_writelane_b32 v40, s44, 9
470; GCN-NEXT:    v_writelane_b32 v40, s45, 10
471; GCN-NEXT:    v_writelane_b32 v40, s46, 11
472; GCN-NEXT:    v_writelane_b32 v40, s47, 12
473; GCN-NEXT:    v_writelane_b32 v40, s48, 13
474; GCN-NEXT:    v_writelane_b32 v40, s49, 14
475; GCN-NEXT:    v_writelane_b32 v40, s50, 15
476; GCN-NEXT:    v_writelane_b32 v40, s51, 16
477; GCN-NEXT:    s_mov_b32 s34, s14
478; GCN-NEXT:    s_mov_b32 s35, s13
479; GCN-NEXT:    s_mov_b32 s36, s12
480; GCN-NEXT:    s_mov_b64 s[38:39], s[10:11]
481; GCN-NEXT:    s_mov_b64 s[40:41], s[8:9]
482; GCN-NEXT:    s_mov_b64 s[42:43], s[6:7]
483; GCN-NEXT:    s_mov_b64 s[44:45], s[4:5]
484; GCN-NEXT:    v_and_b32_e32 v2, 1, v2
485; GCN-NEXT:    v_cmp_eq_u32_e32 vcc, 1, v2
486; GCN-NEXT:    s_and_saveexec_b64 s[46:47], vcc
487; GCN-NEXT:    s_cbranch_execz BB5_4
488; GCN-NEXT:  ; %bb.1: ; %bb1
489; GCN-NEXT:    v_writelane_b32 v40, s30, 17
490; GCN-NEXT:    v_writelane_b32 v40, s31, 18
491; GCN-NEXT:    s_mov_b64 s[48:49], exec
492; GCN-NEXT:  BB5_2: ; =>This Inner Loop Header: Depth=1
493; GCN-NEXT:    v_readfirstlane_b32 s16, v0
494; GCN-NEXT:    v_readfirstlane_b32 s17, v1
495; GCN-NEXT:    v_cmp_eq_u64_e32 vcc, s[16:17], v[0:1]
496; GCN-NEXT:    s_and_saveexec_b64 s[50:51], vcc
497; GCN-NEXT:    s_mov_b64 s[4:5], s[44:45]
498; GCN-NEXT:    s_mov_b64 s[6:7], s[42:43]
499; GCN-NEXT:    s_mov_b64 s[8:9], s[40:41]
500; GCN-NEXT:    s_mov_b64 s[10:11], s[38:39]
501; GCN-NEXT:    s_mov_b32 s12, s36
502; GCN-NEXT:    s_mov_b32 s13, s35
503; GCN-NEXT:    s_mov_b32 s14, s34
504; GCN-NEXT:    s_swappc_b64 s[30:31], s[16:17]
505; GCN-NEXT:    ; implicit-def: $vgpr0_vgpr1
506; GCN-NEXT:    ; implicit-def: $vgpr31
507; GCN-NEXT:    s_xor_b64 exec, exec, s[50:51]
508; GCN-NEXT:    s_cbranch_execnz BB5_2
509; GCN-NEXT:  ; %bb.3:
510; GCN-NEXT:    s_mov_b64 exec, s[48:49]
511; GCN-NEXT:    v_readlane_b32 s30, v40, 17
512; GCN-NEXT:    v_readlane_b32 s31, v40, 18
513; GCN-NEXT:  BB5_4: ; %bb2
514; GCN-NEXT:    s_or_b64 exec, exec, s[46:47]
515; GCN-NEXT:    v_readlane_b32 s51, v40, 16
516; GCN-NEXT:    v_readlane_b32 s50, v40, 15
517; GCN-NEXT:    v_readlane_b32 s49, v40, 14
518; GCN-NEXT:    v_readlane_b32 s48, v40, 13
519; GCN-NEXT:    v_readlane_b32 s47, v40, 12
520; GCN-NEXT:    v_readlane_b32 s46, v40, 11
521; GCN-NEXT:    v_readlane_b32 s45, v40, 10
522; GCN-NEXT:    v_readlane_b32 s44, v40, 9
523; GCN-NEXT:    v_readlane_b32 s43, v40, 8
524; GCN-NEXT:    v_readlane_b32 s42, v40, 7
525; GCN-NEXT:    v_readlane_b32 s41, v40, 6
526; GCN-NEXT:    v_readlane_b32 s40, v40, 5
527; GCN-NEXT:    v_readlane_b32 s39, v40, 4
528; GCN-NEXT:    v_readlane_b32 s38, v40, 3
529; GCN-NEXT:    v_readlane_b32 s36, v40, 2
530; GCN-NEXT:    v_readlane_b32 s35, v40, 1
531; GCN-NEXT:    v_readlane_b32 s34, v40, 0
532; GCN-NEXT:    s_addk_i32 s32, 0xfc00
533; GCN-NEXT:    v_readlane_b32 s33, v40, 19
534; GCN-NEXT:    s_or_saveexec_b64 s[4:5], -1
535; GCN-NEXT:    buffer_load_dword v40, off, s[0:3], s32 ; 4-byte Folded Reload
536; GCN-NEXT:    s_mov_b64 exec, s[4:5]
537; GCN-NEXT:    s_waitcnt vmcnt(0)
538; GCN-NEXT:    s_setpc_b64 s[30:31]
539bb0:
540  br i1 %cond, label %bb1, label %bb2
541
542bb1:
543  call void %fptr()
544  br label %bb2
545
546bb2:
547  ret void
548}
549
550define void @test_indirect_call_vgpr_ptr_inreg_arg(void(i32)* %fptr) {
551; GCN-LABEL: test_indirect_call_vgpr_ptr_inreg_arg:
552; GCN:       ; %bb.0:
553; GCN-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
554; GCN-NEXT:    s_or_saveexec_b64 s[4:5], -1
555; GCN-NEXT:    buffer_store_dword v40, off, s[0:3], s32 ; 4-byte Folded Spill
556; GCN-NEXT:    s_mov_b64 exec, s[4:5]
557; GCN-NEXT:    v_writelane_b32 v40, s33, 6
558; GCN-NEXT:    s_mov_b32 s33, s32
559; GCN-NEXT:    s_addk_i32 s32, 0x400
560; GCN-NEXT:    v_writelane_b32 v40, s34, 0
561; GCN-NEXT:    v_writelane_b32 v40, s35, 1
562; GCN-NEXT:    v_writelane_b32 v40, s36, 2
563; GCN-NEXT:    v_writelane_b32 v40, s37, 3
564; GCN-NEXT:    v_writelane_b32 v40, s30, 4
565; GCN-NEXT:    v_writelane_b32 v40, s31, 5
566; GCN-NEXT:    s_mov_b64 s[34:35], exec
567; GCN-NEXT:  BB6_1: ; =>This Inner Loop Header: Depth=1
568; GCN-NEXT:    v_readfirstlane_b32 s6, v0
569; GCN-NEXT:    v_readfirstlane_b32 s7, v1
570; GCN-NEXT:    v_cmp_eq_u64_e32 vcc, s[6:7], v[0:1]
571; GCN-NEXT:    s_and_saveexec_b64 s[36:37], vcc
572; GCN-NEXT:    s_movk_i32 s4, 0x7b
573; GCN-NEXT:    s_swappc_b64 s[30:31], s[6:7]
574; GCN-NEXT:    ; implicit-def: $vgpr0_vgpr1
575; GCN-NEXT:    s_xor_b64 exec, exec, s[36:37]
576; GCN-NEXT:    s_cbranch_execnz BB6_1
577; GCN-NEXT:  ; %bb.2:
578; GCN-NEXT:    s_mov_b64 exec, s[34:35]
579; GCN-NEXT:    v_readlane_b32 s4, v40, 4
580; GCN-NEXT:    v_readlane_b32 s5, v40, 5
581; GCN-NEXT:    v_readlane_b32 s37, v40, 3
582; GCN-NEXT:    v_readlane_b32 s36, v40, 2
583; GCN-NEXT:    v_readlane_b32 s35, v40, 1
584; GCN-NEXT:    v_readlane_b32 s34, v40, 0
585; GCN-NEXT:    s_addk_i32 s32, 0xfc00
586; GCN-NEXT:    v_readlane_b32 s33, v40, 6
587; GCN-NEXT:    s_or_saveexec_b64 s[6:7], -1
588; GCN-NEXT:    buffer_load_dword v40, off, s[0:3], s32 ; 4-byte Folded Reload
589; GCN-NEXT:    s_mov_b64 exec, s[6:7]
590; GCN-NEXT:    s_waitcnt vmcnt(0)
591; GCN-NEXT:    s_setpc_b64 s[4:5]
592  call amdgpu_gfx void %fptr(i32 inreg 123)
593  ret void
594}
595
596define i32 @test_indirect_call_vgpr_ptr_arg_and_reuse(i32 %i, void(i32)* %fptr) {
597; GCN-LABEL: test_indirect_call_vgpr_ptr_arg_and_reuse:
598; GCN:       ; %bb.0:
599; GCN-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
600; GCN-NEXT:    s_or_saveexec_b64 s[4:5], -1
601; GCN-NEXT:    buffer_store_dword v40, off, s[0:3], s32 offset:4 ; 4-byte Folded Spill
602; GCN-NEXT:    s_mov_b64 exec, s[4:5]
603; GCN-NEXT:    v_writelane_b32 v40, s33, 6
604; GCN-NEXT:    s_mov_b32 s33, s32
605; GCN-NEXT:    s_addk_i32 s32, 0x400
606; GCN-NEXT:    buffer_store_dword v41, off, s[0:3], s33 ; 4-byte Folded Spill
607; GCN-NEXT:    v_writelane_b32 v40, s34, 0
608; GCN-NEXT:    v_writelane_b32 v40, s35, 1
609; GCN-NEXT:    v_writelane_b32 v40, s36, 2
610; GCN-NEXT:    v_writelane_b32 v40, s37, 3
611; GCN-NEXT:    v_writelane_b32 v40, s30, 4
612; GCN-NEXT:    v_writelane_b32 v40, s31, 5
613; GCN-NEXT:    v_mov_b32_e32 v41, v0
614; GCN-NEXT:    s_mov_b64 s[34:35], exec
615; GCN-NEXT:  BB7_1: ; =>This Inner Loop Header: Depth=1
616; GCN-NEXT:    v_readfirstlane_b32 s4, v1
617; GCN-NEXT:    v_readfirstlane_b32 s5, v2
618; GCN-NEXT:    v_cmp_eq_u64_e32 vcc, s[4:5], v[1:2]
619; GCN-NEXT:    s_and_saveexec_b64 s[36:37], vcc
620; GCN-NEXT:    v_mov_b32_e32 v0, v41
621; GCN-NEXT:    s_swappc_b64 s[30:31], s[4:5]
622; GCN-NEXT:    ; implicit-def: $vgpr1_vgpr2
623; GCN-NEXT:    s_xor_b64 exec, exec, s[36:37]
624; GCN-NEXT:    s_cbranch_execnz BB7_1
625; GCN-NEXT:  ; %bb.2:
626; GCN-NEXT:    s_mov_b64 exec, s[34:35]
627; GCN-NEXT:    v_mov_b32_e32 v0, v41
628; GCN-NEXT:    v_readlane_b32 s4, v40, 4
629; GCN-NEXT:    v_readlane_b32 s5, v40, 5
630; GCN-NEXT:    v_readlane_b32 s37, v40, 3
631; GCN-NEXT:    v_readlane_b32 s36, v40, 2
632; GCN-NEXT:    v_readlane_b32 s35, v40, 1
633; GCN-NEXT:    v_readlane_b32 s34, v40, 0
634; GCN-NEXT:    buffer_load_dword v41, off, s[0:3], s33 ; 4-byte Folded Reload
635; GCN-NEXT:    s_addk_i32 s32, 0xfc00
636; GCN-NEXT:    v_readlane_b32 s33, v40, 6
637; GCN-NEXT:    s_or_saveexec_b64 s[6:7], -1
638; GCN-NEXT:    buffer_load_dword v40, off, s[0:3], s32 offset:4 ; 4-byte Folded Reload
639; GCN-NEXT:    s_mov_b64 exec, s[6:7]
640; GCN-NEXT:    s_waitcnt vmcnt(0)
641; GCN-NEXT:    s_setpc_b64 s[4:5]
642  call amdgpu_gfx void %fptr(i32 %i)
643  ret i32 %i
644}
645
646; Use a variable inside a waterfall loop and use the return variable after the loop.
647; TODO The argument and return variable could be in the same physical register, but the register
648; allocator is not able to do that because the return value clashes with the liverange of an
649; IMPLICIT_DEF of the argument.
650define i32 @test_indirect_call_vgpr_ptr_arg_and_return(i32 %i, i32(i32)* %fptr) {
651; GCN-LABEL: test_indirect_call_vgpr_ptr_arg_and_return:
652; GCN:       ; %bb.0:
653; GCN-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
654; GCN-NEXT:    s_or_saveexec_b64 s[4:5], -1
655; GCN-NEXT:    buffer_store_dword v40, off, s[0:3], s32 ; 4-byte Folded Spill
656; GCN-NEXT:    s_mov_b64 exec, s[4:5]
657; GCN-NEXT:    v_writelane_b32 v40, s33, 6
658; GCN-NEXT:    s_mov_b32 s33, s32
659; GCN-NEXT:    s_addk_i32 s32, 0x400
660; GCN-NEXT:    v_writelane_b32 v40, s34, 0
661; GCN-NEXT:    v_writelane_b32 v40, s35, 1
662; GCN-NEXT:    v_writelane_b32 v40, s36, 2
663; GCN-NEXT:    v_writelane_b32 v40, s37, 3
664; GCN-NEXT:    v_writelane_b32 v40, s30, 4
665; GCN-NEXT:    v_writelane_b32 v40, s31, 5
666; GCN-NEXT:    s_mov_b64 s[34:35], exec
667; GCN-NEXT:  BB8_1: ; =>This Inner Loop Header: Depth=1
668; GCN-NEXT:    v_readfirstlane_b32 s4, v1
669; GCN-NEXT:    v_readfirstlane_b32 s5, v2
670; GCN-NEXT:    v_cmp_eq_u64_e32 vcc, s[4:5], v[1:2]
671; GCN-NEXT:    s_and_saveexec_b64 s[36:37], vcc
672; GCN-NEXT:    s_swappc_b64 s[30:31], s[4:5]
673; GCN-NEXT:    v_mov_b32_e32 v3, v0
674; GCN-NEXT:    ; implicit-def: $vgpr1_vgpr2
675; GCN-NEXT:    ; implicit-def: $vgpr0
676; GCN-NEXT:    s_xor_b64 exec, exec, s[36:37]
677; GCN-NEXT:    s_cbranch_execnz BB8_1
678; GCN-NEXT:  ; %bb.2:
679; GCN-NEXT:    s_mov_b64 exec, s[34:35]
680; GCN-NEXT:    v_mov_b32_e32 v0, v3
681; GCN-NEXT:    v_readlane_b32 s4, v40, 4
682; GCN-NEXT:    v_readlane_b32 s5, v40, 5
683; GCN-NEXT:    v_readlane_b32 s37, v40, 3
684; GCN-NEXT:    v_readlane_b32 s36, v40, 2
685; GCN-NEXT:    v_readlane_b32 s35, v40, 1
686; GCN-NEXT:    v_readlane_b32 s34, v40, 0
687; GCN-NEXT:    s_addk_i32 s32, 0xfc00
688; GCN-NEXT:    v_readlane_b32 s33, v40, 6
689; GCN-NEXT:    s_or_saveexec_b64 s[6:7], -1
690; GCN-NEXT:    buffer_load_dword v40, off, s[0:3], s32 ; 4-byte Folded Reload
691; GCN-NEXT:    s_mov_b64 exec, s[6:7]
692; GCN-NEXT:    s_waitcnt vmcnt(0)
693; GCN-NEXT:    s_setpc_b64 s[4:5]
694  %ret = call amdgpu_gfx i32 %fptr(i32 %i)
695  ret i32 %ret
696}
697