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