diff options
author | Jakub Jelinek <jakub@redhat.com> | 2021-09-17 11:28:31 +0200 |
---|---|---|
committer | Jakub Jelinek <jakub@redhat.com> | 2021-09-17 11:28:31 +0200 |
commit | 3a2bcffac602f5de56537a77db1062984bcefd45 (patch) | |
tree | ae688b9db0bfa75b79552f4d331ba4758e7a69cb /gcc/cp/semantics.c | |
parent | 48b3caffcacc99adf72ba1be189a7d9ebc4190be (diff) | |
download | gcc-3a2bcffac602f5de56537a77db1062984bcefd45.zip gcc-3a2bcffac602f5de56537a77db1062984bcefd45.tar.gz gcc-3a2bcffac602f5de56537a77db1062984bcefd45.tar.bz2 |
openmp: Add support for OpenMP 5.1 atomics for C++
Besides the C++ FE changes, I've noticed that the C FE didn't reject
#pragma omp atomic capture compare
{ v = x; x = y; }
and other forms of atomic swap, this patch fixes that too. And the
c-family/ routine needed quite a few changes so that the new code
in it works fine with both FEs.
2021-09-17 Jakub Jelinek <jakub@redhat.com>
gcc/c-family/
* c-omp.c (c_finish_omp_atomic): Avoid creating
TARGET_EXPR if test is true, use create_tmp_var_raw instead of
create_tmp_var and add a zero initializer to TARGET_EXPRs that
had NULL initializer. When omitting operands after v = x,
use type of v rather than type of x. Fix type of vtmp
TARGET_EXPR.
gcc/c/
* c-parser.c (c_parser_omp_atomic): Reject atomic swap if capture
is true.
gcc/cp/
* cp-tree.h (finish_omp_atomic): Add r and weak arguments.
* parser.c (cp_parser_omp_atomic): Update function comment for
OpenMP 5.1 atomics, parse OpenMP 5.1 atomics and fail, compare and
weak clauses.
* semantics.c (finish_omp_atomic): Add r and weak arguments, handle
them, handle COND_EXPRs.
* pt.c (tsubst_expr): Adjust for COND_EXPR forms that
finish_omp_atomic can now produce.
gcc/testsuite/
* c-c++-common/gomp/atomic-18.c: Expect same diagnostics in C++ as in
C.
* c-c++-common/gomp/atomic-25.c: Drop c effective target.
* c-c++-common/gomp/atomic-26.c: Likewise.
* c-c++-common/gomp/atomic-27.c: Likewise.
* c-c++-common/gomp/atomic-28.c: Likewise.
* c-c++-common/gomp/atomic-29.c: Likewise.
* c-c++-common/gomp/atomic-30.c: Likewise. Adjust expected diagnostics
for C++ when it differs from C.
(foo): Change return type from double to void.
* g++.dg/gomp/atomic-5.C: Adjust expected diagnostics wording.
* g++.dg/gomp/atomic-20.C: New test.
libgomp/
* testsuite/libgomp.c-c++-common/atomic-19.c: Drop c effective target.
Use /* */ comments instead of //.
* testsuite/libgomp.c-c++-common/atomic-20.c: Likewise.
* testsuite/libgomp.c-c++-common/atomic-21.c: Likewise.
* testsuite/libgomp.c++/atomic-16.C: New test.
* testsuite/libgomp.c++/atomic-17.C: New test.
Diffstat (limited to 'gcc/cp/semantics.c')
-rw-r--r-- | gcc/cp/semantics.c | 31 |
1 files changed, 25 insertions, 6 deletions
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 94e6b18..35a7b9f 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -9877,14 +9877,15 @@ finish_omp_for_block (tree bind, tree omp_for) void finish_omp_atomic (location_t loc, enum tree_code code, enum tree_code opcode, - tree lhs, tree rhs, tree v, tree lhs1, tree rhs1, - tree clauses, enum omp_memory_order mo) + tree lhs, tree rhs, tree v, tree lhs1, tree rhs1, tree r, + tree clauses, enum omp_memory_order mo, bool weak) { tree orig_lhs; tree orig_rhs; tree orig_v; tree orig_lhs1; tree orig_rhs1; + tree orig_r; bool dependent_p; tree stmt; @@ -9893,6 +9894,7 @@ finish_omp_atomic (location_t loc, enum tree_code code, enum tree_code opcode, orig_v = v; orig_lhs1 = lhs1; orig_rhs1 = rhs1; + orig_r = r; dependent_p = false; stmt = NULL_TREE; @@ -9904,7 +9906,10 @@ finish_omp_atomic (location_t loc, enum tree_code code, enum tree_code opcode, || (rhs && type_dependent_expression_p (rhs)) || (v && type_dependent_expression_p (v)) || (lhs1 && type_dependent_expression_p (lhs1)) - || (rhs1 && type_dependent_expression_p (rhs1))); + || (rhs1 && type_dependent_expression_p (rhs1)) + || (r + && r != void_list_node + && type_dependent_expression_p (r))); if (clauses) { gcc_assert (TREE_CODE (clauses) == OMP_CLAUSE @@ -9925,17 +9930,19 @@ finish_omp_atomic (location_t loc, enum tree_code code, enum tree_code opcode, lhs1 = build_non_dependent_expr (lhs1); if (rhs1) rhs1 = build_non_dependent_expr (rhs1); + if (r && r != void_list_node) + r = build_non_dependent_expr (r); } } if (!dependent_p) { bool swapped = false; - if (rhs1 && cp_tree_equal (lhs, rhs)) + if (rhs1 && opcode != COND_EXPR && cp_tree_equal (lhs, rhs)) { std::swap (rhs, rhs1); swapped = !commutative_tree_code (opcode); } - if (rhs1 && !cp_tree_equal (lhs, rhs1)) + if (rhs1 && opcode != COND_EXPR && !cp_tree_equal (lhs, rhs1)) { if (code == OMP_ATOMIC) error ("%<#pragma omp atomic update%> uses two different " @@ -9956,7 +9963,7 @@ finish_omp_atomic (location_t loc, enum tree_code code, enum tree_code opcode, return; } stmt = c_finish_omp_atomic (loc, code, opcode, lhs, rhs, - v, lhs1, rhs1, NULL_TREE, swapped, mo, false, + v, lhs1, rhs1, r, swapped, mo, weak, processing_template_decl != 0); if (stmt == error_mark_node) return; @@ -9973,6 +9980,16 @@ finish_omp_atomic (location_t loc, enum tree_code code, enum tree_code opcode, { if (opcode == NOP_EXPR) stmt = build2 (MODIFY_EXPR, void_type_node, orig_lhs, orig_rhs); + else if (opcode == COND_EXPR) + { + stmt = build2 (EQ_EXPR, boolean_type_node, orig_lhs, orig_rhs); + if (orig_r) + stmt = build2 (MODIFY_EXPR, boolean_type_node, orig_r, + stmt); + stmt = build3 (COND_EXPR, void_type_node, stmt, orig_rhs1, + orig_lhs); + orig_rhs1 = NULL_TREE; + } else stmt = build2 (opcode, void_type_node, orig_lhs, orig_rhs); if (orig_rhs1) @@ -9982,12 +9999,14 @@ finish_omp_atomic (location_t loc, enum tree_code code, enum tree_code opcode, { stmt = build_min_nt_loc (loc, code, orig_lhs1, stmt); OMP_ATOMIC_MEMORY_ORDER (stmt) = mo; + OMP_ATOMIC_WEAK (stmt) = weak; stmt = build2 (MODIFY_EXPR, void_type_node, orig_v, stmt); } } stmt = build2 (OMP_ATOMIC, void_type_node, clauses ? clauses : integer_zero_node, stmt); OMP_ATOMIC_MEMORY_ORDER (stmt) = mo; + OMP_ATOMIC_WEAK (stmt) = weak; SET_EXPR_LOCATION (stmt, loc); } |