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