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 } 552