[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