Home | History | Annotate | Download | only in AMDGPU
      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