This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[gomp4] Handle seq_cst clause on OpenMP atomics
- From: Jakub Jelinek <jakub at redhat dot com>
- To: gcc-patches at gcc dot gnu dot org
- Cc: Torvald Riegel <triegel at redhat dot com>, Richard Henderson <rth at redhat dot com>
- Date: Tue, 30 Apr 2013 18:10:42 +0200
- Subject: [gomp4] Handle seq_cst clause on OpenMP atomics
- Reply-to: Jakub Jelinek <jakub at redhat dot com>
Hi!
Something I've missed in the latest draft, there can be seq_cst
clause to request sequentially atomic operation as opposed to relaxed.
Handled thusly:
2013-04-30 Jakub Jelinek <jakub@redhat.com>
* gimple-pretty-print.c (dump_gimple_omp_atomic_load,
dump_gimple_omp_atomic_store): Handle gimple_omp_atomic_seq_cst_p.
* gimple.h (enum gf_mask): Add GF_OMP_ATOMIC_SEQ_CST.
(gimple_omp_atomic_set_seq_cst, gimple_omp_atomic_seq_cst_p): New
inline functions.
* omp-low.c (expand_omp_atomic_load, expand_omp_atomic_store,
expand_omp_atomic_fetch_op): If gimple_omp_atomic_seq_cst_p,
pass MEMMODEL_SEQ_CST instead of MEMMODEL_RELAXED to the builtin.
* gimplify.c (gimplify_omp_atomic): Handle OMP_ATOMIC_SEQ_CST.
* tree-pretty-print.c (dump_generic_node): Handle OMP_ATOMIC_SEQ_CST.
* tree.def (OMP_ATOMIC): Add comment that OMP_ATOMIC* must stay
consecutive.
* tree.h (OMP_ATOMIC_SEQ_CST): Define.
c/
* c-parser.c (c_parser_omp_atomic): Parse seq_cst clause, pass
true if it is present to c_finish_omp_atomic.
cp/
* pt.c (tsubst_expr): Pass OMP_ATOMIC_SEQ_CST to finish_omp_atomic.
* semantics.c (finish_omp_atomic): Add seq_cst argument, pass
it through to c_finish_omp_atomic or store into OMP_ATOMIC_SEQ_CST.
* cp-tree.h (finish_omp_atomic): Adjust prototype.
* parser.c (cp_parser_omp_atomic): Parse seq_cst clause, pass
true if it is present to finish_omp_atomic.
c-family/
* c-omp.c (c_finish_omp_atomic): Add seq_cst argument, store it
into OMP_ATOMIC_SEQ_CST bit.
* c-common.h (c_finish_omp_atomic): Adjust prototype.
testsuite/
* testsuite/libgomp.c/atomic-17.c: New test.
* testsuite/libgomp.c++/atomic-14.C: New test.
* testsuite/libgomp.c++/atomic-15.C: New test.
--- gcc/gimple-pretty-print.c.jj 2013-03-27 13:01:09.000000000 +0100
+++ gcc/gimple-pretty-print.c 2013-04-30 17:34:10.663125084 +0200
@@ -1805,6 +1805,8 @@ dump_gimple_omp_atomic_load (pretty_prin
else
{
pp_string (buffer, "#pragma omp atomic_load");
+ if (gimple_omp_atomic_seq_cst_p (gs))
+ pp_string (buffer, " seq_cst");
if (gimple_omp_atomic_need_value_p (gs))
pp_string (buffer, " [needed]");
newline_and_indent (buffer, spc + 2);
@@ -1835,6 +1837,8 @@ dump_gimple_omp_atomic_store (pretty_pri
else
{
pp_string (buffer, "#pragma omp atomic_store ");
+ if (gimple_omp_atomic_seq_cst_p (gs))
+ pp_string (buffer, "seq_cst ");
if (gimple_omp_atomic_need_value_p (gs))
pp_string (buffer, "[needed] ");
pp_character (buffer, '(');
--- gcc/c/c-parser.c.jj 2013-04-24 18:22:37.000000000 +0200
+++ gcc/c/c-parser.c 2013-04-30 16:32:45.967276133 +0200
@@ -10218,10 +10218,23 @@ c_parser_omp_atomic (location_t loc, c_p
location_t eloc;
bool structured_block = false;
bool swapped = false;
+ bool seq_cst = false;
if (c_parser_next_token_is (parser, CPP_NAME))
{
const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
+ if (!strcmp (p, "seq_cst"))
+ {
+ seq_cst = true;
+ c_parser_consume_token (parser);
+ if (c_parser_next_token_is (parser, CPP_COMMA)
+ && c_parser_peek_2nd_token (parser)->type == CPP_NAME)
+ c_parser_consume_token (parser);
+ }
+ }
+ if (c_parser_next_token_is (parser, CPP_NAME))
+ {
+ const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
if (!strcmp (p, "read"))
code = OMP_ATOMIC_READ;
@@ -10236,6 +10249,23 @@ c_parser_omp_atomic (location_t loc, c_p
if (p)
c_parser_consume_token (parser);
}
+ if (!seq_cst)
+ {
+ if (c_parser_next_token_is (parser, CPP_COMMA)
+ && c_parser_peek_2nd_token (parser)->type == CPP_NAME)
+ c_parser_consume_token (parser);
+
+ if (c_parser_next_token_is (parser, CPP_NAME))
+ {
+ const char *p
+ = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
+ if (!strcmp (p, "seq_cst"))
+ {
+ seq_cst = true;
+ c_parser_consume_token (parser);
+ }
+ }
+ }
c_parser_skip_to_pragma_eol (parser);
switch (code)
@@ -10526,7 +10556,7 @@ done:
}
else
stmt = c_finish_omp_atomic (loc, code, opcode, lhs, rhs, v, lhs1, rhs1,
- swapped);
+ swapped, seq_cst);
if (stmt != error_mark_node)
add_stmt (stmt);
--- gcc/gimple.h.jj 2013-03-27 13:01:09.000000000 +0100
+++ gcc/gimple.h 2013-04-30 16:02:24.164400181 +0200
@@ -114,6 +114,7 @@ enum gf_mask {
GF_OMP_SECTION_LAST = 1 << 0,
GF_OMP_ATOMIC_NEED_VALUE = 1 << 0,
+ GF_OMP_ATOMIC_SEQ_CST = 1 << 1,
GF_PREDICT_TAKEN = 1 << 15
};
@@ -1727,6 +1728,29 @@ gimple_omp_atomic_set_need_value (gimple
}
+/* Return true if OMP atomic load/store statement G has the
+ GF_OMP_ATOMIC_SEQ_CST flag set. */
+
+static inline bool
+gimple_omp_atomic_seq_cst_p (const_gimple g)
+{
+ if (gimple_code (g) != GIMPLE_OMP_ATOMIC_LOAD)
+ GIMPLE_CHECK (g, GIMPLE_OMP_ATOMIC_STORE);
+ return (gimple_omp_subcode (g) & GF_OMP_ATOMIC_SEQ_CST) != 0;
+}
+
+
+/* Set the GF_OMP_ATOMIC_SEQ_CST flag on G. */
+
+static inline void
+gimple_omp_atomic_set_seq_cst (gimple g)
+{
+ if (gimple_code (g) != GIMPLE_OMP_ATOMIC_LOAD)
+ GIMPLE_CHECK (g, GIMPLE_OMP_ATOMIC_STORE);
+ g->gsbase.subcode |= GF_OMP_ATOMIC_SEQ_CST;
+}
+
+
/* Return the number of operands for statement GS. */
static inline unsigned
--- gcc/omp-low.c.jj 2013-04-30 10:26:40.000000000 +0200
+++ gcc/omp-low.c 2013-04-30 17:07:27.888328410 +0200
@@ -5472,7 +5472,10 @@ expand_omp_atomic_load (basic_block load
itype = TREE_TYPE (TREE_TYPE (decl));
call = build_call_expr_loc (loc, decl, 2, addr,
- build_int_cst (NULL, MEMMODEL_RELAXED));
+ build_int_cst (NULL,
+ gimple_omp_atomic_seq_cst_p (stmt)
+ ? MEMMODEL_SEQ_CST
+ : MEMMODEL_RELAXED));
if (!useless_type_conversion_p (type, itype))
call = fold_build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
@@ -5544,7 +5547,10 @@ expand_omp_atomic_store (basic_block loa
if (!useless_type_conversion_p (itype, type))
stored_val = fold_build1_loc (loc, VIEW_CONVERT_EXPR, itype, stored_val);
call = build_call_expr_loc (loc, decl, 3, addr, stored_val,
- build_int_cst (NULL, MEMMODEL_RELAXED));
+ build_int_cst (NULL,
+ gimple_omp_atomic_seq_cst_p (stmt)
+ ? MEMMODEL_SEQ_CST
+ : MEMMODEL_RELAXED));
if (exchange)
{
if (!useless_type_conversion_p (type, itype))
@@ -5585,6 +5591,7 @@ expand_omp_atomic_fetch_op (basic_block
enum tree_code code;
bool need_old, need_new;
enum machine_mode imode;
+ bool seq_cst;
/* We expect to find the following sequences:
@@ -5610,6 +5617,7 @@ expand_omp_atomic_fetch_op (basic_block
return false;
need_new = gimple_omp_atomic_need_value_p (gsi_stmt (gsi));
need_old = gimple_omp_atomic_need_value_p (last_stmt (load_bb));
+ seq_cst = gimple_omp_atomic_seq_cst_p (last_stmt (load_bb));
gcc_checking_assert (!need_old || !need_new);
if (!operand_equal_p (gimple_assign_lhs (stmt), stored_val, 0))
@@ -5676,7 +5684,9 @@ expand_omp_atomic_fetch_op (basic_block
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));
+ build_int_cst (NULL,
+ seq_cst ? MEMMODEL_SEQ_CST
+ : MEMMODEL_RELAXED));
if (need_old || need_new)
{
--- gcc/gimplify.c.jj 2013-04-23 16:15:06.000000000 +0200
+++ gcc/gimplify.c 2013-04-30 17:20:19.404861154 +0200
@@ -7076,6 +7076,11 @@ gimplify_omp_atomic (tree *expr_p, gimpl
rhs = tmp_load;
storestmt = gimple_build_omp_atomic_store (rhs);
gimplify_seq_add_stmt (pre_p, storestmt);
+ if (OMP_ATOMIC_SEQ_CST (*expr_p))
+ {
+ gimple_omp_atomic_set_seq_cst (loadstmt);
+ gimple_omp_atomic_set_seq_cst (storestmt);
+ }
switch (TREE_CODE (*expr_p))
{
case OMP_ATOMIC_READ:
@@ -7092,7 +7097,7 @@ gimplify_omp_atomic (tree *expr_p, gimpl
break;
}
- return GS_ALL_DONE;
+ return GS_ALL_DONE;
}
/* Gimplify a TRANSACTION_EXPR. This involves gimplification of the
--- gcc/tree-pretty-print.c.jj 2013-03-27 13:01:09.000000000 +0100
+++ gcc/tree-pretty-print.c 2013-04-30 17:21:00.873622295 +0200
@@ -2431,6 +2431,8 @@ dump_generic_node (pretty_printer *buffe
case OMP_ATOMIC:
pp_string (buffer, "#pragma omp atomic");
+ if (OMP_ATOMIC_SEQ_CST (node))
+ pp_string (buffer, " seq_cst");
newline_and_indent (buffer, spc + 2);
dump_generic_node (buffer, TREE_OPERAND (node, 0), spc, flags, false);
pp_space (buffer);
@@ -2441,6 +2443,8 @@ dump_generic_node (pretty_printer *buffe
case OMP_ATOMIC_READ:
pp_string (buffer, "#pragma omp atomic read");
+ if (OMP_ATOMIC_SEQ_CST (node))
+ pp_string (buffer, " seq_cst");
newline_and_indent (buffer, spc + 2);
dump_generic_node (buffer, TREE_OPERAND (node, 0), spc, flags, false);
pp_space (buffer);
@@ -2449,6 +2453,8 @@ dump_generic_node (pretty_printer *buffe
case OMP_ATOMIC_CAPTURE_OLD:
case OMP_ATOMIC_CAPTURE_NEW:
pp_string (buffer, "#pragma omp atomic capture");
+ if (OMP_ATOMIC_SEQ_CST (node))
+ pp_string (buffer, " seq_cst");
newline_and_indent (buffer, spc + 2);
dump_generic_node (buffer, TREE_OPERAND (node, 0), spc, flags, false);
pp_space (buffer);
--- gcc/cp/pt.c.jj 2013-03-27 13:01:09.000000000 +0100
+++ gcc/cp/pt.c 2013-04-30 16:23:59.019309306 +0200
@@ -13276,7 +13276,8 @@ tsubst_expr (tree t, tree args, tsubst_f
lhs = RECUR (TREE_OPERAND (op1, 0));
rhs = RECUR (TREE_OPERAND (op1, 1));
finish_omp_atomic (OMP_ATOMIC, TREE_CODE (op1), lhs, rhs,
- NULL_TREE, NULL_TREE, rhs1);
+ NULL_TREE, NULL_TREE, rhs1,
+ OMP_ATOMIC_SEQ_CST (t));
}
else
{
@@ -13313,7 +13314,8 @@ tsubst_expr (tree t, tree args, tsubst_f
lhs = RECUR (TREE_OPERAND (op1, 0));
rhs = RECUR (TREE_OPERAND (op1, 1));
}
- finish_omp_atomic (code, opcode, lhs, rhs, v, lhs1, rhs1);
+ finish_omp_atomic (code, opcode, lhs, rhs, v, lhs1, rhs1,
+ OMP_ATOMIC_SEQ_CST (t));
}
break;
--- gcc/cp/semantics.c.jj 2013-04-24 16:29:36.000000000 +0200
+++ gcc/cp/semantics.c 2013-04-30 16:22:36.365769312 +0200
@@ -5221,7 +5221,7 @@ finish_omp_for (location_t locus, enum t
void
finish_omp_atomic (enum tree_code code, enum tree_code opcode, tree lhs,
- tree rhs, tree v, tree lhs1, tree rhs1)
+ tree rhs, tree v, tree lhs1, tree rhs1, bool seq_cst)
{
tree orig_lhs;
tree orig_rhs;
@@ -5292,7 +5292,7 @@ finish_omp_atomic (enum tree_code code,
return;
}
stmt = c_finish_omp_atomic (input_location, code, opcode, lhs, rhs,
- v, lhs1, rhs1, swapped);
+ v, lhs1, rhs1, swapped, seq_cst);
if (stmt == error_mark_node)
return;
}
@@ -5302,6 +5302,7 @@ finish_omp_atomic (enum tree_code code,
{
stmt = build_min_nt_loc (EXPR_LOCATION (orig_lhs),
OMP_ATOMIC_READ, orig_lhs);
+ OMP_ATOMIC_SEQ_CST (stmt) = seq_cst;
stmt = build2 (MODIFY_EXPR, void_type_node, orig_v, stmt);
}
else
@@ -5317,10 +5318,12 @@ finish_omp_atomic (enum tree_code code,
{
stmt = build_min_nt_loc (EXPR_LOCATION (orig_lhs1),
code, orig_lhs1, stmt);
+ OMP_ATOMIC_SEQ_CST (stmt) = seq_cst;
stmt = build2 (MODIFY_EXPR, void_type_node, orig_v, stmt);
}
}
stmt = build2 (OMP_ATOMIC, void_type_node, integer_zero_node, stmt);
+ OMP_ATOMIC_SEQ_CST (stmt) = seq_cst;
}
add_stmt (stmt);
}
--- gcc/cp/cp-tree.h.jj 2013-04-19 14:51:38.000000000 +0200
+++ gcc/cp/cp-tree.h 2013-04-30 16:20:00.938596128 +0200
@@ -5713,7 +5713,8 @@ extern tree finish_omp_for (location_t
tree, tree, tree, tree, tree,
tree, tree);
extern void finish_omp_atomic (enum tree_code, enum tree_code,
- tree, tree, tree, tree, tree);
+ tree, tree, tree, tree, tree,
+ bool);
extern void finish_omp_barrier (void);
extern void finish_omp_flush (void);
extern void finish_omp_taskwait (void);
--- gcc/cp/parser.c.jj 2013-04-30 14:21:06.000000000 +0200
+++ gcc/cp/parser.c 2013-04-30 16:46:06.627751932 +0200
@@ -27197,12 +27197,27 @@ cp_parser_omp_atomic (cp_parser *parser,
tree rhs1 = NULL_TREE, orig_lhs;
enum tree_code code = OMP_ATOMIC, opcode = NOP_EXPR;
bool structured_block = false;
+ bool seq_cst = false;
if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
{
tree id = cp_lexer_peek_token (parser->lexer)->u.value;
const char *p = IDENTIFIER_POINTER (id);
+ if (!strcmp (p, "seq_cst"))
+ {
+ seq_cst = true;
+ cp_lexer_consume_token (parser->lexer);
+ if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA)
+ && cp_lexer_peek_nth_token (parser->lexer, 2)->type == CPP_NAME)
+ cp_lexer_consume_token (parser->lexer);
+ }
+ }
+ if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
+ {
+ tree id = cp_lexer_peek_token (parser->lexer)->u.value;
+ const char *p = IDENTIFIER_POINTER (id);
+
if (!strcmp (p, "read"))
code = OMP_ATOMIC_READ;
else if (!strcmp (p, "write"))
@@ -27216,6 +27231,24 @@ cp_parser_omp_atomic (cp_parser *parser,
if (p)
cp_lexer_consume_token (parser->lexer);
}
+ if (!seq_cst)
+ {
+ if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA)
+ && cp_lexer_peek_nth_token (parser->lexer, 2)->type == CPP_NAME)
+ cp_lexer_consume_token (parser->lexer);
+
+ if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
+ {
+ tree id = cp_lexer_peek_token (parser->lexer)->u.value;
+ const char *p = IDENTIFIER_POINTER (id);
+
+ if (!strcmp (p, "seq_cst"))
+ {
+ seq_cst = true;
+ cp_lexer_consume_token (parser->lexer);
+ }
+ }
+ }
cp_parser_require_pragma_eol (parser, pragma_tok);
switch (code)
@@ -27522,7 +27555,7 @@ stmt_done:
cp_parser_require (parser, CPP_CLOSE_BRACE, RT_CLOSE_BRACE);
}
done:
- finish_omp_atomic (code, opcode, lhs, rhs, v, lhs1, rhs1);
+ finish_omp_atomic (code, opcode, lhs, rhs, v, lhs1, rhs1, seq_cst);
if (!structured_block)
cp_parser_consume_semicolon_at_end_of_statement (parser);
return;
--- gcc/tree.def.jj 2013-03-27 13:01:09.000000000 +0100
+++ gcc/tree.def 2013-04-30 16:00:03.603208178 +0200
@@ -1069,6 +1069,9 @@ DEFTREECODE (OMP_ORDERED, "omp_ordered",
Operand 1: OMP_CRITICAL_NAME: Identifier for critical section. */
DEFTREECODE (OMP_CRITICAL, "omp_critical", tcc_statement, 2)
+/* OMP_ATOMIC through OMP_ATOMIC_CAPTURE_NEW must be consecutive,
+ or OMP_ATOMIC_SEQ_CST needs adjusting. */
+
/* OpenMP - #pragma omp atomic
Operand 0: The address at which the atomic operation is to be performed.
This address should be stabilized with save_expr.
--- gcc/tree.h.jj 2013-04-19 14:51:38.000000000 +0200
+++ gcc/tree.h 2013-04-30 16:04:26.681692052 +0200
@@ -633,6 +633,9 @@ struct GTY(()) tree_base {
OMP_PARALLEL_COMBINED in
OMP_PARALLEL
+ OMP_ATOMIC_SEQ_CST in
+ OMP_ATOMIC*
+
OMP_CLAUSE_PRIVATE_OUTER_REF in
OMP_CLAUSE_PRIVATE
@@ -1872,6 +1875,12 @@ extern void protected_set_expr_location
#define OMP_PARALLEL_COMBINED(NODE) \
(OMP_PARALLEL_CHECK (NODE)->base.private_flag)
+/* True if OMP_ATOMIC* is supposed to be sequentially consistent
+ as opposed to relaxed. */
+#define OMP_ATOMIC_SEQ_CST(NODE) \
+ (TREE_RANGE_CHECK (NODE, OMP_ATOMIC, \
+ OMP_ATOMIC_CAPTURE_NEW)->base.private_flag)
+
/* True on a PRIVATE clause if its decl is kept around for debugging
information only and its DECL_VALUE_EXPR is supposed to point
to what it has been remapped to. */
--- gcc/c-family/c-common.h.jj 2013-03-27 13:01:09.000000000 +0100
+++ gcc/c-family/c-common.h 2013-04-30 15:51:29.681164436 +0200
@@ -1035,7 +1035,7 @@ extern tree c_finish_omp_critical (locat
extern tree c_finish_omp_ordered (location_t, tree);
extern void c_finish_omp_barrier (location_t);
extern tree c_finish_omp_atomic (location_t, enum tree_code, enum tree_code,
- tree, tree, tree, tree, tree, bool);
+ tree, tree, tree, tree, tree, bool, bool);
extern void c_finish_omp_flush (location_t);
extern void c_finish_omp_taskwait (location_t);
extern void c_finish_omp_taskyield (location_t);
--- gcc/c-family/c-omp.c.jj 2013-04-15 15:47:09.000000000 +0200
+++ gcc/c-family/c-omp.c 2013-04-30 16:18:03.588102175 +0200
@@ -122,7 +122,7 @@ c_finish_omp_taskyield (location_t loc)
tree
c_finish_omp_atomic (location_t loc, enum tree_code code,
enum tree_code opcode, tree lhs, tree rhs,
- tree v, tree lhs1, tree rhs1, bool swapped)
+ tree v, tree lhs1, tree rhs1, bool swapped, bool seq_cst)
{
tree x, type, addr;
@@ -168,6 +168,7 @@ c_finish_omp_atomic (location_t loc, enu
{
x = build1 (OMP_ATOMIC_READ, type, addr);
SET_EXPR_LOCATION (x, loc);
+ OMP_ATOMIC_SEQ_CST (x) = seq_cst;
return build_modify_expr (loc, v, NULL_TREE, NOP_EXPR,
loc, x, NULL_TREE);
return x;
@@ -192,6 +193,7 @@ c_finish_omp_atomic (location_t loc, enu
type = void_type_node;
x = build2 (code, type, addr, rhs);
SET_EXPR_LOCATION (x, loc);
+ OMP_ATOMIC_SEQ_CST (x) = seq_cst;
/* Generally it is hard to prove lhs1 and lhs are the same memory
location, just diagnose different variables. */
--- libgomp/testsuite/libgomp.c++/atomic-15.C.jj 2013-04-30 17:19:07.258282355 +0200
+++ libgomp/testsuite/libgomp.c++/atomic-15.C 2013-04-30 17:19:11.440254816 +0200
@@ -0,0 +1,108 @@
+// { dg-do run }
+
+extern "C" void abort (void);
+
+template <typename T>
+void
+foo ()
+{
+ extern T x;
+ T v, l = 2, s = 1;
+ #pragma omp atomic seq_cst
+ x = -3 + x;
+ #pragma omp atomic read seq_cst
+ v = x;
+ if (v != 3)
+ abort ();
+ #pragma omp atomic seq_cst update
+ x = 3 * 2 * 1 + x;
+ #pragma omp atomic read, seq_cst
+ v = x;
+ if (v != 9)
+ abort ();
+ #pragma omp atomic seq_cst, capture
+ v = x = x | 16;
+ if (v != 25)
+ abort ();
+ #pragma omp atomic capture seq_cst
+ v = x = x + 14 * 2 / 4;
+ if (v != 32)
+ abort ();
+ #pragma omp atomic seq_cst capture
+ v = x = 5 | x;
+ if (v != 37)
+ abort ();
+ #pragma omp atomic capture, seq_cst
+ v = x = 40 + 12 - 2 - 7 - x;
+ if (v != 6)
+ abort ();
+ #pragma omp atomic seq_cst read
+ v = x;
+ if (v != 6)
+ abort ();
+ #pragma omp atomic capture seq_cst
+ { v = x; x = 3 + x; }
+ if (v != 6)
+ abort ();
+ #pragma omp atomic seq_cst capture
+ { v = x; x = -1 * -1 * -1 * -1 - x; }
+ if (v != 9)
+ abort ();
+ #pragma omp atomic read seq_cst
+ v = x;
+ if (v != -8)
+ abort ();
+ #pragma omp atomic capture, seq_cst
+ { x = 2 * 2 - x; v = x; }
+ if (v != 12)
+ abort ();
+ #pragma omp atomic seq_cst capture
+ { x = 7 & x; v = x; }
+ if (v != 4)
+ abort ();
+ #pragma omp atomic capture seq_cst
+ { v = x; x = 6; }
+ if (v != 4)
+ abort ();
+ #pragma omp atomic read, seq_cst
+ v = x;
+ if (v != 6)
+ abort ();
+ #pragma omp atomic capture seq_cst
+ { v = x; x = 7 * 8 + 23; }
+ if (v != 6)
+ abort ();
+ #pragma omp atomic seq_cst, read
+ v = x;
+ if (v != 79)
+ abort ();
+ #pragma omp atomic capture , seq_cst
+ { v = x; x = 23 + 6 * 4; }
+ if (v != 79)
+ abort ();
+ #pragma omp atomic read seq_cst
+ v = x;
+ if (v != 47)
+ abort ();
+ #pragma omp atomic seq_cst capture
+ { v = x; x = l ? 17 : 12; }
+ if (v != 47)
+ abort ();
+ #pragma omp atomic capture seq_cst
+ { v = x; x = l = s++ + 3; }
+ if (v != 17 || l != 4 || s != 2)
+ abort ();
+ #pragma omp atomic read seq_cst
+ v = x;
+ if (v != 4)
+ abort ();
+}
+
+int x = 6;
+
+int
+main ()
+{
+ foo <int> ();
+ return 0;
+}
--- libgomp/testsuite/libgomp.c++/atomic-14.C.jj 2013-04-30 17:16:39.941131218 +0200
+++ libgomp/testsuite/libgomp.c++/atomic-14.C 2013-04-30 17:16:48.615079902 +0200
@@ -0,0 +1,99 @@
+// { dg-do run }
+
+extern "C" void abort (void);
+int x = 6;
+
+int
+main ()
+{
+ int v, l = 2, s = 1;
+ #pragma omp atomic seq_cst
+ x = -3 + x;
+ #pragma omp atomic read seq_cst
+ v = x;
+ if (v != 3)
+ abort ();
+ #pragma omp atomic seq_cst update
+ x = 3 * 2 * 1 + x;
+ #pragma omp atomic read, seq_cst
+ v = x;
+ if (v != 9)
+ abort ();
+ #pragma omp atomic seq_cst, capture
+ v = x = x | 16;
+ if (v != 25)
+ abort ();
+ #pragma omp atomic capture seq_cst
+ v = x = x + 14 * 2 / 4;
+ if (v != 32)
+ abort ();
+ #pragma omp atomic seq_cst capture
+ v = x = 5 | x;
+ if (v != 37)
+ abort ();
+ #pragma omp atomic capture, seq_cst
+ v = x = 40 + 12 - 2 - 7 - x;
+ if (v != 6)
+ abort ();
+ #pragma omp atomic seq_cst read
+ v = x;
+ if (v != 6)
+ abort ();
+ #pragma omp atomic capture seq_cst
+ { v = x; x = 3 + x; }
+ if (v != 6)
+ abort ();
+ #pragma omp atomic seq_cst capture
+ { v = x; x = -1 * -1 * -1 * -1 - x; }
+ if (v != 9)
+ abort ();
+ #pragma omp atomic read seq_cst
+ v = x;
+ if (v != -8)
+ abort ();
+ #pragma omp atomic capture, seq_cst
+ { x = 2 * 2 - x; v = x; }
+ if (v != 12)
+ abort ();
+ #pragma omp atomic seq_cst capture
+ { x = 7 & x; v = x; }
+ if (v != 4)
+ abort ();
+ #pragma omp atomic capture seq_cst
+ { v = x; x = 6; }
+ if (v != 4)
+ abort ();
+ #pragma omp atomic read, seq_cst
+ v = x;
+ if (v != 6)
+ abort ();
+ #pragma omp atomic capture seq_cst
+ { v = x; x = 7 * 8 + 23; }
+ if (v != 6)
+ abort ();
+ #pragma omp atomic seq_cst, read
+ v = x;
+ if (v != 79)
+ abort ();
+ #pragma omp atomic capture , seq_cst
+ { v = x; x = 23 + 6 * 4; }
+ if (v != 79)
+ abort ();
+ #pragma omp atomic read seq_cst
+ v = x;
+ if (v != 47)
+ abort ();
+ #pragma omp atomic seq_cst capture
+ { v = x; x = l ? 17 : 12; }
+ if (v != 47)
+ abort ();
+ #pragma omp atomic capture seq_cst
+ { v = x; x = l = s++ + 3; }
+ if (v != 17 || l != 4 || s != 2)
+ abort ();
+ #pragma omp atomic read seq_cst
+ v = x;
+ if (v != 4)
+ abort ();
+ return 0;
+}
--- libgomp/testsuite/libgomp.c/atomic-17.c.jj 2013-04-30 17:14:04.679028473 +0200
+++ libgomp/testsuite/libgomp.c/atomic-17.c 2013-04-30 17:16:00.834357522 +0200
@@ -0,0 +1,99 @@
+// { dg-do run }
+
+extern void abort (void);
+int x = 6;
+
+int
+main ()
+{
+ int v, l = 2, s = 1;
+ #pragma omp atomic seq_cst
+ x = -3 + x;
+ #pragma omp atomic read seq_cst
+ v = x;
+ if (v != 3)
+ abort ();
+ #pragma omp atomic seq_cst update
+ x = 3 * 2 * 1 + x;
+ #pragma omp atomic read, seq_cst
+ v = x;
+ if (v != 9)
+ abort ();
+ #pragma omp atomic seq_cst, capture
+ v = x = x | 16;
+ if (v != 25)
+ abort ();
+ #pragma omp atomic capture seq_cst
+ v = x = x + 14 * 2 / 4;
+ if (v != 32)
+ abort ();
+ #pragma omp atomic seq_cst capture
+ v = x = 5 | x;
+ if (v != 37)
+ abort ();
+ #pragma omp atomic capture, seq_cst
+ v = x = 40 + 12 - 2 - 7 - x;
+ if (v != 6)
+ abort ();
+ #pragma omp atomic seq_cst read
+ v = x;
+ if (v != 6)
+ abort ();
+ #pragma omp atomic capture seq_cst
+ { v = x; x = 3 + x; }
+ if (v != 6)
+ abort ();
+ #pragma omp atomic seq_cst capture
+ { v = x; x = -1 * -1 * -1 * -1 - x; }
+ if (v != 9)
+ abort ();
+ #pragma omp atomic read seq_cst
+ v = x;
+ if (v != -8)
+ abort ();
+ #pragma omp atomic capture, seq_cst
+ { x = 2 * 2 - x; v = x; }
+ if (v != 12)
+ abort ();
+ #pragma omp atomic seq_cst capture
+ { x = 7 & x; v = x; }
+ if (v != 4)
+ abort ();
+ #pragma omp atomic capture seq_cst
+ { v = x; x = 6; }
+ if (v != 4)
+ abort ();
+ #pragma omp atomic read, seq_cst
+ v = x;
+ if (v != 6)
+ abort ();
+ #pragma omp atomic capture seq_cst
+ { v = x; x = 7 * 8 + 23; }
+ if (v != 6)
+ abort ();
+ #pragma omp atomic seq_cst, read
+ v = x;
+ if (v != 79)
+ abort ();
+ #pragma omp atomic capture , seq_cst
+ { v = x; x = 23 + 6 * 4; }
+ if (v != 79)
+ abort ();
+ #pragma omp atomic read seq_cst
+ v = x;
+ if (v != 47)
+ abort ();
+ #pragma omp atomic seq_cst capture
+ { v = x; x = l ? 17 : 12; }
+ if (v != 47)
+ abort ();
+ #pragma omp atomic capture seq_cst
+ { v = x; x = l = s++ + 3; }
+ if (v != 17 || l != 4 || s != 2)
+ abort ();
+ #pragma omp atomic read seq_cst
+ v = x;
+ if (v != 4)
+ abort ();
+ return 0;
+}
Jakub