https://github.com/TIFitis updated 
https://github.com/llvm/llvm-project/pull/169367

>From c7824750af75aadc93913740ba01bf0eff6e4d28 Mon Sep 17 00:00:00 2001
From: Akash Banerjee <[email protected]>
Date: Thu, 27 Nov 2025 19:41:59 +0000
Subject: [PATCH 1/2] [MLIR][OpenMP] Add OpenMPToLLVMIRTranslation support for
 is_device_ptr

This PR adds support for the OpenMP is_device_ptr clause in the MLIR to LLVM IR 
translation for target regions. The is_device_ptr clause allows device pointers 
(allocated via OpenMP runtime APIs) to be used directly in target regions 
without implicit mapping.
---
 .../OpenMP/map-types-and-sizes.f90            |  9 ++++
 .../OpenMP/OpenMPToLLVMIRTranslation.cpp      | 16 ++++---
 mlir/test/Target/LLVMIR/omptarget-llvm.mlir   | 17 +++++++
 mlir/test/Target/LLVMIR/openmp-todo.mlir      | 11 -----
 .../fortran/target-is-device-ptr.f90          | 46 +++++++++++++++++++
 5 files changed, 82 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..abd582e6a4e63 100644
--- a/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp
@@ -332,10 +332,6 @@ 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 checkLinear = [&todo](auto op, LogicalResult &result) {
     if (!op.getLinearVars().empty() || !op.getLinearStepVars().empty())
       result = todo("linear");
@@ -444,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
@@ -3875,6 +3870,11 @@ convertClauseMapFlags(omp::ClauseMapFlags mlirFlags) {
   if (mapTypeToBool(omp::ClauseMapFlags::attach))
     mapType |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_ATTACH;
 
+  if (mapTypeToBool(omp::ClauseMapFlags::is_device_ptr)) {
+    mapType |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM;
+    mapType |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_LITERAL;
+  }
+
   return mapType;
 }
 
@@ -3996,6 +3996,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::is_device_ptr) !=
+        omp::ClauseMapFlags::none;
 
     mapData.OriginalValue.push_back(origValue);
     mapData.BasePointers.push_back(origValue);
@@ -4029,7 +4032,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/omptarget-llvm.mlir 
b/mlir/test/Target/LLVMIR/omptarget-llvm.mlir
index e6ea3aaeec656..e289d5d013eaa 100644
--- a/mlir/test/Target/LLVMIR/omptarget-llvm.mlir
+++ b/mlir/test/Target/LLVMIR/omptarget-llvm.mlir
@@ -622,3 +622,20 @@ module attributes {omp.target_triples = 
["amdgcn-amd-amdhsa"]} {
 // CHECK:         br label %[[VAL_40]]
 // CHECK:       omp.done:                                         ; preds = 
%[[VAL_68]], %[[VAL_63]], %[[VAL_32]]
 // CHECK:         ret void
+
+// -----
+
+module attributes {omp.target_triples = ["amdgcn-amd-amdhsa"]} {
+  llvm.func @_QPomp_target_is_device_ptr(%arg0 : !llvm.ptr) {
+    %map = omp.map.info var_ptr(%arg0 : !llvm.ptr, !llvm.ptr)
+        map_clauses(is_device_ptr) capture(ByRef) -> !llvm.ptr {name = ""}
+    omp.target map_entries(%map -> %ptr_arg : !llvm.ptr) {
+      omp.terminator
+    }
+    llvm.return
+  }
+}
+
+// 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-LABEL: define void @_QPomp_target_is_device_ptr
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..b2da1ad23d093
--- /dev/null
+++ b/offload/test/offloading/fortran/target-is-device-ptr.f90
@@ -0,0 +1,46 @@
+! 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
+
+! RUN: %libomptarget-compile-fortran-run-and-check-generic
+
+program is_device_ptr_target
+  use iso_c_binding, only : c_ptr, c_loc
+  implicit none
+
+  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
+
+  integer, parameter :: n = 4
+  integer, parameter :: dev = 0
+  integer, target :: a(n)
+  type(c_ptr) :: dptr
+  integer :: flag
+
+  a = [2, 4, 6, 8]
+  flag = 0
+
+  !$omp target data map(tofrom: a, flag)
+    dptr = omp_get_mapped_ptr(c_loc(a), dev)
+
+    !$omp target is_device_ptr(dptr) map(tofrom: flag)
+      flag = flag + 1
+    !$omp end target
+  !$omp end target data
+
+  if (flag .eq. 1 .and. all(a == [2, 4, 6, 8])) then
+    print *, "PASS"
+  else
+    print *, "FAIL", a
+  end if
+
+end program is_device_ptr_target
+
+!CHECK: PASS

>From 31d0e473409ea3183d1909f915bb2e89768f8786 Mon Sep 17 00:00:00 2001
From: Akash Banerjee <[email protected]>
Date: Mon, 1 Dec 2025 18:59:52 +0000
Subject: [PATCH 2/2] Update test.

---
 flang/lib/Lower/OpenMP/ClauseProcessor.cpp    |  5 +-
 .../OpenMP/map-types-and-sizes.f90            |  2 +-
 .../OpenMP/OpenMPToLLVMIRTranslation.cpp      | 11 +++-
 .../fortran/target-is-device-ptr.f90          | 62 ++++++++++++-------
 4 files changed, 52 insertions(+), 28 deletions(-)

diff --git a/flang/lib/Lower/OpenMP/ClauseProcessor.cpp 
b/flang/lib/Lower/OpenMP/ClauseProcessor.cpp
index 8c15395c938c0..474d5725e4b82 100644
--- a/flang/lib/Lower/OpenMP/ClauseProcessor.cpp
+++ b/flang/lib/Lower/OpenMP/ClauseProcessor.cpp
@@ -1145,8 +1145,11 @@ bool ClauseProcessor::processIsDevicePtr(
       [&](const omp::clause::IsDevicePtr &clause,
           const parser::CharBlock &source) {
         mlir::Location location = converter.genLocation(source);
+        // Force a map so the descriptor is materialized on the device with the
+        // device address inside.
         mlir::omp::ClauseMapFlags mapTypeBits =
-            mlir::omp::ClauseMapFlags::is_device_ptr;
+            mlir::omp::ClauseMapFlags::is_device_ptr |
+            mlir::omp::ClauseMapFlags::to;
         processMapObjects(stmtCtx, location, clause.v, mapTypeBits,
                           parentMemberIndices, result.isDevicePtrVars,
                           isDeviceSyms);
diff --git a/flang/test/Integration/OpenMP/map-types-and-sizes.f90 
b/flang/test/Integration/OpenMP/map-types-and-sizes.f90
index 85434460bbea6..133b1664668d7 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 33]
 subroutine mapType_is_device_ptr
   use iso_c_binding, only : c_ptr
   type(c_ptr) :: p
diff --git 
a/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp 
b/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp
index abd582e6a4e63..a1adbef23180f 100644
--- a/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp
@@ -3830,6 +3830,9 @@ convertClauseMapFlags(omp::ClauseMapFlags mlirFlags) {
   auto mapTypeToBool = [&mlirFlags](omp::ClauseMapFlags flag) {
     return (mlirFlags & flag) == flag;
   };
+  const bool hasExplicitMap =
+      (mlirFlags & ~omp::ClauseMapFlags::is_device_ptr) !=
+      omp::ClauseMapFlags::none;
 
   llvm::omp::OpenMPOffloadMappingFlags mapType =
       llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_NONE;
@@ -3872,7 +3875,8 @@ convertClauseMapFlags(omp::ClauseMapFlags mlirFlags) {
 
   if (mapTypeToBool(omp::ClauseMapFlags::is_device_ptr)) {
     mapType |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM;
-    mapType |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_LITERAL;
+    if (!hasExplicitMap)
+      mapType |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_LITERAL;
   }
 
   return mapType;
@@ -4025,8 +4029,11 @@ static void collectMapDataFromMapOperands(
         mapData.Mappers.push_back(nullptr);
       }
     } else {
+      // For is_device_ptr we need the map type to propagate so the runtime
+      // can materialize the device-side copy of the pointer container.
       mapData.Types.push_back(
-          llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_LITERAL);
+          isDevicePtr ? mapType
+                      : llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_LITERAL);
       mapData.Mappers.push_back(nullptr);
     }
     mapData.Names.push_back(LLVM::createMappingInformation(
diff --git a/offload/test/offloading/fortran/target-is-device-ptr.f90 
b/offload/test/offloading/fortran/target-is-device-ptr.f90
index b2da1ad23d093..d6d8c02f50d6a 100644
--- a/offload/test/offloading/fortran/target-is-device-ptr.f90
+++ b/offload/test/offloading/fortran/target-is-device-ptr.f90
@@ -4,41 +4,55 @@
 
 ! RUN: %libomptarget-compile-fortran-run-and-check-generic
 
-program is_device_ptr_target
-  use iso_c_binding, only : c_ptr, c_loc
+module mod
   implicit none
+  integer, parameter :: n = 4
+contains
+  subroutine kernel(dptr)
+    use iso_c_binding, only : c_ptr, c_f_pointer
+    implicit none
+
+    type(c_ptr) :: dptr
+    integer, dimension(:), pointer :: b
+    integer :: i
+
+    b => null()
+
+    !$omp target is_device_ptr(dptr)
+      call c_f_pointer(dptr, b, [n])
+      do i = 1, n
+        b(i) = b(i) + 1
+      end do
+    !$omp end target
+  end subroutine kernel
+end module mod
 
-  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
+program is_device_ptr_target
+  use iso_c_binding, only : c_ptr, c_loc, c_f_pointer
+  use omp_lib, only: omp_get_default_device, omp_get_mapped_ptr
+  use mod, only: kernel, n
+  implicit none
 
-  integer, parameter :: n = 4
-  integer, parameter :: dev = 0
-  integer, target :: a(n)
+  integer, dimension(n), target :: a
+  integer :: dev
   type(c_ptr) :: dptr
-  integer :: flag
 
   a = [2, 4, 6, 8]
-  flag = 0
+  print '("BEFORE:", I3)', a
 
-  !$omp target data map(tofrom: a, flag)
-    dptr = omp_get_mapped_ptr(c_loc(a), dev)
+  dev = omp_get_default_device()
 
-    !$omp target is_device_ptr(dptr) map(tofrom: flag)
-      flag = flag + 1
-    !$omp end target
+  !$omp target data map(tofrom: a)
+    dptr = omp_get_mapped_ptr(c_loc(a), dev)
+    call kernel(dptr)
   !$omp end target data
 
-  if (flag .eq. 1 .and. all(a == [2, 4, 6, 8])) then
-    print *, "PASS"
+  print '("AFTER: ", I3)', a
+
+  if (all(a == [3, 5, 7, 9])) then
+    print '("PASS")'
   else
-    print *, "FAIL", a
+    print '("FAIL   ", I3)', a
   end if
 
 end program is_device_ptr_target

_______________________________________________
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits

Reply via email to