When lowering reduction clauses, the compiler brackets the critical section
around the accumulation step with calls to GOMP_atomic_start and
GOMP_atomic_end. These are the same entry points used for `#pragma omp atomic'
constructs, so OMPT cannot distinguish reductions from user atomics.
Introduce dedicated GOMP_reduction_start and GOMP_reduction_end entry
points in libgomp. Update omp-low to emit calls to the new builtins
instead.
Also register the new builtins as memory barriers to avoid illegal optimisations
in later passes.
gcc/ChangeLog:
* omp-builtins.def (BUILT_IN_GOMP_REDUCTION_START): New builtin.
(BUILT_IN_GOMP_REDUCTION_END): New builtin.
* omp-low.cc (lower_reduction_clauses): Replace
BUILT_IN_GOMP_ATOMIC_START / BUILT_IN_GOMP_ATOMIC_END with
BUILT_IN_GOMP_REDUCTION_START / BUILT_IN_GOMP_REDUCTION_END.
(lower_omp_sections): Likewise.
(lower_omp_scope): Likewise.
(lower_omp_for): Likewise.
* tree-ssa-alias.cc (check_fnspec): Handle
BUILT_IN_GOMP_REDUCTION_START and BUILT_IN_GOMP_REDUCTION_END as
memory barriers.
libgomp/ChangeLog:
* atomic.c (GOMP_reduction_start): New function.
(GOMP_reduction_end): New function.
* libgomp.map (GOMP_6.0.2): Export GOMP_reduction_start and
GOMP_reduction_end.
* libgomp_g.h (GOMP_reduction_start): New declaration.
(GOMP_reduction_end): New declaration.
gcc/testsuite/ChangeLog:
* c-c++-common/gomp/reduction-builtins-1.c: New test.
---
gcc/omp-builtins.def | 4 ++
gcc/omp-low.cc | 19 ++++----
.../c-c++-common/gomp/reduction-builtins-1.c | 47 +++++++++++++++++++
gcc/tree-ssa-alias.cc | 2 +
libgomp/atomic.c | 12 +++++
libgomp/libgomp.map | 2 +
libgomp/libgomp_g.h | 2 +
7 files changed, 79 insertions(+), 9 deletions(-)
create mode 100644 gcc/testsuite/c-c++-common/gomp/reduction-builtins-1.c
diff --git a/gcc/omp-builtins.def b/gcc/omp-builtins.def
index b88cc49d6b9..c77ff385de5 100644
--- a/gcc/omp-builtins.def
+++ b/gcc/omp-builtins.def
@@ -98,6 +98,10 @@ DEF_GOMP_BUILTIN (BUILT_IN_GOMP_ATOMIC_START,
"GOMP_atomic_start",
BT_FN_VOID, ATTR_NOTHROW_LEAF_LIST)
DEF_GOMP_BUILTIN (BUILT_IN_GOMP_ATOMIC_END, "GOMP_atomic_end",
BT_FN_VOID, ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_REDUCTION_START, "GOMP_reduction_start",
+ BT_FN_VOID, ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_REDUCTION_END, "GOMP_reduction_end",
+ BT_FN_VOID, ATTR_NOTHROW_LEAF_LIST)
DEF_GOMP_BUILTIN (BUILT_IN_GOMP_BARRIER, "GOMP_barrier", BT_FN_VOID_INT,
ATTR_NOTHROW_LEAF_LIST)
DEF_GOMP_BUILTIN (BUILT_IN_GOMP_BARRIER_CANCEL, "GOMP_barrier_cancel",
diff --git a/gcc/omp-low.cc b/gcc/omp-low.cc
index 810bf8c2efe..25ef047041a 100644
--- a/gcc/omp-low.cc
+++ b/gcc/omp-low.cc
@@ -7991,8 +7991,9 @@ lower_reduction_clauses (tree clauses, gimple_seq
*stmt_seqp,
}
}
- stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START),
- 0);
+ stmt
+ = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_REDUCTION_START),
+ 0);
gimple_seq_add_stmt (stmt_seqp, stmt);
gimple_seq_add_seq (stmt_seqp, sub_seq);
@@ -8003,7 +8004,7 @@ lower_reduction_clauses (tree clauses, gimple_seq
*stmt_seqp,
*clist = NULL;
}
- stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END),
+ stmt = gimple_build_call (builtin_decl_explicit
(BUILT_IN_GOMP_REDUCTION_END),
0);
gimple_seq_add_stmt (stmt_seqp, stmt);
}
@@ -8707,11 +8708,11 @@ lower_omp_sections (gimple_stmt_iterator *gsi_p,
omp_context *ctx)
&clist, ctx);
if (clist)
{
- tree fndecl = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START);
+ tree fndecl = builtin_decl_explicit (BUILT_IN_GOMP_REDUCTION_START);
gcall *g = gimple_build_call (fndecl, 0);
gimple_seq_add_stmt (&olist, g);
gimple_seq_add_seq (&olist, clist);
- fndecl = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END);
+ fndecl = builtin_decl_explicit (BUILT_IN_GOMP_REDUCTION_END);
g = gimple_build_call (fndecl, 0);
gimple_seq_add_stmt (&olist, g);
}
@@ -8986,11 +8987,11 @@ lower_omp_scope (gimple_stmt_iterator *gsi_p,
omp_context *ctx)
&bind_body, &clist, ctx);
if (clist)
{
- tree fndecl = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START);
+ tree fndecl = builtin_decl_explicit (BUILT_IN_GOMP_REDUCTION_START);
gcall *g = gimple_build_call (fndecl, 0);
gimple_seq_add_stmt (&bind_body, g);
gimple_seq_add_seq (&bind_body, clist);
- fndecl = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END);
+ fndecl = builtin_decl_explicit (BUILT_IN_GOMP_REDUCTION_END);
g = gimple_build_call (fndecl, 0);
gimple_seq_add_stmt (&bind_body, g);
}
@@ -11943,11 +11944,11 @@ lower_omp_for (gimple_stmt_iterator *gsi_p,
omp_context *ctx)
if (clist)
{
- tree fndecl = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START);
+ tree fndecl = builtin_decl_explicit (BUILT_IN_GOMP_REDUCTION_START);
gcall *g = gimple_build_call (fndecl, 0);
gimple_seq_add_stmt (&body, g);
gimple_seq_add_seq (&body, clist);
- fndecl = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END);
+ fndecl = builtin_decl_explicit (BUILT_IN_GOMP_REDUCTION_END);
g = gimple_build_call (fndecl, 0);
gimple_seq_add_stmt (&body, g);
}
diff --git a/gcc/testsuite/c-c++-common/gomp/reduction-builtins-1.c
b/gcc/testsuite/c-c++-common/gomp/reduction-builtins-1.c
new file mode 100644
index 00000000000..bef786be374
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/reduction-builtins-1.c
@@ -0,0 +1,47 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-fdump-tree-omplower" } */
+
+/* Check that, for reductions, critical sections are bracketed with
+ GOMP_reduction_start/end rather than GOMP_atomic_start/end. Two scalar
+ reductions force the critical-section path (a single scalar reduction would
+ use an atomic update instead). */
+
+void foo (int);
+
+void r_for (int n) {
+ int a = 0, b = 0, i;
+ #pragma omp parallel
+ #pragma omp for reduction(+: a, b)
+ for (i = 0; i < n; i++) { a += i; b += i; }
+}
+
+void r_sections (void) {
+ int a = 0, b = 0;
+ #pragma omp parallel
+ #pragma omp sections reduction(+: a, b)
+ { foo (a + b); }
+}
+
+void r_scope (void) {
+ int a = 0, b = 0;
+ #pragma omp parallel
+ #pragma omp scope reduction(+: a, b)
+ foo (a + b);
+}
+
+void r_teams (void) {
+ int a = 0, b = 0;
+ #pragma omp teams reduction(+: a, b)
+ foo (a + b);
+}
+
+void r_parallel (void) {
+ int a = 0, b = 0;
+ #pragma omp parallel reduction(+: a, b)
+ foo (a + b);
+}
+
+/* { dg-final { scan-tree-dump-times "GOMP_reduction_start \\(" 5 "omplower" }
} */
+/* { dg-final { scan-tree-dump-times "GOMP_reduction_end \\(" 5 "omplower" } }
*/
+/* { dg-final { scan-tree-dump-not "GOMP_atomic_start" "omplower" } } */
+/* { dg-final { scan-tree-dump-not "GOMP_atomic_end" "omplower" } } */
diff --git a/gcc/tree-ssa-alias.cc b/gcc/tree-ssa-alias.cc
index f662924b07f..affa48d9b1d 100644
--- a/gcc/tree-ssa-alias.cc
+++ b/gcc/tree-ssa-alias.cc
@@ -2807,6 +2807,8 @@ check_fnspec (gcall *call, ao_ref *ref, bool clobber)
#undef DEF_SYNC_BUILTIN
case BUILT_IN_GOMP_ATOMIC_START:
case BUILT_IN_GOMP_ATOMIC_END:
+ case BUILT_IN_GOMP_REDUCTION_START:
+ case BUILT_IN_GOMP_REDUCTION_END:
case BUILT_IN_GOMP_BARRIER:
case BUILT_IN_GOMP_BARRIER_CANCEL:
case BUILT_IN_GOMP_TASKWAIT:
diff --git a/libgomp/atomic.c b/libgomp/atomic.c
index df5b810eaef..0167cdfa40a 100644
--- a/libgomp/atomic.c
+++ b/libgomp/atomic.c
@@ -48,6 +48,18 @@ GOMP_atomic_end (void)
gomp_mutex_unlock (&atomic_lock);
}
+void
+GOMP_reduction_start (void)
+{
+ gomp_mutex_lock (&atomic_lock);
+}
+
+void
+GOMP_reduction_end (void)
+{
+ gomp_mutex_unlock (&atomic_lock);
+}
+
#if !GOMP_MUTEX_INIT_0
static void __attribute__((constructor))
initialize_atomic (void)
diff --git a/libgomp/libgomp.map b/libgomp/libgomp.map
index 415d3883575..67f4cb61bf3 100644
--- a/libgomp/libgomp.map
+++ b/libgomp/libgomp.map
@@ -471,6 +471,8 @@ GOMP_6.0.2 {
GOMP_has_masked_thread_num;
GOMP_loop_static_worksharing;
GOMP_distribute_static_worksharing;
+ GOMP_reduction_start;
+ GOMP_reduction_end;
} GOMP_6.0.1;
OACC_2.0 {
diff --git a/libgomp/libgomp_g.h b/libgomp/libgomp_g.h
index 617f098b990..a51397b2e13 100644
--- a/libgomp/libgomp_g.h
+++ b/libgomp/libgomp_g.h
@@ -46,6 +46,8 @@ extern void GOMP_critical_name_start (void **);
extern void GOMP_critical_name_end (void **);
extern void GOMP_atomic_start (void);
extern void GOMP_atomic_end (void);
+extern void GOMP_reduction_start (void);
+extern void GOMP_reduction_end (void);
/* loop.c */
--
2.53.0