summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>2013-04-30 16:07:01 +0000
committerjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>2013-04-30 16:07:01 +0000
commitd22e24666757a3e0e1ff5b4616d98898b1df8315 (patch)
treed2224db77ecb418a2d96f3990a99d95d752d8b25
parent740af7171c00b73643a8f8560905e5355b33f41d (diff)
downloadgcc-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.gomp14
-rw-r--r--gcc/c-family/ChangeLog.gomp4
-rw-r--r--gcc/c-family/c-common.h2
-rw-r--r--gcc/c-family/c-omp.c4
-rw-r--r--gcc/c/ChangeLog.gomp5
-rw-r--r--gcc/c/c-parser.c32
-rw-r--r--gcc/cp/ChangeLog.gomp9
-rw-r--r--gcc/cp/cp-tree.h3
-rw-r--r--gcc/cp/parser.c35
-rw-r--r--gcc/cp/pt.c6
-rw-r--r--gcc/cp/semantics.c7
-rw-r--r--gcc/gimple-pretty-print.c4
-rw-r--r--gcc/gimple.h24
-rw-r--r--gcc/gimplify.c7
-rw-r--r--gcc/omp-low.c16
-rw-r--r--gcc/tree-pretty-print.c6
-rw-r--r--gcc/tree.def3
-rw-r--r--gcc/tree.h9
-rw-r--r--libgomp/ChangeLog.gomp6
-rw-r--r--libgomp/testsuite/libgomp.c++/atomic-14.C99
-rw-r--r--libgomp/testsuite/libgomp.c++/atomic-15.C108
-rw-r--r--libgomp/testsuite/libgomp.c/atomic-17.c99
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;
+}