diff mbox

[cxx-mem-model] Use __atomic builtins for OpenMP

Message ID 4EAF3FC0.1080207@redhat.com
State New
Headers show

Commit Message

Richard Henderson Nov. 1, 2011, 12:39 a.m. UTC
I do realize that there's technically a regression for i486,
since we'll no longer look for xadd without the i586 cmpxchg.
I really can't imagine that anyone cares.

Tested on x86_64-linux.


r~
Use __atomic builtins for #pragma omp atomic.

        * omp-low.c (expand_omp_atomic_fetch_op): Don't test individual
        fetch_op optabs, only test can_compare_and_swap_p.  Use __atomic
        builtins instead of __sync builtins.
        * optabs.h (get_atomic_op_for_code): Remove decl.
        (struct atomic_op_functions): Move to...
        * optabs.c: ... here.
        (get_atomic_op_for_code): Make static.
    
testsuite/
        * lib/target-supports.exp (check_effective_target_cas_char): New.
        (check_effective_target_cas_int): New.
        * c-c++-common/gomp/atomic-10.c: Use cas_int; match __atomic builtin.
        * c-c++-common/gomp/atomic-3.c: Likewise.
        * c-c++-common/gomp/atomic-9.c: Likewise.
    
        * gcc.dg/gomp/atomic-1.c, gcc.dg/gomp/atomic-2.c,
        gcc.dg/gomp/atomic-3.c, gcc.dg/gomp/atomic-4.c, gcc.dg/gomp/atomic-7.c,
        gcc.dg/gomp/atomic-8.c, gcc.dg/gomp/atomic-9.c,
        gcc.dg/gomp/atomic-10.c, gcc.dg/gomp/atomic-12.c,
        gcc.dg/gomp/atomic-13.c, gcc.dg/gomp/atomic-14.c,
        gcc.dg/gomp/atomic-15.c: Move to c-c++-common/gomp/.
        * g++.dg/gomp/atomic-1.C, g++.dg/gomp/atomic-2.C,
        g++.dg/gomp/atomic-3.C, g++.dg/gomp/atomic-4.C, g++.dg/gomp/atomic-7.C,
        g++.dg/gomp/atomic-8.C, g++.dg/gomp/atomic-9.C,
        g++.dg/gomp/atomic-10.C, g++.dg/gomp/atomic-11.C,
        g++.dg/gomp/atomic-12.C, g++.dg/gomp/atomic-13.C,
        g++.dg/gomp/atomic-15.C: Remove.
        * gcc.dg/gomp/gomp.exp, g++.dg/gomp/gomp.exp: Run c-c++-common tests.
diff mbox

Patch

diff --git a/gcc/omp-low.c b/gcc/omp-low.c
index 972cb6d..d8e7ce3 100644
--- a/gcc/omp-low.c
+++ b/gcc/omp-low.c
@@ -4998,7 +4998,7 @@  expand_omp_atomic_store (basic_block load_bb, tree addr)
 }
 
 /* A subroutine of expand_omp_atomic.  Attempt to implement the atomic
-   operation as a __sync_fetch_and_op builtin.  INDEX is log2 of the
+   operation as a __atomic_fetch_op builtin.  INDEX is log2 of the
    size of the data type, and thus usable to find the index of the builtin
    decl.  Returns false if the expression is not of the proper form.  */
 
@@ -5009,16 +5009,14 @@  expand_omp_atomic_fetch_op (basic_block load_bb,
 {
   enum built_in_function oldbase, newbase, tmpbase;
   tree decl, itype, call;
-  const struct atomic_op_functions *optab;
   tree lhs, rhs;
   basic_block store_bb = single_succ (load_bb);
   gimple_stmt_iterator gsi;
   gimple stmt;
   location_t loc;
+  enum tree_code code;
   bool need_old, need_new;
-  enum rtx_code r_code;
   enum machine_mode imode;
-  bool have_old, have_new, have_noval;
 
   /* We expect to find the following sequences:
 
@@ -5050,38 +5048,33 @@  expand_omp_atomic_fetch_op (basic_block load_bb,
     return false;
 
   /* Check for one of the supported fetch-op operations.  */
-  switch (gimple_assign_rhs_code (stmt))
+  code = gimple_assign_rhs_code (stmt);
+  switch (code)
     {
     case PLUS_EXPR:
     case POINTER_PLUS_EXPR:
-      oldbase = BUILT_IN_SYNC_FETCH_AND_ADD_N;
-      newbase = BUILT_IN_SYNC_ADD_AND_FETCH_N;
-      r_code = PLUS;
+      oldbase = BUILT_IN_ATOMIC_FETCH_ADD_N;
+      newbase = BUILT_IN_ATOMIC_ADD_FETCH_N;
       break;
     case MINUS_EXPR:
-      oldbase = BUILT_IN_SYNC_FETCH_AND_SUB_N;
-      newbase = BUILT_IN_SYNC_SUB_AND_FETCH_N;
-      r_code = MINUS;
+      oldbase = BUILT_IN_ATOMIC_FETCH_SUB_N;
+      newbase = BUILT_IN_ATOMIC_SUB_FETCH_N;
       break;
     case BIT_AND_EXPR:
-      oldbase = BUILT_IN_SYNC_FETCH_AND_AND_N;
-      newbase = BUILT_IN_SYNC_AND_AND_FETCH_N;
-      r_code = AND;
+      oldbase = BUILT_IN_ATOMIC_FETCH_AND_N;
+      newbase = BUILT_IN_ATOMIC_AND_FETCH_N;
       break;
     case BIT_IOR_EXPR:
-      oldbase = BUILT_IN_SYNC_FETCH_AND_OR_N;
-      newbase = BUILT_IN_SYNC_OR_AND_FETCH_N;
-      r_code = IOR;
+      oldbase = BUILT_IN_ATOMIC_FETCH_OR_N;
+      newbase = BUILT_IN_ATOMIC_OR_FETCH_N;
       break;
     case BIT_XOR_EXPR:
-      oldbase = BUILT_IN_SYNC_FETCH_AND_XOR_N;
-      newbase = BUILT_IN_SYNC_XOR_AND_FETCH_N;
-      r_code = XOR;
+      oldbase = BUILT_IN_ATOMIC_FETCH_XOR_N;
+      newbase = BUILT_IN_ATOMIC_XOR_FETCH_N;
       break;
     default:
       return false;
     }
-  optab = get_atomic_op_for_code (r_code);
 
   /* Make sure the expression is of the proper form.  */
   if (operand_equal_p (gimple_assign_rhs1 (stmt), loaded_val, 0))
@@ -5100,37 +5093,23 @@  expand_omp_atomic_fetch_op (basic_block load_bb,
   itype = TREE_TYPE (TREE_TYPE (decl));
   imode = TYPE_MODE (itype);
 
-  have_new =
-    (direct_optab_handler (optab->mem_fetch_after, imode) == CODE_FOR_nothing
-     || direct_optab_handler (optab->fetch_after, imode) == CODE_FOR_nothing);
-  have_old =
-    (direct_optab_handler (optab->mem_fetch_before, imode) == CODE_FOR_nothing
-     || direct_optab_handler (optab->fetch_before, imode) == CODE_FOR_nothing);
-  have_noval =
-    (direct_optab_handler (optab->mem_no_result, imode) == CODE_FOR_nothing
-     || direct_optab_handler (optab->no_result, imode) == CODE_FOR_nothing);
-
-  if (need_new)
-    {
-      /* expand_sync_fetch_operation can always compensate when interested
-	 in the new value.  */
-      if (!have_new && !have_old)
-	return false;
-    }
-  else if (need_old)
-    {
-      /* When interested in the old value, expand_sync_fetch_operation
-	 can compensate only if the operation is reversible.  */
-      if (!have_old && !(have_new && optab->reverse_code != UNKNOWN))
-	return false;
-    }
-  else if (!have_noval && !have_new && !have_old)
+  /* We could test all of the various optabs involved, but the fact of the
+     matter is that (with the exception of i486 vs i586 and xadd) all targets
+     that support any atomic operaton optab also implements compare-and-swap.
+     Let optabs.c take care of expanding any compare-and-swap loop.  */
+  if (!can_compare_and_swap_p (imode))
     return false;
 
   gsi = gsi_last_bb (load_bb);
   gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_LOAD);
-  call = build_call_expr_loc (loc, decl, 2, addr,
-			      fold_convert_loc (loc, itype, rhs));
+
+  /* OpenMP does not imply any barrier-like semantics on its atomic ops.
+     It only requires that the operation happen atomically.  Thus we can
+     use the RELAXED memory model.  */
+  call = build_call_expr_loc (loc, decl, 3, addr,
+			      fold_convert_loc (loc, itype, rhs),
+			      build_int_cst (NULL, MEMMODEL_RELAXED));
+
   if (need_old || need_new)
     {
       lhs = need_old ? loaded_val : stored_val;
@@ -5179,6 +5158,8 @@  expand_omp_atomic_pipeline (basic_block load_bb, basic_block store_bb,
   edge e;
   enum built_in_function fncode;
 
+  /* ??? We need a non-pointer interface to __atomic_compare_exchange in
+     order to use the RELAXED memory model effectively.  */
   fncode = (enum built_in_function)((int)BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_N
 				    + index + 1);
   cmpxchg = builtin_decl_explicit (fncode);
diff --git a/gcc/optabs.c b/gcc/optabs.c
index f594226..1ecab53 100644
--- a/gcc/optabs.c
+++ b/gcc/optabs.c
@@ -7173,7 +7173,18 @@  expand_atomic_store (rtx mem, rtx val, enum memmodel model)
 /* Structure containing the pointers and values required to process the
    various forms of the atomic_fetch_op and atomic_op_fetch builtins.  */
 
-const struct atomic_op_functions *
+struct atomic_op_functions
+{
+  struct direct_optab_d *mem_fetch_before;
+  struct direct_optab_d *mem_fetch_after;
+  struct direct_optab_d *mem_no_result;
+  struct direct_optab_d *fetch_before;
+  struct direct_optab_d *fetch_after;
+  struct direct_optab_d *no_result;
+  enum rtx_code reverse_code;
+};
+
+static const struct atomic_op_functions *
 get_atomic_op_for_code (enum rtx_code code)
 {
   static const struct atomic_op_functions add_op = {
diff --git a/gcc/optabs.h b/gcc/optabs.h
index 4487f52..2ca0fcd 100644
--- a/gcc/optabs.h
+++ b/gcc/optabs.h
@@ -955,19 +955,6 @@  enum insn_code can_float_p (enum machine_mode, enum machine_mode, int);
 /* Return true if there is an inline compare and swap pattern.  */
 extern bool can_compare_and_swap_p (enum machine_mode);
 
-struct atomic_op_functions
-{
-  struct direct_optab_d *mem_fetch_before;
-  struct direct_optab_d *mem_fetch_after;
-  struct direct_optab_d *mem_no_result;
-  struct direct_optab_d *fetch_before;
-  struct direct_optab_d *fetch_after;
-  struct direct_optab_d *no_result;
-  enum rtx_code reverse_code;
-};
-
-extern const struct atomic_op_functions *get_atomic_op_for_code (enum rtx_code);
-
 /* Generate code for a compare and swap.  */
 extern bool expand_atomic_compare_and_swap (rtx *, rtx *, rtx, rtx, rtx, bool,
 					    enum memmodel, enum memmodel);
diff --git a/gcc/testsuite/c-c++-common/gomp/atomic-1.c b/gcc/testsuite/c-c++-common/gomp/atomic-1.c
new file mode 100644
index 0000000..3e4bc56
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/atomic-1.c
@@ -0,0 +1,99 @@ 
+/* { dg-do compile } */
+
+int x;
+volatile int y;
+volatile unsigned char z;
+
+void f1(void)
+{
+  #pragma omp atomic
+    x++;
+  #pragma omp atomic
+    x--;
+  #pragma omp atomic
+    ++x;
+  #pragma omp atomic
+    --x;
+  #pragma omp atomic
+    x += 1;
+  #pragma omp atomic
+    x -= y;
+  #pragma omp atomic
+    x |= 1;
+  #pragma omp atomic
+    x &= 1;
+  #pragma omp atomic
+    x ^= 1;
+  #pragma omp atomic
+    x *= 3;
+  #pragma omp atomic
+    x /= 3;
+  #pragma omp atomic
+    x /= 3;
+  #pragma omp atomic
+    x <<= 3;
+  #pragma omp atomic
+    x >>= 3;
+}
+
+void f2(void)
+{
+  #pragma omp atomic
+    y++;
+  #pragma omp atomic
+    y--;
+  #pragma omp atomic
+    ++y;
+  #pragma omp atomic
+    --y;
+  #pragma omp atomic
+    y += 1;
+  #pragma omp atomic
+    y -= x;
+  #pragma omp atomic
+    y |= 1;
+  #pragma omp atomic
+    y &= 1;
+  #pragma omp atomic
+    y ^= 1;
+  #pragma omp atomic
+    y *= 3;
+  #pragma omp atomic
+    y /= 3;
+  #pragma omp atomic
+    y /= 3;
+  #pragma omp atomic
+    y <<= 3;
+  #pragma omp atomic
+    y >>= 3;
+}
+
+void f3(void)
+{
+  #pragma omp atomic
+    z++;
+  #pragma omp atomic
+    z--;
+  #pragma omp atomic
+    ++z;
+  #pragma omp atomic
+    --z;
+  #pragma omp atomic
+    z += 1;
+  #pragma omp atomic
+    z |= 1;
+  #pragma omp atomic
+    z &= 1;
+  #pragma omp atomic
+    z ^= 1;
+  #pragma omp atomic
+    z *= 3;
+  #pragma omp atomic
+    z /= 3;
+  #pragma omp atomic
+    z /= 3;
+  #pragma omp atomic
+    z <<= 3;
+  #pragma omp atomic
+    z >>= 3;
+}
diff --git a/gcc/testsuite/c-c++-common/gomp/atomic-10.c b/gcc/testsuite/c-c++-common/gomp/atomic-10.c
new file mode 100644
index 0000000..21d035e
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/atomic-10.c
@@ -0,0 +1,25 @@ 
+/* PR middle-end/28046 */
+/* { dg-do compile } */
+/* { dg-options "-fopenmp -fdump-tree-ompexp" } */
+/* { dg-require-effective-target cas_int } */
+
+int a[3], b;
+struct C { int x; int y; } c;
+
+int bar (void), *baz (void);
+
+void
+foo (void)
+{
+#pragma omp atomic
+  a[2] += bar ();
+#pragma omp atomic
+  b += bar ();
+#pragma omp atomic
+  c.y += bar ();
+#pragma omp atomic
+  *baz () += bar ();
+}
+
+/* { dg-final { scan-tree-dump-times "__atomic_fetch_add" 4 "ompexp" } } */
+/* { dg-final { cleanup-tree-dump "ompexp" } } */
diff --git a/gcc/testsuite/c-c++-common/gomp/atomic-12.c b/gcc/testsuite/c-c++-common/gomp/atomic-12.c
new file mode 100644
index 0000000..618c4c8
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/atomic-12.c
@@ -0,0 +1,306 @@ 
+/* PR middle-end/45423 */
+/* { dg-do compile } */
+/* { dg-options "-fopenmp -fdump-tree-gimple -g0" } */
+/* atomicvar should never be referenced in between the barrier and
+   following #pragma omp atomic_load.  */
+/* { dg-final { scan-tree-dump-not "barrier\[^#\]*atomicvar" "gimple" } } */
+/* { dg-final { cleanup-tree-dump "gimple" } } */
+
+#ifdef __cplusplus
+bool atomicvar, c;
+#else
+_Bool atomicvar, c;
+#endif
+int i, atomicvar2, c2;
+
+int
+foo (void)
+{
+  #pragma omp barrier
+  #pragma omp atomic
+    atomicvar |= -1;
+  #pragma omp barrier
+  #pragma omp atomic
+    atomicvar |= 0;
+  #pragma omp barrier
+  #pragma omp atomic
+    atomicvar |= 1;
+  #pragma omp barrier
+  #pragma omp atomic
+    atomicvar |= 2;
+  #pragma omp barrier
+  #pragma omp atomic
+    atomicvar |= c;
+  #pragma omp barrier
+  #pragma omp atomic
+    atomicvar ^= -1;
+  #pragma omp barrier
+  #pragma omp atomic
+    atomicvar ^= 0;
+  #pragma omp barrier
+  #pragma omp atomic
+    atomicvar ^= 1;
+  #pragma omp barrier
+  #pragma omp atomic
+    atomicvar ^= 2;
+  #pragma omp barrier
+  #pragma omp atomic
+    atomicvar ^= c;
+  #pragma omp barrier
+  #pragma omp atomic
+    atomicvar &= -1;
+  #pragma omp barrier
+  #pragma omp atomic
+    atomicvar &= 0;
+  #pragma omp barrier
+  #pragma omp atomic
+    atomicvar &= 1;
+  #pragma omp barrier
+  #pragma omp atomic
+    atomicvar &= 2;
+  #pragma omp barrier
+  #pragma omp atomic
+    atomicvar &= c;
+  #pragma omp barrier
+  #pragma omp atomic
+    atomicvar += -1;
+  #pragma omp barrier
+  #pragma omp atomic
+    atomicvar += 0;
+  #pragma omp barrier
+  #pragma omp atomic
+    atomicvar += 1;
+  #pragma omp barrier
+  #pragma omp atomic
+    atomicvar += 2;
+  #pragma omp barrier
+  #pragma omp atomic
+    atomicvar += c;
+  #pragma omp barrier
+  #pragma omp atomic
+    atomicvar -= -1;
+  #pragma omp barrier
+  #pragma omp atomic
+    atomicvar -= 0;
+  #pragma omp barrier
+  #pragma omp atomic
+    atomicvar -= 1;
+  #pragma omp barrier
+  #pragma omp atomic
+    atomicvar -= 2;
+  #pragma omp barrier
+  #pragma omp atomic
+    atomicvar -= c;
+  #pragma omp barrier
+  #pragma omp atomic
+    atomicvar *= -1;
+  #pragma omp barrier
+  #pragma omp atomic
+    atomicvar *= 0;
+  #pragma omp barrier
+  #pragma omp atomic
+    atomicvar *= 1;
+  #pragma omp barrier
+  #pragma omp atomic
+    atomicvar *= 2;
+  #pragma omp barrier
+  #pragma omp atomic
+    atomicvar *= c;
+  #pragma omp barrier
+  #pragma omp atomic
+    atomicvar /= -1;
+  #pragma omp barrier
+  #pragma omp atomic
+    atomicvar /= 1;
+  #pragma omp barrier
+  #pragma omp atomic
+    atomicvar /= 2;
+  #pragma omp barrier
+  #pragma omp atomic
+    atomicvar /= c;
+  #pragma omp barrier
+  #pragma omp atomic
+    atomicvar <<= 0;
+  #pragma omp barrier
+  #pragma omp atomic
+    atomicvar <<= 1;
+  #pragma omp barrier
+  #pragma omp atomic
+    atomicvar <<= 2;
+  #pragma omp barrier
+  #pragma omp atomic
+    atomicvar <<= i;
+  #pragma omp barrier
+  #pragma omp atomic
+    atomicvar >>= 0;
+  #pragma omp barrier
+  #pragma omp atomic
+    atomicvar >>= 1;
+  #pragma omp barrier
+  #pragma omp atomic
+    atomicvar >>= 2;
+  #pragma omp barrier
+  #pragma omp atomic
+    atomicvar >>= i;
+  #pragma omp barrier
+  #pragma omp atomic
+    atomicvar++;
+  #pragma omp barrier
+  #pragma omp atomic
+    ++atomicvar;
+  #pragma omp barrier
+#ifndef __cplusplus
+  #pragma omp atomic
+    atomicvar--;
+  #pragma omp barrier
+  #pragma omp atomic
+    --atomicvar;
+  #pragma omp barrier
+#endif
+  return 0;
+}
+
+int
+bar (void)
+{
+  #pragma omp barrier
+  #pragma omp atomic
+    atomicvar2 |= -1;
+  #pragma omp barrier
+  #pragma omp atomic
+    atomicvar2 |= 0;
+  #pragma omp barrier
+  #pragma omp atomic
+    atomicvar2 |= 1;
+  #pragma omp barrier
+  #pragma omp atomic
+    atomicvar2 |= 2;
+  #pragma omp barrier
+  #pragma omp atomic
+    atomicvar2 |= c2;
+  #pragma omp barrier
+  #pragma omp atomic
+    atomicvar2 ^= -1;
+  #pragma omp barrier
+  #pragma omp atomic
+    atomicvar2 ^= 0;
+  #pragma omp barrier
+  #pragma omp atomic
+    atomicvar2 ^= 1;
+  #pragma omp barrier
+  #pragma omp atomic
+    atomicvar2 ^= 2;
+  #pragma omp barrier
+  #pragma omp atomic
+    atomicvar2 ^= c2;
+  #pragma omp barrier
+  #pragma omp atomic
+    atomicvar2 &= -1;
+  #pragma omp barrier
+  #pragma omp atomic
+    atomicvar2 &= 0;
+  #pragma omp barrier
+  #pragma omp atomic
+    atomicvar2 &= 1;
+  #pragma omp barrier
+  #pragma omp atomic
+    atomicvar2 &= 2;
+  #pragma omp barrier
+  #pragma omp atomic
+    atomicvar2 &= c2;
+  #pragma omp barrier
+  #pragma omp atomic
+    atomicvar2 += -1;
+  #pragma omp barrier
+  #pragma omp atomic
+    atomicvar2 += 0;
+  #pragma omp barrier
+  #pragma omp atomic
+    atomicvar2 += 1;
+  #pragma omp barrier
+  #pragma omp atomic
+    atomicvar2 += 2;
+  #pragma omp barrier
+  #pragma omp atomic
+    atomicvar2 += c2;
+  #pragma omp barrier
+  #pragma omp atomic
+    atomicvar2 -= -1;
+  #pragma omp barrier
+  #pragma omp atomic
+    atomicvar2 -= 0;
+  #pragma omp barrier
+  #pragma omp atomic
+    atomicvar2 -= 1;
+  #pragma omp barrier
+  #pragma omp atomic
+    atomicvar2 -= 2;
+  #pragma omp barrier
+  #pragma omp atomic
+    atomicvar2 -= c2;
+  #pragma omp barrier
+  #pragma omp atomic
+    atomicvar2 *= -1;
+  #pragma omp barrier
+  #pragma omp atomic
+    atomicvar2 *= 0;
+  #pragma omp barrier
+  #pragma omp atomic
+    atomicvar2 *= 1;
+  #pragma omp barrier
+  #pragma omp atomic
+    atomicvar2 *= 2;
+  #pragma omp barrier
+  #pragma omp atomic
+    atomicvar2 *= c2;
+  #pragma omp barrier
+  #pragma omp atomic
+    atomicvar2 /= -1;
+  #pragma omp barrier
+  #pragma omp atomic
+    atomicvar2 /= 1;
+  #pragma omp barrier
+  #pragma omp atomic
+    atomicvar2 /= 2;
+  #pragma omp barrier
+  #pragma omp atomic
+    atomicvar2 /= c2;
+  #pragma omp barrier
+  #pragma omp atomic
+    atomicvar2 <<= 0;
+  #pragma omp barrier
+  #pragma omp atomic
+    atomicvar2 <<= 1;
+  #pragma omp barrier
+  #pragma omp atomic
+    atomicvar2 <<= 2;
+  #pragma omp barrier
+  #pragma omp atomic
+    atomicvar2 <<= i;
+  #pragma omp barrier
+  #pragma omp atomic
+    atomicvar2 >>= 0;
+  #pragma omp barrier
+  #pragma omp atomic
+    atomicvar2 >>= 1;
+  #pragma omp barrier
+  #pragma omp atomic
+    atomicvar2 >>= 2;
+  #pragma omp barrier
+  #pragma omp atomic
+    atomicvar2 >>= i;
+  #pragma omp barrier
+  #pragma omp atomic
+    atomicvar2++;
+  #pragma omp barrier
+  #pragma omp atomic
+    ++atomicvar2;
+  #pragma omp barrier
+  #pragma omp atomic
+    atomicvar2--;
+  #pragma omp barrier
+  #pragma omp atomic
+    --atomicvar2;
+  #pragma omp barrier
+  return 0;
+}
diff --git a/gcc/testsuite/c-c++-common/gomp/atomic-13.c b/gcc/testsuite/c-c++-common/gomp/atomic-13.c
new file mode 100644
index 0000000..0146825
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/atomic-13.c
@@ -0,0 +1,9 @@ 
+/* PR middle-end/45423 */
+/* { dg-do compile } */
+/* { dg-options "-fopenmp -fdump-tree-gimple -g0 -O2" } */
+/* atomicvar should never be referenced in between the barrier and
+   following #pragma omp atomic_load.  */
+/* { dg-final { scan-tree-dump-not "barrier\[^#\]*atomicvar" "gimple" } } */
+/* { dg-final { cleanup-tree-dump "gimple" } } */
+
+#include "atomic-12.c"
diff --git a/gcc/testsuite/c-c++-common/gomp/atomic-14.c b/gcc/testsuite/c-c++-common/gomp/atomic-14.c
new file mode 100644
index 0000000..f8fc9d8
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/atomic-14.c
@@ -0,0 +1,43 @@ 
+/* PR middle-end/45423 */
+/* { dg-do compile } */
+/* { dg-options "-fopenmp" } */
+
+#ifdef __cplusplus
+bool *baz ();
+#else
+_Bool *baz ();
+#endif
+int *bar ();
+
+int
+foo (void)
+{
+  #pragma omp barrier
+  #pragma omp atomic
+    (*bar ())++;
+  #pragma omp barrier
+  #pragma omp atomic
+    ++(*bar ());
+  #pragma omp barrier
+  #pragma omp atomic
+    (*bar ())--;
+  #pragma omp barrier
+  #pragma omp atomic
+    --(*bar ());
+  #pragma omp barrier
+  #pragma omp atomic
+    (*baz ())++;
+  #pragma omp barrier
+  #pragma omp atomic
+    ++(*baz ());
+#ifndef __cplusplus
+  #pragma omp barrier
+  #pragma omp atomic
+    (*baz ())--;
+  #pragma omp barrier
+  #pragma omp atomic
+    --(*baz ());
+  #pragma omp barrier
+#endif
+  return 0;
+}
diff --git a/gcc/testsuite/c-c++-common/gomp/atomic-15.c b/gcc/testsuite/c-c++-common/gomp/atomic-15.c
new file mode 100644
index 0000000..13a9e0c
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/atomic-15.c
@@ -0,0 +1,46 @@ 
+/* { dg-do compile } */
+/* { dg-options "-fopenmp" } */
+
+int x = 6;
+
+int
+main ()
+{
+  int v;
+  #pragma omp atomic
+    x = x * 7 + 6;	/* { dg-error "expected" } */
+  #pragma omp atomic
+    x = x * 7 ^ 6;	/* { dg-error "expected" } */
+  #pragma omp atomic update
+    x = x - 8 + 6;	/* { dg-error "expected" } */
+  #pragma omp atomic
+    x = x ^ 7 | 2;	/* { dg-error "expected" } */
+  #pragma omp atomic
+    x = x / 7 * 2;	/* { dg-error "expected" } */
+  #pragma omp atomic
+    x = x / 7 / 2;	/* { dg-error "expected" } */
+  #pragma omp atomic capture
+    v = x = x | 6;	/* { dg-error "invalid operator" } */
+  #pragma omp atomic capture
+    { v = x; x = x * 7 + 6; }	/* { dg-error "expected" } */
+  #pragma omp atomic capture
+    { v = x; x = x * 7 ^ 6; }	/* { dg-error "expected" } */
+  #pragma omp atomic capture
+    { v = x; x = x - 8 + 6; }	/* { dg-error "expected" } */
+  #pragma omp atomic capture
+    { v = x; x = x ^ 7 | 2; }	/* { dg-error "expected" } */
+  #pragma omp atomic capture
+    { v = x; x = x / 7 * 2; }	/* { dg-error "expected" } */
+  #pragma omp atomic capture
+    { v = x; x = x / 7 / 2; }	/* { dg-error "expected" } */
+  #pragma omp atomic capture
+    { x = x * 7 + 6; v = x; }	/* { dg-error "expected" } */
+  #pragma omp atomic capture
+    { x = x * 7 ^ 6; v = x; }	/* { dg-error "expected" } */
+  #pragma omp atomic capture
+    { x = x - 8 + 6; v = x; }	/* { dg-error "expected" } */
+  #pragma omp atomic capture
+    { x = x ^ 7 | 2; v = x; }	/* { dg-error "expected" } */
+  (void) v;
+  return 0;
+}
diff --git a/gcc/testsuite/c-c++-common/gomp/atomic-2.c b/gcc/testsuite/c-c++-common/gomp/atomic-2.c
new file mode 100644
index 0000000..720ec9e
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/atomic-2.c
@@ -0,0 +1,23 @@ 
+/* { dg-do compile } */
+
+float x, y;
+
+void f1(void)
+{
+  #pragma omp atomic
+    x++;
+  #pragma omp atomic
+    x--;
+  #pragma omp atomic
+    ++x;
+  #pragma omp atomic
+    --x;
+  #pragma omp atomic
+    x += 1;
+  #pragma omp atomic
+    x -= y;
+  #pragma omp atomic
+    x *= 3;
+  #pragma omp atomic
+    x /= 3;
+}
diff --git a/gcc/testsuite/c-c++-common/gomp/atomic-3.c b/gcc/testsuite/c-c++-common/gomp/atomic-3.c
new file mode 100644
index 0000000..5b9e60c
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/atomic-3.c
@@ -0,0 +1,14 @@ 
+/* { dg-do compile } */
+/* { dg-options "-fopenmp -fdump-tree-ompexp" } */
+/* { dg-require-effective-target cas_int } */
+
+int *xyzzy;
+
+void f1(void)
+{
+  #pragma omp atomic
+    xyzzy++;
+}
+
+/* { dg-final { scan-tree-dump-times "xyzzy, 4" 1 "ompexp" } } */
+/* { dg-final { cleanup-tree-dump "ompexp" } } */
diff --git a/gcc/testsuite/c-c++-common/gomp/atomic-4.c b/gcc/testsuite/c-c++-common/gomp/atomic-4.c
new file mode 100644
index 0000000..7f27370
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/atomic-4.c
@@ -0,0 +1,24 @@ 
+/* { dg-do compile } */
+
+int a[4];
+int *p;
+struct S { int x; int y[4]; } s;
+int *bar(void);
+
+void f1(void)
+{
+  #pragma omp atomic
+    a[4] += 1;
+  #pragma omp atomic
+    *p += 1;
+  #pragma omp atomic
+    s.x += 1;
+  #pragma omp atomic
+    s.y[*p] += 1;
+  #pragma omp atomic
+    s.y[*p] *= 42;
+  #pragma omp atomic
+    *bar() += 1;
+  #pragma omp atomic
+    *bar() *= 42;
+}
diff --git a/gcc/testsuite/c-c++-common/gomp/atomic-7.c b/gcc/testsuite/c-c++-common/gomp/atomic-7.c
new file mode 100644
index 0000000..612e97f
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/atomic-7.c
@@ -0,0 +1,23 @@ 
+/* { dg-do compile } */
+
+double x, y;
+
+void f2(void)
+{
+  #pragma omp atomic
+    y++;
+  #pragma omp atomic
+    y--;
+  #pragma omp atomic
+    ++y;
+  #pragma omp atomic
+    --y;
+  #pragma omp atomic
+    y += 1;
+  #pragma omp atomic
+    y -= x;
+  #pragma omp atomic
+    y *= 3;
+  #pragma omp atomic
+    y /= 3;
+}
diff --git a/gcc/testsuite/c-c++-common/gomp/atomic-8.c b/gcc/testsuite/c-c++-common/gomp/atomic-8.c
new file mode 100644
index 0000000..2f04151
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/atomic-8.c
@@ -0,0 +1,21 @@ 
+/* { dg-do compile } */
+
+long double z;
+
+void f3(void)
+{
+  #pragma omp atomic
+    z++;
+  #pragma omp atomic
+    z--;
+  #pragma omp atomic
+    ++z;
+  #pragma omp atomic
+    --z;
+  #pragma omp atomic
+    z += 1;
+  #pragma omp atomic
+    z *= 3;
+  #pragma omp atomic
+    z /= 3;
+}
diff --git a/gcc/testsuite/c-c++-common/gomp/atomic-9.c b/gcc/testsuite/c-c++-common/gomp/atomic-9.c
new file mode 100644
index 0000000..ff5cb40
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/atomic-9.c
@@ -0,0 +1,14 @@ 
+/* { dg-do compile } */
+/* { dg-options "-fopenmp -fdump-tree-ompexp" } */
+/* { dg-require-effective-target cas_int } */
+
+volatile int *bar(void);
+
+void f1(void)
+{
+  #pragma omp atomic
+    *bar() += 1;
+}
+
+/* { dg-final { scan-tree-dump-times "__atomic_fetch_add" 1 "ompexp" } } */
+/* { dg-final { cleanup-tree-dump "ompexp" } } */
diff --git a/gcc/testsuite/g++.dg/gomp/atomic-1.C b/gcc/testsuite/g++.dg/gomp/atomic-1.C
deleted file mode 100644
index 3e4bc56..0000000
--- a/gcc/testsuite/g++.dg/gomp/atomic-1.C
+++ /dev/null
@@ -1,99 +0,0 @@ 
-/* { dg-do compile } */
-
-int x;
-volatile int y;
-volatile unsigned char z;
-
-void f1(void)
-{
-  #pragma omp atomic
-    x++;
-  #pragma omp atomic
-    x--;
-  #pragma omp atomic
-    ++x;
-  #pragma omp atomic
-    --x;
-  #pragma omp atomic
-    x += 1;
-  #pragma omp atomic
-    x -= y;
-  #pragma omp atomic
-    x |= 1;
-  #pragma omp atomic
-    x &= 1;
-  #pragma omp atomic
-    x ^= 1;
-  #pragma omp atomic
-    x *= 3;
-  #pragma omp atomic
-    x /= 3;
-  #pragma omp atomic
-    x /= 3;
-  #pragma omp atomic
-    x <<= 3;
-  #pragma omp atomic
-    x >>= 3;
-}
-
-void f2(void)
-{
-  #pragma omp atomic
-    y++;
-  #pragma omp atomic
-    y--;
-  #pragma omp atomic
-    ++y;
-  #pragma omp atomic
-    --y;
-  #pragma omp atomic
-    y += 1;
-  #pragma omp atomic
-    y -= x;
-  #pragma omp atomic
-    y |= 1;
-  #pragma omp atomic
-    y &= 1;
-  #pragma omp atomic
-    y ^= 1;
-  #pragma omp atomic
-    y *= 3;
-  #pragma omp atomic
-    y /= 3;
-  #pragma omp atomic
-    y /= 3;
-  #pragma omp atomic
-    y <<= 3;
-  #pragma omp atomic
-    y >>= 3;
-}
-
-void f3(void)
-{
-  #pragma omp atomic
-    z++;
-  #pragma omp atomic
-    z--;
-  #pragma omp atomic
-    ++z;
-  #pragma omp atomic
-    --z;
-  #pragma omp atomic
-    z += 1;
-  #pragma omp atomic
-    z |= 1;
-  #pragma omp atomic
-    z &= 1;
-  #pragma omp atomic
-    z ^= 1;
-  #pragma omp atomic
-    z *= 3;
-  #pragma omp atomic
-    z /= 3;
-  #pragma omp atomic
-    z /= 3;
-  #pragma omp atomic
-    z <<= 3;
-  #pragma omp atomic
-    z >>= 3;
-}
diff --git a/gcc/testsuite/g++.dg/gomp/atomic-10.C b/gcc/testsuite/g++.dg/gomp/atomic-10.C
deleted file mode 100644
index fe64f0f..0000000
--- a/gcc/testsuite/g++.dg/gomp/atomic-10.C
+++ /dev/null
@@ -1,24 +0,0 @@ 
-// PR middle-end/28046
-// { dg-do compile }
-// { dg-options "-fopenmp -fdump-tree-ompexp" }
-
-int a[3], b;
-struct C { int x; int y; } c;
-
-int bar (void), *baz (void);
-
-void
-foo (void)
-{
-#pragma omp atomic
-  a[2] += bar ();
-#pragma omp atomic
-  b += bar ();
-#pragma omp atomic
-  c.y += bar ();
-#pragma omp atomic
-  *baz () += bar ();
-}
-
-// { dg-final { scan-tree-dump-times "__sync_fetch_and_add" 4 "ompexp" { target i?86-*-* x86_64-*-* ia64-*-* powerpc*-*-* alpha*-*-* } } }
-// { dg-final { cleanup-tree-dump "ompexp" } }
diff --git a/gcc/testsuite/g++.dg/gomp/atomic-11.C b/gcc/testsuite/g++.dg/gomp/atomic-11.C
deleted file mode 100644
index 618c4c8..0000000
--- a/gcc/testsuite/g++.dg/gomp/atomic-11.C
+++ /dev/null
@@ -1,306 +0,0 @@ 
-/* PR middle-end/45423 */
-/* { dg-do compile } */
-/* { dg-options "-fopenmp -fdump-tree-gimple -g0" } */
-/* atomicvar should never be referenced in between the barrier and
-   following #pragma omp atomic_load.  */
-/* { dg-final { scan-tree-dump-not "barrier\[^#\]*atomicvar" "gimple" } } */
-/* { dg-final { cleanup-tree-dump "gimple" } } */
-
-#ifdef __cplusplus
-bool atomicvar, c;
-#else
-_Bool atomicvar, c;
-#endif
-int i, atomicvar2, c2;
-
-int
-foo (void)
-{
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar |= -1;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar |= 0;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar |= 1;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar |= 2;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar |= c;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar ^= -1;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar ^= 0;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar ^= 1;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar ^= 2;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar ^= c;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar &= -1;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar &= 0;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar &= 1;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar &= 2;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar &= c;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar += -1;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar += 0;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar += 1;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar += 2;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar += c;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar -= -1;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar -= 0;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar -= 1;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar -= 2;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar -= c;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar *= -1;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar *= 0;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar *= 1;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar *= 2;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar *= c;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar /= -1;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar /= 1;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar /= 2;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar /= c;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar <<= 0;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar <<= 1;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar <<= 2;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar <<= i;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar >>= 0;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar >>= 1;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar >>= 2;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar >>= i;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar++;
-  #pragma omp barrier
-  #pragma omp atomic
-    ++atomicvar;
-  #pragma omp barrier
-#ifndef __cplusplus
-  #pragma omp atomic
-    atomicvar--;
-  #pragma omp barrier
-  #pragma omp atomic
-    --atomicvar;
-  #pragma omp barrier
-#endif
-  return 0;
-}
-
-int
-bar (void)
-{
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar2 |= -1;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar2 |= 0;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar2 |= 1;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar2 |= 2;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar2 |= c2;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar2 ^= -1;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar2 ^= 0;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar2 ^= 1;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar2 ^= 2;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar2 ^= c2;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar2 &= -1;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar2 &= 0;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar2 &= 1;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar2 &= 2;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar2 &= c2;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar2 += -1;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar2 += 0;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar2 += 1;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar2 += 2;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar2 += c2;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar2 -= -1;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar2 -= 0;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar2 -= 1;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar2 -= 2;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar2 -= c2;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar2 *= -1;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar2 *= 0;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar2 *= 1;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar2 *= 2;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar2 *= c2;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar2 /= -1;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar2 /= 1;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar2 /= 2;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar2 /= c2;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar2 <<= 0;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar2 <<= 1;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar2 <<= 2;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar2 <<= i;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar2 >>= 0;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar2 >>= 1;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar2 >>= 2;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar2 >>= i;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar2++;
-  #pragma omp barrier
-  #pragma omp atomic
-    ++atomicvar2;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar2--;
-  #pragma omp barrier
-  #pragma omp atomic
-    --atomicvar2;
-  #pragma omp barrier
-  return 0;
-}
diff --git a/gcc/testsuite/g++.dg/gomp/atomic-12.C b/gcc/testsuite/g++.dg/gomp/atomic-12.C
deleted file mode 100644
index 6c1f965..0000000
--- a/gcc/testsuite/g++.dg/gomp/atomic-12.C
+++ /dev/null
@@ -1,9 +0,0 @@ 
-/* PR middle-end/45423 */
-/* { dg-do compile } */
-/* { dg-options "-fopenmp -fdump-tree-gimple -g0 -O2" } */
-/* atomicvar should never be referenced in between the barrier and
-   following #pragma omp atomic_load.  */
-/* { dg-final { scan-tree-dump-not "barrier\[^#\]*atomicvar" "gimple" } } */
-/* { dg-final { cleanup-tree-dump "gimple" } } */
-
-#include "atomic-11.C"
diff --git a/gcc/testsuite/g++.dg/gomp/atomic-13.C b/gcc/testsuite/g++.dg/gomp/atomic-13.C
deleted file mode 100644
index f8fc9d8..0000000
--- a/gcc/testsuite/g++.dg/gomp/atomic-13.C
+++ /dev/null
@@ -1,43 +0,0 @@ 
-/* PR middle-end/45423 */
-/* { dg-do compile } */
-/* { dg-options "-fopenmp" } */
-
-#ifdef __cplusplus
-bool *baz ();
-#else
-_Bool *baz ();
-#endif
-int *bar ();
-
-int
-foo (void)
-{
-  #pragma omp barrier
-  #pragma omp atomic
-    (*bar ())++;
-  #pragma omp barrier
-  #pragma omp atomic
-    ++(*bar ());
-  #pragma omp barrier
-  #pragma omp atomic
-    (*bar ())--;
-  #pragma omp barrier
-  #pragma omp atomic
-    --(*bar ());
-  #pragma omp barrier
-  #pragma omp atomic
-    (*baz ())++;
-  #pragma omp barrier
-  #pragma omp atomic
-    ++(*baz ());
-#ifndef __cplusplus
-  #pragma omp barrier
-  #pragma omp atomic
-    (*baz ())--;
-  #pragma omp barrier
-  #pragma omp atomic
-    --(*baz ());
-  #pragma omp barrier
-#endif
-  return 0;
-}
diff --git a/gcc/testsuite/g++.dg/gomp/atomic-15.C b/gcc/testsuite/g++.dg/gomp/atomic-15.C
deleted file mode 100644
index 95eb8b4..0000000
--- a/gcc/testsuite/g++.dg/gomp/atomic-15.C
+++ /dev/null
@@ -1,46 +0,0 @@ 
-// { dg-do compile }
-// { dg-options "-fopenmp" }
-
-int x = 6;
-
-int
-main ()
-{
-  int v;
-  #pragma omp atomic
-    x = x * 7 + 6;	// { dg-error "expected" }
-  #pragma omp atomic
-    x = x * 7 ^ 6;	// { dg-error "expected" }
-  #pragma omp atomic update
-    x = x - 8 + 6;	// { dg-error "expected" }
-  #pragma omp atomic
-    x = x ^ 7 | 2;	// { dg-error "expected" }
-  #pragma omp atomic
-    x = x / 7 * 2;	// { dg-error "expected" }
-  #pragma omp atomic
-    x = x / 7 / 2;	// { dg-error "expected" }
-  #pragma omp atomic capture
-    v = x = x | 6;	// { dg-error "invalid operator" }
-  #pragma omp atomic capture
-    { v = x; x = x * 7 + 6; }	// { dg-error "expected" }
-  #pragma omp atomic capture
-    { v = x; x = x * 7 ^ 6; }	// { dg-error "expected" }
-  #pragma omp atomic capture
-    { v = x; x = x - 8 + 6; }	// { dg-error "expected" }
-  #pragma omp atomic capture
-    { v = x; x = x ^ 7 | 2; }	// { dg-error "expected" }
-  #pragma omp atomic capture
-    { v = x; x = x / 7 * 2; }	// { dg-error "expected" }
-  #pragma omp atomic capture
-    { v = x; x = x / 7 / 2; }	// { dg-error "expected" }
-  #pragma omp atomic capture
-    { x = x * 7 + 6; v = x; }	// { dg-error "expected" }
-  #pragma omp atomic capture
-    { x = x * 7 ^ 6; v = x; }	// { dg-error "expected" }
-  #pragma omp atomic capture
-    { x = x - 8 + 6; v = x; }	// { dg-error "expected" }
-  #pragma omp atomic capture
-    { x = x ^ 7 | 2; v = x; }	// { dg-error "expected" }
-  (void) v;
-  return 0;
-}
diff --git a/gcc/testsuite/g++.dg/gomp/atomic-2.C b/gcc/testsuite/g++.dg/gomp/atomic-2.C
deleted file mode 100644
index 720ec9e..0000000
--- a/gcc/testsuite/g++.dg/gomp/atomic-2.C
+++ /dev/null
@@ -1,23 +0,0 @@ 
-/* { dg-do compile } */
-
-float x, y;
-
-void f1(void)
-{
-  #pragma omp atomic
-    x++;
-  #pragma omp atomic
-    x--;
-  #pragma omp atomic
-    ++x;
-  #pragma omp atomic
-    --x;
-  #pragma omp atomic
-    x += 1;
-  #pragma omp atomic
-    x -= y;
-  #pragma omp atomic
-    x *= 3;
-  #pragma omp atomic
-    x /= 3;
-}
diff --git a/gcc/testsuite/g++.dg/gomp/atomic-3.C b/gcc/testsuite/g++.dg/gomp/atomic-3.C
deleted file mode 100644
index 7ea792d..0000000
--- a/gcc/testsuite/g++.dg/gomp/atomic-3.C
+++ /dev/null
@@ -1,13 +0,0 @@ 
-/* { dg-do compile } */
-/* { dg-options "-fopenmp -fdump-tree-ompexp" } */
-
-int *xyzzy;
-
-void f1(void)
-{
-  #pragma omp atomic
-    xyzzy++;
-}
-
-/* { dg-final { scan-tree-dump-times "xyzzy, 4" 1 "ompexp" { target i?86-*-* x86_64-*-* ia64-*-* powerpc*-*-* alpha*-*-* } } } */
-/* { dg-final { cleanup-tree-dump "ompexp" } } */
diff --git a/gcc/testsuite/g++.dg/gomp/atomic-4.C b/gcc/testsuite/g++.dg/gomp/atomic-4.C
deleted file mode 100644
index 7f27370..0000000
--- a/gcc/testsuite/g++.dg/gomp/atomic-4.C
+++ /dev/null
@@ -1,24 +0,0 @@ 
-/* { dg-do compile } */
-
-int a[4];
-int *p;
-struct S { int x; int y[4]; } s;
-int *bar(void);
-
-void f1(void)
-{
-  #pragma omp atomic
-    a[4] += 1;
-  #pragma omp atomic
-    *p += 1;
-  #pragma omp atomic
-    s.x += 1;
-  #pragma omp atomic
-    s.y[*p] += 1;
-  #pragma omp atomic
-    s.y[*p] *= 42;
-  #pragma omp atomic
-    *bar() += 1;
-  #pragma omp atomic
-    *bar() *= 42;
-}
diff --git a/gcc/testsuite/g++.dg/gomp/atomic-7.C b/gcc/testsuite/g++.dg/gomp/atomic-7.C
deleted file mode 100644
index 612e97f..0000000
--- a/gcc/testsuite/g++.dg/gomp/atomic-7.C
+++ /dev/null
@@ -1,23 +0,0 @@ 
-/* { dg-do compile } */
-
-double x, y;
-
-void f2(void)
-{
-  #pragma omp atomic
-    y++;
-  #pragma omp atomic
-    y--;
-  #pragma omp atomic
-    ++y;
-  #pragma omp atomic
-    --y;
-  #pragma omp atomic
-    y += 1;
-  #pragma omp atomic
-    y -= x;
-  #pragma omp atomic
-    y *= 3;
-  #pragma omp atomic
-    y /= 3;
-}
diff --git a/gcc/testsuite/g++.dg/gomp/atomic-8.C b/gcc/testsuite/g++.dg/gomp/atomic-8.C
deleted file mode 100644
index 2f04151..0000000
--- a/gcc/testsuite/g++.dg/gomp/atomic-8.C
+++ /dev/null
@@ -1,21 +0,0 @@ 
-/* { dg-do compile } */
-
-long double z;
-
-void f3(void)
-{
-  #pragma omp atomic
-    z++;
-  #pragma omp atomic
-    z--;
-  #pragma omp atomic
-    ++z;
-  #pragma omp atomic
-    --z;
-  #pragma omp atomic
-    z += 1;
-  #pragma omp atomic
-    z *= 3;
-  #pragma omp atomic
-    z /= 3;
-}
diff --git a/gcc/testsuite/g++.dg/gomp/atomic-9.C b/gcc/testsuite/g++.dg/gomp/atomic-9.C
deleted file mode 100644
index 2fafbd4..0000000
--- a/gcc/testsuite/g++.dg/gomp/atomic-9.C
+++ /dev/null
@@ -1,13 +0,0 @@ 
-/* { dg-do compile } */
-/* { dg-options "-fopenmp -fdump-tree-ompexp" } */
-
-volatile int *bar(void);
-
-void f1(void)
-{
-  #pragma omp atomic
-    *bar() += 1;
-}
-
-/* { dg-final { scan-tree-dump-times "__sync_fetch_and_add" 1 "ompexp" { target i?86-*-* x86_64-*-* ia64-*-* powerpc*-*-* alpha*-*-* } } } */
-/* { dg-final { cleanup-tree-dump "ompexp" } } */
diff --git a/gcc/testsuite/g++.dg/gomp/gomp.exp b/gcc/testsuite/g++.dg/gomp/gomp.exp
index 9f60bc1..b99d302 100644
--- a/gcc/testsuite/g++.dg/gomp/gomp.exp
+++ b/gcc/testsuite/g++.dg/gomp/gomp.exp
@@ -27,7 +27,7 @@  if ![check_effective_target_fopenmp] {
 dg-init
 
 # Main loop.
-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.C]] "" "-fopenmp"
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.C $srcdir/c-c++-common/gomp/*.c]] "" "-fopenmp"
 
 # All done.
 dg-finish
diff --git a/gcc/testsuite/gcc.dg/gomp/atomic-1.c b/gcc/testsuite/gcc.dg/gomp/atomic-1.c
deleted file mode 100644
index 3e4bc56..0000000
--- a/gcc/testsuite/gcc.dg/gomp/atomic-1.c
+++ /dev/null
@@ -1,99 +0,0 @@ 
-/* { dg-do compile } */
-
-int x;
-volatile int y;
-volatile unsigned char z;
-
-void f1(void)
-{
-  #pragma omp atomic
-    x++;
-  #pragma omp atomic
-    x--;
-  #pragma omp atomic
-    ++x;
-  #pragma omp atomic
-    --x;
-  #pragma omp atomic
-    x += 1;
-  #pragma omp atomic
-    x -= y;
-  #pragma omp atomic
-    x |= 1;
-  #pragma omp atomic
-    x &= 1;
-  #pragma omp atomic
-    x ^= 1;
-  #pragma omp atomic
-    x *= 3;
-  #pragma omp atomic
-    x /= 3;
-  #pragma omp atomic
-    x /= 3;
-  #pragma omp atomic
-    x <<= 3;
-  #pragma omp atomic
-    x >>= 3;
-}
-
-void f2(void)
-{
-  #pragma omp atomic
-    y++;
-  #pragma omp atomic
-    y--;
-  #pragma omp atomic
-    ++y;
-  #pragma omp atomic
-    --y;
-  #pragma omp atomic
-    y += 1;
-  #pragma omp atomic
-    y -= x;
-  #pragma omp atomic
-    y |= 1;
-  #pragma omp atomic
-    y &= 1;
-  #pragma omp atomic
-    y ^= 1;
-  #pragma omp atomic
-    y *= 3;
-  #pragma omp atomic
-    y /= 3;
-  #pragma omp atomic
-    y /= 3;
-  #pragma omp atomic
-    y <<= 3;
-  #pragma omp atomic
-    y >>= 3;
-}
-
-void f3(void)
-{
-  #pragma omp atomic
-    z++;
-  #pragma omp atomic
-    z--;
-  #pragma omp atomic
-    ++z;
-  #pragma omp atomic
-    --z;
-  #pragma omp atomic
-    z += 1;
-  #pragma omp atomic
-    z |= 1;
-  #pragma omp atomic
-    z &= 1;
-  #pragma omp atomic
-    z ^= 1;
-  #pragma omp atomic
-    z *= 3;
-  #pragma omp atomic
-    z /= 3;
-  #pragma omp atomic
-    z /= 3;
-  #pragma omp atomic
-    z <<= 3;
-  #pragma omp atomic
-    z >>= 3;
-}
diff --git a/gcc/testsuite/gcc.dg/gomp/atomic-10.c b/gcc/testsuite/gcc.dg/gomp/atomic-10.c
deleted file mode 100644
index 936d0c1..0000000
--- a/gcc/testsuite/gcc.dg/gomp/atomic-10.c
+++ /dev/null
@@ -1,24 +0,0 @@ 
-/* PR middle-end/28046 */
-/* { dg-do compile } */
-/* { dg-options "-fopenmp -fdump-tree-ompexp" } */
-
-int a[3], b;
-struct C { int x; int y; } c;
-
-int bar (void), *baz (void);
-
-void
-foo (void)
-{
-#pragma omp atomic
-  a[2] += bar ();
-#pragma omp atomic
-  b += bar ();
-#pragma omp atomic
-  c.y += bar ();
-#pragma omp atomic
-  *baz () += bar ();
-}
-
-/* { dg-final { scan-tree-dump-times "__sync_fetch_and_add" 4 "ompexp" { target i?86-*-* x86_64-*-* ia64-*-* powerpc*-*-* alpha*-*-* } } } */
-/* { dg-final { cleanup-tree-dump "ompexp" } } */
diff --git a/gcc/testsuite/gcc.dg/gomp/atomic-11.c b/gcc/testsuite/gcc.dg/gomp/atomic-11.c
deleted file mode 100644
index b5647b0..0000000
--- a/gcc/testsuite/gcc.dg/gomp/atomic-11.c
+++ /dev/null
@@ -1,17 +0,0 @@ 
-/* PR middle-end/36877 */
-/* { dg-do compile } */
-/* { dg-options "-fopenmp" } */
-/* { dg-options "-fopenmp -march=i386" { target { { i?86-*-* x86_64-*-* } && ia32 } } } */
-
-int i;
-float f;
-
-void foo (void)
-{
-#pragma omp atomic
-  i++;
-#pragma omp atomic
-  f += 1.0;
-}
-
-/* { dg-final { scan-assembler-not "__sync_(fetch|add|bool|val)" { target i?86-*-* x86_64-*-* powerpc*-*-* ia64-*-* s390*-*-* sparc*-*-* } } } */
diff --git a/gcc/testsuite/gcc.dg/gomp/atomic-12.c b/gcc/testsuite/gcc.dg/gomp/atomic-12.c
deleted file mode 100644
index 618c4c8..0000000
--- a/gcc/testsuite/gcc.dg/gomp/atomic-12.c
+++ /dev/null
@@ -1,306 +0,0 @@ 
-/* PR middle-end/45423 */
-/* { dg-do compile } */
-/* { dg-options "-fopenmp -fdump-tree-gimple -g0" } */
-/* atomicvar should never be referenced in between the barrier and
-   following #pragma omp atomic_load.  */
-/* { dg-final { scan-tree-dump-not "barrier\[^#\]*atomicvar" "gimple" } } */
-/* { dg-final { cleanup-tree-dump "gimple" } } */
-
-#ifdef __cplusplus
-bool atomicvar, c;
-#else
-_Bool atomicvar, c;
-#endif
-int i, atomicvar2, c2;
-
-int
-foo (void)
-{
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar |= -1;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar |= 0;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar |= 1;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar |= 2;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar |= c;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar ^= -1;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar ^= 0;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar ^= 1;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar ^= 2;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar ^= c;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar &= -1;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar &= 0;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar &= 1;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar &= 2;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar &= c;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar += -1;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar += 0;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar += 1;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar += 2;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar += c;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar -= -1;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar -= 0;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar -= 1;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar -= 2;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar -= c;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar *= -1;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar *= 0;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar *= 1;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar *= 2;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar *= c;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar /= -1;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar /= 1;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar /= 2;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar /= c;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar <<= 0;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar <<= 1;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar <<= 2;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar <<= i;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar >>= 0;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar >>= 1;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar >>= 2;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar >>= i;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar++;
-  #pragma omp barrier
-  #pragma omp atomic
-    ++atomicvar;
-  #pragma omp barrier
-#ifndef __cplusplus
-  #pragma omp atomic
-    atomicvar--;
-  #pragma omp barrier
-  #pragma omp atomic
-    --atomicvar;
-  #pragma omp barrier
-#endif
-  return 0;
-}
-
-int
-bar (void)
-{
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar2 |= -1;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar2 |= 0;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar2 |= 1;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar2 |= 2;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar2 |= c2;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar2 ^= -1;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar2 ^= 0;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar2 ^= 1;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar2 ^= 2;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar2 ^= c2;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar2 &= -1;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar2 &= 0;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar2 &= 1;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar2 &= 2;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar2 &= c2;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar2 += -1;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar2 += 0;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar2 += 1;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar2 += 2;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar2 += c2;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar2 -= -1;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar2 -= 0;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar2 -= 1;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar2 -= 2;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar2 -= c2;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar2 *= -1;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar2 *= 0;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar2 *= 1;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar2 *= 2;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar2 *= c2;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar2 /= -1;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar2 /= 1;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar2 /= 2;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar2 /= c2;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar2 <<= 0;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar2 <<= 1;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar2 <<= 2;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar2 <<= i;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar2 >>= 0;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar2 >>= 1;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar2 >>= 2;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar2 >>= i;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar2++;
-  #pragma omp barrier
-  #pragma omp atomic
-    ++atomicvar2;
-  #pragma omp barrier
-  #pragma omp atomic
-    atomicvar2--;
-  #pragma omp barrier
-  #pragma omp atomic
-    --atomicvar2;
-  #pragma omp barrier
-  return 0;
-}
diff --git a/gcc/testsuite/gcc.dg/gomp/atomic-13.c b/gcc/testsuite/gcc.dg/gomp/atomic-13.c
deleted file mode 100644
index 0146825..0000000
--- a/gcc/testsuite/gcc.dg/gomp/atomic-13.c
+++ /dev/null
@@ -1,9 +0,0 @@ 
-/* PR middle-end/45423 */
-/* { dg-do compile } */
-/* { dg-options "-fopenmp -fdump-tree-gimple -g0 -O2" } */
-/* atomicvar should never be referenced in between the barrier and
-   following #pragma omp atomic_load.  */
-/* { dg-final { scan-tree-dump-not "barrier\[^#\]*atomicvar" "gimple" } } */
-/* { dg-final { cleanup-tree-dump "gimple" } } */
-
-#include "atomic-12.c"
diff --git a/gcc/testsuite/gcc.dg/gomp/atomic-14.c b/gcc/testsuite/gcc.dg/gomp/atomic-14.c
deleted file mode 100644
index f8fc9d8..0000000
--- a/gcc/testsuite/gcc.dg/gomp/atomic-14.c
+++ /dev/null
@@ -1,43 +0,0 @@ 
-/* PR middle-end/45423 */
-/* { dg-do compile } */
-/* { dg-options "-fopenmp" } */
-
-#ifdef __cplusplus
-bool *baz ();
-#else
-_Bool *baz ();
-#endif
-int *bar ();
-
-int
-foo (void)
-{
-  #pragma omp barrier
-  #pragma omp atomic
-    (*bar ())++;
-  #pragma omp barrier
-  #pragma omp atomic
-    ++(*bar ());
-  #pragma omp barrier
-  #pragma omp atomic
-    (*bar ())--;
-  #pragma omp barrier
-  #pragma omp atomic
-    --(*bar ());
-  #pragma omp barrier
-  #pragma omp atomic
-    (*baz ())++;
-  #pragma omp barrier
-  #pragma omp atomic
-    ++(*baz ());
-#ifndef __cplusplus
-  #pragma omp barrier
-  #pragma omp atomic
-    (*baz ())--;
-  #pragma omp barrier
-  #pragma omp atomic
-    --(*baz ());
-  #pragma omp barrier
-#endif
-  return 0;
-}
diff --git a/gcc/testsuite/gcc.dg/gomp/atomic-15.c b/gcc/testsuite/gcc.dg/gomp/atomic-15.c
deleted file mode 100644
index 13a9e0c..0000000
--- a/gcc/testsuite/gcc.dg/gomp/atomic-15.c
+++ /dev/null
@@ -1,46 +0,0 @@ 
-/* { dg-do compile } */
-/* { dg-options "-fopenmp" } */
-
-int x = 6;
-
-int
-main ()
-{
-  int v;
-  #pragma omp atomic
-    x = x * 7 + 6;	/* { dg-error "expected" } */
-  #pragma omp atomic
-    x = x * 7 ^ 6;	/* { dg-error "expected" } */
-  #pragma omp atomic update
-    x = x - 8 + 6;	/* { dg-error "expected" } */
-  #pragma omp atomic
-    x = x ^ 7 | 2;	/* { dg-error "expected" } */
-  #pragma omp atomic
-    x = x / 7 * 2;	/* { dg-error "expected" } */
-  #pragma omp atomic
-    x = x / 7 / 2;	/* { dg-error "expected" } */
-  #pragma omp atomic capture
-    v = x = x | 6;	/* { dg-error "invalid operator" } */
-  #pragma omp atomic capture
-    { v = x; x = x * 7 + 6; }	/* { dg-error "expected" } */
-  #pragma omp atomic capture
-    { v = x; x = x * 7 ^ 6; }	/* { dg-error "expected" } */
-  #pragma omp atomic capture
-    { v = x; x = x - 8 + 6; }	/* { dg-error "expected" } */
-  #pragma omp atomic capture
-    { v = x; x = x ^ 7 | 2; }	/* { dg-error "expected" } */
-  #pragma omp atomic capture
-    { v = x; x = x / 7 * 2; }	/* { dg-error "expected" } */
-  #pragma omp atomic capture
-    { v = x; x = x / 7 / 2; }	/* { dg-error "expected" } */
-  #pragma omp atomic capture
-    { x = x * 7 + 6; v = x; }	/* { dg-error "expected" } */
-  #pragma omp atomic capture
-    { x = x * 7 ^ 6; v = x; }	/* { dg-error "expected" } */
-  #pragma omp atomic capture
-    { x = x - 8 + 6; v = x; }	/* { dg-error "expected" } */
-  #pragma omp atomic capture
-    { x = x ^ 7 | 2; v = x; }	/* { dg-error "expected" } */
-  (void) v;
-  return 0;
-}
diff --git a/gcc/testsuite/gcc.dg/gomp/atomic-2.c b/gcc/testsuite/gcc.dg/gomp/atomic-2.c
deleted file mode 100644
index 720ec9e..0000000
--- a/gcc/testsuite/gcc.dg/gomp/atomic-2.c
+++ /dev/null
@@ -1,23 +0,0 @@ 
-/* { dg-do compile } */
-
-float x, y;
-
-void f1(void)
-{
-  #pragma omp atomic
-    x++;
-  #pragma omp atomic
-    x--;
-  #pragma omp atomic
-    ++x;
-  #pragma omp atomic
-    --x;
-  #pragma omp atomic
-    x += 1;
-  #pragma omp atomic
-    x -= y;
-  #pragma omp atomic
-    x *= 3;
-  #pragma omp atomic
-    x /= 3;
-}
diff --git a/gcc/testsuite/gcc.dg/gomp/atomic-3.c b/gcc/testsuite/gcc.dg/gomp/atomic-3.c
deleted file mode 100644
index 7ea792d..0000000
--- a/gcc/testsuite/gcc.dg/gomp/atomic-3.c
+++ /dev/null
@@ -1,13 +0,0 @@ 
-/* { dg-do compile } */
-/* { dg-options "-fopenmp -fdump-tree-ompexp" } */
-
-int *xyzzy;
-
-void f1(void)
-{
-  #pragma omp atomic
-    xyzzy++;
-}
-
-/* { dg-final { scan-tree-dump-times "xyzzy, 4" 1 "ompexp" { target i?86-*-* x86_64-*-* ia64-*-* powerpc*-*-* alpha*-*-* } } } */
-/* { dg-final { cleanup-tree-dump "ompexp" } } */
diff --git a/gcc/testsuite/gcc.dg/gomp/atomic-4.c b/gcc/testsuite/gcc.dg/gomp/atomic-4.c
deleted file mode 100644
index 7f27370..0000000
--- a/gcc/testsuite/gcc.dg/gomp/atomic-4.c
+++ /dev/null
@@ -1,24 +0,0 @@ 
-/* { dg-do compile } */
-
-int a[4];
-int *p;
-struct S { int x; int y[4]; } s;
-int *bar(void);
-
-void f1(void)
-{
-  #pragma omp atomic
-    a[4] += 1;
-  #pragma omp atomic
-    *p += 1;
-  #pragma omp atomic
-    s.x += 1;
-  #pragma omp atomic
-    s.y[*p] += 1;
-  #pragma omp atomic
-    s.y[*p] *= 42;
-  #pragma omp atomic
-    *bar() += 1;
-  #pragma omp atomic
-    *bar() *= 42;
-}
diff --git a/gcc/testsuite/gcc.dg/gomp/atomic-7.c b/gcc/testsuite/gcc.dg/gomp/atomic-7.c
deleted file mode 100644
index 612e97f..0000000
--- a/gcc/testsuite/gcc.dg/gomp/atomic-7.c
+++ /dev/null
@@ -1,23 +0,0 @@ 
-/* { dg-do compile } */
-
-double x, y;
-
-void f2(void)
-{
-  #pragma omp atomic
-    y++;
-  #pragma omp atomic
-    y--;
-  #pragma omp atomic
-    ++y;
-  #pragma omp atomic
-    --y;
-  #pragma omp atomic
-    y += 1;
-  #pragma omp atomic
-    y -= x;
-  #pragma omp atomic
-    y *= 3;
-  #pragma omp atomic
-    y /= 3;
-}
diff --git a/gcc/testsuite/gcc.dg/gomp/atomic-8.c b/gcc/testsuite/gcc.dg/gomp/atomic-8.c
deleted file mode 100644
index 2f04151..0000000
--- a/gcc/testsuite/gcc.dg/gomp/atomic-8.c
+++ /dev/null
@@ -1,21 +0,0 @@ 
-/* { dg-do compile } */
-
-long double z;
-
-void f3(void)
-{
-  #pragma omp atomic
-    z++;
-  #pragma omp atomic
-    z--;
-  #pragma omp atomic
-    ++z;
-  #pragma omp atomic
-    --z;
-  #pragma omp atomic
-    z += 1;
-  #pragma omp atomic
-    z *= 3;
-  #pragma omp atomic
-    z /= 3;
-}
diff --git a/gcc/testsuite/gcc.dg/gomp/atomic-9.c b/gcc/testsuite/gcc.dg/gomp/atomic-9.c
deleted file mode 100644
index 2fafbd4..0000000
--- a/gcc/testsuite/gcc.dg/gomp/atomic-9.c
+++ /dev/null
@@ -1,13 +0,0 @@ 
-/* { dg-do compile } */
-/* { dg-options "-fopenmp -fdump-tree-ompexp" } */
-
-volatile int *bar(void);
-
-void f1(void)
-{
-  #pragma omp atomic
-    *bar() += 1;
-}
-
-/* { dg-final { scan-tree-dump-times "__sync_fetch_and_add" 1 "ompexp" { target i?86-*-* x86_64-*-* ia64-*-* powerpc*-*-* alpha*-*-* } } } */
-/* { dg-final { cleanup-tree-dump "ompexp" } } */
diff --git a/gcc/testsuite/gcc.dg/gomp/gomp.exp b/gcc/testsuite/gcc.dg/gomp/gomp.exp
index e4f31cc..4cb4caf 100644
--- a/gcc/testsuite/gcc.dg/gomp/gomp.exp
+++ b/gcc/testsuite/gcc.dg/gomp/gomp.exp
@@ -29,8 +29,7 @@  if ![check_effective_target_fopenmp] {
 dg-init
 
 # Main loop.
-dg-runtest [lsort [find $srcdir/$subdir *.c]] \
-	"" "-fopenmp"
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c $srcdir/c-c++-common/gomp/*.c]] "" "-fopenmp"
 
 # All done.
 dg-finish
diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp
index 8bb85b8..9f7fcc6 100644
--- a/gcc/testsuite/lib/target-supports.exp
+++ b/gcc/testsuite/lib/target-supports.exp
@@ -655,6 +655,28 @@  proc check_effective_target_tls_runtime {} {
     } [add_options_for_tls ""]]
 }
 
+# Return 1 if atomic compare-and-swap is supported on 'int'
+
+proc check_effective_target_cas_char {} {
+    return [check_no_compiler_messages cas_char assembly {
+	#ifndef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_1
+	#error unsupported
+	#endif
+    } ""]
+}
+
+proc check_effective_target_cas_int {} {
+    return [check_no_compiler_messages cas_int assembly {
+	#if __INT_MAX__ == 0x7fff && __GCC_HAVE_SYNC_COMPARE_AND_SWAP_2
+        /* ok */
+        #elif __INT_MAX__ == 0x7fffffff && __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4
+	/* ok */
+	#else
+	#error unsupported
+	#endif
+    } ""]
+}
+
 # Return 1 if -ffunction-sections is supported, 0 otherwise.
 
 proc check_effective_target_function_sections {} {