[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