[flang-commits] [flang] [flang][OpenMP] Support for dispatch construct (PR #225356)
via flang-commits
flang-commits at lists.llvm.org
Tue Sep 22 03:26:35 PDT 2026
https://github.com/SunilKuravinakop created https://github.com/llvm/llvm-project/pull/225356
Support for omp dispatch and omp dispatch nowait in flang.
>From cd6fcccfb8425766b679266a0263b5972b6c5040 Mon Sep 17 00:00:00 2001
From: Sunil Kuravinakop <koops at hpe.com>
Date: Tue, 22 Sep 2026 05:07:53 -0500
Subject: [PATCH] Support for omp dispatch and omp dispatch nowait in flang.
---
flang/lib/Lower/OpenMP/OpenMP.cpp | 49 ++++++++++++++++++++--
flang/lib/Semantics/rewrite-parse-tree.cpp | 5 +++
flang/test/Lower/OpenMP/Todo/dispatch.f90 | 40 ++++++++++++++----
flang/test/Lower/OpenMP/dispatch.f90 | 39 +++++++++++++++++
flang/test/Semantics/OpenMP/simd-only.f90 | 12 ++++++
5 files changed, 135 insertions(+), 10 deletions(-)
create mode 100644 flang/test/Lower/OpenMP/dispatch.f90
diff --git a/flang/lib/Lower/OpenMP/OpenMP.cpp b/flang/lib/Lower/OpenMP/OpenMP.cpp
index df14d13b76a4b..a815cb2298719 100644
--- a/flang/lib/Lower/OpenMP/OpenMP.cpp
+++ b/flang/lib/Lower/OpenMP/OpenMP.cpp
@@ -2408,6 +2408,18 @@ static void genDistributeClauses(lower::AbstractConverter &converter,
cp.processOrder(clauseOps);
}
+static void genDispatchClauses(lower::AbstractConverter &converter,
+ semantics::SemanticsContext &semaCtx,
+ lower::StatementContext &stmtCtx,
+ const List<Clause> &clauses, mlir::Location loc,
+ mlir::omp::DispatchOperands &clauseOps) {
+ ClauseProcessor cp(converter, semaCtx, clauses);
+ cp.processNowait(clauseOps);
+ cp.processTODO<clause::Depend, clause::Device, clause::IsDevicePtr,
+ clause::Novariants, clause::Nocontext>(
+ loc, llvm::omp::Directive::OMPD_dispatch);
+}
+
static void genFlushClauses(lower::AbstractConverter &converter,
semantics::SemanticsContext &semaCtx,
const ObjectList &objects,
@@ -2981,6 +2993,21 @@ genCriticalOp(lower::AbstractConverter &converter, lower::SymMap &symTable,
queue, item, nameAttr);
}
+static mlir::omp::DispatchOp genDispatchOp(
+ lower::AbstractConverter &converter, lower::SymMap &symTable,
+ lower::StatementContext &stmtCtx, semantics::SemanticsContext &semaCtx,
+ lower::pft::Evaluation &eval, mlir::Location loc,
+ const ConstructQueue &queue, ConstructQueue::const_iterator item) {
+ mlir::omp::DispatchOperands clauseOps;
+ genDispatchClauses(converter, semaCtx, stmtCtx, item->clauses, loc,
+ clauseOps);
+
+ return genOpWithBody<mlir::omp::DispatchOp>(
+ OpWithBodyGenInfo(converter, symTable, semaCtx, loc, eval,
+ llvm::omp::Directive::OMPD_dispatch),
+ queue, item, clauseOps);
+}
+
static mlir::omp::FlushOp
genFlushOp(lower::AbstractConverter &converter, lower::SymMap &symTable,
semantics::SemanticsContext &semaCtx, lower::pft::Evaluation &eval,
@@ -5731,6 +5758,10 @@ genOMPDispatch(lower::AbstractConverter &converter, lower::SymMap &symTable,
case llvm::omp::Directive::OMPD_barrier:
newOp = genBarrierOp(converter, symTable, semaCtx, eval, loc, queue, item);
break;
+ case llvm::omp::Directive::OMPD_dispatch:
+ newOp = genDispatchOp(converter, symTable, stmtCtx, semaCtx, eval, loc,
+ queue, item);
+ break;
case llvm::omp::Directive::OMPD_distribute:
newOp = genStandaloneDistribute(converter, symTable, stmtCtx, semaCtx, eval,
loc, queue, item);
@@ -8385,9 +8416,21 @@ static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable,
static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable,
semantics::SemanticsContext &semaCtx,
lower::pft::Evaluation &eval,
- const parser::OpenMPDispatchConstruct &) {
- if (!semaCtx.langOptions().OpenMPSimd)
- TODO(converter.getCurrentLocation(), "OpenMPDispatchConstruct");
+ const parser::OpenMPDispatchConstruct &dispatchConstruct) {
+ const parser::OmpDirectiveSpecification &beginSpec =
+ dispatchConstruct.BeginDir();
+ List<Clause> clauses = makeClauses(beginSpec.Clauses(), semaCtx);
+ if (auto &endSpec = dispatchConstruct.EndDir())
+ clauses.append(makeClauses(endSpec->Clauses(), semaCtx));
+
+ llvm::omp::Directive directive = beginSpec.DirId();
+ mlir::Location currentLocation = converter.genLocation(beginSpec.source);
+
+ ConstructQueue queue{
+ buildConstructQueue(converter.getFirOpBuilder().getModule(), semaCtx,
+ eval, beginSpec.source, directive, clauses)};
+ genOMPDispatch(converter, symTable, semaCtx, eval, currentLocation, queue,
+ queue.begin());
}
static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable,
diff --git a/flang/lib/Semantics/rewrite-parse-tree.cpp b/flang/lib/Semantics/rewrite-parse-tree.cpp
index a554bb61a68fb..9eb2e8fd8ec8f 100644
--- a/flang/lib/Semantics/rewrite-parse-tree.cpp
+++ b/flang/lib/Semantics/rewrite-parse-tree.cpp
@@ -193,6 +193,11 @@ void RewriteMutator::OpenMPSimdOnly(
&omp->value().u)}) {
it = replaceInlineBlock(std::get<parser::Block>(ompBlock->t), it);
continue;
+ } else if (auto *ompDispatch{
+ std::get_if<parser::OpenMPDispatchConstruct>(
+ &omp->value().u)}) {
+ it = replaceInlineBlock(std::get<parser::Block>(ompDispatch->t), it);
+ continue;
} else if (auto *ompLoop{std::get_if<parser::OpenMPLoopConstruct>(
&omp->value().u)}) {
if (LoopConstructIsSIMD(ompLoop)) {
diff --git a/flang/test/Lower/OpenMP/Todo/dispatch.f90 b/flang/test/Lower/OpenMP/Todo/dispatch.f90
index 380dfa14eaae1..160ab22c20b9b 100644
--- a/flang/test/Lower/OpenMP/Todo/dispatch.f90
+++ b/flang/test/Lower/OpenMP/Todo/dispatch.f90
@@ -1,12 +1,38 @@
-! RUN: %not_todo_cmd %flang_fc1 -emit-fir -fopenmp -fopenmp-version=51 -o - %s 2>&1 | FileCheck %s
+! RUN: %not_todo_cmd %flang_fc1 -emit-fir -fopenmp -fopenmp-version=52 -cpp -DDEPEND -o - %s 2>&1 | FileCheck %s --check-prefix=DEPEND
+! RUN: %not_todo_cmd %flang_fc1 -emit-fir -fopenmp -fopenmp-version=52 -cpp -DDEVICE -o - %s 2>&1 | FileCheck %s --check-prefix=DEVICE
+! RUN: %not_todo_cmd %flang_fc1 -emit-fir -fopenmp -fopenmp-version=52 -cpp -DIS_DEVICE_PTR -o - %s 2>&1 | FileCheck %s --check-prefix=IS_DEVICE_PTR
+! RUN: %not_todo_cmd %flang_fc1 -emit-fir -fopenmp -fopenmp-version=52 -cpp -DNOVARIANTS -o - %s 2>&1 | FileCheck %s --check-prefix=NOVARIANTS
+! RUN: %not_todo_cmd %flang_fc1 -emit-fir -fopenmp -fopenmp-version=52 -cpp -DNOCONTEXT -o - %s 2>&1 | FileCheck %s --check-prefix=NOCONTEXT
-! CHECK: not yet implemented: OpenMPDispatchConstruct
-program p
- integer r
- r = 1
-!$omp dispatch nowait
+! DEPEND: not yet implemented: Unhandled clause DEPEND in DISPATCH construct
+! DEVICE: not yet implemented: Unhandled clause DEVICE in DISPATCH construct
+! IS_DEVICE_PTR: not yet implemented: Unhandled clause IS_DEVICE_PTR in DISPATCH construct
+! NOVARIANTS: not yet implemented: Unhandled clause NOVARIANTS in DISPATCH construct
+! NOCONTEXT: not yet implemented: Unhandled clause NOCONTEXT in DISPATCH construct
+
+subroutine sub()
+#ifdef IS_DEVICE_PTR
+ use iso_c_binding
+ type(c_ptr) :: x
+#endif
+ integer :: r
+#ifdef DEPEND
+!$omp dispatch depend(inout: r)
+#endif
+#ifdef DEVICE
+!$omp dispatch device(0)
+#endif
+#ifdef IS_DEVICE_PTR
+!$omp dispatch is_device_ptr(x)
+#endif
+#ifdef NOVARIANTS
+!$omp dispatch novariants(.true.)
+#endif
+#ifdef NOCONTEXT
+!$omp dispatch nocontext(.true.)
+#endif
call foo()
contains
subroutine foo
end subroutine
-end program p
+end subroutine sub
diff --git a/flang/test/Lower/OpenMP/dispatch.f90 b/flang/test/Lower/OpenMP/dispatch.f90
new file mode 100644
index 0000000000000..d1a437be5664b
--- /dev/null
+++ b/flang/test/Lower/OpenMP/dispatch.f90
@@ -0,0 +1,39 @@
+!RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=51 %s -o - | FileCheck %s --check-prefix=HLFIR
+!RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=52 %s -o - | FileCheck %s --check-prefix=HLFIR
+!RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=60 %s -o - | FileCheck %s --check-prefix=HLFIR
+
+! Dispatch lowers to a no-op omp.dispatch region wrapping the associated call.
+! Variant selection and the nocontext/novariants clauses are added separately;
+! here the call inside the region targets the base procedure unchanged.
+
+module funcs
+ implicit none
+
+contains
+
+ !HLFIR-LABEL: func @_QMfuncsPfoo_dispatch
+ subroutine foo_dispatch()
+ print *, "in foo_dispatch"
+ end subroutine
+
+end module funcs
+
+!HLFIR-LABEL: func @_QQmain
+program dispatch_test
+ use funcs
+ implicit none
+
+ !HLFIR: omp.dispatch {
+ !$omp dispatch
+ !HLFIR: fir.call @_QMfuncsPfoo_dispatch() {{.*}}: () -> ()
+ call foo_dispatch()
+ !HLFIR: omp.terminator
+ !HLFIR: }
+
+ !HLFIR: omp.dispatch nowait {
+ !$omp dispatch nowait
+ !HLFIR: fir.call @_QMfuncsPfoo_dispatch() {{.*}}: () -> ()
+ call foo_dispatch()
+ !HLFIR: omp.terminator
+ !HLFIR: }
+end program
diff --git a/flang/test/Semantics/OpenMP/simd-only.f90 b/flang/test/Semantics/OpenMP/simd-only.f90
index 01370af0a00a7..860befaf43247 100644
--- a/flang/test/Semantics/OpenMP/simd-only.f90
+++ b/flang/test/Semantics/OpenMP/simd-only.f90
@@ -414,3 +414,15 @@ module test_declare_mapper
! CHECK-NOT: DeclarationConstruct -> SpecificationConstruct -> OpenMPDeclarativeConstruct -> OmpDeclareMapperDirective
!$omp declare mapper(myvec_t :: v) map(v, v%data(1:v%len))
end module
+
+! CHECK-LABEL: Name = 'test_dispatch'
+subroutine test_dispatch()
+ ! CHECK-NOT: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPDispatchConstruct
+ ! CHECK-NOT: OmpDirectiveName -> llvm::omp::Directive = dispatch
+ ! CHECK: ExecutionPartConstruct -> ExecutableConstruct -> ActionStmt -> CallStmt
+ !$omp dispatch
+ call foo()
+contains
+ subroutine foo()
+ end subroutine
+end subroutine
More information about the flang-commits
mailing list