https://github.com/TIFitis updated https://github.com/llvm/llvm-project/pull/169367
>From c6440f42e19a54bfce0d7f55ca40b5a28b30f7bc Mon Sep 17 00:00:00 2001 From: Akash Banerjee <[email protected]> Date: Mon, 24 Nov 2025 17:05:29 +0000 Subject: [PATCH 1/4] [MLIR][OpenMP] Add OpenMPToLLVMIRTranslation support for is_device_ptr --- .../OpenMP/map-types-and-sizes.f90 | 9 +++ .../OpenMP/OpenMPToLLVMIRTranslation.cpp | 18 +++-- mlir/test/Target/LLVMIR/openmp-todo.mlir | 11 --- .../fortran/target-is-device-ptr.f90 | 79 +++++++++++++++++++ 4 files changed, 100 insertions(+), 17 deletions(-) create mode 100644 offload/test/offloading/fortran/target-is-device-ptr.f90 diff --git a/flang/test/Integration/OpenMP/map-types-and-sizes.f90 b/flang/test/Integration/OpenMP/map-types-and-sizes.f90 index 44a049f5ac510..85434460bbea6 100644 --- a/flang/test/Integration/OpenMP/map-types-and-sizes.f90 +++ b/flang/test/Integration/OpenMP/map-types-and-sizes.f90 @@ -33,6 +33,15 @@ subroutine mapType_array !$omp end target end subroutine mapType_array +!CHECK: @.offload_sizes{{.*}} = private unnamed_addr constant [1 x i64] [i64 8] +!CHECK: @.offload_maptypes{{.*}} = private unnamed_addr constant [1 x i64] [i64 288] +subroutine mapType_is_device_ptr + use iso_c_binding, only : c_ptr + type(c_ptr) :: p + !$omp target is_device_ptr(p) + !$omp end target +end subroutine mapType_is_device_ptr + !CHECK: @.offload_sizes{{.*}} = private unnamed_addr constant [4 x i64] [i64 0, i64 24, i64 8, i64 0] !CHECK: @.offload_maptypes{{.*}} = private unnamed_addr constant [4 x i64] [i64 32, i64 281474976711169, i64 281474976711171, i64 281474976711187] subroutine mapType_ptr diff --git a/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp b/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp index f28454075f1d3..9fa0e659320d6 100644 --- a/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp +++ b/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp @@ -332,10 +332,7 @@ static LogicalResult checkImplementationStatus(Operation &op) { op.getInReductionSyms()) result = todo("in_reduction"); }; - auto checkIsDevicePtr = [&todo](auto op, LogicalResult &result) { - if (!op.getIsDevicePtrVars().empty()) - result = todo("is_device_ptr"); - }; + auto checkIsDevicePtr = [](auto, LogicalResult &) {}; auto checkLinear = [&todo](auto op, LogicalResult &result) { if (!op.getLinearVars().empty() || !op.getLinearStepVars().empty()) result = todo("linear"); @@ -3996,6 +3993,9 @@ static void collectMapDataFromMapOperands( llvm::Value *origValue = moduleTranslation.lookupValue(offloadPtr); auto mapType = convertClauseMapFlags(mapOp.getMapType()); auto mapTypeAlways = llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_ALWAYS; + bool isDevicePtr = + (mapOp.getMapType() & omp::ClauseMapFlags::storage) == + omp::ClauseMapFlags::storage; mapData.OriginalValue.push_back(origValue); mapData.BasePointers.push_back(origValue); @@ -4006,7 +4006,12 @@ static void collectMapDataFromMapOperands( mapData.Sizes.push_back( builder.getInt64(dl.getTypeSize(mapOp.getVarType()))); mapData.MapClause.push_back(mapOp.getOperation()); - if (llvm::to_underlying(mapType & mapTypeAlways)) { + if (isDevicePtr) { + mapType |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM; + mapType |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_LITERAL; + mapData.Types.push_back(mapType); + mapData.Mappers.push_back(nullptr); + } else if (llvm::to_underlying(mapType & mapTypeAlways)) { // Descriptors are mapped with the ALWAYS flag, since they can get // rematerialized, so the address of the decriptor for a given object // may change from one place to another. @@ -4029,7 +4034,8 @@ static void collectMapDataFromMapOperands( mapData.Names.push_back(LLVM::createMappingInformation( mapOp.getLoc(), *moduleTranslation.getOpenMPBuilder())); mapData.DevicePointers.push_back( - llvm::OpenMPIRBuilder::DeviceInfoTy::Address); + isDevicePtr ? llvm::OpenMPIRBuilder::DeviceInfoTy::Pointer + : llvm::OpenMPIRBuilder::DeviceInfoTy::Address); mapData.IsAMapping.push_back(false); mapData.IsAMember.push_back(checkIsAMember(hasDevAddrOperands, mapOp)); } diff --git a/mlir/test/Target/LLVMIR/openmp-todo.mlir b/mlir/test/Target/LLVMIR/openmp-todo.mlir index af6d254cfd3c3..0704008aa7135 100644 --- a/mlir/test/Target/LLVMIR/openmp-todo.mlir +++ b/mlir/test/Target/LLVMIR/openmp-todo.mlir @@ -238,17 +238,6 @@ llvm.func @target_in_reduction(%x : !llvm.ptr) { // ----- -llvm.func @target_is_device_ptr(%x : !llvm.ptr) { - // expected-error@below {{not yet implemented: Unhandled clause is_device_ptr in omp.target operation}} - // expected-error@below {{LLVM Translation failed for operation: omp.target}} - omp.target is_device_ptr(%x : !llvm.ptr) { - omp.terminator - } - llvm.return -} - -// ----- - llvm.func @target_enter_data_depend(%x: !llvm.ptr) { // expected-error@below {{not yet implemented: Unhandled clause depend in omp.target_enter_data operation}} // expected-error@below {{LLVM Translation failed for operation: omp.target_enter_data}} diff --git a/offload/test/offloading/fortran/target-is-device-ptr.f90 b/offload/test/offloading/fortran/target-is-device-ptr.f90 new file mode 100644 index 0000000000000..6010d59113498 --- /dev/null +++ b/offload/test/offloading/fortran/target-is-device-ptr.f90 @@ -0,0 +1,79 @@ +! Validate that a device pointer allocated via OpenMP runtime APIs can be +! consumed by a TARGET region using the is_device_ptr clause. +! REQUIRES: flang, amdgcn-amd-amdhsa +! UNSUPPORTED: nvptx64-nvidia-cuda +! UNSUPPORTED: nvptx64-nvidia-cuda-LTO +! UNSUPPORTED: aarch64-unknown-linux-gnu +! UNSUPPORTED: aarch64-unknown-linux-gnu-LTO +! UNSUPPORTED: x86_64-unknown-linux-gnu +! UNSUPPORTED: x86_64-unknown-linux-gnu-LTO + +! RUN: %libomptarget-compile-fortran-run-and-check-generic + +program is_device_ptr_target + use omp_lib + use iso_c_binding + implicit none + + integer, parameter :: n = 4 + integer, target :: host(n) + type(c_ptr) :: device_ptr + integer(c_int) :: rc + integer :: i + + do i = 1, n + host(i) = i + end do + + device_ptr = omp_target_alloc(int(n, c_size_t) * int(c_sizeof(host(1)), c_size_t), & + omp_get_default_device()) + if (.not. c_associated(device_ptr)) then + print *, "device alloc failed" + stop 1 + end if + + rc = omp_target_memcpy(device_ptr, c_loc(host), & + int(n, c_size_t) * int(c_sizeof(host(1)), c_size_t), & + 0_c_size_t, 0_c_size_t, & + omp_get_default_device(), omp_get_initial_device()) + if (rc .ne. 0) then + print *, "host->device memcpy failed" + call omp_target_free(device_ptr, omp_get_default_device()) + stop 1 + end if + + call fill_on_device(device_ptr) + + rc = omp_target_memcpy(c_loc(host), device_ptr, & + int(n, c_size_t) * int(c_sizeof(host(1)), c_size_t), & + 0_c_size_t, 0_c_size_t, & + omp_get_initial_device(), omp_get_default_device()) + call omp_target_free(device_ptr, omp_get_default_device()) + + if (rc .ne. 0) then + print *, "device->host memcpy failed" + stop 1 + end if + + if (all(host == [2, 4, 6, 8])) then + print *, "PASS" + else + print *, "FAIL", host + end if + +contains + subroutine fill_on_device(ptr) + type(c_ptr) :: ptr + integer, pointer :: p(:) + call c_f_pointer(ptr, p, [n]) + + !$omp target is_device_ptr(ptr) + p(1) = 2 + p(2) = 4 + p(3) = 6 + p(4) = 8 + !$omp end target + end subroutine fill_on_device +end program is_device_ptr_target + +!CHECK: PASS >From a88f1712d23a53f10dc6eb553efdd7a8b55ea794 Mon Sep 17 00:00:00 2001 From: Akash Banerjee <[email protected]> Date: Mon, 24 Nov 2025 17:09:45 +0000 Subject: [PATCH 2/4] Fix clang-format. --- .../LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp b/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp index 9fa0e659320d6..00c4c351caa4e 100644 --- a/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp +++ b/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp @@ -3993,9 +3993,8 @@ static void collectMapDataFromMapOperands( llvm::Value *origValue = moduleTranslation.lookupValue(offloadPtr); auto mapType = convertClauseMapFlags(mapOp.getMapType()); auto mapTypeAlways = llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_ALWAYS; - bool isDevicePtr = - (mapOp.getMapType() & omp::ClauseMapFlags::storage) == - omp::ClauseMapFlags::storage; + bool isDevicePtr = (mapOp.getMapType() & omp::ClauseMapFlags::storage) == + omp::ClauseMapFlags::storage; mapData.OriginalValue.push_back(origValue); mapData.BasePointers.push_back(origValue); >From f4ff68bf9f61d0da012ea4a85682ba91d45d0777 Mon Sep 17 00:00:00 2001 From: Akash Banerjee <[email protected]> Date: Tue, 25 Nov 2025 16:35:56 +0000 Subject: [PATCH 3/4] Add is_device_ptr to mlir map flag. --- flang/lib/Lower/OpenMP/ClauseProcessor.cpp | 3 ++- mlir/include/mlir/Dialect/OpenMP/OpenMPEnums.td | 4 +++- .../Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp | 11 +++++++---- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/flang/lib/Lower/OpenMP/ClauseProcessor.cpp b/flang/lib/Lower/OpenMP/ClauseProcessor.cpp index 81a47e20b2a88..d8d9b51b23804 100644 --- a/flang/lib/Lower/OpenMP/ClauseProcessor.cpp +++ b/flang/lib/Lower/OpenMP/ClauseProcessor.cpp @@ -1146,7 +1146,8 @@ bool ClauseProcessor::processIsDevicePtr( const parser::CharBlock &source) { mlir::Location location = converter.genLocation(source); mlir::omp::ClauseMapFlags mapTypeBits = - mlir::omp::ClauseMapFlags::storage; + mlir::omp::ClauseMapFlags::return_param | + mlir::omp::ClauseMapFlags::is_device_ptr; processMapObjects(stmtCtx, location, clause.v, mapTypeBits, parentMemberIndices, result.isDevicePtrVars, isDeviceSyms); diff --git a/mlir/include/mlir/Dialect/OpenMP/OpenMPEnums.td b/mlir/include/mlir/Dialect/OpenMP/OpenMPEnums.td index d9882cbcb5977..8a7680bf6385e 100644 --- a/mlir/include/mlir/Dialect/OpenMP/OpenMPEnums.td +++ b/mlir/include/mlir/Dialect/OpenMP/OpenMPEnums.td @@ -126,6 +126,7 @@ def ClauseMapFlagsAttachAuto : I32BitEnumAttrCaseBit<"attach_auto", 15>; def ClauseMapFlagsRefPtr : I32BitEnumAttrCaseBit<"ref_ptr", 16>; def ClauseMapFlagsRefPtee : I32BitEnumAttrCaseBit<"ref_ptee", 17>; def ClauseMapFlagsRefPtrPtee : I32BitEnumAttrCaseBit<"ref_ptr_ptee", 18>; +def ClauseMapFlagsIsDevicePtr : I32BitEnumAttrCaseBit<"is_device_ptr", 19>; def ClauseMapFlags : OpenMP_BitEnumAttr< "ClauseMapFlags", @@ -149,7 +150,8 @@ def ClauseMapFlags : OpenMP_BitEnumAttr< ClauseMapFlagsAttachAuto, ClauseMapFlagsRefPtr, ClauseMapFlagsRefPtee, - ClauseMapFlagsRefPtrPtee + ClauseMapFlagsRefPtrPtee, + ClauseMapFlagsIsDevicePtr ]>; def ClauseMapFlagsAttr : OpenMP_EnumAttr<ClauseMapFlags, diff --git a/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp b/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp index 00c4c351caa4e..1519fee6ea302 100644 --- a/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp +++ b/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp @@ -332,7 +332,6 @@ static LogicalResult checkImplementationStatus(Operation &op) { op.getInReductionSyms()) result = todo("in_reduction"); }; - auto checkIsDevicePtr = [](auto, LogicalResult &) {}; auto checkLinear = [&todo](auto op, LogicalResult &result) { if (!op.getLinearVars().empty() || !op.getLinearStepVars().empty()) result = todo("linear"); @@ -441,7 +440,6 @@ static LogicalResult checkImplementationStatus(Operation &op) { checkBare(op, result); checkDevice(op, result); checkInReduction(op, result); - checkIsDevicePtr(op, result); }) .Default([](Operation &) { // Assume all clauses for an operation can be translated unless they are @@ -3872,6 +3870,10 @@ convertClauseMapFlags(omp::ClauseMapFlags mlirFlags) { if (mapTypeToBool(omp::ClauseMapFlags::attach)) mapType |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_ATTACH; + // No dedicated LLVM runtime flag for is_device_ptr; handled separately. + if (mapTypeToBool(omp::ClauseMapFlags::is_device_ptr)) + mapType |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_RETURN_PARAM; + return mapType; } @@ -3993,8 +3995,9 @@ static void collectMapDataFromMapOperands( llvm::Value *origValue = moduleTranslation.lookupValue(offloadPtr); auto mapType = convertClauseMapFlags(mapOp.getMapType()); auto mapTypeAlways = llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_ALWAYS; - bool isDevicePtr = (mapOp.getMapType() & omp::ClauseMapFlags::storage) == - omp::ClauseMapFlags::storage; + bool isDevicePtr = + (mapOp.getMapType() & omp::ClauseMapFlags::is_device_ptr) != + omp::ClauseMapFlags::none; mapData.OriginalValue.push_back(origValue); mapData.BasePointers.push_back(origValue); >From ec3c5626ff4ae6a9481cc7f771f72a784fa59336 Mon Sep 17 00:00:00 2001 From: Akash Banerjee <[email protected]> Date: Wed, 26 Nov 2025 16:54:20 +0000 Subject: [PATCH 4/4] Update tests. --- .../OpenMP/map-types-and-sizes.f90 | 2 +- .../fortran/target-is-device-ptr.f90 | 87 ++++++------------- 2 files changed, 28 insertions(+), 61 deletions(-) diff --git a/flang/test/Integration/OpenMP/map-types-and-sizes.f90 b/flang/test/Integration/OpenMP/map-types-and-sizes.f90 index 85434460bbea6..ddb943c95fba2 100644 --- a/flang/test/Integration/OpenMP/map-types-and-sizes.f90 +++ b/flang/test/Integration/OpenMP/map-types-and-sizes.f90 @@ -34,7 +34,7 @@ subroutine mapType_array end subroutine mapType_array !CHECK: @.offload_sizes{{.*}} = private unnamed_addr constant [1 x i64] [i64 8] -!CHECK: @.offload_maptypes{{.*}} = private unnamed_addr constant [1 x i64] [i64 288] +!CHECK: @.offload_maptypes{{.*}} = private unnamed_addr constant [1 x i64] [i64 352] subroutine mapType_is_device_ptr use iso_c_binding, only : c_ptr type(c_ptr) :: p diff --git a/offload/test/offloading/fortran/target-is-device-ptr.f90 b/offload/test/offloading/fortran/target-is-device-ptr.f90 index 6010d59113498..b2da1ad23d093 100644 --- a/offload/test/offloading/fortran/target-is-device-ptr.f90 +++ b/offload/test/offloading/fortran/target-is-device-ptr.f90 @@ -1,79 +1,46 @@ -! Validate that a device pointer allocated via OpenMP runtime APIs can be -! consumed by a TARGET region using the is_device_ptr clause. +! Validate that a device pointer obtained via omp_get_mapped_ptr can be used +! inside a TARGET region with the is_device_ptr clause. ! REQUIRES: flang, amdgcn-amd-amdhsa -! UNSUPPORTED: nvptx64-nvidia-cuda -! UNSUPPORTED: nvptx64-nvidia-cuda-LTO -! UNSUPPORTED: aarch64-unknown-linux-gnu -! UNSUPPORTED: aarch64-unknown-linux-gnu-LTO -! UNSUPPORTED: x86_64-unknown-linux-gnu -! UNSUPPORTED: x86_64-unknown-linux-gnu-LTO ! RUN: %libomptarget-compile-fortran-run-and-check-generic program is_device_ptr_target - use omp_lib - use iso_c_binding + use iso_c_binding, only : c_ptr, c_loc implicit none - integer, parameter :: n = 4 - integer, target :: host(n) - type(c_ptr) :: device_ptr - integer(c_int) :: rc - integer :: i - - do i = 1, n - host(i) = i - end do + interface + function omp_get_mapped_ptr(host_ptr, device_num) & + bind(C, name="omp_get_mapped_ptr") + use iso_c_binding, only : c_ptr, c_int + type(c_ptr) :: omp_get_mapped_ptr + type(c_ptr), value :: host_ptr + integer(c_int), value :: device_num + end function omp_get_mapped_ptr + end interface - device_ptr = omp_target_alloc(int(n, c_size_t) * int(c_sizeof(host(1)), c_size_t), & - omp_get_default_device()) - if (.not. c_associated(device_ptr)) then - print *, "device alloc failed" - stop 1 - end if - - rc = omp_target_memcpy(device_ptr, c_loc(host), & - int(n, c_size_t) * int(c_sizeof(host(1)), c_size_t), & - 0_c_size_t, 0_c_size_t, & - omp_get_default_device(), omp_get_initial_device()) - if (rc .ne. 0) then - print *, "host->device memcpy failed" - call omp_target_free(device_ptr, omp_get_default_device()) - stop 1 - end if + integer, parameter :: n = 4 + integer, parameter :: dev = 0 + integer, target :: a(n) + type(c_ptr) :: dptr + integer :: flag - call fill_on_device(device_ptr) + a = [2, 4, 6, 8] + flag = 0 - rc = omp_target_memcpy(c_loc(host), device_ptr, & - int(n, c_size_t) * int(c_sizeof(host(1)), c_size_t), & - 0_c_size_t, 0_c_size_t, & - omp_get_initial_device(), omp_get_default_device()) - call omp_target_free(device_ptr, omp_get_default_device()) + !$omp target data map(tofrom: a, flag) + dptr = omp_get_mapped_ptr(c_loc(a), dev) - if (rc .ne. 0) then - print *, "device->host memcpy failed" - stop 1 - end if + !$omp target is_device_ptr(dptr) map(tofrom: flag) + flag = flag + 1 + !$omp end target + !$omp end target data - if (all(host == [2, 4, 6, 8])) then + if (flag .eq. 1 .and. all(a == [2, 4, 6, 8])) then print *, "PASS" else - print *, "FAIL", host + print *, "FAIL", a end if -contains - subroutine fill_on_device(ptr) - type(c_ptr) :: ptr - integer, pointer :: p(:) - call c_f_pointer(ptr, p, [n]) - - !$omp target is_device_ptr(ptr) - p(1) = 2 - p(2) = 4 - p(3) = 6 - p(4) = 8 - !$omp end target - end subroutine fill_on_device end program is_device_ptr_target !CHECK: PASS _______________________________________________ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
