From 96134b2d67350af6d9516b6c77bd9c89d25cd209 Mon Sep 17 00:00:00 2001 From: agozillon Date: Mon, 8 Jul 2024 08:50:11 -0500 Subject: [PATCH] [Flang][MLIR][OpenMP] Align map clause generation and fix issue with non-shared allocations for assumed shape/size descriptor types This PR aims unify the map argument generation across both the implicit capture (captured in a target region) and the explicit capture (process map), currently the varPtr field of the MapInfo for the same variable will be different depending on how it's captured. This PR tries to align that across the generations of MapInfoOp in the OpenMP lowering. Currently, I have opted to utilise the rawInput (input memref to a HLFIR DeclareInfoOp) as opposed to the addr field which includes more information. The side affect of this is that we have to deal with BoxTypes less often, which will result in simpler maps in these cases. The negative side affect of this is that we don't have access to the bounds information through the resulting value, however, I believe the bounds information we require in our case is still appropriately stored in the map bounds, and this seems to be the case from testing so far. The other fix is for cases where we end up with a BoxType argument into a function (certain assumed shape and sizes cases do this) that has no fir.ref wrapping it. As we need the Box to be a reference type to actually utilise the operation to access the base address stored inside and create the correct mappings we currently generate an intermediate allocation in these cases, and then store into it, and utilise this as the map argument, as opposed to the original. However, as we were not sharing the same intermediate allocation across all of the maps for a variable, this resulted in errors in certain cases when detatching/attatching the data e.g. via enter and exit. This PR adjusts this for cases Currently we only maintain tracking of all intermediate allocations for the current function scope, as opposed to module. Primarily as the only case I am aware of that this is required is in cases where we pass certain types of arguments to functions (so I opted to minimize the overhead of the pass for now). It could likely be extended to module scope if required if we find other cases where it's applicable and causing issues. --- .../flang/Optimizer/Transforms/Passes.td | 6 +- flang/lib/Lower/OpenMP/ClauseProcessor.cpp | 44 ++--- flang/lib/Lower/OpenMP/ClauseProcessor.h | 10 +- flang/lib/Lower/OpenMP/OpenMP.cpp | 150 +++++++++--------- .../Transforms/OMPMapInfoFinalization.cpp | 44 +++-- flang/test/Lower/OpenMP/array-bounds.f90 | 15 +- flang/test/Lower/OpenMP/common-block-map.f90 | 2 +- flang/test/Lower/OpenMP/derived-type-map.f90 | 2 +- flang/test/Lower/OpenMP/target.f90 | 23 ++- 9 files changed, 147 insertions(+), 149 deletions(-) diff --git a/flang/include/flang/Optimizer/Transforms/Passes.td b/flang/include/flang/Optimizer/Transforms/Passes.td index 7e6bebbb464fad..76971911bc5a5e 100644 --- a/flang/include/flang/Optimizer/Transforms/Passes.td +++ b/flang/include/flang/Optimizer/Transforms/Passes.td @@ -342,11 +342,11 @@ def LoopVersioning : Pass<"loop-versioning", "mlir::func::FuncOp"> { } def OMPMapInfoFinalizationPass - : Pass<"omp-map-info-finalization"> { + : Pass<"omp-map-info-finalization", "mlir::func::FuncOp"> { let summary = "expands OpenMP MapInfo operations containing descriptors"; let description = [{ - Expands MapInfo operations containing descriptor types into multiple - MapInfo's for each pointer element in the descriptor that requires + Expands MapInfo operations containing descriptor types into multiple + MapInfo's for each pointer element in the descriptor that requires explicit individual mapping by the OpenMP runtime. }]; let dependentDialects = ["mlir::omp::OpenMPDialect"]; diff --git a/flang/lib/Lower/OpenMP/ClauseProcessor.cpp b/flang/lib/Lower/OpenMP/ClauseProcessor.cpp index 0901e95db573a1..ed81f0d97e06c4 100644 --- a/flang/lib/Lower/OpenMP/ClauseProcessor.cpp +++ b/flang/lib/Lower/OpenMP/ClauseProcessor.cpp @@ -970,25 +970,21 @@ bool ClauseProcessor::processMap( object.ref(), clauseLocation, asFortran, bounds, treatIndexAsSection); - auto origSymbol = converter.getSymbolAddress(*object.sym()); - mlir::Value symAddr = info.addr; - if (origSymbol && fir::isTypeWithDescriptor(origSymbol.getType())) - symAddr = origSymbol; - // Explicit map captures are captured ByRef by default, // optimisation passes may alter this to ByCopy or other capture // types to optimise + mlir::Value baseOp = info.rawInput; auto location = mlir::NameLoc::get( mlir::StringAttr::get(firOpBuilder.getContext(), asFortran.str()), - symAddr.getLoc()); + baseOp.getLoc()); mlir::omp::MapInfoOp mapOp = createMapInfoOp( - firOpBuilder, location, symAddr, + firOpBuilder, location, baseOp, /*varPtrPtr=*/mlir::Value{}, asFortran.str(), bounds, /*members=*/{}, /*membersIndex=*/mlir::DenseIntElementsAttr{}, static_cast< std::underlying_type_t>( mapTypeBits), - mlir::omp::VariableCaptureKind::ByRef, symAddr.getType()); + mlir::omp::VariableCaptureKind::ByRef, baseOp.getType()); if (object.sym()->owner().IsDerivedType()) { addChildIndexAndMapToParent(object, parentMemberIndices, mapOp, @@ -997,9 +993,9 @@ bool ClauseProcessor::processMap( result.mapVars.push_back(mapOp); ptrMapSyms->push_back(object.sym()); if (mapSymTypes) - mapSymTypes->push_back(symAddr.getType()); + mapSymTypes->push_back(baseOp.getType()); if (mapSymLocs) - mapSymLocs->push_back(symAddr.getLoc()); + mapSymLocs->push_back(baseOp.getLoc()); } } }); @@ -1102,30 +1098,26 @@ bool ClauseProcessor::processUseDeviceAddr( object.ref(), location, asFortran, bounds, treatIndexAsSection); - auto origSymbol = converter.getSymbolAddress(*object.sym()); - mlir::Value symAddr = info.addr; - if (origSymbol && fir::isTypeWithDescriptor(origSymbol.getType())) - symAddr = origSymbol; - // Explicit map captures are captured ByRef by default, // optimisation passes may alter this to ByCopy or other capture // types to optimise + mlir::Value baseOp = info.rawInput; mlir::omp::MapInfoOp mapOp = createMapInfoOp( - firOpBuilder, location, symAddr, + firOpBuilder, location, baseOp, /*varPtrPtr=*/mlir::Value{}, asFortran.str(), bounds, /*members=*/{}, /*membersIndex=*/mlir::DenseIntElementsAttr{}, static_cast< std::underlying_type_t>( mapTypeBits), - mlir::omp::VariableCaptureKind::ByRef, symAddr.getType()); + mlir::omp::VariableCaptureKind::ByRef, baseOp.getType()); if (object.sym()->owner().IsDerivedType()) { addChildIndexAndMapToParent(object, parentMemberIndices, mapOp, semaCtx); } else { useDeviceSyms.push_back(object.sym()); - useDeviceTypes.push_back(symAddr.getType()); - useDeviceLocs.push_back(symAddr.getLoc()); + useDeviceTypes.push_back(baseOp.getType()); + useDeviceLocs.push_back(baseOp.getLoc()); result.useDeviceAddrVars.push_back(mapOp); } } @@ -1167,30 +1159,26 @@ bool ClauseProcessor::processUseDevicePtr( object.ref(), location, asFortran, bounds, treatIndexAsSection); - auto origSymbol = converter.getSymbolAddress(*object.sym()); - mlir::Value symAddr = info.addr; - if (origSymbol && fir::isTypeWithDescriptor(origSymbol.getType())) - symAddr = origSymbol; - // Explicit map captures are captured ByRef by default, // optimisation passes may alter this to ByCopy or other capture // types to optimise + mlir::Value baseOp = info.rawInput; mlir::omp::MapInfoOp mapOp = createMapInfoOp( - firOpBuilder, location, symAddr, + firOpBuilder, location, baseOp, /*varPtrPtr=*/mlir::Value{}, asFortran.str(), bounds, /*members=*/{}, /*membersIndex=*/mlir::DenseIntElementsAttr{}, static_cast< std::underlying_type_t>( mapTypeBits), - mlir::omp::VariableCaptureKind::ByRef, symAddr.getType()); + mlir::omp::VariableCaptureKind::ByRef, baseOp.getType()); if (object.sym()->owner().IsDerivedType()) { addChildIndexAndMapToParent(object, parentMemberIndices, mapOp, semaCtx); } else { useDeviceSyms.push_back(object.sym()); - useDeviceTypes.push_back(symAddr.getType()); - useDeviceLocs.push_back(symAddr.getLoc()); + useDeviceTypes.push_back(baseOp.getType()); + useDeviceLocs.push_back(baseOp.getLoc()); result.useDevicePtrVars.push_back(mapOp); } } diff --git a/flang/lib/Lower/OpenMP/ClauseProcessor.h b/flang/lib/Lower/OpenMP/ClauseProcessor.h index 5bf2ef8c7776ad..f4c0c6d5720dfc 100644 --- a/flang/lib/Lower/OpenMP/ClauseProcessor.h +++ b/flang/lib/Lower/OpenMP/ClauseProcessor.h @@ -215,22 +215,18 @@ bool ClauseProcessor::processMotionClauses(lower::StatementContext &stmtCtx, object.ref(), clauseLocation, asFortran, bounds, treatIndexAsSection); - auto origSymbol = converter.getSymbolAddress(*object.sym()); - mlir::Value symAddr = info.addr; - if (origSymbol && fir::isTypeWithDescriptor(origSymbol.getType())) - symAddr = origSymbol; - // Explicit map captures are captured ByRef by default, // optimisation passes may alter this to ByCopy or other capture // types to optimise + mlir::Value baseOp = info.rawInput; mlir::omp::MapInfoOp mapOp = createMapInfoOp( - firOpBuilder, clauseLocation, symAddr, + firOpBuilder, clauseLocation, baseOp, /*varPtrPtr=*/mlir::Value{}, asFortran.str(), bounds, /*members=*/{}, /*membersIndex=*/mlir::DenseIntElementsAttr{}, static_cast< std::underlying_type_t>( mapTypeBits), - mlir::omp::VariableCaptureKind::ByRef, symAddr.getType()); + mlir::omp::VariableCaptureKind::ByRef, baseOp.getType()); if (object.sym()->owner().IsDerivedType()) { addChildIndexAndMapToParent(object, parentMemberIndices, mapOp, diff --git a/flang/lib/Lower/OpenMP/OpenMP.cpp b/flang/lib/Lower/OpenMP/OpenMP.cpp index ab768edca01623..49841ef6a1b125 100644 --- a/flang/lib/Lower/OpenMP/OpenMP.cpp +++ b/flang/lib/Lower/OpenMP/OpenMP.cpp @@ -2024,90 +2024,88 @@ genTargetOp(lower::AbstractConverter &converter, lower::SymMap &symTable, if (llvm::find(mapSyms, common) != mapSyms.end()) return; - if (llvm::find(mapSyms, &sym) == mapSyms.end()) { - mlir::Value baseOp = converter.getSymbolAddress(sym); - if (!baseOp) - if (const auto *details = - sym.template detailsIf()) { - baseOp = converter.getSymbolAddress(details->symbol()); - converter.copySymbolBinding(details->symbol(), sym); - } + // If we come across a symbol without a symbol address, we return as we + // cannot process it, this is intended as a catch all early exit for + // symbols that do not have a corresponding extended value. Such as + // subroutines, interfaces and named blocks. + if (!converter.getSymbolAddress(sym)) + return; - if (baseOp) { - llvm::SmallVector bounds; - std::stringstream name; - fir::ExtendedValue dataExv = converter.getSymbolExtendedValue(sym); - name << sym.name().ToString(); - - lower::AddrAndBoundsInfo info = getDataOperandBaseAddr( - converter, firOpBuilder, sym, converter.getCurrentLocation()); - if (mlir::isa( - fir::unwrapRefType(info.addr.getType()))) - bounds = lower::genBoundsOpsFromBox( - firOpBuilder, converter.getCurrentLocation(), dataExv, info); - if (mlir::isa( - fir::unwrapRefType(info.addr.getType()))) { - bool dataExvIsAssumedSize = - semantics::IsAssumedSizeArray(sym.GetUltimate()); - bounds = lower::genBaseBoundsOps( - firOpBuilder, converter.getCurrentLocation(), dataExv, - dataExvIsAssumedSize); - } + if (llvm::find(mapSyms, &sym) != mapSyms.end()) + return; - llvm::omp::OpenMPOffloadMappingFlags mapFlag = - llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT; - mlir::omp::VariableCaptureKind captureKind = - mlir::omp::VariableCaptureKind::ByRef; - - mlir::Type eleType = baseOp.getType(); - if (auto refType = mlir::dyn_cast(baseOp.getType())) - eleType = refType.getElementType(); - - // If a variable is specified in declare target link and if device - // type is not specified as `nohost`, it needs to be mapped tofrom - mlir::ModuleOp mod = firOpBuilder.getModule(); - mlir::Operation *op = mod.lookupSymbol(converter.mangleName(sym)); - auto declareTargetOp = - llvm::dyn_cast_if_present(op); - if (declareTargetOp && declareTargetOp.isDeclareTarget()) { - if (declareTargetOp.getDeclareTargetCaptureClause() == - mlir::omp::DeclareTargetCaptureClause::link && - declareTargetOp.getDeclareTargetDeviceType() != - mlir::omp::DeclareTargetDeviceType::nohost) { - mapFlag |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TO; - mapFlag |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_FROM; - } - } else if (fir::isa_trivial(eleType) || fir::isa_char(eleType)) { - captureKind = mlir::omp::VariableCaptureKind::ByCopy; - } else if (!fir::isa_builtin_cptr_type(eleType)) { - mapFlag |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TO; - mapFlag |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_FROM; - } - auto location = - mlir::NameLoc::get(mlir::StringAttr::get(firOpBuilder.getContext(), - sym.name().ToString()), - baseOp.getLoc()); - mlir::Value mapOp = createMapInfoOp( - firOpBuilder, location, baseOp, /*varPtrPtr=*/mlir::Value{}, - name.str(), bounds, /*members=*/{}, - /*membersIndex=*/mlir::DenseIntElementsAttr{}, - static_cast< - std::underlying_type_t>( - mapFlag), - captureKind, baseOp.getType()); + if (const auto *details = + sym.template detailsIf()) + converter.copySymbolBinding(details->symbol(), sym); + llvm::SmallVector bounds; + std::stringstream name; + fir::ExtendedValue dataExv = converter.getSymbolExtendedValue(sym); + name << sym.name().ToString(); + + lower::AddrAndBoundsInfo info = getDataOperandBaseAddr( + converter, firOpBuilder, sym, converter.getCurrentLocation()); + mlir::Value baseOp = info.rawInput; + if (mlir::isa(fir::unwrapRefType(baseOp.getType()))) + bounds = lower::genBoundsOpsFromBox( + firOpBuilder, converter.getCurrentLocation(), dataExv, info); + if (mlir::isa(fir::unwrapRefType(baseOp.getType()))) { + bool dataExvIsAssumedSize = + semantics::IsAssumedSizeArray(sym.GetUltimate()); + bounds = lower::genBaseBoundsOps( + firOpBuilder, converter.getCurrentLocation(), dataExv, + dataExvIsAssumedSize); + } - clauseOps.mapVars.push_back(mapOp); - mapSyms.push_back(&sym); - mapLocs.push_back(baseOp.getLoc()); - mapTypes.push_back(baseOp.getType()); + llvm::omp::OpenMPOffloadMappingFlags mapFlag = + llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT; + mlir::omp::VariableCaptureKind captureKind = + mlir::omp::VariableCaptureKind::ByRef; + + mlir::Type eleType = baseOp.getType(); + if (auto refType = mlir::dyn_cast(baseOp.getType())) + eleType = refType.getElementType(); + + // If a variable is specified in declare target link and if device + // type is not specified as `nohost`, it needs to be mapped tofrom + mlir::ModuleOp mod = firOpBuilder.getModule(); + mlir::Operation *op = mod.lookupSymbol(converter.mangleName(sym)); + auto declareTargetOp = + llvm::dyn_cast_if_present(op); + if (declareTargetOp && declareTargetOp.isDeclareTarget()) { + if (declareTargetOp.getDeclareTargetCaptureClause() == + mlir::omp::DeclareTargetCaptureClause::link && + declareTargetOp.getDeclareTargetDeviceType() != + mlir::omp::DeclareTargetDeviceType::nohost) { + mapFlag |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TO; + mapFlag |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_FROM; } + } else if (fir::isa_trivial(eleType) || fir::isa_char(eleType)) { + captureKind = mlir::omp::VariableCaptureKind::ByCopy; + } else if (!fir::isa_builtin_cptr_type(eleType)) { + mapFlag |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TO; + mapFlag |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_FROM; } + auto location = mlir::NameLoc::get( + mlir::StringAttr::get(firOpBuilder.getContext(), sym.name().ToString()), + baseOp.getLoc()); + mlir::Value mapOp = createMapInfoOp( + firOpBuilder, location, baseOp, /*varPtrPtr=*/mlir::Value{}, name.str(), + bounds, /*members=*/{}, + /*membersIndex=*/mlir::DenseIntElementsAttr{}, + static_cast< + std::underlying_type_t>( + mapFlag), + captureKind, baseOp.getType()); + + clauseOps.mapVars.push_back(mapOp); + mapSyms.push_back(&sym); + mapLocs.push_back(baseOp.getLoc()); + mapTypes.push_back(baseOp.getType()); }; lower::pft::visitAllSymbols(eval, captureImplicitMap); - auto targetOp = firOpBuilder.create(loc, clauseOps); genBodyOfTargetOp(converter, symTable, semaCtx, eval, targetOp, mapSyms, mapLocs, mapTypes, dsp, loc, queue, item); diff --git a/flang/lib/Optimizer/Transforms/OMPMapInfoFinalization.cpp b/flang/lib/Optimizer/Transforms/OMPMapInfoFinalization.cpp index dc37edb2a526f7..23d1106b16425c 100644 --- a/flang/lib/Optimizer/Transforms/OMPMapInfoFinalization.cpp +++ b/flang/lib/Optimizer/Transforms/OMPMapInfoFinalization.cpp @@ -51,6 +51,14 @@ class OMPMapInfoFinalizationPass : public fir::impl::OMPMapInfoFinalizationPassBase< OMPMapInfoFinalizationPass> { + /// Tracks any intermediate function/subroutine local allocations we + /// generate for the descriptors of box type dummy arguments, so that + /// we can retrieve it for subsequent reuses within the functions + /// scope. + std::map + localBoxAllocas; + void genDescriptorMemberMaps(mlir::omp::MapInfoOp op, fir::FirOpBuilder &builder, mlir::Operation *target) { @@ -75,14 +83,26 @@ class OMPMapInfoFinalizationPass // perform an alloca and then store to it and retrieve the data from the new // alloca. if (mlir::isa(descriptor.getType())) { - mlir::OpBuilder::InsertPoint insPt = builder.saveInsertionPoint(); - mlir::Block *allocaBlock = builder.getAllocaBlock(); - assert(allocaBlock && "No alloca block found for this top level op"); - builder.setInsertionPointToStart(allocaBlock); - auto alloca = builder.create(loc, descriptor.getType()); - builder.restoreInsertionPoint(insPt); - builder.create(loc, descriptor, alloca); - descriptor = alloca; + // If we have already created a local allocation for this BoxType, + // we must be sure to re-use it so that we end up with the same + // allocations being utilised for the same descriptor across all map uses, + // this prevents runtime issues such as not appropriately releasing or + // deleting all mapped data. + auto find = localBoxAllocas.find(descriptor.getAsOpaquePointer()); + if (find != localBoxAllocas.end()) { + builder.create(loc, descriptor, find->second); + descriptor = find->second; + } else { + mlir::OpBuilder::InsertPoint insPt = builder.saveInsertionPoint(); + mlir::Block *allocaBlock = builder.getAllocaBlock(); + assert(allocaBlock && "No alloca block found for this top level op"); + builder.setInsertionPointToStart(allocaBlock); + auto alloca = builder.create(loc, descriptor.getType()); + builder.restoreInsertionPoint(insPt); + builder.create(loc, descriptor, alloca); + localBoxAllocas[descriptor.getAsOpaquePointer()] = alloca; + descriptor = alloca; + } } mlir::Value baseAddrAddr = builder.create( @@ -243,14 +263,12 @@ class OMPMapInfoFinalizationPass // operation (usually function) containing the MapInfoOp because this pass // will mutate siblings of MapInfoOp. void runOnOperation() override { - mlir::ModuleOp module = - mlir::dyn_cast_or_null(getOperation()); - if (!module) - module = getOperation()->getParentOfType(); + mlir::func::FuncOp func = getOperation(); + mlir::ModuleOp module = func->getParentOfType(); fir::KindMapping kindMap = fir::getKindMapping(module); fir::FirOpBuilder builder{module, std::move(kindMap)}; - getOperation()->walk([&](mlir::omp::MapInfoOp op) { + func->walk([&](mlir::omp::MapInfoOp op) { // TODO: Currently only supports a single user for the MapInfoOp, this // is fine for the moment as the Fortran Frontend will generate a // new MapInfoOp per Target operation for the moment. However, when/if diff --git a/flang/test/Lower/OpenMP/array-bounds.f90 b/flang/test/Lower/OpenMP/array-bounds.f90 index f235d5041ab26a..1b01ced5c3ff7e 100644 --- a/flang/test/Lower/OpenMP/array-bounds.f90 +++ b/flang/test/Lower/OpenMP/array-bounds.f90 @@ -15,12 +15,12 @@ !HOST: %[[C2:.*]] = arith.constant 1 : index !HOST: %[[C3:.*]] = arith.constant 4 : index !HOST: %[[BOUNDS0:.*]] = omp.map.bounds lower_bound(%[[C2]] : index) upper_bound(%[[C3]] : index) extent(%[[C10]] : index) stride(%[[C1]] : index) start_idx(%[[C1]] : index) -!HOST: %[[MAP0:.*]] = omp.map.info var_ptr(%[[READ_DECL]]#0 : !fir.ref>, !fir.array<10xi32>) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS0]]) -> !fir.ref> {name = "sp_read(2:5)"} +!HOST: %[[MAP0:.*]] = omp.map.info var_ptr(%[[READ_DECL]]#1 : !fir.ref>, !fir.array<10xi32>) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS0]]) -> !fir.ref> {name = "sp_read(2:5)"} !HOST: %[[C4:.*]] = arith.constant 1 : index !HOST: %[[C5:.*]] = arith.constant 1 : index !HOST: %[[C6:.*]] = arith.constant 4 : index !HOST: %[[BOUNDS1:.*]] = omp.map.bounds lower_bound(%[[C5]] : index) upper_bound(%[[C6]] : index) extent(%[[C10_0]] : index) stride(%[[C4]] : index) start_idx(%[[C4]] : index) -!HOST: %[[MAP1:.*]] = omp.map.info var_ptr(%[[WRITE_DECL]]#0 : !fir.ref>, !fir.array<10xi32>) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS1]]) -> !fir.ref> {name = "sp_write(2:5)"} +!HOST: %[[MAP1:.*]] = omp.map.info var_ptr(%[[WRITE_DECL]]#1 : !fir.ref>, !fir.array<10xi32>) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS1]]) -> !fir.ref> {name = "sp_write(2:5)"} !HOST: omp.target map_entries(%[[MAP0]] -> %{{.*}}, %[[MAP1]] -> %{{.*}}, {{.*}} -> {{.*}} : !fir.ref>, !fir.ref>, !fir.ref) { subroutine read_write_section() @@ -65,20 +65,19 @@ subroutine assumed_shape_array(arr_read_write) end subroutine assumed_shape_array + + !HOST-LABEL: func.func @_QMassumed_array_routinesPassumed_size_array( !HOST-SAME: %[[ARG0:.*]]: !fir.ref> {fir.bindc_name = "arr_read_write"}) { -!HOST: %[[INTERMEDIATE_ALLOCA:.*]] = fir.alloca !fir.box> !HOST: %[[ARG0_SHAPE:.*]] = fir.shape %{{.*}} : (index) -> !fir.shape<1> !HOST: %[[ARG0_DECL:.*]]:2 = hlfir.declare %[[ARG0]](%[[ARG0_SHAPE]]) dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs, uniq_name = "_QMassumed_array_routinesFassumed_size_arrayEarr_read_write"} : (!fir.ref>, !fir.shape<1>, !fir.dscope) -> (!fir.box>, !fir.ref>) !HOST: %[[ALLOCA:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QMassumed_array_routinesFassumed_size_arrayEi"} !HOST: %[[DIMS0:.*]]:3 = fir.box_dims %[[ARG0_DECL]]#0, %c0{{.*}} : (!fir.box>, index) -> (index, index, index) -!HOST: %[[C4_1:.*]] = arith.subi %c4, %c1{{.*}} : index +!HOST: %[[C4_1:.*]] = arith.subi %c4{{.*}}, %c1{{.*}} : index !HOST: %[[EXT:.*]] = arith.addi %[[C4_1]], %c1{{.*}} : index !HOST: %[[BOUNDS:.*]] = omp.map.bounds lower_bound(%c1{{.*}} : index) upper_bound(%c4{{.*}} : index) extent(%[[EXT]] : index) stride(%[[DIMS0]]#2 : index) start_idx(%c1{{.*}} : index) {stride_in_bytes = true} -!HOST: %[[VAR_PTR_PTR:.*]] = fir.box_offset %[[INTERMEDIATE_ALLOCA]] base_addr : (!fir.ref>>) -> !fir.llvm_ptr>> -!HOST: %[[MAP_INFO_MEMBER:.*]] = omp.map.info var_ptr(%[[INTERMEDIATE_ALLOCA]] : !fir.ref>>, !fir.array) var_ptr_ptr(%[[VAR_PTR_PTR]] : !fir.llvm_ptr>>) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS]]) -> !fir.llvm_ptr>> {name = ""} -!HOST: %[[MAP:.*]] = omp.map.info var_ptr(%[[INTERMEDIATE_ALLOCA]] : !fir.ref>>, !fir.box>) map_clauses(tofrom) capture(ByRef) members(%[[MAP_INFO_MEMBER]] : [0] : !fir.llvm_ptr>>) -> !fir.ref> {name = "arr_read_write(2:5)"} -!HOST: omp.target map_entries(%[[MAP_INFO_MEMBER]] -> %{{.*}}, %[[MAP]] -> %{{.*}}, {{.*}} -> {{.*}} : !fir.llvm_ptr>>, !fir.ref>, !fir.ref) { +!HOST: %[[MAP:.*]] = omp.map.info var_ptr(%[[ARG0_DECL]]#1 : !fir.ref>, !fir.array) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS]]) -> !fir.ref> {name = "arr_read_write(2:5)"} +!HOST: omp.target map_entries(%[[MAP]] -> %{{.*}}, {{.*}} -> {{.*}} : !fir.ref>, !fir.ref) { subroutine assumed_size_array(arr_read_write) integer, intent(inout) :: arr_read_write(*) diff --git a/flang/test/Lower/OpenMP/common-block-map.f90 b/flang/test/Lower/OpenMP/common-block-map.f90 index 5033129683a8eb..0c423efd5eef49 100644 --- a/flang/test/Lower/OpenMP/common-block-map.f90 +++ b/flang/test/Lower/OpenMP/common-block-map.f90 @@ -40,7 +40,7 @@ subroutine map_full_block !CHECK: %[[COORD:.*]] = fir.coordinate_of %[[CB_CONV]], %[[INDEX]] : (!fir.ref>, index) -> !fir.ref !CHECK: %[[CONV:.*]] = fir.convert %[[COORD]] : (!fir.ref) -> !fir.ref !CHECK: %[[CB_MEMBER_2:.*]]:2 = hlfir.declare %[[CONV]] {uniq_name = "_QFmap_mix_of_membersEvar2"} : (!fir.ref) -> (!fir.ref, !fir.ref) -!CHECK: %[[MAP_EXP:.*]] = omp.map.info var_ptr(%[[CB_MEMBER_2]]#0 : !fir.ref, i32) map_clauses(tofrom) capture(ByRef) -> !fir.ref {name = "var2"} +!CHECK: %[[MAP_EXP:.*]] = omp.map.info var_ptr(%[[CB_MEMBER_2]]#1 : !fir.ref, i32) map_clauses(tofrom) capture(ByRef) -> !fir.ref {name = "var2"} !CHECK: %[[MAP_IMP:.*]] = omp.map.info var_ptr(%[[CB_MEMBER_1]]#1 : !fir.ref, i32) map_clauses(implicit, exit_release_or_enter_alloc) capture(ByCopy) -> !fir.ref {name = "var1"} !CHECK: omp.target map_entries(%[[MAP_EXP]] -> %[[ARG_EXP:.*]], %[[MAP_IMP]] -> %[[ARG_IMP:.*]] : !fir.ref, !fir.ref) { !CHECK: ^bb0(%[[ARG_EXP]]: !fir.ref, %[[ARG_IMP]]: !fir.ref): diff --git a/flang/test/Lower/OpenMP/derived-type-map.f90 b/flang/test/Lower/OpenMP/derived-type-map.f90 index 6121b450f06206..30b89e90470b0a 100644 --- a/flang/test/Lower/OpenMP/derived-type-map.f90 +++ b/flang/test/Lower/OpenMP/derived-type-map.f90 @@ -21,7 +21,7 @@ end subroutine mapType_derived_implicit !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]]#0 : !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"} +!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"} !CHECK: omp.target map_entries(%[[MAP]] -> %[[ARG0:.*]] : !fir.ref,int:i32}>>) { !CHECK: ^bb0(%[[ARG0]]: !fir.ref,int:i32}>>): subroutine mapType_derived_explicit diff --git a/flang/test/Lower/OpenMP/target.f90 b/flang/test/Lower/OpenMP/target.f90 index fe4b5ba2e7fdc8..af8c061a928c5c 100644 --- a/flang/test/Lower/OpenMP/target.f90 +++ b/flang/test/Lower/OpenMP/target.f90 @@ -189,7 +189,7 @@ subroutine omp_target_update_depend !$omp end task !CHECK: %[[BOUNDS:.*]] = omp.map.bounds - !CHECK: %[[MAP:.*]] = omp.map.info var_ptr(%[[A]]#0 : !fir.ref>, !fir.array<1024xi32>) map_clauses(to) capture(ByRef) bounds(%[[BOUNDS]]) -> !fir.ref> {name = "a"} + !CHECK: %[[MAP:.*]] = omp.map.info var_ptr(%[[A]]#1 : !fir.ref>, !fir.array<1024xi32>) map_clauses(to) capture(ByRef) bounds(%[[BOUNDS]]) -> !fir.ref> {name = "a"} !CHECK: omp.target_update depend(taskdependin -> %[[A]]#1 : !fir.ref>) map_entries(%[[MAP]] : !fir.ref>) !$omp target update to(a) depend(in:a) end subroutine omp_target_update_depend @@ -205,7 +205,7 @@ subroutine omp_target_update_to !CHECK-DAG: %[[A_DECL:.*]]:2 = hlfir.declare %{{.*}}(%{{.*}}) !CHECK-DAG: %[[BOUNDS:.*]] = omp.map.bounds - !CHECK: %[[TO_MAP:.*]] = omp.map.info var_ptr(%[[A_DECL]]#0 : !fir.ref>, !fir.array<1024xi32>) + !CHECK: %[[TO_MAP:.*]] = omp.map.info var_ptr(%[[A_DECL]]#1 : !fir.ref>, !fir.array<1024xi32>) !CHECK-SAME: map_clauses(to) capture(ByRef) !CHECK-SAME: bounds(%[[BOUNDS]]) -> !fir.ref> {name = "a"} @@ -224,7 +224,7 @@ subroutine omp_target_update_from !CHECK-DAG: %[[A_DECL:.*]]:2 = hlfir.declare %{{.*}}(%{{.*}}) !CHECK-DAG: %[[BOUNDS:.*]] = omp.map.bounds - !CHECK: %[[FROM_MAP:.*]] = omp.map.info var_ptr(%[[A_DECL]]#0 : !fir.ref>, !fir.array<1024xi32>) + !CHECK: %[[FROM_MAP:.*]] = omp.map.info var_ptr(%[[A_DECL]]#1 : !fir.ref>, !fir.array<1024xi32>) !CHECK-SAME: map_clauses(from) capture(ByRef) !CHECK-SAME: bounds(%[[BOUNDS]]) -> !fir.ref> {name = "a"} @@ -292,7 +292,7 @@ subroutine omp_target_data !CHECK: %[[A_DECL:.*]]:2 = hlfir.declare %[[VAL_0]](%{{.*}}) {uniq_name = "_QFomp_target_dataEa"} : (!fir.ref>, !fir.shape<1>) -> (!fir.ref>, !fir.ref>) integer :: a(1024) !CHECK: %[[BOUNDS:.*]] = omp.map.bounds lower_bound({{.*}}) upper_bound({{.*}}) extent({{.*}}) stride({{.*}}) start_idx({{.*}}) - !CHECK: %[[MAP:.*]] = omp.map.info var_ptr(%[[A_DECL]]#0 : !fir.ref>, !fir.array<1024xi32>) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS]]) -> !fir.ref> {name = "a"} + !CHECK: %[[MAP:.*]] = omp.map.info var_ptr(%[[A_DECL]]#1 : !fir.ref>, !fir.array<1024xi32>) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS]]) -> !fir.ref> {name = "a"} !CHECK: omp.target_data map_entries(%[[MAP]] : !fir.ref>) { !$omp target data map(tofrom: a) !CHECK: %[[C10:.*]] = arith.constant 10 : i32 @@ -314,14 +314,14 @@ subroutine omp_target_data_mt !CHECK: %[[VAR_B:.*]] = fir.alloca !fir.array<1024xi32> {bindc_name = "b", uniq_name = "_QFomp_target_data_mtEb"} !CHECK: %[[VAR_B_DECL:.*]]:2 = hlfir.declare %[[VAR_B]](%{{.*}}) {uniq_name = "_QFomp_target_data_mtEb"} : (!fir.ref>, !fir.shape<1>) -> (!fir.ref>, !fir.ref>) !CHECK: %[[BOUNDS_A:.*]] = omp.map.bounds lower_bound({{.*}}) upper_bound({{.*}}) extent({{.*}}) stride({{.*}}) start_idx({{.*}}) - !CHECK: %[[MAP_A:.*]] = omp.map.info var_ptr(%[[VAR_A_DECL]]#0 : !fir.ref>, !fir.array<1024xi32>) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS_A]]) -> !fir.ref> {name = "a"} + !CHECK: %[[MAP_A:.*]] = omp.map.info var_ptr(%[[VAR_A_DECL]]#1 : !fir.ref>, !fir.array<1024xi32>) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS_A]]) -> !fir.ref> {name = "a"} !CHECK: omp.target_data map_entries(%[[MAP_A]] : !fir.ref>) { !$omp target data map(a) !CHECK: omp.terminator !$omp end target data !CHECK: } !CHECK %[[BOUNDS_B:.*]] = omp.map.bounds lower_bound({{.*}}) upper_bound({{.*}}) extent({{.*}}) stride({{.*}}) start_idx({{.*}}) - !CHECK %[[MAP_B:.*]] = omp.map.info var_ptr(%[[VAR_B_DECL]]#0 : !fir.ref>, !fir.array<1024xi32>) map_clauses(always, from) capture(ByRef) bounds(%[[BOUNDS_B]]) -> !fir.ref> {name = "b"} + !CHECK %[[MAP_B:.*]] = omp.map.info var_ptr(%[[VAR_B_DECL]]#1 : !fir.ref>, !fir.array<1024xi32>) map_clauses(always, from) capture(ByRef) bounds(%[[BOUNDS_B]]) -> !fir.ref> {name = "b"} !CHECK omp.target_data map_entries(%[[MAP_B]] : !fir.ref>) { !!$omp target data map(always, from : b) !CHECK omp.terminator @@ -338,7 +338,7 @@ subroutine omp_target !CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %{{.*}}(%{{.*}}) {uniq_name = "_QFomp_targetEa"} : (!fir.ref>, !fir.shape<1>) -> (!fir.ref>, !fir.ref>) integer :: a(1024) !CHECK: %[[BOUNDS:.*]] = omp.map.bounds lower_bound({{.*}}) upper_bound({{.*}}) extent({{.*}}) stride({{.*}}) start_idx({{.*}}) - !CHECK: %[[MAP:.*]] = omp.map.info var_ptr(%[[VAL_1]]#0 : !fir.ref>, !fir.array<1024xi32>) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS]]) -> !fir.ref> {name = "a"} + !CHECK: %[[MAP:.*]] = omp.map.info var_ptr(%[[VAL_1]]#1 : !fir.ref>, !fir.array<1024xi32>) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS]]) -> !fir.ref> {name = "a"} !CHECK: omp.target map_entries(%[[MAP]] -> %[[ARG_0:.*]] : !fir.ref>) { !CHECK: ^bb0(%[[ARG_0]]: !fir.ref>): !$omp target map(tofrom: a) @@ -372,7 +372,7 @@ subroutine omp_target_depend !CHECK: %[[LBOUND_A:.*]] = arith.constant 0 : index !CHECK: %[[UBOUND_A:.*]] = arith.subi %c1024, %c1 : index !CHECK: %[[BOUNDS_A:.*]] = omp.map.bounds lower_bound(%[[LBOUND_A]] : index) upper_bound(%[[UBOUND_A]] : index) extent(%[[EXTENT_A]] : index) stride(%[[STRIDE_A]] : index) start_idx(%[[STRIDE_A]] : index) - !CHECK: %[[MAP_A:.*]] = omp.map.info var_ptr(%[[A]]#0 : !fir.ref>, !fir.array<1024xi32>) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS_A]]) -> !fir.ref> {name = "a"} + !CHECK: %[[MAP_A:.*]] = omp.map.info var_ptr(%[[A]]#1 : !fir.ref>, !fir.array<1024xi32>) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS_A]]) -> !fir.ref> {name = "a"} !CHECK: omp.target map_entries(%[[MAP_A]] -> %[[BB0_ARG:.*]] : !fir.ref>) depend(taskdependin -> %[[A]]#1 : !fir.ref>) { !$omp target map(tofrom: a) depend(in: a) a(1) = 10 @@ -455,12 +455,11 @@ subroutine omp_target_implicit_bounds(n) !CHECK: %[[VAL_8:.*]] = fir.alloca !fir.array, %[[VAL_7]] {bindc_name = "a", uniq_name = "_QFomp_target_implicit_boundsEa"} !CHECK: %[[VAL_9:.*]] = fir.shape %[[VAL_7]] : (index) -> !fir.shape<1> !CHECK: %[[VAL_10:.*]]:2 = hlfir.declare %[[VAL_8]](%[[VAL_9]]) {uniq_name = "_QFomp_target_implicit_boundsEa"} : (!fir.ref>, !fir.shape<1>) -> (!fir.box>, !fir.ref>) - !CHECK: %[[DIMS0:.*]]:3 = fir.box_dims %{{[0-9]+}}#0, %c0{{.*}} : (!fir.box>, index) -> (index, index, index) - !CHECK: %[[UB:.*]] = arith.subi %[[DIMS0]]#1, %c1{{.*}} : index + !CHECK: %[[UB:.*]] = arith.subi %[[VAL_7]], %c1{{.*}} : index integer :: n integer :: a(n) - !CHECK: %[[VAL_14:.*]] = omp.map.bounds lower_bound(%c0{{.*}} : index) upper_bound(%[[UB]] : index) extent(%[[DIMS0]]#1 : index) stride(%[[DIMS0]]#2 : index) start_idx(%c1{{.*}} : index) {stride_in_bytes = true} + !CHECK: %[[VAL_14:.*]] = omp.map.bounds lower_bound(%c0{{.*}} : index) upper_bound(%[[UB]] : index) extent(%[[VAL_7]] : index) stride(%c1{{.*}} : index) start_idx(%c1{{.*}} : index) !CHECK: %[[VAL_15:.*]] = omp.map.info var_ptr(%[[VAL_10]]#1 : !fir.ref>, !fir.array) map_clauses(implicit, tofrom) capture(ByRef) bounds(%[[VAL_14]]) -> !fir.ref> {name = "a"} !CHECK: %[[VAL_16:.*]] = omp.map.info var_ptr(%[[VAL_COPY]] : !fir.ref, i32) map_clauses(implicit, exit_release_or_enter_alloc) capture(ByCopy) -> !fir.ref {name = ""} !CHECK: omp.target map_entries(%[[VAL_15]] -> %[[VAL_17:.*]], %[[VAL_16]] -> %[[VAL_18:.*]] : !fir.ref>, !fir.ref) { @@ -589,7 +588,7 @@ subroutine omp_target_parallel_do !CHECK: %[[C0:.*]] = arith.constant 0 : index !CHECK: %[[SUB:.*]] = arith.subi %[[C1024]], %[[C1]] : index !CHECK: %[[BOUNDS:.*]] = omp.map.bounds lower_bound(%[[C0]] : index) upper_bound(%[[SUB]] : index) extent(%[[C1024]] : index) stride(%[[C1]] : index) start_idx(%[[C1]] : index) - !CHECK: %[[MAP:.*]] = omp.map.info var_ptr(%[[VAL_0_DECL]]#0 : !fir.ref>, !fir.array<1024xi32>) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS]]) -> !fir.ref> {name = "a"} + !CHECK: %[[MAP:.*]] = omp.map.info var_ptr(%[[VAL_0_DECL]]#1 : !fir.ref>, !fir.array<1024xi32>) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS]]) -> !fir.ref> {name = "a"} !CHECK: omp.target map_entries(%[[MAP]] -> %[[ARG_0:.*]], %{{.*}} -> %{{.*}} : !fir.ref>, !fir.ref) { !CHECK: ^bb0(%[[ARG_0]]: !fir.ref>, %{{.*}}: !fir.ref): !CHECK: %[[VAL_0_DECL:.*]]:2 = hlfir.declare %[[ARG_0]](%{{.*}}) {uniq_name = "_QFomp_target_parallel_doEa"} : (!fir.ref>, !fir.shape<1>) -> (!fir.ref>, !fir.ref>)