diff --git a/flang/lib/Lower/OpenMP/ClauseProcessor.cpp b/flang/lib/Lower/OpenMP/ClauseProcessor.cpp index a41f8312a28c9..cc1bdc60c2faf 100644 --- a/flang/lib/Lower/OpenMP/ClauseProcessor.cpp +++ b/flang/lib/Lower/OpenMP/ClauseProcessor.cpp @@ -919,6 +919,10 @@ bool ClauseProcessor::processMap( for (const Fortran::parser::OmpObject &ompObject : std::get(mapClause->v.t).v) { + llvm::omp::OpenMPOffloadMappingFlags objectsMapTypeBits = + checkAndApplyDeclTargetMapFlags(converter, mapTypeBits, + *getOmpObjectSymbol(ompObject)); + llvm::SmallVector bounds; std::stringstream asFortran; @@ -941,9 +945,7 @@ bool ClauseProcessor::processMap( mlir::Value mapOp = createMapInfoOp( firOpBuilder, clauseLocation, symAddr, mlir::Value{}, asFortran.str(), bounds, {}, - static_cast< - std::underlying_type_t>( - mapTypeBits), + static_cast(objectsMapTypeBits), mlir::omp::VariableCaptureKind::ByRef, symAddr.getType()); mapOperands.push_back(mapOp); diff --git a/flang/lib/Lower/OpenMP/ClauseProcessor.h b/flang/lib/Lower/OpenMP/ClauseProcessor.h index 11aff0be25053..f824401302a6c 100644 --- a/flang/lib/Lower/OpenMP/ClauseProcessor.h +++ b/flang/lib/Lower/OpenMP/ClauseProcessor.h @@ -203,6 +203,10 @@ bool ClauseProcessor::processMotionClauses( : llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_FROM; for (const Fortran::parser::OmpObject &ompObject : motionClause->v.v) { + llvm::omp::OpenMPOffloadMappingFlags objectsMapTypeBits = + checkAndApplyDeclTargetMapFlags(converter, mapTypeBits, + *getOmpObjectSymbol(ompObject)); + llvm::SmallVector bounds; std::stringstream asFortran; Fortran::lower::AddrAndBoundsInfo info = @@ -224,9 +228,7 @@ bool ClauseProcessor::processMotionClauses( mlir::Value mapOp = createMapInfoOp( firOpBuilder, clauseLocation, symAddr, mlir::Value{}, asFortran.str(), bounds, {}, - static_cast< - std::underlying_type_t>( - mapTypeBits), + static_cast(objectsMapTypeBits), mlir::omp::VariableCaptureKind::ByRef, symAddr.getType()); mapOperands.push_back(mapOp); diff --git a/flang/lib/Lower/OpenMP/OpenMP.cpp b/flang/lib/Lower/OpenMP/OpenMP.cpp index 185e0316870e9..123bc03d8c341 100644 --- a/flang/lib/Lower/OpenMP/OpenMP.cpp +++ b/flang/lib/Lower/OpenMP/OpenMP.cpp @@ -993,8 +993,7 @@ static void genBodyOfTargetOp( mlir::Value mapOp = createMapInfoOp( firOpBuilder, copyVal.getLoc(), copyVal, mlir::Value{}, name.str(), bounds, llvm::SmallVector{}, - static_cast< - std::underlying_type_t>( + static_cast( llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT), mlir::omp::VariableCaptureKind::ByCopy, copyVal.getType()); targetOp.getMapOperandsMutable().append(mapOp); @@ -1127,13 +1126,13 @@ genTargetOp(Fortran::lower::AbstractConverter &converter, mapFlag |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_FROM; } - mlir::Value mapOp = createMapInfoOp( - converter.getFirOpBuilder(), baseOp.getLoc(), baseOp, mlir::Value{}, - name.str(), bounds, {}, - static_cast< - std::underlying_type_t>( - mapFlag), - captureKind, baseOp.getType()); + mapFlag = checkAndApplyDeclTargetMapFlags(converter, mapFlag, sym); + + mlir::Value mapOp = + createMapInfoOp(converter.getFirOpBuilder(), baseOp.getLoc(), + baseOp, mlir::Value{}, name.str(), bounds, {}, + static_cast(mapFlag), + captureKind, baseOp.getType()); mapOperands.push_back(mapOp); mapSymTypes.push_back(baseOp.getType()); diff --git a/flang/lib/Lower/OpenMP/Utils.cpp b/flang/lib/Lower/OpenMP/Utils.cpp index 49517f62895df..8d09864b8071f 100644 --- a/flang/lib/Lower/OpenMP/Utils.cpp +++ b/flang/lib/Lower/OpenMP/Utils.cpp @@ -34,6 +34,22 @@ namespace Fortran { namespace lower { namespace omp { +llvm::omp::OpenMPOffloadMappingFlags +checkAndApplyDeclTargetMapFlags(Fortran::lower::AbstractConverter &converter, + llvm::omp::OpenMPOffloadMappingFlags mapFlags, + const Fortran::semantics::Symbol &symbol) { + std::string symMangle = converter.mangleName(symbol); + mlir::Operation *symOp = converter.getModuleOp().lookupSymbol(symMangle); + auto declTarOp = + llvm::dyn_cast_if_present(symOp); + // Only Link clauses have OMP_MAP_PTR_AND_OBJ applied, To clause + // seems to function differently. + if (declTarOp && declTarOp.getDeclareTargetCaptureClause() == + mlir::omp::DeclareTargetCaptureClause::link) + mapFlags |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ; + return mapFlags; +} + void genObjectList(const Fortran::parser::OmpObjectList &objectList, Fortran::lower::AbstractConverter &converter, llvm::SmallVectorImpl &operands) { diff --git a/flang/lib/Lower/OpenMP/Utils.h b/flang/lib/Lower/OpenMP/Utils.h index 76a15e8bcaab9..56a8ef2c54380 100644 --- a/flang/lib/Lower/OpenMP/Utils.h +++ b/flang/lib/Lower/OpenMP/Utils.h @@ -21,6 +21,10 @@ namespace fir { class FirOpBuilder; } // namespace fir +namespace llvm::omp { +enum class OpenMPOffloadMappingFlags : uint64_t; +} // namespace llvm::omp + namespace Fortran { namespace semantics { @@ -50,6 +54,11 @@ createMapInfoOp(fir::FirOpBuilder &builder, mlir::Location loc, mlir::omp::VariableCaptureKind mapCaptureType, mlir::Type retTy, bool isVal = false); +llvm::omp::OpenMPOffloadMappingFlags +checkAndApplyDeclTargetMapFlags(Fortran::lower::AbstractConverter &converter, + llvm::omp::OpenMPOffloadMappingFlags mapFlags, + const Fortran::semantics::Symbol &symbol); + void gatherFuncAndVarSyms( const Fortran::parser::OmpObjectList &objList, mlir::omp::DeclareTargetCaptureClause clause, diff --git a/flang/lib/Optimizer/Transforms/OMPDescriptorMapInfoGen.cpp b/flang/lib/Optimizer/Transforms/OMPDescriptorMapInfoGen.cpp index 6ffcf0746c76f..282a507147b02 100644 --- a/flang/lib/Optimizer/Transforms/OMPDescriptorMapInfoGen.cpp +++ b/flang/lib/Optimizer/Transforms/OMPDescriptorMapInfoGen.cpp @@ -29,6 +29,7 @@ #include "mlir/Pass/Pass.h" #include "mlir/Support/LLVM.h" #include "llvm/ADT/SmallPtrSet.h" +#include "llvm/Frontend/OpenMP/OMPConstants.h" #include namespace fir { @@ -76,6 +77,11 @@ class OMPDescriptorMapInfoGenPass mlir::Value baseAddrAddr = builder.create( loc, descriptor, fir::BoxFieldAttr::base_addr); + llvm::omp::OpenMPOffloadMappingFlags baseAddrMapFlag = + llvm::omp::OpenMPOffloadMappingFlags(op.getMapType().value()); + baseAddrMapFlag |= + llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ; + // Member of the descriptor pointing at the allocated data mlir::Value baseAddr = builder.create( loc, baseAddrAddr.getType(), descriptor, @@ -83,8 +89,9 @@ class OMPDescriptorMapInfoGenPass fir::unwrapRefType(baseAddrAddr.getType())) .getElementType(), baseAddrAddr, mlir::SmallVector{}, op.getBounds(), - builder.getIntegerAttr(builder.getIntegerType(64, false), - op.getMapType().value()), + builder.getIntegerAttr( + builder.getIntegerType(64, false), + static_cast(baseAddrMapFlag)), builder.getAttr( mlir::omp::VariableCaptureKind::ByRef), builder.getStringAttr("") /*name*/); diff --git a/flang/test/Fir/convert-to-llvm-openmp-and-fir.fir b/flang/test/Fir/convert-to-llvm-openmp-and-fir.fir index a1fc614334dbc..997eb161b639c 100644 --- a/flang/test/Fir/convert-to-llvm-openmp-and-fir.fir +++ b/flang/test/Fir/convert-to-llvm-openmp-and-fir.fir @@ -914,8 +914,8 @@ func.func @omp_critical_() { func.func @omp_map_info_descriptor_type_conversion(%arg0 : !fir.ref>>) { // CHECK: %[[GEP:.*]] = llvm.getelementptr %[[ARG_0]][0, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8)> %0 = fir.box_offset %arg0 base_addr : (!fir.ref>>) -> !fir.llvm_ptr> - // CHECK: %[[MEMBER_MAP:.*]] = omp.map_info var_ptr(%[[GEP]] : !llvm.ptr, i32) map_clauses(tofrom) capture(ByRef) -> !llvm.ptr {name = ""} - %1 = omp.map_info var_ptr(%0 : !fir.llvm_ptr>, i32) map_clauses(tofrom) capture(ByRef) -> !fir.llvm_ptr> {name = ""} + // CHECK: %[[MEMBER_MAP:.*]] = omp.map_info var_ptr(%[[GEP]] : !llvm.ptr, i32) map_clauses(ptr_and_obj, tofrom) capture(ByRef) -> !llvm.ptr {name = ""} + %1 = omp.map_info var_ptr(%0 : !fir.llvm_ptr>, i32) map_clauses(ptr_and_obj, tofrom) capture(ByRef) -> !fir.llvm_ptr> {name = ""} // CHECK: %[[DESC_MAP:.*]] = omp.map_info var_ptr(%[[ARG_0]] : !llvm.ptr, !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8)>) map_clauses(always, delete) capture(ByRef) members(%[[MEMBER_MAP]] : !llvm.ptr) -> !llvm.ptr {name = ""} %2 = omp.map_info var_ptr(%arg0 : !fir.ref>>, !fir.box>) map_clauses(always, delete) capture(ByRef) members(%1 : !fir.llvm_ptr>) -> !fir.ref>> {name = ""} // CHECK: omp.target_exit_data map_entries(%[[DESC_MAP]] : !llvm.ptr) diff --git a/flang/test/Lower/OpenMP/FIR/array-bounds.f90 b/flang/test/Lower/OpenMP/FIR/array-bounds.f90 index 3cd284c46e727..1e7ad6dc8ea0b 100644 --- a/flang/test/Lower/OpenMP/FIR/array-bounds.f90 +++ b/flang/test/Lower/OpenMP/FIR/array-bounds.f90 @@ -46,7 +46,7 @@ module assumed_array_routines !ALL: %[[DIMS1:.*]]:3 = fir.box_dims %arg0, %[[C0_1]] : (!fir.box>, index) -> (index, index, index) !ALL: %[[BOUNDS:.*]] = omp.bounds lower_bound(%[[C3]] : index) upper_bound(%[[C4]] : index) extent(%[[DIMS1]]#1 : index) stride(%[[DIMS0]]#2 : index) start_idx(%[[C0]] : index) {stride_in_bytes = true} !ALL: %[[BOXADDRADDR:.*]] = fir.box_offset %0 base_addr : (!fir.ref>>) -> !fir.llvm_ptr>> -!ALL: %[[MAP_MEMBER:.*]] = omp.map_info var_ptr(%0 : !fir.ref>>, !fir.array) var_ptr_ptr(%[[BOXADDRADDR]] : !fir.llvm_ptr>>) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS]]) -> !fir.llvm_ptr>> {name = ""} +!ALL: %[[MAP_MEMBER:.*]] = omp.map_info var_ptr(%0 : !fir.ref>>, !fir.array) var_ptr_ptr(%[[BOXADDRADDR]] : !fir.llvm_ptr>>) map_clauses(ptr_and_obj, tofrom) capture(ByRef) bounds(%[[BOUNDS]]) -> !fir.llvm_ptr>> {name = ""} !ALL: %[[MAP:.*]] = omp.map_info var_ptr(%0 : !fir.ref>>, !fir.box>) map_clauses(tofrom) capture(ByRef) members(%[[MAP_MEMBER]] : !fir.llvm_ptr>>) -> !fir.ref> {name = "arr_read_write(2:5)"} !ALL: %[[MAP2:.*]] = omp.map_info var_ptr(%[[ALLOCA]] : !fir.ref, i32) map_clauses(implicit, exit_release_or_enter_alloc) capture(ByCopy) -> !fir.ref {name = "i"} !ALL: omp.target map_entries(%[[MAP_MEMBER]] -> %{{.*}}, %[[MAP]] -> %{{.*}}, %[[MAP2]] -> %{{.*}} : !fir.llvm_ptr>>, !fir.ref>, !fir.ref) { diff --git a/flang/test/Lower/OpenMP/FIR/target.f90 b/flang/test/Lower/OpenMP/FIR/target.f90 index 06772771647de..cb4bfa06e618a 100644 --- a/flang/test/Lower/OpenMP/FIR/target.f90 +++ b/flang/test/Lower/OpenMP/FIR/target.f90 @@ -450,7 +450,7 @@ end subroutine omp_target_device_ptr subroutine omp_target_device_addr integer, pointer :: a !CHECK: %[[VAL_0:.*]] = fir.alloca !fir.box> {bindc_name = "a", uniq_name = "_QFomp_target_device_addrEa"} - !CHECK: %[[MAP_MEMBERS:.*]] = omp.map_info var_ptr({{.*}} : !fir.ref>>, i32) var_ptr_ptr({{.*}} : !fir.llvm_ptr>) map_clauses(tofrom) capture(ByRef) -> !fir.llvm_ptr> {name = ""} + !CHECK: %[[MAP_MEMBERS:.*]] = omp.map_info var_ptr({{.*}} : !fir.ref>>, i32) var_ptr_ptr({{.*}} : !fir.llvm_ptr>) map_clauses(ptr_and_obj, tofrom) capture(ByRef) -> !fir.llvm_ptr> {name = ""} !CHECK: %[[MAP:.*]] = omp.map_info var_ptr({{.*}} : !fir.ref>>, !fir.box>) map_clauses(tofrom) capture(ByRef) members(%[[MAP_MEMBERS]] : !fir.llvm_ptr>) -> !fir.ref>> {name = "a"} !CHECK: omp.target_data map_entries(%[[MAP_MEMBERS]], %[[MAP]] : {{.*}}) use_device_addr(%[[VAL_0]] : !fir.ref>>) { !$omp target data map(tofrom: a) use_device_addr(a) diff --git a/flang/test/Lower/OpenMP/allocatable-array-bounds.f90 b/flang/test/Lower/OpenMP/allocatable-array-bounds.f90 index adf74efa9b596..42cb7cffe6494 100644 --- a/flang/test/Lower/OpenMP/allocatable-array-bounds.f90 +++ b/flang/test/Lower/OpenMP/allocatable-array-bounds.f90 @@ -23,7 +23,7 @@ !HOST: %[[BOX_3:.*]]:3 = fir.box_dims %[[LOAD_3]], %[[CONSTANT_3]] : (!fir.box>>, index) -> (index, index, index) !HOST: %[[BOUNDS_1:.*]] = omp.bounds lower_bound(%[[LB_1]] : index) upper_bound(%[[UB_1]] : index) extent(%[[BOX_3]]#1 : index) stride(%[[BOX_2]]#2 : index) start_idx(%[[BOX_1]]#0 : index) {stride_in_bytes = true} !HOST: %[[VAR_PTR_PTR:.*]] = fir.box_offset %[[DECLARE_1]]#1 base_addr : (!fir.ref>>>) -> !fir.llvm_ptr>> -!HOST: %[[MAP_INFO_MEMBER:.*]] = omp.map_info var_ptr(%[[DECLARE_1]]#1 : !fir.ref>>>, !fir.array) var_ptr_ptr(%[[VAR_PTR_PTR]] : !fir.llvm_ptr>>) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS_1]]) -> !fir.llvm_ptr>> {name = ""} +!HOST: %[[MAP_INFO_MEMBER:.*]] = omp.map_info var_ptr(%[[DECLARE_1]]#1 : !fir.ref>>>, !fir.array) var_ptr_ptr(%[[VAR_PTR_PTR]] : !fir.llvm_ptr>>) map_clauses(ptr_and_obj, tofrom) capture(ByRef) bounds(%[[BOUNDS_1]]) -> !fir.llvm_ptr>> {name = ""} !HOST: %[[MAP_INFO_1:.*]] = omp.map_info var_ptr(%[[DECLARE_1]]#1 : !fir.ref>>>, !fir.box>>) map_clauses(tofrom) capture(ByRef) members(%[[MAP_INFO_MEMBER]] : !fir.llvm_ptr>>) -> !fir.ref>>> {name = "sp_read(2:5)"} !HOST: %[[LOAD_3:.*]] = fir.load %[[DECLARE_2]]#0 : !fir.ref>>> @@ -41,7 +41,7 @@ !HOST: %[[BOX_5:.*]]:3 = fir.box_dims %[[LOAD_5]], %[[CONSTANT_5]] : (!fir.box>>, index) -> (index, index, index) !HOST: %[[BOUNDS_2:.*]] = omp.bounds lower_bound(%[[LB_2]] : index) upper_bound(%[[UB_2]] : index) extent(%[[BOX_5]]#1 : index) stride(%[[BOX_4]]#2 : index) start_idx(%[[BOX_3]]#0 : index) {stride_in_bytes = true} !HOST: %[[VAR_PTR_PTR:.*]] = fir.box_offset %[[DECLARE_2]]#1 base_addr : (!fir.ref>>>) -> !fir.llvm_ptr>> -!HOST: %[[MAP_INFO_MEMBER:.*]] = omp.map_info var_ptr(%[[DECLARE_2]]#1 : !fir.ref>>>, !fir.array) var_ptr_ptr(%[[VAR_PTR_PTR]] : !fir.llvm_ptr>>) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS_2]]) -> !fir.llvm_ptr>> {name = ""} +!HOST: %[[MAP_INFO_MEMBER:.*]] = omp.map_info var_ptr(%[[DECLARE_2]]#1 : !fir.ref>>>, !fir.array) var_ptr_ptr(%[[VAR_PTR_PTR]] : !fir.llvm_ptr>>) map_clauses(ptr_and_obj, tofrom) capture(ByRef) bounds(%[[BOUNDS_2]]) -> !fir.llvm_ptr>> {name = ""} !HOST: %[[MAP_INFO_2:.*]] = omp.map_info var_ptr(%[[DECLARE_2]]#1 : !fir.ref>>>, !fir.box>>) map_clauses(tofrom) capture(ByRef) members(%[[MAP_INFO_MEMBER]] : !fir.llvm_ptr>>) -> !fir.ref>>> {name = "sp_write(2:5)"} subroutine read_write_section() @@ -80,7 +80,7 @@ module assumed_allocatable_array_routines !HOST: %[[BOX_3:.*]]:3 = fir.box_dims %[[LOAD_3]], %[[CONSTANT_3]] : (!fir.box>>, index) -> (index, index, index) !HOST: %[[BOUNDS:.*]] = omp.bounds lower_bound(%[[LB]] : index) upper_bound(%[[UB]] : index) extent(%[[BOX_3]]#1 : index) stride(%[[BOX_2]]#2 : index) start_idx(%[[BOX_1]]#0 : index) {stride_in_bytes = true} !HOST: %[[VAR_PTR_PTR:.*]] = fir.box_offset %[[DECLARE]]#1 base_addr : (!fir.ref>>>) -> !fir.llvm_ptr>> -!HOST: %[[MAP_INFO_MEMBER:.*]] = omp.map_info var_ptr(%[[DECLARE]]#1 : !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_INFO_MEMBER:.*]] = omp.map_info var_ptr(%[[DECLARE]]#1 : !fir.ref>>>, !fir.array) var_ptr_ptr(%[[VAR_PTR_PTR]] : !fir.llvm_ptr>>) map_clauses(ptr_and_obj, tofrom) capture(ByRef) bounds(%[[BOUNDS]]) -> !fir.llvm_ptr>> {name = ""} !HOST: %[[MAP_INFO:.*]] = omp.map_info var_ptr(%[[DECLARE]]#1 : !fir.ref>>>, !fir.box>>) map_clauses(tofrom) capture(ByRef) members(%[[MAP_INFO_MEMBER]] : !fir.llvm_ptr>>) -> !fir.ref>>> {name = "arr_read_write(2:5)"} subroutine assumed_shape_array(arr_read_write) integer, allocatable, intent(inout) :: arr_read_write(:) diff --git a/flang/test/Lower/OpenMP/allocatable-map.f90 b/flang/test/Lower/OpenMP/allocatable-map.f90 index ddc20b582b26e..4854a0cc82b72 100644 --- a/flang/test/Lower/OpenMP/allocatable-map.f90 +++ b/flang/test/Lower/OpenMP/allocatable-map.f90 @@ -2,12 +2,12 @@ !HLFIRDIALECT: %[[POINTER:.*]]:2 = hlfir.declare %0 {fortran_attrs = #fir.var_attrs, uniq_name = "_QFpointer_routineEpoint"} : (!fir.ref>>) -> (!fir.ref>>, !fir.ref>>) !HLFIRDIALECT: %[[BOX_OFF:.*]] = fir.box_offset %[[POINTER]]#1 base_addr : (!fir.ref>>) -> !fir.llvm_ptr> -!HLFIRDIALECT: %[[POINTER_MAP_MEMBER:.*]] = omp.map_info var_ptr(%[[POINTER]]#1 : !fir.ref>>, i32) var_ptr_ptr(%[[BOX_OFF]] : !fir.llvm_ptr>) map_clauses(implicit, tofrom) capture(ByRef) -> !fir.llvm_ptr> {name = ""} -!HLFIRDIALECT: %[[POINTER_MAP:.*]] = omp.map_info var_ptr(%[[POINTER]]#1 : !fir.ref>>, !fir.box>) map_clauses(implicit, tofrom) capture(ByRef) members(%[[POINTER_MAP_MEMBER]] : !fir.llvm_ptr>) -> !fir.ref>> {name = "point"} -!HLFIRDIALECT: omp.target map_entries({{.*}}, %[[POINTER_MAP_MEMBER]] -> {{.*}}, %[[POINTER_MAP]] -> {{.*}} : {{.*}}, !fir.llvm_ptr>, !fir.ref>>) { +!HLFIRDIALECT: %[[POINTER_MAP_MEMBER:.*]] = omp.map_info var_ptr(%[[POINTER]]#1 : !fir.ref>>, i32) var_ptr_ptr(%[[BOX_OFF]] : !fir.llvm_ptr>) map_clauses(ptr_and_obj, tofrom) capture(ByRef) -> !fir.llvm_ptr> {name = ""} +!HLFIRDIALECT: %[[POINTER_MAP:.*]] = omp.map_info var_ptr(%[[POINTER]]#1 : !fir.ref>>, !fir.box>) map_clauses(tofrom) capture(ByRef) members(%[[POINTER_MAP_MEMBER]] : !fir.llvm_ptr>) -> !fir.ref>> {name = "point"} +!HLFIRDIALECT: omp.target map_entries(%[[POINTER_MAP_MEMBER]] -> {{.*}}, %[[POINTER_MAP]] -> {{.*}} : !fir.llvm_ptr>, !fir.ref>>) { subroutine pointer_routine() integer, pointer :: point -!$omp target map(tofrom:pointer) +!$omp target map(tofrom:point) point = 1 !$omp end target end subroutine pointer_routine diff --git a/flang/test/Lower/OpenMP/array-bounds.f90 b/flang/test/Lower/OpenMP/array-bounds.f90 index 7d76ff4b106a0..706428544afb3 100644 --- a/flang/test/Lower/OpenMP/array-bounds.f90 +++ b/flang/test/Lower/OpenMP/array-bounds.f90 @@ -51,7 +51,7 @@ module assumed_array_routines !HOST: %[[DIMS1:.*]]:3 = fir.box_dims %[[ARG0_DECL]]#1, %[[C0_1]] : (!fir.box>, index) -> (index, index, index) !HOST: %[[BOUNDS:.*]] = omp.bounds lower_bound(%[[C3]] : index) upper_bound(%[[C4]] : index) extent(%[[DIMS1]]#1 : index) stride(%[[DIMS0]]#2 : index) start_idx(%[[C0]] : index) {stride_in_bytes = true} !HOST: %[[VAR_PTR_PTR:.*]] = fir.box_offset %0 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_INFO_MEMBER:.*]] = omp.map_info var_ptr(%[[INTERMEDIATE_ALLOCA]] : !fir.ref>>, !fir.array) var_ptr_ptr(%[[VAR_PTR_PTR]] : !fir.llvm_ptr>>) map_clauses(ptr_and_obj, 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]] : !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) { subroutine assumed_shape_array(arr_read_write) @@ -76,7 +76,7 @@ end subroutine assumed_shape_array !HOST: %[[EXT:.*]] = arith.addi %[[C4_1]], %c1{{.*}} : index !HOST: %[[BOUNDS:.*]] = omp.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_INFO_MEMBER:.*]] = omp.map_info var_ptr(%[[INTERMEDIATE_ALLOCA]] : !fir.ref>>, !fir.array) var_ptr_ptr(%[[VAR_PTR_PTR]] : !fir.llvm_ptr>>) map_clauses(ptr_and_obj, 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]] : !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) { subroutine assumed_size_array(arr_read_write) diff --git a/flang/test/Lower/OpenMP/target.f90 b/flang/test/Lower/OpenMP/target.f90 index 030533e1a0455..8e8b3aba82ffb 100644 --- a/flang/test/Lower/OpenMP/target.f90 +++ b/flang/test/Lower/OpenMP/target.f90 @@ -530,7 +530,7 @@ subroutine omp_target_device_addr integer, pointer :: a !CHECK: %[[VAL_0:.*]] = fir.alloca !fir.box> {bindc_name = "a", uniq_name = "_QFomp_target_device_addrEa"} !CHECK: %[[VAL_0_DECL:.*]]:2 = hlfir.declare %0 {fortran_attrs = #fir.var_attrs, uniq_name = "_QFomp_target_device_addrEa"} : (!fir.ref>>) -> (!fir.ref>>, !fir.ref>>) - !CHECK: %[[MAP_MEMBERS:.*]] = omp.map_info var_ptr({{.*}} : !fir.ref>>, i32) var_ptr_ptr({{.*}} : !fir.llvm_ptr>) map_clauses(tofrom) capture(ByRef) -> !fir.llvm_ptr> {name = ""} + !CHECK: %[[MAP_MEMBERS:.*]] = omp.map_info var_ptr({{.*}} : !fir.ref>>, i32) var_ptr_ptr({{.*}} : !fir.llvm_ptr>) map_clauses(ptr_and_obj, tofrom) capture(ByRef) -> !fir.llvm_ptr> {name = ""} !CHECK: %[[MAP:.*]] = omp.map_info var_ptr({{.*}} : !fir.ref>>, !fir.box>) map_clauses(tofrom) capture(ByRef) members(%[[MAP_MEMBERS]] : !fir.llvm_ptr>) -> !fir.ref>> {name = "a"} !CHECK: omp.target_data map_entries(%[[MAP_MEMBERS]], %[[MAP]] : {{.*}}) use_device_addr(%[[VAL_0_DECL]]#1 : !fir.ref>>) { !$omp target data map(tofrom: a) use_device_addr(a) diff --git a/flang/test/Transforms/omp-descriptor-map-info-gen.fir b/flang/test/Transforms/omp-descriptor-map-info-gen.fir index 22594ec88c9cb..a8bf2c2077af8 100644 --- a/flang/test/Transforms/omp-descriptor-map-info-gen.fir +++ b/flang/test/Transforms/omp-descriptor-map-info-gen.fir @@ -34,11 +34,11 @@ module attributes {omp.is_target_device = false} { // CHECK: %[[DECLARE2:.*]]:2 = hlfir.declare %[[ALLOCA2]] {fortran_attrs = #fir.var_attrs, uniq_name = "test2"} : (!fir.ref>>) -> (!fir.ref>>, !fir.ref>>) // CHECK: %[[BOUNDS:.*]] = omp.bounds lower_bound(%{{.*}} : index) upper_bound(%{{.*}} : index) extent(%{{.*}} : index) stride(%{{.*}} : index) start_idx(%{{.*}} : index) {stride_in_bytes = true} // CHECK: %[[BASE_ADDR_OFF:.*]] = fir.box_offset %[[DECLARE2]]#1 base_addr : (!fir.ref>>) -> !fir.llvm_ptr> -// CHECK: %[[DESC_MEMBER_MAP:.*]] = omp.map_info var_ptr(%[[DECLARE2]]#1 : !fir.ref>>, i32) var_ptr_ptr(%[[BASE_ADDR_OFF]] : !fir.llvm_ptr>) map_clauses(tofrom) capture(ByRef) -> !fir.llvm_ptr> {name = ""} +// CHECK: %[[DESC_MEMBER_MAP:.*]] = omp.map_info var_ptr(%[[DECLARE2]]#1 : !fir.ref>>, i32) var_ptr_ptr(%[[BASE_ADDR_OFF]] : !fir.llvm_ptr>) map_clauses(ptr_and_obj, tofrom) capture(ByRef) -> !fir.llvm_ptr> {name = ""} // CHECK: %[[DESC_PARENT_MAP:.*]] = omp.map_info var_ptr(%[[DECLARE2]]#1 : !fir.ref>>, !fir.box>) map_clauses(tofrom) capture(ByRef) members(%[[DESC_MEMBER_MAP]] : !fir.llvm_ptr>) -> !fir.ref>> // CHECK: fir.store %[[DECLARE1]]#1 to %[[ALLOCA]] : !fir.ref>> // CHECK: %[[BASE_ADDR_OFF_2:.*]] = fir.box_offset %[[ALLOCA]] base_addr : (!fir.ref>>) -> !fir.llvm_ptr>> -// CHECK: %[[DESC_MEMBER_MAP_2:.*]] = omp.map_info var_ptr(%[[ALLOCA]] : !fir.ref>>, !fir.array) var_ptr_ptr(%[[BASE_ADDR_OFF_2]] : !fir.llvm_ptr>>) map_clauses(from) capture(ByRef) bounds(%[[BOUNDS]]) -> !fir.llvm_ptr>> {name = ""} +// CHECK: %[[DESC_MEMBER_MAP_2:.*]] = omp.map_info var_ptr(%[[ALLOCA]] : !fir.ref>>, !fir.array) var_ptr_ptr(%[[BASE_ADDR_OFF_2]] : !fir.llvm_ptr>>) map_clauses(ptr_and_obj, from) capture(ByRef) bounds(%[[BOUNDS]]) -> !fir.llvm_ptr>> {name = ""} // CHECK: %[[DESC_PARENT_MAP_2:.*]] = omp.map_info var_ptr(%[[ALLOCA]] : !fir.ref>>, !fir.box>) map_clauses(from) capture(ByRef) members(%15 : !fir.llvm_ptr>>) -> !fir.ref> // CHECK: omp.target map_entries(%[[DESC_MEMBER_MAP]] -> %[[ARG1:.*]], %[[DESC_PARENT_MAP]] -> %[[ARG2:.*]], %[[DESC_MEMBER_MAP_2]] -> %[[ARG3:.*]], %[[DESC_PARENT_MAP_2]] -> %[[ARG4:.*]] : {{.*}}) { // CHECK: ^bb0(%[[ARG1]]: !fir.llvm_ptr>, %[[ARG2]]: !fir.ref>>, %[[ARG3]]: !fir.llvm_ptr>>, %[[ARG4]]: !fir.ref>): diff --git a/llvm/include/llvm/Frontend/OpenMP/OMPConstants.h b/llvm/include/llvm/Frontend/OpenMP/OMPConstants.h index f8812e7955b82..21251e9137a78 100644 --- a/llvm/include/llvm/Frontend/OpenMP/OMPConstants.h +++ b/llvm/include/llvm/Frontend/OpenMP/OMPConstants.h @@ -244,6 +244,11 @@ enum class OpenMPOffloadMappingFlags : uint64_t { LLVM_MARK_AS_BITMASK_ENUM(/* LargestFlag = */ OMP_MAP_MEMBER_OF) }; +/// Type alias for accessing the underlying type of the +/// OpenMPOffloadMappingFlags enum, simplifies casting back and forth from the +/// enum. +using OMPMapFlagType = std::underlying_type_t; + enum OpenMPOffloadingReservedDeviceIDs { /// Device ID if the device was not defined, runtime should get it /// from environment variables in the spec. diff --git a/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp b/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp index 8a6980e2c6a2d..80c0002c57ff3 100644 --- a/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp +++ b/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp @@ -915,6 +915,9 @@ static ParseResult parseMapClause(OpAsmParser &parser, IntegerAttr &mapType) { if (mapTypeMod == "delete") mapTypeBits |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_DELETE; + if (mapTypeMod == "ptr_and_obj") + mapTypeBits |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ; + return success(); }; @@ -951,6 +954,10 @@ static void printMapClause(OpAsmPrinter &p, Operation *op, if (mapTypeToBitFlag(mapTypeBits, llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_PRESENT)) mapTypeStrs.push_back("present"); + if (mapTypeToBitFlag( + mapTypeBits, + llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ)) + mapTypeStrs.push_back("ptr_and_obj"); // special handling of to/from/tofrom/delete and release/alloc, release + // alloc are the abscense of one of the other flags, whereas tofrom requires diff --git a/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp b/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp index bef227f2c583e..30efb4f56a562 100644 --- a/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp +++ b/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp @@ -1820,6 +1820,17 @@ uint64_t getArrayElementSizeInBits(LLVM::LLVMArrayType arrTy, DataLayout &dl) { return dl.getTypeSizeInBits(arrTy.getElementType()); } +// This may be a bit of a naive check, the intent is to verify if the +// mapped data being passed is a pointer -> pointee that requires special +// handling in certain cases. There may be a better way to verify this, but +// unfortunately with opaque pointers we lose the ability to easily check if +// something is a pointer whilst maintaining access to the underlying type. +static bool checkIfPointerMap(llvm::omp::OpenMPOffloadMappingFlags mapFlag) { + mapFlag = mapFlag & llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ; + int hasPtrAndObj = static_cast(mapFlag); + return hasPtrAndObj != 0; +} + // This function calculates the size to be offloaded for a specified type, given // its associated map clause (which can contain bounds information which affects // the total size), this size is calculated based on the underlying element type @@ -2034,12 +2045,12 @@ static void processMapMembersWithParent( assert(memberDataIdx >= 0 && "could not find mapped member of structure"); // Same MemberOfFlag to indicate its link with parent and other members - // of, and we flag that it's part of a pointer and object coupling. auto mapFlag = llvm::omp::OpenMPOffloadMappingFlags(memberClause.getMapType().value()); mapFlag &= ~llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM; + mapFlag |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF; ompBuilder.setCorrectMemberOfFlag(mapFlag, memberOfFlag); - mapFlag |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ; + combinedInfo.Types.emplace_back(mapFlag); combinedInfo.DevicePointers.emplace_back( llvm::OpenMPIRBuilder::DeviceInfoTy::None); @@ -2159,15 +2170,13 @@ static void genMapInfos(llvm::IRBuilderBase &builder, // OMP_MAP_TARGET_PARAM as they are not passed as parameters, they're // marked with OMP_MAP_PTR_AND_OBJ instead. auto mapFlag = mapData.Types[i]; - if (mapData.IsDeclareTarget[i]) - mapFlag |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ; - else if (isTargetParams) + if (isTargetParams && !mapData.IsDeclareTarget[i]) mapFlag |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM; if (auto mapInfoOp = dyn_cast(mapData.MapClause[i])) if (mapInfoOp.getMapCaptureType().value() == mlir::omp::VariableCaptureKind::ByCopy && - !mapInfoOp.getVarType().isa()) + !checkIfPointerMap(mapFlag)) mapFlag |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_LITERAL; combinedInfo.BasePointers.emplace_back(mapData.BasePointers[i]); @@ -2630,10 +2639,14 @@ createAlteredByCaptureMap(MapInfoData &mapData, mlir::omp::VariableCaptureKind captureKind = mlir::omp::VariableCaptureKind::ByRef; + bool isPtrTy = false; if (auto mapOp = mlir::dyn_cast_if_present( mapData.MapClause[i])) { captureKind = mapOp.getMapCaptureType().value_or( mlir::omp::VariableCaptureKind::ByRef); + + isPtrTy = checkIfPointerMap( + llvm::omp::OpenMPOffloadMappingFlags(mapOp.getMapType().value())); } switch (captureKind) { @@ -2673,7 +2686,7 @@ createAlteredByCaptureMap(MapInfoData &mapData, else newV = mapData.Pointers[i]; - if (!type->isPointerTy()) { + if (!isPtrTy) { auto curInsert = builder.saveIP(); builder.restoreIP(findAllocaInsertPoint(builder, moduleTranslation)); auto *memTempAlloc = diff --git a/mlir/test/Dialect/OpenMP/ops.mlir b/mlir/test/Dialect/OpenMP/ops.mlir index 211ff0ff9272e..e3f84ea976300 100644 --- a/mlir/test/Dialect/OpenMP/ops.mlir +++ b/mlir/test/Dialect/OpenMP/ops.mlir @@ -2171,8 +2171,8 @@ func.func @omp_target_update_data (%if_cond : i1, %device : si32, %map1: memref< // CHECK-LABEL: omp_targets_is_allocatable // CHECK-SAME: (%[[ARG0:.*]]: !llvm.ptr, %[[ARG1:.*]]: !llvm.ptr) func.func @omp_targets_is_allocatable(%arg0: !llvm.ptr, %arg1: !llvm.ptr) -> () { - // CHECK: %[[MAP0:.*]] = omp.map_info var_ptr(%[[ARG0]] : !llvm.ptr, i32) map_clauses(tofrom) capture(ByRef) -> !llvm.ptr {name = ""} - %mapv1 = omp.map_info var_ptr(%arg0 : !llvm.ptr, i32) map_clauses(tofrom) capture(ByRef) -> !llvm.ptr {name = ""} + // CHECK: %[[MAP0:.*]] = omp.map_info var_ptr(%[[ARG0]] : !llvm.ptr, i32) map_clauses(ptr_and_obj, tofrom) capture(ByRef) -> !llvm.ptr {name = ""} + %mapv1 = omp.map_info var_ptr(%arg0 : !llvm.ptr, i32) map_clauses(ptr_and_obj, tofrom) capture(ByRef) -> !llvm.ptr {name = ""} // CHECK: %[[MAP1:.*]] = omp.map_info var_ptr(%[[ARG1]] : !llvm.ptr, !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8)>) map_clauses(tofrom) capture(ByRef) members(%[[MAP0]] : !llvm.ptr) -> !llvm.ptr {name = ""} %mapv2 = omp.map_info var_ptr(%arg1 : !llvm.ptr, !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8)>) map_clauses(tofrom) capture(ByRef) members(%mapv1 : !llvm.ptr) -> !llvm.ptr {name = ""} // CHECK: omp.target map_entries(%[[MAP0]] -> {{.*}}, %[[MAP1]] -> {{.*}} : !llvm.ptr, !llvm.ptr) diff --git a/mlir/test/Target/LLVMIR/omptarget-fortran-allocatable-types-host.mlir b/mlir/test/Target/LLVMIR/omptarget-fortran-allocatable-types-host.mlir index 831cd05871c4e..0f6dc330395e3 100644 --- a/mlir/test/Target/LLVMIR/omptarget-fortran-allocatable-types-host.mlir +++ b/mlir/test/Target/LLVMIR/omptarget-fortran-allocatable-types-host.mlir @@ -2,10 +2,9 @@ // This test checks the offload sizes, map types and base pointers and pointers // provided to the OpenMP kernel argument structure are correct when lowering -// to LLVM-IR from MLIR when the fortran allocatables flag is switched on and -// a fortran allocatable descriptor type is provided alongside the omp.map_info, -// the test utilises mapping of array sections, full arrays and individual -// allocated scalars. +// to LLVM-IR from MLIR when a fortran allocatable descriptor type is provided +// alongside the omp.map_info, the test utilises mapping of array sections, +// full arrays and individual allocated scalars. module attributes {omp.is_target_device = false} { llvm.func @_QQmain() { @@ -26,7 +25,7 @@ module attributes {omp.is_target_device = false} { %14 = llvm.sub %11, %2 : i64 %15 = omp.bounds lower_bound(%7 : i64) upper_bound(%14 : i64) extent(%11 : i64) stride(%13 : i64) start_idx(%9 : i64) {stride_in_bytes = true} %16 = llvm.getelementptr %3[0, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>)> - %17 = omp.map_info var_ptr(%16 : !llvm.ptr, f32) map_clauses(tofrom) capture(ByRef) bounds(%15) -> !llvm.ptr {name = "full_arr"} + %17 = omp.map_info var_ptr(%16 : !llvm.ptr, f32) map_clauses(ptr_and_obj, tofrom) capture(ByRef) bounds(%15) -> !llvm.ptr {name = "full_arr"} %18 = omp.map_info var_ptr(%3 : !llvm.ptr, !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>)>) map_clauses(tofrom) capture(ByRef) members(%17 : !llvm.ptr) -> !llvm.ptr {name = "full_arr"} %19 = llvm.getelementptr %6[0, 7, %7, 0] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>)> %20 = llvm.load %19 : !llvm.ptr -> i64 @@ -38,10 +37,10 @@ module attributes {omp.is_target_device = false} { %26 = llvm.sub %0, %20 : i64 %27 = omp.bounds lower_bound(%25 : i64) upper_bound(%26 : i64) extent(%22 : i64) stride(%24 : i64) start_idx(%20 : i64) {stride_in_bytes = true} %28 = llvm.getelementptr %6[0, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>)> - %29 = omp.map_info var_ptr(%6 : !llvm.ptr, i32) var_ptr_ptr(%28 : !llvm.ptr) map_clauses(tofrom) capture(ByRef) bounds(%27) -> !llvm.ptr {name = "sect_arr(2:5)"} + %29 = omp.map_info var_ptr(%6 : !llvm.ptr, i32) var_ptr_ptr(%28 : !llvm.ptr) map_clauses(ptr_and_obj, tofrom) capture(ByRef) bounds(%27) -> !llvm.ptr {name = "sect_arr(2:5)"} %30 = omp.map_info var_ptr(%6 : !llvm.ptr, !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>)>) map_clauses(tofrom) capture(ByRef) members(%29 : !llvm.ptr) -> !llvm.ptr {name = "sect_arr(2:5)"} %31 = llvm.getelementptr %5[0, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8)> - %32 = omp.map_info var_ptr(%5 : !llvm.ptr, f32) var_ptr_ptr(%31 : !llvm.ptr) map_clauses(tofrom) capture(ByRef) -> !llvm.ptr {name = "scalar"} + %32 = omp.map_info var_ptr(%5 : !llvm.ptr, f32) var_ptr_ptr(%31 : !llvm.ptr) map_clauses(ptr_and_obj, tofrom) capture(ByRef) -> !llvm.ptr {name = "scalar"} %33 = omp.map_info var_ptr(%5 : !llvm.ptr, !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8)>) map_clauses(tofrom) capture(ByRef) members(%32 : !llvm.ptr) -> !llvm.ptr {name = "scalar"} omp.target map_entries(%17 -> %arg0, %18 -> %arg1, %29 -> %arg2, %30 -> %arg3, %32 -> %arg4, %33 -> %arg5 : !llvm.ptr, !llvm.ptr, !llvm.ptr, !llvm.ptr, !llvm.ptr, !llvm.ptr) { ^bb0(%arg0: !llvm.ptr, %arg1: !llvm.ptr, %arg2: !llvm.ptr, %arg3: !llvm.ptr, %arg4: !llvm.ptr, %arg5: !llvm.ptr):