[flang-commits] [flang] 703e9b3 - [Flang][OpenMP] Implement DEPEND clause for TASKWAIT directive (#193568)

via flang-commits flang-commits at lists.llvm.org
Wed Jul 15 07:39:49 PDT 2026


Author: Phoebe Linck
Date: 2026-07-15T15:39:44+01:00
New Revision: 703e9b3b79f1520d05fceebabfacf31af4ad4e14

URL: https://github.com/llvm/llvm-project/commit/703e9b3b79f1520d05fceebabfacf31af4ad4e14
DIFF: https://github.com/llvm/llvm-project/commit/703e9b3b79f1520d05fceebabfacf31af4ad4e14.diff

LOG: [Flang][OpenMP] Implement DEPEND clause for TASKWAIT directive (#193568)

Implements support for the `DEPEND` clause on `TASKWAIT`, added in
OpenMP 5.0.

Added: 
    flang/test/Lower/OpenMP/taskwait-depend.f90
    mlir/test/Target/LLVMIR/openmp-taskwait-depend.mlir

Modified: 
    flang/lib/Lower/OpenMP/OpenMP.cpp
    llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h
    llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
    mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp
    mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp
    mlir/test/Target/LLVMIR/openmp-todo.mlir

Removed: 
    flang/test/Lower/OpenMP/Todo/taskwait-depend.f90


################################################################################
diff  --git a/flang/lib/Lower/OpenMP/OpenMP.cpp b/flang/lib/Lower/OpenMP/OpenMP.cpp
index 8a7dde1063ea1..0d58703f3f15b 100644
--- a/flang/lib/Lower/OpenMP/OpenMP.cpp
+++ b/flang/lib/Lower/OpenMP/OpenMP.cpp
@@ -2627,8 +2627,10 @@ static void genTaskwaitClauses(lower::AbstractConverter &converter,
                                const List<Clause> &clauses, mlir::Location loc,
                                mlir::omp::TaskwaitOperands &clauseOps) {
   ClauseProcessor cp(converter, semaCtx, clauses);
-  cp.processTODO<clause::Depend, clause::Nowait>(
-      loc, llvm::omp::Directive::OMPD_taskwait);
+  lower::StatementContext stmtCtx;
+  lower::SymMap &symTable = converter.getSymbolMap();
+  cp.processDepend(symTable, stmtCtx, clauseOps);
+  cp.processTODO<clause::Nowait>(loc, llvm::omp::Directive::OMPD_taskwait);
 }
 
 static void genWorkshareClauses(lower::AbstractConverter &converter,

diff  --git a/flang/test/Lower/OpenMP/Todo/taskwait-depend.f90 b/flang/test/Lower/OpenMP/Todo/taskwait-depend.f90
deleted file mode 100644
index d1f953be8802f..0000000000000
--- a/flang/test/Lower/OpenMP/Todo/taskwait-depend.f90
+++ /dev/null
@@ -1,10 +0,0 @@
-! RUN: %not_todo_cmd bbc -emit-fir -fopenmp -o - %s -fopenmp-version=50 2>&1 | FileCheck %s
-! RUN: %not_todo_cmd %flang_fc1 -emit-fir -fopenmp -o - %s -fopenmp-version=50 2>&1 | FileCheck %s
-
-! CHECK: not yet implemented: Unhandled clause DEPEND in TASKWAIT construct
-subroutine omp_tw_depend
-  integer :: res
-  !$omp taskwait depend(out: res)
-  res = res + 1
-end subroutine omp_tw_depend
-

diff  --git a/flang/test/Lower/OpenMP/taskwait-depend.f90 b/flang/test/Lower/OpenMP/taskwait-depend.f90
new file mode 100644
index 0000000000000..21e3423fa4ae7
--- /dev/null
+++ b/flang/test/Lower/OpenMP/taskwait-depend.f90
@@ -0,0 +1,8 @@
+!RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=50 %s -o - | FileCheck %s
+
+!CHECK-LABEL: @_QPomp_taskwait_depend
+subroutine omp_taskwait_depend
+  integer :: x
+  !CHECK: omp.taskwait depend(taskdependin -> %{{.+}} : !fir.ref<i32>)
+  !$omp taskwait depend(in: x)
+end subroutine omp_taskwait_depend

diff  --git a/llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h b/llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h
index 54d14602fbdbf..fee8c712998b5 100644
--- a/llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h
+++ b/llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h
@@ -1497,11 +1497,6 @@ class OpenMPIRBuilder {
   /// \param Loc The location where the flush directive was encountered
   LLVM_ABI void createFlush(const LocationDescription &Loc);
 
-  /// Generator for '#omp taskwait'
-  ///
-  /// \param Loc The location where the taskwait directive was encountered.
-  LLVM_ABI void createTaskwait(const LocationDescription &Loc);
-
   /// Generator for '#omp taskyield'
   ///
   /// \param Loc The location where the taskyield directive was encountered.
@@ -1540,7 +1535,14 @@ class OpenMPIRBuilder {
   LLVM_ABI void emitTaskDependency(IRBuilderBase &Builder, Value *Entry,
                                    const DependData &Dep);
 
-  /// Return the LLVM struct type matching runtime `kmp_task_affinity_info_t`.
+  /// Generator for '#omp taskwait'
+  ///
+  /// \param Loc The location where the taskwait directive was encountered.
+  /// \param Dependencies dependencies as specified by the 'depend' clause.
+  LLVM_ABI void createTaskwait(const LocationDescription &Loc,
+                               DependenciesInfo Dependencies = {});
+
+  ///  Return the LLVM struct type matching runtime `kmp_task_affinity_info_t`.
   /// `{ kmp_intptr_t base_addr; size_t len; flags (bitfield storage as i32) }`
   LLVM_ABI llvm::StructType *getKmpTaskAffinityInfoTy();
 

diff  --git a/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp b/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
index 0dc704a87e4ed..dd00a3fae26e3 100644
--- a/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
+++ b/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
@@ -2184,25 +2184,6 @@ void OpenMPIRBuilder::createFlush(const LocationDescription &Loc) {
   emitFlush(Loc);
 }
 
-void OpenMPIRBuilder::emitTaskwaitImpl(const LocationDescription &Loc) {
-  // Build call kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32
-  // global_tid);
-  uint32_t SrcLocStrSize;
-  Constant *SrcLocStr = getOrCreateSrcLocStr(Loc, SrcLocStrSize);
-  Value *Ident = getOrCreateIdent(SrcLocStr, SrcLocStrSize);
-  Value *Args[] = {Ident, getOrCreateThreadID(Ident)};
-
-  // Ignore return result until untied tasks are supported.
-  createRuntimeFunctionCall(
-      getOrCreateRuntimeFunctionPtr(OMPRTL___kmpc_omp_taskwait), Args);
-}
-
-void OpenMPIRBuilder::createTaskwait(const LocationDescription &Loc) {
-  if (!updateToLocation(Loc))
-    return;
-  emitTaskwaitImpl(Loc);
-}
-
 void OpenMPIRBuilder::emitTaskyieldImpl(const LocationDescription &Loc) {
   // Build call __kmpc_omp_taskyield(loc, thread_id, 0);
   uint32_t SrcLocStrSize;
@@ -2293,6 +2274,69 @@ static Value *emitTaskDependencies(
   return DepArray;
 }
 
+void OpenMPIRBuilder::emitTaskwaitImpl(const LocationDescription &Loc) {
+  // Build call kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32
+  // global_tid);
+  uint32_t SrcLocStrSize;
+  Constant *SrcLocStr = getOrCreateSrcLocStr(Loc, SrcLocStrSize);
+  Value *Ident = getOrCreateIdent(SrcLocStr, SrcLocStrSize);
+  Value *Args[] = {Ident, getOrCreateThreadID(Ident)};
+
+  // Ignore return result until untied tasks are supported.
+  createRuntimeFunctionCall(
+      getOrCreateRuntimeFunctionPtr(OMPRTL___kmpc_omp_taskwait), Args);
+}
+
+void OpenMPIRBuilder::createTaskwait(const LocationDescription &Loc,
+                                     DependenciesInfo Dependencies) {
+  if (!updateToLocation(Loc))
+    return;
+
+  Value *DepArray = nullptr;
+  Type *DepArrayTy = nullptr;
+  Value *NumDeps = nullptr;
+  if (Dependencies.DepArray) {
+    DepArray = Dependencies.DepArray;
+    NumDeps = Dependencies.NumDeps;
+  } else if (!Dependencies.Deps.empty()) {
+    InsertPointTy OldIP = Builder.saveIP();
+    BasicBlock &entryBB =
+        Builder.GetInsertBlock()->getParent()->getEntryBlock();
+    Builder.SetInsertPoint(&entryBB, entryBB.getFirstInsertionPt());
+
+    DepArrayTy = ArrayType::get(DependInfo, Dependencies.Deps.size());
+    DepArray = Builder.CreateAlloca(DepArrayTy, nullptr, ".dep.arr.addr");
+    NumDeps = Builder.getInt32(Dependencies.Deps.size());
+
+    Builder.restoreIP(OldIP);
+    for (const auto &[DepIdx, Dep] : enumerate(Dependencies.Deps)) {
+      Value *Base =
+          Builder.CreateConstInBoundsGEP2_64(DepArrayTy, DepArray, 0, DepIdx);
+      this->emitTaskDependency(Builder, Base, Dep);
+    }
+  }
+
+  if (DepArray) {
+    uint32_t SrcLocStrSize;
+    Constant *SrcLocStr = getOrCreateSrcLocStr(Loc, SrcLocStrSize);
+    Value *Ident = getOrCreateIdent(SrcLocStr, SrcLocStrSize);
+    Value *Args[] = {
+        Ident,
+        getOrCreateThreadID(Ident),
+        NumDeps,
+        DepArray,
+        ConstantInt::get(Builder.getInt32Ty(), 0),
+        ConstantPointerNull::get(PointerType::getUnqual(M.getContext())),
+        ConstantInt::get(Builder.getInt32Ty(), false)};
+    createRuntimeFunctionCall(
+        getOrCreateRuntimeFunctionPtr(
+            omp::RuntimeFunction::OMPRTL___kmpc_omp_taskwait_deps_51),
+        Args);
+  } else {
+    emitTaskwaitImpl(Loc);
+  }
+}
+
 /// Create the task duplication function passed to kmpc_taskloop.
 Expected<Value *> OpenMPIRBuilder::createTaskDuplicationFunction(
     Type *PrivatesTy, int32_t PrivatesIndex, TaskDupCallbackTy DupCB) {

diff  --git a/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp b/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp
index 3a3798c3ad00b..67bc2bdf35619 100644
--- a/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp
+++ b/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp
@@ -4687,10 +4687,15 @@ LogicalResult OrderedRegionOp::verify() { return verifyOrderedParent(**this); }
 
 void TaskwaitOp::build(OpBuilder &builder, OperationState &state,
                        const TaskwaitOperands &clauses) {
-  // TODO Store clauses in op: dependKinds, dependVars, nowait.
-  TaskwaitOp::build(builder, state, /*depend_kinds=*/nullptr,
-                    /*depend_vars=*/{}, /*depend_iterated_kinds=*/nullptr,
-                    /*depend_iterated=*/{}, /*nowait=*/nullptr);
+  // TODO Store clauses in op: depend_iterated_kinds, depend_iterated, nowait.
+  MLIRContext *ctx = builder.getContext();
+  TaskwaitOp::build(
+      builder, state,
+      /*depend_kinds=*/makeArrayAttr(ctx, clauses.dependKinds),
+      /*depend_vars=*/clauses.dependVars,
+      /*depend_iterated_kinds=*/makeArrayAttr(ctx, clauses.dependIteratedKinds),
+      /*depend_iterated=*/ValueRange(clauses.dependIterated),
+      /*nowait=*/nullptr);
 }
 
 //===----------------------------------------------------------------------===//

diff  --git a/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp b/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp
index bd773662b8bbd..f2fefa1f5a53f 100644
--- a/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp
@@ -511,10 +511,7 @@ static LogicalResult checkImplementationStatus(Operation &op) {
         checkAllocate(op, result);
         checkTaskReductionByref(op, result);
       })
-      .Case([&](omp::TaskwaitOp op) {
-        checkDepend(op, result);
-        checkNowait(op, result);
-      })
+      .Case([&](omp::TaskwaitOp op) { checkNowait(op, result); })
       .Case([&](omp::TaskloopContextOp op) {
         checkAllocate(op, result);
         checkInReduction(op, result);
@@ -4373,7 +4370,18 @@ convertOmpTaskwaitOp(omp::TaskwaitOp twOp, llvm::IRBuilderBase &builder,
   if (failed(checkImplementationStatus(*twOp)))
     return failure();
 
-  moduleTranslation.getOpenMPBuilder()->createTaskwait(builder.saveIP());
+  llvm::OpenMPIRBuilder::DependenciesInfo dds;
+  if (failed(buildDependData(
+          twOp.getDependVars(), twOp.getDependKinds(), twOp.getDependIterated(),
+          twOp.getDependIteratedKinds(), builder, moduleTranslation, dds))) {
+    return failure();
+  }
+
+  moduleTranslation.getOpenMPBuilder()->createTaskwait(builder.saveIP(), dds);
+  if (dds.DepArray) {
+    builder.CreateFree(dds.DepArray);
+  }
+
   return success();
 }
 

diff  --git a/mlir/test/Target/LLVMIR/openmp-taskwait-depend.mlir b/mlir/test/Target/LLVMIR/openmp-taskwait-depend.mlir
new file mode 100644
index 0000000000000..24a26805df618
--- /dev/null
+++ b/mlir/test/Target/LLVMIR/openmp-taskwait-depend.mlir
@@ -0,0 +1,53 @@
+// RUN: mlir-translate --mlir-to-llvmir -split-input-file %s | FileCheck %s
+
+llvm.func @taskwait_depend(%x: !llvm.ptr) {
+  omp.taskwait depend(taskdependout -> %x : !llvm.ptr)
+  llvm.return
+}
+
+// CHECK-LABEL: define void @taskwait_depend
+// CHECK-SAME: (ptr[[xaddr:.+]])
+// CHECK: %[[dep_arr_addr:.+]] = alloca [1 x %struct.kmp_dep_info], align 8
+// CHECK: %[[omp_global_thread_num:.+]] = call i32 @__kmpc_global_thread_num({{.+}})
+// CHECK: call void @__kmpc_omp_taskwait_deps_51(ptr @{{.+}}, i32 %[[omp_global_thread_num]], i32 1, ptr %[[dep_arr_addr]], i32 0, ptr null, i32 0)
+
+llvm.func @taskwait_depend_iterator(%x: !llvm.ptr) {
+  %c1 = llvm.mlir.constant(1 : i64) : i64
+  %c10 = llvm.mlir.constant(10 : i64) : i64
+  %step = llvm.mlir.constant(1 : i64) : i64
+
+  %ix = omp.iterator(%i: i64) = (%c1 to %c10 step %step) {
+    omp.yield(%x : !llvm.ptr)
+  } -> !omp.iterated<!llvm.ptr>
+  omp.taskwait depend(taskdependin -> %ix : !omp.iterated<!llvm.ptr>)
+  llvm.return
+}
+
+// CHECK-LABEL: define void @taskwait_depend_iterator
+// CHECK-SAME: (ptr[[xaddr:.+]])
+// CHECK: %[[dep_arr_addr:.+]] = tail call ptr @malloc(i64 %mallocsize)
+//
+// CHECK: omp_dep_iterator.header:
+// CHECK: %[[iv:.*]] = phi i64 [ 0, %omp_dep_iterator.preheader ], [ %[[next:.*]], %omp_dep_iterator.inc ]
+//
+// CHECK: omp_dep_iterator.cond:
+// CHECK: %[[cmp:.*]] = icmp ult i64 %[[iv]], 10
+// CHECK: br i1 %[[cmp]], label %omp_dep_iterator.body, label %omp_dep_iterator.exit
+//
+// CHECK: omp_dep_iterator.body:
+// CHECK: %[[idx:.*]] = add i64 0, %[[iv]]
+// CHECK: %[[entry:.*]] = getelementptr inbounds %struct.kmp_dep_info, ptr %[[dep_arr_addr]], i64 %[[idx]]
+// CHECK: %[[base_gep:.*]] = getelementptr inbounds nuw %struct.kmp_dep_info, ptr %[[entry]], i32 0, i32 0
+// CHECK: %[[ptrint:.*]] = ptrtoint ptr[[xaddr]] to i64
+// CHECK: store i64 %[[ptrint]], ptr %[[base_gep]]
+// CHECK: %[[len_gep:.*]] = getelementptr inbounds nuw %struct.kmp_dep_info, ptr %[[entry]], i32 0, i32 1
+// CHECK: store i64 8, ptr %[[len_gep]]
+// CHECK: %[[flags_gep:.*]] = getelementptr inbounds nuw %struct.kmp_dep_info, ptr %[[entry]], i32 0, i32 2
+// CHECK: store i8 1, ptr %[[flags_gep]]
+//
+// CHECK: omp_dep_iterator.inc:
+// CHECK: %[[next]] = add nuw i64 %[[iv]], 1
+//
+// CHECK: %[[omp_global_thread_num:.+]] = call i32 @__kmpc_global_thread_num({{.+}})
+// CHECK: call void @__kmpc_omp_taskwait_deps_51(ptr @{{.+}}, i32 %[[omp_global_thread_num]], i32 10, ptr %[[dep_arr_addr]], i32 0, ptr null, i32 0)
+// CHECK: tail call void @free(ptr %[[dep_arr_addr:.+]])

diff  --git a/mlir/test/Target/LLVMIR/openmp-todo.mlir b/mlir/test/Target/LLVMIR/openmp-todo.mlir
index 943b5bad6970f..e29659255f690 100644
--- a/mlir/test/Target/LLVMIR/openmp-todo.mlir
+++ b/mlir/test/Target/LLVMIR/openmp-todo.mlir
@@ -624,17 +624,6 @@ llvm.func @taskloop_reduction_two_arg_init(%lb : i32, %ub : i32, %step : i32, %x
 
 // -----
 
-llvm.func @taskwait_depend(%x: !llvm.ptr) {
-  // expected-error at below {{not yet implemented: Unhandled clause depend in omp.taskwait operation}}
-  // expected-error at below {{LLVM Translation failed for operation: omp.taskwait}}
-  omp.taskwait depend(taskdependin -> %x : !llvm.ptr) {
-    omp.terminator
-  }
-  llvm.return
-}
-
-// -----
-
 llvm.func @taskwait_nowait() {
   // expected-error at below {{not yet implemented: Unhandled clause nowait in omp.taskwait operation}}
   // expected-error at below {{LLVM Translation failed for operation: omp.taskwait}}


        


More information about the flang-commits mailing list