diff mbox

[committed] #pragma omp atomic fixes (PR middle-end/45423)

Message ID 20100830171955.GB1269@tyan-ft48-01.lab.bos.redhat.com
State New
Headers show

Commit Message

Jakub Jelinek Aug. 30, 2010, 5:19 p.m. UTC
Hi!

This patch fixes a problem during gimplification of some boolean
#pragma omp atomic stmts, and fixes parsing of
boolean ++/-- atomic stmts in C and ++ atomic stmts in C++ (-- is disallowed
by the standard).

Bootstrapped/regtested on x86_64-linux and i686-linux, committed
to trunk.  Will backport to 4.5/4.4 when I get to test it there.

2010-08-30  Jakub Jelinek  <jakub@redhat.com>

	PR middle-end/45423
	* gimplify.c (goa_stabilize_expr): Handle TRUTH_NOT_EXPR
	and TRUTH_{AND,OR,XOR}_EXPR.
	* c-parser.c (c_parser_omp_atomic): Handle boolean
	{PRE,POST}_{INC,DEC}REMENT.
cp/
	* parser.c (cp_parser_omp_atomic): Handle boolean
	{PRE,POST}_INCREMENT.
testsuite/
	* gcc.dg/gomp/atomic-12.c: New test.
	* gcc.dg/gomp/atomic-13.c: New test.
	* gcc.dg/gomp/atomic-14.c: New test.
	* g++.dg/gomp/atomic-11.C: New test.
	* g++.dg/gomp/atomic-12.C: New test.
	* g++.dg/gomp/atomic-13.C: New test.
	* g++.dg/gomp/atomic-14.C: New test.


	Jakub
diff mbox

Patch

--- gcc/gimplify.c.jj	2010-08-20 16:05:41.000000000 +0200
+++ gcc/gimplify.c	2010-08-30 11:43:53.000000000 +0200
@@ -6405,8 +6405,12 @@  goa_stabilize_expr (tree *expr_p, gimple
 	{
 	case TRUTH_ANDIF_EXPR:
 	case TRUTH_ORIF_EXPR:
+	case TRUTH_AND_EXPR:
+	case TRUTH_OR_EXPR:
+	case TRUTH_XOR_EXPR:
 	  saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 1), pre_p,
 					 lhs_addr, lhs_var);
+	case TRUTH_NOT_EXPR:
 	  saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 0), pre_p,
 					 lhs_addr, lhs_var);
 	  break;
--- gcc/c-parser.c.jj	2010-08-11 21:08:06.000000000 +0200
+++ gcc/c-parser.c	2010-08-30 13:10:27.000000000 +0200
@@ -8004,6 +8004,42 @@  c_parser_omp_atomic (location_t loc, c_p
       rhs = integer_one_node;
       break;
 
+    case COMPOUND_EXPR:
+      if (TREE_CODE (TREE_OPERAND (lhs, 0)) == SAVE_EXPR
+	  && TREE_CODE (TREE_OPERAND (lhs, 1)) == COMPOUND_EXPR
+	  && TREE_CODE (TREE_OPERAND (TREE_OPERAND (lhs, 1), 0)) == MODIFY_EXPR
+	  && TREE_OPERAND (TREE_OPERAND (lhs, 1), 1) == TREE_OPERAND (lhs, 0)
+	  && TREE_CODE (TREE_TYPE (TREE_OPERAND (TREE_OPERAND
+					      (TREE_OPERAND (lhs, 1), 0), 0)))
+	     == BOOLEAN_TYPE)
+	/* Undo effects of boolean_increment for post {in,de}crement.  */
+	lhs = TREE_OPERAND (TREE_OPERAND (lhs, 1), 0);
+      /* FALLTHRU */
+    case MODIFY_EXPR:
+      if (TREE_CODE (lhs) == MODIFY_EXPR
+	  && TREE_CODE (TREE_TYPE (TREE_OPERAND (lhs, 0))) == BOOLEAN_TYPE)
+	{
+	  /* Undo effects of boolean_increment.  */
+	  if (integer_onep (TREE_OPERAND (lhs, 1)))
+	    {
+	      /* This is pre or post increment.  */
+	      rhs = TREE_OPERAND (lhs, 1);
+	      lhs = TREE_OPERAND (lhs, 0);
+	      code = NOP_EXPR;
+	      break;
+	    }
+	  if (TREE_CODE (TREE_OPERAND (lhs, 1)) == TRUTH_NOT_EXPR
+	      && TREE_OPERAND (lhs, 0)
+		 == TREE_OPERAND (TREE_OPERAND (lhs, 1), 0))
+	    {
+	      /* This is pre or post decrement.  */
+	      rhs = TREE_OPERAND (lhs, 1);
+	      lhs = TREE_OPERAND (lhs, 0);
+	      code = NOP_EXPR;
+	      break;
+	    }
+	}
+      /* FALLTHRU */
     default:
       switch (c_parser_peek_token (parser)->type)
 	{
--- gcc/cp/parser.c.jj	2010-08-20 16:05:29.000000000 +0200
+++ gcc/cp/parser.c	2010-08-30 13:22:13.000000000 +0200
@@ -22489,6 +22489,32 @@  cp_parser_omp_atomic (cp_parser *parser,
       rhs = integer_one_node;
       break;
 
+    case COMPOUND_EXPR:
+      if (TREE_CODE (TREE_OPERAND (lhs, 0)) == SAVE_EXPR
+	 && TREE_CODE (TREE_OPERAND (lhs, 1)) == COMPOUND_EXPR
+	 && TREE_CODE (TREE_OPERAND (TREE_OPERAND (lhs, 1), 0)) == MODIFY_EXPR
+	 && TREE_OPERAND (TREE_OPERAND (lhs, 1), 1) == TREE_OPERAND (lhs, 0)
+	 && TREE_CODE (TREE_TYPE (TREE_OPERAND (TREE_OPERAND
+					     (TREE_OPERAND (lhs, 1), 0), 0)))
+	    == BOOLEAN_TYPE)
+       /* Undo effects of boolean_increment for post {in,de}crement.  */
+       lhs = TREE_OPERAND (TREE_OPERAND (lhs, 1), 0);
+      /* FALLTHRU */
+    case MODIFY_EXPR:
+      if (TREE_CODE (lhs) == MODIFY_EXPR
+	 && TREE_CODE (TREE_TYPE (TREE_OPERAND (lhs, 0))) == BOOLEAN_TYPE)
+       {
+	 /* Undo effects of boolean_increment.  */
+	 if (integer_onep (TREE_OPERAND (lhs, 1)))
+	   {
+	     /* This is pre or post increment.  */
+	     rhs = TREE_OPERAND (lhs, 1);
+	     lhs = TREE_OPERAND (lhs, 0);
+	     code = NOP_EXPR;
+	     break;
+	   }
+       }
+      /* FALLTHRU */
     default:
       switch (cp_lexer_peek_token (parser->lexer)->type)
 	{
--- gcc/testsuite/gcc.dg/gomp/atomic-12.c.jj	2010-08-30 10:51:28.000000000 +0200
+++ gcc/testsuite/gcc.dg/gomp/atomic-12.c	2010-08-30 13:19:51.000000000 +0200
@@ -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;
+}
--- gcc/testsuite/gcc.dg/gomp/atomic-13.c.jj	2010-08-30 10:51:42.000000000 +0200
+++ gcc/testsuite/gcc.dg/gomp/atomic-13.c	2010-08-30 13:12:55.000000000 +0200
@@ -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"
--- gcc/testsuite/gcc.dg/gomp/atomic-14.c.jj	2010-08-30 13:15:34.000000000 +0200
+++ gcc/testsuite/gcc.dg/gomp/atomic-14.c	2010-08-30 13:15:27.000000000 +0200
@@ -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;
+}
--- gcc/testsuite/g++.dg/gomp/atomic-11.C.jj	2010-08-30 10:54:13.000000000 +0200
+++ gcc/testsuite/g++.dg/gomp/atomic-11.C	2010-08-30 13:19:19.000000000 +0200
@@ -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;
+}
--- gcc/testsuite/g++.dg/gomp/atomic-12.C.jj	2010-08-30 10:54:23.000000000 +0200
+++ gcc/testsuite/g++.dg/gomp/atomic-12.C	2010-08-30 13:16:18.000000000 +0200
@@ -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-11.C"
--- gcc/testsuite/g++.dg/gomp/atomic-13.C.jj	2010-08-30 13:20:02.000000000 +0200
+++ gcc/testsuite/g++.dg/gomp/atomic-13.C	2010-08-30 13:15:27.000000000 +0200
@@ -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;
+}
--- gcc/testsuite/g++.dg/gomp/atomic-14.C.jj	2010-08-30 13:29:13.000000000 +0200
+++ gcc/testsuite/g++.dg/gomp/atomic-14.C	2010-08-30 13:30:37.000000000 +0200
@@ -0,0 +1,19 @@ 
+// PR middle-end/45423
+// { dg-do compile }
+// { dg-options "-fopenmp" }
+
+bool *baz (), atomicvar;
+
+int
+foo (void)
+{
+  #pragma omp atomic
+    (*baz ())--;	// { dg-error "invalid use of Boolean" }
+  #pragma omp atomic
+    --(*baz ());	// { dg-error "invalid use of Boolean" }
+  #pragma omp atomic
+    atomicvar--;	// { dg-error "invalid use of Boolean" }
+  #pragma omp atomic
+    --atomicvar;	// { dg-error "invalid use of Boolean" }
+  return 0;
+}