1 // RUN: %clang_cc1 %s -emit-llvm -o - -ffreestanding -triple=i686-apple-darwin9 | FileCheck %s 2 3 // Also test serialization of atomic operations here, to avoid duplicating the 4 // test. 5 // RUN: %clang_cc1 %s -emit-pch -o %t -ffreestanding -triple=i686-apple-darwin9 6 // RUN: %clang_cc1 %s -include-pch %t -ffreestanding -triple=i686-apple-darwin9 -emit-llvm -o - | FileCheck %s 7 #ifndef ALREADY_INCLUDED 8 #define ALREADY_INCLUDED 9 10 #include <stdatomic.h> 11 12 // Basic IRGen tests for __c11_atomic_* and GNU __atomic_* 13 14 int fi1(_Atomic(int) *i) { 15 // CHECK-LABEL: @fi1 16 // CHECK: load atomic i32, i32* {{.*}} seq_cst 17 return __c11_atomic_load(i, memory_order_seq_cst); 18 } 19 20 int fi1a(int *i) { 21 // CHECK-LABEL: @fi1a 22 // CHECK: load atomic i32, i32* {{.*}} seq_cst 23 int v; 24 __atomic_load(i, &v, memory_order_seq_cst); 25 return v; 26 } 27 28 int fi1b(int *i) { 29 // CHECK-LABEL: @fi1b 30 // CHECK: load atomic i32, i32* {{.*}} seq_cst 31 return __atomic_load_n(i, memory_order_seq_cst); 32 } 33 34 int fi1c(atomic_int *i) { 35 // CHECK-LABEL: @fi1c 36 // CHECK: load atomic i32, i32* {{.*}} seq_cst 37 return atomic_load(i); 38 } 39 40 void fi2(_Atomic(int) *i) { 41 // CHECK-LABEL: @fi2 42 // CHECK: store atomic i32 {{.*}} seq_cst 43 __c11_atomic_store(i, 1, memory_order_seq_cst); 44 } 45 46 void fi2a(int *i) { 47 // CHECK-LABEL: @fi2a 48 // CHECK: store atomic i32 {{.*}} seq_cst 49 int v = 1; 50 __atomic_store(i, &v, memory_order_seq_cst); 51 } 52 53 void fi2b(int *i) { 54 // CHECK-LABEL: @fi2b 55 // CHECK: store atomic i32 {{.*}} seq_cst 56 __atomic_store_n(i, 1, memory_order_seq_cst); 57 } 58 59 void fi2c(atomic_int *i) { 60 // CHECK-LABEL: @fi2c 61 // CHECK: store atomic i32 {{.*}} seq_cst 62 atomic_store(i, 1); 63 } 64 65 int fi3(_Atomic(int) *i) { 66 // CHECK-LABEL: @fi3 67 // CHECK: atomicrmw and 68 // CHECK-NOT: and 69 return __c11_atomic_fetch_and(i, 1, memory_order_seq_cst); 70 } 71 72 int fi3a(int *i) { 73 // CHECK-LABEL: @fi3a 74 // CHECK: atomicrmw xor 75 // CHECK-NOT: xor 76 return __atomic_fetch_xor(i, 1, memory_order_seq_cst); 77 } 78 79 int fi3b(int *i) { 80 // CHECK-LABEL: @fi3b 81 // CHECK: atomicrmw add 82 // CHECK: add 83 return __atomic_add_fetch(i, 1, memory_order_seq_cst); 84 } 85 86 int fi3c(int *i) { 87 // CHECK-LABEL: @fi3c 88 // CHECK: atomicrmw nand 89 // CHECK-NOT: and 90 return __atomic_fetch_nand(i, 1, memory_order_seq_cst); 91 } 92 93 int fi3d(int *i) { 94 // CHECK-LABEL: @fi3d 95 // CHECK: atomicrmw nand 96 // CHECK: and 97 // CHECK: xor 98 return __atomic_nand_fetch(i, 1, memory_order_seq_cst); 99 } 100 101 int fi3e(atomic_int *i) { 102 // CHECK-LABEL: @fi3e 103 // CHECK: atomicrmw or 104 // CHECK-NOT: {{ or }} 105 return atomic_fetch_or(i, 1); 106 } 107 108 int fi3f(int *i) { 109 // CHECK-LABEL: @fi3f 110 // CHECK-NOT: store volatile 111 // CHECK: atomicrmw or 112 // CHECK-NOT: {{ or }} 113 return __atomic_fetch_or(i, (short)1, memory_order_seq_cst); 114 } 115 116 _Bool fi4(_Atomic(int) *i) { 117 // CHECK-LABEL: @fi4( 118 // CHECK: [[PAIR:%[.0-9A-Z_a-z]+]] = cmpxchg i32* [[PTR:%[.0-9A-Z_a-z]+]], i32 [[EXPECTED:%[.0-9A-Z_a-z]+]], i32 [[DESIRED:%[.0-9A-Z_a-z]+]] 119 // CHECK: [[OLD:%[.0-9A-Z_a-z]+]] = extractvalue { i32, i1 } [[PAIR]], 0 120 // CHECK: [[CMP:%[.0-9A-Z_a-z]+]] = extractvalue { i32, i1 } [[PAIR]], 1 121 // CHECK: br i1 [[CMP]], label %[[STORE_EXPECTED:[.0-9A-Z_a-z]+]], label %[[CONTINUE:[.0-9A-Z_a-z]+]] 122 // CHECK: store i32 [[OLD]] 123 int cmp = 0; 124 return __c11_atomic_compare_exchange_strong(i, &cmp, 1, memory_order_acquire, memory_order_acquire); 125 } 126 127 _Bool fi4a(int *i) { 128 // CHECK-LABEL: @fi4a 129 // CHECK: [[PAIR:%[.0-9A-Z_a-z]+]] = cmpxchg i32* [[PTR:%[.0-9A-Z_a-z]+]], i32 [[EXPECTED:%[.0-9A-Z_a-z]+]], i32 [[DESIRED:%[.0-9A-Z_a-z]+]] 130 // CHECK: [[OLD:%[.0-9A-Z_a-z]+]] = extractvalue { i32, i1 } [[PAIR]], 0 131 // CHECK: [[CMP:%[.0-9A-Z_a-z]+]] = extractvalue { i32, i1 } [[PAIR]], 1 132 // CHECK: br i1 [[CMP]], label %[[STORE_EXPECTED:[.0-9A-Z_a-z]+]], label %[[CONTINUE:[.0-9A-Z_a-z]+]] 133 // CHECK: store i32 [[OLD]] 134 int cmp = 0; 135 int desired = 1; 136 return __atomic_compare_exchange(i, &cmp, &desired, 0, memory_order_acquire, memory_order_acquire); 137 } 138 139 _Bool fi4b(int *i) { 140 // CHECK-LABEL: @fi4b( 141 // CHECK: [[PAIR:%[.0-9A-Z_a-z]+]] = cmpxchg weak i32* [[PTR:%[.0-9A-Z_a-z]+]], i32 [[EXPECTED:%[.0-9A-Z_a-z]+]], i32 [[DESIRED:%[.0-9A-Z_a-z]+]] 142 // CHECK: [[OLD:%[.0-9A-Z_a-z]+]] = extractvalue { i32, i1 } [[PAIR]], 0 143 // CHECK: [[CMP:%[.0-9A-Z_a-z]+]] = extractvalue { i32, i1 } [[PAIR]], 1 144 // CHECK: br i1 [[CMP]], label %[[STORE_EXPECTED:[.0-9A-Z_a-z]+]], label %[[CONTINUE:[.0-9A-Z_a-z]+]] 145 // CHECK: store i32 [[OLD]] 146 int cmp = 0; 147 return __atomic_compare_exchange_n(i, &cmp, 1, 1, memory_order_acquire, memory_order_acquire); 148 } 149 150 _Bool fi4c(atomic_int *i) { 151 // CHECK-LABEL: @fi4c 152 // CHECK: cmpxchg i32* 153 int cmp = 0; 154 return atomic_compare_exchange_strong(i, &cmp, 1); 155 } 156 157 float ff1(_Atomic(float) *d) { 158 // CHECK-LABEL: @ff1 159 // CHECK: load atomic i32, i32* {{.*}} monotonic 160 return __c11_atomic_load(d, memory_order_relaxed); 161 } 162 163 void ff2(_Atomic(float) *d) { 164 // CHECK-LABEL: @ff2 165 // CHECK: store atomic i32 {{.*}} release 166 __c11_atomic_store(d, 1, memory_order_release); 167 } 168 169 float ff3(_Atomic(float) *d) { 170 return __c11_atomic_exchange(d, 2, memory_order_seq_cst); 171 } 172 173 struct S { 174 double x; 175 }; 176 177 struct S fd1(struct S *a) { 178 // CHECK-LABEL: @fd1 179 // CHECK: [[RETVAL:%.*]] = alloca %struct.S, align 4 180 // CHECK: [[RET:%.*]] = alloca %struct.S, align 4 181 // CHECK: [[CALL:%.*]] = call i64 @__atomic_load_8( 182 // CHECK: [[CAST:%.*]] = bitcast %struct.S* [[RET]] to i64* 183 // CHECK: store i64 [[CALL]], i64* [[CAST]], align 4 184 struct S ret; 185 __atomic_load(a, &ret, memory_order_seq_cst); 186 return ret; 187 } 188 189 void fd2(struct S *a, struct S *b) { 190 // CHECK-LABEL: @fd2 191 // CHECK: [[A_ADDR:%.*]] = alloca %struct.S*, align 4 192 // CHECK-NEXT: [[B_ADDR:%.*]] = alloca %struct.S*, align 4 193 // CHECK-NEXT: store %struct.S* %a, %struct.S** [[A_ADDR]], align 4 194 // CHECK-NEXT: store %struct.S* %b, %struct.S** [[B_ADDR]], align 4 195 // CHECK-NEXT: [[LOAD_A_PTR:%.*]] = load %struct.S*, %struct.S** [[A_ADDR]], align 4 196 // CHECK-NEXT: [[LOAD_B_PTR:%.*]] = load %struct.S*, %struct.S** [[B_ADDR]], align 4 197 // CHECK-NEXT: [[COERCED_A:%.*]] = bitcast %struct.S* [[LOAD_A_PTR]] to i8* 198 // CHECK-NEXT: [[COERCED_B:%.*]] = bitcast %struct.S* [[LOAD_B_PTR]] to i64* 199 // CHECK-NEXT: [[LOAD_B:%.*]] = load i64, i64* [[COERCED_B]], align 4 200 // CHECK-NEXT: call void @__atomic_store_8(i8* [[COERCED_A]], i64 [[LOAD_B]], 201 // CHECK-NEXT: ret void 202 __atomic_store(a, b, memory_order_seq_cst); 203 } 204 205 void fd3(struct S *a, struct S *b, struct S *c) { 206 // CHECK-LABEL: @fd3 207 // CHECK: [[A_ADDR:%.*]] = alloca %struct.S*, align 4 208 // CHECK-NEXT: [[B_ADDR:%.*]] = alloca %struct.S*, align 4 209 // CHECK-NEXT: [[C_ADDR:%.*]] = alloca %struct.S*, align 4 210 // CHECK-NEXT: store %struct.S* %a, %struct.S** [[A_ADDR]], align 4 211 // CHECK-NEXT: store %struct.S* %b, %struct.S** [[B_ADDR]], align 4 212 // CHECK-NEXT: store %struct.S* %c, %struct.S** [[C_ADDR]], align 4 213 // CHECK-NEXT: [[LOAD_A_PTR:%.*]] = load %struct.S*, %struct.S** [[A_ADDR]], align 4 214 // CHECK-NEXT: [[LOAD_B_PTR:%.*]] = load %struct.S*, %struct.S** [[B_ADDR]], align 4 215 // CHECK-NEXT: [[LOAD_C_PTR:%.*]] = load %struct.S*, %struct.S** [[C_ADDR]], align 4 216 // CHECK-NEXT: [[COERCED_A:%.*]] = bitcast %struct.S* [[LOAD_A_PTR]] to i8* 217 // CHECK-NEXT: [[COERCED_B:%.*]] = bitcast %struct.S* [[LOAD_B_PTR]] to i64* 218 // CHECK-NEXT: [[LOAD_B:%.*]] = load i64, i64* [[COERCED_B]], align 4 219 // CHECK-NEXT: [[CALL:%.*]] = call i64 @__atomic_exchange_8(i8* [[COERCED_A]], i64 [[LOAD_B]], 220 // CHECK-NEXT: [[COERCED_C:%.*]] = bitcast %struct.S* [[LOAD_C_PTR]] to i64* 221 // CHECK-NEXT: store i64 [[CALL]], i64* [[COERCED_C]], align 4 222 223 __atomic_exchange(a, b, c, memory_order_seq_cst); 224 } 225 226 _Bool fd4(struct S *a, struct S *b, struct S *c) { 227 // CHECK-LABEL: @fd4 228 // CHECK: [[A_ADDR:%.*]] = alloca %struct.S*, align 4 229 // CHECK-NEXT: [[B_ADDR:%.*]] = alloca %struct.S*, align 4 230 // CHECK-NEXT: [[C_ADDR:%.*]] = alloca %struct.S*, align 4 231 // CHECK: store %struct.S* %a, %struct.S** [[A_ADDR]], align 4 232 // CHECK-NEXT: store %struct.S* %b, %struct.S** [[B_ADDR]], align 4 233 // CHECK-NEXT: store %struct.S* %c, %struct.S** [[C_ADDR]], align 4 234 // CHECK-NEXT: [[LOAD_A_PTR:%.*]] = load %struct.S*, %struct.S** [[A_ADDR]], align 4 235 // CHECK-NEXT: [[LOAD_B_PTR:%.*]] = load %struct.S*, %struct.S** [[B_ADDR]], align 4 236 // CHECK-NEXT: [[LOAD_C_PTR:%.*]] = load %struct.S*, %struct.S** [[C_ADDR]], align 4 237 // CHECK-NEXT: [[COERCED_A:%.*]] = bitcast %struct.S* [[LOAD_A_PTR]] to i8* 238 // CHECK-NEXT: [[COERCED_B:%.*]] = bitcast %struct.S* [[LOAD_B_PTR]] to i8* 239 // CHECK-NEXT: [[COERCED_C:%.*]] = bitcast %struct.S* [[LOAD_C_PTR]] to i64* 240 // CHECK-NEXT: [[LOAD_C:%.*]] = load i64, i64* [[COERCED_C]], align 4 241 // CHECK-NEXT: [[CALL:%.*]] = call zeroext i1 @__atomic_compare_exchange_8(i8* [[COERCED_A]], i8* [[COERCED_B]], i64 [[LOAD_C]] 242 // CHECK-NEXT: ret i1 [[CALL]] 243 return __atomic_compare_exchange(a, b, c, 1, 5, 5); 244 } 245 246 int* fp1(_Atomic(int*) *p) { 247 // CHECK-LABEL: @fp1 248 // CHECK: load atomic i32, i32* {{.*}} seq_cst 249 return __c11_atomic_load(p, memory_order_seq_cst); 250 } 251 252 int* fp2(_Atomic(int*) *p) { 253 // CHECK-LABEL: @fp2 254 // CHECK: store i32 4 255 // CHECK: atomicrmw add {{.*}} monotonic 256 return __c11_atomic_fetch_add(p, 1, memory_order_relaxed); 257 } 258 259 int *fp2a(int **p) { 260 // CHECK-LABEL: @fp2a 261 // CHECK: store i32 4 262 // CHECK: atomicrmw sub {{.*}} monotonic 263 // Note, the GNU builtins do not multiply by sizeof(T)! 264 return __atomic_fetch_sub(p, 4, memory_order_relaxed); 265 } 266 267 _Complex float fc(_Atomic(_Complex float) *c) { 268 // CHECK-LABEL: @fc 269 // CHECK: atomicrmw xchg i64* 270 return __c11_atomic_exchange(c, 2, memory_order_seq_cst); 271 } 272 273 typedef struct X { int x; } X; 274 X fs(_Atomic(X) *c) { 275 // CHECK-LABEL: @fs 276 // CHECK: atomicrmw xchg i32* 277 return __c11_atomic_exchange(c, (X){2}, memory_order_seq_cst); 278 } 279 280 X fsa(X *c, X *d) { 281 // CHECK-LABEL: @fsa 282 // CHECK: atomicrmw xchg i32* 283 X ret; 284 __atomic_exchange(c, d, &ret, memory_order_seq_cst); 285 return ret; 286 } 287 288 _Bool fsb(_Bool *c) { 289 // CHECK-LABEL: @fsb 290 // CHECK: atomicrmw xchg i8* 291 return __atomic_exchange_n(c, 1, memory_order_seq_cst); 292 } 293 294 char flag1; 295 volatile char flag2; 296 void test_and_set() { 297 // CHECK: atomicrmw xchg i8* @flag1, i8 1 seq_cst 298 __atomic_test_and_set(&flag1, memory_order_seq_cst); 299 // CHECK: atomicrmw volatile xchg i8* @flag2, i8 1 acquire 300 __atomic_test_and_set(&flag2, memory_order_acquire); 301 // CHECK: store atomic volatile i8 0, i8* @flag2 release 302 __atomic_clear(&flag2, memory_order_release); 303 // CHECK: store atomic i8 0, i8* @flag1 seq_cst 304 __atomic_clear(&flag1, memory_order_seq_cst); 305 } 306 307 struct Sixteen { 308 char c[16]; 309 } sixteen; 310 struct Seventeen { 311 char c[17]; 312 } seventeen; 313 314 int lock_free(struct Incomplete *incomplete) { 315 // CHECK-LABEL: @lock_free 316 317 // CHECK: call i32 @__atomic_is_lock_free(i32 3, i8* null) 318 __c11_atomic_is_lock_free(3); 319 320 // CHECK: call i32 @__atomic_is_lock_free(i32 16, i8* {{.*}}@sixteen{{.*}}) 321 __atomic_is_lock_free(16, &sixteen); 322 323 // CHECK: call i32 @__atomic_is_lock_free(i32 17, i8* {{.*}}@seventeen{{.*}}) 324 __atomic_is_lock_free(17, &seventeen); 325 326 // CHECK: call i32 @__atomic_is_lock_free(i32 4, {{.*}}) 327 __atomic_is_lock_free(4, incomplete); 328 329 char cs[20]; 330 // CHECK: call i32 @__atomic_is_lock_free(i32 4, {{.*}}) 331 __atomic_is_lock_free(4, cs+1); 332 333 // CHECK-NOT: call 334 __atomic_always_lock_free(3, 0); 335 __atomic_always_lock_free(16, 0); 336 __atomic_always_lock_free(17, 0); 337 __atomic_always_lock_free(16, &sixteen); 338 __atomic_always_lock_free(17, &seventeen); 339 340 int n; 341 __atomic_is_lock_free(4, &n); 342 343 // CHECK: ret i32 1 344 return __c11_atomic_is_lock_free(sizeof(_Atomic(int))); 345 } 346 347 // Tests for atomic operations on big values. These should call the functions 348 // defined here: 349 // http://gcc.gnu.org/wiki/Atomic/GCCMM/LIbrary#The_Library_interface 350 351 struct foo { 352 int big[128]; 353 }; 354 struct bar { 355 char c[3]; 356 }; 357 358 struct bar smallThing, thing1, thing2; 359 struct foo bigThing; 360 _Atomic(struct foo) bigAtomic; 361 362 void structAtomicStore() { 363 // CHECK-LABEL: @structAtomicStore 364 struct foo f = {0}; 365 struct bar b = {0}; 366 __atomic_store(&smallThing, &b, 5); 367 // CHECK: call void @__atomic_store(i32 3, i8* {{.*}} @smallThing 368 369 __atomic_store(&bigThing, &f, 5); 370 // CHECK: call void @__atomic_store(i32 512, i8* {{.*}} @bigThing 371 } 372 void structAtomicLoad() { 373 // CHECK-LABEL: @structAtomicLoad 374 struct bar b; 375 __atomic_load(&smallThing, &b, 5); 376 // CHECK: call void @__atomic_load(i32 3, i8* {{.*}} @smallThing 377 378 struct foo f = {0}; 379 __atomic_load(&bigThing, &f, 5); 380 // CHECK: call void @__atomic_load(i32 512, i8* {{.*}} @bigThing 381 } 382 struct foo structAtomicExchange() { 383 // CHECK-LABEL: @structAtomicExchange 384 struct foo f = {0}; 385 struct foo old; 386 __atomic_exchange(&f, &bigThing, &old, 5); 387 // CHECK: call void @__atomic_exchange(i32 512, {{.*}}, i8* bitcast ({{.*}} @bigThing to i8*), 388 389 return __c11_atomic_exchange(&bigAtomic, f, 5); 390 // CHECK: call void @__atomic_exchange(i32 512, i8* bitcast ({{.*}} @bigAtomic to i8*), 391 } 392 int structAtomicCmpExchange() { 393 // CHECK-LABEL: @structAtomicCmpExchange 394 // CHECK: %[[x_mem:.*]] = alloca i8 395 _Bool x = __atomic_compare_exchange(&smallThing, &thing1, &thing2, 1, 5, 5); 396 // CHECK: %[[call1:.*]] = call zeroext i1 @__atomic_compare_exchange(i32 3, {{.*}} @smallThing{{.*}} @thing1{{.*}} @thing2 397 // CHECK: %[[zext1:.*]] = zext i1 %[[call1]] to i8 398 // CHECK: store i8 %[[zext1]], i8* %[[x_mem]], align 1 399 // CHECK: %[[x:.*]] = load i8, i8* %[[x_mem]] 400 // CHECK: %[[x_bool:.*]] = trunc i8 %[[x]] to i1 401 // CHECK: %[[conv1:.*]] = zext i1 %[[x_bool]] to i32 402 403 struct foo f = {0}; 404 struct foo g = {0}; 405 g.big[12] = 12; 406 return x & __c11_atomic_compare_exchange_strong(&bigAtomic, &f, g, 5, 5); 407 // CHECK: %[[call2:.*]] = call zeroext i1 @__atomic_compare_exchange(i32 512, i8* bitcast ({{.*}} @bigAtomic to i8*), 408 // CHECK: %[[conv2:.*]] = zext i1 %[[call2]] to i32 409 // CHECK: %[[and:.*]] = and i32 %[[conv1]], %[[conv2]] 410 // CHECK: ret i32 %[[and]] 411 } 412 413 // Check that no atomic operations are used in any initialisation of _Atomic 414 // types. 415 _Atomic(int) atomic_init_i = 42; 416 417 // CHECK-LABEL: @atomic_init_foo 418 void atomic_init_foo() 419 { 420 // CHECK-NOT: } 421 // CHECK-NOT: atomic 422 // CHECK: store 423 _Atomic(int) j = 12; 424 425 // CHECK-NOT: } 426 // CHECK-NOT: atomic 427 // CHECK: store 428 __c11_atomic_init(&j, 42); 429 430 // CHECK-NOT: atomic 431 // CHECK: } 432 } 433 434 // CHECK-LABEL: @failureOrder 435 void failureOrder(_Atomic(int) *ptr, int *ptr2) { 436 __c11_atomic_compare_exchange_strong(ptr, ptr2, 43, memory_order_acquire, memory_order_relaxed); 437 // CHECK: cmpxchg i32* {{%[0-9A-Za-z._]+}}, i32 {{%[0-9A-Za-z._]+}}, i32 {{%[0-9A-Za-z_.]+}} acquire monotonic 438 439 __c11_atomic_compare_exchange_weak(ptr, ptr2, 43, memory_order_seq_cst, memory_order_acquire); 440 // CHECK: cmpxchg weak i32* {{%[0-9A-Za-z._]+}}, i32 {{%[0-9A-Za-z._]+}}, i32 {{%[0-9A-Za-z_.]+}} seq_cst acquire 441 442 // Unknown ordering: conservatively pick strongest valid option (for now!). 443 __atomic_compare_exchange(ptr2, ptr2, ptr2, 0, memory_order_acq_rel, *ptr2); 444 // CHECK: cmpxchg i32* {{%[0-9A-Za-z._]+}}, i32 {{%[0-9A-Za-z._]+}}, i32 {{%[0-9A-Za-z_.]+}} acq_rel acquire 445 446 // Undefined behaviour: don't really care what that last ordering is so leave 447 // it out: 448 __atomic_compare_exchange_n(ptr2, ptr2, 43, 1, memory_order_seq_cst, 42); 449 // CHECK: cmpxchg weak i32* {{%[0-9A-Za-z._]+}}, i32 {{%[0-9A-Za-z._]+}}, i32 {{%[0-9A-Za-z_.]+}} seq_cst 450 } 451 452 // CHECK-LABEL: @generalFailureOrder 453 void generalFailureOrder(_Atomic(int) *ptr, int *ptr2, int success, int fail) { 454 __c11_atomic_compare_exchange_strong(ptr, ptr2, 42, success, fail); 455 // CHECK: switch i32 {{.*}}, label %[[MONOTONIC:[0-9a-zA-Z._]+]] [ 456 // CHECK-NEXT: i32 1, label %[[ACQUIRE:[0-9a-zA-Z._]+]] 457 // CHECK-NEXT: i32 2, label %[[ACQUIRE]] 458 // CHECK-NEXT: i32 3, label %[[RELEASE:[0-9a-zA-Z._]+]] 459 // CHECK-NEXT: i32 4, label %[[ACQREL:[0-9a-zA-Z._]+]] 460 // CHECK-NEXT: i32 5, label %[[SEQCST:[0-9a-zA-Z._]+]] 461 462 // CHECK: [[MONOTONIC]] 463 // CHECK: switch {{.*}}, label %[[MONOTONIC_MONOTONIC:[0-9a-zA-Z._]+]] [ 464 // CHECK-NEXT: ] 465 466 // CHECK: [[ACQUIRE]] 467 // CHECK: switch {{.*}}, label %[[ACQUIRE_MONOTONIC:[0-9a-zA-Z._]+]] [ 468 // CHECK-NEXT: i32 1, label %[[ACQUIRE_ACQUIRE:[0-9a-zA-Z._]+]] 469 // CHECK-NEXT: i32 2, label %[[ACQUIRE_ACQUIRE:[0-9a-zA-Z._]+]] 470 // CHECK-NEXT: ] 471 472 // CHECK: [[RELEASE]] 473 // CHECK: switch {{.*}}, label %[[RELEASE_MONOTONIC:[0-9a-zA-Z._]+]] [ 474 // CHECK-NEXT: ] 475 476 // CHECK: [[ACQREL]] 477 // CHECK: switch {{.*}}, label %[[ACQREL_MONOTONIC:[0-9a-zA-Z._]+]] [ 478 // CHECK-NEXT: i32 1, label %[[ACQREL_ACQUIRE:[0-9a-zA-Z._]+]] 479 // CHECK-NEXT: i32 2, label %[[ACQREL_ACQUIRE:[0-9a-zA-Z._]+]] 480 // CHECK-NEXT: ] 481 482 // CHECK: [[SEQCST]] 483 // CHECK: switch {{.*}}, label %[[SEQCST_MONOTONIC:[0-9a-zA-Z._]+]] [ 484 // CHECK-NEXT: i32 1, label %[[SEQCST_ACQUIRE:[0-9a-zA-Z._]+]] 485 // CHECK-NEXT: i32 2, label %[[SEQCST_ACQUIRE:[0-9a-zA-Z._]+]] 486 // CHECK-NEXT: i32 5, label %[[SEQCST_SEQCST:[0-9a-zA-Z._]+]] 487 // CHECK-NEXT: ] 488 489 // CHECK: [[MONOTONIC_MONOTONIC]] 490 // CHECK: cmpxchg {{.*}} monotonic monotonic 491 // CHECK: br 492 493 // CHECK: [[ACQUIRE_MONOTONIC]] 494 // CHECK: cmpxchg {{.*}} acquire monotonic 495 // CHECK: br 496 497 // CHECK: [[ACQUIRE_ACQUIRE]] 498 // CHECK: cmpxchg {{.*}} acquire acquire 499 // CHECK: br 500 501 // CHECK: [[ACQREL_MONOTONIC]] 502 // CHECK: cmpxchg {{.*}} acq_rel monotonic 503 // CHECK: br 504 505 // CHECK: [[ACQREL_ACQUIRE]] 506 // CHECK: cmpxchg {{.*}} acq_rel acquire 507 // CHECK: br 508 509 // CHECK: [[SEQCST_MONOTONIC]] 510 // CHECK: cmpxchg {{.*}} seq_cst monotonic 511 // CHECK: br 512 513 // CHECK: [[SEQCST_ACQUIRE]] 514 // CHECK: cmpxchg {{.*}} seq_cst acquire 515 // CHECK: br 516 517 // CHECK: [[SEQCST_SEQCST]] 518 // CHECK: cmpxchg {{.*}} seq_cst seq_cst 519 // CHECK: br 520 } 521 522 void generalWeakness(int *ptr, int *ptr2, _Bool weak) { 523 __atomic_compare_exchange_n(ptr, ptr2, 42, weak, memory_order_seq_cst, memory_order_seq_cst); 524 // CHECK: switch i1 {{.*}}, label %[[WEAK:[0-9a-zA-Z._]+]] [ 525 // CHECK-NEXT: i1 false, label %[[STRONG:[0-9a-zA-Z._]+]] 526 527 // CHECK: [[STRONG]] 528 // CHECK-NOT: br 529 // CHECK: cmpxchg {{.*}} seq_cst seq_cst 530 // CHECK: br 531 532 // CHECK: [[WEAK]] 533 // CHECK-NOT: br 534 // CHECK: cmpxchg weak {{.*}} seq_cst seq_cst 535 // CHECK: br 536 } 537 538 // Having checked the flow in the previous two cases, we'll trust clang to 539 // combine them sanely. 540 void EMIT_ALL_THE_THINGS(int *ptr, int *ptr2, int new, _Bool weak, int success, int fail) { 541 __atomic_compare_exchange(ptr, ptr2, &new, weak, success, fail); 542 543 // CHECK: = cmpxchg {{.*}} monotonic monotonic 544 // CHECK: = cmpxchg weak {{.*}} monotonic monotonic 545 // CHECK: = cmpxchg {{.*}} acquire monotonic 546 // CHECK: = cmpxchg {{.*}} acquire acquire 547 // CHECK: = cmpxchg weak {{.*}} acquire monotonic 548 // CHECK: = cmpxchg weak {{.*}} acquire acquire 549 // CHECK: = cmpxchg {{.*}} release monotonic 550 // CHECK: = cmpxchg weak {{.*}} release monotonic 551 // CHECK: = cmpxchg {{.*}} acq_rel monotonic 552 // CHECK: = cmpxchg {{.*}} acq_rel acquire 553 // CHECK: = cmpxchg weak {{.*}} acq_rel monotonic 554 // CHECK: = cmpxchg weak {{.*}} acq_rel acquire 555 // CHECK: = cmpxchg {{.*}} seq_cst monotonic 556 // CHECK: = cmpxchg {{.*}} seq_cst acquire 557 // CHECK: = cmpxchg {{.*}} seq_cst seq_cst 558 // CHECK: = cmpxchg weak {{.*}} seq_cst monotonic 559 // CHECK: = cmpxchg weak {{.*}} seq_cst acquire 560 // CHECK: = cmpxchg weak {{.*}} seq_cst seq_cst 561 } 562 563 int PR21643() { 564 return __atomic_or_fetch((int __attribute__((address_space(257))) *)0x308, 1, 565 __ATOMIC_RELAXED); 566 // CHECK: %[[atomictmp:.*]] = alloca i32, align 4 567 // CHECK: %[[atomicdst:.*]] = alloca i32, align 4 568 // CHECK: store i32 1, i32* %[[atomictmp]] 569 // CHECK: %[[one:.*]] = load i32, i32* %[[atomictmp]], align 4 570 // CHECK: %[[old:.*]] = atomicrmw or i32 addrspace(257)* inttoptr (i32 776 to i32 addrspace(257)*), i32 %[[one]] monotonic 571 // CHECK: %[[new:.*]] = or i32 %[[old]], %[[one]] 572 // CHECK: store i32 %[[new]], i32* %[[atomicdst]], align 4 573 // CHECK: %[[ret:.*]] = load i32, i32* %[[atomicdst]], align 4 574 // CHECK: ret i32 %[[ret]] 575 } 576 577 int PR17306_1(volatile _Atomic(int) *i) { 578 // CHECK-LABEL: @PR17306_1 579 // CHECK: %[[i_addr:.*]] = alloca i32 580 // CHECK-NEXT: %[[atomicdst:.*]] = alloca i32 581 // CHECK-NEXT: store i32* %i, i32** %[[i_addr]] 582 // CHECK-NEXT: %[[addr:.*]] = load i32*, i32** %[[i_addr]] 583 // CHECK-NEXT: %[[res:.*]] = load atomic volatile i32, i32* %[[addr]] seq_cst 584 // CHECK-NEXT: store i32 %[[res]], i32* %[[atomicdst]] 585 // CHECK-NEXT: %[[retval:.*]] = load i32, i32* %[[atomicdst]] 586 // CHECK-NEXT: ret i32 %[[retval]] 587 return __c11_atomic_load(i, memory_order_seq_cst); 588 } 589 590 int PR17306_2(volatile int *i, int value) { 591 // CHECK-LABEL: @PR17306_2 592 // CHECK: %[[i_addr:.*]] = alloca i32* 593 // CHECK-NEXT: %[[value_addr:.*]] = alloca i32 594 // CHECK-NEXT: %[[atomictmp:.*]] = alloca i32 595 // CHECK-NEXT: %[[atomicdst:.*]] = alloca i32 596 // CHECK-NEXT: store i32* %i, i32** %[[i_addr]] 597 // CHECK-NEXT: store i32 %value, i32* %[[value_addr]] 598 // CHECK-NEXT: %[[i_lval:.*]] = load i32*, i32** %[[i_addr]] 599 // CHECK-NEXT: %[[value:.*]] = load i32, i32* %[[value_addr]] 600 // CHECK-NEXT: store i32 %[[value]], i32* %[[atomictmp]] 601 // CHECK-NEXT: %[[value_lval:.*]] = load i32, i32* %[[atomictmp]] 602 // CHECK-NEXT: %[[old_val:.*]] = atomicrmw volatile add i32* %[[i_lval]], i32 %[[value_lval]] seq_cst 603 // CHECK-NEXT: %[[new_val:.*]] = add i32 %[[old_val]], %[[value_lval]] 604 // CHECK-NEXT: store i32 %[[new_val]], i32* %[[atomicdst]] 605 // CHECK-NEXT: %[[retval:.*]] = load i32, i32* %[[atomicdst]] 606 // CHECK-NEXT: ret i32 %[[retval]] 607 return __atomic_add_fetch(i, value, memory_order_seq_cst); 608 } 609 610 #endif 611