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 <ja...@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