diff --git a/flang/lib/Lower/OpenMP/ClauseProcessor.cpp b/flang/lib/Lower/OpenMP/ClauseProcessor.cpp index 7bea427099a28..58f3d9d5e62f3 100644 --- a/flang/lib/Lower/OpenMP/ClauseProcessor.cpp +++ b/flang/lib/Lower/OpenMP/ClauseProcessor.cpp @@ -1183,8 +1183,19 @@ void ClauseProcessor::processMapObjects( typeSpec->name().ToString() + llvm::omp::OmpDefaultMapperName; if (auto *sym = converter.getCurrentScope().FindSymbol(mapperIdName)) mapperIdName = converter.mangleName(mapperIdName, sym->owner()); + else + mapperIdName = + converter.mangleName(mapperIdName, *typeSpec->GetScope()); } } + + // Make sure we don't return a mapper to self. + llvm::StringRef parentOpName; + if (auto declMapOp = mlir::dyn_cast( + firOpBuilder.getRegion().getParentOp())) + parentOpName = declMapOp.getSymName(); + if (mapperIdName == parentOpName) + mapperIdName = ""; }; // Create the mapper symbol from its name, if specified. @@ -1288,7 +1299,7 @@ bool ClauseProcessor::processMap( llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_NONE; std::string mapperIdName = "__implicit_mapper"; // If the map type is specified, then process it else set the appropriate - // default value + // default value. Map::MapType type; if (directive == llvm::omp::Directive::OMPD_target_enter_data && semaCtx.langOptions().OpenMPVersion >= 52) diff --git a/flang/lib/Lower/OpenMP/OpenMP.cpp b/flang/lib/Lower/OpenMP/OpenMP.cpp index 0a56e888ac44b..3b40f9dda8bb2 100644 --- a/flang/lib/Lower/OpenMP/OpenMP.cpp +++ b/flang/lib/Lower/OpenMP/OpenMP.cpp @@ -2391,6 +2391,122 @@ genSingleOp(lower::AbstractConverter &converter, lower::SymMap &symTable, queue, item, clauseOps); } +static mlir::FlatSymbolRefAttr getOrGenImplicitDefaultDeclareMapper( + lower::AbstractConverter &converter, mlir::Location loc, + fir::RecordType recordType, llvm::StringRef mapperNameStr) { + if (converter.getModuleOp().lookupSymbol(mapperNameStr)) + return mlir::FlatSymbolRefAttr::get(&converter.getMLIRContext(), + mapperNameStr); + + fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); + + // Save current insertion point before moving to the module scope to create + // the DeclareMapperOp. + mlir::OpBuilder::InsertionGuard guard(firOpBuilder); + + firOpBuilder.setInsertionPointToStart(converter.getModuleOp().getBody()); + auto declMapperOp = firOpBuilder.create( + loc, mapperNameStr, recordType); + auto ®ion = declMapperOp.getRegion(); + firOpBuilder.createBlock(®ion); + auto mapperArg = region.addArgument(firOpBuilder.getRefType(recordType), loc); + + auto declareOp = + firOpBuilder.create(loc, mapperArg, /*uniq_name=*/""); + + const auto genBoundsOps = [&](mlir::Value mapVal, + llvm::SmallVectorImpl &bounds) { + fir::ExtendedValue extVal = + hlfir::translateToExtendedValue(mapVal.getLoc(), firOpBuilder, + hlfir::Entity{mapVal}, + /*contiguousHint=*/true) + .first; + fir::factory::AddrAndBoundsInfo info = fir::factory::getDataOperandBaseAddr( + firOpBuilder, mapVal, /*isOptional=*/false, mapVal.getLoc()); + bounds = fir::factory::genImplicitBoundsOps( + firOpBuilder, info, extVal, + /*dataExvIsAssumedSize=*/false, mapVal.getLoc()); + }; + + // Return a reference to the contents of a derived type with one field. + // Also return the field type. + const auto getFieldRef = + [&](mlir::Value rec, llvm::StringRef fieldName, mlir::Type fieldTy, + mlir::Type recType) -> std::tuple { + mlir::Value field = firOpBuilder.create( + loc, fir::FieldType::get(recType.getContext()), fieldName, recType, + fir::getTypeParams(rec)); + return {firOpBuilder.create( + loc, firOpBuilder.getRefType(fieldTy), rec, field), + fieldTy}; + }; + + mlir::omp::DeclareMapperInfoOperands clauseOps; + llvm::SmallVector> memberPlacementIndices; + llvm::SmallVector memberMapOps; + + llvm::omp::OpenMPOffloadMappingFlags mapFlag = + llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TO | + llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_FROM | + llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT; + mlir::omp::VariableCaptureKind captureKind = + mlir::omp::VariableCaptureKind::ByRef; + + // Populate the declareMapper region with the map information. + for (const auto &entry : llvm::enumerate( + mlir::dyn_cast(recordType).getTypeList())) { + const auto &memberName = entry.value().first; + const auto &memberType = entry.value().second; + auto [ref, type] = + getFieldRef(declareOp.getBase(), memberName, memberType, recordType); + mlir::FlatSymbolRefAttr mapperId; + if (auto recType = mlir::dyn_cast(memberType)) { + std::string mapperIdName = + recType.getName().str() + llvm::omp::OmpDefaultMapperName; + if (auto *sym = converter.getCurrentScope().FindSymbol(mapperIdName)) + mapperIdName = converter.mangleName(mapperIdName, sym->owner()); + else if (auto *sym = converter.getCurrentScope().FindSymbol(memberName)) + mapperIdName = converter.mangleName(mapperIdName, sym->owner()); + + mapperId = getOrGenImplicitDefaultDeclareMapper(converter, loc, recType, + mapperIdName); + } + + llvm::SmallVector bounds; + genBoundsOps(ref, bounds); + mlir::Value mapOp = createMapInfoOp( + firOpBuilder, loc, ref, /*varPtrPtr=*/mlir::Value{}, /*name=*/"", + bounds, + /*members=*/{}, + /*membersIndex=*/mlir::ArrayAttr{}, + static_cast< + std::underlying_type_t>( + mapFlag), + captureKind, ref.getType(), /*partialMap=*/false, mapperId); + memberMapOps.emplace_back(mapOp); + memberPlacementIndices.emplace_back( + llvm::SmallVector{(int64_t)entry.index()}); + } + + llvm::SmallVector bounds; + genBoundsOps(declareOp.getOriginalBase(), bounds); + mlir::omp::MapInfoOp mapOp = createMapInfoOp( + firOpBuilder, loc, declareOp.getOriginalBase(), + /*varPtrPtr=*/mlir::Value(), /*name=*/"", bounds, memberMapOps, + firOpBuilder.create2DI64ArrayAttr(memberPlacementIndices), + static_cast>( + mapFlag), + captureKind, declareOp.getType(0), + /*partialMap=*/true); + + clauseOps.mapVars.emplace_back(mapOp); + + firOpBuilder.create(loc, clauseOps.mapVars); + return mlir::FlatSymbolRefAttr::get(&converter.getMLIRContext(), + mapperNameStr); +} + static mlir::omp::TargetOp genTargetOp(lower::AbstractConverter &converter, lower::SymMap &symTable, lower::StatementContext &stmtCtx, @@ -2467,15 +2583,25 @@ genTargetOp(lower::AbstractConverter &converter, lower::SymMap &symTable, name << sym.name().ToString(); mlir::FlatSymbolRefAttr mapperId; - if (sym.GetType()->category() == semantics::DeclTypeSpec::TypeDerived) { + if (sym.GetType()->category() == semantics::DeclTypeSpec::TypeDerived && + defaultMaps.empty()) { auto &typeSpec = sym.GetType()->derivedTypeSpec(); std::string mapperIdName = typeSpec.name().ToString() + llvm::omp::OmpDefaultMapperName; if (auto *sym = converter.getCurrentScope().FindSymbol(mapperIdName)) mapperIdName = converter.mangleName(mapperIdName, sym->owner()); + else + mapperIdName = + converter.mangleName(mapperIdName, *typeSpec.GetScope()); + if (converter.getModuleOp().lookupSymbol(mapperIdName)) mapperId = mlir::FlatSymbolRefAttr::get(&converter.getMLIRContext(), mapperIdName); + mapperId = getOrGenImplicitDefaultDeclareMapper( + converter, loc, + mlir::cast( + converter.genType(sym.GetType()->derivedTypeSpec())), + mapperIdName); } fir::factory::AddrAndBoundsInfo info = diff --git a/flang/lib/Optimizer/OpenMP/MapInfoFinalization.cpp b/flang/lib/Optimizer/OpenMP/MapInfoFinalization.cpp index f052cf8d22d1e..2a11aff4befc0 100644 --- a/flang/lib/Optimizer/OpenMP/MapInfoFinalization.cpp +++ b/flang/lib/Optimizer/OpenMP/MapInfoFinalization.cpp @@ -433,7 +433,7 @@ class MapInfoFinalizationPass getDescriptorMapType(mapType, target)), op.getMapCaptureTypeAttr(), /*varPtrPtr=*/mlir::Value{}, newMembers, newMembersAttr, /*bounds=*/mlir::SmallVector{}, - /*mapperId*/ mlir::FlatSymbolRefAttr(), op.getNameAttr(), + op.getMapperIdAttr(), op.getNameAttr(), /*partial_map=*/builder.getBoolAttr(false)); op.replaceAllUsesWith(newDescParentMapOp.getResult()); op->erase(); diff --git a/flang/test/Lower/OpenMP/derived-type-map.f90 b/flang/test/Lower/OpenMP/derived-type-map.f90 index 279cddec51fcf..1dd73229d8251 100644 --- a/flang/test/Lower/OpenMP/derived-type-map.f90 +++ b/flang/test/Lower/OpenMP/derived-type-map.f90 @@ -1,9 +1,11 @@ !RUN: %flang_fc1 -emit-hlfir -fopenmp %s -o - | FileCheck %s +!CHECK: omp.declare_mapper @[[MAPPER1:_QQFmaptype_derived_implicit_allocatablescalar_and_array.omp.default.mapper]] : !fir.type<_QFmaptype_derived_implicit_allocatableTscalar_and_array{real:f32,array:!fir.array<10xi32>,int:i32}> { +!CHECK: omp.declare_mapper @[[MAPPER2:_QQFmaptype_derived_implicitscalar_and_array.omp.default.mapper]] : !fir.type<_QFmaptype_derived_implicitTscalar_and_array{real:f32,array:!fir.array<10xi32>,int:i32}> { !CHECK: %[[ALLOCA:.*]] = fir.alloca !fir.type<_QFmaptype_derived_implicitTscalar_and_array{real:f32,array:!fir.array<10xi32>,int:i32}> {bindc_name = "scalar_arr", uniq_name = "_QFmaptype_derived_implicitEscalar_arr"} !CHECK: %[[DECLARE:.*]]:2 = hlfir.declare %[[ALLOCA]] {uniq_name = "_QFmaptype_derived_implicitEscalar_arr"} : (!fir.ref,int:i32}>>) -> (!fir.ref,int:i32}>>, !fir.ref,int:i32}>>) -!CHECK: %[[MAP:.*]] = omp.map.info var_ptr(%[[DECLARE]]#1 : !fir.ref,int:i32}>>, !fir.type<_QFmaptype_derived_implicitTscalar_and_array{real:f32,array:!fir.array<10xi32>,int:i32}>) map_clauses(implicit, tofrom) capture(ByRef) -> !fir.ref,int:i32}>> {name = "scalar_arr"} +!CHECK: %[[MAP:.*]] = omp.map.info var_ptr(%[[DECLARE]]#1 : !fir.ref,int:i32}>>, !fir.type<_QFmaptype_derived_implicitTscalar_and_array{real:f32,array:!fir.array<10xi32>,int:i32}>) map_clauses(implicit, tofrom) capture(ByRef) mapper(@[[MAPPER2]]) -> !fir.ref,int:i32}>> {name = "scalar_arr"} !CHECK: omp.target map_entries(%[[MAP]] -> %[[ARG0:.*]] : !fir.ref,int:i32}>>) { subroutine mapType_derived_implicit type :: scalar_and_array @@ -18,6 +20,24 @@ subroutine mapType_derived_implicit !$omp end target end subroutine mapType_derived_implicit +!CHECK: %[[ALLOCA:.*]] = fir.alloca !fir.box,int:i32}>>> {bindc_name = "scalar_arr", uniq_name = "_QFmaptype_derived_implicit_allocatableEscalar_arr"} +!CHECK: %[[DECLARE:.*]]:2 = hlfir.declare %[[ALLOCA]] {fortran_attrs = #fir.var_attrs, uniq_name = "_QFmaptype_derived_implicit_allocatableEscalar_arr"} : {{.*}} +!CHECK: %[[MAP:.*]] = omp.map.info var_ptr(%[[DECLARE]]#1 : {{.*}}) map_clauses(implicit, to) capture(ByRef) mapper(@[[MAPPER1]]) +!CHECK: omp.target map_entries(%[[MAP]] -> %[[ARG0:.*]] : !fir.ref,int:i32}>>>>, !fir.llvm_ptr,int:i32}>>>) { +subroutine mapType_derived_implicit_allocatable + type :: scalar_and_array + real(4) :: real + integer(4) :: array(10) + integer(4) :: int + end type scalar_and_array + type(scalar_and_array), allocatable :: scalar_arr + + allocate (scalar_arr) + !$omp target + scalar_arr%int = 1 + !$omp end target +end subroutine mapType_derived_implicit_allocatable + !CHECK: %[[ALLOCA:.*]] = fir.alloca !fir.type<_QFmaptype_derived_explicitTscalar_and_array{real:f32,array:!fir.array<10xi32>,int:i32}> {bindc_name = "scalar_arr", uniq_name = "_QFmaptype_derived_explicitEscalar_arr"} !CHECK: %[[DECLARE:.*]]:2 = hlfir.declare %[[ALLOCA]] {uniq_name = "_QFmaptype_derived_explicitEscalar_arr"} : (!fir.ref,int:i32}>>) -> (!fir.ref,int:i32}>>, !fir.ref,int:i32}>>) !CHECK: %[[MAP:.*]] = omp.map.info var_ptr(%[[DECLARE]]#1 : !fir.ref,int:i32}>>, !fir.type<_QFmaptype_derived_explicitTscalar_and_array{real:f32,array:!fir.array<10xi32>,int:i32}>) map_clauses(tofrom) capture(ByRef) -> !fir.ref,int:i32}>> {name = "scalar_arr"}