321 lines · c
1// RUN: %clang_cc1 %s -emit-llvm -o - -triple=x86_64-apple-macosx10.9.0 | FileCheck %s2// REQUIRES: x86-registered-target3// Also test serialization of atomic operations here, to avoid duplicating the4// test.5// RUN: %clang_cc1 %s -emit-pch -o %t -triple=x86_64-apple-macosx10.9.06// RUN: %clang_cc1 %s -include-pch %t -triple=x86_64-apple-macosx10.9.0 -emit-llvm -o - | FileCheck %s7#ifndef ALREADY_INCLUDED8#define ALREADY_INCLUDED9 10// Basic IRGen tests for __c11_atomic_* and GNU __atomic_*11 12typedef enum memory_order {13 memory_order_relaxed, memory_order_consume, memory_order_acquire,14 memory_order_release, memory_order_acq_rel, memory_order_seq_cst15} memory_order;16 17int fi1(_Atomic(int) *i) {18 // CHECK: @fi119 // CHECK: load atomic i32, ptr {{.*}} seq_cst, align 420 return __c11_atomic_load(i, memory_order_seq_cst);21}22 23int fi1a(int *i) {24 // CHECK: @fi1a25 // CHECK: load atomic i32, ptr {{.*}} seq_cst, align 426 int v;27 __atomic_load(i, &v, memory_order_seq_cst);28 return v;29}30 31int fi1b(int *i) {32 // CHECK: @fi1b33 // CHECK: load atomic i32, ptr {{.*}} seq_cst, align 434 return __atomic_load_n(i, memory_order_seq_cst);35}36 37void fi2(_Atomic(int) *i) {38 // CHECK: @fi239 // CHECK: store atomic i32 {{.*}} seq_cst, align 440 __c11_atomic_store(i, 1, memory_order_seq_cst);41}42 43void fi2a(int *i) {44 // CHECK: @fi2a45 // CHECK: store atomic i32 {{.*}} seq_cst, align 446 int v = 1;47 __atomic_store(i, &v, memory_order_seq_cst);48}49 50void fi2b(int *i) {51 // CHECK: @fi2b52 // CHECK: store atomic i32 {{.*}} seq_cst, align 453 __atomic_store_n(i, 1, memory_order_seq_cst);54}55 56int fi3(_Atomic(int) *i) {57 // CHECK: @fi358 // CHECK: atomicrmw and {{.*}} seq_cst, align 459 // CHECK-NOT: and60 return __c11_atomic_fetch_and(i, 1, memory_order_seq_cst);61}62 63int fi3a(int *i) {64 // CHECK: @fi3a65 // CHECK: atomicrmw xor {{.*}} seq_cst, align 466 // CHECK-NOT: xor67 return __atomic_fetch_xor(i, 1, memory_order_seq_cst);68}69 70int fi3b(int *i) {71 // CHECK: @fi3b72 // CHECK: atomicrmw add {{.*}} seq_cst, align 473 // CHECK: add74 return __atomic_add_fetch(i, 1, memory_order_seq_cst);75}76 77int fi3c(int *i) {78 // CHECK: @fi3c79 // CHECK: atomicrmw nand {{.*}} seq_cst, align 480 // CHECK-NOT: and81 return __atomic_fetch_nand(i, 1, memory_order_seq_cst);82}83 84int fi3d(int *i) {85 // CHECK: @fi3d86 // CHECK: atomicrmw nand {{.*}} seq_cst, align 487 // CHECK: and88 // CHECK: xor89 return __atomic_nand_fetch(i, 1, memory_order_seq_cst);90}91 92_Bool fi4(_Atomic(int) *i) {93 // CHECK: @fi494 // CHECK: cmpxchg ptr {{.*}} acquire acquire, align 495 int cmp = 0;96 return __c11_atomic_compare_exchange_strong(i, &cmp, 1, memory_order_acquire, memory_order_acquire);97}98 99_Bool fi4a(int *i) {100 // CHECK: @fi4101 // CHECK: cmpxchg ptr {{.*}} acquire acquire, align 4102 int cmp = 0;103 int desired = 1;104 return __atomic_compare_exchange(i, &cmp, &desired, 0, memory_order_acquire, memory_order_acquire);105}106 107_Bool fi4b(int *i) {108 // CHECK: @fi4109 // CHECK: cmpxchg weak ptr {{.*}} acquire acquire, align 4110 int cmp = 0;111 return __atomic_compare_exchange_n(i, &cmp, 1, 1, memory_order_acquire, memory_order_acquire);112}113 114float ff1(_Atomic(float) *d) {115 // CHECK: @ff1116 // CHECK: load atomic i32, ptr {{.*}} monotonic, align 4117 return __c11_atomic_load(d, memory_order_relaxed);118}119 120void ff2(_Atomic(float) *d) {121 // CHECK: @ff2122 // CHECK: store atomic i32 {{.*}} release, align 4123 __c11_atomic_store(d, 1, memory_order_release);124}125 126float ff3(_Atomic(float) *d) {127 return __c11_atomic_exchange(d, 2, memory_order_seq_cst);128}129 130int* fp1(_Atomic(int*) *p) {131 // CHECK: @fp1132 // CHECK: load atomic i64, ptr {{.*}} seq_cst, align 8133 return __c11_atomic_load(p, memory_order_seq_cst);134}135 136int* fp2(_Atomic(int*) *p) {137 // CHECK: @fp2138 // CHECK: store i64 4139 // CHECK: atomicrmw add {{.*}} monotonic, align 8140 return __c11_atomic_fetch_add(p, 1, memory_order_relaxed);141}142 143int *fp2a(int **p) {144 // CHECK: @fp2a145 // CHECK: store i64 4146 // CHECK: atomicrmw sub {{.*}} monotonic, align 8147 // Note, the GNU builtins do not multiply by sizeof(T)!148 return __atomic_fetch_sub(p, 4, memory_order_relaxed);149}150 151_Complex float fc(_Atomic(_Complex float) *c) {152 // CHECK: @fc153 // CHECK: atomicrmw xchg ptr {{.*}} seq_cst, align 8154 return __c11_atomic_exchange(c, 2, memory_order_seq_cst);155}156 157typedef struct X { int x; } X;158X fs(_Atomic(X) *c) {159 // CHECK: @fs160 // CHECK: atomicrmw xchg ptr {{.*}} seq_cst, align 4161 return __c11_atomic_exchange(c, (X){2}, memory_order_seq_cst);162}163 164X fsa(X *c, X *d) {165 // CHECK: @fsa166 // CHECK: atomicrmw xchg ptr {{.*}} seq_cst, align 4167 X ret;168 __atomic_exchange(c, d, &ret, memory_order_seq_cst);169 return ret;170}171 172_Bool fsb(_Bool *c) {173 // CHECK: @fsb174 // CHECK: atomicrmw xchg ptr {{.*}} seq_cst, align 1175 return __atomic_exchange_n(c, 1, memory_order_seq_cst);176}177 178char flag1;179volatile char flag2;180void test_and_set(void) {181 // CHECK: atomicrmw xchg ptr @flag1, i8 1 seq_cst, align 1182 __atomic_test_and_set(&flag1, memory_order_seq_cst);183 // CHECK: atomicrmw volatile xchg ptr @flag2, i8 1 acquire, align 1184 __atomic_test_and_set(&flag2, memory_order_acquire);185 // CHECK: store atomic volatile i8 0, ptr @flag2 release, align 1186 __atomic_clear(&flag2, memory_order_release);187 // CHECK: store atomic i8 0, ptr @flag1 seq_cst, align 1188 __atomic_clear(&flag1, memory_order_seq_cst);189}190 191struct Sixteen {192 char c[16];193} sixteen;194struct Seventeen {195 char c[17];196} seventeen;197 198int lock_free(struct Incomplete *incomplete) {199 // CHECK: @lock_free200 201 // CHECK: call zeroext i1 @__atomic_is_lock_free(i64 noundef 3, ptr noundef null)202 __c11_atomic_is_lock_free(3);203 204 // CHECK: call zeroext i1 @__atomic_is_lock_free(i64 noundef 16, ptr noundef {{.*}}@sixteen{{.*}})205 __atomic_is_lock_free(16, &sixteen);206 207 // CHECK: call zeroext i1 @__atomic_is_lock_free(i64 noundef 17, ptr noundef {{.*}}@seventeen{{.*}})208 __atomic_is_lock_free(17, &seventeen);209 210 // CHECK: call zeroext i1 @__atomic_is_lock_free(i64 noundef 4, {{.*}})211 __atomic_is_lock_free(4, incomplete);212 213 char cs[20];214 // CHECK: call zeroext i1 @__atomic_is_lock_free(i64 noundef 4, {{.*}})215 __atomic_is_lock_free(4, cs+1);216 217 // CHECK-NOT: call218 __atomic_always_lock_free(3, 0);219 __atomic_always_lock_free(16, 0);220 __atomic_always_lock_free(17, 0);221 __atomic_always_lock_free(16, &sixteen);222 __atomic_always_lock_free(17, &seventeen);223 224 int n;225 __atomic_is_lock_free(4, &n);226 227 // CHECK: ret i32 1228 return __c11_atomic_is_lock_free(sizeof(_Atomic(int)));229}230 231// Tests for atomic operations on big values. These should call the functions232// defined here:233// http://gcc.gnu.org/wiki/Atomic/GCCMM/LIbrary#The_Library_interface234 235struct foo {236 int big[128];237};238struct bar {239 char c[3];240};241 242struct bar smallThing, thing1, thing2;243struct foo bigThing;244_Atomic(struct foo) bigAtomic;245 246void structAtomicStore(void) {247 // CHECK: @structAtomicStore248 struct foo f = {0};249 __c11_atomic_store(&bigAtomic, f, 5);250 // CHECK: call void @__atomic_store(i64 noundef 512, ptr noundef @bigAtomic,251 252 struct bar b = {0};253 __atomic_store(&smallThing, &b, 5);254 // CHECK: call void @__atomic_store(i64 noundef 3, ptr noundef @smallThing255 256 __atomic_store(&bigThing, &f, 5);257 // CHECK: call void @__atomic_store(i64 noundef 512, ptr noundef @bigThing258}259void structAtomicLoad(void) {260 // CHECK: @structAtomicLoad261 struct foo f = __c11_atomic_load(&bigAtomic, 5);262 // CHECK: call void @__atomic_load(i64 noundef 512, ptr noundef @bigAtomic,263 264 struct bar b;265 __atomic_load(&smallThing, &b, 5);266 // CHECK: call void @__atomic_load(i64 noundef 3, ptr noundef @smallThing267 268 __atomic_load(&bigThing, &f, 5);269 // CHECK: call void @__atomic_load(i64 noundef 512, ptr noundef @bigThing270}271struct foo structAtomicExchange(void) {272 // CHECK: @structAtomicExchange273 struct foo f = {0};274 struct foo old;275 __atomic_exchange(&f, &bigThing, &old, 5);276 // CHECK: call void @__atomic_exchange(i64 noundef 512, {{.*}}, ptr noundef @bigThing,277 278 return __c11_atomic_exchange(&bigAtomic, f, 5);279 // CHECK: call void @__atomic_exchange(i64 noundef 512, ptr noundef @bigAtomic,280}281int structAtomicCmpExchange(void) {282 // CHECK: @structAtomicCmpExchange283 _Bool x = __atomic_compare_exchange(&smallThing, &thing1, &thing2, 1, 5, 5);284 // CHECK: call zeroext i1 @__atomic_compare_exchange(i64 noundef 3, {{.*}} @smallThing{{.*}} @thing1{{.*}} @thing2285 286 struct foo f = {0};287 struct foo g = {0};288 g.big[12] = 12;289 return x & __c11_atomic_compare_exchange_strong(&bigAtomic, &f, g, 5, 5);290 // CHECK: call zeroext i1 @__atomic_compare_exchange(i64 noundef 512, ptr noundef @bigAtomic,291}292 293// Check that no atomic operations are used in any initialisation of _Atomic294// types.295_Atomic(int) atomic_init_i = 42;296 297// CHECK: @atomic_init_foo298void atomic_init_foo(void)299{300 // CHECK-NOT: }301 // CHECK-NOT: atomic302 // CHECK: store303 _Atomic(int) j = 12;304 305 // CHECK-NOT: }306 // CHECK-NOT: atomic307 // CHECK: store308 __c11_atomic_init(&j, 42);309 310 // CHECK-NOT: atomic311 // CHECK: }312}313 314// Check this doesn't crash315// CHECK: @test_atomic_array_param(316void test_atomic_array_param(_Atomic(struct foo) a) {317 test_atomic_array_param(a);318}319 320#endif321