-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[Flang] [OpenMP] Add LLVM lowering support for PRIORITY in TASK #120710
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Flang] [OpenMP] Add LLVM lowering support for PRIORITY in TASK #120710
Conversation
Implementation details: The PRIORITY clause is recognized by setting the flags = 32 to the `__kmpc_omp_task_alloc` runtime call. Also, Store the priority-value to the `kmp_task_t` struct
@llvm/pr-subscribers-mlir-openmp @llvm/pr-subscribers-flang-openmp Author: Thirumalai Shaktivel (Thirumalai-Shaktivel) ChangesImplementation details: Full diff: https://github.com/llvm/llvm-project/pull/120710.diff 5 Files Affected:
diff --git a/llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h b/llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h
index 9a7c7f72711cc5..c9b08218ca6770 100644
--- a/llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h
+++ b/llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h
@@ -1265,12 +1265,14 @@ class OpenMPIRBuilder {
/// \param EventHandle If present, signifies the event handle as part of
/// the detach clause
/// \param Mergeable If the given task is `mergeable`
+ /// \param priority `priority-value' specifies the execution order of the
+ /// tasks that is generated by the construct
InsertPointOrErrorTy
createTask(const LocationDescription &Loc, InsertPointTy AllocaIP,
BodyGenCallbackTy BodyGenCB, bool Tied = true,
Value *Final = nullptr, Value *IfCondition = nullptr,
SmallVector<DependData> Dependencies = {}, bool Mergeable = false,
- Value *EventHandle = nullptr);
+ Value *EventHandle = nullptr, Value *Priority = nullptr);
/// Generator for the taskgroup construct
///
diff --git a/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp b/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
index 0d8dbbe3a8a718..7a36aaad277249 100644
--- a/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
+++ b/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
@@ -1818,7 +1818,8 @@ 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, Value *EventHandle) {
+ SmallVector<DependData> Dependencies, bool Mergeable, Value *EventHandle,
+ Value *Priority) {
if (!updateToLocation(Loc))
return InsertPointTy();
@@ -1864,7 +1865,7 @@ OpenMPIRBuilder::InsertPointOrErrorTy OpenMPIRBuilder::createTask(
Builder, AllocaIP, ToBeDeleted, TaskAllocaIP, "global.tid", false));
OI.PostOutlineCB = [this, Ident, Tied, Final, IfCondition, Dependencies,
- Mergeable, EventHandle, TaskAllocaBB,
+ Mergeable, Priority, EventHandle, TaskAllocaBB,
ToBeDeleted](Function &OutlinedFn) mutable {
// Replace the Stale CI by appropriate RTL function call.
assert(OutlinedFn.getNumUses() == 1 &&
@@ -1892,6 +1893,8 @@ OpenMPIRBuilder::InsertPointOrErrorTy OpenMPIRBuilder::createTask(
// Task is not final iff (Flags & 2) == 0.
// Task is mergeable iff (Flags & 4) == 4.
// Task is not mergeable iff (Flags & 4) == 0.
+ // Task is priority iff (Flags & 32) == 32.
+ // Task is not priority iff (Flags & 32) == 0.
// TODO: Handle the other flags.
Value *Flags = Builder.getInt32(Tied);
if (Final) {
@@ -1902,6 +1905,8 @@ OpenMPIRBuilder::InsertPointOrErrorTy OpenMPIRBuilder::createTask(
if (Mergeable)
Flags = Builder.CreateOr(Builder.getInt32(4), Flags);
+ if (Priority)
+ Flags = Builder.CreateOr(Builder.getInt32(32), Flags);
// Argument - `sizeof_kmp_task_t` (TaskSize)
// Tasksize refers to the size in bytes of kmp_task_t data structure
@@ -1958,6 +1963,30 @@ OpenMPIRBuilder::InsertPointOrErrorTy OpenMPIRBuilder::createTask(
SharedsSize);
}
+ if (Priority) {
+ //
+ // The return type of "__kmpc_omp_task_alloc" is "kmp_task_t *",
+ // we populate the priority information into the "kmp_task_t" here
+ //
+ // The struct "kmp_task_t" definition is available in kmp.h
+ // kmp_task_t = { shareds, routine, part_id, data1, data2 }
+ // data2 is used for priority
+ //
+ Type *Int32Ty = Builder.getInt32Ty();
+ // kmp_task_t* => { ptr }
+ Type *taskPtr = StructType::get(VoidPtr);
+ Value *taskGEP = Builder.CreateInBoundsGEP(
+ taskPtr, TaskData,
+ {ConstantInt::get(Int32Ty, 0), ConstantInt::get(Int32Ty, 0)});
+ // kmp_task_t => { ptr, ptr, i32, ptr, ptr }
+ Type *taskStructType = StructType::get(
+ VoidPtr, VoidPtr, Builder.getInt32Ty(), VoidPtr, VoidPtr);
+ Value *priorityData = Builder.CreateInBoundsGEP(
+ taskStructType, taskGEP,
+ {ConstantInt::get(Int32Ty, 0), ConstantInt::get(Int32Ty, 4)});
+ Builder.CreateStore(Priority, priorityData);
+ }
+
Value *DepArray = nullptr;
if (Dependencies.size()) {
InsertPointTy OldIP = Builder.saveIP();
diff --git a/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp b/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp
index 060113c4123241..c4e72b16cc221b 100644
--- a/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp
@@ -257,7 +257,6 @@ static LogicalResult checkImplementationStatus(Operation &op) {
.Case([&](omp::TaskOp op) {
checkAllocate(op, result);
checkInReduction(op, result);
- checkPriority(op, result);
checkUntied(op, result);
})
.Case([&](omp::TaskgroupOp op) {
@@ -273,6 +272,11 @@ static LogicalResult checkImplementationStatus(Operation &op) {
checkLinear(op, result);
checkOrder(op, result);
})
+ .Case([&](omp::TaskloopOp op) {
+ // TODO: Add other clauses check
+ checkPriority(op, result);
+ checkUntied(op, result);
+ })
.Case([&](omp::ParallelOp op) { checkAllocate(op, result); })
.Case([&](omp::SimdOp op) {
checkAligned(op, result);
@@ -1775,7 +1779,8 @@ convertOmpTaskOp(omp::TaskOp taskOp, llvm::IRBuilderBase &builder,
moduleTranslation.lookupValue(taskOp.getFinal()),
moduleTranslation.lookupValue(taskOp.getIfExpr()), dds,
taskOp.getMergeable(),
- moduleTranslation.lookupValue(taskOp.getEventHandle()));
+ moduleTranslation.lookupValue(taskOp.getEventHandle()),
+ moduleTranslation.lookupValue(taskOp.getPriority()));
if (failed(handleError(afterIP, *taskOp)))
return failure();
diff --git a/mlir/test/Target/LLVMIR/openmp-llvm.mlir b/mlir/test/Target/LLVMIR/openmp-llvm.mlir
index 5f8bdf8afdf783..fc21a008bf7caa 100644
--- a/mlir/test/Target/LLVMIR/openmp-llvm.mlir
+++ b/mlir/test/Target/LLVMIR/openmp-llvm.mlir
@@ -2834,6 +2834,42 @@ llvm.func @omp_taskgroup_task(%x: i32, %y: i32, %zaddr: !llvm.ptr) {
// -----
+llvm.func @test_01() attributes {sym_visibility = "private"}
+llvm.func @test_02() attributes {sym_visibility = "private"}
+// CHECK-LABEL: define void @_QPomp_task_priority() {
+llvm.func @_QPomp_task_priority() {
+ %0 = llvm.mlir.constant(1 : i64) : i64
+ %1 = llvm.alloca %0 x i32 {bindc_name = "x"} : (i64) -> !llvm.ptr
+ %2 = llvm.mlir.constant(4 : i32) : i32
+ %3 = llvm.mlir.constant(true) : i1
+ %4 = llvm.load %1 : !llvm.ptr -> i32
+// CHECK: %[[Gid_01:.*]] = call i32 @__kmpc_global_thread_num(ptr {{.*}})
+// CHECK: %[[I_01:.*]] = call ptr @__kmpc_omp_task_alloc(ptr {{.*}}, i32 %[[Gid_01:.*]], i32 33, i64 40, i64 0, ptr @{{.*}})
+// CHECK: %[[I_02:.*]] = getelementptr inbounds { ptr }, ptr %[[I_01:.*]], i32 0, i32 0
+// CHECK: %[[I_03:.*]] = getelementptr inbounds { ptr, ptr, i32, ptr, ptr }, ptr %[[I_02:.*]], i32 0, i32 4
+// CHECK: store i32 %[[I_00:.*]], ptr %[[I_03:.*]], align 4
+// CHECK: %{{.*}} = call i32 @__kmpc_omp_task(ptr {{.*}}, i32 %[[Gid_01:.*]], ptr %[[I_01:.*]])
+ omp.task priority(%4 : i32) {
+ llvm.call @test_01() : () -> ()
+ omp.terminator
+ }
+// CHECK: %[[Gid_02:.*]] = call i32 @__kmpc_global_thread_num(ptr {{.*}})
+// CHECK: %[[I_04:.*]] = call ptr @__kmpc_omp_task_alloc(ptr {{.*}}, i32 %[[Gid_02:.*]], i32 35, i64 40, i64 0, ptr @{{.*}})
+// CHECK: %[[I_05:.*]] = getelementptr inbounds { ptr }, ptr %[[I_04:.*]], i32 0, i32 0
+// CHECK: %[[I_06:.*]] = getelementptr inbounds { ptr, ptr, i32, ptr, ptr }, ptr %[[I_05:.*]], i32 0, i32 4
+// CHECK: store i32 4, ptr %[[I_06:.*]], align 4
+// CHECK: %{{.*}} = call i32 @__kmpc_omp_task(ptr {{.*}}, i32 %[[Gid_02:.*]], ptr %[[I_04:.*]])
+ omp.task final(%3) priority(%2 : i32) {
+ llvm.call @test_02() : () -> ()
+ omp.terminator
+ }
+ llvm.return
+// CHECK: ret void
+// CHECK: }
+}
+
+// -----
+
// CHECK-LABEL: @omp_opaque_pointers
// CHECK-SAME: (ptr %[[ARG0:.*]], ptr %[[ARG1:.*]], i32 %[[EXPR:.*]])
llvm.func @omp_opaque_pointers(%arg0 : !llvm.ptr, %arg1: !llvm.ptr, %expr: i32) -> () {
diff --git a/mlir/test/Target/LLVMIR/openmp-todo.mlir b/mlir/test/Target/LLVMIR/openmp-todo.mlir
index 8f3e466cfbbeb6..6bbf34502b4970 100644
--- a/mlir/test/Target/LLVMIR/openmp-todo.mlir
+++ b/mlir/test/Target/LLVMIR/openmp-todo.mlir
@@ -429,17 +429,6 @@ llvm.func @task_in_reduction(%x : !llvm.ptr) {
// -----
-llvm.func @task_priority(%x : i32) {
- // expected-error@below {{not yet implemented: Unhandled clause priority in omp.task operation}}
- // expected-error@below {{LLVM Translation failed for operation: omp.task}}
- omp.task priority(%x : i32) {
- omp.terminator
- }
- llvm.return
-}
-
-// -----
-
llvm.func @task_untied() {
// expected-error@below {{not yet implemented: Unhandled clause untied in omp.task operation}}
// expected-error@below {{LLVM Translation failed for operation: omp.task}}
|
@llvm/pr-subscribers-flang-codegen Author: Thirumalai Shaktivel (Thirumalai-Shaktivel) ChangesImplementation details: Full diff: https://github.com/llvm/llvm-project/pull/120710.diff 5 Files Affected:
diff --git a/llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h b/llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h
index 9a7c7f72711cc5..c9b08218ca6770 100644
--- a/llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h
+++ b/llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h
@@ -1265,12 +1265,14 @@ class OpenMPIRBuilder {
/// \param EventHandle If present, signifies the event handle as part of
/// the detach clause
/// \param Mergeable If the given task is `mergeable`
+ /// \param priority `priority-value' specifies the execution order of the
+ /// tasks that is generated by the construct
InsertPointOrErrorTy
createTask(const LocationDescription &Loc, InsertPointTy AllocaIP,
BodyGenCallbackTy BodyGenCB, bool Tied = true,
Value *Final = nullptr, Value *IfCondition = nullptr,
SmallVector<DependData> Dependencies = {}, bool Mergeable = false,
- Value *EventHandle = nullptr);
+ Value *EventHandle = nullptr, Value *Priority = nullptr);
/// Generator for the taskgroup construct
///
diff --git a/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp b/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
index 0d8dbbe3a8a718..7a36aaad277249 100644
--- a/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
+++ b/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
@@ -1818,7 +1818,8 @@ 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, Value *EventHandle) {
+ SmallVector<DependData> Dependencies, bool Mergeable, Value *EventHandle,
+ Value *Priority) {
if (!updateToLocation(Loc))
return InsertPointTy();
@@ -1864,7 +1865,7 @@ OpenMPIRBuilder::InsertPointOrErrorTy OpenMPIRBuilder::createTask(
Builder, AllocaIP, ToBeDeleted, TaskAllocaIP, "global.tid", false));
OI.PostOutlineCB = [this, Ident, Tied, Final, IfCondition, Dependencies,
- Mergeable, EventHandle, TaskAllocaBB,
+ Mergeable, Priority, EventHandle, TaskAllocaBB,
ToBeDeleted](Function &OutlinedFn) mutable {
// Replace the Stale CI by appropriate RTL function call.
assert(OutlinedFn.getNumUses() == 1 &&
@@ -1892,6 +1893,8 @@ OpenMPIRBuilder::InsertPointOrErrorTy OpenMPIRBuilder::createTask(
// Task is not final iff (Flags & 2) == 0.
// Task is mergeable iff (Flags & 4) == 4.
// Task is not mergeable iff (Flags & 4) == 0.
+ // Task is priority iff (Flags & 32) == 32.
+ // Task is not priority iff (Flags & 32) == 0.
// TODO: Handle the other flags.
Value *Flags = Builder.getInt32(Tied);
if (Final) {
@@ -1902,6 +1905,8 @@ OpenMPIRBuilder::InsertPointOrErrorTy OpenMPIRBuilder::createTask(
if (Mergeable)
Flags = Builder.CreateOr(Builder.getInt32(4), Flags);
+ if (Priority)
+ Flags = Builder.CreateOr(Builder.getInt32(32), Flags);
// Argument - `sizeof_kmp_task_t` (TaskSize)
// Tasksize refers to the size in bytes of kmp_task_t data structure
@@ -1958,6 +1963,30 @@ OpenMPIRBuilder::InsertPointOrErrorTy OpenMPIRBuilder::createTask(
SharedsSize);
}
+ if (Priority) {
+ //
+ // The return type of "__kmpc_omp_task_alloc" is "kmp_task_t *",
+ // we populate the priority information into the "kmp_task_t" here
+ //
+ // The struct "kmp_task_t" definition is available in kmp.h
+ // kmp_task_t = { shareds, routine, part_id, data1, data2 }
+ // data2 is used for priority
+ //
+ Type *Int32Ty = Builder.getInt32Ty();
+ // kmp_task_t* => { ptr }
+ Type *taskPtr = StructType::get(VoidPtr);
+ Value *taskGEP = Builder.CreateInBoundsGEP(
+ taskPtr, TaskData,
+ {ConstantInt::get(Int32Ty, 0), ConstantInt::get(Int32Ty, 0)});
+ // kmp_task_t => { ptr, ptr, i32, ptr, ptr }
+ Type *taskStructType = StructType::get(
+ VoidPtr, VoidPtr, Builder.getInt32Ty(), VoidPtr, VoidPtr);
+ Value *priorityData = Builder.CreateInBoundsGEP(
+ taskStructType, taskGEP,
+ {ConstantInt::get(Int32Ty, 0), ConstantInt::get(Int32Ty, 4)});
+ Builder.CreateStore(Priority, priorityData);
+ }
+
Value *DepArray = nullptr;
if (Dependencies.size()) {
InsertPointTy OldIP = Builder.saveIP();
diff --git a/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp b/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp
index 060113c4123241..c4e72b16cc221b 100644
--- a/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp
@@ -257,7 +257,6 @@ static LogicalResult checkImplementationStatus(Operation &op) {
.Case([&](omp::TaskOp op) {
checkAllocate(op, result);
checkInReduction(op, result);
- checkPriority(op, result);
checkUntied(op, result);
})
.Case([&](omp::TaskgroupOp op) {
@@ -273,6 +272,11 @@ static LogicalResult checkImplementationStatus(Operation &op) {
checkLinear(op, result);
checkOrder(op, result);
})
+ .Case([&](omp::TaskloopOp op) {
+ // TODO: Add other clauses check
+ checkPriority(op, result);
+ checkUntied(op, result);
+ })
.Case([&](omp::ParallelOp op) { checkAllocate(op, result); })
.Case([&](omp::SimdOp op) {
checkAligned(op, result);
@@ -1775,7 +1779,8 @@ convertOmpTaskOp(omp::TaskOp taskOp, llvm::IRBuilderBase &builder,
moduleTranslation.lookupValue(taskOp.getFinal()),
moduleTranslation.lookupValue(taskOp.getIfExpr()), dds,
taskOp.getMergeable(),
- moduleTranslation.lookupValue(taskOp.getEventHandle()));
+ moduleTranslation.lookupValue(taskOp.getEventHandle()),
+ moduleTranslation.lookupValue(taskOp.getPriority()));
if (failed(handleError(afterIP, *taskOp)))
return failure();
diff --git a/mlir/test/Target/LLVMIR/openmp-llvm.mlir b/mlir/test/Target/LLVMIR/openmp-llvm.mlir
index 5f8bdf8afdf783..fc21a008bf7caa 100644
--- a/mlir/test/Target/LLVMIR/openmp-llvm.mlir
+++ b/mlir/test/Target/LLVMIR/openmp-llvm.mlir
@@ -2834,6 +2834,42 @@ llvm.func @omp_taskgroup_task(%x: i32, %y: i32, %zaddr: !llvm.ptr) {
// -----
+llvm.func @test_01() attributes {sym_visibility = "private"}
+llvm.func @test_02() attributes {sym_visibility = "private"}
+// CHECK-LABEL: define void @_QPomp_task_priority() {
+llvm.func @_QPomp_task_priority() {
+ %0 = llvm.mlir.constant(1 : i64) : i64
+ %1 = llvm.alloca %0 x i32 {bindc_name = "x"} : (i64) -> !llvm.ptr
+ %2 = llvm.mlir.constant(4 : i32) : i32
+ %3 = llvm.mlir.constant(true) : i1
+ %4 = llvm.load %1 : !llvm.ptr -> i32
+// CHECK: %[[Gid_01:.*]] = call i32 @__kmpc_global_thread_num(ptr {{.*}})
+// CHECK: %[[I_01:.*]] = call ptr @__kmpc_omp_task_alloc(ptr {{.*}}, i32 %[[Gid_01:.*]], i32 33, i64 40, i64 0, ptr @{{.*}})
+// CHECK: %[[I_02:.*]] = getelementptr inbounds { ptr }, ptr %[[I_01:.*]], i32 0, i32 0
+// CHECK: %[[I_03:.*]] = getelementptr inbounds { ptr, ptr, i32, ptr, ptr }, ptr %[[I_02:.*]], i32 0, i32 4
+// CHECK: store i32 %[[I_00:.*]], ptr %[[I_03:.*]], align 4
+// CHECK: %{{.*}} = call i32 @__kmpc_omp_task(ptr {{.*}}, i32 %[[Gid_01:.*]], ptr %[[I_01:.*]])
+ omp.task priority(%4 : i32) {
+ llvm.call @test_01() : () -> ()
+ omp.terminator
+ }
+// CHECK: %[[Gid_02:.*]] = call i32 @__kmpc_global_thread_num(ptr {{.*}})
+// CHECK: %[[I_04:.*]] = call ptr @__kmpc_omp_task_alloc(ptr {{.*}}, i32 %[[Gid_02:.*]], i32 35, i64 40, i64 0, ptr @{{.*}})
+// CHECK: %[[I_05:.*]] = getelementptr inbounds { ptr }, ptr %[[I_04:.*]], i32 0, i32 0
+// CHECK: %[[I_06:.*]] = getelementptr inbounds { ptr, ptr, i32, ptr, ptr }, ptr %[[I_05:.*]], i32 0, i32 4
+// CHECK: store i32 4, ptr %[[I_06:.*]], align 4
+// CHECK: %{{.*}} = call i32 @__kmpc_omp_task(ptr {{.*}}, i32 %[[Gid_02:.*]], ptr %[[I_04:.*]])
+ omp.task final(%3) priority(%2 : i32) {
+ llvm.call @test_02() : () -> ()
+ omp.terminator
+ }
+ llvm.return
+// CHECK: ret void
+// CHECK: }
+}
+
+// -----
+
// CHECK-LABEL: @omp_opaque_pointers
// CHECK-SAME: (ptr %[[ARG0:.*]], ptr %[[ARG1:.*]], i32 %[[EXPR:.*]])
llvm.func @omp_opaque_pointers(%arg0 : !llvm.ptr, %arg1: !llvm.ptr, %expr: i32) -> () {
diff --git a/mlir/test/Target/LLVMIR/openmp-todo.mlir b/mlir/test/Target/LLVMIR/openmp-todo.mlir
index 8f3e466cfbbeb6..6bbf34502b4970 100644
--- a/mlir/test/Target/LLVMIR/openmp-todo.mlir
+++ b/mlir/test/Target/LLVMIR/openmp-todo.mlir
@@ -429,17 +429,6 @@ llvm.func @task_in_reduction(%x : !llvm.ptr) {
// -----
-llvm.func @task_priority(%x : i32) {
- // expected-error@below {{not yet implemented: Unhandled clause priority in omp.task operation}}
- // expected-error@below {{LLVM Translation failed for operation: omp.task}}
- omp.task priority(%x : i32) {
- omp.terminator
- }
- llvm.return
-}
-
-// -----
-
llvm.func @task_untied() {
// expected-error@below {{not yet implemented: Unhandled clause untied in omp.task operation}}
// expected-error@below {{LLVM Translation failed for operation: omp.task}}
|
// TODO: Add other clauses check | ||
checkPriority(op, result); | ||
checkUntied(op, result); | ||
}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These changes are taken from here: https://github.com/llvm/llvm-project/pull/115283/files#diff-2cbb5651f4570d81d55ac4198deda0f6f7341b2503479752ef2295da3774c586R266-R269.
I will merge that PR soon.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the patch. A few minor comments.
%2 = llvm.mlir.constant(4 : i32) : i32 | ||
%3 = llvm.mlir.constant(true) : i1 | ||
%4 = llvm.load %1 : !llvm.ptr -> i32 | ||
// CHECK: %[[Gid_01:.*]] = call i32 @__kmpc_global_thread_num(ptr {{.*}}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// CHECK: %[[Gid_01:.*]] = call i32 @__kmpc_global_thread_num(ptr {{.*}}) | |
// CHECK: %[[GID_01:.*]] = call i32 @__kmpc_global_thread_num(ptr {{.*}}) |
llvm.call @test_01() : () -> () | ||
omp.terminator | ||
} | ||
// CHECK: %[[Gid_02:.*]] = call i32 @__kmpc_global_thread_num(ptr {{.*}}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// CHECK: %[[Gid_02:.*]] = call i32 @__kmpc_global_thread_num(ptr {{.*}}) | |
// CHECK: %[[GID_02:.*]] = call i32 @__kmpc_global_thread_num(ptr {{.*}}) |
// | ||
Type *Int32Ty = Builder.getInt32Ty(); | ||
// kmp_task_t* => { ptr } | ||
Type *taskPtr = StructType::get(VoidPtr); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Type *taskPtr = StructType::get(VoidPtr); | |
Type *TaskPtr = StructType::get(VoidPtr); |
And for other variables. While this is slightly confusing because MLIR's is somewhat different but we have to stick to the guidelines.
https://llvm.org/docs/CodingStandards.html#name-types-functions-variables-and-enumerators-properly
Variable names should be nouns (as they represent state). The name should be camel case, and start with an upper case letter (e.g. Leader or Boats).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, thanks for the information.
Type *taskStructType = StructType::get( | ||
VoidPtr, VoidPtr, Builder.getInt32Ty(), VoidPtr, VoidPtr); | ||
Value *priorityData = Builder.CreateInBoundsGEP( | ||
taskStructType, taskGEP, | ||
{ConstantInt::get(Int32Ty, 0), ConstantInt::get(Int32Ty, 4)}); | ||
Builder.CreateStore(Priority, priorityData); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since data2 is another struct ( kmp_cmplrdata), Is this sufficient because priority is the first field of kmp_cmplrdata, or do we have to index into kmp_cmplrdata as well?
typedef union kmp_cmplrdata {
kmp_int32 priority; /**< priority specified by user for the task */
kmp_routine_entry_t
destructors; /* pointer to function to invoke deconstructors of
firstprivate C++ objects */
/* future data */
} kmp_cmplrdata_t;
/* sizeof_kmp_task_t passed as arg to kmpc_omp_task call */
/*!
*/
typedef struct kmp_task { /* GEH: Shouldn't this be aligned somehow? */
void *shareds; /**< pointer to block of pointers to shared vars */
kmp_routine_entry_t
routine; /**< pointer to routine to call for executing task */
kmp_int32 part_id; /**< part id for the task */
kmp_cmplrdata_t
data1; /* Two known optional additions: destructors and priority */
kmp_cmplrdata_t data2; /* Process destructors first, priority second */
/* future data */
/* private vars */
} kmp_task_t;
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this sufficient because priority is the first field of kmp_cmplrdata
Yes, because I checked whether the priority value is passed to runtime by printing the value inside the __kmpc_omp_task
, and it prints the correct value.
But, after thinking about this, we should indeed index through kmp_cmplrdata_t (which might reduce some bugs for the future.)
19a2b17
to
4309b80
Compare
Done, @kiranchandramohan, can you please review this again, so that we can merge it? |
✅ With the latest revision this PR passed the C/C++ code formatter. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, thanks!
Thanks for the review @tblah! |
Implementation details:
The PRIORITY clause is recognized by setting the flags = 32 to the
__kmpc_omp_task_alloc
runtime call. Also, Store the priority-valueto the
kmp_task_t
struct