R600 -> AMDGPU rename
[oota-llvm.git] / test / CodeGen / AMDGPU / local-atomics.ll
1 ; RUN: llc -march=amdgcn -mcpu=SI -verify-machineinstrs < %s | FileCheck -check-prefix=SI -check-prefix=GCN -check-prefix=FUNC %s
2 ; RUN: llc -march=amdgcn -mcpu=bonaire -verify-machineinstrs < %s | FileCheck -check-prefix=CIVI -check-prefix=GCN -check-prefix=FUNC %s
3 ; RUN: llc -march=amdgcn -mcpu=tonga -verify-machineinstrs < %s | FileCheck -check-prefix=CIVI -check-prefix=GCN -check-prefix=FUNC %s
4 ; RUN: llc -march=r600 -mcpu=redwood -verify-machineinstrs < %s | FileCheck -check-prefix=EG -check-prefix=FUNC %s
5
6 ; FUNC-LABEL: {{^}}lds_atomic_xchg_ret_i32:
7 ; EG: LDS_WRXCHG_RET *
8 ; GCN: v_mov_b32_e32 [[DATA:v[0-9]+]], 4
9 ; GCN: s_load_dword [[SPTR:s[0-9]+]],
10 ; GCN: v_mov_b32_e32 [[VPTR:v[0-9]+]], [[SPTR]]
11 ; GCN: ds_wrxchg_rtn_b32 [[RESULT:v[0-9]+]], [[VPTR]], [[DATA]]
12 ; GCN: buffer_store_dword [[RESULT]],
13 ; GCN: s_endpgm
14 define void @lds_atomic_xchg_ret_i32(i32 addrspace(1)* %out, i32 addrspace(3)* %ptr) nounwind {
15   %result = atomicrmw xchg i32 addrspace(3)* %ptr, i32 4 seq_cst
16   store i32 %result, i32 addrspace(1)* %out, align 4
17   ret void
18 }
19
20 ; FUNC-LABEL: {{^}}lds_atomic_xchg_ret_i32_offset:
21 ; EG: LDS_WRXCHG_RET *
22 ; GCN: ds_wrxchg_rtn_b32 v{{[0-9]+}}, v{{[0-9]+}}, v{{[0-9]+}} offset:16
23 ; GCN: s_endpgm
24 define void @lds_atomic_xchg_ret_i32_offset(i32 addrspace(1)* %out, i32 addrspace(3)* %ptr) nounwind {
25   %gep = getelementptr i32, i32 addrspace(3)* %ptr, i32 4
26   %result = atomicrmw xchg i32 addrspace(3)* %gep, i32 4 seq_cst
27   store i32 %result, i32 addrspace(1)* %out, align 4
28   ret void
29 }
30
31 ; XXX - Is it really necessary to load 4 into VGPR?
32 ; FUNC-LABEL: {{^}}lds_atomic_add_ret_i32:
33 ; EG: LDS_ADD_RET *
34 ; GCN: v_mov_b32_e32 [[DATA:v[0-9]+]], 4
35 ; GCN: s_load_dword [[SPTR:s[0-9]+]],
36 ; GCN: v_mov_b32_e32 [[VPTR:v[0-9]+]], [[SPTR]]
37 ; GCN: ds_add_rtn_u32 [[RESULT:v[0-9]+]], [[VPTR]], [[DATA]]
38 ; GCN: buffer_store_dword [[RESULT]],
39 ; GCN: s_endpgm
40 define void @lds_atomic_add_ret_i32(i32 addrspace(1)* %out, i32 addrspace(3)* %ptr) nounwind {
41   %result = atomicrmw add i32 addrspace(3)* %ptr, i32 4 seq_cst
42   store i32 %result, i32 addrspace(1)* %out, align 4
43   ret void
44 }
45
46 ; FUNC-LABEL: {{^}}lds_atomic_add_ret_i32_offset:
47 ; EG: LDS_ADD_RET *
48 ; GCN: ds_add_rtn_u32 v{{[0-9]+}}, v{{[0-9]+}}, v{{[0-9]+}} offset:16
49 ; GCN: s_endpgm
50 define void @lds_atomic_add_ret_i32_offset(i32 addrspace(1)* %out, i32 addrspace(3)* %ptr) nounwind {
51   %gep = getelementptr i32, i32 addrspace(3)* %ptr, i32 4
52   %result = atomicrmw add i32 addrspace(3)* %gep, i32 4 seq_cst
53   store i32 %result, i32 addrspace(1)* %out, align 4
54   ret void
55 }
56
57 ; FUNC-LABEL: {{^}}lds_atomic_add_ret_i32_bad_si_offset:
58 ; EG: LDS_ADD_RET *
59 ; SI: ds_add_rtn_u32 v{{[0-9]+}}, v{{[0-9]+}}, v{{[0-9]+}}
60 ; CIVI: ds_add_rtn_u32 v{{[0-9]+}}, v{{[0-9]+}}, v{{[0-9]+}} offset:16
61 ; GCN: s_endpgm
62 define void @lds_atomic_add_ret_i32_bad_si_offset(i32 addrspace(1)* %out, i32 addrspace(3)* %ptr, i32 %a, i32 %b) nounwind {
63   %sub = sub i32 %a, %b
64   %add = add i32 %sub, 4
65   %gep = getelementptr i32, i32 addrspace(3)* %ptr, i32 %add
66   %result = atomicrmw add i32 addrspace(3)* %gep, i32 4 seq_cst
67   store i32 %result, i32 addrspace(1)* %out, align 4
68   ret void
69 }
70
71 ; FUNC-LABEL: {{^}}lds_atomic_inc_ret_i32:
72 ; EG: LDS_ADD_RET *
73 ; GCN: v_mov_b32_e32 [[NEGONE:v[0-9]+]], -1
74 ; GCN: ds_inc_rtn_u32 v{{[0-9]+}}, v{{[0-9]+}}, [[NEGONE]]
75 ; GCN: s_endpgm
76 define void @lds_atomic_inc_ret_i32(i32 addrspace(1)* %out, i32 addrspace(3)* %ptr) nounwind {
77   %result = atomicrmw add i32 addrspace(3)* %ptr, i32 1 seq_cst
78   store i32 %result, i32 addrspace(1)* %out, align 4
79   ret void
80 }
81
82 ; FUNC-LABEL: {{^}}lds_atomic_inc_ret_i32_offset:
83 ; EG: LDS_ADD_RET *
84 ; GCN: v_mov_b32_e32 [[NEGONE:v[0-9]+]], -1
85 ; GCN: ds_inc_rtn_u32 v{{[0-9]+}}, v{{[0-9]+}}, [[NEGONE]] offset:16
86 ; GCN: s_endpgm
87 define void @lds_atomic_inc_ret_i32_offset(i32 addrspace(1)* %out, i32 addrspace(3)* %ptr) nounwind {
88   %gep = getelementptr i32, i32 addrspace(3)* %ptr, i32 4
89   %result = atomicrmw add i32 addrspace(3)* %gep, i32 1 seq_cst
90   store i32 %result, i32 addrspace(1)* %out, align 4
91   ret void
92 }
93
94 ; FUNC-LABEL: {{^}}lds_atomic_inc_ret_i32_bad_si_offset:
95 ; EG: LDS_ADD_RET *
96 ; SI: ds_inc_rtn_u32 v{{[0-9]+}}, v{{[0-9]+}}, v{{[0-9]+}}
97 ; CIVI: ds_inc_rtn_u32 v{{[0-9]+}}, v{{[0-9]+}}, v{{[0-9]+}} offset:16
98 ; GCN: s_endpgm
99 define void @lds_atomic_inc_ret_i32_bad_si_offset(i32 addrspace(1)* %out, i32 addrspace(3)* %ptr, i32 %a, i32 %b) nounwind {
100   %sub = sub i32 %a, %b
101   %add = add i32 %sub, 4
102   %gep = getelementptr i32, i32 addrspace(3)* %ptr, i32 %add
103   %result = atomicrmw add i32 addrspace(3)* %gep, i32 1 seq_cst
104   store i32 %result, i32 addrspace(1)* %out, align 4
105   ret void
106 }
107
108 ; FUNC-LABEL: {{^}}lds_atomic_sub_ret_i32:
109 ; EG: LDS_SUB_RET *
110 ; GCN: ds_sub_rtn_u32
111 ; GCN: s_endpgm
112 define void @lds_atomic_sub_ret_i32(i32 addrspace(1)* %out, i32 addrspace(3)* %ptr) nounwind {
113   %result = atomicrmw sub i32 addrspace(3)* %ptr, i32 4 seq_cst
114   store i32 %result, i32 addrspace(1)* %out, align 4
115   ret void
116 }
117
118 ; FUNC-LABEL: {{^}}lds_atomic_sub_ret_i32_offset:
119 ; EG: LDS_SUB_RET *
120 ; GCN: ds_sub_rtn_u32 v{{[0-9]+}}, v{{[0-9]+}}, v{{[0-9]+}} offset:16
121 ; GCN: s_endpgm
122 define void @lds_atomic_sub_ret_i32_offset(i32 addrspace(1)* %out, i32 addrspace(3)* %ptr) nounwind {
123   %gep = getelementptr i32, i32 addrspace(3)* %ptr, i32 4
124   %result = atomicrmw sub i32 addrspace(3)* %gep, i32 4 seq_cst
125   store i32 %result, i32 addrspace(1)* %out, align 4
126   ret void
127 }
128
129 ; FUNC-LABEL: {{^}}lds_atomic_dec_ret_i32:
130 ; EG: LDS_SUB_RET *
131 ; GCN: v_mov_b32_e32 [[NEGONE:v[0-9]+]], -1
132 ; GCN: ds_dec_rtn_u32  v{{[0-9]+}}, v{{[0-9]+}}, [[NEGONE]]
133 ; GCN: s_endpgm
134 define void @lds_atomic_dec_ret_i32(i32 addrspace(1)* %out, i32 addrspace(3)* %ptr) nounwind {
135   %result = atomicrmw sub i32 addrspace(3)* %ptr, i32 1 seq_cst
136   store i32 %result, i32 addrspace(1)* %out, align 4
137   ret void
138 }
139
140 ; FUNC-LABEL: {{^}}lds_atomic_dec_ret_i32_offset:
141 ; EG: LDS_SUB_RET *
142 ; GCN: v_mov_b32_e32 [[NEGONE:v[0-9]+]], -1
143 ; GCN: ds_dec_rtn_u32 v{{[0-9]+}}, v{{[0-9]+}}, [[NEGONE]] offset:16
144 ; GCN: s_endpgm
145 define void @lds_atomic_dec_ret_i32_offset(i32 addrspace(1)* %out, i32 addrspace(3)* %ptr) nounwind {
146   %gep = getelementptr i32, i32 addrspace(3)* %ptr, i32 4
147   %result = atomicrmw sub i32 addrspace(3)* %gep, i32 1 seq_cst
148   store i32 %result, i32 addrspace(1)* %out, align 4
149   ret void
150 }
151
152 ; FUNC-LABEL: {{^}}lds_atomic_and_ret_i32:
153 ; EG: LDS_AND_RET *
154 ; GCN: ds_and_rtn_b32
155 ; GCN: s_endpgm
156 define void @lds_atomic_and_ret_i32(i32 addrspace(1)* %out, i32 addrspace(3)* %ptr) nounwind {
157   %result = atomicrmw and i32 addrspace(3)* %ptr, i32 4 seq_cst
158   store i32 %result, i32 addrspace(1)* %out, align 4
159   ret void
160 }
161
162 ; FUNC-LABEL: {{^}}lds_atomic_and_ret_i32_offset:
163 ; EG: LDS_AND_RET *
164 ; GCN: ds_and_rtn_b32 v{{[0-9]+}}, v{{[0-9]+}}, v{{[0-9]+}} offset:16
165 ; GCN: s_endpgm
166 define void @lds_atomic_and_ret_i32_offset(i32 addrspace(1)* %out, i32 addrspace(3)* %ptr) nounwind {
167   %gep = getelementptr i32, i32 addrspace(3)* %ptr, i32 4
168   %result = atomicrmw and i32 addrspace(3)* %gep, i32 4 seq_cst
169   store i32 %result, i32 addrspace(1)* %out, align 4
170   ret void
171 }
172
173 ; FUNC-LABEL: {{^}}lds_atomic_or_ret_i32:
174 ; EG: LDS_OR_RET *
175 ; GCN: ds_or_rtn_b32
176 ; GCN: s_endpgm
177 define void @lds_atomic_or_ret_i32(i32 addrspace(1)* %out, i32 addrspace(3)* %ptr) nounwind {
178   %result = atomicrmw or i32 addrspace(3)* %ptr, i32 4 seq_cst
179   store i32 %result, i32 addrspace(1)* %out, align 4
180   ret void
181 }
182
183 ; FUNC-LABEL: {{^}}lds_atomic_or_ret_i32_offset:
184 ; EG: LDS_OR_RET *
185 ; GCN: ds_or_rtn_b32 v{{[0-9]+}}, v{{[0-9]+}}, v{{[0-9]+}} offset:16
186 ; GCN: s_endpgm
187 define void @lds_atomic_or_ret_i32_offset(i32 addrspace(1)* %out, i32 addrspace(3)* %ptr) nounwind {
188   %gep = getelementptr i32, i32 addrspace(3)* %ptr, i32 4
189   %result = atomicrmw or i32 addrspace(3)* %gep, i32 4 seq_cst
190   store i32 %result, i32 addrspace(1)* %out, align 4
191   ret void
192 }
193
194 ; FUNC-LABEL: {{^}}lds_atomic_xor_ret_i32:
195 ; EG: LDS_XOR_RET *
196 ; GCN: ds_xor_rtn_b32
197 ; GCN: s_endpgm
198 define void @lds_atomic_xor_ret_i32(i32 addrspace(1)* %out, i32 addrspace(3)* %ptr) nounwind {
199   %result = atomicrmw xor i32 addrspace(3)* %ptr, i32 4 seq_cst
200   store i32 %result, i32 addrspace(1)* %out, align 4
201   ret void
202 }
203
204 ; FUNC-LABEL: {{^}}lds_atomic_xor_ret_i32_offset:
205 ; EG: LDS_XOR_RET *
206 ; GCN: ds_xor_rtn_b32 v{{[0-9]+}}, v{{[0-9]+}}, v{{[0-9]+}} offset:16
207 ; GCN: s_endpgm
208 define void @lds_atomic_xor_ret_i32_offset(i32 addrspace(1)* %out, i32 addrspace(3)* %ptr) nounwind {
209   %gep = getelementptr i32, i32 addrspace(3)* %ptr, i32 4
210   %result = atomicrmw xor i32 addrspace(3)* %gep, i32 4 seq_cst
211   store i32 %result, i32 addrspace(1)* %out, align 4
212   ret void
213 }
214
215 ; FIXME: There is no atomic nand instr
216 ; XFUNC-LABEL: {{^}}lds_atomic_nand_ret_i32:uction, so we somehow need to expand this.
217 ; define void @lds_atomic_nand_ret_i32(i32 addrspace(1)* %out, i32 addrspace(3)* %ptr) nounwind {
218 ;   %result = atomicrmw nand i32 addrspace(3)* %ptr, i32 4 seq_cst
219 ;   store i32 %result, i32 addrspace(1)* %out, align 4
220 ;   ret void
221 ; }
222
223 ; FUNC-LABEL: {{^}}lds_atomic_min_ret_i32:
224 ; EG: LDS_MIN_INT_RET *
225 ; GCN: ds_min_rtn_i32
226 ; GCN: s_endpgm
227 define void @lds_atomic_min_ret_i32(i32 addrspace(1)* %out, i32 addrspace(3)* %ptr) nounwind {
228   %result = atomicrmw min i32 addrspace(3)* %ptr, i32 4 seq_cst
229   store i32 %result, i32 addrspace(1)* %out, align 4
230   ret void
231 }
232
233 ; FUNC-LABEL: {{^}}lds_atomic_min_ret_i32_offset:
234 ; EG: LDS_MIN_INT_RET *
235 ; GCN: ds_min_rtn_i32 v{{[0-9]+}}, v{{[0-9]+}}, v{{[0-9]+}} offset:16
236 ; GCN: s_endpgm
237 define void @lds_atomic_min_ret_i32_offset(i32 addrspace(1)* %out, i32 addrspace(3)* %ptr) nounwind {
238   %gep = getelementptr i32, i32 addrspace(3)* %ptr, i32 4
239   %result = atomicrmw min i32 addrspace(3)* %gep, i32 4 seq_cst
240   store i32 %result, i32 addrspace(1)* %out, align 4
241   ret void
242 }
243
244 ; FUNC-LABEL: {{^}}lds_atomic_max_ret_i32:
245 ; EG: LDS_MAX_INT_RET *
246 ; GCN: ds_max_rtn_i32
247 ; GCN: s_endpgm
248 define void @lds_atomic_max_ret_i32(i32 addrspace(1)* %out, i32 addrspace(3)* %ptr) nounwind {
249   %result = atomicrmw max i32 addrspace(3)* %ptr, i32 4 seq_cst
250   store i32 %result, i32 addrspace(1)* %out, align 4
251   ret void
252 }
253
254 ; FUNC-LABEL: {{^}}lds_atomic_max_ret_i32_offset:
255 ; EG: LDS_MAX_INT_RET *
256 ; GCN: ds_max_rtn_i32 v{{[0-9]+}}, v{{[0-9]+}}, v{{[0-9]+}} offset:16
257 ; GCN: s_endpgm
258 define void @lds_atomic_max_ret_i32_offset(i32 addrspace(1)* %out, i32 addrspace(3)* %ptr) nounwind {
259   %gep = getelementptr i32, i32 addrspace(3)* %ptr, i32 4
260   %result = atomicrmw max i32 addrspace(3)* %gep, i32 4 seq_cst
261   store i32 %result, i32 addrspace(1)* %out, align 4
262   ret void
263 }
264
265 ; FUNC-LABEL: {{^}}lds_atomic_umin_ret_i32:
266 ; EG: LDS_MIN_UINT_RET *
267 ; GCN: ds_min_rtn_u32
268 ; GCN: s_endpgm
269 define void @lds_atomic_umin_ret_i32(i32 addrspace(1)* %out, i32 addrspace(3)* %ptr) nounwind {
270   %result = atomicrmw umin i32 addrspace(3)* %ptr, i32 4 seq_cst
271   store i32 %result, i32 addrspace(1)* %out, align 4
272   ret void
273 }
274
275 ; FUNC-LABEL: {{^}}lds_atomic_umin_ret_i32_offset:
276 ; EG: LDS_MIN_UINT_RET *
277 ; GCN: ds_min_rtn_u32 v{{[0-9]+}}, v{{[0-9]+}}, v{{[0-9]+}} offset:16
278 ; GCN: s_endpgm
279 define void @lds_atomic_umin_ret_i32_offset(i32 addrspace(1)* %out, i32 addrspace(3)* %ptr) nounwind {
280   %gep = getelementptr i32, i32 addrspace(3)* %ptr, i32 4
281   %result = atomicrmw umin i32 addrspace(3)* %gep, i32 4 seq_cst
282   store i32 %result, i32 addrspace(1)* %out, align 4
283   ret void
284 }
285
286 ; FUNC-LABEL: {{^}}lds_atomic_umax_ret_i32:
287 ; EG: LDS_MAX_UINT_RET *
288 ; GCN: ds_max_rtn_u32
289 ; GCN: s_endpgm
290 define void @lds_atomic_umax_ret_i32(i32 addrspace(1)* %out, i32 addrspace(3)* %ptr) nounwind {
291   %result = atomicrmw umax i32 addrspace(3)* %ptr, i32 4 seq_cst
292   store i32 %result, i32 addrspace(1)* %out, align 4
293   ret void
294 }
295
296 ; FUNC-LABEL: {{^}}lds_atomic_umax_ret_i32_offset:
297 ; EG: LDS_MAX_UINT_RET *
298 ; GCN: ds_max_rtn_u32 v{{[0-9]+}}, v{{[0-9]+}}, v{{[0-9]+}} offset:16
299 ; GCN: s_endpgm
300 define void @lds_atomic_umax_ret_i32_offset(i32 addrspace(1)* %out, i32 addrspace(3)* %ptr) nounwind {
301   %gep = getelementptr i32, i32 addrspace(3)* %ptr, i32 4
302   %result = atomicrmw umax i32 addrspace(3)* %gep, i32 4 seq_cst
303   store i32 %result, i32 addrspace(1)* %out, align 4
304   ret void
305 }
306
307 ; FUNC-LABEL: {{^}}lds_atomic_xchg_noret_i32:
308 ; GCN: s_load_dword [[SPTR:s[0-9]+]],
309 ; GCN: v_mov_b32_e32 [[DATA:v[0-9]+]], 4
310 ; GCN: v_mov_b32_e32 [[VPTR:v[0-9]+]], [[SPTR]]
311 ; GCN: ds_wrxchg_rtn_b32 [[RESULT:v[0-9]+]], [[VPTR]], [[DATA]]
312 ; GCN: s_endpgm
313 define void @lds_atomic_xchg_noret_i32(i32 addrspace(3)* %ptr) nounwind {
314   %result = atomicrmw xchg i32 addrspace(3)* %ptr, i32 4 seq_cst
315   ret void
316 }
317
318 ; FUNC-LABEL: {{^}}lds_atomic_xchg_noret_i32_offset:
319 ; GCN: ds_wrxchg_rtn_b32 v{{[0-9]+}}, v{{[0-9]+}}, v{{[0-9]+}} offset:16
320 ; GCN: s_endpgm
321 define void @lds_atomic_xchg_noret_i32_offset(i32 addrspace(3)* %ptr) nounwind {
322   %gep = getelementptr i32, i32 addrspace(3)* %ptr, i32 4
323   %result = atomicrmw xchg i32 addrspace(3)* %gep, i32 4 seq_cst
324   ret void
325 }
326
327 ; XXX - Is it really necessary to load 4 into VGPR?
328 ; FUNC-LABEL: {{^}}lds_atomic_add_noret_i32:
329 ; GCN: s_load_dword [[SPTR:s[0-9]+]],
330 ; GCN: v_mov_b32_e32 [[DATA:v[0-9]+]], 4
331 ; GCN: v_mov_b32_e32 [[VPTR:v[0-9]+]], [[SPTR]]
332 ; GCN: ds_add_u32 [[VPTR]], [[DATA]]
333 ; GCN: s_endpgm
334 define void @lds_atomic_add_noret_i32(i32 addrspace(3)* %ptr) nounwind {
335   %result = atomicrmw add i32 addrspace(3)* %ptr, i32 4 seq_cst
336   ret void
337 }
338
339 ; FUNC-LABEL: {{^}}lds_atomic_add_noret_i32_offset:
340 ; GCN: ds_add_u32 v{{[0-9]+}}, v{{[0-9]+}} offset:16
341 ; GCN: s_endpgm
342 define void @lds_atomic_add_noret_i32_offset(i32 addrspace(3)* %ptr) nounwind {
343   %gep = getelementptr i32, i32 addrspace(3)* %ptr, i32 4
344   %result = atomicrmw add i32 addrspace(3)* %gep, i32 4 seq_cst
345   ret void
346 }
347
348 ; FUNC-LABEL: {{^}}lds_atomic_add_noret_i32_bad_si_offset
349 ; SI: ds_add_u32 v{{[0-9]+}}, v{{[0-9]+}}
350 ; CIVI: ds_add_u32 v{{[0-9]+}}, v{{[0-9]+}} offset:16
351 ; GCN: s_endpgm
352 define void @lds_atomic_add_noret_i32_bad_si_offset(i32 addrspace(3)* %ptr, i32 %a, i32 %b) nounwind {
353   %sub = sub i32 %a, %b
354   %add = add i32 %sub, 4
355   %gep = getelementptr i32, i32 addrspace(3)* %ptr, i32 %add
356   %result = atomicrmw add i32 addrspace(3)* %gep, i32 4 seq_cst
357   ret void
358 }
359
360 ; FUNC-LABEL: {{^}}lds_atomic_inc_noret_i32:
361 ; GCN: v_mov_b32_e32 [[NEGONE:v[0-9]+]], -1
362 ; GCN: ds_inc_u32 v{{[0-9]+}}, [[NEGONE]]
363 ; GCN: s_endpgm
364 define void @lds_atomic_inc_noret_i32(i32 addrspace(3)* %ptr) nounwind {
365   %result = atomicrmw add i32 addrspace(3)* %ptr, i32 1 seq_cst
366   ret void
367 }
368
369 ; FUNC-LABEL: {{^}}lds_atomic_inc_noret_i32_offset:
370 ; GCN: v_mov_b32_e32 [[NEGONE:v[0-9]+]], -1
371 ; GCN: ds_inc_u32 v{{[0-9]+}}, [[NEGONE]] offset:16
372 ; GCN: s_endpgm
373 define void @lds_atomic_inc_noret_i32_offset(i32 addrspace(3)* %ptr) nounwind {
374   %gep = getelementptr i32, i32 addrspace(3)* %ptr, i32 4
375   %result = atomicrmw add i32 addrspace(3)* %gep, i32 1 seq_cst
376   ret void
377 }
378
379 ; FUNC-LABEL: {{^}}lds_atomic_inc_noret_i32_bad_si_offset:
380 ; SI: ds_inc_u32 v{{[0-9]+}}, v{{[0-9]+}}
381 ; CIVI: ds_inc_u32 v{{[0-9]+}}, v{{[0-9]+}} offset:16
382 ; GCN: s_endpgm
383 define void @lds_atomic_inc_noret_i32_bad_si_offset(i32 addrspace(3)* %ptr, i32 %a, i32 %b) nounwind {
384   %sub = sub i32 %a, %b
385   %add = add i32 %sub, 4
386   %gep = getelementptr i32, i32 addrspace(3)* %ptr, i32 %add
387   %result = atomicrmw add i32 addrspace(3)* %gep, i32 1 seq_cst
388   ret void
389 }
390
391 ; FUNC-LABEL: {{^}}lds_atomic_sub_noret_i32:
392 ; GCN: ds_sub_u32
393 ; GCN: s_endpgm
394 define void @lds_atomic_sub_noret_i32(i32 addrspace(3)* %ptr) nounwind {
395   %result = atomicrmw sub i32 addrspace(3)* %ptr, i32 4 seq_cst
396   ret void
397 }
398
399 ; FUNC-LABEL: {{^}}lds_atomic_sub_noret_i32_offset:
400 ; GCN: ds_sub_u32 v{{[0-9]+}}, v{{[0-9]+}} offset:16
401 ; GCN: s_endpgm
402 define void @lds_atomic_sub_noret_i32_offset(i32 addrspace(3)* %ptr) nounwind {
403   %gep = getelementptr i32, i32 addrspace(3)* %ptr, i32 4
404   %result = atomicrmw sub i32 addrspace(3)* %gep, i32 4 seq_cst
405   ret void
406 }
407
408 ; FUNC-LABEL: {{^}}lds_atomic_dec_noret_i32:
409 ; GCN: v_mov_b32_e32 [[NEGONE:v[0-9]+]], -1
410 ; GCN: ds_dec_u32  v{{[0-9]+}}, [[NEGONE]]
411 ; GCN: s_endpgm
412 define void @lds_atomic_dec_noret_i32(i32 addrspace(3)* %ptr) nounwind {
413   %result = atomicrmw sub i32 addrspace(3)* %ptr, i32 1 seq_cst
414   ret void
415 }
416
417 ; FUNC-LABEL: {{^}}lds_atomic_dec_noret_i32_offset:
418 ; GCN: v_mov_b32_e32 [[NEGONE:v[0-9]+]], -1
419 ; GCN: ds_dec_u32 v{{[0-9]+}}, [[NEGONE]] offset:16
420 ; GCN: s_endpgm
421 define void @lds_atomic_dec_noret_i32_offset(i32 addrspace(3)* %ptr) nounwind {
422   %gep = getelementptr i32, i32 addrspace(3)* %ptr, i32 4
423   %result = atomicrmw sub i32 addrspace(3)* %gep, i32 1 seq_cst
424   ret void
425 }
426
427 ; FUNC-LABEL: {{^}}lds_atomic_and_noret_i32:
428 ; GCN: ds_and_b32
429 ; GCN: s_endpgm
430 define void @lds_atomic_and_noret_i32(i32 addrspace(3)* %ptr) nounwind {
431   %result = atomicrmw and i32 addrspace(3)* %ptr, i32 4 seq_cst
432   ret void
433 }
434
435 ; FUNC-LABEL: {{^}}lds_atomic_and_noret_i32_offset:
436 ; GCN: ds_and_b32 v{{[0-9]+}}, v{{[0-9]+}} offset:16
437 ; GCN: s_endpgm
438 define void @lds_atomic_and_noret_i32_offset(i32 addrspace(3)* %ptr) nounwind {
439   %gep = getelementptr i32, i32 addrspace(3)* %ptr, i32 4
440   %result = atomicrmw and i32 addrspace(3)* %gep, i32 4 seq_cst
441   ret void
442 }
443
444 ; FUNC-LABEL: {{^}}lds_atomic_or_noret_i32:
445 ; GCN: ds_or_b32
446 ; GCN: s_endpgm
447 define void @lds_atomic_or_noret_i32(i32 addrspace(3)* %ptr) nounwind {
448   %result = atomicrmw or i32 addrspace(3)* %ptr, i32 4 seq_cst
449   ret void
450 }
451
452 ; FUNC-LABEL: {{^}}lds_atomic_or_noret_i32_offset:
453 ; GCN: ds_or_b32 v{{[0-9]+}}, v{{[0-9]+}} offset:16
454 ; GCN: s_endpgm
455 define void @lds_atomic_or_noret_i32_offset(i32 addrspace(3)* %ptr) nounwind {
456   %gep = getelementptr i32, i32 addrspace(3)* %ptr, i32 4
457   %result = atomicrmw or i32 addrspace(3)* %gep, i32 4 seq_cst
458   ret void
459 }
460
461 ; FUNC-LABEL: {{^}}lds_atomic_xor_noret_i32:
462 ; GCN: ds_xor_b32
463 ; GCN: s_endpgm
464 define void @lds_atomic_xor_noret_i32(i32 addrspace(3)* %ptr) nounwind {
465   %result = atomicrmw xor i32 addrspace(3)* %ptr, i32 4 seq_cst
466   ret void
467 }
468
469 ; FUNC-LABEL: {{^}}lds_atomic_xor_noret_i32_offset:
470 ; GCN: ds_xor_b32 v{{[0-9]+}}, v{{[0-9]+}} offset:16
471 ; GCN: s_endpgm
472 define void @lds_atomic_xor_noret_i32_offset(i32 addrspace(3)* %ptr) nounwind {
473   %gep = getelementptr i32, i32 addrspace(3)* %ptr, i32 4
474   %result = atomicrmw xor i32 addrspace(3)* %gep, i32 4 seq_cst
475   ret void
476 }
477
478 ; FIXME: There is no atomic nand instr
479 ; XFUNC-LABEL: {{^}}lds_atomic_nand_noret_i32:uction, so we somehow need to expand this.
480 ; define void @lds_atomic_nand_noret_i32(i32 addrspace(3)* %ptr) nounwind {
481 ;   %result = atomicrmw nand i32 addrspace(3)* %ptr, i32 4 seq_cst
482 ;   ret void
483 ; }
484
485 ; FUNC-LABEL: {{^}}lds_atomic_min_noret_i32:
486 ; GCN: ds_min_i32
487 ; GCN: s_endpgm
488 define void @lds_atomic_min_noret_i32(i32 addrspace(3)* %ptr) nounwind {
489   %result = atomicrmw min i32 addrspace(3)* %ptr, i32 4 seq_cst
490   ret void
491 }
492
493 ; FUNC-LABEL: {{^}}lds_atomic_min_noret_i32_offset:
494 ; GCN: ds_min_i32 v{{[0-9]+}}, v{{[0-9]+}} offset:16
495 ; GCN: s_endpgm
496 define void @lds_atomic_min_noret_i32_offset(i32 addrspace(3)* %ptr) nounwind {
497   %gep = getelementptr i32, i32 addrspace(3)* %ptr, i32 4
498   %result = atomicrmw min i32 addrspace(3)* %gep, i32 4 seq_cst
499   ret void
500 }
501
502 ; FUNC-LABEL: {{^}}lds_atomic_max_noret_i32:
503 ; GCN: ds_max_i32
504 ; GCN: s_endpgm
505 define void @lds_atomic_max_noret_i32(i32 addrspace(3)* %ptr) nounwind {
506   %result = atomicrmw max i32 addrspace(3)* %ptr, i32 4 seq_cst
507   ret void
508 }
509
510 ; FUNC-LABEL: {{^}}lds_atomic_max_noret_i32_offset:
511 ; GCN: ds_max_i32 v{{[0-9]+}}, v{{[0-9]+}} offset:16
512 ; GCN: s_endpgm
513 define void @lds_atomic_max_noret_i32_offset(i32 addrspace(3)* %ptr) nounwind {
514   %gep = getelementptr i32, i32 addrspace(3)* %ptr, i32 4
515   %result = atomicrmw max i32 addrspace(3)* %gep, i32 4 seq_cst
516   ret void
517 }
518
519 ; FUNC-LABEL: {{^}}lds_atomic_umin_noret_i32:
520 ; GCN: ds_min_u32
521 ; GCN: s_endpgm
522 define void @lds_atomic_umin_noret_i32(i32 addrspace(3)* %ptr) nounwind {
523   %result = atomicrmw umin i32 addrspace(3)* %ptr, i32 4 seq_cst
524   ret void
525 }
526
527 ; FUNC-LABEL: {{^}}lds_atomic_umin_noret_i32_offset:
528 ; GCN: ds_min_u32 v{{[0-9]+}}, v{{[0-9]+}} offset:16
529 ; GCN: s_endpgm
530 define void @lds_atomic_umin_noret_i32_offset(i32 addrspace(3)* %ptr) nounwind {
531   %gep = getelementptr i32, i32 addrspace(3)* %ptr, i32 4
532   %result = atomicrmw umin i32 addrspace(3)* %gep, i32 4 seq_cst
533   ret void
534 }
535
536 ; FUNC-LABEL: {{^}}lds_atomic_umax_noret_i32:
537 ; GCN: ds_max_u32
538 ; GCN: s_endpgm
539 define void @lds_atomic_umax_noret_i32(i32 addrspace(3)* %ptr) nounwind {
540   %result = atomicrmw umax i32 addrspace(3)* %ptr, i32 4 seq_cst
541   ret void
542 }
543
544 ; FUNC-LABEL: {{^}}lds_atomic_umax_noret_i32_offset:
545 ; GCN: ds_max_u32 v{{[0-9]+}}, v{{[0-9]+}} offset:16
546 ; GCN: s_endpgm
547 define void @lds_atomic_umax_noret_i32_offset(i32 addrspace(3)* %ptr) nounwind {
548   %gep = getelementptr i32, i32 addrspace(3)* %ptr, i32 4
549   %result = atomicrmw umax i32 addrspace(3)* %gep, i32 4 seq_cst
550   ret void
551 }