1 ; RUN: llc -mtriple=aarch64-none-linux-gnu -verify-machineinstrs < %s | FileCheck %s 2 3 @var8 = global i8 0 4 @var16 = global i16 0 5 @var32 = global i32 0 6 @var64 = global i64 0 7 8 define i8 @test_atomic_load_add_i8(i8 %offset) nounwind { 9 ; CHECK-LABEL: test_atomic_load_add_i8: 10 %old = atomicrmw add i8* @var8, i8 %offset seq_cst 11 ; CHECK-NOT: dmb 12 ; CHECK: adrp [[TMPADDR:x[0-9]+]], var8 13 ; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], #:lo12:var8 14 15 ; CHECK: .LBB{{[0-9]+}}_1: 16 ; CHECK-NEXT: ldaxrb w[[OLD:[0-9]+]], [x[[ADDR]]] 17 ; w0 below is a reasonable guess but could change: it certainly comes into the 18 ; function there. 19 ; CHECK-NEXT: add [[NEW:w[0-9]+]], w[[OLD]], w0 20 ; CHECK-NEXT: stlxrb [[STATUS:w[0-9]+]], [[NEW]], [x[[ADDR]]] 21 ; CHECK-NEXT: cbnz [[STATUS]], .LBB{{[0-9]+}}_1 22 ; CHECK-NOT: dmb 23 24 ; CHECK: mov x0, x[[OLD]] 25 ret i8 %old 26 } 27 28 define i16 @test_atomic_load_add_i16(i16 %offset) nounwind { 29 ; CHECK-LABEL: test_atomic_load_add_i16: 30 %old = atomicrmw add i16* @var16, i16 %offset acquire 31 ; CHECK-NOT: dmb 32 ; CHECK: adrp [[TMPADDR:x[0-9]+]], var16 33 ; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], #:lo12:var16 34 35 ; CHECK: .LBB{{[0-9]+}}_1: 36 ; CHECK-NEXT: ldaxrh w[[OLD:[0-9]+]], [x[[ADDR]]] 37 ; w0 below is a reasonable guess but could change: it certainly comes into the 38 ; function there. 39 ; CHECK-NEXT: add [[NEW:w[0-9]+]], w[[OLD]], w0 40 ; CHECK-NEXT: stxrh [[STATUS:w[0-9]+]], [[NEW]], [x[[ADDR]]] 41 ; CHECK-NEXT: cbnz [[STATUS]], .LBB{{[0-9]+}}_1 42 ; CHECK-NOT: dmb 43 44 ; CHECK: mov x0, x[[OLD]] 45 ret i16 %old 46 } 47 48 define i32 @test_atomic_load_add_i32(i32 %offset) nounwind { 49 ; CHECK-LABEL: test_atomic_load_add_i32: 50 %old = atomicrmw add i32* @var32, i32 %offset release 51 ; CHECK-NOT: dmb 52 ; CHECK: adrp [[TMPADDR:x[0-9]+]], var32 53 ; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], #:lo12:var32 54 55 ; CHECK: .LBB{{[0-9]+}}_1: 56 ; CHECK-NEXT: ldxr w[[OLD:[0-9]+]], [x[[ADDR]]] 57 ; w0 below is a reasonable guess but could change: it certainly comes into the 58 ; function there. 59 ; CHECK-NEXT: add [[NEW:w[0-9]+]], w[[OLD]], w0 60 ; CHECK-NEXT: stlxr [[STATUS:w[0-9]+]], [[NEW]], [x[[ADDR]]] 61 ; CHECK-NEXT: cbnz [[STATUS]], .LBB{{[0-9]+}}_1 62 ; CHECK-NOT: dmb 63 64 ; CHECK: mov x0, x[[OLD]] 65 ret i32 %old 66 } 67 68 define i64 @test_atomic_load_add_i64(i64 %offset) nounwind { 69 ; CHECK-LABEL: test_atomic_load_add_i64: 70 %old = atomicrmw add i64* @var64, i64 %offset monotonic 71 ; CHECK-NOT: dmb 72 ; CHECK: adrp [[TMPADDR:x[0-9]+]], var64 73 ; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], #:lo12:var64 74 75 ; CHECK: .LBB{{[0-9]+}}_1: 76 ; CHECK-NEXT: ldxr x[[OLD:[0-9]+]], [x[[ADDR]]] 77 ; x0 below is a reasonable guess but could change: it certainly comes into the 78 ; function there. 79 ; CHECK-NEXT: add [[NEW:x[0-9]+]], x[[OLD]], x0 80 ; CHECK-NEXT: stxr [[STATUS:w[0-9]+]], [[NEW]], [x[[ADDR]]] 81 ; CHECK-NEXT: cbnz [[STATUS]], .LBB{{[0-9]+}}_1 82 ; CHECK-NOT: dmb 83 84 ; CHECK: mov x0, x[[OLD]] 85 ret i64 %old 86 } 87 88 define i8 @test_atomic_load_sub_i8(i8 %offset) nounwind { 89 ; CHECK-LABEL: test_atomic_load_sub_i8: 90 %old = atomicrmw sub i8* @var8, i8 %offset monotonic 91 ; CHECK-NOT: dmb 92 ; CHECK: adrp [[TMPADDR:x[0-9]+]], var8 93 ; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], #:lo12:var8 94 95 ; CHECK: .LBB{{[0-9]+}}_1: 96 ; CHECK-NEXT: ldxrb w[[OLD:[0-9]+]], [x[[ADDR]]] 97 ; w0 below is a reasonable guess but could change: it certainly comes into the 98 ; function there. 99 ; CHECK-NEXT: sub [[NEW:w[0-9]+]], w[[OLD]], w0 100 ; CHECK-NEXT: stxrb [[STATUS:w[0-9]+]], [[NEW]], [x[[ADDR]]] 101 ; CHECK-NEXT: cbnz [[STATUS]], .LBB{{[0-9]+}}_1 102 ; CHECK-NOT: dmb 103 104 ; CHECK: mov x0, x[[OLD]] 105 ret i8 %old 106 } 107 108 define i16 @test_atomic_load_sub_i16(i16 %offset) nounwind { 109 ; CHECK-LABEL: test_atomic_load_sub_i16: 110 %old = atomicrmw sub i16* @var16, i16 %offset release 111 ; CHECK-NOT: dmb 112 ; CHECK: adrp [[TMPADDR:x[0-9]+]], var16 113 ; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], #:lo12:var16 114 115 ; CHECK: .LBB{{[0-9]+}}_1: 116 ; CHECK-NEXT: ldxrh w[[OLD:[0-9]+]], [x[[ADDR]]] 117 ; w0 below is a reasonable guess but could change: it certainly comes into the 118 ; function there. 119 ; CHECK-NEXT: sub [[NEW:w[0-9]+]], w[[OLD]], w0 120 ; CHECK-NEXT: stlxrh [[STATUS:w[0-9]+]], [[NEW]], [x[[ADDR]]] 121 ; CHECK-NEXT: cbnz [[STATUS]], .LBB{{[0-9]+}}_1 122 ; CHECK-NOT: dmb 123 124 ; CHECK: mov x0, x[[OLD]] 125 ret i16 %old 126 } 127 128 define i32 @test_atomic_load_sub_i32(i32 %offset) nounwind { 129 ; CHECK-LABEL: test_atomic_load_sub_i32: 130 %old = atomicrmw sub i32* @var32, i32 %offset acquire 131 ; CHECK-NOT: dmb 132 ; CHECK: adrp [[TMPADDR:x[0-9]+]], var32 133 ; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], #:lo12:var32 134 135 ; CHECK: .LBB{{[0-9]+}}_1: 136 ; CHECK-NEXT: ldaxr w[[OLD:[0-9]+]], [x[[ADDR]]] 137 ; w0 below is a reasonable guess but could change: it certainly comes into the 138 ; function there. 139 ; CHECK-NEXT: sub [[NEW:w[0-9]+]], w[[OLD]], w0 140 ; CHECK-NEXT: stxr [[STATUS:w[0-9]+]], [[NEW]], [x[[ADDR]]] 141 ; CHECK-NEXT: cbnz [[STATUS]], .LBB{{[0-9]+}}_1 142 ; CHECK-NOT: dmb 143 144 ; CHECK: mov x0, x[[OLD]] 145 ret i32 %old 146 } 147 148 define i64 @test_atomic_load_sub_i64(i64 %offset) nounwind { 149 ; CHECK-LABEL: test_atomic_load_sub_i64: 150 %old = atomicrmw sub i64* @var64, i64 %offset seq_cst 151 ; CHECK-NOT: dmb 152 ; CHECK: adrp [[TMPADDR:x[0-9]+]], var64 153 ; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], #:lo12:var64 154 155 ; CHECK: .LBB{{[0-9]+}}_1: 156 ; CHECK-NEXT: ldaxr x[[OLD:[0-9]+]], [x[[ADDR]]] 157 ; x0 below is a reasonable guess but could change: it certainly comes into the 158 ; function there. 159 ; CHECK-NEXT: sub [[NEW:x[0-9]+]], x[[OLD]], x0 160 ; CHECK-NEXT: stlxr [[STATUS:w[0-9]+]], [[NEW]], [x[[ADDR]]] 161 ; CHECK-NEXT: cbnz [[STATUS]], .LBB{{[0-9]+}}_1 162 ; CHECK-NOT: dmb 163 164 ; CHECK: mov x0, x[[OLD]] 165 ret i64 %old 166 } 167 168 define i8 @test_atomic_load_and_i8(i8 %offset) nounwind { 169 ; CHECK-LABEL: test_atomic_load_and_i8: 170 %old = atomicrmw and i8* @var8, i8 %offset release 171 ; CHECK-NOT: dmb 172 ; CHECK: adrp [[TMPADDR:x[0-9]+]], var8 173 ; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], #:lo12:var8 174 175 ; CHECK: .LBB{{[0-9]+}}_1: 176 ; CHECK-NEXT: ldxrb w[[OLD:[0-9]+]], [x[[ADDR]]] 177 ; w0 below is a reasonable guess but could change: it certainly comes into the 178 ; function there. 179 ; CHECK-NEXT: and [[NEW:w[0-9]+]], w[[OLD]], w0 180 ; CHECK-NEXT: stlxrb [[STATUS:w[0-9]+]], [[NEW]], [x[[ADDR]]] 181 ; CHECK-NEXT: cbnz [[STATUS]], .LBB{{[0-9]+}}_1 182 ; CHECK-NOT: dmb 183 184 ; CHECK: mov x0, x[[OLD]] 185 ret i8 %old 186 } 187 188 define i16 @test_atomic_load_and_i16(i16 %offset) nounwind { 189 ; CHECK-LABEL: test_atomic_load_and_i16: 190 %old = atomicrmw and i16* @var16, i16 %offset monotonic 191 ; CHECK-NOT: dmb 192 ; CHECK: adrp [[TMPADDR:x[0-9]+]], var16 193 ; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], #:lo12:var16 194 195 ; CHECK: .LBB{{[0-9]+}}_1: 196 ; CHECK-NEXT: ldxrh w[[OLD:[0-9]+]], [x[[ADDR]]] 197 ; w0 below is a reasonable guess but could change: it certainly comes into the 198 ; function there. 199 ; CHECK-NEXT: and [[NEW:w[0-9]+]], w[[OLD]], w0 200 ; CHECK-NEXT: stxrh [[STATUS:w[0-9]+]], [[NEW]], [x[[ADDR]]] 201 ; CHECK-NEXT: cbnz [[STATUS]], .LBB{{[0-9]+}}_1 202 ; CHECK-NOT: dmb 203 204 ; CHECK: mov x0, x[[OLD]] 205 ret i16 %old 206 } 207 208 define i32 @test_atomic_load_and_i32(i32 %offset) nounwind { 209 ; CHECK-LABEL: test_atomic_load_and_i32: 210 %old = atomicrmw and i32* @var32, i32 %offset seq_cst 211 ; CHECK-NOT: dmb 212 ; CHECK: adrp [[TMPADDR:x[0-9]+]], var32 213 ; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], #:lo12:var32 214 215 ; CHECK: .LBB{{[0-9]+}}_1: 216 ; CHECK-NEXT: ldaxr w[[OLD:[0-9]+]], [x[[ADDR]]] 217 ; w0 below is a reasonable guess but could change: it certainly comes into the 218 ; function there. 219 ; CHECK-NEXT: and [[NEW:w[0-9]+]], w[[OLD]], w0 220 ; CHECK-NEXT: stlxr [[STATUS:w[0-9]+]], [[NEW]], [x[[ADDR]]] 221 ; CHECK-NEXT: cbnz [[STATUS]], .LBB{{[0-9]+}}_1 222 ; CHECK-NOT: dmb 223 224 ; CHECK: mov x0, x[[OLD]] 225 ret i32 %old 226 } 227 228 define i64 @test_atomic_load_and_i64(i64 %offset) nounwind { 229 ; CHECK-LABEL: test_atomic_load_and_i64: 230 %old = atomicrmw and i64* @var64, i64 %offset acquire 231 ; CHECK-NOT: dmb 232 ; CHECK: adrp [[TMPADDR:x[0-9]+]], var64 233 ; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], #:lo12:var64 234 235 ; CHECK: .LBB{{[0-9]+}}_1: 236 ; CHECK-NEXT: ldaxr x[[OLD:[0-9]+]], [x[[ADDR]]] 237 ; x0 below is a reasonable guess but could change: it certainly comes into the 238 ; function there. 239 ; CHECK-NEXT: and [[NEW:x[0-9]+]], x[[OLD]], x0 240 ; CHECK-NEXT: stxr [[STATUS:w[0-9]+]], [[NEW]], [x[[ADDR]]] 241 ; CHECK-NEXT: cbnz [[STATUS]], .LBB{{[0-9]+}}_1 242 ; CHECK-NOT: dmb 243 244 ; CHECK: mov x0, x[[OLD]] 245 ret i64 %old 246 } 247 248 define i8 @test_atomic_load_or_i8(i8 %offset) nounwind { 249 ; CHECK-LABEL: test_atomic_load_or_i8: 250 %old = atomicrmw or i8* @var8, i8 %offset seq_cst 251 ; CHECK-NOT: dmb 252 ; CHECK: adrp [[TMPADDR:x[0-9]+]], var8 253 ; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], #:lo12:var8 254 255 ; CHECK: .LBB{{[0-9]+}}_1: 256 ; CHECK-NEXT: ldaxrb w[[OLD:[0-9]+]], [x[[ADDR]]] 257 ; w0 below is a reasonable guess but could change: it certainly comes into the 258 ; function there. 259 ; CHECK-NEXT: orr [[NEW:w[0-9]+]], w[[OLD]], w0 260 ; CHECK-NEXT: stlxrb [[STATUS:w[0-9]+]], [[NEW]], [x[[ADDR]]] 261 ; CHECK-NEXT: cbnz [[STATUS]], .LBB{{[0-9]+}}_1 262 ; CHECK-NOT: dmb 263 264 ; CHECK: mov x0, x[[OLD]] 265 ret i8 %old 266 } 267 268 define i16 @test_atomic_load_or_i16(i16 %offset) nounwind { 269 ; CHECK-LABEL: test_atomic_load_or_i16: 270 %old = atomicrmw or i16* @var16, i16 %offset monotonic 271 ; CHECK-NOT: dmb 272 ; CHECK: adrp [[TMPADDR:x[0-9]+]], var16 273 ; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], #:lo12:var16 274 275 ; CHECK: .LBB{{[0-9]+}}_1: 276 ; CHECK-NEXT: ldxrh w[[OLD:[0-9]+]], [x[[ADDR]]] 277 ; w0 below is a reasonable guess but could change: it certainly comes into the 278 ; function there. 279 ; CHECK-NEXT: orr [[NEW:w[0-9]+]], w[[OLD]], w0 280 ; CHECK-NEXT: stxrh [[STATUS:w[0-9]+]], [[NEW]], [x[[ADDR]]] 281 ; CHECK-NEXT: cbnz [[STATUS]], .LBB{{[0-9]+}}_1 282 ; CHECK-NOT: dmb 283 284 ; CHECK: mov x0, x[[OLD]] 285 ret i16 %old 286 } 287 288 define i32 @test_atomic_load_or_i32(i32 %offset) nounwind { 289 ; CHECK-LABEL: test_atomic_load_or_i32: 290 %old = atomicrmw or i32* @var32, i32 %offset acquire 291 ; CHECK-NOT: dmb 292 ; CHECK: adrp [[TMPADDR:x[0-9]+]], var32 293 ; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], #:lo12:var32 294 295 ; CHECK: .LBB{{[0-9]+}}_1: 296 ; CHECK-NEXT: ldaxr w[[OLD:[0-9]+]], [x[[ADDR]]] 297 ; w0 below is a reasonable guess but could change: it certainly comes into the 298 ; function there. 299 ; CHECK-NEXT: orr [[NEW:w[0-9]+]], w[[OLD]], w0 300 ; CHECK-NEXT: stxr [[STATUS:w[0-9]+]], [[NEW]], [x[[ADDR]]] 301 ; CHECK-NEXT: cbnz [[STATUS]], .LBB{{[0-9]+}}_1 302 ; CHECK-NOT: dmb 303 304 ; CHECK: mov x0, x[[OLD]] 305 ret i32 %old 306 } 307 308 define i64 @test_atomic_load_or_i64(i64 %offset) nounwind { 309 ; CHECK-LABEL: test_atomic_load_or_i64: 310 %old = atomicrmw or i64* @var64, i64 %offset release 311 ; CHECK-NOT: dmb 312 ; CHECK: adrp [[TMPADDR:x[0-9]+]], var64 313 ; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], #:lo12:var64 314 315 ; CHECK: .LBB{{[0-9]+}}_1: 316 ; CHECK-NEXT: ldxr x[[OLD:[0-9]+]], [x[[ADDR]]] 317 ; x0 below is a reasonable guess but could change: it certainly comes into the 318 ; function there. 319 ; CHECK-NEXT: orr [[NEW:x[0-9]+]], x[[OLD]], x0 320 ; CHECK-NEXT: stlxr [[STATUS:w[0-9]+]], [[NEW]], [x[[ADDR]]] 321 ; CHECK-NEXT: cbnz [[STATUS]], .LBB{{[0-9]+}}_1 322 ; CHECK-NOT: dmb 323 324 ; CHECK: mov x0, x[[OLD]] 325 ret i64 %old 326 } 327 328 define i8 @test_atomic_load_xor_i8(i8 %offset) nounwind { 329 ; CHECK-LABEL: test_atomic_load_xor_i8: 330 %old = atomicrmw xor i8* @var8, i8 %offset acquire 331 ; CHECK-NOT: dmb 332 ; CHECK: adrp [[TMPADDR:x[0-9]+]], var8 333 ; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], #:lo12:var8 334 335 ; CHECK: .LBB{{[0-9]+}}_1: 336 ; CHECK-NEXT: ldaxrb w[[OLD:[0-9]+]], [x[[ADDR]]] 337 ; w0 below is a reasonable guess but could change: it certainly comes into the 338 ; function there. 339 ; CHECK-NEXT: eor [[NEW:w[0-9]+]], w[[OLD]], w0 340 ; CHECK-NEXT: stxrb [[STATUS:w[0-9]+]], [[NEW]], [x[[ADDR]]] 341 ; CHECK-NEXT: cbnz [[STATUS]], .LBB{{[0-9]+}}_1 342 ; CHECK-NOT: dmb 343 344 ; CHECK: mov x0, x[[OLD]] 345 ret i8 %old 346 } 347 348 define i16 @test_atomic_load_xor_i16(i16 %offset) nounwind { 349 ; CHECK-LABEL: test_atomic_load_xor_i16: 350 %old = atomicrmw xor i16* @var16, i16 %offset release 351 ; CHECK-NOT: dmb 352 ; CHECK: adrp [[TMPADDR:x[0-9]+]], var16 353 ; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], #:lo12:var16 354 355 ; CHECK: .LBB{{[0-9]+}}_1: 356 ; CHECK-NEXT: ldxrh w[[OLD:[0-9]+]], [x[[ADDR]]] 357 ; w0 below is a reasonable guess but could change: it certainly comes into the 358 ; function there. 359 ; CHECK-NEXT: eor [[NEW:w[0-9]+]], w[[OLD]], w0 360 ; CHECK-NEXT: stlxrh [[STATUS:w[0-9]+]], [[NEW]], [x[[ADDR]]] 361 ; CHECK-NEXT: cbnz [[STATUS]], .LBB{{[0-9]+}}_1 362 ; CHECK-NOT: dmb 363 364 ; CHECK: mov x0, x[[OLD]] 365 ret i16 %old 366 } 367 368 define i32 @test_atomic_load_xor_i32(i32 %offset) nounwind { 369 ; CHECK-LABEL: test_atomic_load_xor_i32: 370 %old = atomicrmw xor i32* @var32, i32 %offset seq_cst 371 ; CHECK-NOT: dmb 372 ; CHECK: adrp [[TMPADDR:x[0-9]+]], var32 373 ; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], #:lo12:var32 374 375 ; CHECK: .LBB{{[0-9]+}}_1: 376 ; CHECK-NEXT: ldaxr w[[OLD:[0-9]+]], [x[[ADDR]]] 377 ; w0 below is a reasonable guess but could change: it certainly comes into the 378 ; function there. 379 ; CHECK-NEXT: eor [[NEW:w[0-9]+]], w[[OLD]], w0 380 ; CHECK-NEXT: stlxr [[STATUS:w[0-9]+]], [[NEW]], [x[[ADDR]]] 381 ; CHECK-NEXT: cbnz [[STATUS]], .LBB{{[0-9]+}}_1 382 ; CHECK-NOT: dmb 383 384 ; CHECK: mov x0, x[[OLD]] 385 ret i32 %old 386 } 387 388 define i64 @test_atomic_load_xor_i64(i64 %offset) nounwind { 389 ; CHECK-LABEL: test_atomic_load_xor_i64: 390 %old = atomicrmw xor i64* @var64, i64 %offset monotonic 391 ; CHECK-NOT: dmb 392 ; CHECK: adrp [[TMPADDR:x[0-9]+]], var64 393 ; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], #:lo12:var64 394 395 ; CHECK: .LBB{{[0-9]+}}_1: 396 ; CHECK-NEXT: ldxr x[[OLD:[0-9]+]], [x[[ADDR]]] 397 ; x0 below is a reasonable guess but could change: it certainly comes into the 398 ; function there. 399 ; CHECK-NEXT: eor [[NEW:x[0-9]+]], x[[OLD]], x0 400 ; CHECK-NEXT: stxr [[STATUS:w[0-9]+]], [[NEW]], [x[[ADDR]]] 401 ; CHECK-NEXT: cbnz [[STATUS]], .LBB{{[0-9]+}}_1 402 ; CHECK-NOT: dmb 403 404 ; CHECK: mov x0, x[[OLD]] 405 ret i64 %old 406 } 407 408 define i8 @test_atomic_load_xchg_i8(i8 %offset) nounwind { 409 ; CHECK-LABEL: test_atomic_load_xchg_i8: 410 %old = atomicrmw xchg i8* @var8, i8 %offset monotonic 411 ; CHECK-NOT: dmb 412 ; CHECK: adrp [[TMPADDR:x[0-9]+]], var8 413 ; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], #:lo12:var8 414 415 ; CHECK: .LBB{{[0-9]+}}_1: 416 ; CHECK-NEXT: ldxrb w[[OLD:[0-9]+]], [x[[ADDR]]] 417 ; w0 below is a reasonable guess but could change: it certainly comes into the 418 ; function there. 419 ; CHECK-NEXT: stxrb [[STATUS:w[0-9]+]], w0, [x[[ADDR]]] 420 ; CHECK-NEXT: cbnz [[STATUS]], .LBB{{[0-9]+}}_1 421 ; CHECK-NOT: dmb 422 423 ; CHECK: mov x0, x[[OLD]] 424 ret i8 %old 425 } 426 427 define i16 @test_atomic_load_xchg_i16(i16 %offset) nounwind { 428 ; CHECK-LABEL: test_atomic_load_xchg_i16: 429 %old = atomicrmw xchg i16* @var16, i16 %offset seq_cst 430 ; CHECK-NOT: dmb 431 ; CHECK: adrp [[TMPADDR:x[0-9]+]], var16 432 ; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], #:lo12:var16 433 434 ; CHECK: .LBB{{[0-9]+}}_1: 435 ; CHECK-NEXT: ldaxrh w[[OLD:[0-9]+]], [x[[ADDR]]] 436 ; w0 below is a reasonable guess but could change: it certainly comes into the 437 ; function there. 438 ; CHECK-NEXT: stlxrh [[STATUS:w[0-9]+]], w0, [x[[ADDR]]] 439 ; CHECK-NEXT: cbnz [[STATUS]], .LBB{{[0-9]+}}_1 440 ; CHECK-NOT: dmb 441 442 ; CHECK: mov x0, x[[OLD]] 443 ret i16 %old 444 } 445 446 define i32 @test_atomic_load_xchg_i32(i32 %offset) nounwind { 447 ; CHECK-LABEL: test_atomic_load_xchg_i32: 448 %old = atomicrmw xchg i32* @var32, i32 %offset release 449 ; CHECK-NOT: dmb 450 ; CHECK: adrp [[TMPADDR:x[0-9]+]], var32 451 ; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], #:lo12:var32 452 453 ; CHECK: .LBB{{[0-9]+}}_1: 454 ; CHECK-NEXT: ldxr w[[OLD:[0-9]+]], [x[[ADDR]]] 455 ; w0 below is a reasonable guess but could change: it certainly comes into the 456 ; function there. 457 ; CHECK-NEXT: stlxr [[STATUS:w[0-9]+]], w0, [x[[ADDR]]] 458 ; CHECK-NEXT: cbnz [[STATUS]], .LBB{{[0-9]+}}_1 459 ; CHECK-NOT: dmb 460 461 ; CHECK: mov x0, x[[OLD]] 462 ret i32 %old 463 } 464 465 define i64 @test_atomic_load_xchg_i64(i64 %offset) nounwind { 466 ; CHECK-LABEL: test_atomic_load_xchg_i64: 467 %old = atomicrmw xchg i64* @var64, i64 %offset acquire 468 ; CHECK-NOT: dmb 469 ; CHECK: adrp [[TMPADDR:x[0-9]+]], var64 470 ; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], #:lo12:var64 471 472 ; CHECK: .LBB{{[0-9]+}}_1: 473 ; CHECK-NEXT: ldaxr x[[OLD:[0-9]+]], [x[[ADDR]]] 474 ; x0 below is a reasonable guess but could change: it certainly comes into the 475 ; function there. 476 ; CHECK-NEXT: stxr [[STATUS:w[0-9]+]], x0, [x[[ADDR]]] 477 ; CHECK-NEXT: cbnz [[STATUS]], .LBB{{[0-9]+}}_1 478 ; CHECK-NOT: dmb 479 480 ; CHECK: mov x0, x[[OLD]] 481 ret i64 %old 482 } 483 484 485 define i8 @test_atomic_load_min_i8(i8 %offset) nounwind { 486 ; CHECK-LABEL: test_atomic_load_min_i8: 487 %old = atomicrmw min i8* @var8, i8 %offset acquire 488 ; CHECK-NOT: dmb 489 ; CHECK: adrp [[TMPADDR:x[0-9]+]], var8 490 ; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], #:lo12:var8 491 492 ; CHECK: .LBB{{[0-9]+}}_1: 493 ; CHECK-NEXT: ldaxrb w[[OLD:[0-9]+]], [x[[ADDR]]] 494 ; w0 below is a reasonable guess but could change: it certainly comes into the 495 ; function there. 496 ; CHECK-NEXT: cmp w0, w[[OLD]], sxtb 497 ; CHECK-NEXT: csel [[NEW:w[0-9]+]], w[[OLD]], w0, gt 498 ; CHECK-NEXT: stxrb [[STATUS:w[0-9]+]], [[NEW]], [x[[ADDR]]] 499 ; CHECK-NEXT: cbnz [[STATUS]], .LBB{{[0-9]+}}_1 500 ; CHECK-NOT: dmb 501 502 ; CHECK: mov x0, x[[OLD]] 503 ret i8 %old 504 } 505 506 define i16 @test_atomic_load_min_i16(i16 %offset) nounwind { 507 ; CHECK-LABEL: test_atomic_load_min_i16: 508 %old = atomicrmw min i16* @var16, i16 %offset release 509 ; CHECK-NOT: dmb 510 ; CHECK: adrp [[TMPADDR:x[0-9]+]], var16 511 ; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], #:lo12:var16 512 513 ; CHECK: .LBB{{[0-9]+}}_1: 514 ; CHECK-NEXT: ldxrh w[[OLD:[0-9]+]], [x[[ADDR]]] 515 ; w0 below is a reasonable guess but could change: it certainly comes into the 516 ; function there. 517 ; CHECK-NEXT: cmp w0, w[[OLD]], sxth 518 ; CHECK-NEXT: csel [[NEW:w[0-9]+]], w[[OLD]], w0, gt 519 ; CHECK-NEXT: stlxrh [[STATUS:w[0-9]+]], [[NEW]], [x[[ADDR]]] 520 ; CHECK-NEXT: cbnz [[STATUS]], .LBB{{[0-9]+}}_1 521 ; CHECK-NOT: dmb 522 523 ; CHECK: mov x0, x[[OLD]] 524 ret i16 %old 525 } 526 527 define i32 @test_atomic_load_min_i32(i32 %offset) nounwind { 528 ; CHECK-LABEL: test_atomic_load_min_i32: 529 %old = atomicrmw min i32* @var32, i32 %offset monotonic 530 ; CHECK-NOT: dmb 531 ; CHECK: adrp [[TMPADDR:x[0-9]+]], var32 532 ; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], #:lo12:var32 533 534 ; CHECK: .LBB{{[0-9]+}}_1: 535 ; CHECK-NEXT: ldxr w[[OLD:[0-9]+]], [x[[ADDR]]] 536 ; w0 below is a reasonable guess but could change: it certainly comes into the 537 ; function there. 538 ; CHECK-NEXT: cmp w0, w[[OLD]] 539 ; CHECK-NEXT: csel [[NEW:w[0-9]+]], w[[OLD]], w0, gt 540 ; CHECK-NEXT: stxr [[STATUS:w[0-9]+]], [[NEW]], [x[[ADDR]]] 541 ; CHECK-NEXT: cbnz [[STATUS]], .LBB{{[0-9]+}}_1 542 ; CHECK-NOT: dmb 543 544 ; CHECK: mov x0, x[[OLD]] 545 ret i32 %old 546 } 547 548 define i64 @test_atomic_load_min_i64(i64 %offset) nounwind { 549 ; CHECK-LABEL: test_atomic_load_min_i64: 550 %old = atomicrmw min i64* @var64, i64 %offset seq_cst 551 ; CHECK-NOT: dmb 552 ; CHECK: adrp [[TMPADDR:x[0-9]+]], var64 553 ; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], #:lo12:var64 554 555 ; CHECK: .LBB{{[0-9]+}}_1: 556 ; CHECK-NEXT: ldaxr x[[OLD:[0-9]+]], [x[[ADDR]]] 557 ; x0 below is a reasonable guess but could change: it certainly comes into the 558 ; function there. 559 ; CHECK-NEXT: cmp x0, x[[OLD]] 560 ; CHECK-NEXT: csel [[NEW:x[0-9]+]], x[[OLD]], x0, gt 561 ; CHECK-NEXT: stlxr [[STATUS:w[0-9]+]], [[NEW]], [x[[ADDR]]] 562 ; CHECK-NEXT: cbnz [[STATUS]], .LBB{{[0-9]+}}_1 563 ; CHECK-NOT: dmb 564 565 ; CHECK: mov x0, x[[OLD]] 566 ret i64 %old 567 } 568 569 define i8 @test_atomic_load_max_i8(i8 %offset) nounwind { 570 ; CHECK-LABEL: test_atomic_load_max_i8: 571 %old = atomicrmw max i8* @var8, i8 %offset seq_cst 572 ; CHECK-NOT: dmb 573 ; CHECK: adrp [[TMPADDR:x[0-9]+]], var8 574 ; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], #:lo12:var8 575 576 ; CHECK: .LBB{{[0-9]+}}_1: 577 ; CHECK-NEXT: ldaxrb w[[OLD:[0-9]+]], [x[[ADDR]]] 578 ; w0 below is a reasonable guess but could change: it certainly comes into the 579 ; function there. 580 ; CHECK-NEXT: cmp w0, w[[OLD]], sxtb 581 ; CHECK-NEXT: csel [[NEW:w[0-9]+]], w[[OLD]], w0, lt 582 ; CHECK-NEXT: stlxrb [[STATUS:w[0-9]+]], [[NEW]], [x[[ADDR]]] 583 ; CHECK-NEXT: cbnz [[STATUS]], .LBB{{[0-9]+}}_1 584 ; CHECK-NOT: dmb 585 586 ; CHECK: mov x0, x[[OLD]] 587 ret i8 %old 588 } 589 590 define i16 @test_atomic_load_max_i16(i16 %offset) nounwind { 591 ; CHECK-LABEL: test_atomic_load_max_i16: 592 %old = atomicrmw max i16* @var16, i16 %offset acquire 593 ; CHECK-NOT: dmb 594 ; CHECK: adrp [[TMPADDR:x[0-9]+]], var16 595 ; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], #:lo12:var16 596 597 ; CHECK: .LBB{{[0-9]+}}_1: 598 ; CHECK-NEXT: ldaxrh w[[OLD:[0-9]+]], [x[[ADDR]]] 599 ; w0 below is a reasonable guess but could change: it certainly comes into the 600 ; function there. 601 ; CHECK-NEXT: cmp w0, w[[OLD]], sxth 602 ; CHECK-NEXT: csel [[NEW:w[0-9]+]], w[[OLD]], w0, lt 603 ; CHECK-NEXT: stxrh [[STATUS:w[0-9]+]], [[NEW]], [x[[ADDR]]] 604 ; CHECK-NEXT: cbnz [[STATUS]], .LBB{{[0-9]+}}_1 605 ; CHECK-NOT: dmb 606 607 ; CHECK: mov x0, x[[OLD]] 608 ret i16 %old 609 } 610 611 define i32 @test_atomic_load_max_i32(i32 %offset) nounwind { 612 ; CHECK-LABEL: test_atomic_load_max_i32: 613 %old = atomicrmw max i32* @var32, i32 %offset release 614 ; CHECK-NOT: dmb 615 ; CHECK: adrp [[TMPADDR:x[0-9]+]], var32 616 ; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], #:lo12:var32 617 618 ; CHECK: .LBB{{[0-9]+}}_1: 619 ; CHECK-NEXT: ldxr w[[OLD:[0-9]+]], [x[[ADDR]]] 620 ; w0 below is a reasonable guess but could change: it certainly comes into the 621 ; function there. 622 ; CHECK-NEXT: cmp w0, w[[OLD]] 623 ; CHECK-NEXT: csel [[NEW:w[0-9]+]], w[[OLD]], w0, lt 624 ; CHECK-NEXT: stlxr [[STATUS:w[0-9]+]], [[NEW]], [x[[ADDR]]] 625 ; CHECK-NEXT: cbnz [[STATUS]], .LBB{{[0-9]+}}_1 626 ; CHECK-NOT: dmb 627 628 ; CHECK: mov x0, x[[OLD]] 629 ret i32 %old 630 } 631 632 define i64 @test_atomic_load_max_i64(i64 %offset) nounwind { 633 ; CHECK-LABEL: test_atomic_load_max_i64: 634 %old = atomicrmw max i64* @var64, i64 %offset monotonic 635 ; CHECK-NOT: dmb 636 ; CHECK: adrp [[TMPADDR:x[0-9]+]], var64 637 ; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], #:lo12:var64 638 639 ; CHECK: .LBB{{[0-9]+}}_1: 640 ; CHECK-NEXT: ldxr x[[OLD:[0-9]+]], [x[[ADDR]]] 641 ; x0 below is a reasonable guess but could change: it certainly comes into the 642 ; function there. 643 ; CHECK-NEXT: cmp x0, x[[OLD]] 644 ; CHECK-NEXT: csel [[NEW:x[0-9]+]], x[[OLD]], x0, lt 645 ; CHECK-NEXT: stxr [[STATUS:w[0-9]+]], [[NEW]], [x[[ADDR]]] 646 ; CHECK-NEXT: cbnz [[STATUS]], .LBB{{[0-9]+}}_1 647 ; CHECK-NOT: dmb 648 649 ; CHECK: mov x0, x[[OLD]] 650 ret i64 %old 651 } 652 653 define i8 @test_atomic_load_umin_i8(i8 %offset) nounwind { 654 ; CHECK-LABEL: test_atomic_load_umin_i8: 655 %old = atomicrmw umin i8* @var8, i8 %offset monotonic 656 ; CHECK-NOT: dmb 657 ; CHECK: adrp [[TMPADDR:x[0-9]+]], var8 658 ; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], #:lo12:var8 659 660 ; CHECK: .LBB{{[0-9]+}}_1: 661 ; CHECK-NEXT: ldxrb w[[OLD:[0-9]+]], [x[[ADDR]]] 662 ; w0 below is a reasonable guess but could change: it certainly comes into the 663 ; function there. 664 ; CHECK-NEXT: cmp w0, w[[OLD]], uxtb 665 ; CHECK-NEXT: csel [[NEW:w[0-9]+]], w[[OLD]], w0, hi 666 ; CHECK-NEXT: stxrb [[STATUS:w[0-9]+]], [[NEW]], [x[[ADDR]]] 667 ; CHECK-NEXT: cbnz [[STATUS]], .LBB{{[0-9]+}}_1 668 ; CHECK-NOT: dmb 669 670 ; CHECK: mov x0, x[[OLD]] 671 ret i8 %old 672 } 673 674 define i16 @test_atomic_load_umin_i16(i16 %offset) nounwind { 675 ; CHECK-LABEL: test_atomic_load_umin_i16: 676 %old = atomicrmw umin i16* @var16, i16 %offset acquire 677 ; CHECK-NOT: dmb 678 ; CHECK: adrp [[TMPADDR:x[0-9]+]], var16 679 ; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], #:lo12:var16 680 681 ; CHECK: .LBB{{[0-9]+}}_1: 682 ; CHECK-NEXT: ldaxrh w[[OLD:[0-9]+]], [x[[ADDR]]] 683 ; w0 below is a reasonable guess but could change: it certainly comes into the 684 ; function there. 685 ; CHECK-NEXT: cmp w0, w[[OLD]], uxth 686 ; CHECK-NEXT: csel [[NEW:w[0-9]+]], w[[OLD]], w0, hi 687 ; CHECK-NEXT: stxrh [[STATUS:w[0-9]+]], [[NEW]], [x[[ADDR]]] 688 ; CHECK-NEXT: cbnz [[STATUS]], .LBB{{[0-9]+}}_1 689 ; CHECK-NOT: dmb 690 691 ; CHECK: mov x0, x[[OLD]] 692 ret i16 %old 693 } 694 695 define i32 @test_atomic_load_umin_i32(i32 %offset) nounwind { 696 ; CHECK-LABEL: test_atomic_load_umin_i32: 697 %old = atomicrmw umin i32* @var32, i32 %offset seq_cst 698 ; CHECK-NOT: dmb 699 ; CHECK: adrp [[TMPADDR:x[0-9]+]], var32 700 ; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], #:lo12:var32 701 702 ; CHECK: .LBB{{[0-9]+}}_1: 703 ; CHECK-NEXT: ldaxr w[[OLD:[0-9]+]], [x[[ADDR]]] 704 ; w0 below is a reasonable guess but could change: it certainly comes into the 705 ; function there. 706 ; CHECK-NEXT: cmp w0, w[[OLD]] 707 ; CHECK-NEXT: csel [[NEW:w[0-9]+]], w[[OLD]], w0, hi 708 ; CHECK-NEXT: stlxr [[STATUS:w[0-9]+]], [[NEW]], [x[[ADDR]]] 709 ; CHECK-NEXT: cbnz [[STATUS]], .LBB{{[0-9]+}}_1 710 ; CHECK-NOT: dmb 711 712 ; CHECK: mov x0, x[[OLD]] 713 ret i32 %old 714 } 715 716 define i64 @test_atomic_load_umin_i64(i64 %offset) nounwind { 717 ; CHECK-LABEL: test_atomic_load_umin_i64: 718 %old = atomicrmw umin i64* @var64, i64 %offset acq_rel 719 ; CHECK-NOT: dmb 720 ; CHECK: adrp [[TMPADDR:x[0-9]+]], var64 721 ; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], #:lo12:var64 722 723 ; CHECK: .LBB{{[0-9]+}}_1: 724 ; CHECK-NEXT: ldaxr x[[OLD:[0-9]+]], [x[[ADDR]]] 725 ; x0 below is a reasonable guess but could change: it certainly comes into the 726 ; function there. 727 ; CHECK-NEXT: cmp x0, x[[OLD]] 728 ; CHECK-NEXT: csel [[NEW:x[0-9]+]], x[[OLD]], x0, hi 729 ; CHECK-NEXT: stlxr [[STATUS:w[0-9]+]], [[NEW]], [x[[ADDR]]] 730 ; CHECK-NEXT: cbnz [[STATUS]], .LBB{{[0-9]+}}_1 731 ; CHECK-NOT: dmb 732 733 ; CHECK: mov x0, x[[OLD]] 734 ret i64 %old 735 } 736 737 define i8 @test_atomic_load_umax_i8(i8 %offset) nounwind { 738 ; CHECK-LABEL: test_atomic_load_umax_i8: 739 %old = atomicrmw umax i8* @var8, i8 %offset acq_rel 740 ; CHECK-NOT: dmb 741 ; CHECK: adrp [[TMPADDR:x[0-9]+]], var8 742 ; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], #:lo12:var8 743 744 ; CHECK: .LBB{{[0-9]+}}_1: 745 ; CHECK-NEXT: ldaxrb w[[OLD:[0-9]+]], [x[[ADDR]]] 746 ; w0 below is a reasonable guess but could change: it certainly comes into the 747 ; function there. 748 ; CHECK-NEXT: cmp w0, w[[OLD]], uxtb 749 ; CHECK-NEXT: csel [[NEW:w[0-9]+]], w[[OLD]], w0, lo 750 ; CHECK-NEXT: stlxrb [[STATUS:w[0-9]+]], [[NEW]], [x[[ADDR]]] 751 ; CHECK-NEXT: cbnz [[STATUS]], .LBB{{[0-9]+}}_1 752 ; CHECK-NOT: dmb 753 754 ; CHECK: mov x0, x[[OLD]] 755 ret i8 %old 756 } 757 758 define i16 @test_atomic_load_umax_i16(i16 %offset) nounwind { 759 ; CHECK-LABEL: test_atomic_load_umax_i16: 760 %old = atomicrmw umax i16* @var16, i16 %offset monotonic 761 ; CHECK-NOT: dmb 762 ; CHECK: adrp [[TMPADDR:x[0-9]+]], var16 763 ; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], #:lo12:var16 764 765 ; CHECK: .LBB{{[0-9]+}}_1: 766 ; CHECK-NEXT: ldxrh w[[OLD:[0-9]+]], [x[[ADDR]]] 767 ; w0 below is a reasonable guess but could change: it certainly comes into the 768 ; function there. 769 ; CHECK-NEXT: cmp w0, w[[OLD]], uxth 770 ; CHECK-NEXT: csel [[NEW:w[0-9]+]], w[[OLD]], w0, lo 771 ; CHECK-NEXT: stxrh [[STATUS:w[0-9]+]], [[NEW]], [x[[ADDR]]] 772 ; CHECK-NEXT: cbnz [[STATUS]], .LBB{{[0-9]+}}_1 773 ; CHECK-NOT: dmb 774 775 ; CHECK: mov x0, x[[OLD]] 776 ret i16 %old 777 } 778 779 define i32 @test_atomic_load_umax_i32(i32 %offset) nounwind { 780 ; CHECK-LABEL: test_atomic_load_umax_i32: 781 %old = atomicrmw umax i32* @var32, i32 %offset seq_cst 782 ; CHECK-NOT: dmb 783 ; CHECK: adrp [[TMPADDR:x[0-9]+]], var32 784 ; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], #:lo12:var32 785 786 ; CHECK: .LBB{{[0-9]+}}_1: 787 ; CHECK-NEXT: ldaxr w[[OLD:[0-9]+]], [x[[ADDR]]] 788 ; w0 below is a reasonable guess but could change: it certainly comes into the 789 ; function there. 790 ; CHECK-NEXT: cmp w0, w[[OLD]] 791 ; CHECK-NEXT: csel [[NEW:w[0-9]+]], w[[OLD]], w0, lo 792 ; CHECK-NEXT: stlxr [[STATUS:w[0-9]+]], [[NEW]], [x[[ADDR]]] 793 ; CHECK-NEXT: cbnz [[STATUS]], .LBB{{[0-9]+}}_1 794 ; CHECK-NOT: dmb 795 796 ; CHECK: mov x0, x[[OLD]] 797 ret i32 %old 798 } 799 800 define i64 @test_atomic_load_umax_i64(i64 %offset) nounwind { 801 ; CHECK-LABEL: test_atomic_load_umax_i64: 802 %old = atomicrmw umax i64* @var64, i64 %offset release 803 ; CHECK-NOT: dmb 804 ; CHECK: adrp [[TMPADDR:x[0-9]+]], var64 805 ; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], #:lo12:var64 806 807 ; CHECK: .LBB{{[0-9]+}}_1: 808 ; CHECK-NEXT: ldxr x[[OLD:[0-9]+]], [x[[ADDR]]] 809 ; x0 below is a reasonable guess but could change: it certainly comes into the 810 ; function there. 811 ; CHECK-NEXT: cmp x0, x[[OLD]] 812 ; CHECK-NEXT: csel [[NEW:x[0-9]+]], x[[OLD]], x0, lo 813 ; CHECK-NEXT: stlxr [[STATUS:w[0-9]+]], [[NEW]], [x[[ADDR]]] 814 ; CHECK-NEXT: cbnz [[STATUS]], .LBB{{[0-9]+}}_1 815 ; CHECK-NOT: dmb 816 817 ; CHECK: mov x0, x[[OLD]] 818 ret i64 %old 819 } 820 821 define i8 @test_atomic_cmpxchg_i8(i8 %wanted, i8 %new) nounwind { 822 ; CHECK-LABEL: test_atomic_cmpxchg_i8: 823 %old = cmpxchg i8* @var8, i8 %wanted, i8 %new acquire 824 ; CHECK-NOT: dmb 825 ; CHECK: adrp [[TMPADDR:x[0-9]+]], var8 826 ; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], #:lo12:var8 827 828 ; CHECK: [[STARTAGAIN:.LBB[0-9]+_[0-9]+]]: 829 ; CHECK-NEXT: ldaxrb w[[OLD:[0-9]+]], [x[[ADDR]]] 830 ; w0 below is a reasonable guess but could change: it certainly comes into the 831 ; function there. 832 ; CHECK-NEXT: cmp w[[OLD]], w0 833 ; CHECK-NEXT: b.ne [[GET_OUT:.LBB[0-9]+_[0-9]+]] 834 ; As above, w1 is a reasonable guess. 835 ; CHECK: stxrb [[STATUS:w[0-9]+]], w1, [x[[ADDR]]] 836 ; CHECK-NEXT: cbnz [[STATUS]], [[STARTAGAIN]] 837 ; CHECK-NOT: dmb 838 839 ; CHECK: mov x0, x[[OLD]] 840 ret i8 %old 841 } 842 843 define i16 @test_atomic_cmpxchg_i16(i16 %wanted, i16 %new) nounwind { 844 ; CHECK-LABEL: test_atomic_cmpxchg_i16: 845 %old = cmpxchg i16* @var16, i16 %wanted, i16 %new seq_cst 846 ; CHECK-NOT: dmb 847 ; CHECK: adrp [[TMPADDR:x[0-9]+]], var16 848 ; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], #:lo12:var16 849 850 ; CHECK: [[STARTAGAIN:.LBB[0-9]+_[0-9]+]]: 851 ; CHECK-NEXT: ldaxrh w[[OLD:[0-9]+]], [x[[ADDR]]] 852 ; w0 below is a reasonable guess but could change: it certainly comes into the 853 ; function there. 854 ; CHECK-NEXT: cmp w[[OLD]], w0 855 ; CHECK-NEXT: b.ne [[GET_OUT:.LBB[0-9]+_[0-9]+]] 856 ; As above, w1 is a reasonable guess. 857 ; CHECK: stlxrh [[STATUS:w[0-9]+]], w1, [x[[ADDR]]] 858 ; CHECK-NEXT: cbnz [[STATUS]], [[STARTAGAIN]] 859 ; CHECK-NOT: dmb 860 861 ; CHECK: mov x0, x[[OLD]] 862 ret i16 %old 863 } 864 865 define i32 @test_atomic_cmpxchg_i32(i32 %wanted, i32 %new) nounwind { 866 ; CHECK-LABEL: test_atomic_cmpxchg_i32: 867 %old = cmpxchg i32* @var32, i32 %wanted, i32 %new release 868 ; CHECK-NOT: dmb 869 ; CHECK: adrp [[TMPADDR:x[0-9]+]], var32 870 ; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], #:lo12:var32 871 872 ; CHECK: [[STARTAGAIN:.LBB[0-9]+_[0-9]+]]: 873 ; CHECK-NEXT: ldxr w[[OLD:[0-9]+]], [x[[ADDR]]] 874 ; w0 below is a reasonable guess but could change: it certainly comes into the 875 ; function there. 876 ; CHECK-NEXT: cmp w[[OLD]], w0 877 ; CHECK-NEXT: b.ne [[GET_OUT:.LBB[0-9]+_[0-9]+]] 878 ; As above, w1 is a reasonable guess. 879 ; CHECK: stlxr [[STATUS:w[0-9]+]], w1, [x[[ADDR]]] 880 ; CHECK-NEXT: cbnz [[STATUS]], [[STARTAGAIN]] 881 ; CHECK-NOT: dmb 882 883 ; CHECK: mov x0, x[[OLD]] 884 ret i32 %old 885 } 886 887 define i64 @test_atomic_cmpxchg_i64(i64 %wanted, i64 %new) nounwind { 888 ; CHECK-LABEL: test_atomic_cmpxchg_i64: 889 %old = cmpxchg i64* @var64, i64 %wanted, i64 %new monotonic 890 ; CHECK-NOT: dmb 891 ; CHECK: adrp [[TMPADDR:x[0-9]+]], var64 892 ; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], #:lo12:var64 893 894 ; CHECK: [[STARTAGAIN:.LBB[0-9]+_[0-9]+]]: 895 ; CHECK-NEXT: ldxr x[[OLD:[0-9]+]], [x[[ADDR]]] 896 ; w0 below is a reasonable guess but could change: it certainly comes into the 897 ; function there. 898 ; CHECK-NEXT: cmp x[[OLD]], x0 899 ; CHECK-NEXT: b.ne [[GET_OUT:.LBB[0-9]+_[0-9]+]] 900 ; As above, w1 is a reasonable guess. 901 ; CHECK: stxr [[STATUS:w[0-9]+]], x1, [x[[ADDR]]] 902 ; CHECK-NEXT: cbnz [[STATUS]], [[STARTAGAIN]] 903 ; CHECK-NOT: dmb 904 905 ; CHECK: mov x0, x[[OLD]] 906 ret i64 %old 907 } 908 909 define i8 @test_atomic_load_monotonic_i8() nounwind { 910 ; CHECK-LABEL: test_atomic_load_monotonic_i8: 911 %val = load atomic i8* @var8 monotonic, align 1 912 ; CHECK-NOT: dmb 913 ; CHECK: adrp x[[HIADDR:[0-9]+]], var8 914 ; CHECK: ldrb w0, [x[[HIADDR]], #:lo12:var8] 915 ; CHECK-NOT: dmb 916 917 ret i8 %val 918 } 919 920 define i8 @test_atomic_load_monotonic_regoff_i8(i64 %base, i64 %off) nounwind { 921 ; CHECK-LABEL: test_atomic_load_monotonic_regoff_i8: 922 %addr_int = add i64 %base, %off 923 %addr = inttoptr i64 %addr_int to i8* 924 925 %val = load atomic i8* %addr monotonic, align 1 926 ; CHECK-NOT: dmb 927 ; CHECK: ldrb w0, [x0, x1] 928 ; CHECK-NOT: dmb 929 930 ret i8 %val 931 } 932 933 define i8 @test_atomic_load_acquire_i8() nounwind { 934 ; CHECK-LABEL: test_atomic_load_acquire_i8: 935 %val = load atomic i8* @var8 acquire, align 1 936 ; CHECK-NOT: dmb 937 ; CHECK: adrp [[TMPADDR:x[0-9]+]], var8 938 ; CHECK-NOT: dmb 939 ; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], #:lo12:var8 940 ; CHECK-NOT: dmb 941 ; CHECK: ldarb w0, [x[[ADDR]]] 942 ; CHECK-NOT: dmb 943 ret i8 %val 944 } 945 946 define i8 @test_atomic_load_seq_cst_i8() nounwind { 947 ; CHECK-LABEL: test_atomic_load_seq_cst_i8: 948 %val = load atomic i8* @var8 seq_cst, align 1 949 ; CHECK-NOT: dmb 950 ; CHECK: adrp [[HIADDR:x[0-9]+]], var8 951 ; CHECK-NOT: dmb 952 ; CHECK: add x[[ADDR:[0-9]+]], [[HIADDR]], #:lo12:var8 953 ; CHECK-NOT: dmb 954 ; CHECK: ldarb w0, [x[[ADDR]]] 955 ; CHECK-NOT: dmb 956 ret i8 %val 957 } 958 959 define i16 @test_atomic_load_monotonic_i16() nounwind { 960 ; CHECK-LABEL: test_atomic_load_monotonic_i16: 961 %val = load atomic i16* @var16 monotonic, align 2 962 ; CHECK-NOT: dmb 963 ; CHECK: adrp x[[HIADDR:[0-9]+]], var16 964 ; CHECK-NOT: dmb 965 ; CHECK: ldrh w0, [x[[HIADDR]], #:lo12:var16] 966 ; CHECK-NOT: dmb 967 968 ret i16 %val 969 } 970 971 define i32 @test_atomic_load_monotonic_regoff_i32(i64 %base, i64 %off) nounwind { 972 ; CHECK-LABEL: test_atomic_load_monotonic_regoff_i32: 973 %addr_int = add i64 %base, %off 974 %addr = inttoptr i64 %addr_int to i32* 975 976 %val = load atomic i32* %addr monotonic, align 4 977 ; CHECK-NOT: dmb 978 ; CHECK: ldr w0, [x0, x1] 979 ; CHECK-NOT: dmb 980 981 ret i32 %val 982 } 983 984 define i64 @test_atomic_load_seq_cst_i64() nounwind { 985 ; CHECK-LABEL: test_atomic_load_seq_cst_i64: 986 %val = load atomic i64* @var64 seq_cst, align 8 987 ; CHECK-NOT: dmb 988 ; CHECK: adrp [[HIADDR:x[0-9]+]], var64 989 ; CHECK-NOT: dmb 990 ; CHECK: add x[[ADDR:[0-9]+]], [[HIADDR]], #:lo12:var64 991 ; CHECK-NOT: dmb 992 ; CHECK: ldar x0, [x[[ADDR]]] 993 ; CHECK-NOT: dmb 994 ret i64 %val 995 } 996 997 define void @test_atomic_store_monotonic_i8(i8 %val) nounwind { 998 ; CHECK-LABEL: test_atomic_store_monotonic_i8: 999 store atomic i8 %val, i8* @var8 monotonic, align 1 1000 ; CHECK: adrp x[[HIADDR:[0-9]+]], var8 1001 ; CHECK: strb w0, [x[[HIADDR]], #:lo12:var8] 1002 1003 ret void 1004 } 1005 1006 define void @test_atomic_store_monotonic_regoff_i8(i64 %base, i64 %off, i8 %val) nounwind { 1007 ; CHECK-LABEL: test_atomic_store_monotonic_regoff_i8: 1008 1009 %addr_int = add i64 %base, %off 1010 %addr = inttoptr i64 %addr_int to i8* 1011 1012 store atomic i8 %val, i8* %addr monotonic, align 1 1013 ; CHECK: strb w2, [x0, x1] 1014 1015 ret void 1016 } 1017 define void @test_atomic_store_release_i8(i8 %val) nounwind { 1018 ; CHECK-LABEL: test_atomic_store_release_i8: 1019 store atomic i8 %val, i8* @var8 release, align 1 1020 ; CHECK-NOT: dmb 1021 ; CHECK: adrp [[HIADDR:x[0-9]+]], var8 1022 ; CHECK-NOT: dmb 1023 ; CHECK: add x[[ADDR:[0-9]+]], [[HIADDR]], #:lo12:var8 1024 ; CHECK-NOT: dmb 1025 ; CHECK: stlrb w0, [x[[ADDR]]] 1026 ; CHECK-NOT: dmb 1027 ret void 1028 } 1029 1030 define void @test_atomic_store_seq_cst_i8(i8 %val) nounwind { 1031 ; CHECK-LABEL: test_atomic_store_seq_cst_i8: 1032 store atomic i8 %val, i8* @var8 seq_cst, align 1 1033 ; CHECK-NOT: dmb 1034 ; CHECK: adrp [[HIADDR:x[0-9]+]], var8 1035 ; CHECK-NOT: dmb 1036 ; CHECK: add x[[ADDR:[0-9]+]], [[HIADDR]], #:lo12:var8 1037 ; CHECK-NOT: dmb 1038 ; CHECK: stlrb w0, [x[[ADDR]]] 1039 ; CHECK-NOT: dmb 1040 1041 ret void 1042 } 1043 1044 define void @test_atomic_store_monotonic_i16(i16 %val) nounwind { 1045 ; CHECK-LABEL: test_atomic_store_monotonic_i16: 1046 store atomic i16 %val, i16* @var16 monotonic, align 2 1047 ; CHECK-NOT: dmb 1048 ; CHECK: adrp x[[HIADDR:[0-9]+]], var16 1049 ; CHECK-NOT: dmb 1050 ; CHECK: strh w0, [x[[HIADDR]], #:lo12:var16] 1051 ; CHECK-NOT: dmb 1052 ret void 1053 } 1054 1055 define void @test_atomic_store_monotonic_regoff_i32(i64 %base, i64 %off, i32 %val) nounwind { 1056 ; CHECK-LABEL: test_atomic_store_monotonic_regoff_i32: 1057 1058 %addr_int = add i64 %base, %off 1059 %addr = inttoptr i64 %addr_int to i32* 1060 1061 store atomic i32 %val, i32* %addr monotonic, align 4 1062 ; CHECK-NOT: dmb 1063 ; CHECK: str w2, [x0, x1] 1064 ; CHECK-NOT: dmb 1065 1066 ret void 1067 } 1068 1069 define void @test_atomic_store_release_i64(i64 %val) nounwind { 1070 ; CHECK-LABEL: test_atomic_store_release_i64: 1071 store atomic i64 %val, i64* @var64 release, align 8 1072 ; CHECK-NOT: dmb 1073 ; CHECK: adrp [[HIADDR:x[0-9]+]], var64 1074 ; CHECK-NOT: dmb 1075 ; CHECK: add x[[ADDR:[0-9]+]], [[HIADDR]], #:lo12:var64 1076 ; CHECK-NOT: dmb 1077 ; CHECK: stlr x0, [x[[ADDR]]] 1078 ; CHECK-NOT: dmb 1079 ret void 1080 } 1081