GOMP_barrier is called for at least three distinct purposes: implicit
barriers at the end of parallel/teams regions, implicit barriers at the
end of worksharing constructs, and explicit `#pragma omp barrier'
directives. OMPT requires distinguishing these in its sync-region
callbacks.
Add an integer `kind' parameter to both GOMP_barrier and GOMP_barrier_cancel.
Update all compiler call sites to pass the appropriate constant.
The `kind' parameter is accepted but not yet acted upon in libgomp; it
is reserved for future OMPT instrumentation.
gcc/c-family/ChangeLog:
* c-omp.cc (c_finish_omp_barrier): Pass GOMP_BARRIER_EXPLICIT to
GOMP_barrier.
gcc/cp/ChangeLog:
* semantics.cc (finish_omp_barrier): Push GOMP_BARRIER_EXPLICIT
onto the argument vector.
gcc/fortran/ChangeLog:
* trans-openmp.cc (gfc_trans_omp_barrier): Pass GOMP_BARRIER_EXPLICIT
to GOMP_barrier.
gcc/ChangeLog:
* omp-builtins.def (BUILT_IN_GOMP_BARRIER): Change type from
BT_FN_VOID to BT_FN_VOID_INT.
(BUILT_IN_GOMP_BARRIER_CANCEL): Change type from BT_FN_BOOL to
BT_FN_BOOL_INT.
* omp-expand.cc (expand_omp_for_static_nochunk): Pass
GOMP_BARRIER_IMPLICIT_WORKSHARE to omp_build_barrier.
(expand_omp_for_static_chunk): Likewise.
(expand_omp_single): Likewise.
* omp-general.cc (omp_build_barrier): Add kind parameter; pass it
to GOMP_barrier or GOMP_barrier_cancel.
* omp-general.h (omp_build_barrier): Update declaration to add
kind parameter.
* omp-low.cc (lower_rec_input_clauses): Determine barrier kind from
the enclosing gimple statement code and pass it to omp_build_barrier.
(lower_omp_for_scan): Pass GOMP_BARRIER_IMPLICIT_WORKSHARE to
omp_build_barrier.
include/ChangeLog:
* gomp-constants.h (GOMP_BARRIER_IMPLICIT_PARALLEL): New macro.
(GOMP_BARRIER_IMPLICIT_WORKSHARE): New macro.
(GOMP_BARRIER_EXPLICIT): New macro.
libgomp/ChangeLog:
* barrier.c (GOMP_barrier): Add kind parameter.
(GOMP_barrier_cancel): Likewise.
* libgomp_g.h (GOMP_barrier): Update declaration.
(GOMP_barrier_cancel): Update declaration.
* testsuite/libgomp.c/barrier-1.c: Update GOMP_barrier calls to pass
GOMP_BARRIER_EXPLICIT.
gcc/testsuite/ChangeLog:
* g++.dg/gomp/barrier-1.C: Update scan dump.
* gcc.dg/gomp/barrier-1.c: Likewise.
* c-c++-common/gomp/implicit-barrier-1.c: New test.
* gfortran.dg/gomp/lastprivate-allocatable-barrier-1.f90: New test.
---
gcc/c-family/c-omp.cc | 4 +-
gcc/cp/semantics.cc | 1 +
gcc/fortran/trans-openmp.cc | 4 +-
gcc/omp-builtins.def | 6 +-
gcc/omp-expand.cc | 14 ++-
gcc/omp-general.cc | 5 +-
gcc/omp-general.h | 2 +-
gcc/omp-low.cc | 24 ++++-
.../c-c++-common/gomp/implicit-barrier-1.c | 102 ++++++++++++++++++
gcc/testsuite/g++.dg/gomp/barrier-1.C | 2 +-
gcc/testsuite/gcc.dg/gomp/barrier-1.c | 2 +-
.../lastprivate-allocatable-barrier-1.f90 | 33 ++++++
include/gomp-constants.h | 6 ++
libgomp/barrier.c | 4 +-
libgomp/libgomp_g.h | 4 +-
libgomp/testsuite/libgomp.c/barrier-1.c | 8 +-
16 files changed, 197 insertions(+), 24 deletions(-)
create mode 100644 gcc/testsuite/c-c++-common/gomp/implicit-barrier-1.c
create mode 100644
gcc/testsuite/gfortran.dg/gomp/lastprivate-allocatable-barrier-1.f90
diff --git a/gcc/c-family/c-omp.cc b/gcc/c-family/c-omp.cc
index c6bdcf8244c..e263706a3f1 100644
--- a/gcc/c-family/c-omp.cc
+++ b/gcc/c-family/c-omp.cc
@@ -175,7 +175,9 @@ c_finish_omp_barrier (location_t loc)
tree x;
x = builtin_decl_explicit (BUILT_IN_GOMP_BARRIER);
- x = build_call_expr_loc (loc, x, 0);
+ x = build_call_expr_loc (loc, x, 1,
+ build_int_cst (integer_type_node,
+ GOMP_BARRIER_EXPLICIT));
add_stmt (x);
}
diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
index 0d47b20fb3c..c5b2323c88e 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -12544,6 +12544,7 @@ finish_omp_barrier (void)
{
tree fn = builtin_decl_explicit (BUILT_IN_GOMP_BARRIER);
releasing_vec vec;
+ vec->quick_push (build_int_cst (integer_type_node, GOMP_BARRIER_EXPLICIT));
tree stmt = finish_call_expr (fn, &vec, false, false, tf_warning_or_error);
finish_expr_stmt (stmt);
}
diff --git a/gcc/fortran/trans-openmp.cc b/gcc/fortran/trans-openmp.cc
index 30b8e604486..c79aec703bb 100644
--- a/gcc/fortran/trans-openmp.cc
+++ b/gcc/fortran/trans-openmp.cc
@@ -6815,7 +6815,9 @@ static tree
gfc_trans_omp_barrier (void)
{
tree decl = builtin_decl_explicit (BUILT_IN_GOMP_BARRIER);
- return build_call_expr_loc (input_location, decl, 0);
+ return build_call_expr_loc (input_location, decl, 1,
+ build_int_cst (integer_type_node,
+ GOMP_BARRIER_EXPLICIT));
}
static tree
diff --git a/gcc/omp-builtins.def b/gcc/omp-builtins.def
index 2578624be2d..b88cc49d6b9 100644
--- a/gcc/omp-builtins.def
+++ b/gcc/omp-builtins.def
@@ -98,10 +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_BARRIER, "GOMP_barrier",
- 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",
- BT_FN_BOOL, ATTR_NOTHROW_LEAF_LIST)
+ BT_FN_BOOL_INT, ATTR_NOTHROW_LEAF_LIST)
DEF_GOMP_BUILTIN (BUILT_IN_GOMP_TASKWAIT, "GOMP_taskwait",
BT_FN_VOID, ATTR_NOTHROW_LEAF_LIST)
DEF_GOMP_BUILTIN (BUILT_IN_GOMP_TASKWAIT_DEPEND, "GOMP_taskwait_depend",
diff --git a/gcc/omp-expand.cc b/gcc/omp-expand.cc
index ade4e0f5329..60d180f536b 100644
--- a/gcc/omp-expand.cc
+++ b/gcc/omp-expand.cc
@@ -5605,7 +5605,10 @@ expand_omp_for_static_nochunk (struct omp_region *region,
gsi_insert_after (&gsi, g, GSI_SAME_STMT);
}
else
- gsi_insert_after (&gsi, omp_build_barrier (t), GSI_SAME_STMT);
+ gsi_insert_after (&gsi,
+ omp_build_barrier (t,
+ GOMP_BARRIER_IMPLICIT_WORKSHARE),
+ GSI_SAME_STMT);
}
else if ((fd->have_pointer_condtemp || fd->have_scantemp)
&& !fd->have_nonctrl_scantemp)
@@ -6330,7 +6333,10 @@ expand_omp_for_static_chunk (struct omp_region *region,
gsi_insert_after (&gsi, g, GSI_SAME_STMT);
}
else
- gsi_insert_after (&gsi, omp_build_barrier (t), GSI_SAME_STMT);
+ gsi_insert_after (&gsi,
+ omp_build_barrier (t,
+ GOMP_BARRIER_IMPLICIT_WORKSHARE),
+ GSI_SAME_STMT);
}
else if (fd->have_pointer_condtemp)
{
@@ -8708,7 +8714,9 @@ expand_omp_single (struct omp_region *region)
if (!gimple_omp_return_nowait_p (gsi_stmt (si)))
{
tree t = gimple_omp_return_lhs (gsi_stmt (si));
- gsi_insert_after (&si, omp_build_barrier (t), GSI_SAME_STMT);
+ gsi_insert_after (&si,
+ omp_build_barrier (t, GOMP_BARRIER_IMPLICIT_WORKSHARE),
+ GSI_SAME_STMT);
}
gsi_remove (&si, true);
single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
diff --git a/gcc/omp-general.cc b/gcc/omp-general.cc
index 118653c53d2..60335074b70 100644
--- a/gcc/omp-general.cc
+++ b/gcc/omp-general.cc
@@ -920,11 +920,12 @@ omp_extract_for_data (gomp_for *for_stmt, struct
omp_for_data *fd,
/* Build a call to GOMP_barrier. */
gimple *
-omp_build_barrier (tree lhs)
+omp_build_barrier (tree lhs, int kind)
{
tree fndecl = builtin_decl_explicit (lhs ? BUILT_IN_GOMP_BARRIER_CANCEL
: BUILT_IN_GOMP_BARRIER);
- gcall *g = gimple_build_call (fndecl, 0);
+ gcall *g = gimple_build_call (fndecl, 1,
+ build_int_cst (integer_type_node, kind));
if (lhs)
gimple_call_set_lhs (g, lhs);
return g;
diff --git a/gcc/omp-general.h b/gcc/omp-general.h
index a5126269650..ebfe16d0a4f 100644
--- a/gcc/omp-general.h
+++ b/gcc/omp-general.h
@@ -189,7 +189,7 @@ extern void omp_adjust_for_condition (location_t loc, enum
tree_code *cond_code,
extern tree omp_get_for_step_from_incr (location_t loc, tree incr);
extern void omp_extract_for_data (gomp_for *for_stmt, struct omp_for_data *fd,
struct omp_for_data_loop *loops);
-extern gimple *omp_build_barrier (tree lhs);
+extern gimple *omp_build_barrier (tree lhs, int kind);
extern tree find_combined_omp_for (tree *, int *, void *);
extern poly_uint64 omp_max_vf (bool);
extern int omp_max_simt_vf (void);
diff --git a/gcc/omp-low.cc b/gcc/omp-low.cc
index 030bc8d9fc3..810bf8c2efe 100644
--- a/gcc/omp-low.cc
+++ b/gcc/omp-low.cc
@@ -7034,7 +7034,25 @@ lower_rec_input_clauses (tree clauses, gimple_seq
*ilist, gimple_seq *dlist,
if (!is_task_ctx (ctx)
&& (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
|| gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_FOR))
- gimple_seq_add_stmt (ilist, omp_build_barrier (NULL_TREE));
+ {
+ int barrier_kind;
+ switch (gimple_code (ctx->stmt))
+ {
+ case GIMPLE_OMP_SECTIONS:
+ case GIMPLE_OMP_SCOPE:
+ case GIMPLE_OMP_FOR:
+ barrier_kind = GOMP_BARRIER_IMPLICIT_WORKSHARE;
+ break;
+ case GIMPLE_OMP_PARALLEL:
+ case GIMPLE_OMP_TEAMS:
+ barrier_kind = GOMP_BARRIER_IMPLICIT_PARALLEL;
+ break;
+ default:
+ gcc_unreachable ();
+ }
+ gimple_seq_add_stmt (ilist,
+ omp_build_barrier (NULL_TREE, barrier_kind));
+ }
}
/* If max_vf is non-zero, then we can use only a vectorization factor
@@ -11468,7 +11486,7 @@ lower_omp_for_scan (gimple_seq *body_p, gimple_seq
*dlist, gomp_for *stmt,
g = gimple_build_label (lab1);
gimple_seq_add_stmt (body_p, g);
- g = omp_build_barrier (NULL);
+ g = omp_build_barrier (NULL, GOMP_BARRIER_IMPLICIT_WORKSHARE);
gimple_seq_add_stmt (body_p, g);
tree down = create_tmp_var (unsigned_type_node);
@@ -11585,7 +11603,7 @@ lower_omp_for_scan (gimple_seq *body_p, gimple_seq
*dlist, gomp_for *stmt,
g = gimple_build_label (lab12);
gimple_seq_add_stmt (body_p, g);
- g = omp_build_barrier (NULL);
+ g = omp_build_barrier (NULL, GOMP_BARRIER_IMPLICIT_WORKSHARE);
gimple_seq_add_stmt (body_p, g);
g = gimple_build_cond (NE_EXPR, k, build_zero_cst (unsigned_type_node),
diff --git a/gcc/testsuite/c-c++-common/gomp/implicit-barrier-1.c
b/gcc/testsuite/c-c++-common/gomp/implicit-barrier-1.c
new file mode 100644
index 00000000000..f212bac957d
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/implicit-barrier-1.c
@@ -0,0 +1,102 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-fdump-tree-ompexp" } */
+
+/* Check that implicit barriers are emitted with the correct kind. */
+
+void body (void);
+void bar (int);
+void foo (int);
+
+/* OMP for construct with static schedule (with and without chunk) -> workshare
+ barrier. */
+void wfor (int n) {
+ int i;
+ #pragma omp for schedule(static)
+ for (i = 0; i < n; i++) bar (i);
+ #pragma omp for schedule(static, 4)
+ for (i = 0; i < n; i++) bar (i);
+}
+
+/* OMP for construct with inscan reduction -> workshare barrier. */
+int r;
+void wfor_scan (int n)
+{
+ int i;
+ #pragma omp for reduction(inscan, + : r) private(i)
+ for (i = 0; i < n; i = i + 1)
+ {
+ {
+ bar (r);
+ }
+ #pragma omp scan inclusive(r)
+ {
+ foo (r);
+ }
+ }
+}
+
+/* OMP sections construct with firstprivate and lastprivate clauses ->
workshare
+ barrier. */
+int a;
+int wsections (void) {
+ #pragma omp sections firstprivate(a) lastprivate(a)
+ { foo (a); }
+ return a;
+}
+
+/* parallel with a copyin variable passed by reference (an aggregate, so
+ use_pointer_for_field is true) -> copyin_by_ref -> parallel barrier. */
+int tp[64];
+#pragma omp threadprivate (tp)
+void pcopyin (void) {
+ #pragma omp parallel copyin(tp)
+ body ();
+}
+
+/* UDR whose initializer references omp_orig, used on a (non-task) parallel
+ construct -> reduction_omp_orig_ref -> parallel barrier. */
+struct S { int s; };
+void combine (struct S *out, struct S *in);
+struct S init_from_orig (struct S *orig);
+void use (struct S *);
+
+#pragma omp declare reduction (+: struct S: combine (&omp_out, &omp_in)) \
+ initializer (omp_priv = init_from_orig (&omp_orig))
+
+void preduction_orig (struct S s) {
+ #pragma omp parallel reduction (+: s)
+ use (&s);
+}
+
+/* Same omp_orig UDR on a teams construct -> parallel barrier. */
+void treduction_orig (struct S s) {
+ #pragma omp teams reduction (+: s)
+ use (&s);
+}
+
+/* Same omp_orig UDR on a scope construct -> workshare barrier. */
+struct S gs;
+void sreduction_orig (void) {
+ #pragma omp parallel
+ #pragma omp scope reduction (+: gs)
+ use (&gs);
+}
+
+/* OMP single construct (without nowait) -> workshare barrier. */
+void wsingle (void) {
+ #pragma omp single
+ body ();
+}
+
+/* OMP scope construct (without nowait) -> workshare barrier. */
+void wscope (void) {
+ #pragma omp scope
+ body ();
+}
+
+/* GOMP_BARRIER_IMPLICIT_PARALLEL (0): pcopyin, preduction_orig,
+ treduction_orig. */
+/* { dg-final { scan-tree-dump-times "GOMP_barrier \\(0\\)" 3 "ompexp" } } */
+/* GOMP_BARRIER_IMPLICIT_WORKSHARE (1): wfor (x2), wfor_scan (x2), wsections,
+ sreduction_orig, wsingle, wscope. */
+/* { dg-final { scan-tree-dump-times "GOMP_barrier \\(1\\)" 8 "ompexp" } } */
diff --git a/gcc/testsuite/g++.dg/gomp/barrier-1.C
b/gcc/testsuite/g++.dg/gomp/barrier-1.C
index 55f3035193e..ba2f0c65d0a 100644
--- a/gcc/testsuite/g++.dg/gomp/barrier-1.C
+++ b/gcc/testsuite/g++.dg/gomp/barrier-1.C
@@ -14,4 +14,4 @@ void f2(bool p)
}
}
-/* { dg-final { scan-tree-dump-times "GOMP_barrier" 2 "gimple" } } */
+/* { dg-final { scan-tree-dump-times "GOMP_barrier \\(2\\)" 2 "gimple" } } */
diff --git a/gcc/testsuite/gcc.dg/gomp/barrier-1.c
b/gcc/testsuite/gcc.dg/gomp/barrier-1.c
index 42c70e91163..405ff2f352d 100644
--- a/gcc/testsuite/gcc.dg/gomp/barrier-1.c
+++ b/gcc/testsuite/gcc.dg/gomp/barrier-1.c
@@ -14,4 +14,4 @@ void f2(_Bool p)
}
}
-/* { dg-final { scan-tree-dump-times "GOMP_barrier" 2 "gimple" } } */
+/* { dg-final { scan-tree-dump-times "GOMP_barrier \\(2\\)" 2 "gimple" } } */
diff --git
a/gcc/testsuite/gfortran.dg/gomp/lastprivate-allocatable-barrier-1.f90
b/gcc/testsuite/gfortran.dg/gomp/lastprivate-allocatable-barrier-1.f90
new file mode 100644
index 00000000000..b05fc742e84
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/lastprivate-allocatable-barrier-1.f90
@@ -0,0 +1,33 @@
+! { dg-do compile }
+! { dg-additional-options "-fdump-tree-omplower" }
+
+! A lastprivate allocatable (without a corresponding firstprivate) needs an
+! outer-variable reference (gfc_omp_private_outer_ref is true), which makes
+! lower_rec_input_clauses emit the implicit barrier. The barrier kind
+! depends on the construct the clause ends up on:
+! - combined "parallel do" -> GOMP_BARRIER_IMPLICIT_PARALLEL (0)
+! - "do" enclosed in a "parallel" -> GOMP_BARRIER_IMPLICIT_WORKSHARE (1)
+
+subroutine parallel_case
+ integer, allocatable :: a(:)
+ integer :: i
+ !$omp parallel do lastprivate(a)
+ do i = 1, 1
+ a = [i]
+ end do
+end subroutine parallel_case
+
+subroutine workshare_case
+ integer, allocatable :: a(:)
+ integer :: i
+ !$omp parallel
+ !$omp do lastprivate(a)
+ do i = 1, 1
+ a = [i]
+ end do
+ !$omp end do
+ !$omp end parallel
+end subroutine workshare_case
+
+! { dg-final { scan-tree-dump-times "GOMP_barrier \\(0\\)" 1 "omplower" } }
+! { dg-final { scan-tree-dump-times "GOMP_barrier \\(1\\)" 1 "omplower" } }
diff --git a/include/gomp-constants.h b/include/gomp-constants.h
index 0a0761043f9..0e107e2db02 100644
--- a/include/gomp-constants.h
+++ b/include/gomp-constants.h
@@ -433,4 +433,10 @@ enum gomp_map_kind
/* Identifiers of device-specific target arguments. */
#define GOMP_TARGET_ARG_HSA_KERNEL_ATTRIBUTES (1 << 8)
+/* GOMP_barrier{,_cancel} argument.
+ TODO turn this into an enum? */
+#define GOMP_BARRIER_IMPLICIT_PARALLEL 0
+#define GOMP_BARRIER_IMPLICIT_WORKSHARE 1
+#define GOMP_BARRIER_EXPLICIT 2
+
#endif
diff --git a/libgomp/barrier.c b/libgomp/barrier.c
index 3a6037e4355..04aa8a9583e 100644
--- a/libgomp/barrier.c
+++ b/libgomp/barrier.c
@@ -29,7 +29,7 @@
void
-GOMP_barrier (void)
+GOMP_barrier (int kind)
{
struct gomp_thread *thr = gomp_thread ();
struct gomp_team *team = thr->ts.team;
@@ -42,7 +42,7 @@ GOMP_barrier (void)
}
bool
-GOMP_barrier_cancel (void)
+GOMP_barrier_cancel (int kind)
{
struct gomp_thread *thr = gomp_thread ();
struct gomp_team *team = thr->ts.team;
diff --git a/libgomp/libgomp_g.h b/libgomp/libgomp_g.h
index 6890547bfa7..617f098b990 100644
--- a/libgomp/libgomp_g.h
+++ b/libgomp/libgomp_g.h
@@ -35,8 +35,8 @@
/* barrier.c */
-extern void GOMP_barrier (void);
-extern bool GOMP_barrier_cancel (void);
+extern void GOMP_barrier (int);
+extern bool GOMP_barrier_cancel (int);
/* critical.c */
diff --git a/libgomp/testsuite/libgomp.c/barrier-1.c
b/libgomp/testsuite/libgomp.c/barrier-1.c
index 1f8d1f0d3f9..66283de936a 100644
--- a/libgomp/testsuite/libgomp.c/barrier-1.c
+++ b/libgomp/testsuite/libgomp.c/barrier-1.c
@@ -5,7 +5,7 @@
#include <unistd.h>
#include <assert.h>
#include "libgomp_g.h"
-
+#include <gomp-constants.h>
struct timeval stamps[3][3];
@@ -17,7 +17,7 @@ static void function(void *dummy)
if (iam == 0)
usleep (10);
- GOMP_barrier ();
+ GOMP_barrier (GOMP_BARRIER_EXPLICIT);
if (iam == 0)
{
@@ -25,8 +25,8 @@ static void function(void *dummy)
usleep (10);
}
- GOMP_barrier ();
-
+ GOMP_barrier (GOMP_BARRIER_EXPLICIT);
+
gettimeofday (&stamps[iam][2], NULL);
}
--
2.53.0