[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