diff --git a/flang/lib/Lower/OpenMP.cpp b/flang/lib/Lower/OpenMP.cpp --- a/flang/lib/Lower/OpenMP.cpp +++ b/flang/lib/Lower/OpenMP.cpp @@ -732,6 +732,7 @@ if (!(fir::isa_std_type(checkType) || checkType.isa() || + checkType.isa() || (checkType.isa() && !checkType.cast().hasDynamicExtents()))) TODO(currentLocation, "OMPD_target_data MapOperand type"); diff --git a/llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h b/llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h --- a/llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h +++ b/llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h @@ -1566,6 +1566,15 @@ Value *Ptr = nullptr; }; + /// This structure contains information generated for use_deviceptr/addr + /// clause operands including the alloca pointers, base pointers and their + /// use sets. + struct UseDeviceInfo { + Value *AllocaPtr = nullptr; + Value *BasePtr = nullptr; + SmallDenseSet Uses; + }; + /// Generator for '#omp target data' /// /// \param Loc The location where the target data construct was encountered. @@ -1577,13 +1586,15 @@ /// \param DeviceID Stores the DeviceID from the device clause. /// \param IfCond Value which corresponds to the if clause condition. /// \param MapInfos Map from a 'map' Value* to its corresponding MapInfo. + /// \param UseDeviceInfos Map from a use device pointer Value* to its + /// corresponding UseDeviceInfo. /// \param BodyGenCB Callback that will generate the region body code. - InsertPointTy createTargetData(const LocationDescription &Loc, - InsertPointTy AllocaIP, - InsertPointTy CodeGenIP, bool IsBegin, - int64_t DeviceID, Value *IfCond, - SmallMapVector &MapInfos, - BodyGenCallbackTy BodyGenCB = {}); + InsertPointTy + createTargetData(const LocationDescription &Loc, InsertPointTy AllocaIP, + InsertPointTy CodeGenIP, bool IsBegin, int64_t DeviceID, + Value *IfCond, SmallMapVector &MapInfos, + SmallMapVector &UseDeviceInfos, + BodyGenCallbackTy BodyGenCB = {}); /// Declarations for LLVM-IR types (simple, array, function and structure) are /// generated below. Their names are defined and used in OpenMPKinds.def. Here @@ -1703,6 +1714,8 @@ /// \param CodeGenIP The insertion point at which the target directive code /// should be placed. /// \param MapInfos Map from a 'map' Value* to its corresponding MapInfo. + /// \param UseDeviceInfos Map from a use device pointer Value* to its + /// corresponding UseDeviceInfo. /// \param BodyGenCB Callback that will generate the region body code. /// \param MapperAllocas Return param for the Alloca pointers from /// BasePtr, Ptr and Size ptr. @@ -1712,9 +1725,17 @@ void ProcessMapInfo(const LocationDescription &Loc, InsertPointTy AllocaIP, InsertPointTy CodeGenIP, SmallMapVector &MapInfos, + SmallMapVector &UseDeviceInfos, struct MapperAllocas &MapperAllocas, Value **MapNamesGV, Value **MapTypesGV, Value **MapSizesGV); + /// Generator for use device ptr & addr clauses + /// + /// \param UseDeviceInfos Map from a use device pointer Value* to its + /// corresponding UseDeviceInfo. + void ProcessUseDeviceInfo( + SmallMapVector &UseDeviceInfos); + private: enum AtomicKind { Read, Write, Update, Capture, Compare }; diff --git a/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp b/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp --- a/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp +++ b/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp @@ -4041,15 +4041,35 @@ return OutlinedFnID; } +void OpenMPIRBuilder::ProcessUseDeviceInfo( + SmallMapVector &UseDeviceInfos) { + for (auto &UseDeviceOp : UseDeviceInfos) { + auto *UseDeviceVal = UseDeviceOp.first; + auto &UseDeviceInfo = UseDeviceOp.second; + auto *LoadInst = + Builder.CreateLoad(Builder.getPtrTy(), UseDeviceInfo.BasePtr); + Builder.CreateStore(LoadInst, UseDeviceInfo.AllocaPtr); + + for (auto &Use : UseDeviceVal->uses()) + UseDeviceInfo.Uses.insert(&Use); + } +} + void OpenMPIRBuilder::ProcessMapInfo( const LocationDescription &Loc, InsertPointTy AllocaIP, InsertPointTy CodeGenIP, SmallMapVector &MapInfos, + SmallMapVector &UseDeviceInfos, struct MapperAllocas &MapperAllocas, Value **MapNamesArg, Value **MapTypesArg, Value **MapSizesArg) { auto NumMapOperands = MapInfos.size(); createMapperAllocas(Loc, AllocaIP, NumMapOperands, MapperAllocas, false); + Builder.restoreIP(AllocaIP); + + for (auto &UseDeviceOp : UseDeviceInfos) + UseDeviceOp.second.AllocaPtr = Builder.CreateAlloca(Builder.getPtrTy()); + Builder.restoreIP(CodeGenIP); ArrayType *ArrI8PtrTy = @@ -4080,6 +4100,9 @@ Index++; } + for (auto &UseDeviceOp : UseDeviceInfos) + UseDeviceOp.second.BasePtr = MapInfos[UseDeviceOp.first].BasePtr; + SmallVector MapNames; SmallVector MapTypes; SmallVector MapSizes; @@ -4111,6 +4134,7 @@ const LocationDescription &Loc, InsertPointTy AllocaIP, InsertPointTy CodeGenIP, bool IsBegin, int64_t DeviceID, Value *IfCond, SmallMapVector &MapInfos, + SmallMapVector &UseDeviceInfos, BodyGenCallbackTy BodyGenCB) { if (!updateToLocation(Loc)) return InsertPointTy(); @@ -4131,8 +4155,8 @@ struct MapperAllocas MapperAllocas; Value *MapNamesArg = nullptr, *MapTypesArg = nullptr, *MapSizesArg = nullptr; - ProcessMapInfo(Loc, AllocaIP, Builder.saveIP(), MapInfos, MapperAllocas, - &MapNamesArg, &MapTypesArg, &MapSizesArg); + ProcessMapInfo(Loc, AllocaIP, Builder.saveIP(), MapInfos, UseDeviceInfos, + MapperAllocas, &MapNamesArg, &MapTypesArg, &MapSizesArg); uint32_t SrcLocStrSize; Constant *SrcLocStr = getOrCreateSrcLocStr(Loc, SrcLocStrSize); @@ -4149,8 +4173,22 @@ MapNamesArg, MapperAllocas, DeviceID, MapInfos.size(), MapSizesArg); + ProcessUseDeviceInfo(UseDeviceInfos); + BodyGenCB(Builder.saveIP(), Builder.saveIP()); + for (auto &UseDeviceOp : UseDeviceInfos) { + auto *UseDeviceVal = UseDeviceOp.first; + auto &UseDeviceInfo = UseDeviceOp.second; + SmallDenseSet ReplaceUses; + for (auto &Use : UseDeviceVal->uses()) { + if (UseDeviceInfo.Uses.find(&Use) == UseDeviceInfo.Uses.end()) + ReplaceUses.insert(&Use); + } + for (auto &Use : ReplaceUses) + Use->set(UseDeviceInfo.AllocaPtr); + } + Builder.SetInsertPoint(UI->getParent()); // Create call to end the data region. emitMapperCall(Builder.saveIP(), endMapperFunc, srcLocInfo, MapTypesArg, diff --git a/llvm/unittests/Frontend/OpenMPIRBuilderTest.cpp b/llvm/unittests/Frontend/OpenMPIRBuilderTest.cpp --- a/llvm/unittests/Frontend/OpenMPIRBuilderTest.cpp +++ b/llvm/unittests/Frontend/OpenMPIRBuilderTest.cpp @@ -4929,6 +4929,8 @@ llvm::SmallMapVector MapInfos; + llvm::SmallMapVector + UseDeviceInfos; uint32_t temp; MapInfos[Val1].Name = OMPBuilder.getOrCreateSrcLocStr("unknown", temp); @@ -4937,7 +4939,7 @@ Builder.restoreIP(OMPBuilder.createTargetData( Loc, AllocaIP, Builder.saveIP(), /* IsBegin= */ true, DeviceID, - /* IfCond= */ nullptr, MapInfos)); + /* IfCond= */ nullptr, MapInfos, UseDeviceInfos)); CallInst *TargetDataCall = dyn_cast(&BB->back()); EXPECT_NE(TargetDataCall, nullptr); @@ -4969,6 +4971,8 @@ llvm::SmallMapVector MapInfos; + llvm::SmallMapVector + UseDeviceInfos; uint32_t temp; MapInfos[Val1].Name = OMPBuilder.getOrCreateSrcLocStr("unknown", temp); @@ -4977,7 +4981,7 @@ Builder.restoreIP(OMPBuilder.createTargetData( Loc, AllocaIP, Builder.saveIP(), /* IsBegin= */ false, DeviceID, - /* IfCond= */ nullptr, MapInfos)); + /* IfCond= */ nullptr, MapInfos, UseDeviceInfos)); CallInst *TargetDataCall = dyn_cast(&BB->back()); EXPECT_NE(TargetDataCall, nullptr); @@ -5000,24 +5004,34 @@ OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL}); int64_t DeviceID = 2; - AllocaInst *Val1 = - Builder.CreateAlloca(Builder.getInt32Ty(), Builder.getInt64(1)); + AllocaInst *Val1 = Builder.CreateAlloca(Builder.getInt32Ty()); ASSERT_NE(Val1, nullptr); + AllocaInst *Val2 = Builder.CreateAlloca(Builder.getInt32Ty()->getPointerTo()); + ASSERT_NE(Val2, nullptr); + IRBuilder<>::InsertPoint AllocaIP(&F->getEntryBlock(), F->getEntryBlock().getFirstInsertionPt()); llvm::SmallMapVector MapInfos; + llvm::SmallMapVector + UseDeviceInfos; uint32_t temp; MapInfos[Val1].Name = OMPBuilder.getOrCreateSrcLocStr("unknown", temp); MapInfos[Val1].Size = OMPBuilder.getSizeInBytes(Val1); MapInfos[Val1].Type = 3; + MapInfos[Val2].Name = OMPBuilder.getOrCreateSrcLocStr("unknown", temp); + MapInfos[Val2].Size = OMPBuilder.getSizeInBytes(Val2); + MapInfos[Val2].Type = 67; + + UseDeviceInfos[Val2]; using InsertPointTy = OpenMPIRBuilder::InsertPointTy; auto BodyCB = [&](InsertPointTy allocaIP, InsertPointTy codeGenIP) { - CallInst *TargetDataCall = dyn_cast(BB->back().getPrevNode()); + CallInst *TargetDataCall = dyn_cast( + BB->back().getPrevNode()->getPrevNode()->getPrevNode()->getPrevNode()); EXPECT_NE(TargetDataCall, nullptr); EXPECT_EQ(TargetDataCall->arg_size(), 9U); EXPECT_EQ(TargetDataCall->getCalledFunction()->getName(), @@ -5026,12 +5040,20 @@ EXPECT_TRUE(TargetDataCall->getOperand(2)->getType()->isIntegerTy(32)); EXPECT_TRUE(TargetDataCall->getOperand(8)->getType()->isPointerTy()); Builder.restoreIP(codeGenIP); - Builder.CreateStore(Builder.getInt32(99), Val1); + Builder.CreateStore(Builder.getInt32(10), Val1); + auto *LI = Builder.CreateLoad(Builder.getInt32Ty()->getPointerTo(), Val2); + Builder.CreateStore(Builder.getInt32(20), LI); }; Builder.restoreIP(OMPBuilder.createTargetData( Loc, AllocaIP, Builder.saveIP(), /* IsBegin= */ false, DeviceID, - /* IfCond= */ nullptr, MapInfos, BodyCB)); + /* IfCond= */ nullptr, MapInfos, UseDeviceInfos, BodyCB)); + + LoadInst *UseDeviceLoadInst = dyn_cast( + BB->back().getPrevNode()->getPrevNode()->getPrevNode()->getPrevNode()); + EXPECT_NE(UseDeviceLoadInst->getPointerOperand(), Val2); + EXPECT_EQ(UseDeviceLoadInst->getPointerOperand(), + UseDeviceInfos[Val2].AllocaPtr); CallInst *TargetDataCall = dyn_cast(&BB->back()); EXPECT_NE(TargetDataCall, nullptr); diff --git a/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp b/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp --- a/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp +++ b/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp @@ -1357,8 +1357,11 @@ static LogicalResult gatherMapInfo( LLVM::ModuleTranslation &moduleTranslation, const SmallVectorImpl &mapOperands, const ArrayAttr &mapTypes, + const SmallVectorImpl &useDevicePtrOperands, llvm::SmallMapVector - &mapInfos) { + &mapInfos, + llvm::SmallMapVector + &useDeviceInfos) { llvm::OpenMPIRBuilder *ompBuilder = moduleTranslation.getOpenMPBuilder(); unsigned index = 0; for (const auto &mapOp : mapOperands) { @@ -1372,6 +1375,25 @@ mapInfos[mapOpValue].Size = ompBuilder->getSizeInBytes(mapOpValue); index++; } + + // Look at the use_device_ptr and use_device_addr clauses information and + // mark the existing map entries as such. If there is no map information for + // an entry in the use_device_ptr and use_device_addr list, we create one + // with map type 'alloc' and zero size section. + for (const auto &ptrOp : useDevicePtrOperands) { + llvm::Value *ptrOpValue = moduleTranslation.lookupValue(ptrOp); + if (mapInfos.find(ptrOpValue) == mapInfos.end()) { + mapInfos[ptrOpValue].Name = + mlir::LLVM::createMappingInformation(ptrOp.getLoc(), *ompBuilder); + mapInfos[ptrOpValue].Type = 0x00; + mapInfos[ptrOpValue].Size = 0; + } + mapInfos[ptrOpValue].Type |= static_cast< + std::underlying_type_t>( + llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_RETURN_PARAM); + useDeviceInfos[ptrOpValue]; + } + return success(); } @@ -1382,16 +1404,19 @@ bool isBegin; llvm::Value *ifCond = nullptr; int64_t deviceID = llvm::omp::OMP_DEVICEID_UNDEF; - SmallVector mapOperands; + SmallVector mapOperands, useDevicePtrOperands; ArrayAttr mapTypes; + llvm::SmallMapVector + mapInfos; + llvm::SmallMapVector + useDeviceInfos; llvm::OpenMPIRBuilder *ompBuilder = moduleTranslation.getOpenMPBuilder(); LogicalResult result = llvm::TypeSwitch(op) .Case([&](omp::DataOp dataOp) { - if (dataOp.getUseDeviceAddr().size() || - dataOp.getUseDevicePtr().size()) + if (dataOp.getUseDeviceAddr().size()) return failure(); if (auto ifExprVar = dataOp.getIfExpr()) @@ -1407,6 +1432,7 @@ numMapOperands = dataOp.getMapOperands().size(); mapOperands = dataOp.getMapOperands(); mapTypes = dataOp.getMapTypes(); + useDevicePtrOperands = dataOp.getUseDevicePtr(); return success(); }) .Case([&](omp::EnterDataOp enterDataOp) { @@ -1460,16 +1486,26 @@ LogicalResult bodyGenStatus = success(); using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy; auto bodyCB = [&](InsertPointTy allocaIP, InsertPointTy codeGenIP) { + // llvm::SmallDenseMap saveValueMap; + // for (const auto &ptrOp : useDevicePtrOperands) { + // llvm::Value *ptrOpValue = moduleTranslation.lookupValue(ptrOp); + // saveValueMap[ptrOp] = ptrOpValue; + // moduleTranslation.mapValue(ptrOp, + // useDeviceInfos[ptrOpValue].AllocaPtr); + // } + // DataOp has only one region associated with it. auto ®ion = cast(op).getRegion(); builder.restoreIP(codeGenIP); bodyGenStatus = inlineConvertOmpRegions(region, "omp.data.region", builder, moduleTranslation); + + // for (const auto &ptrOp : useDevicePtrOperands) + // moduleTranslation.mapValue(ptrOp, saveValueMap[ptrOp]); }; - llvm::SmallMapVector - mapInfos; - if (failed(gatherMapInfo(moduleTranslation, mapOperands, mapTypes, mapInfos))) + if (failed(gatherMapInfo(moduleTranslation, mapOperands, mapTypes, + useDevicePtrOperands, mapInfos, useDeviceInfos))) return failure(); llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder); @@ -1479,11 +1515,11 @@ if (isa(op)) { builder.restoreIP(ompBuilder->createTargetData( ompLoc, allocaIP, builder.saveIP(), isBegin, deviceID, ifCond, mapInfos, - bodyCB)); + useDeviceInfos, bodyCB)); } else { - builder.restoreIP(ompBuilder->createTargetData(ompLoc, allocaIP, - builder.saveIP(), isBegin, - deviceID, ifCond, mapInfos)); + builder.restoreIP(ompBuilder->createTargetData( + ompLoc, allocaIP, builder.saveIP(), isBegin, deviceID, ifCond, mapInfos, + useDeviceInfos)); } return bodyGenStatus; diff --git a/mlir/test/Target/LLVMIR/omptarget-llvm.mlir b/mlir/test/Target/LLVMIR/omptarget-llvm.mlir --- a/mlir/test/Target/LLVMIR/omptarget-llvm.mlir +++ b/mlir/test/Target/LLVMIR/omptarget-llvm.mlir @@ -155,3 +155,74 @@ // CHECK: ret void // ----- + +llvm.func @_QPopenmp_target_use_dev_ptr() { + %0 = llvm.mlir.constant(1 : i64) : i64 + %a = llvm.alloca %0 x !llvm.ptr> : (i64) -> !llvm.ptr> + %1 = llvm.mlir.constant(1 : i64) : i64 + %b = llvm.alloca %0 x !llvm.ptr> : (i64) -> !llvm.ptr> + omp.target_data use_device_ptr(%a : !llvm.ptr>) map((from -> %a : !llvm.ptr>)) { + %3 = llvm.mlir.constant(10 : i32) : i32 + %4 = llvm.load %a : !llvm.ptr> + llvm.store %3, %4 : !llvm.ptr + omp.terminator + } + omp.target_data use_device_ptr(%a : !llvm.ptr>) map((from -> %b : !llvm.ptr>)) { + %3 = llvm.mlir.constant(10 : i32) : i32 + %4 = llvm.load %a : !llvm.ptr> + llvm.store %3, %4 : !llvm.ptr + omp.terminator + } + llvm.return +} + +// CHECK: @.offload_maptypes = private unnamed_addr constant [1 x i64] [i64 66] +// CHECK: @.offload_sizes = private unnamed_addr constant [1 x i64] [i64 8] +// CHECK: @.offload_maptypes.2 = private unnamed_addr constant [2 x i64] [i64 2, i64 64] +// CHECK: @.offload_sizes.3 = private unnamed_addr constant [2 x i64] [i64 8, i64 0] +// CHECK-LABEL: define void @_QPopenmp_target_use_dev_ptr +// CHECK: %[[VAL_0:.*]] = alloca [2 x ptr], align 8 +// CHECK: %[[VAL_1:.*]] = alloca [2 x ptr], align 8 +// CHECK: %[[VAL_2:.*]] = alloca ptr, align 8 +// CHECK: %[[VAL_3:.*]] = alloca [1 x ptr], align 8 +// CHECK: %[[VAL_4:.*]] = alloca [1 x ptr], align 8 +// CHECK: %[[VAL_5:.*]] = alloca ptr, align 8 +// CHECK: %[[VAL_6:.*]] = alloca ptr, i64 1, align 8 +// CHECK: %[[VAL_7:.*]] = alloca ptr, i64 1, align 8 +// CHECK: br label %[[VAL_8:.*]] +// CHECK: entry: ; preds = %[[VAL_9:.*]] +// CHECK: %[[VAL_10:.*]] = getelementptr inbounds [1 x ptr], ptr %[[VAL_3]], i32 0, i32 0 +// CHECK: store ptr %[[VAL_6]], ptr %[[VAL_10]], align 8 +// CHECK: %[[VAL_11:.*]] = getelementptr inbounds [1 x ptr], ptr %[[VAL_4]], i32 0, i32 0 +// CHECK: store ptr %[[VAL_6]], ptr %[[VAL_11]], align 8 +// CHECK: %[[VAL_12:.*]] = getelementptr inbounds [1 x ptr], ptr %[[VAL_3]], i32 0, i32 0 +// CHECK: %[[VAL_13:.*]] = getelementptr inbounds [1 x ptr], ptr %[[VAL_4]], i32 0, i32 0 +// CHECK: call void @__tgt_target_data_begin_mapper(ptr @2, i64 -1, i32 1, ptr %[[VAL_12]], ptr %[[VAL_13]], ptr @.offload_sizes, ptr @.offload_maptypes, ptr @.offload_mapnames, ptr null) +// CHECK: %[[VAL_14:.*]] = load ptr, ptr %[[VAL_10]], align 8 +// CHECK: store ptr %[[VAL_14]], ptr %[[VAL_5]], align 8 +// CHECK: %[[VAL_15:.*]] = load ptr, ptr %[[VAL_5]], align 8 +// CHECK: store i32 10, ptr %[[VAL_15]], align 4 +// CHECK: %[[VAL_16:.*]] = getelementptr inbounds [1 x ptr], ptr %[[VAL_3]], i32 0, i32 0 +// CHECK: %[[VAL_17:.*]] = getelementptr inbounds [1 x ptr], ptr %[[VAL_4]], i32 0, i32 0 +// CHECK: call void @__tgt_target_data_end_mapper(ptr @2, i64 -1, i32 1, ptr %[[VAL_16]], ptr %[[VAL_17]], ptr @.offload_sizes, ptr @.offload_maptypes, ptr @.offload_mapnames, ptr null) +// CHECK: %[[VAL_18:.*]] = getelementptr inbounds [2 x ptr], ptr %[[VAL_0]], i32 0, i32 0 +// CHECK: store ptr %[[VAL_7]], ptr %[[VAL_18]], align 8 +// CHECK: %[[VAL_19:.*]] = getelementptr inbounds [2 x ptr], ptr %[[VAL_1]], i32 0, i32 0 +// CHECK: store ptr %[[VAL_7]], ptr %[[VAL_19]], align 8 +// CHECK: %[[VAL_20:.*]] = getelementptr inbounds [2 x ptr], ptr %[[VAL_0]], i32 0, i32 1 +// CHECK: store ptr %[[VAL_6]], ptr %[[VAL_20]], align 8 +// CHECK: %[[VAL_21:.*]] = getelementptr inbounds [2 x ptr], ptr %[[VAL_1]], i32 0, i32 1 +// CHECK: store ptr %[[VAL_6]], ptr %[[VAL_21]], align 8 +// CHECK: %[[VAL_22:.*]] = getelementptr inbounds [2 x ptr], ptr %[[VAL_0]], i32 0, i32 0 +// CHECK: %[[VAL_23:.*]] = getelementptr inbounds [2 x ptr], ptr %[[VAL_1]], i32 0, i32 0 +// CHECK: call void @__tgt_target_data_begin_mapper(ptr @2, i64 -1, i32 2, ptr %[[VAL_22]], ptr %[[VAL_23]], ptr @.offload_sizes.3, ptr @.offload_maptypes.2, ptr @.offload_mapnames.1, ptr null) +// CHECK: %[[VAL_24:.*]] = load ptr, ptr %[[VAL_20]], align 8 +// CHECK: store ptr %[[VAL_24]], ptr %[[VAL_2]], align 8 +// CHECK: %[[VAL_25:.*]] = load ptr, ptr %[[VAL_2]], align 8 +// CHECK: store i32 10, ptr %[[VAL_25]], align 4 +// CHECK: %[[VAL_26:.*]] = getelementptr inbounds [2 x ptr], ptr %[[VAL_0]], i32 0, i32 0 +// CHECK: %[[VAL_27:.*]] = getelementptr inbounds [2 x ptr], ptr %[[VAL_1]], i32 0, i32 0 +// CHECK: call void @__tgt_target_data_end_mapper(ptr @2, i64 -1, i32 2, ptr %[[VAL_26]], ptr %[[VAL_27]], ptr @.offload_sizes.3, ptr @.offload_maptypes.2, ptr @.offload_mapnames.1, ptr null) +// CHECK: ret void + +// -----