[flang-commits] [flang] [Flang][OpenMP] Add lowering support for is_device_ptr clause (PR #168875)

Akash Banerjee via flang-commits flang-commits at lists.llvm.org
Thu Nov 20 06:03:30 PST 2025


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

>From 57765c04cd4ec5cd9cf1155126d133c16c6e2252 Mon Sep 17 00:00:00 2001
From: Akash Banerjee <Akash.Banerjee at amd.com>
Date: Thu, 20 Nov 2025 13:18:00 +0000
Subject: [PATCH 1/4] [Flang][OpenMP] Add lowering support for is_device_ptr
 clause

Add support for OpenMP is_device_ptr clause for target directives.
---
 flang/lib/Lower/OpenMP/OpenMP.cpp             | 79 ++++++++++++++++++-
 .../OpenMP/is-device-ptr-target-lowering.f90  | 30 +++++++
 2 files changed, 106 insertions(+), 3 deletions(-)
 create mode 100644 flang/test/Lower/OpenMP/is-device-ptr-target-lowering.f90

diff --git a/flang/lib/Lower/OpenMP/OpenMP.cpp b/flang/lib/Lower/OpenMP/OpenMP.cpp
index 71067283d13f7..fa2e5281f0e1c 100644
--- a/flang/lib/Lower/OpenMP/OpenMP.cpp
+++ b/flang/lib/Lower/OpenMP/OpenMP.cpp
@@ -2485,13 +2485,15 @@ static bool isDuplicateMappedSymbol(
     const semantics::Symbol &sym,
     const llvm::SetVector<const semantics::Symbol *> &privatizedSyms,
     const llvm::SmallVectorImpl<const semantics::Symbol *> &hasDevSyms,
-    const llvm::SmallVectorImpl<const semantics::Symbol *> &mappedSyms) {
+    const llvm::SmallVectorImpl<const semantics::Symbol *> &mappedSyms,
+    const llvm::SmallVectorImpl<const semantics::Symbol *> &isDevicePtrSyms) {
   llvm::SmallVector<const semantics::Symbol *> concatSyms;
   concatSyms.reserve(privatizedSyms.size() + hasDevSyms.size() +
-                     mappedSyms.size());
+                     mappedSyms.size() + isDevicePtrSyms.size());
   concatSyms.append(privatizedSyms.begin(), privatizedSyms.end());
   concatSyms.append(hasDevSyms.begin(), hasDevSyms.end());
   concatSyms.append(mappedSyms.begin(), mappedSyms.end());
+  concatSyms.append(isDevicePtrSyms.begin(), isDevicePtrSyms.end());
 
   auto checkSymbol = [&](const semantics::Symbol &checkSym) {
     return std::any_of(concatSyms.begin(), concatSyms.end(),
@@ -2538,6 +2540,77 @@ genTargetOp(lower::AbstractConverter &converter, lower::SymMap &symTable,
                            /*isTargetPrivitization=*/true);
   dsp.processStep1(&clauseOps);
 
+  // Ensure is_device_ptr variables are available inside the target region by
+  // passing them as block arguments via the has_device_addr list, and record
+  // the associated var_ptr values so the clause operands reference the same
+  // MLIR SSA values used by the map info operations.
+  if (!isDevicePtrSyms.empty()) {
+    fir::FirOpBuilder &builder = converter.getFirOpBuilder();
+    llvm::DenseMap<const semantics::Symbol *, mlir::Value> symToMapInfo;
+    for (auto [symPtr, mapVal] : llvm::zip(hasDeviceAddrSyms, clauseOps.hasDeviceAddrVars))
+      if (symPtr)
+        symToMapInfo.try_emplace(symPtr, mapVal);
+
+    llvm::SmallVector<mlir::Value> remappedIsDevicePtrVars;
+    remappedIsDevicePtrVars.reserve(isDevicePtrSyms.size());
+
+    for (const semantics::Symbol *sym : isDevicePtrSyms) {
+      if (!sym)
+        continue;
+
+      mlir::omp::MapInfoOp mapInfoOp;
+      if (auto it = symToMapInfo.find(sym); it != symToMapInfo.end())
+        mapInfoOp = mlir::dyn_cast_or_null<mlir::omp::MapInfoOp>(
+            it->second.getDefiningOp());
+
+      if (!mapInfoOp && !llvm::is_contained(mapSyms, sym)) {
+        fir::ExtendedValue dataExv = converter.getSymbolExtendedValue(*sym);
+
+        fir::factory::AddrAndBoundsInfo info =
+            Fortran::lower::getDataOperandBaseAddr(
+                converter, builder, sym->GetUltimate(),
+                converter.getCurrentLocation());
+
+        llvm::SmallVector<mlir::Value> bounds =
+            fir::factory::genImplicitBoundsOps<mlir::omp::MapBoundsOp,
+                                               mlir::omp::MapBoundsType>(
+                builder, info, dataExv,
+                semantics::IsAssumedSizeArray(sym->GetUltimate()),
+                converter.getCurrentLocation());
+
+        mlir::Value baseOp = info.rawInput;
+        if (auto refType =
+                mlir::dyn_cast<fir::ReferenceType>(baseOp.getType()))
+          (void)refType; // element type not needed for storage-only mapping
+
+        mlir::Value mapVal = createMapInfoOp(
+            builder, converter.getCurrentLocation(), baseOp,
+            /*varPtrPtr=*/mlir::Value{}, sym->name().ToString(), bounds,
+            /*members=*/{}, /*membersIndex=*/mlir::ArrayAttr{},
+            mlir::omp::ClauseMapFlags::storage,
+            mlir::omp::VariableCaptureKind::ByRef, baseOp.getType(),
+            /*partialMap=*/false, /*mapperId=*/mlir::FlatSymbolRefAttr{});
+
+        clauseOps.hasDeviceAddrVars.push_back(mapVal);
+        hasDeviceAddrSyms.push_back(sym);
+        symToMapInfo[sym] = mapVal;
+        mapInfoOp = mapVal.getDefiningOp<mlir::omp::MapInfoOp>();
+      }
+
+      if (mapInfoOp) {
+        builder.setInsertionPointAfter(mapInfoOp);
+        auto clonedOp = builder.clone(*mapInfoOp.getOperation());
+        auto clonedMapInfo = mlir::dyn_cast<mlir::omp::MapInfoOp>(clonedOp);
+        assert(clonedMapInfo && "expected cloned map info op");
+        remappedIsDevicePtrVars.push_back(clonedMapInfo.getResult());
+      }
+    }
+
+    if (!remappedIsDevicePtrVars.empty())
+      clauseOps.isDevicePtrVars.assign(remappedIsDevicePtrVars.begin(),
+                                       remappedIsDevicePtrVars.end());
+  }
+
   // 5.8.1 Implicit Data-Mapping Attribute Rules
   // The following code follows the implicit data-mapping rules to map all the
   // symbols used inside the region that do not have explicit data-environment
@@ -2570,7 +2643,7 @@ genTargetOp(lower::AbstractConverter &converter, lower::SymMap &symTable,
       return;
 
     if (!isDuplicateMappedSymbol(sym, dsp.getAllSymbolsToPrivatize(),
-                                 hasDeviceAddrSyms, mapSyms)) {
+                                 hasDeviceAddrSyms, mapSyms, isDevicePtrSyms)) {
       if (const auto *details =
               sym.template detailsIf<semantics::HostAssocDetails>())
         converter.copySymbolBinding(details->symbol(), sym);
diff --git a/flang/test/Lower/OpenMP/is-device-ptr-target-lowering.f90 b/flang/test/Lower/OpenMP/is-device-ptr-target-lowering.f90
new file mode 100644
index 0000000000000..226614e6576b4
--- /dev/null
+++ b/flang/test/Lower/OpenMP/is-device-ptr-target-lowering.f90
@@ -0,0 +1,30 @@
+! RUN: %flang_fc1 -emit-hlfir -fopenmp %s -o - | FileCheck %s
+
+! Verify that lowering a TARGET with is_device_ptr attaches
+! the clause to the resulting omp.target op.
+
+program test_is_device_ptr_lowering
+  use iso_c_binding, only: c_associated, c_ptr
+  implicit none
+  integer :: i
+  integer :: arr(4)
+  type(c_ptr) :: p
+
+  i = 0
+  arr = 0
+
+  !$omp target is_device_ptr(p)
+    if (c_associated(p)) i = i + 1
+    arr(1) = i
+  !$omp end target
+end program test_is_device_ptr_lowering
+
+! CHECK: %[[P_STORAGE:.*]] = omp.map.info {{.*}}{name = "p"}
+! CHECK: %[[P_IS:.*]] = omp.map.info {{.*}}{name = "p"}
+! CHECK: %[[I_MAP:.*]] = omp.map.info {{.*}}{name = "i"}
+! CHECK: %[[ARR_MAP:.*]] = omp.map.info {{.*}}{name = "arr"}
+! CHECK: omp.target is_device_ptr(%[[P_IS]] :
+! CHECK-SAME: has_device_addr(%[[P_STORAGE]] ->
+! CHECK-SAME: map_entries(%[[I_MAP]] ->
+! CHECK-SAME: %[[ARR_MAP]] ->
+! CHECK: omp.terminator

>From 3f65b961a2d8c5bdb0a6b12ac2439cbd3fe380b5 Mon Sep 17 00:00:00 2001
From: Akash Banerjee <Akash.Banerjee at amd.com>
Date: Thu, 20 Nov 2025 13:46:34 +0000
Subject: [PATCH 2/4] move test to flang/test/Lower/OpenMP/target.f90.

---
 .../OpenMP/is-device-ptr-target-lowering.f90  | 30 -----------------
 flang/test/Lower/OpenMP/target.f90            | 32 +++++++++++++++++++
 2 files changed, 32 insertions(+), 30 deletions(-)
 delete mode 100644 flang/test/Lower/OpenMP/is-device-ptr-target-lowering.f90

diff --git a/flang/test/Lower/OpenMP/is-device-ptr-target-lowering.f90 b/flang/test/Lower/OpenMP/is-device-ptr-target-lowering.f90
deleted file mode 100644
index 226614e6576b4..0000000000000
--- a/flang/test/Lower/OpenMP/is-device-ptr-target-lowering.f90
+++ /dev/null
@@ -1,30 +0,0 @@
-! RUN: %flang_fc1 -emit-hlfir -fopenmp %s -o - | FileCheck %s
-
-! Verify that lowering a TARGET with is_device_ptr attaches
-! the clause to the resulting omp.target op.
-
-program test_is_device_ptr_lowering
-  use iso_c_binding, only: c_associated, c_ptr
-  implicit none
-  integer :: i
-  integer :: arr(4)
-  type(c_ptr) :: p
-
-  i = 0
-  arr = 0
-
-  !$omp target is_device_ptr(p)
-    if (c_associated(p)) i = i + 1
-    arr(1) = i
-  !$omp end target
-end program test_is_device_ptr_lowering
-
-! CHECK: %[[P_STORAGE:.*]] = omp.map.info {{.*}}{name = "p"}
-! CHECK: %[[P_IS:.*]] = omp.map.info {{.*}}{name = "p"}
-! CHECK: %[[I_MAP:.*]] = omp.map.info {{.*}}{name = "i"}
-! CHECK: %[[ARR_MAP:.*]] = omp.map.info {{.*}}{name = "arr"}
-! CHECK: omp.target is_device_ptr(%[[P_IS]] :
-! CHECK-SAME: has_device_addr(%[[P_STORAGE]] ->
-! CHECK-SAME: map_entries(%[[I_MAP]] ->
-! CHECK-SAME: %[[ARR_MAP]] ->
-! CHECK: omp.terminator
diff --git a/flang/test/Lower/OpenMP/target.f90 b/flang/test/Lower/OpenMP/target.f90
index 26bd62edf9d0c..c6767ab74889a 100644
--- a/flang/test/Lower/OpenMP/target.f90
+++ b/flang/test/Lower/OpenMP/target.f90
@@ -566,6 +566,38 @@ subroutine omp_target_device_addr
 end subroutine omp_target_device_addr
 
 
+!===============================================================================
+! Target `is_device_ptr` clause
+!===============================================================================
+
+!CHECK-LABEL: func.func @_QPomp_target_is_device_ptr() {
+subroutine omp_target_is_device_ptr
+   use iso_c_binding, only: c_associated, c_ptr
+   implicit none
+   integer :: i
+   integer :: arr(4)
+   type(c_ptr) :: p
+
+   i = 0
+   arr = 0
+
+   !CHECK: %[[P_STORAGE:.*]] = omp.map.info {{.*}}{name = "p"}
+   !CHECK: %[[P_IS:.*]] = omp.map.info {{.*}}{name = "p"}
+   !CHECK: %[[I_MAP:.*]] = omp.map.info {{.*}}{name = "i"}
+   !CHECK: %[[ARR_MAP:.*]] = omp.map.info {{.*}}{name = "arr"}
+   !CHECK: omp.target is_device_ptr(%[[P_IS]] :
+   !CHECK-SAME: has_device_addr(%[[P_STORAGE]] ->
+   !CHECK-SAME: map_entries(%[[I_MAP]] ->
+   !CHECK-SAME: %[[ARR_MAP]] ->
+   !$omp target is_device_ptr(p)
+      if (c_associated(p)) i = i + 1
+      arr(1) = i
+   !$omp end target
+   !CHECK: omp.terminator
+   !CHECK: }
+end subroutine omp_target_is_device_ptr
+
+
 !===============================================================================
 ! Target Data with unstructured code
 !===============================================================================

>From 859b8742f698dd595e8128be674afe0665ceb52c Mon Sep 17 00:00:00 2001
From: Akash Banerjee <Akash.Banerjee at amd.com>
Date: Thu, 20 Nov 2025 13:57:31 +0000
Subject: [PATCH 3/4] Fix test.

---
 flang/test/Lower/OpenMP/target.f90 | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/flang/test/Lower/OpenMP/target.f90 b/flang/test/Lower/OpenMP/target.f90
index c6767ab74889a..1e62adc0f6f98 100644
--- a/flang/test/Lower/OpenMP/target.f90
+++ b/flang/test/Lower/OpenMP/target.f90
@@ -583,12 +583,10 @@ subroutine omp_target_is_device_ptr
 
    !CHECK: %[[P_STORAGE:.*]] = omp.map.info {{.*}}{name = "p"}
    !CHECK: %[[P_IS:.*]] = omp.map.info {{.*}}{name = "p"}
-   !CHECK: %[[I_MAP:.*]] = omp.map.info {{.*}}{name = "i"}
    !CHECK: %[[ARR_MAP:.*]] = omp.map.info {{.*}}{name = "arr"}
    !CHECK: omp.target is_device_ptr(%[[P_IS]] :
    !CHECK-SAME: has_device_addr(%[[P_STORAGE]] ->
-   !CHECK-SAME: map_entries(%[[I_MAP]] ->
-   !CHECK-SAME: %[[ARR_MAP]] ->
+   !CHECK-SAME: map_entries({{.*}}%[[ARR_MAP]] ->
    !$omp target is_device_ptr(p)
       if (c_associated(p)) i = i + 1
       arr(1) = i

>From eb37df515116eb20dfe3cae8212a04f89f4ab299 Mon Sep 17 00:00:00 2001
From: Akash Banerjee <Akash.Banerjee at amd.com>
Date: Thu, 20 Nov 2025 14:03:12 +0000
Subject: [PATCH 4/4] Fix clang-foramt.

---
 flang/lib/Lower/OpenMP/OpenMP.cpp | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/flang/lib/Lower/OpenMP/OpenMP.cpp b/flang/lib/Lower/OpenMP/OpenMP.cpp
index fa2e5281f0e1c..1a64a44be7c6e 100644
--- a/flang/lib/Lower/OpenMP/OpenMP.cpp
+++ b/flang/lib/Lower/OpenMP/OpenMP.cpp
@@ -2547,7 +2547,8 @@ genTargetOp(lower::AbstractConverter &converter, lower::SymMap &symTable,
   if (!isDevicePtrSyms.empty()) {
     fir::FirOpBuilder &builder = converter.getFirOpBuilder();
     llvm::DenseMap<const semantics::Symbol *, mlir::Value> symToMapInfo;
-    for (auto [symPtr, mapVal] : llvm::zip(hasDeviceAddrSyms, clauseOps.hasDeviceAddrVars))
+    for (auto [symPtr, mapVal] :
+         llvm::zip(hasDeviceAddrSyms, clauseOps.hasDeviceAddrVars))
       if (symPtr)
         symToMapInfo.try_emplace(symPtr, mapVal);
 
@@ -2579,8 +2580,7 @@ genTargetOp(lower::AbstractConverter &converter, lower::SymMap &symTable,
                 converter.getCurrentLocation());
 
         mlir::Value baseOp = info.rawInput;
-        if (auto refType =
-                mlir::dyn_cast<fir::ReferenceType>(baseOp.getType()))
+        if (auto refType = mlir::dyn_cast<fir::ReferenceType>(baseOp.getType()))
           (void)refType; // element type not needed for storage-only mapping
 
         mlir::Value mapVal = createMapInfoOp(



More information about the flang-commits mailing list