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