[flang-commits] [flang] [llvm] [Flang][OpenMP] Fix Fortran pointer map(present) null handling (PR #204615)
Akash Banerjee via flang-commits
flang-commits at lists.llvm.org
Thu Jun 18 07:57:17 PDT 2026
https://github.com/TIFitis created https://github.com/llvm/llvm-project/pull/204615
Allow map(present, to: ...) on a Fortran pointer with a null, zero-length pointee map without aborting the target region.
>From 3d273241433ed9e3966b043f99597a4ec9706e9d Mon Sep 17 00:00:00 2001
From: Akash Banerjee <Akash.Banerjee at amd.com>
Date: Thu, 18 Jun 2026 15:40:22 +0100
Subject: [PATCH] [Flang][OpenMP] Fix Fortran pointer map(present) null
handling
Allow map(present, to: ...) on a Fortran pointer with a null, zero-length pointee map without aborting the target region.
Co-authored-by: Codex <codex at openai.com>
---
.../test/Lower/OpenMP/map-present-pointer.f90 | 16 +++++++++
offload/include/OpenMP/Mapping.h | 4 +++
offload/libomptarget/OpenMP/Mapping.cpp | 2 +-
offload/libomptarget/omptarget.cpp | 6 ++--
.../fortran/target_map_present_pointer.f90 | 34 +++++++++++++++++++
5 files changed, 59 insertions(+), 3 deletions(-)
create mode 100644 flang/test/Lower/OpenMP/map-present-pointer.f90
create mode 100644 offload/test/offloading/fortran/target_map_present_pointer.f90
diff --git a/flang/test/Lower/OpenMP/map-present-pointer.f90 b/flang/test/Lower/OpenMP/map-present-pointer.f90
new file mode 100644
index 0000000000000..8363606be9d99
--- /dev/null
+++ b/flang/test/Lower/OpenMP/map-present-pointer.f90
@@ -0,0 +1,16 @@
+! RUN: %flang_fc1 -emit-hlfir -fopenmp %s -o - | FileCheck %s
+
+subroutine map_present_pointer(p)
+ integer, pointer :: p(:)
+
+! CHECK-LABEL: func.func @_QPmap_present_pointer
+! CHECK: %[[DECL:.*]]:2 = hlfir.declare %{{.*}} {fortran_attrs = #fir.var_attrs<pointer>
+! CHECK: %[[BASE:.*]] = fir.box_offset %[[DECL]]#1 base_addr
+! CHECK: %[[PTEE_MAP:.*]] = omp.map.info var_ptr(%[[DECL]]#1 : {{.*}}) map_clauses(present, to) capture(ByRef) var_ptr_ptr(%[[BASE]] : {{.*}}) {{.*}} -> !fir.llvm_ptr
+! CHECK: %[[DESC_MAP:.*]] = omp.map.info var_ptr(%[[DECL]]#1 : {{.*}}) map_clauses(always, to) capture(ByRef) members(%[[PTEE_MAP]] : [0] : {{.*}}) -> {{.*}} {name = "p"}
+! CHECK: %[[ATTACH_MAP:.*]] = omp.map.info var_ptr(%[[DECL]]#1 : {{.*}}) map_clauses(attach, ref_ptr, ref_ptee) capture(ByRef) var_ptr_ptr(%[[BASE]] : {{.*}})
+! CHECK: omp.target map_entries(%[[DESC_MAP]] -> {{.*}}, %[[ATTACH_MAP]] -> {{.*}}, %[[PTEE_MAP]] -> {{.*}}
+!$omp target map(present, to: p)
+ if (associated(p)) p(1) = p(1)
+!$omp end target
+end subroutine
diff --git a/offload/include/OpenMP/Mapping.h b/offload/include/OpenMP/Mapping.h
index e4024abf26690..f76363af5091c 100644
--- a/offload/include/OpenMP/Mapping.h
+++ b/offload/include/OpenMP/Mapping.h
@@ -28,6 +28,10 @@ class AsyncInfoTy;
using map_var_info_t = void *;
+inline bool isNullMap(const void *HstPtrBegin, int64_t Size) {
+ return HstPtrBegin == nullptr && Size == 0;
+}
+
class MappingConfig {
MappingConfig() {
diff --git a/offload/libomptarget/OpenMP/Mapping.cpp b/offload/libomptarget/OpenMP/Mapping.cpp
index 1bb2e424bd083..3639fb160181a 100644
--- a/offload/libomptarget/OpenMP/Mapping.cpp
+++ b/offload/libomptarget/OpenMP/Mapping.cpp
@@ -283,7 +283,7 @@ TargetPointerResultTy MappingInfoTy::getTargetPointer(
LR.TPR.Flags.IsHostPointer = true;
LR.TPR.TargetPointer = HstPtrBegin;
}
- } else if (HasPresentModifier) {
+ } else if (HasPresentModifier && !isNullMap(HstPtrBegin, Size)) {
ODBG(ODT_Mapping) << "Mapping required by 'present' map type modifier does "
<< "not exist for HstPtrBegin=" << HstPtrBegin
<< ", Size=" << Size;
diff --git a/offload/libomptarget/omptarget.cpp b/offload/libomptarget/omptarget.cpp
index 17b215732d51b..91489f9c03a9b 100644
--- a/offload/libomptarget/omptarget.cpp
+++ b/offload/libomptarget/omptarget.cpp
@@ -665,7 +665,8 @@ int targetDataBegin(ident_t *Loc, DeviceTy &Device, int32_t ArgNum,
IsHostPtr = TPR.Flags.IsHostPointer;
// If data_size==0, then the argument could be a zero-length pointer to
// NULL, so getOrAlloc() returning NULL is not an error.
- if (!TgtPtrBegin && (DataSize || HasPresentModifier)) {
+ if (!TgtPtrBegin && (DataSize || (HasPresentModifier &&
+ !isNullMap(HstPtrBegin, DataSize)))) {
REPORT() << "Call to getTargetPointer returned null pointer ("
<< (HasPresentModifier ? "'present' map type modifier"
: "device failure or illegal mapping")
@@ -1132,7 +1133,8 @@ int targetDataEnd(ident_t *Loc, DeviceTy &Device, int32_t ArgNum,
ForceDelete, /*FromDataEnd=*/true);
void *TgtPtrBegin = TPR.TargetPointer;
if (!TPR.isPresent() && !TPR.isHostPointer() &&
- (DataSize || HasPresentModifier)) {
+ (DataSize ||
+ (HasPresentModifier && !isNullMap(HstPtrBegin, DataSize)))) {
ODBG(ODT_Mapping) << "Mapping does not exist ("
<< (HasPresentModifier ? "'present' map type modifier"
: "ignored")
diff --git a/offload/test/offloading/fortran/target_map_present_pointer.f90 b/offload/test/offloading/fortran/target_map_present_pointer.f90
new file mode 100644
index 0000000000000..07d2176b3e312
--- /dev/null
+++ b/offload/test/offloading/fortran/target_map_present_pointer.f90
@@ -0,0 +1,34 @@
+! REQUIRES: flang, amdgpu
+! RUN: %libomptarget-compile-fortran-generic
+! RUN: %libomptarget-run-generic 2>&1 | %fcheck-generic
+
+program map_present_pointer
+ implicit none
+ integer, target :: src(4) = [10, 20, 30, 40]
+ integer, pointer :: p(:) => null()
+ integer :: out
+
+ out = -1
+!$omp target map(present, to: p) map(tofrom: out)
+ if (associated(p)) out = p(1)
+!$omp end target
+
+ if (out /= -1) stop 1
+ print *, "null pointer ok"
+
+ p => src
+ out = -1
+
+!$omp target enter data map(to: src)
+!$omp target map(present, to: p) map(from: out)
+ out = p(2)
+!$omp end target
+!$omp target exit data map(delete: src)
+
+ if (out /= 20) stop 2
+ print *, "associated pointer ok"
+end program
+
+! CHECK-NOT: omptarget
+! CHECK: null pointer ok
+! CHECK: associated pointer ok
More information about the flang-commits
mailing list