diff options
author | jakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4> | 2013-04-30 16:07:01 +0000 |
---|---|---|
committer | jakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4> | 2013-04-30 16:07:01 +0000 |
commit | d22e24666757a3e0e1ff5b4616d98898b1df8315 (patch) | |
tree | d2224db77ecb418a2d96f3990a99d95d752d8b25 | |
parent | 740af7171c00b73643a8f8560905e5355b33f41d (diff) | |
download | gcc-d22e24666757a3e0e1ff5b4616d98898b1df8315.tar.gz |
* 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.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/gomp-4_0-branch@198461 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r-- | gcc/ChangeLog.gomp | 14 | ||||
-rw-r--r-- | gcc/c-family/ChangeLog.gomp | 4 | ||||
-rw-r--r-- | gcc/c-family/c-common.h | 2 | ||||
-rw-r--r-- | gcc/c-family/c-omp.c | 4 | ||||
-rw-r--r-- | gcc/c/ChangeLog.gomp | 5 | ||||
-rw-r--r-- | gcc/c/c-parser.c | 32 | ||||
-rw-r--r-- | gcc/cp/ChangeLog.gomp | 9 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 3 | ||||
-rw-r--r-- | gcc/cp/parser.c | 35 | ||||
-rw-r--r-- | gcc/cp/pt.c | 6 | ||||
-rw-r--r-- | gcc/cp/semantics.c | 7 | ||||
-rw-r--r-- | gcc/gimple-pretty-print.c | 4 | ||||
-rw-r--r-- | gcc/gimple.h | 24 | ||||
-rw-r--r-- | gcc/gimplify.c | 7 | ||||
-rw-r--r-- | gcc/omp-low.c | 16 | ||||
-rw-r--r-- | gcc/tree-pretty-print.c | 6 | ||||
-rw-r--r-- | gcc/tree.def | 3 | ||||
-rw-r--r-- | gcc/tree.h | 9 | ||||
-rw-r--r-- | libgomp/ChangeLog.gomp | 6 | ||||
-rw-r--r-- | libgomp/testsuite/libgomp.c++/atomic-14.C | 99 | ||||
-rw-r--r-- | libgomp/testsuite/libgomp.c++/atomic-15.C | 108 | ||||
-rw-r--r-- | libgomp/testsuite/libgomp.c/atomic-17.c | 99 |
22 files changed, 489 insertions, 13 deletions
diff --git a/gcc/ChangeLog.gomp b/gcc/ChangeLog.gomp index c8d5f76f564..3802a119cfa 100644 --- a/gcc/ChangeLog.gomp +++ b/gcc/ChangeLog.gomp @@ -1,5 +1,19 @@ 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. + * omp-low.c (check_omp_nesting_restrictions): Diagnose OpenMP constructs nested inside simd region. Don't treat #pragma omp simd as work-sharing region. Disallow work-sharing diff --git a/gcc/c-family/ChangeLog.gomp b/gcc/c-family/ChangeLog.gomp index 6bf1bfd8e44..9ed6de1a55f 100644 --- a/gcc/c-family/ChangeLog.gomp +++ b/gcc/c-family/ChangeLog.gomp @@ -1,5 +1,9 @@ 2013-04-30 Jakub Jelinek <jakub@redhat.com> + * 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. + * c-pragma.c (omp_pragmas): Add PRAGMA_OMP_DISTRIBUTE. 2013-04-10 Jakub Jelinek <jakub@redhat.com> diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h index 57f2f6062f7..ea2600cda21 100644 --- a/gcc/c-family/c-common.h +++ b/gcc/c-family/c-common.h @@ -1035,7 +1035,7 @@ extern tree c_finish_omp_critical (location_t, tree, tree); 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); diff --git a/gcc/c-family/c-omp.c b/gcc/c-family/c-omp.c index 06a2da28fe2..d8edcf8145f 100644 --- a/gcc/c-family/c-omp.c +++ b/gcc/c-family/c-omp.c @@ -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, enum tree_code code, { 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, enum tree_code code, 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. */ diff --git a/gcc/c/ChangeLog.gomp b/gcc/c/ChangeLog.gomp index 83c2f14baf0..3e1f7156faa 100644 --- a/gcc/c/ChangeLog.gomp +++ b/gcc/c/ChangeLog.gomp @@ -1,3 +1,8 @@ +2013-04-30 Jakub Jelinek <jakub@redhat.com> + + * c-parser.c (c_parser_omp_atomic): Parse seq_cst clause, pass + true if it is present to c_finish_omp_atomic. + 2013-04-24 Jakub Jelinek <jakub@redhat.com> * c-parser.c (c_parser_compound_statement, diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c index eea10811f0d..58e53d56294 100644 --- a/gcc/c/c-parser.c +++ b/gcc/c/c-parser.c @@ -10218,10 +10218,23 @@ c_parser_omp_atomic (location_t loc, c_parser *parser) 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_parser *parser) 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); diff --git a/gcc/cp/ChangeLog.gomp b/gcc/cp/ChangeLog.gomp index ac49b6e603b..aa7d736e47d 100644 --- a/gcc/cp/ChangeLog.gomp +++ b/gcc/cp/ChangeLog.gomp @@ -1,3 +1,12 @@ +2013-04-30 Jakub Jelinek <jakub@redhat.com> + + * 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. + 2013-04-24 Jakub Jelinek <jakub@redhat.com> * parser.c (cp_parser_omp_clause_name): Add missing break after diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index bb0a4ae72ce..f99a8e67a48 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -5713,7 +5713,8 @@ extern tree finish_omp_for (location_t, enum tree_code, 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); diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index bcee34589bc..943764c3d54 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -27146,12 +27146,27 @@ cp_parser_omp_atomic (cp_parser *parser, cp_token *pragma_tok) 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")) @@ -27165,6 +27180,24 @@ cp_parser_omp_atomic (cp_parser *parser, cp_token *pragma_tok) 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) @@ -27471,7 +27504,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; diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 7ddb6a31dbc..a225849359c 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -13276,7 +13276,8 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl, 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_flags_t complain, tree in_decl, 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; diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 96e6c538d11..004d690d59b 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -5221,7 +5221,7 @@ finish_omp_for (location_t locus, enum tree_code code, tree declv, tree initv, 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, enum tree_code opcode, tree lhs, 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, enum tree_code opcode, tree lhs, { 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, enum tree_code opcode, tree lhs, { 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); } diff --git a/gcc/gimple-pretty-print.c b/gcc/gimple-pretty-print.c index 2f3926d982f..28baa411b4b 100644 --- a/gcc/gimple-pretty-print.c +++ b/gcc/gimple-pretty-print.c @@ -1805,6 +1805,8 @@ dump_gimple_omp_atomic_load (pretty_printer *buffer, gimple gs, int spc, 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_printer *buffer, gimple gs, int spc, 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, '('); diff --git a/gcc/gimple.h b/gcc/gimple.h index d25289f88b1..36ad626c9aa 100644 --- a/gcc/gimple.h +++ b/gcc/gimple.h @@ -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 g) } +/* 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 diff --git a/gcc/gimplify.c b/gcc/gimplify.c index f990fac6210..7488706de0e 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -7076,6 +7076,11 @@ gimplify_omp_atomic (tree *expr_p, gimple_seq *pre_p) 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, gimple_seq *pre_p) break; } - return GS_ALL_DONE; + return GS_ALL_DONE; } /* Gimplify a TRANSACTION_EXPR. This involves gimplification of the diff --git a/gcc/omp-low.c b/gcc/omp-low.c index ea46d76e65a..b320817b567 100644 --- a/gcc/omp-low.c +++ b/gcc/omp-low.c @@ -5472,7 +5472,10 @@ expand_omp_atomic_load (basic_block load_bb, tree addr, 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 load_bb, tree addr, 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 load_bb, 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 load_bb, 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 load_bb, 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) { diff --git a/gcc/tree-pretty-print.c b/gcc/tree-pretty-print.c index f3de68c1d91..0c3fec75d04 100644 --- a/gcc/tree-pretty-print.c +++ b/gcc/tree-pretty-print.c @@ -2431,6 +2431,8 @@ dump_generic_node (pretty_printer *buffer, tree node, int spc, int flags, 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 *buffer, tree node, int spc, int flags, 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 *buffer, tree node, int spc, int flags, 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); diff --git a/gcc/tree.def b/gcc/tree.def index 92df7d721ce..147b6805b0a 100644 --- a/gcc/tree.def +++ b/gcc/tree.def @@ -1069,6 +1069,9 @@ DEFTREECODE (OMP_ORDERED, "omp_ordered", tcc_statement, 1) 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. diff --git a/gcc/tree.h b/gcc/tree.h index b4bd6c490f4..46bb2b415cb 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -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 (tree, location_t); #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. */ diff --git a/libgomp/ChangeLog.gomp b/libgomp/ChangeLog.gomp index d62cdc93055..e01eaa946d2 100644 --- a/libgomp/ChangeLog.gomp +++ b/libgomp/ChangeLog.gomp @@ -1,3 +1,9 @@ +2013-04-30 Jakub Jelinek <jakub@redhat.com> + + * testsuite/libgomp.c/atomic-17.c: New test. + * testsuite/libgomp.c++/atomic-14.C: New test. + * testsuite/libgomp.c++/atomic-15.C: New test. + 2013-04-10 Jakub Jelinek <jakub@redhat.com> * libgomp.map (omp_get_cancellation, omp_get_cancellation_, diff --git a/libgomp/testsuite/libgomp.c++/atomic-14.C b/libgomp/testsuite/libgomp.c++/atomic-14.C new file mode 100644 index 00000000000..dccea3acd80 --- /dev/null +++ b/libgomp/testsuite/libgomp.c++/atomic-14.C @@ -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; +} diff --git a/libgomp/testsuite/libgomp.c++/atomic-15.C b/libgomp/testsuite/libgomp.c++/atomic-15.C new file mode 100644 index 00000000000..9abefb64688 --- /dev/null +++ b/libgomp/testsuite/libgomp.c++/atomic-15.C @@ -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; +} diff --git a/libgomp/testsuite/libgomp.c/atomic-17.c b/libgomp/testsuite/libgomp.c/atomic-17.c new file mode 100644 index 00000000000..147ab26a953 --- /dev/null +++ b/libgomp/testsuite/libgomp.c/atomic-17.c @@ -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; +} |