diff --git a/flang/lib/Lower/OpenMP/ClauseProcessor.cpp b/flang/lib/Lower/OpenMP/ClauseProcessor.cpp index 0ba4eddcfec2a..f618024b1162d 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); @@ -1542,7 +1554,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 e2018add11206..92934181ece4e 100644 --- a/flang/lib/Lower/OpenMP/OpenMP.cpp +++ b/flang/lib/Lower/OpenMP/OpenMP.cpp @@ -2845,11 +2845,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( 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