1; RUN: llc -mtriple=amdgcn-amd-amdhsa -mcpu=gfx900 -enable-misched=0 -post-RA-scheduler=0 -stress-regalloc=8 < %s | FileCheck %s
2
3; Test that the VGPR spiller correctly switches to SGPR offsets when the
4; instruction offset field would overflow, and that it accounts for memory
5; swizzling.
6
7; CHECK-LABEL: test_inst_offset_kernel
8define amdgpu_kernel void @test_inst_offset_kernel() {
9entry:
10  ; Occupy 4092 bytes of scratch, so the offset of the spill of %a just fits in
11  ; the instruction offset field.
12  %alloca = alloca i8, i32 4088, align 4, addrspace(5)
13  %buf = bitcast i8 addrspace(5)* %alloca to i32 addrspace(5)*
14
15  %aptr = getelementptr i32, i32 addrspace(5)* %buf, i32 1
16  ; CHECK: buffer_store_dword v{{[0-9]+}}, off, s[{{[0-9]+:[0-9]+}}], s{{[0-9]+}} offset:4092 ; 4-byte Folded Spill
17  %a = load volatile i32, i32 addrspace(5)* %aptr
18
19  ; Force %a to spill.
20  call void asm sideeffect "", "~{v0},~{v1},~{v2},~{v3},~{v4},~{v5},~{v6},~{v7}" ()
21
22  %outptr = getelementptr i32, i32 addrspace(5)* %buf, i32 1
23  store volatile i32 %a, i32 addrspace(5)* %outptr
24
25  ret void
26}
27
28; CHECK-LABEL: test_sgpr_offset_kernel
29define amdgpu_kernel void @test_sgpr_offset_kernel() {
30entry:
31  ; Occupy 4096 bytes of scratch, so the offset of the spill of %a does not
32  ; fit in the instruction, and has to live in the SGPR offset.
33  %alloca = alloca i8, i32 4092, align 4, addrspace(5)
34  %buf = bitcast i8 addrspace(5)* %alloca to i32 addrspace(5)*
35
36  %aptr = getelementptr i32, i32 addrspace(5)* %buf, i32 1
37  ; 0x40000 / 64 = 4096 (for wave64)
38  ; CHECK: s_add_u32 s6, s7, 0x40000
39  ; CHECK: buffer_store_dword v{{[0-9]+}}, off, s[{{[0-9]+:[0-9]+}}], s6 ; 4-byte Folded Spill
40  %a = load volatile i32, i32 addrspace(5)* %aptr
41
42  ; Force %a to spill
43  call void asm sideeffect "", "~{v0},~{v1},~{v2},~{v3},~{v4},~{v5},~{v6},~{v7}" ()
44
45  %outptr = getelementptr i32, i32 addrspace(5)* %buf, i32 1
46  store volatile i32 %a, i32 addrspace(5)* %outptr
47
48  ret void
49}
50
51; CHECK-LABEL: test_sgpr_offset_kernel_scavenge_fail
52define amdgpu_kernel void @test_sgpr_offset_kernel_scavenge_fail() #1 {
53entry:
54  ; Occupy 4096 bytes of scratch, so the offset of the spill of %a does not
55  ; fit in the instruction, and has to live in the SGPR offset.
56  %alloca = alloca i8, i32 4092, align 4, addrspace(5)
57  %buf = bitcast i8 addrspace(5)* %alloca to i32 addrspace(5)*
58
59  %aptr = getelementptr i32, i32 addrspace(5)* %buf, i32 1
60
61  ; 0x40000 / 64 = 4096 (for wave64)
62  %a = load volatile i32, i32 addrspace(5)* %aptr
63
64  %asm = call { i32, i32, i32, i32, i32, i32, i32, i32 } asm sideeffect "", "=s,=s,=s,=s,=s,=s,=s,=s"()
65  %asm0 = extractvalue { i32, i32, i32, i32, i32, i32, i32, i32 } %asm, 0
66  %asm1 = extractvalue { i32, i32, i32, i32, i32, i32, i32, i32 } %asm, 1
67  %asm2 = extractvalue { i32, i32, i32, i32, i32, i32, i32, i32 } %asm, 2
68  %asm3 = extractvalue { i32, i32, i32, i32, i32, i32, i32, i32 } %asm, 3
69  %asm4 = extractvalue { i32, i32, i32, i32, i32, i32, i32, i32 } %asm, 4
70  %asm5 = extractvalue { i32, i32, i32, i32, i32, i32, i32, i32 } %asm, 5
71  %asm6 = extractvalue { i32, i32, i32, i32, i32, i32, i32, i32 } %asm, 6
72  %asm7 = extractvalue { i32, i32, i32, i32, i32, i32, i32, i32 } %asm, 7
73
74  call void asm sideeffect "", "~{v0},~{v1},~{v2},~{v3},~{v4},~{v5},~{v6},~{v7}"() #0
75
76  ; CHECK: s_add_u32 s7, s7, 0x40000
77  ; CHECK: buffer_load_dword v{{[0-9]+}}, off, s[{{[0-9]+:[0-9]+}}], s7 ; 4-byte Folded Reload
78  ; CHECK: s_sub_u32 s7, s7, 0x40000
79
80   ; Force %a to spill with no free SGPRs
81  call void asm sideeffect "", "s,s,s,s,s,s,s,s,v"(i32 %asm0, i32 %asm1, i32 %asm2, i32 %asm3, i32 %asm4, i32 %asm5, i32 %asm6, i32 %asm7, i32 %a)
82  ret void
83}
84
85; CHECK-LABEL: test_sgpr_offset_subregs_kernel
86define amdgpu_kernel void @test_sgpr_offset_subregs_kernel() {
87entry:
88  ; Occupy 4088 bytes of scratch, so that the spill of the last subreg of %a
89  ; still fits below offset 4096 (4088 + 8 - 4 = 4092), and can be placed in
90  ; the instruction offset field.
91  %alloca = alloca i8, i32 4084, align 4, addrspace(5)
92  %bufv1 = bitcast i8 addrspace(5)* %alloca to i32 addrspace(5)*
93  %bufv2 = bitcast i8 addrspace(5)* %alloca to <2 x i32> addrspace(5)*
94
95  ; CHECK: buffer_store_dword v{{[0-9]+}}, off, s[{{[0-9]+:[0-9]+}}], s{{[0-9]+}} offset:4088 ; 4-byte Folded Spill
96  ; CHECK: buffer_store_dword v{{[0-9]+}}, off, s[{{[0-9]+:[0-9]+}}], s{{[0-9]+}} offset:4092 ; 4-byte Folded Spill
97  %aptr = getelementptr <2 x i32>, <2 x i32> addrspace(5)* %bufv2, i32 1
98  %a = load volatile <2 x i32>, <2 x i32> addrspace(5)* %aptr
99
100  ; Force %a to spill.
101  call void asm sideeffect "", "~{v0},~{v1},~{v2},~{v3},~{v4},~{v5},~{v6},~{v7}" ()
102
103  ; Ensure the alloca sticks around.
104  %bptr = getelementptr i32, i32 addrspace(5)* %bufv1, i32 1
105  %b = load volatile i32, i32 addrspace(5)* %bptr
106
107  ; Ensure the spill is of the full super-reg.
108  call void asm sideeffect "; $0", "r"(<2 x i32> %a)
109
110  ret void
111}
112
113; CHECK-LABEL: test_inst_offset_subregs_kernel
114define amdgpu_kernel void @test_inst_offset_subregs_kernel() {
115entry:
116  ; Occupy 4092 bytes of scratch, so that the spill of the last subreg of %a
117  ; does not fit below offset 4096 (4092 + 8 - 4 = 4096), and has to live
118  ; in the SGPR offset.
119  %alloca = alloca i8, i32 4088, align 4, addrspace(5)
120  %bufv1 = bitcast i8 addrspace(5)* %alloca to i32 addrspace(5)*
121  %bufv2 = bitcast i8 addrspace(5)* %alloca to <2 x i32> addrspace(5)*
122
123  ; 0x3ff00 / 64 = 4092 (for wave64)
124  ; CHECK: s_add_u32 s6, s7, 0x3ff00
125  ; CHECK: buffer_store_dword v{{[0-9]+}}, off, s[{{[0-9]+:[0-9]+}}], s6 ; 4-byte Folded Spill
126  ; CHECK: buffer_store_dword v{{[0-9]+}}, off, s[{{[0-9]+:[0-9]+}}], s6 offset:4 ; 4-byte Folded Spill
127  %aptr = getelementptr <2 x i32>, <2 x i32> addrspace(5)* %bufv2, i32 1
128  %a = load volatile <2 x i32>, <2 x i32> addrspace(5)* %aptr
129
130  ; Force %a to spill.
131  call void asm sideeffect "", "~{v0},~{v1},~{v2},~{v3},~{v4},~{v5},~{v6},~{v7}" ()
132
133  ; Ensure the alloca sticks around.
134  %bptr = getelementptr i32, i32 addrspace(5)* %bufv1, i32 1
135  %b = load volatile i32, i32 addrspace(5)* %bptr
136
137  ; Ensure the spill is of the full super-reg.
138  call void asm sideeffect "; $0", "r"(<2 x i32> %a)
139
140  ret void
141}
142
143; CHECK-LABEL: test_inst_offset_function
144define void @test_inst_offset_function() {
145entry:
146  ; Occupy 4092 bytes of scratch, so the offset of the spill of %a just fits in
147  ; the instruction offset field.
148  %alloca = alloca i8, i32 4088, align 4, addrspace(5)
149  %buf = bitcast i8 addrspace(5)* %alloca to i32 addrspace(5)*
150
151  %aptr = getelementptr i32, i32 addrspace(5)* %buf, i32 1
152  ; CHECK: buffer_store_dword v{{[0-9]+}}, off, s[{{[0-9]+:[0-9]+}}], s{{[0-9]+}} offset:4092 ; 4-byte Folded Spill
153  %a = load volatile i32, i32 addrspace(5)* %aptr
154
155  ; Force %a to spill.
156  call void asm sideeffect "", "~{v0},~{v1},~{v2},~{v3},~{v4},~{v5},~{v6},~{v7}" ()
157
158  %outptr = getelementptr i32, i32 addrspace(5)* %buf, i32 1
159  store volatile i32 %a, i32 addrspace(5)* %outptr
160
161  ret void
162}
163
164; CHECK-LABEL: test_sgpr_offset_function
165define void @test_sgpr_offset_function() {
166entry:
167  ; Occupy 4096 bytes of scratch, so the offset of the spill of %a does not
168  ; fit in the instruction, and has to live in the SGPR offset.
169  %alloca = alloca i8, i32 4092, align 4, addrspace(5)
170  %buf = bitcast i8 addrspace(5)* %alloca to i32 addrspace(5)*
171
172  %aptr = getelementptr i32, i32 addrspace(5)* %buf, i32 1
173  ; 0x40000 / 64 = 4096 (for wave64)
174  ; CHECK: s_add_u32 s6, s5, 0x40000
175  ; CHECK: buffer_store_dword v{{[0-9]+}}, off, s[{{[0-9]+:[0-9]+}}], s6 ; 4-byte Folded Spill
176  %a = load volatile i32, i32 addrspace(5)* %aptr
177
178  ; Force %a to spill
179  call void asm sideeffect "", "~{v0},~{v1},~{v2},~{v3},~{v4},~{v5},~{v6},~{v7}" ()
180
181  %outptr = getelementptr i32, i32 addrspace(5)* %buf, i32 1
182  store volatile i32 %a, i32 addrspace(5)* %outptr
183
184  ret void
185}
186
187; CHECK-LABEL: test_sgpr_offset_subregs_function
188define void @test_sgpr_offset_subregs_function() {
189entry:
190  ; Occupy 4088 bytes of scratch, so that the spill of the last subreg of %a
191  ; still fits below offset 4096 (4088 + 8 - 4 = 4092), and can be placed in
192  ; the instruction offset field.
193  %alloca = alloca i8, i32 4084, align 4, addrspace(5)
194  %bufv1 = bitcast i8 addrspace(5)* %alloca to i32 addrspace(5)*
195  %bufv2 = bitcast i8 addrspace(5)* %alloca to <2 x i32> addrspace(5)*
196
197  ; CHECK: buffer_store_dword v{{[0-9]+}}, off, s[{{[0-9]+:[0-9]+}}], s{{[0-9]+}} offset:4088 ; 4-byte Folded Spill
198  ; CHECK: buffer_store_dword v{{[0-9]+}}, off, s[{{[0-9]+:[0-9]+}}], s{{[0-9]+}} offset:4092 ; 4-byte Folded Spill
199  %aptr = getelementptr <2 x i32>, <2 x i32> addrspace(5)* %bufv2, i32 1
200  %a = load volatile <2 x i32>, <2 x i32> addrspace(5)* %aptr
201
202  ; Force %a to spill.
203  call void asm sideeffect "", "~{v0},~{v1},~{v2},~{v3},~{v4},~{v5},~{v6},~{v7}" ()
204
205  ; Ensure the alloca sticks around.
206  %bptr = getelementptr i32, i32 addrspace(5)* %bufv1, i32 1
207  %b = load volatile i32, i32 addrspace(5)* %bptr
208
209  ; Ensure the spill is of the full super-reg.
210  call void asm sideeffect "; $0", "r"(<2 x i32> %a)
211
212  ret void
213}
214
215; CHECK-LABEL: test_inst_offset_subregs_function
216define void @test_inst_offset_subregs_function() {
217entry:
218  ; Occupy 4092 bytes of scratch, so that the spill of the last subreg of %a
219  ; does not fit below offset 4096 (4092 + 8 - 4 = 4096), and has to live
220  ; in the SGPR offset.
221  %alloca = alloca i8, i32 4088, align 4, addrspace(5)
222  %bufv1 = bitcast i8 addrspace(5)* %alloca to i32 addrspace(5)*
223  %bufv2 = bitcast i8 addrspace(5)* %alloca to <2 x i32> addrspace(5)*
224
225  ; 0x3ff00 / 64 = 4092 (for wave64)
226  ; CHECK: s_add_u32 s6, s5, 0x3ff00
227  ; CHECK: buffer_store_dword v{{[0-9]+}}, off, s[{{[0-9]+:[0-9]+}}], s6 ; 4-byte Folded Spill
228  ; CHECK: buffer_store_dword v{{[0-9]+}}, off, s[{{[0-9]+:[0-9]+}}], s6 offset:4 ; 4-byte Folded Spill
229  %aptr = getelementptr <2 x i32>, <2 x i32> addrspace(5)* %bufv2, i32 1
230  %a = load volatile <2 x i32>, <2 x i32> addrspace(5)* %aptr
231
232  ; Force %a to spill.
233  call void asm sideeffect "", "~{v0},~{v1},~{v2},~{v3},~{v4},~{v5},~{v6},~{v7}" ()
234
235  ; Ensure the alloca sticks around.
236  %bptr = getelementptr i32, i32 addrspace(5)* %bufv1, i32 1
237  %b = load volatile i32, i32 addrspace(5)* %bptr
238
239  ; Ensure the spill is of the full super-reg.
240  call void asm sideeffect "; $0", "r"(<2 x i32> %a)
241
242  ret void
243}
244
245attributes #0 = { nounwind }
246attributes #1 = { nounwind "amdgpu-num-sgpr"="18" "amdgpu-num-vgpr"="8" }
247