[flang-commits] [flang] f55080d - [flang][OpenMP] Avoid implicit default mapper on pointer captures (#184382)
via flang-commits
flang-commits at lists.llvm.org
Wed Mar 4 07:27:12 PST 2026
Author: Akash Banerjee
Date: 2026-03-04T15:27:06Z
New Revision: f55080da988a68da6736407b34eafd00817b7143
URL: https://github.com/llvm/llvm-project/commit/f55080da988a68da6736407b34eafd00817b7143
DIFF: https://github.com/llvm/llvm-project/commit/f55080da988a68da6736407b34eafd00817b7143.diff
LOG: [flang][OpenMP] Avoid implicit default mapper on pointer captures (#184382)
This change fixes incorrect implicit declare mapper behavior in Flang
OpenMP lowering.
Issue:
Implicit default mappers were being attached/generated for pointer-based
implicit captures, and also on data-motion directives. That could
trigger recursive component mapping that overlaps/conflicts with
explicit user mappings, causing runtime mapping failures.
Fix:
- Skip implicit default mapper generation for implicit pointer captures
(keep support for allocatables).
- Do not auto-attach implicit mappers on target enter data, target exit
data, or target update.
- Apply the same pointer guard in the implicit target-capture lowering
path.
Added:
flang/test/Lower/OpenMP/implicit-map-pointer-no-default-mapper.f90
Modified:
flang/lib/Lower/OpenMP/ClauseProcessor.cpp
flang/lib/Lower/OpenMP/OpenMP.cpp
flang/test/Lower/OpenMP/target-data-skip-mapper-calls.f90
Removed:
################################################################################
diff --git a/flang/lib/Lower/OpenMP/ClauseProcessor.cpp b/flang/lib/Lower/OpenMP/ClauseProcessor.cpp
index 85493bf45453e..e437ba103a258 100644
--- a/flang/lib/Lower/OpenMP/ClauseProcessor.cpp
+++ b/flang/lib/Lower/OpenMP/ClauseProcessor.cpp
@@ -1485,9 +1485,21 @@ void ClauseProcessor::processMapObjects(
mapperId = mlir::FlatSymbolRefAttr();
} else if (objectTypeSpec) {
std::string mapperIdName = getDefaultMapperID(objectTypeSpec);
+ bool isAllocOrPointer =
+ semantics::IsAllocatableOrObjectPointer(object.sym());
+ bool isPointer = semantics::IsPointer(*object.sym());
+ bool isImplicitMap =
+ (mapTypeBits & mlir::omp::ClauseMapFlags::implicit) ==
+ mlir::omp::ClauseMapFlags::implicit;
bool needsDefaultMapper =
- semantics::IsAllocatableOrObjectPointer(object.sym()) ||
+ isAllocOrPointer ||
requiresImplicitDefaultDeclareMapper(*objectTypeSpec);
+ // For implicit captures, avoid synthesizing default mappers for pointer
+ // entities (which can over-map pointer payloads) and for plain
+ // non-allocatable/non-pointer entities. Keep implicit mapper support
+ // for allocatables.
+ if (isImplicitMap && (isPointer || !isAllocOrPointer))
+ needsDefaultMapper = false;
if (!mapperIdName.empty())
mapperId = addImplicitMapper(object, mapperIdName,
/*allowGenerate=*/needsDefaultMapper);
@@ -1568,7 +1580,14 @@ bool ClauseProcessor::processMap(
if (attachMod)
TODO(currentLocation, "ATTACH modifier is not implemented yet");
mlir::omp::ClauseMapFlags mapTypeBits = mlir::omp::ClauseMapFlags::none;
+ // For data-motion directives we avoid auto-attaching implicit default
+ // mappers. Deep recursive mapping there can conflict with explicit
+ // component enter/exit maps users commonly spell out.
std::string mapperIdName = "__implicit_mapper";
+ if (directive == llvm::omp::Directive::OMPD_target_enter_data ||
+ directive == llvm::omp::Directive::OMPD_target_exit_data ||
+ directive == llvm::omp::Directive::OMPD_target_update)
+ mapperIdName.clear();
// If the map type is specified, then process it else set the appropriate
// default value
Map::MapType type;
diff --git a/flang/lib/Lower/OpenMP/OpenMP.cpp b/flang/lib/Lower/OpenMP/OpenMP.cpp
index 0676b1ce0ce53..89af32121487b 100644
--- a/flang/lib/Lower/OpenMP/OpenMP.cpp
+++ b/flang/lib/Lower/OpenMP/OpenMP.cpp
@@ -2848,11 +2848,14 @@ genTargetOp(lower::AbstractConverter &converter, lower::SymMap &symTable,
converter.mangleName(mapperIdName, *typeSpec->GetScope());
if (!mapperIdName.empty()) {
- bool allowImplicitMapper =
- semantics::IsAllocatableOrObjectPointer(&sym);
+ bool isPointer = semantics::IsPointer(sym);
+ bool isAllocatable = semantics::IsAllocatable(sym);
bool hasDefaultMapper =
converter.getModuleOp().lookupSymbol(mapperIdName);
- if (hasDefaultMapper || allowImplicitMapper) {
+ // Avoid attaching implicit default mappers to pointer captures.
+ // For large pointer-based derived aggregates this can over-map
+ // nested payloads and conflict with explicit enter/exit maps.
+ if (!isPointer && (hasDefaultMapper || isAllocatable)) {
if (!hasDefaultMapper) {
if (auto recordType = mlir::dyn_cast_or_null<fir::RecordType>(
converter.genType(*typeSpec)))
diff --git a/flang/test/Lower/OpenMP/implicit-map-pointer-no-default-mapper.f90 b/flang/test/Lower/OpenMP/implicit-map-pointer-no-default-mapper.f90
new file mode 100644
index 0000000000000..60a6db69acfa8
--- /dev/null
+++ b/flang/test/Lower/OpenMP/implicit-map-pointer-no-default-mapper.f90
@@ -0,0 +1,26 @@
+! RUN: %flang_fc1 -emit-hlfir -fopenmp %s -o - | FileCheck %s
+program p
+ type t
+ integer :: x
+ end type
+
+ type(t), pointer :: ptr
+ type(t), allocatable :: al
+ allocate(ptr, al)
+
+ !$omp target
+ ptr%x = ptr%x + 1
+ al%x = al%x + 1
+ !$omp end target
+end program
+
+! CHECK-LABEL: omp.declare_mapper @_QQFt_omp_default_mapper
+
+! CHECK-LABEL: func.func @_QQmain
+! The pointer capture should not get an implicit default mapper.
+! CHECK: %[[PTR_PTEE_MAP:.*]] = omp.map.info {{.*}}map_clauses(implicit, tofrom){{.*}} {name = ""}
+! CHECK: %[[PTR_DESC_MAP:.*]] = omp.map.info {{.*}}members(%[[PTR_PTEE_MAP]]{{.*}}){{.*}} {name = "ptr"}
+
+! The allocatable capture should still use the implicit default mapper.
+! CHECK: %[[ALLOC_PTEE_MAP:.*]] = omp.map.info {{.*}}map_clauses(implicit, tofrom){{.*}}mapper(@_QQFt_omp_default_mapper){{.*}} {name = ""}
+! CHECK: %[[ALLOC_DESC_MAP:.*]] = omp.map.info {{.*}}members(%[[ALLOC_PTEE_MAP]]{{.*}}){{.*}} {name = "al"}
diff --git a/flang/test/Lower/OpenMP/target-data-skip-mapper-calls.f90 b/flang/test/Lower/OpenMP/target-data-skip-mapper-calls.f90
index d1d441d0a7c0c..e2302873bd68e 100644
--- a/flang/test/Lower/OpenMP/target-data-skip-mapper-calls.f90
+++ b/flang/test/Lower/OpenMP/target-data-skip-mapper-calls.f90
@@ -23,8 +23,14 @@ program test
subroutine f(x, y)
integer :: x, y
+ type :: t
+ integer, pointer :: p(:)
+ end type
+ type(t) :: d
!$omp target data map(tofrom: x, y)
x = x + y
!$omp end target data
+ !$omp target enter data map(to: d)
+ !$omp target exit data map(release: d)
end subroutine
end
More information about the flang-commits
mailing list