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++.

llvm-svn: 154579
diff --git a/clang/test/CodeGen/atomic-ops.c b/clang/test/CodeGen/atomic-ops.c
index c94f140..24692c7 100644
--- a/clang/test/CodeGen/atomic-ops.c
+++ b/clang/test/CodeGen/atomic-ops.c
@@ -22,23 +22,80 @@
   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) {
-  // CHECK: @fi3
-  // CHECK: atomicrmw and
-  __c11_atomic_fetch_and(i, 1, memory_order_seq_cst);
+void fi2a(int *i) {
+  // CHECK: @fi2a
+  // CHECK: store atomic i32 {{.*}} seq_cst
+  int v = 1;
+  __atomic_store(i, &v, memory_order_seq_cst);
 }
 
-void fi4(_Atomic(int) *i) {
+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
+  // 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;
-  __c11_atomic_compare_exchange_strong(i, &cmp, 1, memory_order_acquire, memory_order_acquire);
+  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);
+}
+
+_Bool fi4b(int *i) {
+  // CHECK: @fi4
+  // CHECK: cmpxchg i32*
+  int cmp = 0;
+  return __atomic_compare_exchange_n(i, &cmp, 1, 1, memory_order_acquire, memory_order_acquire);
 }
 
 float ff1(_Atomic(float) *d) {
@@ -70,6 +127,13 @@
   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 @@
   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 @@
 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/clang/test/CodeGen/atomic_init.c b/clang/test/CodeGen/atomic_init.c
deleted file mode 100644
index 6f773be..0000000
--- a/clang/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
-}
diff --git a/clang/test/Misc/serialized-diags.c b/clang/test/Misc/serialized-diags.c
index 73ac050..ae4611ba 100644
--- a/clang/test/Misc/serialized-diags.c
+++ b/clang/test/Misc/serialized-diags.c
@@ -58,11 +58,10 @@
 // CHECK: +-Range: {{.*[/\\]}}serialized-diags.c:22:3 {{.*[/\\]}}serialized-diags.c:22:6
 // CHECK: +-Range: {{.*[/\\]}}serialized-diags.c:20:15 {{.*[/\\]}}serialized-diags.c:20:16
 // CHECK: +-{{.*[/\\]}}serialized-diags.c:19:1: note: 'taz' declared here []
-// CHECK: {{.*[/\\]}}serialized-diags.h:5:7: warning: incompatible integer to pointer conversion initializing 'char *' with an expression of type 'int';  [-Wint-conversion]
+// CHECK: {{.*[/\\]}}serialized-diags.h:5:7: warning: incompatible integer to pointer conversion initializing 'char *' with an expression of type 'int' [-Wint-conversion]
 // CHECK: Range: {{.*[/\\]}}serialized-diags.h:5:16 {{.*[/\\]}}serialized-diags.h:5:17
 // CHECK: +-{{.*[/\\]}}serialized-diags.c:26:10: note: in file included from {{.*[/\\]}}serialized-diags.c:26: []
 // CHECK: Number FIXITs = 0
 // CHECK: {{.*[/\\]}}serialized-diags.c:30:12: warning: unused variable 'x'
 // CHECK: Number FIXITs = 0
 // CHECK: Number of diagnostics: 6
-
diff --git a/clang/test/Sema/atomic-ops.c b/clang/test/Sema/atomic-ops.c
index 0560a74..0e5634f 100644
--- a/clang/test/Sema/atomic-ops.c
+++ b/clang/test/Sema/atomic-ops.c
@@ -2,36 +2,96 @@
 
 // Basic parsing/Sema tests for __c11_atomic_*
 
-// FIXME: Need to implement __c11_atomic_is_lock_free
+// FIXME: Need to implement:
+//   __c11_atomic_is_lock_free
+//   __atomic_is_lock_free
+//   __atomic_always_lock_free
+//   __atomic_test_and_set
+//   __atomic_clear
 
 typedef enum memory_order {
   memory_order_relaxed, memory_order_consume, memory_order_acquire,
   memory_order_release, memory_order_acq_rel, memory_order_seq_cst
 } memory_order;
 
-void f(_Atomic(int) *i, _Atomic(int*) *p, _Atomic(float) *d) {
+struct S { char c[3]; };
+
+void f(_Atomic(int) *i, _Atomic(int*) *p, _Atomic(float) *d,
+       int *I, int **P, float *D, struct S *s1, struct S *s2) {
+  __c11_atomic_init(I, 5); // expected-error {{pointer to _Atomic}}
   __c11_atomic_load(0); // expected-error {{too few arguments to function}}
   __c11_atomic_load(0,0,0); // expected-error {{too many arguments to function}}
-  __c11_atomic_store(0,0,0); // expected-error {{first argument to atomic operation}}
-  __c11_atomic_store((int*)0,0,0); // expected-error {{first argument to atomic operation}}
+  __c11_atomic_store(0,0,0); // expected-error {{first argument to atomic builtin must be a pointer}}
+  __c11_atomic_store((int*)0,0,0); // expected-error {{first argument to atomic operation must be a pointer to _Atomic}}
 
   __c11_atomic_load(i, memory_order_seq_cst);
   __c11_atomic_load(p, memory_order_seq_cst);
   __c11_atomic_load(d, memory_order_seq_cst);
 
+  int load_n_1 = __atomic_load_n(I, memory_order_relaxed);
+  int *load_n_2 = __atomic_load_n(P, memory_order_relaxed);
+  float load_n_3 = __atomic_load_n(D, memory_order_relaxed); // expected-error {{must be a pointer to integer or pointer}}
+  __atomic_load_n(s1, memory_order_relaxed); // expected-error {{must be a pointer to integer or pointer}}
+
+  __atomic_load(i, I, memory_order_relaxed); // expected-error {{must be a pointer to a trivially-copyable type}}
+  __atomic_load(I, i, memory_order_relaxed); // expected-warning {{passing '_Atomic(int) *' to parameter of type 'int *'}}
+  __atomic_load(I, *P, memory_order_relaxed);
+  __atomic_load(I, *P, memory_order_relaxed, 42); // expected-error {{too many arguments}}
+  (int)__atomic_load(I, I, memory_order_seq_cst); // expected-error {{operand of type 'void'}}
+  __atomic_load(s1, s2, memory_order_acquire);
+
   __c11_atomic_store(i, 1, memory_order_seq_cst);
   __c11_atomic_store(p, 1, memory_order_seq_cst); // expected-warning {{incompatible integer to pointer conversion}}
   (int)__c11_atomic_store(d, 1, memory_order_seq_cst); // expected-error {{operand of type 'void'}}
 
+  __atomic_store_n(I, 4, memory_order_release);
+  __atomic_store_n(I, 4.0, memory_order_release);
+  __atomic_store_n(I, P, memory_order_release); // expected-warning {{parameter of type 'int'}}
+  __atomic_store_n(i, 1, memory_order_release); // expected-error {{must be a pointer to integer or pointer}}
+  __atomic_store_n(s1, *s2, memory_order_release); // expected-error {{must be a pointer to integer or pointer}}
+
+  __atomic_store(I, *P, memory_order_release);
+  __atomic_store(s1, s2, memory_order_release);
+  __atomic_store(i, I, memory_order_release); // expected-error {{trivially-copyable}}
+
+  int exchange_1 = __c11_atomic_exchange(i, 1, memory_order_seq_cst);
+  int exchange_2 = __c11_atomic_exchange(I, 1, memory_order_seq_cst); // expected-error {{must be a pointer to _Atomic}}
+  int exchange_3 = __atomic_exchange_n(i, 1, memory_order_seq_cst); // expected-error {{must be a pointer to integer or pointer}}
+  int exchange_4 = __atomic_exchange_n(I, 1, memory_order_seq_cst);
+
+  __atomic_exchange(s1, s2, s2, memory_order_seq_cst);
+  __atomic_exchange(s1, I, P, memory_order_seq_cst); // expected-warning 2{{parameter of type 'struct S *'}}
+  (int)__atomic_exchange(s1, s2, s2, memory_order_seq_cst); // expected-error {{operand of type 'void'}}
+
   __c11_atomic_fetch_add(i, 1, memory_order_seq_cst);
   __c11_atomic_fetch_add(p, 1, memory_order_seq_cst);
   __c11_atomic_fetch_add(d, 1, memory_order_seq_cst); // expected-error {{must be a pointer to atomic integer or pointer}}
 
+  __atomic_fetch_add(i, 3, memory_order_seq_cst); // expected-error {{pointer to integer or pointer}}
+  __atomic_fetch_sub(I, 3, memory_order_seq_cst);
+  __atomic_fetch_sub(P, 3, memory_order_seq_cst);
+  __atomic_fetch_sub(D, 3, memory_order_seq_cst); // expected-error {{must be a pointer to integer or pointer}}
+  __atomic_fetch_sub(s1, 3, memory_order_seq_cst); // expected-error {{must be a pointer to integer or pointer}}
+
   __c11_atomic_fetch_and(i, 1, memory_order_seq_cst);
   __c11_atomic_fetch_and(p, 1, memory_order_seq_cst); // expected-error {{must be a pointer to atomic integer}}
   __c11_atomic_fetch_and(d, 1, memory_order_seq_cst); // expected-error {{must be a pointer to atomic integer}}
 
-  __c11_atomic_compare_exchange_strong(i, 0, 1, memory_order_seq_cst, memory_order_seq_cst);
-  __c11_atomic_compare_exchange_strong(p, 0, (int*)1, memory_order_seq_cst, memory_order_seq_cst);
-  __c11_atomic_compare_exchange_strong(d, (int*)0, 1, memory_order_seq_cst, memory_order_seq_cst); // expected-warning {{incompatible pointer types}}
+  __atomic_fetch_and(i, 3, memory_order_seq_cst); // expected-error {{pointer to integer}}
+  __atomic_fetch_or(I, 3, memory_order_seq_cst);
+  __atomic_fetch_xor(P, 3, memory_order_seq_cst); // expected-error {{must be a pointer to integer}}
+  __atomic_fetch_or(D, 3, memory_order_seq_cst); // expected-error {{must be a pointer to integer}}
+  __atomic_fetch_and(s1, 3, memory_order_seq_cst); // expected-error {{must be a pointer to integer}}
+
+  _Bool cmpexch_1 = __c11_atomic_compare_exchange_strong(i, 0, 1, memory_order_seq_cst, memory_order_seq_cst);
+  _Bool cmpexch_2 = __c11_atomic_compare_exchange_strong(p, 0, (int*)1, memory_order_seq_cst, memory_order_seq_cst);
+  _Bool cmpexch_3 = __c11_atomic_compare_exchange_strong(d, (int*)0, 1, memory_order_seq_cst, memory_order_seq_cst); // expected-warning {{incompatible pointer types}}
+
+  _Bool cmpexch_4 = __atomic_compare_exchange_n(I, I, 5, 1, memory_order_seq_cst, memory_order_seq_cst);
+  _Bool cmpexch_5 = __atomic_compare_exchange_n(I, P, 5, 0, memory_order_seq_cst, memory_order_seq_cst); // expected-warning {{; dereference with *}}
+  _Bool cmpexch_6 = __atomic_compare_exchange_n(I, I, P, 0, memory_order_seq_cst, memory_order_seq_cst); // expected-warning {{passing 'int **' to parameter of type 'int'}}
+
+  _Bool cmpexch_7 = __atomic_compare_exchange(I, I, 5, 1, memory_order_seq_cst, memory_order_seq_cst); // expected-warning {{passing 'int' to parameter of type 'int *'}}
+  _Bool cmpexch_8 = __atomic_compare_exchange(I, P, I, 0, memory_order_seq_cst, memory_order_seq_cst); // expected-warning {{; dereference with *}}
+  _Bool cmpexch_9 = __atomic_compare_exchange(I, I, I, 0, memory_order_seq_cst, memory_order_seq_cst);
 }