[flang] [llvm] [OMPIRBuilder] Pass work loop type in ident flags (PR #189347)

Jan André Reuter via llvm-commits llvm-commits at lists.llvm.org
Mon Mar 30 03:03:24 PDT 2026


https://github.com/Thyre created https://github.com/llvm/llvm-project/pull/189347

Flang uses the OMPIRBuilder to lower OpenMP constructs to LLVM IR.
When dealing with work sharing constructs, such as DO, DISTRIBUTE or SECTIONS/SECTION, OMPIRBuilder needs to construct the call to the OpenMP runtime, typically `__kmpc_for_static_init` or `__kmpc_dist_for_static_init`.

The first passed flag to these functions is the `ident_t` struct, defined in `kmp.h`. Most of the arguments are reserved for usage in Fortran and unused in `openmp`. However, the `flags` argument is used throughout the code base to identify specific constructs, such as the type of work sharing construct.

In https://github.com/llvm/llvm-project/issues/112545, it was identified that Flang does not provide the correct `ident_t` flags when calling into e.g. `__kmpc_for_static_init`, causing the following runtime warning to appear when the OpenMP Tools Interface is used:

```
OMP: Warning #189: OMPT: Cannot determine workshare type; using the default (loop) instead. This issue is fixed in an up-to-date compiler.
```

This PR adds a test, verifying that the work sharing constructs provide the correct flags to the runtime call. The IR check for SECTIONS/SECTION maps against `KMP_IDENT_WORK_LOOP`, as the OMPIRBuilder converts the SECTIONS construct into a DO loop with a switch-case for every SECTION clause.

In addition, `OMPIRBuilder` is modified, so that the work loop type is passed via `ident_t.flags` to the respective `__kmpc_for_static_init`/`__kmpc_dist_for_static_init` calls, letting the test pass and the `libomp` warning disappear.
Wherever possible, provide the mapping based on the passed `LoopType`. If not available, I implemented the decision based on the `DistScheduleSchedType`, or in case of `applyDynamicWorkshareLoop`, hard-coded this to `OMP_IDENT_FLAG_WORK_LOOP`.

---

As this is the first time dealing with `OMPIRBuilder`, I'm not sure if I missed anything while implementing these changes.
If there's anything that can be improved here, e.g. with the ident flag mapping, I'm very grateful for any feedback. I tried to implement this with the best of my understanding based on taking a look at the existing code and tests.

For example, I was not sure if adding a test to `flang/test/Integration/OpenMP/` is the correct approach here, or if I rather should try to modify `unittests/Frontend/OpenMPIRBuilderTest.cpp`. In the end, the former looked to me more straight-forward.

---

Fixes https://github.com/llvm/llvm-project/issues/112545

>From cc8e7609ed8d037eb3bd0de02a74fd6fed5507d8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jan=20Andr=C3=A9=20Reuter?= <jan at zyten.de>
Date: Mon, 30 Mar 2026 10:13:18 +0200
Subject: [PATCH 1/2] [NFC][Flang][OpenMP] Add test for workshare ident flag
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Flang uses the OMPIRBuilder to lower OpenMP constructs to LLVM IR.
When dealing with work sharing constructs, such as DO, DISTRIBUTE or
SECTIONS/SECTION, OMPIRBuilder needs to construct the call to the OpenMP
runtime, typically `__kmpc_for_static_init` or `__kmpc_dist_for_static_init`.

The first passed flag to these functions is the `ident_t` struct, defined in
`kmp.h`. Most of the arguments are reserved for usage in Fortran and unused in
`openmp`. However, the `flags` argument is used throughout the code base to
identify specific constructs, such as the type of work sharing construct.

In https://github.com/llvm/llvm-project/issues/112545, it was identified that
Flang does not provide the correct `ident_t` flags when calling into e.g.
`__kmpc_for_static_init`, causing the following runtime warning to appear
when the OpenMP Tools Interface is used:

```
OMP: Warning #189: OMPT: Cannot determine workshare type; using the default
(loop) instead. This issue is fixed in an up-to-date compiler.
```

This commit adds a test, verifying that the work sharing constructs indeed
to not provide the correct flags to the runtime call.
The IR check for SECTIONS/SECTION maps against `KMP_IDENT_WORK_LOOP`, as
the OMPIRBuilder converts the SECTIONS construct into a DO loop with a
switch-case for every SECTION clause.

Signed-off-by: Jan André Reuter <jan at zyten.de>
---
 .../OpenMP/workshare-ident-flag.f90           | 73 +++++++++++++++++++
 1 file changed, 73 insertions(+)
 create mode 100644 flang/test/Integration/OpenMP/workshare-ident-flag.f90

diff --git a/flang/test/Integration/OpenMP/workshare-ident-flag.f90 b/flang/test/Integration/OpenMP/workshare-ident-flag.f90
new file mode 100644
index 0000000000000..3612ba9cf7c63
--- /dev/null
+++ b/flang/test/Integration/OpenMP/workshare-ident-flag.f90
@@ -0,0 +1,73 @@
+!===----------------------------------------------------------------------===!
+! This directory can be used to add Integration tests involving multiple
+! stages of the compiler (for eg. from Fortran to LLVM IR). It should not
+! contain executable tests. We should only add tests here sparingly and only
+! if there is no other way to test. Repeat this message in each test that is
+! added to this directory and sub-directories.
+!===----------------------------------------------------------------------===!
+
+! RUN: %flang_fc1 -fopenmp -emit-llvm %s -o - | FileCheck %s
+
+! Regression test for https://github.com/llvm/llvm-project/issues/112545
+! Test if OMPIRBuilder passes the correct ident_f->flags for worksharing constructs. Intended:
+! DO: ident_t->flags == 0x200 (KMP_IDENT_WORK_LOOP) | 0x002 (KMP_IDENT_KMPC)
+! SECTIONS/SECTION: ident_t->flags == 0x200 (KMP_IDENT_WORK_LOOP) | 0x002 (KMP_IDENT_KMPC)
+! DISTRIBUTE: ident_t->flags == 0x800 (KMP_IDENT_WORK_DISTRIBUTE) | 0x002 (KMP_IDENT_KMPC)
+! DISTRIBUTE DO:
+!  ident_t->flags == 0x800 (KMP_IDENT_WORK_DISTRIBUTE) | 0x200 (KMPC_IDENT_WORK_LOOP | 0x002 (KMP_IDENT_KMPC)
+
+subroutine workshare_do_ident_flag()
+  integer :: i
+
+  !$OMP PARALLEL
+  !$OMP DO
+  do i = 1, 10
+  end do
+  !$OMP END DO
+  !$OMP END PARALLEL
+end subroutine workshare_do_ident_flag
+
+subroutine workshare_sections_ident_flag()
+  !$OMP PARALLEL
+  !$OMP SECTIONS
+  !$OMP SECTION
+  block
+  end block
+  !$OMP END SECTIONS
+  !$OMP END PARALLEL
+end subroutine workshare_sections_ident_flag
+
+subroutine workshare_distribute_ident_flag()
+  integer :: i
+
+  !$OMP TEAMS
+  !$OMP DISTRIBUTE
+  do i = 1, 10
+  end do
+  !$OMP END DISTRIBUTE
+  !$OMP END TEAMS
+end subroutine workshare_distribute_ident_flag
+
+subroutine workshare_distribute_do_ident_flag()
+  integer :: i
+
+  !$OMP TEAMS
+  !$OMP DISTRIBUTE PARALLEL DO
+  do i = 1, 10
+  end do
+  !$OMP END DISTRIBUTE PARALLEL DO
+  !$OMP END TEAMS
+end subroutine workshare_distribute_do_ident_flag
+
+! CHECK: @[[IDENT_DO:[0-9]+]] = private unnamed_addr constant %struct.ident_t { i32 {{[0-9]+}}, i32 514, i32 {{[0-9]+}}, i32 {{[0-9]+}}, ptr @0 }, align 8
+! CHECK: @[[IDENT_DISTRIBUTE:[0-9]+]] = private unnamed_addr constant %struct.ident_t { i32 {{[0-9]+}}, i32 2050, i32 {{[0-9]+}}, i32 {{[0-9]+}}, ptr @0 }, align 8
+! CHECK: @[[IDENT_DISTRIBUTE_DO:[0-9]+]] = private unnamed_addr constant %struct.ident_t { i32 {{[0-9]+}}, i32 2562, i32 {{[0-9]+}}, i32 {{[0-9]+}}, ptr @0 }, align 8
+
+! Test workshare_do_ident_flag
+! CHECK: call void @__kmpc_for_static_init_{{.*}}(ptr @[[IDENT_DO]], {{.*}})
+! Test workshare_sections_ident_flag
+! CHECK: call void @__kmpc_for_static_init_{{.*}}(ptr @[[IDENT_DO]], {{.*}})
+! Test workshare_distribute_ident_flag
+! CHECK: call void @__kmpc_for_static_init_{{.*}}(ptr @[[IDENT_DISTRIBUTE]], {{.*}})
+! Test workshare_distribute_do_ident_flag
+! CHECK: call void @__kmpc_dist_for_static_init_{{.*}}(ptr @[[IDENT_DISTRIBUTE_DO]], {{.*}})

>From 6328d207334e9373645e9f99a3b061c6964b1ccb Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jan=20Andr=C3=A9=20Reuter?= <jan at zyten.de>
Date: Mon, 30 Mar 2026 08:35:17 +0200
Subject: [PATCH 2/2] [OMPIRBuilder] Pass work loop type in ident flags
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Implement `IdentFlag` mapping for work sharing constructs to provide the
correct `ident_t.flags` to `__kmpc_for_static_init` and
`__kmpc_dist_for_static_init`. Wherever possible, provide the mapping based
on the passed `LoopType`. If not available, try to decide based on the
`DistScheduleSchedType`.

Expand `OMPKinds.def` to provide the enum values for the ident flags, based on
`kmp.h`.

Fixes https://github.com/llvm/llvm-project/issues/112545

Signed-off-by: Jan André Reuter <jan at zyten.de>
---
 .../include/llvm/Frontend/OpenMP/OMPKinds.def |  3 ++
 llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp     | 43 +++++++++++++++++--
 2 files changed, 42 insertions(+), 4 deletions(-)

diff --git a/llvm/include/llvm/Frontend/OpenMP/OMPKinds.def b/llvm/include/llvm/Frontend/OpenMP/OMPKinds.def
index 5fe7ee8997243..e0e1b832e51c9 100644
--- a/llvm/include/llvm/Frontend/OpenMP/OMPKinds.def
+++ b/llvm/include/llvm/Frontend/OpenMP/OMPKinds.def
@@ -1135,6 +1135,9 @@ __OMP_IDENT_FLAG(BARRIER_IMPL_FOR, 0x0040)
 __OMP_IDENT_FLAG(BARRIER_IMPL_SECTIONS, 0x00C0)
 __OMP_IDENT_FLAG(BARRIER_IMPL_SINGLE, 0x0140)
 __OMP_IDENT_FLAG(BARRIER_IMPL_WORKSHARE, 0x01C0)
+__OMP_IDENT_FLAG(WORK_LOOP, 0x200)
+__OMP_IDENT_FLAG(WORK_SECTIONS, 0x400)
+__OMP_IDENT_FLAG(WORK_DISTRIBUTE, 0x800)
 
 #undef __OMP_IDENT_FLAG
 #undef OMP_IDENT_FLAG
diff --git a/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp b/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
index 2bd054501506a..b25a8b1e3194a 100644
--- a/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
+++ b/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
@@ -5443,7 +5443,22 @@ OpenMPIRBuilder::InsertPointOrErrorTy OpenMPIRBuilder::applyStaticWorkshareLoop(
 
   uint32_t SrcLocStrSize;
   Constant *SrcLocStr = getOrCreateSrcLocStr(DL, SrcLocStrSize);
-  Value *SrcLoc = getOrCreateIdent(SrcLocStr, SrcLocStrSize);
+  IdentFlag Flag;
+  switch (LoopType) {
+  case WorksharingLoopType::ForStaticLoop:
+    Flag = OMP_IDENT_FLAG_WORK_LOOP;
+    break;
+  case WorksharingLoopType::DistributeStaticLoop:
+    Flag = OMP_IDENT_FLAG_WORK_DISTRIBUTE;
+    break;
+  case WorksharingLoopType::DistributeForStaticLoop:
+    Flag = OMP_IDENT_FLAG_WORK_DISTRIBUTE | OMP_IDENT_FLAG_WORK_LOOP;
+    break;
+  default:
+    Flag = IdentFlag(0);
+    break;
+  }
+  Value *SrcLoc = getOrCreateIdent(SrcLocStr, SrcLocStrSize, Flag);
 
   // Declare useful OpenMP runtime functions.
   Value *IV = CLI->getIndVar();
@@ -5666,7 +5681,11 @@ OpenMPIRBuilder::applyStaticChunkedWorkshareLoop(
   // value it produced.
   uint32_t SrcLocStrSize;
   Constant *SrcLocStr = getOrCreateSrcLocStr(DL, SrcLocStrSize);
-  Value *SrcLoc = getOrCreateIdent(SrcLocStr, SrcLocStrSize);
+  IdentFlag Flag = OMP_IDENT_FLAG_WORK_LOOP;
+  if (DistScheduleSchedType != OMPScheduleType::None) {
+    Flag |= OMP_IDENT_FLAG_WORK_DISTRIBUTE;
+  }
+  Value *SrcLoc = getOrCreateIdent(SrcLocStr, SrcLocStrSize, Flag);
   Value *ThreadNum = getOrCreateThreadID(SrcLoc);
   auto BuildInitCall = [StaticInit, SrcLoc, ThreadNum, PLastIter, PLowerBound,
                         PUpperBound, PStride, One,
@@ -5923,7 +5942,22 @@ OpenMPIRBuilder::InsertPointTy OpenMPIRBuilder::applyWorkshareLoopTarget(
     WorksharingLoopType LoopType, bool NoLoop) {
   uint32_t SrcLocStrSize;
   Constant *SrcLocStr = getOrCreateSrcLocStr(DL, SrcLocStrSize);
-  Value *Ident = getOrCreateIdent(SrcLocStr, SrcLocStrSize);
+  IdentFlag Flag;
+  switch (LoopType) {
+  case WorksharingLoopType::ForStaticLoop:
+    Flag = OMP_IDENT_FLAG_WORK_LOOP;
+    break;
+  case WorksharingLoopType::DistributeStaticLoop:
+    Flag = OMP_IDENT_FLAG_WORK_DISTRIBUTE;
+    break;
+  case WorksharingLoopType::DistributeForStaticLoop:
+    Flag = OMP_IDENT_FLAG_WORK_DISTRIBUTE | OMP_IDENT_FLAG_WORK_LOOP;
+    break;
+  default:
+    Flag = IdentFlag(0);
+    break;
+  }
+  Value *Ident = getOrCreateIdent(SrcLocStr, SrcLocStrSize, Flag);
 
   OutlineInfo OI;
   OI.OuterAllocaBB = CLI->getPreheader();
@@ -6145,7 +6179,8 @@ OpenMPIRBuilder::applyDynamicWorkshareLoop(DebugLoc DL, CanonicalLoopInfo *CLI,
 
   uint32_t SrcLocStrSize;
   Constant *SrcLocStr = getOrCreateSrcLocStr(DL, SrcLocStrSize);
-  Value *SrcLoc = getOrCreateIdent(SrcLocStr, SrcLocStrSize);
+  Value *SrcLoc =
+      getOrCreateIdent(SrcLocStr, SrcLocStrSize, OMP_IDENT_FLAG_WORK_LOOP);
 
   // Declare useful OpenMP runtime functions.
   Value *IV = CLI->getIndVar();



More information about the llvm-commits mailing list