1 ; RUN: llc -march=amdgcn -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: s_load_dword [[SPTR:s[0-9]+]], 9 ; GCN: v_mov_b32_e32 [[DATA:v[0-9]+]], 4 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: s_load_dword [[SPTR:s[0-9]+]], 35 ; GCN: v_mov_b32_e32 [[DATA:v[0-9]+]], 4 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_add1_ret_i32: 72 ; EG: LDS_ADD_RET * 73 ; GCN: v_mov_b32_e32 [[ONE:v[0-9]+]], 1{{$}} 74 ; GCN: ds_add_rtn_u32 v{{[0-9]+}}, v{{[0-9]+}}, [[ONE]] 75 ; GCN: s_endpgm 76 define void @lds_atomic_add1_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_add1_ret_i32_offset: 83 ; EG: LDS_ADD_RET * 84 ; GCN: v_mov_b32_e32 [[ONE:v[0-9]+]], 1{{$}} 85 ; GCN: ds_add_rtn_u32 v{{[0-9]+}}, v{{[0-9]+}}, [[ONE]] offset:16 86 ; GCN: s_endpgm 87 define void @lds_atomic_add1_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_add1_ret_i32_bad_si_offset: 95 ; EG: LDS_ADD_RET * 96 ; SI: ds_add_rtn_u32 v{{[0-9]+}}, v{{[0-9]+}}, v{{[0-9]+}} 97 ; CIVI: ds_add_rtn_u32 v{{[0-9]+}}, v{{[0-9]+}}, v{{[0-9]+}} offset:16 98 ; GCN: s_endpgm 99 define void @lds_atomic_add1_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_sub1_ret_i32: 130 ; EG: LDS_SUB_RET * 131 ; GCN: v_mov_b32_e32 [[ONE:v[0-9]+]], 1{{$}} 132 ; GCN: ds_sub_rtn_u32 v{{[0-9]+}}, v{{[0-9]+}}, [[ONE]] 133 ; GCN: s_endpgm 134 define void @lds_atomic_sub1_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_sub1_ret_i32_offset: 141 ; EG: LDS_SUB_RET * 142 ; GCN: v_mov_b32_e32 [[ONE:v[0-9]+]], 1{{$}} 143 ; GCN: ds_sub_rtn_u32 v{{[0-9]+}}, v{{[0-9]+}}, [[ONE]] offset:16 144 ; GCN: s_endpgm 145 define void @lds_atomic_sub1_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 ; FUNC-LABEL: {{^}}lds_atomic_add_noret_i32: 328 ; GCN: s_load_dword [[SPTR:s[0-9]+]], 329 ; GCN: v_mov_b32_e32 [[DATA:v[0-9]+]], 4 330 ; GCN: v_mov_b32_e32 [[VPTR:v[0-9]+]], [[SPTR]] 331 ; GCN: ds_add_u32 [[VPTR]], [[DATA]] 332 ; GCN: s_endpgm 333 define void @lds_atomic_add_noret_i32(i32 addrspace(3)* %ptr) nounwind { 334 %result = atomicrmw add i32 addrspace(3)* %ptr, i32 4 seq_cst 335 ret void 336 } 337 338 ; FUNC-LABEL: {{^}}lds_atomic_add_noret_i32_offset: 339 ; GCN: ds_add_u32 v{{[0-9]+}}, v{{[0-9]+}} offset:16 340 ; GCN: s_endpgm 341 define void @lds_atomic_add_noret_i32_offset(i32 addrspace(3)* %ptr) nounwind { 342 %gep = getelementptr i32, i32 addrspace(3)* %ptr, i32 4 343 %result = atomicrmw add i32 addrspace(3)* %gep, i32 4 seq_cst 344 ret void 345 } 346 347 ; FUNC-LABEL: {{^}}lds_atomic_add_noret_i32_bad_si_offset 348 ; SI: ds_add_u32 v{{[0-9]+}}, v{{[0-9]+}} 349 ; CIVI: ds_add_u32 v{{[0-9]+}}, v{{[0-9]+}} offset:16 350 ; GCN: s_endpgm 351 define void @lds_atomic_add_noret_i32_bad_si_offset(i32 addrspace(3)* %ptr, i32 %a, i32 %b) nounwind { 352 %sub = sub i32 %a, %b 353 %add = add i32 %sub, 4 354 %gep = getelementptr i32, i32 addrspace(3)* %ptr, i32 %add 355 %result = atomicrmw add i32 addrspace(3)* %gep, i32 4 seq_cst 356 ret void 357 } 358 359 ; FUNC-LABEL: {{^}}lds_atomic_add1_noret_i32: 360 ; GCN: v_mov_b32_e32 [[ONE:v[0-9]+]], 1{{$}} 361 ; GCN: ds_add_u32 v{{[0-9]+}}, [[ONE]] 362 ; GCN: s_endpgm 363 define void @lds_atomic_add1_noret_i32(i32 addrspace(3)* %ptr) nounwind { 364 %result = atomicrmw add i32 addrspace(3)* %ptr, i32 1 seq_cst 365 ret void 366 } 367 368 ; FUNC-LABEL: {{^}}lds_atomic_add1_noret_i32_offset: 369 ; GCN: v_mov_b32_e32 [[ONE:v[0-9]+]], 1{{$}} 370 ; GCN: ds_add_u32 v{{[0-9]+}}, [[ONE]] offset:16 371 ; GCN: s_endpgm 372 define void @lds_atomic_add1_noret_i32_offset(i32 addrspace(3)* %ptr) nounwind { 373 %gep = getelementptr i32, i32 addrspace(3)* %ptr, i32 4 374 %result = atomicrmw add i32 addrspace(3)* %gep, i32 1 seq_cst 375 ret void 376 } 377 378 ; FUNC-LABEL: {{^}}lds_atomic_add1_noret_i32_bad_si_offset: 379 ; SI: ds_add_u32 v{{[0-9]+}}, v{{[0-9]+}} 380 ; CIVI: ds_add_u32 v{{[0-9]+}}, v{{[0-9]+}} offset:16 381 ; GCN: s_endpgm 382 define void @lds_atomic_add1_noret_i32_bad_si_offset(i32 addrspace(3)* %ptr, i32 %a, i32 %b) nounwind { 383 %sub = sub i32 %a, %b 384 %add = add i32 %sub, 4 385 %gep = getelementptr i32, i32 addrspace(3)* %ptr, i32 %add 386 %result = atomicrmw add i32 addrspace(3)* %gep, i32 1 seq_cst 387 ret void 388 } 389 390 ; FUNC-LABEL: {{^}}lds_atomic_sub_noret_i32: 391 ; GCN: ds_sub_u32 392 ; GCN: s_endpgm 393 define void @lds_atomic_sub_noret_i32(i32 addrspace(3)* %ptr) nounwind { 394 %result = atomicrmw sub i32 addrspace(3)* %ptr, i32 4 seq_cst 395 ret void 396 } 397 398 ; FUNC-LABEL: {{^}}lds_atomic_sub_noret_i32_offset: 399 ; GCN: ds_sub_u32 v{{[0-9]+}}, v{{[0-9]+}} offset:16 400 ; GCN: s_endpgm 401 define void @lds_atomic_sub_noret_i32_offset(i32 addrspace(3)* %ptr) nounwind { 402 %gep = getelementptr i32, i32 addrspace(3)* %ptr, i32 4 403 %result = atomicrmw sub i32 addrspace(3)* %gep, i32 4 seq_cst 404 ret void 405 } 406 407 ; FUNC-LABEL: {{^}}lds_atomic_sub1_noret_i32: 408 ; GCN: v_mov_b32_e32 [[ONE:v[0-9]+]], 1{{$}} 409 ; GCN: ds_sub_u32 v{{[0-9]+}}, [[ONE]] 410 ; GCN: s_endpgm 411 define void @lds_atomic_sub1_noret_i32(i32 addrspace(3)* %ptr) nounwind { 412 %result = atomicrmw sub i32 addrspace(3)* %ptr, i32 1 seq_cst 413 ret void 414 } 415 416 ; FUNC-LABEL: {{^}}lds_atomic_sub1_noret_i32_offset: 417 ; GCN: v_mov_b32_e32 [[ONE:v[0-9]+]], 1{{$}} 418 ; GCN: ds_sub_u32 v{{[0-9]+}}, [[ONE]] offset:16 419 ; GCN: s_endpgm 420 define void @lds_atomic_sub1_noret_i32_offset(i32 addrspace(3)* %ptr) nounwind { 421 %gep = getelementptr i32, i32 addrspace(3)* %ptr, i32 4 422 %result = atomicrmw sub i32 addrspace(3)* %gep, i32 1 seq_cst 423 ret void 424 } 425 426 ; FUNC-LABEL: {{^}}lds_atomic_and_noret_i32: 427 ; GCN: ds_and_b32 428 ; GCN: s_endpgm 429 define void @lds_atomic_and_noret_i32(i32 addrspace(3)* %ptr) nounwind { 430 %result = atomicrmw and i32 addrspace(3)* %ptr, i32 4 seq_cst 431 ret void 432 } 433 434 ; FUNC-LABEL: {{^}}lds_atomic_and_noret_i32_offset: 435 ; GCN: ds_and_b32 v{{[0-9]+}}, v{{[0-9]+}} offset:16 436 ; GCN: s_endpgm 437 define void @lds_atomic_and_noret_i32_offset(i32 addrspace(3)* %ptr) nounwind { 438 %gep = getelementptr i32, i32 addrspace(3)* %ptr, i32 4 439 %result = atomicrmw and i32 addrspace(3)* %gep, i32 4 seq_cst 440 ret void 441 } 442 443 ; FUNC-LABEL: {{^}}lds_atomic_or_noret_i32: 444 ; GCN: ds_or_b32 445 ; GCN: s_endpgm 446 define void @lds_atomic_or_noret_i32(i32 addrspace(3)* %ptr) nounwind { 447 %result = atomicrmw or i32 addrspace(3)* %ptr, i32 4 seq_cst 448 ret void 449 } 450 451 ; FUNC-LABEL: {{^}}lds_atomic_or_noret_i32_offset: 452 ; GCN: ds_or_b32 v{{[0-9]+}}, v{{[0-9]+}} offset:16 453 ; GCN: s_endpgm 454 define void @lds_atomic_or_noret_i32_offset(i32 addrspace(3)* %ptr) nounwind { 455 %gep = getelementptr i32, i32 addrspace(3)* %ptr, i32 4 456 %result = atomicrmw or i32 addrspace(3)* %gep, i32 4 seq_cst 457 ret void 458 } 459 460 ; FUNC-LABEL: {{^}}lds_atomic_xor_noret_i32: 461 ; GCN: ds_xor_b32 462 ; GCN: s_endpgm 463 define void @lds_atomic_xor_noret_i32(i32 addrspace(3)* %ptr) nounwind { 464 %result = atomicrmw xor i32 addrspace(3)* %ptr, i32 4 seq_cst 465 ret void 466 } 467 468 ; FUNC-LABEL: {{^}}lds_atomic_xor_noret_i32_offset: 469 ; GCN: ds_xor_b32 v{{[0-9]+}}, v{{[0-9]+}} offset:16 470 ; GCN: s_endpgm 471 define void @lds_atomic_xor_noret_i32_offset(i32 addrspace(3)* %ptr) nounwind { 472 %gep = getelementptr i32, i32 addrspace(3)* %ptr, i32 4 473 %result = atomicrmw xor i32 addrspace(3)* %gep, i32 4 seq_cst 474 ret void 475 } 476 477 ; FIXME: There is no atomic nand instr 478 ; XFUNC-LABEL: {{^}}lds_atomic_nand_noret_i32:uction, so we somehow need to expand this. 479 ; define void @lds_atomic_nand_noret_i32(i32 addrspace(3)* %ptr) nounwind { 480 ; %result = atomicrmw nand i32 addrspace(3)* %ptr, i32 4 seq_cst 481 ; ret void 482 ; } 483 484 ; FUNC-LABEL: {{^}}lds_atomic_min_noret_i32: 485 ; GCN: ds_min_i32 486 ; GCN: s_endpgm 487 define void @lds_atomic_min_noret_i32(i32 addrspace(3)* %ptr) nounwind { 488 %result = atomicrmw min i32 addrspace(3)* %ptr, i32 4 seq_cst 489 ret void 490 } 491 492 ; FUNC-LABEL: {{^}}lds_atomic_min_noret_i32_offset: 493 ; GCN: ds_min_i32 v{{[0-9]+}}, v{{[0-9]+}} offset:16 494 ; GCN: s_endpgm 495 define void @lds_atomic_min_noret_i32_offset(i32 addrspace(3)* %ptr) nounwind { 496 %gep = getelementptr i32, i32 addrspace(3)* %ptr, i32 4 497 %result = atomicrmw min i32 addrspace(3)* %gep, i32 4 seq_cst 498 ret void 499 } 500 501 ; FUNC-LABEL: {{^}}lds_atomic_max_noret_i32: 502 ; GCN: ds_max_i32 503 ; GCN: s_endpgm 504 define void @lds_atomic_max_noret_i32(i32 addrspace(3)* %ptr) nounwind { 505 %result = atomicrmw max i32 addrspace(3)* %ptr, i32 4 seq_cst 506 ret void 507 } 508 509 ; FUNC-LABEL: {{^}}lds_atomic_max_noret_i32_offset: 510 ; GCN: ds_max_i32 v{{[0-9]+}}, v{{[0-9]+}} offset:16 511 ; GCN: s_endpgm 512 define void @lds_atomic_max_noret_i32_offset(i32 addrspace(3)* %ptr) nounwind { 513 %gep = getelementptr i32, i32 addrspace(3)* %ptr, i32 4 514 %result = atomicrmw max i32 addrspace(3)* %gep, i32 4 seq_cst 515 ret void 516 } 517 518 ; FUNC-LABEL: {{^}}lds_atomic_umin_noret_i32: 519 ; GCN: ds_min_u32 520 ; GCN: s_endpgm 521 define void @lds_atomic_umin_noret_i32(i32 addrspace(3)* %ptr) nounwind { 522 %result = atomicrmw umin i32 addrspace(3)* %ptr, i32 4 seq_cst 523 ret void 524 } 525 526 ; FUNC-LABEL: {{^}}lds_atomic_umin_noret_i32_offset: 527 ; GCN: ds_min_u32 v{{[0-9]+}}, v{{[0-9]+}} offset:16 528 ; GCN: s_endpgm 529 define void @lds_atomic_umin_noret_i32_offset(i32 addrspace(3)* %ptr) nounwind { 530 %gep = getelementptr i32, i32 addrspace(3)* %ptr, i32 4 531 %result = atomicrmw umin i32 addrspace(3)* %gep, i32 4 seq_cst 532 ret void 533 } 534 535 ; FUNC-LABEL: {{^}}lds_atomic_umax_noret_i32: 536 ; GCN: ds_max_u32 537 ; GCN: s_endpgm 538 define void @lds_atomic_umax_noret_i32(i32 addrspace(3)* %ptr) nounwind { 539 %result = atomicrmw umax i32 addrspace(3)* %ptr, i32 4 seq_cst 540 ret void 541 } 542 543 ; FUNC-LABEL: {{^}}lds_atomic_umax_noret_i32_offset: 544 ; GCN: ds_max_u32 v{{[0-9]+}}, v{{[0-9]+}} offset:16 545 ; GCN: s_endpgm 546 define void @lds_atomic_umax_noret_i32_offset(i32 addrspace(3)* %ptr) nounwind { 547 %gep = getelementptr i32, i32 addrspace(3)* %ptr, i32 4 548 %result = atomicrmw umax i32 addrspace(3)* %gep, i32 4 seq_cst 549 ret void 550 } 551