1; RUN: llc -march=amdgcn -mcpu=hawaii -verify-machineinstrs < %s | FileCheck  -enable-var-scope -check-prefix=GCN -check-prefix=CI %s
2; RUN: llc -march=amdgcn -mcpu=gfx900 -verify-machineinstrs < %s | FileCheck  -enable-var-scope -check-prefix=GCN -check-prefix=GFX9 %s
3
4; GCN-LABEL: {{^}}callee_no_stack:
5; GCN: ; %bb.0:
6; GCN-NEXT: s_waitcnt
7; GCN-NEXT: s_setpc_b64
8define void @callee_no_stack() #0 {
9  ret void
10}
11
12; GCN-LABEL: {{^}}callee_no_stack_no_fp_elim_all:
13; GCN: ; %bb.0:
14; GCN-NEXT: s_waitcnt
15; GCN-NEXT: s_mov_b32 s4, s33
16; GCN-NEXT: s_mov_b32 s33, s32
17; GCN-NEXT: s_mov_b32 s33, s4
18; GCN-NEXT: s_setpc_b64
19define void @callee_no_stack_no_fp_elim_all() #1 {
20  ret void
21}
22
23; GCN-LABEL: {{^}}callee_no_stack_no_fp_elim_nonleaf:
24; GCN: ; %bb.0:
25; GCN-NEXT: s_waitcnt
26; GCN-NEXT: s_setpc_b64
27define void @callee_no_stack_no_fp_elim_nonleaf() #2 {
28  ret void
29}
30
31; GCN-LABEL: {{^}}callee_with_stack:
32; GCN: ; %bb.0:
33; GCN-NEXT: s_waitcnt
34; GCN-NEXT: v_mov_b32_e32 v0, 0{{$}}
35; GCN-NEXT: buffer_store_dword v0, off, s[0:3], s32{{$}}
36; GCN-NEXT: s_waitcnt
37; GCN-NEXT: s_setpc_b64
38define void @callee_with_stack() #0 {
39  %alloca = alloca i32, addrspace(5)
40  store volatile i32 0, i32 addrspace(5)* %alloca
41  ret void
42}
43
44; Can use free call clobbered register to preserve original FP value.
45
46; GCN-LABEL: {{^}}callee_with_stack_no_fp_elim_all:
47; GCN: ; %bb.0:
48; GCN-NEXT: s_waitcnt
49; GCN-NEXT: s_mov_b32 s4, s33
50; GCN-NEXT: s_mov_b32 s33, s32
51; GCN-NEXT: s_add_u32 s32, s32, 0x200
52; GCN-NEXT: v_mov_b32_e32 v0, 0{{$}}
53; GCN-NEXT: buffer_store_dword v0, off, s[0:3], s33 offset:4{{$}}
54; GCN-NEXT: s_sub_u32 s32, s32, 0x200
55; GCN-NEXT: s_mov_b32 s33, s4
56; GCN-NEXT: s_waitcnt vmcnt(0)
57; GCN-NEXT: s_setpc_b64
58define void @callee_with_stack_no_fp_elim_all() #1 {
59  %alloca = alloca i32, addrspace(5)
60  store volatile i32 0, i32 addrspace(5)* %alloca
61  ret void
62}
63
64; GCN-LABEL: {{^}}callee_with_stack_no_fp_elim_non_leaf:
65; GCN: ; %bb.0:
66; GCN-NEXT: s_waitcnt
67; GCN-NEXT: v_mov_b32_e32 v0, 0{{$}}
68; GCN-NEXT: buffer_store_dword v0, off, s[0:3], s32{{$}}
69; GCN-NEXT: s_waitcnt
70; GCN-NEXT: s_setpc_b64
71define void @callee_with_stack_no_fp_elim_non_leaf() #2 {
72  %alloca = alloca i32, addrspace(5)
73  store volatile i32 0, i32 addrspace(5)* %alloca
74  ret void
75}
76
77; GCN-LABEL: {{^}}callee_with_stack_and_call:
78; GCN: ; %bb.0:
79; GCN-NEXT: s_waitcnt
80; GCN: s_or_saveexec_b64 [[COPY_EXEC0:s\[[0-9]+:[0-9]+\]]], -1{{$}}
81; GCN-NEXT: buffer_store_dword [[CSR_VGPR:v[0-9]+]], off, s[0:3], s32 offset:4 ; 4-byte Folded Spill
82; GCN-NEXT: s_mov_b64 exec, [[COPY_EXEC0]]
83; GCN: v_writelane_b32 [[CSR_VGPR]], s33, 2
84; GCN-DAG: s_mov_b32 s33, s32
85; GCN-DAG: s_add_u32 s32, s32, 0x400{{$}}
86; GCN-DAG: v_mov_b32_e32 [[ZERO:v[0-9]+]], 0{{$}}
87; GCN-DAG: v_writelane_b32 [[CSR_VGPR]], s30,
88; GCN-DAG: v_writelane_b32 [[CSR_VGPR]], s31,
89
90; GCN-DAG: buffer_store_dword [[ZERO]], off, s[0:3], s33{{$}}
91
92; GCN: s_swappc_b64
93
94; GCN-DAG: v_readlane_b32 s5, [[CSR_VGPR]]
95; GCN-DAG: v_readlane_b32 s4, [[CSR_VGPR]]
96
97; GCN: s_sub_u32 s32, s32, 0x400{{$}}
98; GCN-NEXT: v_readlane_b32 s33, [[CSR_VGPR]], 2
99; GCN-NEXT: s_or_saveexec_b64 [[COPY_EXEC1:s\[[0-9]+:[0-9]+\]]], -1{{$}}
100; GCN-NEXT: buffer_load_dword [[CSR_VGPR]], off, s[0:3], s32 offset:4 ; 4-byte Folded Reload
101; GCN-NEXT: s_mov_b64 exec, [[COPY_EXEC1]]
102; GCN-NEXT: s_waitcnt vmcnt(0)
103
104; GCN-NEXT: s_setpc_b64
105define void @callee_with_stack_and_call() #0 {
106  %alloca = alloca i32, addrspace(5)
107  store volatile i32 0, i32 addrspace(5)* %alloca
108  call void @external_void_func_void()
109  ret void
110}
111
112; Should be able to copy incoming stack pointer directly to inner
113; call's stack pointer argument.
114
115; There is stack usage only because of the need to evict a VGPR for
116; spilling CSR SGPRs.
117
118; GCN-LABEL: {{^}}callee_no_stack_with_call:
119; GCN: s_waitcnt
120; GCN-NEXT: s_or_saveexec_b64 [[COPY_EXEC0:s\[[0-9]+:[0-9]+\]]], -1{{$}}
121; GCN-NEXT: buffer_store_dword [[CSR_VGPR:v[0-9]+]], off, s[0:3], s32 ; 4-byte Folded Spill
122; GCN-NEXT: s_mov_b64 exec, [[COPY_EXEC0]]
123; GCN-DAG: s_add_u32 s32, s32, 0x400
124; GCN-DAG: v_writelane_b32 [[CSR_VGPR]], s33, [[FP_SPILL_LANE:[0-9]+]]
125
126; GCN-DAG: v_writelane_b32 [[CSR_VGPR]], s30, 0
127; GCN-DAG: v_writelane_b32 [[CSR_VGPR]], s31, 1
128; GCN: s_swappc_b64
129
130; GCN-DAG: v_readlane_b32 s4, v40, 0
131; GCN-DAG: v_readlane_b32 s5, v40, 1
132
133; GCN: s_sub_u32 s32, s32, 0x400
134; GCN-NEXT: v_readlane_b32 s33, [[CSR_VGPR]], [[FP_SPILL_LANE]]
135; GCN-NEXT: s_or_saveexec_b64 [[COPY_EXEC1:s\[[0-9]+:[0-9]+\]]], -1{{$}}
136; GCN-NEXT: buffer_load_dword [[CSR_VGPR]], off, s[0:3], s32 ; 4-byte Folded Reload
137; GCN-NEXT: s_mov_b64 exec, [[COPY_EXEC1]]
138; GCN-NEXT: s_waitcnt vmcnt(0)
139; GCN-NEXT: s_setpc_b64
140define void @callee_no_stack_with_call() #0 {
141  call void @external_void_func_void()
142  ret void
143}
144
145declare hidden void @external_void_func_void() #0
146
147; Make sure if a CSR vgpr is used for SGPR spilling, it is saved and
148; restored. No FP is required.
149;
150; GCN-LABEL: {{^}}callee_func_sgpr_spill_no_calls:
151; GCN: s_or_saveexec_b64 [[COPY_EXEC0:s\[[0-9]+:[0-9]+\]]], -1{{$}}
152; GCN-NEXT: buffer_store_dword [[CSR_VGPR:v[0-9]+]], off, s[0:3], s32 ; 4-byte Folded Spill
153; GCN-NEXT: s_mov_b64 exec, [[COPY_EXEC0]]
154; GCN: v_writelane_b32 [[CSR_VGPR]], s
155; GCN: v_writelane_b32 [[CSR_VGPR]], s
156
157; GCN: ;;#ASMSTART
158; GCN: v_readlane_b32 s{{[0-9]+}}, [[CSR_VGPR]]
159; GCN: v_readlane_b32 s{{[0-9]+}}, [[CSR_VGPR]]
160
161; GCN: s_or_saveexec_b64 [[COPY_EXEC1:s\[[0-9]+:[0-9]+\]]], -1{{$}}
162; GCN-NEXT: buffer_load_dword [[CSR_VGPR]], off, s[0:3], s32 ; 4-byte Folded Reload
163; GCN-NEXT: s_mov_b64 exec, [[COPY_EXEC1]]
164; GCN-NEXT: s_waitcnt
165; GCN-NEXT: s_setpc_b64
166define void @callee_func_sgpr_spill_no_calls(i32 %in) #0 {
167  call void asm sideeffect "", "~{v0},~{v1},~{v2},~{v3},~{v4},~{v5},~{v6},~{v7}"() #0
168  call void asm sideeffect "", "~{v8},~{v9},~{v10},~{v11},~{v12},~{v13},~{v14},~{v15}"() #0
169  call void asm sideeffect "", "~{v16},~{v17},~{v18},~{v19},~{v20},~{v21},~{v22},~{v23}"() #0
170  call void asm sideeffect "", "~{v24},~{v25},~{v26},~{v27},~{v28},~{v29},~{v30},~{v31}"() #0
171  call void asm sideeffect "", "~{v32},~{v33},~{v34},~{v35},~{v36},~{v37},~{v38},~{v39}"() #0
172
173  %wide.sgpr0 = call <16 x i32> asm sideeffect "; def $0", "=s" () #0
174  %wide.sgpr1 = call <16 x i32> asm sideeffect "; def $0", "=s" () #0
175  %wide.sgpr2 = call <16 x i32> asm sideeffect "; def $0", "=s" () #0
176  %wide.sgpr5 = call <16 x i32> asm sideeffect "; def $0", "=s" () #0
177  %wide.sgpr3 = call <8 x i32> asm sideeffect "; def $0", "=s" () #0
178  %wide.sgpr4 = call <2 x i32> asm sideeffect "; def $0", "=s" () #0
179
180  call void asm sideeffect "; use $0", "s"(<16 x i32> %wide.sgpr0) #0
181  call void asm sideeffect "; use $0", "s"(<16 x i32> %wide.sgpr1) #0
182  call void asm sideeffect "; use $0", "s"(<16 x i32> %wide.sgpr2) #0
183  call void asm sideeffect "; use $0", "s"(<8 x i32> %wide.sgpr3) #0
184  call void asm sideeffect "; use $0", "s"(<2 x i32> %wide.sgpr4) #0
185  call void asm sideeffect "; use $0", "s"(<16 x i32> %wide.sgpr5) #0
186  ret void
187}
188
189; Has no spilled CSR VGPRs used for SGPR spilling, so no need to
190; enable all lanes and restore.
191
192; GCN-LABEL: {{^}}spill_only_csr_sgpr:
193; GCN: s_waitcnt
194; GCN-NEXT: v_writelane_b32 v0, s42, 0
195; GCN-NEXT: ;;#ASMSTART
196; GCN-NEXT: ; clobber s42
197; GCN-NEXT: ;;#ASMEND
198; GCN-NEXT: v_readlane_b32 s42, v0, 0
199; GCN-NEXT: s_setpc_b64
200define void @spill_only_csr_sgpr() {
201  call void asm sideeffect "; clobber s42", "~{s42}"()
202  ret void
203}
204
205; TODO: Can the SP inc/deec be remvoed?
206; GCN-LABEL: {{^}}callee_with_stack_no_fp_elim_csr_vgpr:
207; GCN: s_waitcnt
208; GCN-NEXT:s_mov_b32 [[FP_COPY:s[0-9]+]], s33
209; GCN-NEXT: s_mov_b32 s33, s32
210; GCN: v_mov_b32_e32 [[ZERO:v[0-9]+]], 0
211; GCN-DAG: buffer_store_dword v41, off, s[0:3], s33 ; 4-byte Folded Spill
212; GCN-DAG: buffer_store_dword [[ZERO]], off, s[0:3], s33 offset:8
213
214; GCN:	;;#ASMSTART
215; GCN-NEXT: ; clobber v41
216; GCN-NEXT: ;;#ASMEND
217
218; GCN: buffer_load_dword v41, off, s[0:3], s33 ; 4-byte Folded Reload
219; GCN: s_add_u32 s32, s32, 0x300
220; GCN-NEXT: s_sub_u32 s32, s32, 0x300
221; GCN-NEXT: s_mov_b32 s33, s4
222; GCN-NEXT: s_waitcnt vmcnt(0)
223; GCN-NEXT: s_setpc_b64
224define void @callee_with_stack_no_fp_elim_csr_vgpr() #1 {
225  %alloca = alloca i32, addrspace(5)
226  store volatile i32 0, i32 addrspace(5)* %alloca
227  call void asm sideeffect "; clobber v41", "~{v41}"()
228  ret void
229}
230
231; Use a copy to a free SGPR instead of introducing a second CSR VGPR.
232; GCN-LABEL: {{^}}last_lane_vgpr_for_fp_csr:
233; GCN: s_waitcnt
234; GCN-NEXT: v_writelane_b32 v1, s33, 63
235; GCN-NEXT: s_mov_b32 s33, s32
236; GCN: buffer_store_dword v41, off, s[0:3], s33 ; 4-byte Folded Spill
237; GCN-COUNT-63: v_writelane_b32 v1
238; GCN: buffer_store_dword v{{[0-9]+}}, off, s[0:3], s33 offset:8
239; GCN: ;;#ASMSTART
240; GCN-COUNT-63: v_readlane_b32 s{{[0-9]+}}, v1
241
242; GCN: s_add_u32 s32, s32, 0x300
243; GCN-NEXT: s_sub_u32 s32, s32, 0x300
244; GCN-NEXT: v_readlane_b32 s33, v1, 63
245; GCN-NEXT: s_waitcnt vmcnt(0)
246; GCN-NEXT: s_setpc_b64
247define void @last_lane_vgpr_for_fp_csr() #1 {
248  %alloca = alloca i32, addrspace(5)
249  store volatile i32 0, i32 addrspace(5)* %alloca
250  call void asm sideeffect "; clobber v41", "~{v41}"()
251  call void asm sideeffect "",
252    "~{s40},~{s41},~{s42},~{s43},~{s44},~{s45},~{s46},~{s47},~{s48},~{s49}
253    ,~{s50},~{s51},~{s52},~{s53},~{s54},~{s55},~{s56},~{s57},~{s58},~{s59}
254    ,~{s60},~{s61},~{s62},~{s63},~{s64},~{s65},~{s66},~{s67},~{s68},~{s69}
255    ,~{s70},~{s71},~{s72},~{s73},~{s74},~{s75},~{s76},~{s77},~{s78},~{s79}
256    ,~{s80},~{s81},~{s82},~{s83},~{s84},~{s85},~{s86},~{s87},~{s88},~{s89}
257    ,~{s90},~{s91},~{s92},~{s93},~{s94},~{s95},~{s96},~{s97},~{s98},~{s99}
258    ,~{s100},~{s101},~{s102}"() #1
259
260  ret void
261}
262
263; Use a copy to a free SGPR instead of introducing a second CSR VGPR.
264; GCN-LABEL: {{^}}no_new_vgpr_for_fp_csr:
265; GCN: s_waitcnt
266; GCN-NEXT: s_mov_b32 [[FP_COPY:s[0-9]+]], s33
267; GCN-NEXT: s_mov_b32 s33, s32
268; GCN-NEXT: buffer_store_dword v41, off, s[0:3], s33 ; 4-byte Folded Spill
269; GCN-COUNT-64: v_writelane_b32 v1,
270
271; GCN: buffer_store_dword
272; GCN: ;;#ASMSTART
273; GCN-COUNT-64: v_readlane_b32 s{{[0-9]+}}, v1
274
275; GCN: buffer_load_dword v41, off, s[0:3], s33 ; 4-byte Folded Reload
276; GCN: s_add_u32 s32, s32, 0x300
277; GCN-NEXT: s_sub_u32 s32, s32, 0x300
278; GCN-NEXT: s_mov_b32 s33, [[FP_COPY]]
279; GCN-NEXT: s_waitcnt vmcnt(0)
280; GCN-NEXT: s_setpc_b64
281define void @no_new_vgpr_for_fp_csr() #1 {
282  %alloca = alloca i32, addrspace(5)
283  store volatile i32 0, i32 addrspace(5)* %alloca
284  call void asm sideeffect "; clobber v41", "~{v41}"()
285  call void asm sideeffect "",
286    "~{s39},~{s40},~{s41},~{s42},~{s43},~{s44},~{s45},~{s46},~{s47},~{s48},~{s49}
287    ,~{s50},~{s51},~{s52},~{s53},~{s54},~{s55},~{s56},~{s57},~{s58},~{s59}
288    ,~{s60},~{s61},~{s62},~{s63},~{s64},~{s65},~{s66},~{s67},~{s68},~{s69}
289    ,~{s70},~{s71},~{s72},~{s73},~{s74},~{s75},~{s76},~{s77},~{s78},~{s79}
290    ,~{s80},~{s81},~{s82},~{s83},~{s84},~{s85},~{s86},~{s87},~{s88},~{s89}
291    ,~{s90},~{s91},~{s92},~{s93},~{s94},~{s95},~{s96},~{s97},~{s98},~{s99}
292    ,~{s100},~{s101},~{s102}"() #1
293
294  ret void
295}
296
297; GCN-LABEL: {{^}}realign_stack_no_fp_elim:
298; GCN: s_waitcnt
299; GCN-NEXT: s_add_u32 [[SCRATCH:s[0-9]+]], s32, 0x7ffc0
300; GCN-NEXT: s_mov_b32 s4, s33
301; GCN-NEXT: s_and_b32 s33, [[SCRATCH]], 0xfff80000
302; GCN-NEXT: s_add_u32 s32, s32, 0x100000
303; GCN-NEXT: v_mov_b32_e32 [[ZERO:v[0-9]+]], 0
304; GCN-NEXT: buffer_store_dword [[ZERO]], off, s[0:3], s33
305; GCN-NEXT: s_sub_u32 s32, s32, 0x100000
306; GCN-NEXT: s_mov_b32 s33, s4
307; GCN-NEXT: s_waitcnt vmcnt(0)
308; GCN-NEXT: s_setpc_b64
309define void @realign_stack_no_fp_elim() #1 {
310  %alloca = alloca i32, align 8192, addrspace(5)
311  store volatile i32 0, i32 addrspace(5)* %alloca
312  ret void
313}
314
315; GCN-LABEL: {{^}}no_unused_non_csr_sgpr_for_fp:
316; GCN: s_waitcnt
317; GCN-NEXT: v_writelane_b32 v1, s33, 2
318; GCN-NEXT: v_writelane_b32 v1, s30, 0
319; GCN-NEXT: s_mov_b32 s33, s32
320; GCN: v_mov_b32_e32 [[ZERO:v[0-9]+]], 0
321; GCN: v_writelane_b32 v1, s31, 1
322; GCN: buffer_store_dword [[ZERO]], off, s[0:3], s33 offset:4
323; GCN: ;;#ASMSTART
324; GCN: v_readlane_b32 s4, v1, 0
325; GCN-NEXT: s_add_u32 s32, s32, 0x200
326; GCN-NEXT: v_readlane_b32 s5, v1, 1
327; GCN-NEXT: s_sub_u32 s32, s32, 0x200
328; GCN-NEXT: v_readlane_b32 s33, v1, 2
329; GCN-NEXT: s_waitcnt vmcnt(0)
330; GCN-NEXT: s_setpc_b64 s[4:5]
331define void @no_unused_non_csr_sgpr_for_fp() #1 {
332  %alloca = alloca i32, addrspace(5)
333  store volatile i32 0, i32 addrspace(5)* %alloca
334
335  ; Use all clobberable registers, so FP has to spill to a VGPR.
336  call void asm sideeffect "",
337    "~{s0},~{s1},~{s2},~{s3},~{s4},~{s5},~{s6},~{s7},~{s8},~{s9}
338    ,~{s10},~{s11},~{s12},~{s13},~{s14},~{s15},~{s16},~{s17},~{s18},~{s19}
339    ,~{s20},~{s21},~{s22},~{s23},~{s24},~{s25},~{s26},~{s27},~{s28},~{s29}
340    ,~{s30},~{s31}"() #0
341
342  ret void
343}
344
345; Need a new CSR VGPR to satisfy the FP spill.
346; GCN-LABEL: {{^}}no_unused_non_csr_sgpr_for_fp_no_scratch_vgpr:
347; GCN: s_waitcnt
348; GCN-NEXT: s_or_saveexec_b64 [[COPY_EXEC0:s\[[0-9]+:[0-9]+\]]], -1{{$}}
349; GCN-NEXT: buffer_store_dword [[CSR_VGPR:v[0-9]+]], off, s[0:3], s32 offset:8 ; 4-byte Folded Spill
350; GCN-NEXT: s_mov_b64 exec, [[COPY_EXEC0]]
351; GCN-NEXT: v_writelane_b32 [[CSR_VGPR]], s33, 2
352; GCN-NEXT: v_writelane_b32 [[CSR_VGPR]], s30, 0
353; GCN-NEXT: s_mov_b32 s33, s32
354
355; GCN-DAG: v_writelane_b32 [[CSR_VGPR]], s31, 1
356; GCN-DAG: buffer_store_dword
357; GCN: s_add_u32 s32, s32, 0x300{{$}}
358
359; GCN: ;;#ASMSTART
360
361; GCN: v_readlane_b32 s4, [[CSR_VGPR]], 0
362; GCN-NEXT: v_readlane_b32 s5, [[CSR_VGPR]], 1
363; GCN-NEXT: s_sub_u32 s32, s32, 0x300{{$}}
364; GCN-NEXT: v_readlane_b32 s33, [[CSR_VGPR]], 2
365; GCN-NEXT: s_or_saveexec_b64 [[COPY_EXEC1:s\[[0-9]+:[0-9]+\]]], -1{{$}}
366; GCN-NEXT: buffer_load_dword [[CSR_VGPR]], off, s[0:3], s32 offset:8 ; 4-byte Folded Reload
367; GCN-NEXT: s_mov_b64 exec, [[COPY_EXEC1]]
368; GCN-NEXT: s_waitcnt vmcnt(0)
369; GCN-NEXT: s_setpc_b64
370define void @no_unused_non_csr_sgpr_for_fp_no_scratch_vgpr() #1 {
371  %alloca = alloca i32, addrspace(5)
372  store volatile i32 0, i32 addrspace(5)* %alloca
373
374  ; Use all clobberable registers, so FP has to spill to a VGPR.
375  call void asm sideeffect "",
376    "~{s0},~{s1},~{s2},~{s3},~{s4},~{s5},~{s6},~{s7},~{s8},~{s9}
377    ,~{s10},~{s11},~{s12},~{s13},~{s14},~{s15},~{s16},~{s17},~{s18},~{s19}
378    ,~{s20},~{s21},~{s22},~{s23},~{s24},~{s25},~{s26},~{s27},~{s28},~{s29}
379    ,~{s30},~{s31}"() #0
380
381  call void asm sideeffect "; clobber nonpreserved initial VGPRs",
382    "~{v0},~{v1},~{v2},~{v3},~{v4},~{v5},~{v6},~{v7},~{v8},~{v9}
383    ,~{v10},~{v11},~{v12},~{v13},~{v14},~{v15},~{v16},~{v17},~{v18},~{v19}
384    ,~{v20},~{v21},~{v22},~{v23},~{v24},~{v25},~{v26},~{v27},~{v28},~{v29}
385    ,~{v30},~{v31},~{v32},~{v33},~{v34},~{v35},~{v36},~{v37},~{v38},~{v39}"() #1
386
387  ret void
388}
389
390; The byval argument exceeds the MUBUF constant offset, so a scratch
391; register is needed to access the CSR VGPR slot.
392; GCN-LABEL: {{^}}scratch_reg_needed_mubuf_offset:
393; GCN: s_waitcnt
394; GCN-NEXT: s_or_saveexec_b64 [[COPY_EXEC0:s\[[0-9]+:[0-9]+\]]], -1{{$}}
395; GCN-NEXT: v_mov_b32_e32 [[SCRATCH_VGPR:v[0-9]+]], 0x1008
396; GCN-NEXT: buffer_store_dword [[CSR_VGPR:v[0-9]+]], [[SCRATCH_VGPR]], s[0:3], s32 offen ; 4-byte Folded Spill
397; GCN-NEXT: s_mov_b64 exec, [[COPY_EXEC0]]
398; GCN-NEXT: v_writelane_b32 [[CSR_VGPR]], s33, 2
399; GCN-NEXT: v_writelane_b32 [[CSR_VGPR]], s30, 0
400; GCN-NEXT: s_mov_b32 s33, s32
401; GCN-DAG: v_writelane_b32 [[CSR_VGPR]], s31, 1
402; GCN-DAG: s_add_u32 s32, s32, 0x40300{{$}}
403; GCN-DAG: buffer_store_dword
404
405; GCN: ;;#ASMSTART
406
407; GCN: v_readlane_b32 s4, [[CSR_VGPR]], 0
408; GCN-NEXT: v_readlane_b32 s5, [[CSR_VGPR]], 1
409; GCN-NEXT: s_sub_u32 s32, s32, 0x40300{{$}}
410; GCN-NEXT: v_readlane_b32 s33, [[CSR_VGPR]], 2
411; GCN-NEXT: s_or_saveexec_b64 [[COPY_EXEC1:s\[[0-9]+:[0-9]+\]]], -1{{$}}
412; GCN-NEXT: v_mov_b32_e32 [[SCRATCH_VGPR:v[0-9]+]], 0x1008
413; GCN-NEXT: buffer_load_dword [[CSR_VGPR]], [[SCRATCH_VGPR]], s[0:3], s32 offen ; 4-byte Folded Reload
414; GCN-NEXT: s_mov_b64 exec, [[COPY_EXEC1]]
415; GCN-NEXT: s_waitcnt vmcnt(0)
416; GCN-NEXT: s_setpc_b64
417define void @scratch_reg_needed_mubuf_offset([4096 x i8] addrspace(5)* byval align 4 %arg) #1 {
418  %alloca = alloca i32, addrspace(5)
419  store volatile i32 0, i32 addrspace(5)* %alloca
420
421  ; Use all clobberable registers, so FP has to spill to a VGPR.
422  call void asm sideeffect "; clobber nonpreserved SGPRs",
423    "~{s0},~{s1},~{s2},~{s3},~{s4},~{s5},~{s6},~{s7},~{s8},~{s9}
424    ,~{s10},~{s11},~{s12},~{s13},~{s14},~{s15},~{s16},~{s17},~{s18},~{s19}
425    ,~{s20},~{s21},~{s22},~{s23},~{s24},~{s25},~{s26},~{s27},~{s28},~{s29}
426    ,~{s30},~{s31}"() #0
427
428  ; Use all clobberable VGPRs, so a CSR spill is needed for the VGPR
429  call void asm sideeffect "; clobber nonpreserved VGPRs",
430    "~{v0},~{v1},~{v2},~{v3},~{v4},~{v5},~{v6},~{v7},~{v8},~{v9}
431    ,~{v10},~{v11},~{v12},~{v13},~{v14},~{v15},~{v16},~{v17},~{v18},~{v19}
432    ,~{v20},~{v21},~{v22},~{v23},~{v24},~{v25},~{v26},~{v27},~{v28},~{v29}
433    ,~{v30},~{v31},~{v32},~{v33},~{v34},~{v35},~{v36},~{v37},~{v38},~{v39}"() #1
434
435  ret void
436}
437
438; GCN-LABEL: {{^}}local_empty_func:
439; GCN: s_waitcnt
440; GCN-NEXT: s_setpc_b64
441define internal void @local_empty_func() #0 {
442  ret void
443}
444
445; An FP is needed, despite not needing any spills
446; TODO: Ccould see callee does not use stack and omit FP.
447; GCN-LABEL: {{^}}ipra_call_with_stack:
448; GCN: s_mov_b32 [[FP_COPY:s[0-9]+]], s33
449; GCN: s_mov_b32 s33, s32
450; GCN: s_add_u32 s32, s32, 0x400
451; GCN: buffer_store_dword v{{[0-9]+}}, off, s[0:3], s33{{$}}
452; GCN: s_swappc_b64
453; GCN: s_sub_u32 s32, s32, 0x400
454; GCN: s_mov_b32 s33, [[FP_COPY:s[0-9]+]]
455define void @ipra_call_with_stack() #0 {
456  %alloca = alloca i32, addrspace(5)
457  store volatile i32 0, i32 addrspace(5)* %alloca
458  call void @local_empty_func()
459  ret void
460}
461
462; With no free registers, we must spill the FP to memory.
463; GCN-LABEL: {{^}}callee_need_to_spill_fp_to_memory:
464; GCN: s_or_saveexec_b64 [[COPY_EXEC1:s\[[0-9]+:[0-9]+\]]], -1{{$}}
465; GCN: v_mov_b32_e32 [[TMP_VGPR1:v[0-9]+]], s33
466; GCN: buffer_store_dword [[TMP_VGPR1]], off, s[0:3], s32 offset:[[OFF:[0-9]+]]
467; GCN: s_mov_b64 exec, [[COPY_EXEC1]]
468; GCN: s_mov_b32 s33, s32
469; GCN: s_or_saveexec_b64 [[COPY_EXEC2:s\[[0-9]+:[0-9]+\]]], -1{{$}}
470; GCN: buffer_load_dword [[TMP_VGPR2:v[0-9]+]], off, s[0:3], s32 offset:[[OFF]]
471; GCN: s_waitcnt vmcnt(0)
472; GCN: v_readfirstlane_b32 s33, [[TMP_VGPR2]]
473; GCN: s_mov_b64 exec, [[COPY_EXEC2]]
474; GCN: s_setpc_b64
475define void @callee_need_to_spill_fp_to_memory() #3 {
476  call void asm sideeffect "; clobber nonpreserved SGPRs",
477    "~{s4},~{s5},~{s6},~{s7},~{s8},~{s9}
478    ,~{s10},~{s11},~{s12},~{s13},~{s14},~{s15},~{s16},~{s17},~{s18},~{s19}
479    ,~{s20},~{s21},~{s22},~{s23},~{s24},~{s25},~{s26},~{s27},~{s28},~{s29}
480    ,~{vcc}"()
481
482  call void asm sideeffect "; clobber all VGPRs",
483    "~{v0},~{v1},~{v2},~{v3},~{v4},~{v5},~{v6},~{v7},~{v8},~{v9}
484    ,~{v10},~{v11},~{v12},~{v13},~{v14},~{v15},~{v16},~{v17},~{v18},~{v19}
485    ,~{v20},~{v21},~{v22},~{v23},~{v24},~{v25},~{v26},~{v27},~{v28},~{v29}
486    ,~{v30},~{v31},~{v32},~{v33},~{v34},~{v35},~{v36},~{v37},~{v38},~{v39}"()
487  ret void
488}
489
490; If we have a reserved VGPR that can be used for SGPR spills, we may still
491; need to spill the FP to memory if there are no free lanes in the reserved
492; VGPR.
493; GCN-LABEL: {{^}}callee_need_to_spill_fp_to_memory_full_reserved_vgpr:
494; GCN: s_or_saveexec_b64 [[COPY_EXEC1:s\[[0-9]+:[0-9]+\]]], -1{{$}}
495; GCN: v_mov_b32_e32 [[TMP_VGPR1:v[0-9]+]], s33
496; GCN: buffer_store_dword [[TMP_VGPR1]], off, s[0:3], s32 offset:[[OFF:[0-9]+]]
497; GCN: s_mov_b64 exec, [[COPY_EXEC1]]
498; GCN-NOT: v_writelane_b32 v40, s33
499; GCN: s_mov_b32 s33, s32
500; GCN-NOT: v_readlane_b32 s33, v40
501; GCN: s_or_saveexec_b64 [[COPY_EXEC2:s\[[0-9]+:[0-9]+\]]], -1{{$}}
502; GCN: buffer_load_dword [[TMP_VGPR2:v[0-9]+]], off, s[0:3], s32 offset:[[OFF]]
503; GCN: v_readfirstlane_b32 s33, [[TMP_VGPR2]]
504; GCN: s_mov_b64 exec, [[COPY_EXEC2]]
505; GCN: s_setpc_b64
506define void @callee_need_to_spill_fp_to_memory_full_reserved_vgpr() #3 {
507  call void asm sideeffect "; clobber nonpreserved SGPRs and 64 CSRs",
508    "~{s4},~{s5},~{s6},~{s7},~{s8},~{s9}
509    ,~{s10},~{s11},~{s12},~{s13},~{s14},~{s15},~{s16},~{s17},~{s18},~{s19}
510    ,~{s20},~{s21},~{s22},~{s23},~{s24},~{s25},~{s26},~{s27},~{s28},~{s29}
511    ,~{s40},~{s41},~{s42},~{s43},~{s44},~{s45},~{s46},~{s47},~{s48},~{s49}
512    ,~{s50},~{s51},~{s52},~{s53},~{s54},~{s55},~{s56},~{s57},~{s58},~{s59}
513    ,~{s60},~{s61},~{s62},~{s63},~{s64},~{s65},~{s66},~{s67},~{s68},~{s69}
514    ,~{s70},~{s71},~{s72},~{s73},~{s74},~{s75},~{s76},~{s77},~{s78},~{s79}
515    ,~{s80},~{s81},~{s82},~{s83},~{s84},~{s85},~{s86},~{s87},~{s88},~{s89}
516    ,~{s90},~{s91},~{s92},~{s93},~{s94},~{s95},~{s96},~{s97},~{s98},~{s99}
517    ,~{s100},~{s101},~{s102},~{s39},~{vcc}"()
518
519  call void asm sideeffect "; clobber all VGPRs except CSR v40",
520    "~{v0},~{v1},~{v2},~{v3},~{v4},~{v5},~{v6},~{v7},~{v8},~{v9}
521    ,~{v10},~{v11},~{v12},~{v13},~{v14},~{v15},~{v16},~{v17},~{v18},~{v19}
522    ,~{v20},~{v21},~{v22},~{v23},~{v24},~{v25},~{v26},~{v27},~{v28},~{v29}
523    ,~{v30},~{v31},~{v32},~{v33},~{v34},~{v35},~{v36},~{v37},~{v38}"()
524  ret void
525}
526
527; If the size of the offset exceeds the MUBUF offset field we need another
528; scratch VGPR to hold the offset.
529; GCN-LABEL: {{^}}spill_fp_to_memory_scratch_reg_needed_mubuf_offset
530; GCN: s_or_saveexec_b64 s[4:5], -1
531; GCN: v_mov_b32_e32 v0, s33
532; GCN-NOT: v_mov_b32_e32 v0, 0x100c
533; GCN-NEXT: v_mov_b32_e32 v1, 0x100c
534; GCN-NEXT: buffer_store_dword v0, v1, s[0:3], s32 offen
535define void @spill_fp_to_memory_scratch_reg_needed_mubuf_offset([4096 x i8] addrspace(5)* byval align 4 %arg) #3 {
536  %alloca = alloca i32, addrspace(5)
537  store volatile i32 0, i32 addrspace(5)* %alloca
538
539  call void asm sideeffect "; clobber nonpreserved SGPRs and 64 CSRs",
540    "~{s4},~{s5},~{s6},~{s7},~{s8},~{s9}
541    ,~{s10},~{s11},~{s12},~{s13},~{s14},~{s15},~{s16},~{s17},~{s18},~{s19}
542    ,~{s20},~{s21},~{s22},~{s23},~{s24},~{s25},~{s26},~{s27},~{s28},~{s29}
543    ,~{s40},~{s41},~{s42},~{s43},~{s44},~{s45},~{s46},~{s47},~{s48},~{s49}
544    ,~{s50},~{s51},~{s52},~{s53},~{s54},~{s55},~{s56},~{s57},~{s58},~{s59}
545    ,~{s60},~{s61},~{s62},~{s63},~{s64},~{s65},~{s66},~{s67},~{s68},~{s69}
546    ,~{s70},~{s71},~{s72},~{s73},~{s74},~{s75},~{s76},~{s77},~{s78},~{s79}
547    ,~{s80},~{s81},~{s82},~{s83},~{s84},~{s85},~{s86},~{s87},~{s88},~{s89}
548    ,~{s90},~{s91},~{s92},~{s93},~{s94},~{s95},~{s96},~{s97},~{s98},~{s99}
549    ,~{s100},~{s101},~{s102},~{s39},~{vcc}"()
550
551  call void asm sideeffect "; clobber all VGPRs except CSR v40",
552    "~{v0},~{v1},~{v2},~{v3},~{v4},~{v5},~{v6},~{v7},~{v8},~{v9}
553    ,~{v10},~{v11},~{v12},~{v13},~{v14},~{v15},~{v16},~{v17},~{v18},~{v19}
554    ,~{v20},~{v21},~{v22},~{v23},~{v24},~{v25},~{v26},~{v27},~{v28},~{v29}
555    ,~{v30},~{v31},~{v32},~{v33},~{v34},~{v35},~{v36},~{v37},~{v38}"()
556  ret void
557}
558
559attributes #0 = { nounwind }
560attributes #1 = { nounwind "frame-pointer"="all" }
561attributes #2 = { nounwind "frame-pointer"="non-leaf" }
562attributes #3 = { nounwind "frame-pointer"="all" "amdgpu-waves-per-eu"="6,6" }
563