[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