diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2012-04-12 05:08:17 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2012-04-12 05:08:17 +0000 |
commit | ff34d401ff385ef7173ca612432b4ea717fff690 (patch) | |
tree | de759a7c65405730906e7d4ffd5f25cbbd5bcf69 /test/CodeGen | |
parent | b92bd4b3271b7892abe9fd8c74fb54a27ad702ab (diff) |
Implement support for 18 of the GNU-compatible __atomic builtins.
This is not quite sufficient for libstdc++'s <atomic>: we still need
__atomic_test_and_set and __atomic_clear, and may need a more complete
__atomic_is_lock_free implementation.
We are also missing an implementation of __atomic_always_lock_free,
__atomic_nand_fetch, and __atomic_fetch_nand, but those aren't needed
for libstdc++.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@154579 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'test/CodeGen')
-rw-r--r-- | test/CodeGen/atomic-ops.c | 143 | ||||
-rw-r--r-- | test/CodeGen/atomic_init.c | 14 |
2 files changed, 134 insertions, 23 deletions
diff --git a/test/CodeGen/atomic-ops.c b/test/CodeGen/atomic-ops.c index c94f14023e..24692c7585 100644 --- a/test/CodeGen/atomic-ops.c +++ b/test/CodeGen/atomic-ops.c @@ -22,23 +22,80 @@ int fi1(_Atomic(int) *i) { return __c11_atomic_load(i, memory_order_seq_cst); } +int fi1a(int *i) { + // CHECK: @fi1a + // CHECK: load atomic i32* {{.*}} seq_cst + int v; + __atomic_load(i, &v, memory_order_seq_cst); + return v; +} + +int fi1b(int *i) { + // CHECK: @fi1b + // CHECK: load atomic i32* {{.*}} seq_cst + return __atomic_load_n(i, memory_order_seq_cst); +} + void fi2(_Atomic(int) *i) { // CHECK: @fi2 // CHECK: store atomic i32 {{.*}} seq_cst __c11_atomic_store(i, 1, memory_order_seq_cst); } -void fi3(_Atomic(int) *i) { +void fi2a(int *i) { + // CHECK: @fi2a + // CHECK: store atomic i32 {{.*}} seq_cst + int v = 1; + __atomic_store(i, &v, memory_order_seq_cst); +} + +void fi2b(int *i) { + // CHECK: @fi2b + // CHECK: store atomic i32 {{.*}} seq_cst + __atomic_store_n(i, 1, memory_order_seq_cst); +} + +int fi3(_Atomic(int) *i) { // CHECK: @fi3 // CHECK: atomicrmw and - __c11_atomic_fetch_and(i, 1, memory_order_seq_cst); + // CHECK-NOT: and + return __c11_atomic_fetch_and(i, 1, memory_order_seq_cst); +} + +int fi3a(int *i) { + // CHECK: @fi3a + // CHECK: atomicrmw xor + // CHECK-NOT: xor + return __atomic_fetch_xor(i, 1, memory_order_seq_cst); +} + +int fi3b(int *i) { + // CHECK: @fi3b + // CHECK: atomicrmw add + // CHECK: add + return __atomic_add_fetch(i, 1, memory_order_seq_cst); +} + +_Bool fi4(_Atomic(int) *i) { + // CHECK: @fi4 + // CHECK: cmpxchg i32* + int cmp = 0; + return __c11_atomic_compare_exchange_strong(i, &cmp, 1, memory_order_acquire, memory_order_acquire); +} + +_Bool fi4a(int *i) { + // CHECK: @fi4 + // CHECK: cmpxchg i32* + int cmp = 0; + int desired = 1; + return __atomic_compare_exchange(i, &cmp, &desired, 0, memory_order_acquire, memory_order_acquire); } -void fi4(_Atomic(int) *i) { +_Bool fi4b(int *i) { // CHECK: @fi4 // CHECK: cmpxchg i32* int cmp = 0; - __c11_atomic_compare_exchange_strong(i, &cmp, 1, memory_order_acquire, memory_order_acquire); + return __atomic_compare_exchange_n(i, &cmp, 1, 1, memory_order_acquire, memory_order_acquire); } float ff1(_Atomic(float) *d) { @@ -70,6 +127,13 @@ int* fp2(_Atomic(int*) *p) { return __c11_atomic_fetch_add(p, 1, memory_order_relaxed); } +int *fp2a(int **p) { + // CHECK: @fp2a + // CHECK: store i32 4 + // CHECK: atomicrmw sub {{.*}} monotonic + return __atomic_fetch_sub(p, 1, memory_order_relaxed); +} + _Complex float fc(_Atomic(_Complex float) *c) { // CHECK: @fc // CHECK: atomicrmw xchg i64* @@ -83,6 +147,20 @@ X fs(_Atomic(X) *c) { return __c11_atomic_exchange(c, (X){2}, memory_order_seq_cst); } +X fsa(X *c, X *d) { + // CHECK: @fsa + // CHECK: atomicrmw xchg i32* + X ret; + __atomic_exchange(c, d, &ret, memory_order_seq_cst); + return ret; +} + +_Bool fsb(_Bool *c) { + // CHECK: @fsb + // CHECK: atomicrmw xchg i8* + return __atomic_exchange_n(c, 1, memory_order_seq_cst); +} + int lock_free() { // CHECK: @lock_free // CHECK: ret i32 1 @@ -96,33 +174,80 @@ int lock_free() { struct foo { int big[128]; }; +struct bar { + char c[3]; +}; +struct bar smallThing, thing1, thing2; +struct foo bigThing; _Atomic(struct foo) bigAtomic; void structAtomicStore() { // CHECK: @structAtomicStore struct foo f = {0}; __c11_atomic_store(&bigAtomic, f, 5); - // CHECK: call void @__atomic_store(i32 512, i8* bitcast (%struct.foo* @bigAtomic to i8*), + // CHECK: call void @__atomic_store(i32 512, i8* bitcast ({{.*}} @bigAtomic to i8*), + + struct bar b = {0}; + __atomic_store(&smallThing, &b, 5); + // CHECK: call void @__atomic_store(i32 3, i8* {{.*}} @smallThing + + __atomic_store(&bigThing, &f, 5); + // CHECK: call void @__atomic_store(i32 512, i8* {{.*}} @bigThing } void structAtomicLoad() { // CHECK: @structAtomicLoad struct foo f = __c11_atomic_load(&bigAtomic, 5); - // CHECK: call void @__atomic_load(i32 512, i8* bitcast (%struct.foo* @bigAtomic to i8*), + // CHECK: call void @__atomic_load(i32 512, i8* bitcast ({{.*}} @bigAtomic to i8*), + + struct bar b; + __atomic_load(&smallThing, &b, 5); + // CHECK: call void @__atomic_load(i32 3, i8* {{.*}} @smallThing + + __atomic_load(&bigThing, &f, 5); + // CHECK: call void @__atomic_load(i32 512, i8* {{.*}} @bigThing } struct foo structAtomicExchange() { // CHECK: @structAtomicExchange struct foo f = {0}; + struct foo old; + __atomic_exchange(&f, &bigThing, &old, 5); + // CHECK: call void @__atomic_exchange(i32 512, {{.*}}, i8* bitcast ({{.*}} @bigThing to i8*), + return __c11_atomic_exchange(&bigAtomic, f, 5); - // CHECK: call void @__atomic_exchange(i32 512, i8* bitcast (%struct.foo* @bigAtomic to i8*), + // CHECK: call void @__atomic_exchange(i32 512, i8* bitcast ({{.*}} @bigAtomic to i8*), } int structAtomicCmpExchange() { // CHECK: @structAtomicCmpExchange + _Bool x = __atomic_compare_exchange(&smallThing, &thing1, &thing2, 1, 5, 5); + // CHECK: call zeroext i1 @__atomic_compare_exchange(i32 3, {{.*}} @smallThing{{.*}} @thing1{{.*}} @thing2 + struct foo f = {0}; struct foo g = {0}; g.big[12] = 12; - return __c11_atomic_compare_exchange_strong(&bigAtomic, &f, g, 5, 5); - // CHECK: call zeroext i1 @__atomic_compare_exchange(i32 512, i8* bitcast (%struct.foo* @bigAtomic to i8*), + return x & __c11_atomic_compare_exchange_strong(&bigAtomic, &f, g, 5, 5); + // CHECK: call zeroext i1 @__atomic_compare_exchange(i32 512, i8* bitcast ({{.*}} @bigAtomic to i8*), +} + +// Check that no atomic operations are used in any initialisation of _Atomic +// types. +_Atomic(int) atomic_init_i = 42; + +// CHECK: @atomic_init_foo +void atomic_init_foo() +{ + // CHECK-NOT: } + // CHECK-NOT: atomic + // CHECK: store + _Atomic(int) j = 12; + + // CHECK-NOT: } + // CHECK-NOT: atomic + // CHECK: store + __c11_atomic_init(&j, 42); + + // CHECK-NOT: atomic + // CHECK: } } #endif diff --git a/test/CodeGen/atomic_init.c b/test/CodeGen/atomic_init.c deleted file mode 100644 index 6f773bef48..0000000000 --- a/test/CodeGen/atomic_init.c +++ /dev/null @@ -1,14 +0,0 @@ -// RUN: %clang_cc1 -emit-llvm %s -o - | FileCheck %s - -// Check that no atomic operations are used in any initialisation of _Atomic -// types. - -_Atomic(int) i = 42; - -void foo() -{ - _Atomic(int) j = 12; // CHECK: store - // CHECK-NOT: atomic - __c11_atomic_init(&j, 42); // CHECK: store - // CHECK-NOT: atomic -} |