[llvm] 9eb4056 - [mlir][llvm] Translation support for task detach (#116601)
via llvm-commits
llvm-commits at lists.llvm.org
Sun Dec 8 06:09:55 PST 2024
Author: NimishMishra
Date: 2024-12-08T06:09:52-08:00
New Revision: 9eb4056144a9d2e940272ba9e9675acaa3fbb354
URL: https://github.com/llvm/llvm-project/commit/9eb4056144a9d2e940272ba9e9675acaa3fbb354
DIFF: https://github.com/llvm/llvm-project/commit/9eb4056144a9d2e940272ba9e9675acaa3fbb354.diff
LOG: [mlir][llvm] Translation support for task detach (#116601)
This PR adds translation support for task detach. Essentially, if the
`detach` clause is present on a task, emit a
`__kmpc_task_allow_completion_event` on it, and store its return (of
type `kmp_event_t*`) into the `event_handle`.
Added:
Modified:
llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h
llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
mlir/include/mlir/Dialect/OpenMP/OpenMPClauses.td
mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td
mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp
mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp
mlir/test/Dialect/OpenMP/invalid.mlir
mlir/test/Dialect/OpenMP/ops.mlir
mlir/test/Target/LLVMIR/openmp-llvm.mlir
Removed:
################################################################################
diff --git a/llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h b/llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h
index a97deafa3683cf..1f0b129f867ae6 100644
--- a/llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h
+++ b/llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h
@@ -1262,12 +1262,15 @@ class OpenMPIRBuilder {
/// cannot be resumed until execution of the structured
/// block that is associated with the generated task is
/// completed.
+ /// \param EventHandle If present, signifies the event handle as part of
+ /// the detach clause
/// \param Mergeable If the given task is `mergeable`
InsertPointOrErrorTy
createTask(const LocationDescription &Loc, InsertPointTy AllocaIP,
BodyGenCallbackTy BodyGenCB, bool Tied = true,
Value *Final = nullptr, Value *IfCondition = nullptr,
- SmallVector<DependData> Dependencies = {}, bool Mergeable = false);
+ SmallVector<DependData> Dependencies = {}, bool Mergeable = false,
+ Value *EventHandle = nullptr);
/// Generator for the taskgroup construct
///
diff --git a/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp b/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
index 1fae138b449ed5..21004e6a15d495 100644
--- a/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
+++ b/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
@@ -1818,7 +1818,7 @@ static Value *emitTaskDependencies(
OpenMPIRBuilder::InsertPointOrErrorTy OpenMPIRBuilder::createTask(
const LocationDescription &Loc, InsertPointTy AllocaIP,
BodyGenCallbackTy BodyGenCB, bool Tied, Value *Final, Value *IfCondition,
- SmallVector<DependData> Dependencies, bool Mergeable) {
+ SmallVector<DependData> Dependencies, bool Mergeable, Value *EventHandle) {
if (!updateToLocation(Loc))
return InsertPointTy();
@@ -1864,7 +1864,7 @@ OpenMPIRBuilder::InsertPointOrErrorTy OpenMPIRBuilder::createTask(
Builder, AllocaIP, ToBeDeleted, TaskAllocaIP, "global.tid", false));
OI.PostOutlineCB = [this, Ident, Tied, Final, IfCondition, Dependencies,
- Mergeable, TaskAllocaBB,
+ Mergeable, EventHandle, TaskAllocaBB,
ToBeDeleted](Function &OutlinedFn) mutable {
// Replace the Stale CI by appropriate RTL function call.
assert(OutlinedFn.getNumUses() == 1 &&
@@ -1935,6 +1935,20 @@ OpenMPIRBuilder::InsertPointOrErrorTy OpenMPIRBuilder::createTask(
/*sizeof_task=*/TaskSize, /*sizeof_shared=*/SharedsSize,
/*task_func=*/&OutlinedFn});
+ // Emit detach clause initialization.
+ // evt = (typeof(evt))__kmpc_task_allow_completion_event(loc, tid,
+ // task_descriptor);
+ if (EventHandle) {
+ Function *TaskDetachFn = getOrCreateRuntimeFunctionPtr(
+ OMPRTL___kmpc_task_allow_completion_event);
+ llvm::Value *EventVal =
+ Builder.CreateCall(TaskDetachFn, {Ident, ThreadID, TaskData});
+ llvm::Value *EventHandleAddr =
+ Builder.CreatePointerBitCastOrAddrSpaceCast(EventHandle,
+ Builder.getPtrTy(0));
+ EventVal = Builder.CreatePtrToInt(EventVal, Builder.getInt64Ty());
+ Builder.CreateStore(EventVal, EventHandleAddr);
+ }
// Copy the arguments for outlined function
if (HasShareds) {
Value *Shareds = StaleCI->getArgOperand(1);
diff --git a/mlir/include/mlir/Dialect/OpenMP/OpenMPClauses.td b/mlir/include/mlir/Dialect/OpenMP/OpenMPClauses.td
index 855deab94b2f16..077d6602628aa0 100644
--- a/mlir/include/mlir/Dialect/OpenMP/OpenMPClauses.td
+++ b/mlir/include/mlir/Dialect/OpenMP/OpenMPClauses.td
@@ -909,6 +909,34 @@ class OpenMP_ParallelizationLevelClauseSkip<
def OpenMP_ParallelizationLevelClause : OpenMP_ParallelizationLevelClauseSkip<>;
+//===----------------------------------------------------------------------===//
+// OpenMPV5.2: [12.5.2] `detach` clause
+//===----------------------------------------------------------------------===//
+
+class OpenMP_DetachClauseSkip<
+ bit traits = false, bit arguments = false, bit assemblyFormat = false,
+ bit description = false, bit extraClassDeclaration = false>
+ : OpenMP_Clause<traits, arguments, assemblyFormat, description,
+ extraClassDeclaration> {
+
+ let traits = [BlockArgOpenMPOpInterface];
+
+ let arguments = (ins Optional<OpenMP_PointerLikeType>:$event_handle);
+
+ let optAssemblyFormat = [{
+ `detach` `(` $event_handle `:` type($event_handle) `)`
+ }];
+
+ let description = [{
+ The detach clause specifies that the task generated by the construct on which it appears is a
+ detachable task. A new allow-completion event is created and connected to the completion of the
+ associated task region. The original event-handle is updated to represent that allow-completion
+ event before the task data environment is created.
+ }];
+}
+
+def OpenMP_DetachClause : OpenMP_DetachClauseSkip<>;
+
//===----------------------------------------------------------------------===//
// V5.2: [12.4] `priority` clause
//===----------------------------------------------------------------------===//
diff --git a/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td b/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td
index f6c7f19fffddf9..85b6a6638036fb 100644
--- a/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td
+++ b/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td
@@ -657,15 +657,18 @@ def DistributeOp : OpenMP_Op<"distribute", traits = [
// 2.10.1 task Construct
//===----------------------------------------------------------------------===//
-def TaskOp : OpenMP_Op<"task", traits = [
- AttrSizedOperandSegments, AutomaticAllocationScope,
- OutlineableOpenMPOpInterface
- ], clauses = [
- // TODO: Complete clause list (affinity, detach).
- OpenMP_AllocateClause, OpenMP_DependClause, OpenMP_FinalClause,
- OpenMP_IfClause, OpenMP_InReductionClause, OpenMP_MergeableClause,
- OpenMP_PriorityClause, OpenMP_PrivateClause, OpenMP_UntiedClause
- ], singleRegion = true> {
+def TaskOp
+ : OpenMP_Op<"task",
+ traits = [AttrSizedOperandSegments, AutomaticAllocationScope,
+ OutlineableOpenMPOpInterface],
+ clauses = [
+ // TODO: Complete clause list (affinity, detach).
+ OpenMP_AllocateClause, OpenMP_DependClause,
+ OpenMP_FinalClause, OpenMP_IfClause,
+ OpenMP_InReductionClause, OpenMP_MergeableClause,
+ OpenMP_PriorityClause, OpenMP_PrivateClause,
+ OpenMP_UntiedClause, OpenMP_DetachClause],
+ singleRegion = true> {
let summary = "task construct";
let description = [{
The task construct defines an explicit task.
diff --git a/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp b/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp
index 6d7dbbf58bbda7..e20530be07b2f9 100644
--- a/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp
+++ b/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp
@@ -2303,7 +2303,7 @@ void TaskOp::build(OpBuilder &builder, OperationState &state,
makeArrayAttr(ctx, clauses.inReductionSyms), clauses.mergeable,
clauses.priority, /*private_vars=*/clauses.privateVars,
/*private_syms=*/makeArrayAttr(ctx, clauses.privateSyms),
- clauses.untied);
+ clauses.untied, clauses.eventHandle);
}
LogicalResult TaskOp::verify() {
diff --git a/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp b/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp
index 063055f8015b81..946c3c423267dd 100644
--- a/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp
@@ -1703,7 +1703,8 @@ convertOmpTaskOp(omp::TaskOp taskOp, llvm::IRBuilderBase &builder,
ompLoc, allocaIP, bodyCB, !taskOp.getUntied(),
moduleTranslation.lookupValue(taskOp.getFinal()),
moduleTranslation.lookupValue(taskOp.getIfExpr()), dds,
- taskOp.getMergeable());
+ taskOp.getMergeable(),
+ moduleTranslation.lookupValue(taskOp.getEventHandle()));
if (failed(handleError(afterIP, *taskOp)))
return failure();
diff --git a/mlir/test/Dialect/OpenMP/invalid.mlir b/mlir/test/Dialect/OpenMP/invalid.mlir
index 2a19e4837f5504..1fbb4c93e855b9 100644
--- a/mlir/test/Dialect/OpenMP/invalid.mlir
+++ b/mlir/test/Dialect/OpenMP/invalid.mlir
@@ -1634,7 +1634,7 @@ func.func @omp_single_copyprivate(%data_var : memref<i32>) -> () {
// -----
func.func @omp_task_depend(%data_var: memref<i32>) {
- // expected-error @below {{op expected as many depend values as depend variables}}
+ // expected-error @below {{'omp.task' op operand count (1) does not match with the total size (0) specified in attribute 'operandSegmentSizes'}}
"omp.task"(%data_var) ({
"omp.terminator"() : () -> ()
}) {depend_kinds = [], operandSegmentSizes = array<i32: 0, 0, 1, 0, 0, 0, 0, 0>} : (memref<i32>) -> ()
diff --git a/mlir/test/Dialect/OpenMP/ops.mlir b/mlir/test/Dialect/OpenMP/ops.mlir
index 94c63dd8e9aa0e..26943068ed95a4 100644
--- a/mlir/test/Dialect/OpenMP/ops.mlir
+++ b/mlir/test/Dialect/OpenMP/ops.mlir
@@ -1975,8 +1975,8 @@ func.func @omp_single_copyprivate(%data_var: memref<i32>) {
}
// CHECK-LABEL: @omp_task
-// CHECK-SAME: (%[[bool_var:.*]]: i1, %[[i64_var:.*]]: i64, %[[i32_var:.*]]: i32, %[[data_var:.*]]: memref<i32>)
-func.func @omp_task(%bool_var: i1, %i64_var: i64, %i32_var: i32, %data_var: memref<i32>) {
+// CHECK-SAME: (%[[bool_var:.*]]: i1, %[[i64_var:.*]]: i64, %[[i32_var:.*]]: i32, %[[data_var:.*]]: memref<i32>, %[[event_handle:.*]]: !llvm.ptr)
+func.func @omp_task(%bool_var: i1, %i64_var: i64, %i32_var: i32, %data_var: memref<i32>, %event_handle : !llvm.ptr) {
// Checking simple task
// CHECK: omp.task {
@@ -2054,7 +2054,11 @@ func.func @omp_task(%bool_var: i1, %i64_var: i64, %i32_var: i32, %data_var: memr
// CHECK: omp.terminator
omp.terminator
}
-
+ // Checking detach clause
+ // CHECK: omp.task detach(%[[event_handle]] : !llvm.ptr)
+ omp.task detach(%event_handle : !llvm.ptr){
+ omp.terminator
+ }
// Checking multiple clauses
// CHECK: omp.task allocate(%[[data_var]] : memref<i32> -> %[[data_var]] : memref<i32>)
omp.task allocate(%data_var : memref<i32> -> %data_var : memref<i32>)
diff --git a/mlir/test/Target/LLVMIR/openmp-llvm.mlir b/mlir/test/Target/LLVMIR/openmp-llvm.mlir
index b40ec0a831d2e8..5f8bdf8afdf783 100644
--- a/mlir/test/Target/LLVMIR/openmp-llvm.mlir
+++ b/mlir/test/Target/LLVMIR/openmp-llvm.mlir
@@ -2505,6 +2505,23 @@ llvm.mlir.global internal @_QFsubEx() : i32
// -----
+// CHECK-LABEL: define void @omp_task_detach
+// CHECK-SAME: (ptr %[[event_handle:.*]])
+llvm.func @omp_task_detach(%event_handle : !llvm.ptr){
+ // CHECK: %[[omp_global_thread_num:.+]] = call i32 @__kmpc_global_thread_num({{.+}})
+ // CHECK: %[[task_data:.+]] = call ptr @__kmpc_omp_task_alloc
+ // CHECK: %[[return_val:.*]] = call ptr @__kmpc_task_allow_completion_event(ptr {{.*}}, i32 %[[omp_global_thread_num]], ptr %[[task_data]])
+ // CHECK: %[[conv:.*]] = ptrtoint ptr %[[return_val]] to i64
+ // CHECK: store i64 %[[conv]], ptr %[[event_handle]], align 4
+ // CHECK: call i32 @__kmpc_omp_task(ptr @{{.+}}, i32 %[[omp_global_thread_num]], ptr %[[task_data]])
+ omp.task detach(%event_handle : !llvm.ptr){
+ omp.terminator
+ }
+ llvm.return
+}
+
+// -----
+
// CHECK-LABEL: define void @omp_task
// CHECK-SAME: (i32 %[[x:.+]], i32 %[[y:.+]], ptr %[[zaddr:.+]])
llvm.func @omp_task(%x: i32, %y: i32, %zaddr: !llvm.ptr) {
More information about the llvm-commits
mailing list