summaryrefslogtreecommitdiffstats
path: root/test/CodeGen
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2012-04-12 05:08:17 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2012-04-12 05:08:17 +0000
commitff34d401ff385ef7173ca612432b4ea717fff690 (patch)
treede759a7c65405730906e7d4ffd5f25cbbd5bcf69 /test/CodeGen
parentb92bd4b3271b7892abe9fd8c74fb54a27ad702ab (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.c143
-rw-r--r--test/CodeGen/atomic_init.c14
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
-}