1 ; RUN: llc < %s -mtriple=armv7-apple-ios | FileCheck %s 2 ; RUN: llc < %s -mtriple=thumbv7-none-linux-gnueabihf | FileCheck %s --check-prefix=CHECK-THUMB 3 4 define i64 @test1(i64* %ptr, i64 %val) { 5 ; CHECK-LABEL: test1: 6 ; CHECK: dmb {{ish$}} 7 ; CHECK: ldrexd [[REG1:(r[0-9]?[02468])]], [[REG2:(r[0-9]?[13579])]] 8 ; CHECK: adds [[REG3:(r[0-9]?[02468])]], [[REG1]] 9 ; CHECK: adc [[REG4:(r[0-9]?[13579])]], [[REG2]] 10 ; CHECK: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]] 11 ; CHECK: cmp 12 ; CHECK: bne 13 ; CHECK: dmb {{ish$}} 14 15 ; CHECK-THUMB-LABEL: test1: 16 ; CHECK-THUMB: dmb {{ish$}} 17 ; CHECK-THUMB: ldrexd [[REG1:[a-z0-9]+]], [[REG2:[a-z0-9]+]] 18 ; CHECK-THUMB: adds.w [[REG3:[a-z0-9]+]], [[REG1]] 19 ; CHECK-THUMB: adc.w [[REG4:[a-z0-9]+]], [[REG2]] 20 ; CHECK-THUMB: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]] 21 ; CHECK-THUMB: cmp 22 ; CHECK-THUMB: bne 23 ; CHECK-THUMB: dmb {{ish$}} 24 25 %r = atomicrmw add i64* %ptr, i64 %val seq_cst 26 ret i64 %r 27 } 28 29 define i64 @test2(i64* %ptr, i64 %val) { 30 ; CHECK-LABEL: test2: 31 ; CHECK: dmb {{ish$}} 32 ; CHECK: ldrexd [[REG1:(r[0-9]?[02468])]], [[REG2:(r[0-9]?[13579])]] 33 ; CHECK: subs [[REG3:(r[0-9]?[02468])]], [[REG1]] 34 ; CHECK: sbc [[REG4:(r[0-9]?[13579])]], [[REG2]] 35 ; CHECK: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]] 36 ; CHECK: cmp 37 ; CHECK: bne 38 ; CHECK: dmb {{ish$}} 39 40 ; CHECK-THUMB-LABEL: test2: 41 ; CHECK-THUMB: dmb {{ish$}} 42 ; CHECK-THUMB: ldrexd [[REG1:[a-z0-9]+]], [[REG2:[a-z0-9]+]] 43 ; CHECK-THUMB: subs.w [[REG3:[a-z0-9]+]], [[REG1]] 44 ; CHECK-THUMB: sbc.w [[REG4:[a-z0-9]+]], [[REG2]] 45 ; CHECK-THUMB: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]] 46 ; CHECK-THUMB: cmp 47 ; CHECK-THUMB: bne 48 ; CHECK-THUMB: dmb {{ish$}} 49 50 %r = atomicrmw sub i64* %ptr, i64 %val seq_cst 51 ret i64 %r 52 } 53 54 define i64 @test3(i64* %ptr, i64 %val) { 55 ; CHECK-LABEL: test3: 56 ; CHECK: dmb {{ish$}} 57 ; CHECK: ldrexd [[REG1:(r[0-9]?[02468])]], [[REG2:(r[0-9]?[13579])]] 58 ; CHECK: and [[REG3:(r[0-9]?[02468])]], [[REG1]] 59 ; CHECK: and [[REG4:(r[0-9]?[13579])]], [[REG2]] 60 ; CHECK: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]] 61 ; CHECK: cmp 62 ; CHECK: bne 63 ; CHECK: dmb {{ish$}} 64 65 ; CHECK-THUMB-LABEL: test3: 66 ; CHECK-THUMB: dmb {{ish$}} 67 ; CHECK-THUMB: ldrexd [[REG1:[a-z0-9]+]], [[REG2:[a-z0-9]+]] 68 ; CHECK-THUMB: and.w [[REG3:[a-z0-9]+]], [[REG1]] 69 ; CHECK-THUMB: and.w [[REG4:[a-z0-9]+]], [[REG2]] 70 ; CHECK-THUMB: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]] 71 ; CHECK-THUMB: cmp 72 ; CHECK-THUMB: bne 73 ; CHECK-THUMB: dmb {{ish$}} 74 75 %r = atomicrmw and i64* %ptr, i64 %val seq_cst 76 ret i64 %r 77 } 78 79 define i64 @test4(i64* %ptr, i64 %val) { 80 ; CHECK-LABEL: test4: 81 ; CHECK: dmb {{ish$}} 82 ; CHECK: ldrexd [[REG1:(r[0-9]?[02468])]], [[REG2:(r[0-9]?[13579])]] 83 ; CHECK: orr [[REG3:(r[0-9]?[02468])]], [[REG1]] 84 ; CHECK: orr [[REG4:(r[0-9]?[13579])]], [[REG2]] 85 ; CHECK: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]] 86 ; CHECK: cmp 87 ; CHECK: bne 88 ; CHECK: dmb {{ish$}} 89 90 ; CHECK-THUMB-LABEL: test4: 91 ; CHECK-THUMB: dmb {{ish$}} 92 ; CHECK-THUMB: ldrexd [[REG1:[a-z0-9]+]], [[REG2:[a-z0-9]+]] 93 ; CHECK-THUMB: orr.w [[REG3:[a-z0-9]+]], [[REG1]] 94 ; CHECK-THUMB: orr.w [[REG4:[a-z0-9]+]], [[REG2]] 95 ; CHECK-THUMB: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]] 96 ; CHECK-THUMB: cmp 97 ; CHECK-THUMB: bne 98 ; CHECK-THUMB: dmb {{ish$}} 99 100 %r = atomicrmw or i64* %ptr, i64 %val seq_cst 101 ret i64 %r 102 } 103 104 define i64 @test5(i64* %ptr, i64 %val) { 105 ; CHECK-LABEL: test5: 106 ; CHECK: dmb {{ish$}} 107 ; CHECK: ldrexd [[REG1:(r[0-9]?[02468])]], [[REG2:(r[0-9]?[13579])]] 108 ; CHECK: eor [[REG3:(r[0-9]?[02468])]], [[REG1]] 109 ; CHECK: eor [[REG4:(r[0-9]?[13579])]], [[REG2]] 110 ; CHECK: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]] 111 ; CHECK: cmp 112 ; CHECK: bne 113 ; CHECK: dmb {{ish$}} 114 115 ; CHECK-THUMB-LABEL: test5: 116 ; CHECK-THUMB: dmb {{ish$}} 117 ; CHECK-THUMB: ldrexd [[REG1:[a-z0-9]+]], [[REG2:[a-z0-9]+]] 118 ; CHECK-THUMB: eor.w [[REG3:[a-z0-9]+]], [[REG1]] 119 ; CHECK-THUMB: eor.w [[REG4:[a-z0-9]+]], [[REG2]] 120 ; CHECK-THUMB: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]] 121 ; CHECK-THUMB: cmp 122 ; CHECK-THUMB: bne 123 ; CHECK-THUMB: dmb {{ish$}} 124 125 %r = atomicrmw xor i64* %ptr, i64 %val seq_cst 126 ret i64 %r 127 } 128 129 define i64 @test6(i64* %ptr, i64 %val) { 130 ; CHECK-LABEL: test6: 131 ; CHECK: dmb {{ish$}} 132 ; CHECK: ldrexd [[REG1:(r[0-9]?[02468])]], [[REG2:(r[0-9]?[13579])]] 133 ; CHECK: strexd {{[a-z0-9]+}}, {{r[0-9]?[02468]}}, {{r[0-9]?[13579]}} 134 ; CHECK: cmp 135 ; CHECK: bne 136 ; CHECK: dmb {{ish$}} 137 138 ; CHECK-THUMB-LABEL: test6: 139 ; CHECK-THUMB: dmb {{ish$}} 140 ; CHECK-THUMB: ldrexd [[REG1:[a-z0-9]+]], [[REG2:[a-z0-9]+]] 141 ; CHECK-THUMB: strexd {{[a-z0-9]+}}, {{[a-z0-9]+}}, {{[a-z0-9]+}} 142 ; CHECK-THUMB: cmp 143 ; CHECK-THUMB: bne 144 ; CHECK-THUMB: dmb {{ish$}} 145 146 %r = atomicrmw xchg i64* %ptr, i64 %val seq_cst 147 ret i64 %r 148 } 149 150 define i64 @test7(i64* %ptr, i64 %val1, i64 %val2) { 151 ; CHECK-LABEL: test7: 152 ; CHECK: dmb {{ish$}} 153 ; CHECK: ldrexd [[REG1:(r[0-9]?[02468])]], [[REG2:(r[0-9]?[13579])]] 154 ; CHECK: cmp [[REG1]] 155 ; CHECK: cmpeq [[REG2]] 156 ; CHECK: bne 157 ; CHECK: strexd {{[a-z0-9]+}}, {{r[0-9]?[02468]}}, {{r[0-9]?[13579]}} 158 ; CHECK: cmp 159 ; CHECK: bne 160 ; CHECK: dmb {{ish$}} 161 162 ; CHECK-THUMB-LABEL: test7: 163 ; CHECK-THUMB: dmb {{ish$}} 164 ; CHECK-THUMB: ldrexd [[REG1:[a-z0-9]+]], [[REG2:[a-z0-9]+]] 165 ; CHECK-THUMB: cmp [[REG1]] 166 ; CHECK-THUMB: it eq 167 ; CHECK-THUMB: cmpeq [[REG2]] 168 ; CHECK-THUMB: bne 169 ; CHECK-THUMB: strexd {{[a-z0-9]+}}, {{[a-z0-9]+}}, {{[a-z0-9]+}} 170 ; CHECK-THUMB: cmp 171 ; CHECK-THUMB: bne 172 ; CHECK-THUMB: dmb {{ish$}} 173 174 %r = cmpxchg i64* %ptr, i64 %val1, i64 %val2 seq_cst 175 ret i64 %r 176 } 177 178 ; Compiles down to cmpxchg 179 ; FIXME: Should compile to a single ldrexd 180 define i64 @test8(i64* %ptr) { 181 ; CHECK-LABEL: test8: 182 ; CHECK: ldrexd [[REG1:(r[0-9]?[02468])]], [[REG2:(r[0-9]?[13579])]] 183 ; CHECK: cmp [[REG1]] 184 ; CHECK: cmpeq [[REG2]] 185 ; CHECK: bne 186 ; CHECK: strexd {{[a-z0-9]+}}, {{r[0-9]?[02468]}}, {{r[0-9]?[13579]}} 187 ; CHECK: cmp 188 ; CHECK: bne 189 ; CHECK: dmb {{ish$}} 190 191 ; CHECK-THUMB-LABEL: test8: 192 ; CHECK-THUMB: ldrexd [[REG1:[a-z0-9]+]], [[REG2:[a-z0-9]+]] 193 ; CHECK-THUMB: cmp [[REG1]] 194 ; CHECK-THUMB: it eq 195 ; CHECK-THUMB: cmpeq [[REG2]] 196 ; CHECK-THUMB: bne 197 ; CHECK-THUMB: strexd {{[a-z0-9]+}}, {{[a-z0-9]+}}, {{[a-z0-9]+}} 198 ; CHECK-THUMB: cmp 199 ; CHECK-THUMB: bne 200 ; CHECK-THUMB: dmb {{ish$}} 201 202 %r = load atomic i64* %ptr seq_cst, align 8 203 ret i64 %r 204 } 205 206 ; Compiles down to atomicrmw xchg; there really isn't any more efficient 207 ; way to write it. 208 define void @test9(i64* %ptr, i64 %val) { 209 ; CHECK-LABEL: test9: 210 ; CHECK: dmb {{ish$}} 211 ; CHECK: ldrexd [[REG1:(r[0-9]?[02468])]], [[REG2:(r[0-9]?[13579])]] 212 ; CHECK: strexd {{[a-z0-9]+}}, {{r[0-9]?[02468]}}, {{r[0-9]?[13579]}} 213 ; CHECK: cmp 214 ; CHECK: bne 215 ; CHECK: dmb {{ish$}} 216 217 ; CHECK-THUMB-LABEL: test9: 218 ; CHECK-THUMB: dmb {{ish$}} 219 ; CHECK-THUMB: ldrexd [[REG1:[a-z0-9]+]], [[REG2:[a-z0-9]+]] 220 ; CHECK-THUMB: strexd {{[a-z0-9]+}}, {{[a-z0-9]+}}, {{[a-z0-9]+}} 221 ; CHECK-THUMB: cmp 222 ; CHECK-THUMB: bne 223 ; CHECK-THUMB: dmb {{ish$}} 224 225 store atomic i64 %val, i64* %ptr seq_cst, align 8 226 ret void 227 } 228 229 define i64 @test10(i64* %ptr, i64 %val) { 230 ; CHECK-LABEL: test10: 231 ; CHECK: dmb {{ish$}} 232 ; CHECK: ldrexd [[REG1:(r[0-9]?[02468])]], [[REG2:(r[0-9]?[13579])]] 233 ; CHECK: subs {{[a-z0-9]+}}, [[REG1]], [[REG3:(r[0-9]?[02468])]] 234 ; CHECK: sbcs {{[a-z0-9]+}}, [[REG2]], [[REG4:(r[0-9]?[13579])]] 235 ; CHECK: blt 236 ; CHECK: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]] 237 ; CHECK: cmp 238 ; CHECK: bne 239 ; CHECK: dmb {{ish$}} 240 241 ; CHECK-THUMB-LABEL: test10: 242 ; CHECK-THUMB: dmb {{ish$}} 243 ; CHECK-THUMB: ldrexd [[REG1:[a-z0-9]+]], [[REG2:[a-z0-9]+]] 244 ; CHECK-THUMB: subs.w {{[a-z0-9]+}}, [[REG1]], [[REG3:[a-z0-9]+]] 245 ; CHECK-THUMB: sbcs.w {{[a-z0-9]+}}, [[REG2]], [[REG4:[a-z0-9]+]] 246 ; CHECK-THUMB: blt 247 ; CHECK-THUMB: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]] 248 ; CHECK-THUMB: cmp 249 ; CHECK-THUMB: bne 250 ; CHECK-THUMB: dmb {{ish$}} 251 252 %r = atomicrmw min i64* %ptr, i64 %val seq_cst 253 ret i64 %r 254 } 255 256 define i64 @test11(i64* %ptr, i64 %val) { 257 ; CHECK-LABEL: test11: 258 ; CHECK: dmb {{ish$}} 259 ; CHECK: ldrexd [[REG1:(r[0-9]?[02468])]], [[REG2:(r[0-9]?[13579])]] 260 ; CHECK: subs {{[a-z0-9]+}}, [[REG1]], [[REG3:(r[0-9]?[02468])]] 261 ; CHECK: sbcs {{[a-z0-9]+}}, [[REG2]], [[REG4:(r[0-9]?[13579])]] 262 ; CHECK: blo 263 ; CHECK: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]] 264 ; CHECK: cmp 265 ; CHECK: bne 266 ; CHECK: dmb {{ish$}} 267 268 269 ; CHECK-THUMB-LABEL: test11: 270 ; CHECK-THUMB: dmb {{ish$}} 271 ; CHECK-THUMB: ldrexd [[REG1:[a-z0-9]+]], [[REG2:[a-z0-9]+]] 272 ; CHECK-THUMB: subs.w {{[a-z0-9]+}}, [[REG1]], [[REG3:[a-z0-9]+]] 273 ; CHECK-THUMB: sbcs.w {{[a-z0-9]+}}, [[REG2]], [[REG4:[a-z0-9]+]] 274 ; CHECK-THUMB: blo 275 ; CHECK-THUMB: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]] 276 ; CHECK-THUMB: cmp 277 ; CHECK-THUMB: bne 278 ; CHECK-THUMB: dmb {{ish$}} 279 280 %r = atomicrmw umin i64* %ptr, i64 %val seq_cst 281 ret i64 %r 282 } 283 284 define i64 @test12(i64* %ptr, i64 %val) { 285 ; CHECK-LABEL: test12: 286 ; CHECK: dmb {{ish$}} 287 ; CHECK: ldrexd [[REG1:(r[0-9]?[02468])]], [[REG2:(r[0-9]?[13579])]] 288 ; CHECK: subs {{[a-z0-9]+}}, [[REG1]], [[REG3:(r[0-9]?[02468])]] 289 ; CHECK: sbcs {{[a-z0-9]+}}, [[REG2]], [[REG4:(r[0-9]?[13579])]] 290 ; CHECK: bge 291 ; CHECK: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]] 292 ; CHECK: cmp 293 ; CHECK: bne 294 ; CHECK: dmb {{ish$}} 295 296 ; CHECK-THUMB-LABEL: test12: 297 ; CHECK-THUMB: dmb {{ish$}} 298 ; CHECK-THUMB: ldrexd [[REG1:[a-z0-9]+]], [[REG2:[a-z0-9]+]] 299 ; CHECK-THUMB: subs.w {{[a-z0-9]+}}, [[REG1]], [[REG3:[a-z0-9]+]] 300 ; CHECK-THUMB: sbcs.w {{[a-z0-9]+}}, [[REG2]], [[REG4:[a-z0-9]+]] 301 ; CHECK-THUMB: bge 302 ; CHECK-THUMB: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]] 303 ; CHECK-THUMB: cmp 304 ; CHECK-THUMB: bne 305 ; CHECK-THUMB: dmb {{ish$}} 306 307 %r = atomicrmw max i64* %ptr, i64 %val seq_cst 308 ret i64 %r 309 } 310 311 define i64 @test13(i64* %ptr, i64 %val) { 312 ; CHECK-LABEL: test13: 313 ; CHECK: dmb {{ish$}} 314 ; CHECK: ldrexd [[REG1:(r[0-9]?[02468])]], [[REG2:(r[0-9]?[13579])]] 315 ; CHECK: subs {{[a-z0-9]+}}, [[REG1]], [[REG3:(r[0-9]?[02468])]] 316 ; CHECK: sbcs {{[a-z0-9]+}}, [[REG2]], [[REG4:(r[0-9]?[13579])]] 317 ; CHECK: bhs 318 ; CHECK: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]] 319 ; CHECK: cmp 320 ; CHECK: bne 321 ; CHECK: dmb {{ish$}} 322 323 ; CHECK-THUMB-LABEL: test13: 324 ; CHECK-THUMB: dmb {{ish$}} 325 ; CHECK-THUMB: ldrexd [[REG1:[a-z0-9]+]], [[REG2:[a-z0-9]+]] 326 ; CHECK-THUMB: subs.w {{[a-z0-9]+}}, [[REG1]], [[REG3:[a-z0-9]+]] 327 ; CHECK-THUMB: sbcs.w {{[a-z0-9]+}}, [[REG2]], [[REG4:[a-z0-9]+]] 328 ; CHECK-THUMB: bhs 329 ; CHECK-THUMB: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]] 330 ; CHECK-THUMB: cmp 331 ; CHECK-THUMB: bne 332 ; CHECK-THUMB: dmb {{ish$}} 333 %r = atomicrmw umax i64* %ptr, i64 %val seq_cst 334 ret i64 %r 335 } 336 337