On 25/06/2026 14:48, Thomas Schwinge wrote:
Hi!

On 2026-06-23T19:51:49+0200, Paul-Antoine Arras <[email protected]> wrote:
For the `omp master' and `omp masked filter(x)' constructs, the compiler lowers
the filter check by emitting omp_get_thread_num() == filter. Because
omp_get_thread_num is a public OpenMP API function, OMPT cannot distinguish this
internal check from a user-level thread-number query.

Introduce GOMP_has_masked_thread_num(int tid), a new libgomp entry point that
encapsulates the thread id check, and update lower_omp_master to call it instead
of building the comparison inline.

The C++ complains:

     [...]/libgomp/parallel.cc: In function ‘bool 
GOMP_has_masked_thread_num(int)’:
     [...]/libgomp/parallel.cc:445:14: error: comparison of integer expressions 
of different signedness: ‘int’ and ‘unsigned int’ [-Werror=sign-compare]
       445 |   return tid == gomp_thread ()->ts.team_id;
           |          ~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Is the correct/preferable fix to change the 'GOMP_has_masked_thread_num'
API (that is, 'unsigned kind'), or cast locally (which expression?)?

In lower_omp_master, filter is treated as integer_type_node (rather than unsigned_type_node). Similarly, in the OpenMP API, omp_get_thread_num is defined with an (signed) int return type. However, OpenMP defines a "thread number" as "a non-negative number". So that all seems rather inconsistent.

I would be of the opinion to cast tid to unsigned, but I may be missing something.

Thanks,

PA

Grüße
  Thomas


gcc/ChangeLog:

        * omp-builtins.def (BUILT_IN_GOMP_HAS_MASKED_THREAD_NUM): New builtin.
        * omp-low.cc (lower_omp_master): Call it.

libgomp/ChangeLog:

        * libgomp.map (GOMP_6.0.2): New symbol version. Export
        GOMP_has_masked_thread_num.
        * libgomp_g.h (GOMP_has_masked_thread_num): New declaration.
        * parallel.c (GOMP_has_masked_thread_num): New function.

gcc/testsuite/ChangeLog:

        * c-c++-common/gomp/masked-1.c: Add scan directives verifying that
        GOMP_has_masked_thread_num is emitted and omp_get_thread_num is not.
        * g++.dg/gomp/master-3.C: Update scan-tree-dump-times to look for
        GOMP_has_masked_thread_num instead of omp_get_thread_num.
        * gcc.dg/gomp/master-3.c: Likewise.
        * gfortran.dg/gomp/masked-1.f90: Add scan directive for
        GOMP_has_masked_thread_num.
---
  gcc/omp-builtins.def                        | 3 +++
  gcc/omp-low.cc                              | 5 ++---
  gcc/testsuite/c-c++-common/gomp/masked-1.c  | 6 ++++++
  gcc/testsuite/g++.dg/gomp/master-3.C        | 2 +-
  gcc/testsuite/gcc.dg/gomp/master-3.c        | 2 +-
  gcc/testsuite/gfortran.dg/gomp/masked-1.f90 | 6 +++++-
  libgomp/libgomp.map                         | 5 +++++
  libgomp/libgomp_g.h                         | 1 +
  libgomp/parallel.c                          | 9 +++++++++
  9 files changed, 33 insertions(+), 6 deletions(-)

diff --git a/gcc/omp-builtins.def b/gcc/omp-builtins.def
index f5b16c5d29e..c7ddea9880a 100644
--- a/gcc/omp-builtins.def
+++ b/gcc/omp-builtins.def
@@ -496,3 +496,6 @@ DEF_GOMP_BUILTIN (BUILT_IN_GOMP_WARNING, "GOMP_warning",
                  BT_FN_VOID_CONST_PTR_SIZE, ATTR_NOTHROW_LEAF_LIST)
  DEF_GOMP_BUILTIN (BUILT_IN_GOMP_ERROR, "GOMP_error",
                  BT_FN_VOID_CONST_PTR_SIZE, 
ATTR_COLD_NORETURN_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_HAS_MASKED_THREAD_NUM,
+                 "GOMP_has_masked_thread_num", BT_FN_BOOL_INT,
+                 ATTR_CONST_NOTHROW_LEAF_LIST)
diff --git a/gcc/omp-low.cc b/gcc/omp-low.cc
index eef0b418b9b..e067267cede 100644
--- a/gcc/omp-low.cc
+++ b/gcc/omp-low.cc
@@ -9068,9 +9068,8 @@ lower_omp_master (gimple_stmt_iterator *gsi_p, 
omp_context *ctx)
    gsi_replace (gsi_p, bind, true);
    gimple_bind_add_stmt (bind, stmt);
- bfn_decl = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
-  x = build_call_expr_loc (loc, bfn_decl, 0);
-  x = build2 (EQ_EXPR, boolean_type_node, x, filter);
+  bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_HAS_MASKED_THREAD_NUM);
+  x = build_call_expr_loc (loc, bfn_decl, 1, filter);
    x = build3 (COND_EXPR, void_type_node, x, NULL, build_and_jump (&lab));
    tseq = NULL;
    gimplify_and_add (x, &tseq);
diff --git a/gcc/testsuite/c-c++-common/gomp/masked-1.c 
b/gcc/testsuite/c-c++-common/gomp/masked-1.c
index 36c2e492892..8de87b551e3 100644
--- a/gcc/testsuite/c-c++-common/gomp/masked-1.c
+++ b/gcc/testsuite/c-c++-common/gomp/masked-1.c
@@ -1,3 +1,6 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-fdump-tree-omplower" } */
+
  void bar (void);
void
@@ -21,3 +24,6 @@ foo (int x, int *a)
    #pragma omp masked filter (x)
    ;
  }
+
+/* { dg-final { scan-tree-dump "GOMP_has_masked_thread_num" "omplower" } } */
+/* { dg-final { scan-tree-dump-not "omp_get_thread_num" "omplower" } } */
diff --git a/gcc/testsuite/g++.dg/gomp/master-3.C 
b/gcc/testsuite/g++.dg/gomp/master-3.C
index c396128afdb..3d27b936d64 100644
--- a/gcc/testsuite/g++.dg/gomp/master-3.C
+++ b/gcc/testsuite/g++.dg/gomp/master-3.C
@@ -9,4 +9,4 @@ void foo (void)
      bar(0);
  }
-/* { dg-final { scan-tree-dump-times "omp_get_thread_num" 1 "omplower" } } */
+/* { dg-final { scan-tree-dump-times "GOMP_has_masked_thread_num" 1 "omplower" 
} } */
diff --git a/gcc/testsuite/gcc.dg/gomp/master-3.c 
b/gcc/testsuite/gcc.dg/gomp/master-3.c
index 5c0544dfa3c..0d5836748ce 100644
--- a/gcc/testsuite/gcc.dg/gomp/master-3.c
+++ b/gcc/testsuite/gcc.dg/gomp/master-3.c
@@ -9,4 +9,4 @@ void foo (void)
      bar(0);
  }
-/* { dg-final { scan-tree-dump-times "omp_get_thread_num" 1 "ompexp" } } */
+/* { dg-final { scan-tree-dump-times "GOMP_has_masked_thread_num" 1 "ompexp" } 
} */
diff --git a/gcc/testsuite/gfortran.dg/gomp/masked-1.f90 
b/gcc/testsuite/gfortran.dg/gomp/masked-1.f90
index 1bd61760ced..2b2526ac712 100644
--- a/gcc/testsuite/gfortran.dg/gomp/masked-1.f90
+++ b/gcc/testsuite/gfortran.dg/gomp/masked-1.f90
@@ -1,4 +1,6 @@
-! { dg-additional-options "-ffree-line-length-none" }
+! { dg-do compile }
+! { dg-additional-options "-ffree-line-length-none -fdump-tree-omplower" }
+
  subroutine foo (x, a)
    implicit none
    integer, value :: x
@@ -92,3 +94,5 @@ subroutine foobar (d, f, fi, p, s, g, i1, i2, l, ll, nth, 
ntm, pp, q, r, r2)
      end do
    !$omp end parallel masked taskloop simd
  end subroutine
+
+! { dg-final { scan-tree-dump "GOMP_has_masked_thread_num" "omplower" } }
diff --git a/libgomp/libgomp.map b/libgomp/libgomp.map
index dbde88c4d5f..5faeb27b74b 100644
--- a/libgomp/libgomp.map
+++ b/libgomp/libgomp.map
@@ -482,6 +482,11 @@ GOMP_6.0.1 {
        omp_target_memset_async;
  } GOMP_6.0;
+GOMP_6.0.2 {
+  global:
+       GOMP_has_masked_thread_num;
+} GOMP_6.0.1;
+
  OACC_2.0 {
    global:
        acc_get_num_devices;
diff --git a/libgomp/libgomp_g.h b/libgomp/libgomp_g.h
index 761c9bd594b..d36d9d36020 100644
--- a/libgomp/libgomp_g.h
+++ b/libgomp/libgomp_g.h
@@ -293,6 +293,7 @@ extern unsigned GOMP_parallel_reductions (void (*) (void 
*), void *, unsigned,
                                          unsigned);
  extern bool GOMP_cancel (int, bool);
  extern bool GOMP_cancellation_point (int);
+extern bool GOMP_has_masked_thread_num (int);
/* task.c */ diff --git a/libgomp/parallel.c b/libgomp/parallel.c
index fe7939ddcce..175554de4c9 100644
--- a/libgomp/parallel.c
+++ b/libgomp/parallel.c
@@ -270,6 +270,15 @@ GOMP_cancel (int which, bool do_cancel)
    gomp_team_barrier_cancel (team);
    return true;
  }
+
+/* Return true if the current thread number equals TID.
+   Used to implement the masked construct's filter clause.  */
+
+bool
+GOMP_has_masked_thread_num (int tid)
+{
+  return tid == gomp_thread ()->ts.team_id;
+}
  
  /* The public OpenMP API for thread and team related inquiries.  */
--
2.53.0


--
PA

Reply via email to