[gcc/devel/omp/gcc-16] openmp: Add GOMP_reduction_start and GOMP_reduction_end

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

commit 0aae238fb1a2ae8ab312032e04ed541ee3eeac8f
Author: Paul-Antoine Arras <[email protected]>
Date:   Fri Jun 19 16:53:21 2026 +0200

    openmp: Add GOMP_reduction_start and GOMP_reduction_end
    
    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/atomic-builtins-1.c: New test.
            * c-c++-common/gomp/reduction-builtins-1.c: New test.
    
    (cherry picked from commit d50e9f17fffa9b047dcf02eb9e1fe499178a0f02)

Diff:
---
 gcc/omp-builtins.def                               |  4 ++
 gcc/omp-low.cc                                     | 19 ++++-----
 .../c-c++-common/gomp/atomic-builtins-1.c          | 13 ++++++
 .../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 +
 8 files changed, 92 insertions(+), 9 deletions(-)

diff --git a/gcc/omp-builtins.def b/gcc/omp-builtins.def
index 0a9dde8f6187..d7440a42761b 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_ext", BT_FN_VOID_INT,
 		  ATTR_NOTHROW_LEAF_LIST)
 DEF_GOMP_BUILTIN (BUILT_IN_GOMP_BARRIER_CANCEL, "GOMP_barrier_cancel_ext",
diff --git a/gcc/omp-low.cc b/gcc/omp-low.cc
index 80bd96403a2e..10e8cbd859c0 100644
--- a/gcc/omp-low.cc
+++ b/gcc/omp-low.cc
@@ -8000,8 +8000,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);
@@ -8012,7 +8013,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);
 }
@@ -8716,11 +8717,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);
     }
@@ -8995,11 +8996,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);
     }
@@ -11952,11 +11953,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/atomic-builtins-1.c b/gcc/testsuite/c-c++-common/gomp/atomic-builtins-1.c
new file mode 100644
index 000000000000..75b34319ddb6
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/atomic-builtins-1.c
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-fdump-tree-ompexp" } */
+
+/* Check that an GIMPLE_OMP_ATOMIC statement expands to GOMP_atomic_start/end
+   when atomic operations cannot be used and a mutex is required.  */
+
+void bar (__int128 a, __int128 b) {
+  #pragma omp atomic capture
+    b = a++;
+}
+
+/* { dg-final { scan-tree-dump "GOMP_atomic_start" "ompexp" } } */
+/* { dg-final { scan-tree-dump "GOMP_atomic_end" "ompexp" } } */
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 000000000000..bef786be374a
--- /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 f662924b07f0..affa48d9b1d1 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 df5b810eaef8..0167cdfa40ae 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 92ef5c298f4d..e2985347bf77 100644
--- a/libgomp/libgomp.map
+++ b/libgomp/libgomp.map
@@ -489,6 +489,8 @@ GOMP_6.0.2 {
 	GOMP_distribute_static_worksharing;
 	GOMP_barrier_ext;
 	GOMP_barrier_cancel_ext;
+	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 89ed7b3462e3..892ad3a55810 100644
--- a/libgomp/libgomp_g.h
+++ b/libgomp/libgomp_g.h
@@ -51,6 +51,8 @@ extern void GOMP_critical_start (void);
 extern void GOMP_critical_end (void);
 extern void GOMP_critical_name_start (void **);
 extern void GOMP_critical_name_end (void **);
+extern void GOMP_reduction_start (void);
+extern void GOMP_reduction_end (void);
 
 /* loop.c */
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.