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
14define 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
24define 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
40define 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
50define 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
62define 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
76define 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
87define 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
99define 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
112define 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
122define 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
134define 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
145define 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
156define 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
166define 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
177define 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
187define 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
198define 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
208define 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
227define 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
237define 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
248define 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
258define 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
269define 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
279define 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
290define 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
300define 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
313define 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
321define 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
334define 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
342define 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
352define 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
364define 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
373define 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
383define 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
394define 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
402define 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
412define 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
421define 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
430define 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
438define 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
447define 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
455define 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
464define 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
472define 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
488define 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
496define 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
505define 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
513define 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
522define 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
530define 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
539define 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
547define 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}
552