[gcc/devel/omp/gcc-16] openmp: Add barrier kind to GOMP_barrier and GOMP_barrier_cancel

Sandra Loosemore via Gcc-cvs <[email protected]>
Newsgroups gmane.comp.gcc.cvs
Message-ID <[email protected]>
https://gcc.gnu.org/g:1dec44adf43b63304166ff971253511bd39f9ba6

commit 1dec44adf43b63304166ff971253511bd39f9ba6
Author: Paul-Antoine Arras <[email protected]>
Date:   Thu Jun 18 18:40:22 2026 +0200

    openmp: Add barrier kind to GOMP_barrier and GOMP_barrier_cancel
    
    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.
    
    Create new, semantically equivalent functions GOMP_barrier_ext and
    GOMP_barrier_cancel_ext with an integer `kind' parameter. Update all compiler
    call sites to pass the appropriate constant. Preserve now unused functions
    GOMP_barrier and GOMP_barrier_cancel for backward compatibility.
    
    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_ext.
    
    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_ext.
    
    gcc/ChangeLog:
    
            * omp-builtins.def (BUILT_IN_GOMP_BARRIER): Change function to
            GOMP_barrier_ext and type to BT_FN_VOID_INT.
            (BUILT_IN_GOMP_BARRIER_CANCEL): Change function to
            GOMP_barrier_cancel_ext and type to BT_FN_VOID_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_ext or GOMP_barrier_cancel_ext.
            * 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_ext): New function.
            (GOMP_barrier_cancel_ext): Likewise.
            * libgomp_g.h (GOMP_barrier_ext): Declare.
            (GOMP_barrier_cancel_ext): Likewise.
            * libgomp.map (GOMP_6.0.2): Add GOMP_barrier_ext and
            GOMP_barrier_cancel_ext.
            * testsuite/libgomp.c/barrier-1.c: Update GOMP_barrier_ext calls to pass
            GOMP_BARRIER_EXPLICIT.
    
    gcc/testsuite/ChangeLog:
    
            * g++.dg/gomp/barrier-1.C: Update scan dump.
            * g++.dg/gomp/tpl-barrier-1.C: Likewise.
            * 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.
    
    (cherry picked from commit 22ada6bbe4e66747dcf6ee121c20730685cf5b03)

Diff:
---
 gcc/c-family/c-omp.cc                              |   4 +-
 gcc/cp/semantics.cc                                |   1 +
 gcc/fortran/trans-openmp.cc                        |   4 +-
 gcc/omp-builtins.def                               |   8 +-
 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/g++.dg/gomp/tpl-barrier-1.C          |   2 +-
 gcc/testsuite/gcc.dg/gomp/barrier-1.c              |   2 +-
 .../gomp/lastprivate-allocatable-barrier-1.f90     |  33 +++++++
 include/gomp-constants.h                           |   6 ++
 libgomp/barrier.c                                  |  30 ++++++
 libgomp/libgomp.map                                |   2 +
 libgomp/libgomp_g.h                                |   2 +
 libgomp/testsuite/libgomp.c/barrier-1.c            |   8 +-
 18 files changed, 229 insertions(+), 22 deletions(-)

diff --git a/gcc/c-family/c-omp.cc b/gcc/c-family/c-omp.cc
index b48243a22616..99ff4e8e77c7 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 225d8793eab8..cf1a9049adc4 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -12546,6 +12546,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 e23f10d34a82..0f8411fb55b1 100644
--- a/gcc/fortran/trans-openmp.cc
+++ b/gcc/fortran/trans-openmp.cc
@@ -6970,7 +6970,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 82736e773407..0a9dde8f6187 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_CANCEL, "GOMP_barrier_cancel",
-		  BT_FN_BOOL, ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_BARRIER, "GOMP_barrier_ext", BT_FN_VOID_INT,
+		  ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_BARRIER_CANCEL, "GOMP_barrier_cancel_ext",
+		  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 bb7b47f3e022..ca77fb5914aa 100644
--- a/gcc/omp-expand.cc
+++ b/gcc/omp-expand.cc
@@ -5602,7 +5602,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)
@@ -6324,7 +6327,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)
     {
@@ -8702,7 +8708,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 78a13bda60e9..fdd934f5223f 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 a5126269650c..ebfe16d0a4fe 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 bd15defd40e6..80bd96403a2e 100644
--- a/gcc/omp-low.cc
+++ b/gcc/omp-low.cc
@@ -7043,7 +7043,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
@@ -11477,7 +11495,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);
@@ -11594,7 +11612,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 000000000000..d53b424233f6
--- /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_ext \\(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_ext \\(1\\)" 8 "ompexp" } } */
diff --git a/gcc/testsuite/g++.dg/gomp/barrier-1.C b/gcc/testsuite/g++.dg/gomp/barrier-1.C
index 55f3035193ec..a601d85669f5 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_ext \\(2\\)" 2 "gimple" } } */
diff --git a/gcc/testsuite/g++.dg/gomp/tpl-barrier-1.C b/gcc/testsuite/g++.dg/gomp/tpl-barrier-1.C
index b45cb1ee5cca..f198cddb5568 100644
--- a/gcc/testsuite/g++.dg/gomp/tpl-barrier-1.C
+++ b/gcc/testsuite/g++.dg/gomp/tpl-barrier-1.C
@@ -21,4 +21,4 @@ void f3 ()
   f2<0> (true);
 }
 
-// { dg-final { scan-tree-dump-times "GOMP_barrier" 2 "gimple" } }
+// { dg-final { scan-tree-dump-times "GOMP_barrier_ext" 2 "gimple" } }
diff --git a/gcc/testsuite/gcc.dg/gomp/barrier-1.c b/gcc/testsuite/gcc.dg/gomp/barrier-1.c
index 42c70e91163b..be874d38503b 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_ext \\(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 000000000000..48499f6a4c8b
--- /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_ext \\(0\\)" 1 "omplower" } }
+! { dg-final { scan-tree-dump-times "GOMP_barrier_ext \\(1\\)" 1 "omplower" } }
diff --git a/include/gomp-constants.h b/include/gomp-constants.h
index 203477db8c15..51de90df97d6 100644
--- a/include/gomp-constants.h
+++ b/include/gomp-constants.h
@@ -435,4 +435,10 @@ enum gomp_map_kind
 /* Identifiers of device-specific target arguments.  */
 #define GOMP_TARGET_ARG_HSA_KERNEL_ATTRIBUTES	(1 << 8)
 
+/* GOMP_barrier{,_cancel}_ext 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 3a6037e43552..d11fd710b193 100644
--- a/libgomp/barrier.c
+++ b/libgomp/barrier.c
@@ -27,6 +27,8 @@
 
 #include "libgomp.h"
 
+/* GOMP_barrier is no longer called by new code; it is only kept for
+   backward compatibility. New code uses GOMP_barrier_ext.  */
 
 void
 GOMP_barrier (void)
@@ -41,6 +43,22 @@ GOMP_barrier (void)
   gomp_team_barrier_wait (&team->barrier);
 }
 
+void
+GOMP_barrier_ext (int kind __attribute__ ((unused)))
+{
+  struct gomp_thread *thr = gomp_thread ();
+  struct gomp_team *team = thr->ts.team;
+
+  /* It is legal to have orphaned barriers.  */
+  if (team == NULL)
+    return;
+
+  gomp_team_barrier_wait (&team->barrier);
+}
+
+/* GOMP_barrier_cancel is no longer called by new code; it is only kept for
+   backward compatibility. New code uses GOMP_barrier_cancel_ext.  */
+
 bool
 GOMP_barrier_cancel (void)
 {
@@ -52,3 +70,15 @@ GOMP_barrier_cancel (void)
      never have an orphaned cancellable barrier.  */
   return gomp_team_barrier_wait_cancel (&team->barrier);
 }
+
+bool
+GOMP_barrier_cancel_ext (int kind __attribute__ ((unused)))
+{
+  struct gomp_thread *thr = gomp_thread ();
+  struct gomp_team *team = thr->ts.team;
+
+  /* The compiler transforms to barrier_cancel when it sees that the
+     barrier is within a construct that can cancel.  Thus we should
+     never have an orphaned cancellable barrier.  */
+  return gomp_team_barrier_wait_cancel (&team->barrier);
+}
diff --git a/libgomp/libgomp.map b/libgomp/libgomp.map
index 4aa518ecdae7..92ef5c298f4d 100644
--- a/libgomp/libgomp.map
+++ b/libgomp/libgomp.map
@@ -487,6 +487,8 @@ GOMP_6.0.2 {
 	GOMP_has_masked_thread_num;
 	GOMP_loop_static_worksharing;
 	GOMP_distribute_static_worksharing;
+	GOMP_barrier_ext;
+	GOMP_barrier_cancel_ext;
 } GOMP_6.0.1;
 
 OACC_2.0 {
diff --git a/libgomp/libgomp_g.h b/libgomp/libgomp_g.h
index 6dc1fd46fcea..89ed7b3462e3 100644
--- a/libgomp/libgomp_g.h
+++ b/libgomp/libgomp_g.h
@@ -41,7 +41,9 @@ extern void GOMP_atomic_end (void);
 /* barrier.c */
 
 extern void GOMP_barrier (void);
+extern void GOMP_barrier_ext (int);
 extern bool GOMP_barrier_cancel (void);
+extern bool GOMP_barrier_cancel_ext (int);
 
 /* critical.c */
 
diff --git a/libgomp/testsuite/libgomp.c/barrier-1.c b/libgomp/testsuite/libgomp.c/barrier-1.c
index 1f8d1f0d3f98..1fe678a0a093 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_ext (GOMP_BARRIER_EXPLICIT);
 
   if (iam == 0)
     {
@@ -25,8 +25,8 @@ static void function(void *dummy)
       usleep (10);
     }
 
-  GOMP_barrier ();
-  
+  GOMP_barrier_ext (GOMP_BARRIER_EXPLICIT);
+
   gettimeofday (&stamps[iam][2], NULL);
 }
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.