[flang-commits] [flang] [Flang][OpenMP] Restrict implicit default declare mapper from applying deep-copies of pointer members (PR #197885)
via flang-commits
flang-commits at lists.llvm.org
Fri May 15 02:03:22 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-flang-fir-hlfir
Author: agozillon
<details>
<summary>Changes</summary>
According to the OpenMP specification, only allocatables should get deep-copy behaviour inside of implicit default declare mappers. This PR restricts this behaviour. Relevant specification exert, added as a comment for a reminder:
// "If a component of a derived type list item is a map clause list item
// that results from the predefined default mapper for that derived type,
// and the component is not also an explicit list item or the array base
// of an explicit list item on the same construct, then: if it has the
// POINTER attribute, it is attach-INELIGIBLE. If a list item in a map
// clause is an associated pointer that is attach-ineligible, the effect
// of the map clause does not apply to its pointer target."
This prevents certain programs from unexpected over-mapping via pointer nesting, doesn't prevent that for allocatables, but that's OpenMP specification mandated foot shooting, so it's free game.
---
Full diff: https://github.com/llvm/llvm-project/pull/197885.diff
2 Files Affected:
- (modified) flang/lib/Utils/OpenMP.cpp (+32)
- (added) flang/test/Lower/OpenMP/implicit-mapper-no-pointer-map.f90 (+74)
``````````diff
diff --git a/flang/lib/Utils/OpenMP.cpp b/flang/lib/Utils/OpenMP.cpp
index 834ced682a34d..b55265845c524 100644
--- a/flang/lib/Utils/OpenMP.cpp
+++ b/flang/lib/Utils/OpenMP.cpp
@@ -228,6 +228,36 @@ mlir::FlatSymbolRefAttr getOrGenImplicitDefaultDeclareMapper(
for (const auto &entry : llvm::enumerate(recordType.getTypeList())) {
const auto &memberName = entry.value().first;
const auto &memberType = entry.value().second;
+
+ // OpenMP 5.0, 5.1, 5.2: Default Map Clause
+ //
+ // "If a component of a derived type list item is a map clause list item
+ // that results from the predefined default mapper for that derived type,
+ // and the component is not also an explicit list item or the array base
+ // of an explicit list item on the same construct, then: if it has the
+ // POINTER attribute, it is attach-INELIGIBLE. If a list item in a map
+ // clause is an associated pointer that is attach-ineligible, the effect
+ // of the map clause does not apply to its pointer target."
+ //
+ // What this comes down to is we wish to skip emitting a map inside of
+ // the implicit declare mapper generation for pointer components. As well
+ // as preventing any nested record types that are pointers from being
+ // processed further by the declare mapper infrastructure. The
+ // descriptor ("pointer") should be mapped by the containing derived
+ // type, this prevents the data ("pointee") from being mapped and
+ // processed any further. We should, however, keep an eye on if the
+ // record types mapping applying to this descriptor poses issues, or
+ // if attach-ineligible still requires an attach map to be emitted
+ // alongside the descriptor, even if the pointee has no map emitted.
+ // if either case applies, then we will need to emit the maps here and
+ // then opt out of base address expansion for these implicit declare
+ // mappers in the MapInfoFinalization pass.
+ //
+ // Notably, this caveat does not apply to allocatables. They get
+ // deep-copy semantics.
+ if (fir::isPointerType(fir::unwrapRefType(memberType)))
+ continue;
+
mlir::FlatSymbolRefAttr mapperId;
if (auto recType = mlir::dyn_cast<fir::RecordType>(
fir::getFortranElementType(memberType))) {
@@ -238,6 +268,8 @@ mlir::FlatSymbolRefAttr getOrGenImplicitDefaultDeclareMapper(
firOpBuilder, loc, recType, mapperIdName, mangler);
}
+ // - do we prevent maps of internal pointer record types with this? need to
+ // test that
auto ref =
getFieldRef(declareOp.getBase(), memberName, memberType, recordType);
llvm::SmallVector<mlir::Value> bounds;
diff --git a/flang/test/Lower/OpenMP/implicit-mapper-no-pointer-map.f90 b/flang/test/Lower/OpenMP/implicit-mapper-no-pointer-map.f90
new file mode 100644
index 0000000000000..9338f9ba87888
--- /dev/null
+++ b/flang/test/Lower/OpenMP/implicit-mapper-no-pointer-map.f90
@@ -0,0 +1,74 @@
+! RUN: %flang_fc1 -emit-hlfir -fopenmp %s -o - | FileCheck %s
+
+! Test that pointer components (including pointers to nested record types)
+! do not have maps emitted inside implicit declare mappers, while
+! allocatable components do have maps. Tests three levels of nesting.
+
+program test_implicit_mapper_no_pointer_map
+ implicit none
+
+ type :: leaf_type
+ integer :: leaf_val = 0
+ real(8), allocatable :: leaf_arr(:)
+ real(8), pointer :: leaf_ptr_arr(:) => null() ! Should NOT be mapped
+ end type leaf_type
+
+ type :: inner_type
+ integer :: val = 0
+ real(8), allocatable :: arr(:)
+ real(8), pointer :: ptr_arr(:) => null() ! Should NOT be mapped
+ type(leaf_type), allocatable :: alloc_leaf ! SHOULD be mapped with nested mapper
+ type(leaf_type), pointer :: ptr_leaf => null() ! Should NOT be mapped
+ end type inner_type
+
+ type :: outer_type
+ integer :: id = 0
+ type(inner_type), allocatable :: alloc_inner ! SHOULD be mapped with nested mapper
+ type(inner_type), pointer :: ptr_inner => null() ! Should NOT be mapped
+ real(8), allocatable :: alloc_arr(:) ! SHOULD be mapped
+ integer, pointer :: ptr_scalar => null() ! Should NOT be mapped
+ end type outer_type
+
+ type(outer_type), allocatable :: obj
+
+ !$omp target
+ obj%id = 1
+ !$omp end target
+
+end program test_implicit_mapper_no_pointer_map
+
+! CHECK-LABEL: omp.declare_mapper @{{.*}}leaf_type_omp_default_mapper : !fir.type<_QFTleaf_type{
+! CHECK: %[[LEAF_VAL:.*]] = omp.map.info var_ptr(%{{.*}} : !fir.ref<i32>, i32){{.*}}map_clauses(implicit, tofrom)
+! CHECK: %[[LEAF_ARR_DATA:.*]] = omp.map.info var_ptr(%{{.*}}){{.*}}map_clauses(implicit, tofrom){{.*}}-> !fir.llvm_ptr
+! CHECK: %[[LEAF_ARR_DESC:.*]] = omp.map.info var_ptr(%{{.*}}){{.*}}map_clauses(always, implicit, to)
+! CHECK: %[[LEAF_ARR_ATTACH:.*]] = omp.map.info var_ptr(%{{.*}}){{.*}}map_clauses(attach, ref_ptr, ref_ptee)
+! CHECK: %[[LEAF_PARENT:.*]] = omp.map.info var_ptr({{.*}}!fir.type<_QFTleaf_type{{.*}}>){{.*}}members(%[[LEAF_VAL]], %[[LEAF_ARR_DESC]], %[[LEAF_ARR_DATA]] : [0], [1], [1, 0] :
+! CHECK: omp.declare_mapper.info map_entries(%[[LEAF_PARENT]], %[[LEAF_VAL]], %[[LEAF_ARR_DESC]], %[[LEAF_ARR_ATTACH]], %[[LEAF_ARR_DATA]] :
+
+! CHECK-LABEL: omp.declare_mapper @{{.*}}inner_type_omp_default_mapper : !fir.type<_QFTinner_type{
+! CHECK: %[[INNER_VAL:.*]] = omp.map.info var_ptr(%{{.*}} : !fir.ref<i32>, i32){{.*}}map_clauses(implicit, tofrom)
+! CHECK: %[[INNER_ARR_DATA:.*]] = omp.map.info var_ptr(%{{.*}}){{.*}}map_clauses(implicit, tofrom){{.*}}-> !fir.llvm_ptr{{.*}}{name = ""}
+! CHECK: %[[INNER_ARR_DESC:.*]] = omp.map.info var_ptr(%{{.*}}){{.*}}map_clauses(always, implicit, to){{.*}}{name = ""}
+! CHECK: %[[INNER_ARR_ATTACH:.*]] = omp.map.info var_ptr(%{{.*}}){{.*}}map_clauses(attach, ref_ptr, ref_ptee){{.*}}{name = ""}
+! CHECK: %[[INNER_ALLOC_LEAF_DATA:.*]] = omp.map.info var_ptr(%{{.*}}){{.*}}map_clauses(implicit, tofrom){{.*}}mapper(@{{.*}}leaf_type_omp_default_mapper){{.*}}-> !fir.llvm_ptr
+! CHECK: %[[INNER_ALLOC_LEAF_DESC:.*]] = omp.map.info var_ptr(%{{.*}}){{.*}}map_clauses(always, implicit, to){{.*}}{name = ""}
+! CHECK: %[[INNER_ALLOC_LEAF_ATTACH:.*]] = omp.map.info var_ptr(%{{.*}}){{.*}}map_clauses(attach, ref_ptr, ref_ptee){{.*}}{name = ""}
+! CHECK: %[[INNER_PARENT:.*]] = omp.map.info var_ptr({{.*}}!fir.type<_QFTinner_type{{.*}}>){{.*}}members(%[[INNER_VAL]], %[[INNER_ARR_DESC]], %[[INNER_ARR_DATA]], %[[INNER_ALLOC_LEAF_DESC]], %[[INNER_ALLOC_LEAF_DATA]] : [0], [1], [1, 0], [3], [3, 0] :
+! CHECK: omp.declare_mapper.info map_entries(%[[INNER_PARENT]], %[[INNER_VAL]], %[[INNER_ARR_DESC]], %[[INNER_ALLOC_LEAF_DESC]], %[[INNER_ARR_ATTACH]], %[[INNER_ALLOC_LEAF_ATTACH]], %[[INNER_ARR_DATA]], %[[INNER_ALLOC_LEAF_DATA]] :
+
+! CHECK-LABEL: omp.declare_mapper @{{.*}}outer_type_omp_default_mapper : !fir.type<_QFTouter_type{
+! CHECK: %[[OUTER_ID:.*]] = omp.map.info var_ptr(%{{.*}} : !fir.ref<i32>, i32){{.*}}map_clauses(implicit, tofrom)
+! CHECK: %[[OUTER_ALLOC_INNER_DATA:.*]] = omp.map.info var_ptr(%{{.*}}){{.*}}map_clauses(implicit, tofrom){{.*}}mapper(@{{.*}}inner_type_omp_default_mapper){{.*}}-> !fir.llvm_ptr
+! CHECK: %[[OUTER_ALLOC_INNER_DESC:.*]] = omp.map.info var_ptr(%{{.*}}){{.*}}map_clauses(always, implicit, to){{.*}}{name = ""}
+! CHECK: %[[OUTER_ALLOC_INNER_ATTACH:.*]] = omp.map.info var_ptr(%{{.*}}){{.*}}map_clauses(attach, ref_ptr, ref_ptee){{.*}}{name = ""}
+! CHECK: %[[OUTER_ALLOC_ARR_DATA:.*]] = omp.map.info var_ptr(%{{.*}}){{.*}}map_clauses(implicit, tofrom){{.*}}-> !fir.llvm_ptr{{.*}}{name = ""}
+! CHECK: %[[OUTER_ALLOC_ARR_DESC:.*]] = omp.map.info var_ptr(%{{.*}}){{.*}}map_clauses(always, implicit, to){{.*}}{name = ""}
+! CHECK: %[[OUTER_ALLOC_ARR_ATTACH:.*]] = omp.map.info var_ptr(%{{.*}}){{.*}}map_clauses(attach, ref_ptr, ref_ptee){{.*}}{name = ""}
+! CHECK: %[[OUTER_PARENT:.*]] = omp.map.info var_ptr({{.*}}!fir.type<_QFTouter_type{{.*}}>){{.*}}members(%[[OUTER_ID]], %[[OUTER_ALLOC_INNER_DESC]], %[[OUTER_ALLOC_INNER_DATA]], %[[OUTER_ALLOC_ARR_DESC]], %[[OUTER_ALLOC_ARR_DATA]] : [0], [1], [1, 0], [3], [3, 0] :
+! CHECK: omp.declare_mapper.info map_entries(%[[OUTER_PARENT]], %[[OUTER_ID]], %[[OUTER_ALLOC_INNER_DESC]], %[[OUTER_ALLOC_ARR_DESC]], %[[OUTER_ALLOC_INNER_ATTACH]], %[[OUTER_ALLOC_ARR_ATTACH]], %[[OUTER_ALLOC_INNER_DATA]], %[[OUTER_ALLOC_ARR_DATA]] :
+
+! CHECK-LABEL: func.func @_QQmain
+! CHECK: %[[DATA_MAP:.*]] = omp.map.info var_ptr({{.*}}){{.*}}map_clauses(implicit, tofrom){{.*}}mapper(@{{.*}}outer_type_omp_default_mapper){{.*}}-> !fir.llvm_ptr
+! CHECK: %[[DESC_MAP:.*]] = omp.map.info var_ptr({{.*}}){{.*}}map_clauses(always, implicit, to){{.*}}members(%[[DATA_MAP]] : [0] :{{.*}}){{.*}}{name = "obj"}
+! CHECK: %[[ATTACH_MAP:.*]] = omp.map.info var_ptr({{.*}}){{.*}}map_clauses(attach, ref_ptr, ref_ptee){{.*}}{name = "obj"}
+! CHECK: omp.target map_entries(%[[DESC_MAP]] -> %{{.*}}, %[[ATTACH_MAP]] -> %{{.*}}, %[[DATA_MAP]] -> %{{.*}} :
``````````
</details>
https://github.com/llvm/llvm-project/pull/197885
More information about the flang-commits
mailing list