Skip to content

[MLIR][OpenMP][Offload] Lower target update op to DeviceRT #75159

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

Merged
merged 1 commit into from
Dec 18, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -1915,6 +1915,23 @@ convertOmpTargetData(Operation *op, llvm::IRBuilderBase &builder,
mapOperands = exitDataOp.getMapOperands();
return success();
})
.Case([&](omp::UpdateDataOp updateDataOp) {
if (updateDataOp.getNowait())
return failure();

if (auto ifExprVar = updateDataOp.getIfExpr())
ifCond = moduleTranslation.lookupValue(ifExprVar);

if (auto devId = updateDataOp.getDevice())
if (auto constOp =
dyn_cast<LLVM::ConstantOp>(devId.getDefiningOp()))
if (auto intAttr = dyn_cast<IntegerAttr>(constOp.getValue()))
deviceID = intAttr.getInt();

RTLFn = llvm::omp::OMPRTL___tgt_target_data_update_mapper;
mapOperands = updateDataOp.getMotionOperands();
return success();
})
.Default([&](Operation *op) {
return op->emitError("unsupported OpenMP operation: ")
<< op->getName();
Expand Down Expand Up @@ -2748,9 +2765,10 @@ LogicalResult OpenMPDialectLLVMIRTranslationInterface::convertOperation(
.Case([&](omp::ThreadprivateOp) {
return convertOmpThreadprivate(*op, builder, moduleTranslation);
})
.Case<omp::DataOp, omp::EnterDataOp, omp::ExitDataOp>([&](auto op) {
return convertOmpTargetData(op, builder, moduleTranslation);
})
.Case<omp::DataOp, omp::EnterDataOp, omp::ExitDataOp, omp::UpdateDataOp>(
[&](auto op) {
return convertOmpTargetData(op, builder, moduleTranslation);
})
.Case([&](omp::TargetOp) {
return convertOmpTarget(*op, builder, moduleTranslation);
})
Expand Down
38 changes: 38 additions & 0 deletions mlir/test/Target/LLVMIR/omptarget-llvm.mlir
Original file line number Diff line number Diff line change
Expand Up @@ -441,3 +441,41 @@ llvm.func @_QPopenmp_target_use_dev_both() {
// CHECK: ret void

// -----

llvm.func @_QPopenmp_target_data_update() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you add more tests to cover different data types (like Fortran pointers, allocatable arrays etc.)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As discussed offline, the FIR dialect is not registered with mlir-translate. So we cannot use fir.ref in omptarget-llvm.mlir.

However, I will double check with @agozillon whether we have existing tests for lowering map_info op's arguments from fir to llvm types or not. If not, I will open another PR with more testing.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, LGTM

%0 = llvm.mlir.constant(1 : i64) : i64
%1 = llvm.alloca %0 x i32 {bindc_name = "i", in_type = i32, operand_segment_sizes = array<i32: 0, 0>, uniq_name = "_QFopenmp_target_dataEi"} : (i64) -> !llvm.ptr
%2 = omp.map_info var_ptr(%1 : !llvm.ptr, i32) map_clauses(to) capture(ByRef) -> !llvm.ptr {name = ""}
omp.target_data map_entries(%2 : !llvm.ptr) {
%3 = llvm.mlir.constant(99 : i32) : i32
llvm.store %3, %1 : i32, !llvm.ptr
omp.terminator
}

omp.target_update_data motion_entries(%2 : !llvm.ptr)

llvm.return
}

// CHECK-LABEL: define void @_QPopenmp_target_data_update

// CHECK-DAG: %[[OFFLOAD_BASEPTRS:.*]] = alloca [1 x ptr], align 8
// CHECK-DAG: %[[OFFLOAD_PTRS:.*]] = alloca [1 x ptr], align 8
// CHECK-DAG: %[[INT_ALLOCA:.*]] = alloca i32, i64 1, align 4
// CHECK-DAG: %[[OFFLOAD_MAPPERS:.*]] = alloca [1 x ptr], align 8

// CHECK: call void @__tgt_target_data_begin_mapper
// CHECK: store i32 99, ptr %[[INT_ALLOCA]], align 4
// CHECK: call void @__tgt_target_data_end_mapper

// CHECK: %[[BASEPTRS_VAL:.*]] = getelementptr inbounds [1 x ptr], ptr %[[OFFLOAD_BASEPTRS]], i32 0, i32 0
// CHECK: store ptr %[[INT_ALLOCA]], ptr %[[BASEPTRS_VAL]], align 8
// CHECK: %[[PTRS_VAL:.*]] = getelementptr inbounds [1 x ptr], ptr %[[OFFLOAD_PTRS]], i32 0, i32 0
// CHECK: store ptr %[[INT_ALLOCA]], ptr %[[PTRS_VAL]], align 8
// CHECK: %[[MAPPERS_VAL:.*]] = getelementptr inbounds [1 x ptr], ptr %[[OFFLOAD_MAPPERS]], i64 0, i64 0
// CHECK: store ptr null, ptr %[[MAPPERS_VAL]], align 8
// CHECK: %[[BASEPTRS_VAL_2:.*]] = getelementptr inbounds [1 x ptr], ptr %[[OFFLOAD_BASEPTRS]], i32 0, i32 0
// CHECK: %[[PTRS_VAL_2:.*]] = getelementptr inbounds [1 x ptr], ptr %[[OFFLOAD_PTRS]], i32 0, i32 0
// CHECK: call void @__tgt_target_data_update_mapper(ptr @2, i64 -1, i32 1, ptr %[[BASEPTRS_VAL_2]], ptr %[[PTRS_VAL_2]], ptr @{{.*}}, ptr @{{.*}}, ptr @{{.*}}, ptr null)

// CHECK: ret void