2021-09-17 11:28:31 +02:00
|
|
|
/* { dg-do run } */
|
openmp: Implement OpenMP 5.1 atomics, so far for C only
This patch implements OpenMP 5.1 atomics (with clarifications from upcoming 5.2).
The most important changes are that it is now possible to write (for C/C++,
for Fortran it was possible before already) min/max atomics and more importantly
compare and exchange in various forms.
Also, acq_rel is now allowed on read/write and acq_rel/acquire are allowed on
update, and there are new compare, weak and fail clauses.
2021-09-10 Jakub Jelinek <jakub@redhat.com>
gcc/
* tree-core.h (enum omp_memory_order): Add OMP_MEMORY_ORDER_MASK,
OMP_FAIL_MEMORY_ORDER_UNSPECIFIED, OMP_FAIL_MEMORY_ORDER_RELAXED,
OMP_FAIL_MEMORY_ORDER_ACQUIRE, OMP_FAIL_MEMORY_ORDER_RELEASE,
OMP_FAIL_MEMORY_ORDER_ACQ_REL, OMP_FAIL_MEMORY_ORDER_SEQ_CST and
OMP_FAIL_MEMORY_ORDER_MASK enumerators.
(OMP_FAIL_MEMORY_ORDER_SHIFT): Define.
* gimple-pretty-print.c (dump_gimple_omp_atomic_load,
dump_gimple_omp_atomic_store): Print [weak] for weak atomic
load/store.
* gimple.h (enum gf_mask): Change GF_OMP_ATOMIC_MEMORY_ORDER
to 6-bit mask, adjust GF_OMP_ATOMIC_NEED_VALUE value and add
GF_OMP_ATOMIC_WEAK.
(gimple_omp_atomic_weak_p, gimple_omp_atomic_set_weak): New inline
functions.
* tree.h (OMP_ATOMIC_WEAK): Define.
* tree-pretty-print.c (dump_omp_atomic_memory_order): Adjust for
fail memory order being encoded in the same enum and also print
fail clause if present.
(dump_generic_node): Print weak clause if OMP_ATOMIC_WEAK.
* gimplify.c (goa_stabilize_expr): Add target_expr and rhs arguments,
handle pre_p == NULL case as a test mode that only returns value
but doesn't change gimplify nor change anything otherwise, adjust
recursive calls, add MODIFY_EXPR, ADDR_EXPR, COND_EXPR, TARGET_EXPR
and CALL_EXPR handling, adjust COMPOUND_EXPR handling for
__builtin_clear_padding calls, for !rhs gimplify as lvalue rather
than rvalue.
(gimplify_omp_atomic): Adjust goa_stabilize_expr caller. Handle
COND_EXPR rhs. Set weak flag on gimple load/store for
OMP_ATOMIC_WEAK.
* omp-expand.c (omp_memory_order_to_fail_memmodel): New function.
(omp_memory_order_to_memmodel): Adjust for fail clause encoded
in the same enum.
(expand_omp_atomic_cas): New function.
(expand_omp_atomic_pipeline): Use omp_memory_order_to_fail_memmodel
function.
(expand_omp_atomic): Attempt to optimize atomic compare and exchange
using expand_omp_atomic_cas.
gcc/c-family/
* c-common.h (c_finish_omp_atomic): Add r and weak arguments.
* c-omp.c: Include gimple-fold.h.
(c_finish_omp_atomic): Add r and weak arguments. Add support for
OpenMP 5.1 atomics.
gcc/c/
* c-parser.c (c_parser_conditional_expression): If omp_atomic_lhs and
cond.value is >, < or == with omp_atomic_lhs as one of the operands,
don't call build_conditional_expr, instead build a COND_EXPR directly.
(c_parser_binary_expression): Avoid calling parser_build_binary_op
if omp_atomic_lhs even in more cases for >, < or ==.
(c_parser_omp_atomic): Update function comment for OpenMP 5.1 atomics,
parse OpenMP 5.1 atomics and fail, compare and weak clauses, allow
acq_rel on atomic read/write and acq_rel/acquire clauses on update.
* c-typeck.c (build_binary_op): For flag_openmp only handle
MIN_EXPR/MAX_EXPR.
gcc/cp/
* parser.c (cp_parser_omp_atomic): Allow acq_rel on atomic read/write
and acq_rel/acquire clauses on update.
* semantics.c (finish_omp_atomic): Adjust c_finish_omp_atomic caller.
gcc/testsuite/
* c-c++-common/gomp/atomic-17.c (foo): Add tests for atomic read,
write or update with acq_rel clause and atomic update with acquire clause.
* c-c++-common/gomp/atomic-18.c (foo): Adjust expected diagnostics
wording, remove tests moved to atomic-17.c.
* c-c++-common/gomp/atomic-21.c: Expect only 2 omp atomic release and
2 omp atomic acq_rel directives instead of 4 omp atomic release.
* c-c++-common/gomp/atomic-25.c: New test.
* c-c++-common/gomp/atomic-26.c: New test.
* c-c++-common/gomp/atomic-27.c: New test.
* c-c++-common/gomp/atomic-28.c: New test.
* c-c++-common/gomp/atomic-29.c: New test.
* c-c++-common/gomp/atomic-30.c: New test.
* c-c++-common/goacc-gomp/atomic.c: Expect 1 omp atomic release and
1 omp atomic_acq_rel instead of 2 omp atomic release directives.
* gcc.dg/gomp/atomic-5.c: Adjust expected error diagnostic wording.
* g++.dg/gomp/atomic-18.C:Expect 4 omp atomic release and
1 omp atomic_acq_rel instead of 5 omp atomic release directives.
libgomp/
* testsuite/libgomp.c-c++-common/atomic-19.c: New test.
* testsuite/libgomp.c-c++-common/atomic-20.c: New test.
* testsuite/libgomp.c-c++-common/atomic-21.c: New test.
2021-09-10 20:41:33 +02:00
|
|
|
|
|
|
|
extern
|
|
|
|
#ifdef __cplusplus
|
|
|
|
"C"
|
|
|
|
#endif
|
|
|
|
void abort (void);
|
|
|
|
int x = 6;
|
|
|
|
int w, y;
|
|
|
|
|
|
|
|
int *
|
|
|
|
foo (void)
|
|
|
|
{
|
|
|
|
if (w)
|
|
|
|
abort ();
|
|
|
|
return &y;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
main ()
|
|
|
|
{
|
|
|
|
int v, r;
|
|
|
|
#pragma omp atomic compare
|
|
|
|
x = x > 8 ? 8 : x;
|
|
|
|
#pragma omp atomic read
|
|
|
|
v = x;
|
|
|
|
if (v != 6)
|
|
|
|
abort ();
|
|
|
|
#pragma omp atomic compare
|
|
|
|
x = x > 4 ? 4 : x;
|
|
|
|
#pragma omp atomic read
|
|
|
|
v = x;
|
|
|
|
if (v != 4)
|
|
|
|
abort ();
|
|
|
|
#pragma omp atomic compare capture
|
|
|
|
v = x = x < 8 ? 8 : x;
|
|
|
|
if (v != 8)
|
|
|
|
abort ();
|
|
|
|
#pragma omp atomic read
|
|
|
|
v = x;
|
|
|
|
if (v != 8)
|
|
|
|
abort ();
|
|
|
|
#pragma omp atomic capture compare
|
|
|
|
{ v = x; x = x < 12 ? 12 : x; }
|
|
|
|
if (v != 8)
|
|
|
|
abort ();
|
|
|
|
#pragma omp atomic read
|
|
|
|
v = x;
|
|
|
|
if (v != 12)
|
|
|
|
abort ();
|
|
|
|
#pragma omp atomic capture compare
|
|
|
|
{ v = x; x = x < 4 ? 4 : x; }
|
|
|
|
if (v != 12)
|
|
|
|
abort ();
|
|
|
|
#pragma omp atomic read
|
|
|
|
v = x;
|
|
|
|
if (v != 12)
|
|
|
|
abort ();
|
|
|
|
#pragma omp atomic write
|
|
|
|
x = -32;
|
|
|
|
#pragma omp atomic capture compare seq_cst fail(relaxed)
|
|
|
|
{ x = 12U < x ? 12U : x; v = x; }
|
|
|
|
if (v != 12)
|
|
|
|
abort ();
|
|
|
|
#pragma omp atomic read
|
|
|
|
v = x;
|
|
|
|
if (v != 12)
|
|
|
|
abort ();
|
|
|
|
#pragma omp atomic compare
|
|
|
|
x = x == 12 ? 16 : x;
|
|
|
|
#pragma omp atomic read
|
|
|
|
v = x;
|
|
|
|
if (v != 16)
|
|
|
|
abort ();
|
|
|
|
r = 57;
|
|
|
|
#pragma omp atomic compare capture
|
|
|
|
v = x = x == 15 ? r + 7 : x;
|
|
|
|
if (v != 16)
|
|
|
|
abort ();
|
|
|
|
#pragma omp atomic read
|
|
|
|
v = x;
|
|
|
|
if (v != 16)
|
|
|
|
abort ();
|
|
|
|
#pragma omp atomic capture, update, compare seq_cst fail(acquire)
|
|
|
|
{ v = x; x = x == 73ULL - r ? 12LL : x; }
|
|
|
|
if (v != 16)
|
|
|
|
abort ();
|
|
|
|
#pragma omp atomic read
|
|
|
|
v = x;
|
|
|
|
if (v != 12)
|
|
|
|
abort ();
|
|
|
|
#pragma omp atomic update, compare, capture
|
|
|
|
{ x = x == 69LL - r ? (unsigned char) 6 : x; v = x; }
|
|
|
|
if (v != 6)
|
|
|
|
abort ();
|
|
|
|
#pragma omp atomic read
|
|
|
|
v = x;
|
|
|
|
if (v != 6)
|
|
|
|
abort ();
|
|
|
|
#pragma omp atomic compare
|
|
|
|
if (x > 8) { x = 8; }
|
|
|
|
#pragma omp atomic read
|
|
|
|
v = x;
|
|
|
|
if (v != 6)
|
|
|
|
abort ();
|
|
|
|
#pragma omp atomic compare
|
|
|
|
if (x > 4) { x = 4; }
|
|
|
|
#pragma omp atomic read
|
|
|
|
v = x;
|
|
|
|
if (v != 4)
|
|
|
|
abort ();
|
|
|
|
#pragma omp atomic compare capture
|
|
|
|
{ if (x < 8) { x = 8; } v = x; }
|
|
|
|
if (v != 8)
|
|
|
|
abort ();
|
|
|
|
#pragma omp atomic read
|
|
|
|
v = x;
|
|
|
|
if (v != 8)
|
|
|
|
abort ();
|
|
|
|
#pragma omp atomic capture compare
|
|
|
|
{ v = x; if (x < 12) { x = 12; } }
|
|
|
|
if (v != 8)
|
|
|
|
abort ();
|
|
|
|
#pragma omp atomic read
|
|
|
|
v = x;
|
|
|
|
if (v != 12)
|
|
|
|
abort ();
|
|
|
|
#pragma omp atomic capture compare
|
|
|
|
{ v = x; if (x < 4) { x = 4; } }
|
|
|
|
if (v != 12)
|
|
|
|
abort ();
|
|
|
|
#pragma omp atomic read
|
|
|
|
v = x;
|
|
|
|
if (v != 12)
|
|
|
|
abort ();
|
|
|
|
#pragma omp atomic write
|
|
|
|
x = -32;
|
|
|
|
#pragma omp atomic capture compare seq_cst fail(relaxed)
|
|
|
|
{ if (12U < x) { x = 12U; } v = x; }
|
|
|
|
if (v != 12)
|
|
|
|
abort ();
|
|
|
|
#pragma omp atomic read
|
|
|
|
v = x;
|
|
|
|
if (v != 12)
|
|
|
|
abort ();
|
|
|
|
#pragma omp atomic compare
|
|
|
|
if (x == 12) { x = 16; }
|
|
|
|
#pragma omp atomic read
|
|
|
|
v = x;
|
|
|
|
if (v != 16)
|
|
|
|
abort ();
|
|
|
|
r = 57;
|
|
|
|
#pragma omp atomic compare capture
|
|
|
|
{ if (x == 15) { x = r + 7; } v = x; }
|
|
|
|
if (v != 16)
|
|
|
|
abort ();
|
|
|
|
#pragma omp atomic read
|
|
|
|
v = x;
|
|
|
|
if (v != 16)
|
|
|
|
abort ();
|
|
|
|
#pragma omp atomic capture, update, compare seq_cst fail(acquire)
|
|
|
|
{ v = x; if (x == 73ULL - r) { x = 12LL; } }
|
|
|
|
if (v != 16)
|
|
|
|
abort ();
|
|
|
|
#pragma omp atomic read
|
|
|
|
v = x;
|
|
|
|
if (v != 12)
|
|
|
|
abort ();
|
|
|
|
#pragma omp atomic update, compare, capture
|
|
|
|
{ if (x == 69LL - r) { x = (unsigned char) 6; } v = x; }
|
|
|
|
if (v != 6)
|
|
|
|
abort ();
|
|
|
|
#pragma omp atomic read
|
|
|
|
v = x;
|
|
|
|
if (v != 6)
|
|
|
|
abort ();
|
|
|
|
v = 24;
|
|
|
|
#pragma omp atomic compare capture
|
|
|
|
if (x == 12) { x = 16; } else { v = x; }
|
|
|
|
if (v != 6)
|
|
|
|
abort ();
|
|
|
|
v = 32;
|
|
|
|
#pragma omp atomic read
|
|
|
|
v = x;
|
|
|
|
if (v != 6)
|
|
|
|
abort ();
|
|
|
|
v = 147;
|
|
|
|
#pragma omp atomic capture compare
|
|
|
|
if (x == 6) { x = 57; } else { v = x; }
|
|
|
|
if (v != 147)
|
|
|
|
abort ();
|
|
|
|
#pragma omp atomic read
|
|
|
|
v = x;
|
|
|
|
if (v != 57)
|
|
|
|
abort ();
|
|
|
|
#pragma omp atomic update, capture, compare, weak, seq_cst, fail (relaxed)
|
|
|
|
{ r = x == 137; if (r) { x = 174; } }
|
|
|
|
if (r)
|
|
|
|
abort ();
|
|
|
|
#pragma omp atomic read
|
|
|
|
v = x;
|
|
|
|
if (v != 57)
|
|
|
|
abort ();
|
|
|
|
#pragma omp atomic compare capture fail (relaxed)
|
|
|
|
{ r = x == 57; if (r) { x = 6; } }
|
|
|
|
if (r != 1)
|
|
|
|
abort ();
|
|
|
|
#pragma omp atomic read
|
|
|
|
v = x;
|
|
|
|
if (v != 6)
|
|
|
|
abort ();
|
|
|
|
v = -5;
|
|
|
|
#pragma omp atomic capture compare
|
|
|
|
{ r = x == 17; if (r) { x = 25; } else { v = x; } }
|
|
|
|
if (r || v != 6)
|
|
|
|
abort ();
|
|
|
|
#pragma omp atomic read
|
|
|
|
v = x;
|
|
|
|
if (v != 6)
|
|
|
|
abort ();
|
|
|
|
v = 15;
|
|
|
|
#pragma omp atomic capture compare
|
|
|
|
{ r = x == 6; if (r) { x = 23; } else { v = x; } }
|
|
|
|
if (r != 1 || v != 15)
|
|
|
|
abort ();
|
|
|
|
#pragma omp atomic read
|
|
|
|
v = x;
|
|
|
|
if (v != 23)
|
|
|
|
abort ();
|
|
|
|
w = 1;
|
|
|
|
#pragma omp atomic compare capture
|
|
|
|
if (x == 23) { x = 57; } else { foo ()[0] = x; }
|
|
|
|
#pragma omp atomic read
|
|
|
|
v = x;
|
|
|
|
if (v != 57)
|
|
|
|
abort ();
|
|
|
|
#pragma omp atomic capture update compare
|
|
|
|
{ r = x == 57; if (r) { x = 23; } else { foo ()[0] = x; } }
|
|
|
|
if (r != 1)
|
|
|
|
abort ();
|
|
|
|
#pragma omp atomic read
|
|
|
|
v = x;
|
|
|
|
if (v != 23)
|
|
|
|
abort ();
|
|
|
|
w = 0;
|
|
|
|
#pragma omp atomic compare capture
|
|
|
|
if (x == 24) { x = 57; } else { foo ()[0] = x; }
|
|
|
|
if (y != 23)
|
|
|
|
abort ();
|
|
|
|
#pragma omp atomic read
|
|
|
|
v = x;
|
|
|
|
if (v != 23)
|
|
|
|
abort ();
|
|
|
|
y = -5;
|
|
|
|
#pragma omp atomic capture update compare
|
|
|
|
{
|
|
|
|
r = x == 57;
|
|
|
|
if (r)
|
|
|
|
{
|
|
|
|
x = 27;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
foo ()[0] = x;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (r || y != 23)
|
|
|
|
abort ();
|
|
|
|
#pragma omp atomic read
|
|
|
|
v = x;
|
|
|
|
if (v != 23)
|
|
|
|
abort ();
|
|
|
|
return 0;
|
|
|
|
}
|