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 @@ -4848,14 +4848,12 @@ Builder.restoreIP(AllocaIP); Info.DevicePtrInfoMap[BPVal] = {BP, Builder.CreateAlloca(PtrTy)}; Builder.restoreIP(CodeGenIP); - assert(DeviceAddrCB && - "DeviceAddrCB missing for DevicePtr code generation"); - DeviceAddrCB(I, Info.DevicePtrInfoMap[BPVal].second); + if (DeviceAddrCB) + DeviceAddrCB(I, Info.DevicePtrInfoMap[BPVal].second); } else if (CombinedInfo.DevicePointers[I] == DeviceInfoTy::Address) { Info.DevicePtrInfoMap[BPVal] = {BP, BP}; - assert(DeviceAddrCB && - "DeviceAddrCB missing for DevicePtr code generation"); - DeviceAddrCB(I, BP); + if (DeviceAddrCB) + DeviceAddrCB(I, BP); } } 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 @@ -4894,6 +4894,8 @@ CombinedInfo.BasePointers.emplace_back(Val1); CombinedInfo.Pointers.emplace_back(Val1); + CombinedInfo.DevicePointers.emplace_back( + llvm::OpenMPIRBuilder::DeviceInfoTy::None); CombinedInfo.Sizes.emplace_back(Builder.getInt64(4)); CombinedInfo.Types.emplace_back(llvm::omp::OpenMPOffloadMappingFlags(1)); uint32_t temp; @@ -4951,6 +4953,8 @@ CombinedInfo.BasePointers.emplace_back(Val1); CombinedInfo.Pointers.emplace_back(Val1); + CombinedInfo.DevicePointers.emplace_back( + llvm::OpenMPIRBuilder::DeviceInfoTy::None); CombinedInfo.Sizes.emplace_back(Builder.getInt64(4)); CombinedInfo.Types.emplace_back(llvm::omp::OpenMPOffloadMappingFlags(2)); uint32_t temp; @@ -4996,36 +5000,63 @@ Builder.CreateAlloca(Builder.getInt32Ty(), Builder.getInt64(1)); ASSERT_NE(Val1, nullptr); + AllocaInst *Val2 = Builder.CreateAlloca(Builder.getPtrTy()); + ASSERT_NE(Val2, nullptr); + + AllocaInst *Val3 = Builder.CreateAlloca(Builder.getPtrTy()); + ASSERT_NE(Val3, nullptr); + IRBuilder<>::InsertPoint AllocaIP(&F->getEntryBlock(), F->getEntryBlock().getFirstInsertionPt()); + using DeviceInfoTy = llvm::OpenMPIRBuilder::DeviceInfoTy; llvm::OpenMPIRBuilder::MapInfosTy CombinedInfo; using InsertPointTy = OpenMPIRBuilder::InsertPointTy; auto GenMapInfoCB = [&](InsertPointTy codeGenIP) -> llvm::OpenMPIRBuilder::MapInfosTy & { // Get map clause information. Builder.restoreIP(codeGenIP); + uint32_t temp; CombinedInfo.BasePointers.emplace_back(Val1); CombinedInfo.Pointers.emplace_back(Val1); + CombinedInfo.DevicePointers.emplace_back(DeviceInfoTy::None); CombinedInfo.Sizes.emplace_back(Builder.getInt64(4)); CombinedInfo.Types.emplace_back(llvm::omp::OpenMPOffloadMappingFlags(3)); - uint32_t temp; + CombinedInfo.Names.emplace_back( + OMPBuilder.getOrCreateSrcLocStr("unknown", temp)); + + CombinedInfo.BasePointers.emplace_back(Val2); + CombinedInfo.Pointers.emplace_back(Val2); + CombinedInfo.DevicePointers.emplace_back(DeviceInfoTy::Pointer); + CombinedInfo.Sizes.emplace_back(Builder.getInt64(8)); + CombinedInfo.Types.emplace_back(llvm::omp::OpenMPOffloadMappingFlags(67)); + CombinedInfo.Names.emplace_back( + OMPBuilder.getOrCreateSrcLocStr("unknown", temp)); + + CombinedInfo.BasePointers.emplace_back(Val3); + CombinedInfo.Pointers.emplace_back(Val3); + CombinedInfo.DevicePointers.emplace_back(DeviceInfoTy::Address); + CombinedInfo.Sizes.emplace_back(Builder.getInt64(8)); + CombinedInfo.Types.emplace_back(llvm::omp::OpenMPOffloadMappingFlags(67)); CombinedInfo.Names.emplace_back( OMPBuilder.getOrCreateSrcLocStr("unknown", temp)); return CombinedInfo; }; llvm::OpenMPIRBuilder::TargetDataInfo Info( - /*RequiresDevicePointerInfo=*/false, + /*RequiresDevicePointerInfo=*/true, /*SeparateBeginEndCalls=*/true); OMPBuilder.Config.setIsGPU(true); - auto BodyCB = [&](InsertPointTy CodeGenIP, int BodyGenType) { - if (BodyGenType == 3) { + using BodyGenTy = llvm::OpenMPIRBuilder::BodyGenTy; + auto BodyCB = [&](InsertPointTy CodeGenIP, BodyGenTy BodyGenType) { + if (BodyGenType == BodyGenTy::Priv) { + EXPECT_EQ(Info.DevicePtrInfoMap.size(), 2u); Builder.restoreIP(CodeGenIP); - CallInst *TargetDataCall = dyn_cast(&BB->back()); + CallInst *TargetDataCall = + dyn_cast(BB->back().getPrevNode()->getPrevNode()); EXPECT_NE(TargetDataCall, nullptr); EXPECT_EQ(TargetDataCall->arg_size(), 9U); EXPECT_EQ(TargetDataCall->getCalledFunction()->getName(), @@ -5033,7 +5064,15 @@ EXPECT_TRUE(TargetDataCall->getOperand(1)->getType()->isIntegerTy(64)); EXPECT_TRUE(TargetDataCall->getOperand(2)->getType()->isIntegerTy(32)); EXPECT_TRUE(TargetDataCall->getOperand(8)->getType()->isPointerTy()); - Builder.restoreIP(CodeGenIP); + + LoadInst *LI = dyn_cast(BB->back().getPrevNode()); + EXPECT_NE(LI, nullptr); + StoreInst *SI = dyn_cast(&BB->back()); + EXPECT_NE(SI, nullptr); + EXPECT_EQ(SI->getValueOperand(), LI); + EXPECT_EQ(SI->getPointerOperand(), Info.DevicePtrInfoMap[Val2].second); + EXPECT_TRUE(isa(Info.DevicePtrInfoMap[Val2].second)); + EXPECT_TRUE(isa(Info.DevicePtrInfoMap[Val3].second)); Builder.CreateStore(Builder.getInt32(99), Val1); } return Builder.saveIP(); 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 @@ -1367,44 +1367,92 @@ return success(); } -int64_t getSizeInBytes(DataLayout &DL, const mlir::Type &type) { +int64_t getSizeInBytes(DataLayout &DL, const Type &type) { if (isa(type)) return DL.getTypeSize(cast(type).getElementType()); return 0; } +// Generate all map related information and fill the combinedInfo. static void genMapInfos(llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation, DataLayout &DL, llvm::OpenMPIRBuilder::MapInfosTy &combinedInfo, const SmallVector &mapOperands, - const ArrayAttr &mapTypes) { - // Get map clause information. + const ArrayAttr &mapTypes, + const SmallVector &devPtrOperands = {}, + const SmallVector &devAddrOperands = {}) { llvm::OpenMPIRBuilder *ompBuilder = moduleTranslation.getOpenMPBuilder(); + + auto fail = [&combinedInfo]() -> void { + combinedInfo.BasePointers.clear(); + combinedInfo.Pointers.clear(); + combinedInfo.DevicePointers.clear(); + combinedInfo.Sizes.clear(); + combinedInfo.Types.clear(); + combinedInfo.Names.clear(); + }; + + auto findMapInfo = [&combinedInfo](llvm::Value *val, unsigned &index) { + index = 0; + for (auto basePtr : combinedInfo.BasePointers) { + if (basePtr == val) + return true; + index++; + } + return false; + }; + unsigned index = 0; for (const auto &mapOp : mapOperands) { - if (!mapOp.getType().isa()) { - // TODO: Only LLVMPointerTypes are handled. - combinedInfo.BasePointers.clear(); - combinedInfo.Pointers.clear(); - combinedInfo.Sizes.clear(); - combinedInfo.Types.clear(); - combinedInfo.Names.clear(); - return; - } + // TODO: Only LLVMPointerTypes are handled. + if (!mapOp.getType().isa()) + return fail(); llvm::Value *mapOpValue = moduleTranslation.lookupValue(mapOp); combinedInfo.BasePointers.emplace_back(mapOpValue); combinedInfo.Pointers.emplace_back(mapOpValue); + combinedInfo.DevicePointers.emplace_back( + llvm::OpenMPIRBuilder::DeviceInfoTy::None); combinedInfo.Names.emplace_back( - mlir::LLVM::createMappingInformation(mapOp.getLoc(), *ompBuilder)); + LLVM::createMappingInformation(mapOp.getLoc(), *ompBuilder)); combinedInfo.Types.emplace_back(llvm::omp::OpenMPOffloadMappingFlags( - mapTypes[index].dyn_cast().getInt())); + mapTypes[index].dyn_cast().getInt())); combinedInfo.Sizes.emplace_back( builder.getInt64(getSizeInBytes(DL, mapOp.getType()))); index++; } + + auto addDevInfos = [&, fail](auto devOperands, auto devOpType) -> void { + for (const auto &devOp : devOperands) { + // TODO: Only LLVMPointerTypes are handled. + if (!devOp.getType().template isa()) + return fail(); + + llvm::Value *mapOpValue = moduleTranslation.lookupValue(devOp); + + // Check if map info is already present for this entry. + unsigned infoIndex; + if (findMapInfo(mapOpValue, infoIndex)) { + combinedInfo.Types[infoIndex] |= + llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_RETURN_PARAM; + combinedInfo.DevicePointers[infoIndex] = devOpType; + } else { + combinedInfo.BasePointers.emplace_back(mapOpValue); + combinedInfo.Pointers.emplace_back(mapOpValue); + combinedInfo.DevicePointers.emplace_back(devOpType); + combinedInfo.Names.emplace_back( + LLVM::createMappingInformation(devOp.getLoc(), *ompBuilder)); + combinedInfo.Types.emplace_back( + llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_RETURN_PARAM); + combinedInfo.Sizes.emplace_back(builder.getInt64(0)); + } + } + }; + + addDevInfos(devPtrOperands, llvm::OpenMPIRBuilder::DeviceInfoTy::Pointer); + addDevInfos(devAddrOperands, llvm::OpenMPIRBuilder::DeviceInfoTy::Address); } static LogicalResult @@ -1413,6 +1461,8 @@ llvm::Value *ifCond = nullptr; int64_t deviceID = llvm::omp::OMP_DEVICEID_UNDEF; SmallVector mapOperands; + SmallVector useDevPtrOperands; + SmallVector useDevAddrOperands; ArrayAttr mapTypes; llvm::omp::RuntimeFunction RTLFn; DataLayout DL = DataLayout(op->getParentOfType()); @@ -1422,23 +1472,20 @@ LogicalResult result = llvm::TypeSwitch(op) .Case([&](omp::DataOp dataOp) { - if (!dataOp.getUseDeviceAddr().empty() || - !dataOp.getUseDevicePtr().empty()) - return failure(); - if (auto ifExprVar = dataOp.getIfExpr()) ifCond = moduleTranslation.lookupValue(ifExprVar); if (auto devId = dataOp.getDevice()) - if (auto constOp = mlir::dyn_cast( - devId.getDefiningOp())) - if (auto intAttr = - dyn_cast(constOp.getValue())) + if (auto constOp = + dyn_cast(devId.getDefiningOp())) + if (auto intAttr = dyn_cast(constOp.getValue())) deviceID = intAttr.getInt(); mapOperands = dataOp.getMapOperands(); if (dataOp.getMapTypes()) mapTypes = dataOp.getMapTypes().value(); + useDevPtrOperands = dataOp.getUseDevicePtr(); + useDevAddrOperands = dataOp.getUseDeviceAddr(); return success(); }) .Case([&](omp::EnterDataOp enterDataOp) { @@ -1449,10 +1496,9 @@ ifCond = moduleTranslation.lookupValue(ifExprVar); if (auto devId = enterDataOp.getDevice()) - if (auto constOp = mlir::dyn_cast( - devId.getDefiningOp())) - if (auto intAttr = - dyn_cast(constOp.getValue())) + if (auto constOp = + dyn_cast(devId.getDefiningOp())) + if (auto intAttr = dyn_cast(constOp.getValue())) deviceID = intAttr.getInt(); RTLFn = llvm::omp::OMPRTL___tgt_target_data_begin_mapper; mapOperands = enterDataOp.getMapOperands(); @@ -1467,10 +1513,9 @@ ifCond = moduleTranslation.lookupValue(ifExprVar); if (auto devId = exitDataOp.getDevice()) - if (auto constOp = mlir::dyn_cast( - devId.getDefiningOp())) - if (auto intAttr = - dyn_cast(constOp.getValue())) + if (auto constOp = + dyn_cast(devId.getDefiningOp())) + if (auto intAttr = dyn_cast(constOp.getValue())) deviceID = intAttr.getInt(); RTLFn = llvm::omp::OMPRTL___tgt_target_data_end_mapper; @@ -1493,26 +1538,61 @@ auto genMapInfoCB = [&](InsertPointTy codeGenIP) -> llvm::OpenMPIRBuilder::MapInfosTy & { builder.restoreIP(codeGenIP); - genMapInfos(builder, moduleTranslation, DL, combinedInfo, mapOperands, - mapTypes); + if (auto DataOp = dyn_cast(op)) { + genMapInfos(builder, moduleTranslation, DL, combinedInfo, mapOperands, + mapTypes, useDevPtrOperands, useDevAddrOperands); + } else { + genMapInfos(builder, moduleTranslation, DL, combinedInfo, mapOperands, + mapTypes); + } return combinedInfo; }; - LogicalResult bodyGenStatus = success(); + llvm::OpenMPIRBuilder::TargetDataInfo info(/*RequiresDevicePointerInfo=*/true, + /*SeparateBeginEndCalls=*/true); + using BodyGenTy = llvm::OpenMPIRBuilder::BodyGenTy; + LogicalResult bodyGenStatus = success(); auto bodyGenCB = [&](InsertPointTy codeGenIP, BodyGenTy bodyGenType) { + assert(isa(op) && "BodyGen requested for non DataOp"); + Region ®ion = cast(op).getRegion(); switch (bodyGenType) { case BodyGenTy::Priv: + // Check if any device ptr/addr info is available + if (!info.DevicePtrInfoMap.empty()) { + builder.restoreIP(codeGenIP); + unsigned argIndex = 0; + for (auto &devPtrOp : useDevPtrOperands) { + llvm::Value *mapOpValue = moduleTranslation.lookupValue(devPtrOp); + const auto &arg = region.front().getArgument(argIndex); + moduleTranslation.mapValue(arg, + info.DevicePtrInfoMap[mapOpValue].second); + argIndex++; + } + + for (auto &devAddrOp : useDevAddrOperands) { + llvm::Value *mapOpValue = moduleTranslation.lookupValue(devAddrOp); + const auto &arg = region.front().getArgument(argIndex); + auto *LI = builder.CreateLoad( + builder.getPtrTy(), info.DevicePtrInfoMap[mapOpValue].second); + moduleTranslation.mapValue(arg, LI); + argIndex++; + } + + bodyGenStatus = inlineConvertOmpRegions(region, "omp.data.region", + builder, moduleTranslation); + } break; case BodyGenTy::DupNoPriv: break; - case BodyGenTy::NoPriv: { - // DataOp has only one region associated with it. - auto ®ion = cast(op).getRegion(); - builder.restoreIP(codeGenIP); - bodyGenStatus = inlineConvertOmpRegions(region, "omp.data.region", - builder, moduleTranslation); - } + case BodyGenTy::NoPriv: + // If device info is available then region has already been generated + if (info.DevicePtrInfoMap.empty()) { + builder.restoreIP(codeGenIP); + bodyGenStatus = inlineConvertOmpRegions(region, "omp.data.region", + builder, moduleTranslation); + } + break; } return builder.saveIP(); }; @@ -1520,11 +1600,6 @@ llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder); llvm::OpenMPIRBuilder::InsertPointTy allocaIP = findAllocaInsertPoint(builder, moduleTranslation); - - // TODO: Add support for DevicePointerInfo - llvm::OpenMPIRBuilder::TargetDataInfo info( - /*RequiresDevicePointerInfo=*/false, - /*SeparateBeginEndCalls=*/true); if (isa(op)) { builder.restoreIP(ompBuilder->createTargetData( ompLoc, allocaIP, builder.saveIP(), builder.getInt64(deviceID), ifCond, @@ -1693,7 +1768,7 @@ // lowering while removing functions at the current time. if (!isDeviceCompilation) return success(); - + omp::DeclareTargetDeviceType declareType = declareTargetAttr.getDeviceType().getValue(); 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 @@ -168,3 +168,239 @@ // 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> + omp.target_data map((from -> %a : !llvm.ptr>)) use_device_ptr(%a : !llvm.ptr>) { + ^bb0(%arg0: !llvm.ptr>): + %1 = llvm.mlir.constant(10 : i32) : i32 + %2 = llvm.load %arg0 : !llvm.ptr> + llvm.store %1, %2 : !llvm.ptr + omp.terminator + } + llvm.return +} + +// CHECK: @.offload_sizes = private unnamed_addr constant [1 x i64] [i64 8] +// CHECK: @.offload_maptypes = private unnamed_addr constant [1 x i64] [i64 66] +// CHECK-LABEL: define void @_QPopenmp_target_use_dev_ptr +// CHECK: %[[VAL_0:.*]] = alloca [1 x ptr], align 8 +// CHECK: %[[VAL_1:.*]] = alloca [1 x ptr], align 8 +// CHECK: %[[VAL_2:.*]] = alloca [1 x ptr], align 8 +// CHECK: %[[VAL_3:.*]] = alloca ptr, align 8 +// CHECK: %[[VAL_4:.*]] = alloca ptr, i64 1, align 8 +// CHECK: br label %[[VAL_5:.*]] +// CHECK: entry: ; preds = %[[VAL_6:.*]] +// CHECK: %[[VAL_7:.*]] = getelementptr inbounds [1 x ptr], ptr %[[VAL_0]], i32 0, i32 0 +// CHECK: store ptr %[[VAL_4]], ptr %[[VAL_7]], align 8 +// CHECK: %[[VAL_8:.*]] = getelementptr inbounds [1 x ptr], ptr %[[VAL_1]], i32 0, i32 0 +// CHECK: store ptr %[[VAL_4]], ptr %[[VAL_8]], align 8 +// CHECK: %[[VAL_9:.*]] = getelementptr inbounds [1 x ptr], ptr %[[VAL_2]], i64 0, i64 0 +// CHECK: store ptr null, ptr %[[VAL_9]], align 8 +// CHECK: %[[VAL_10:.*]] = getelementptr inbounds [1 x ptr], ptr %[[VAL_0]], i32 0, i32 0 +// CHECK: %[[VAL_11:.*]] = getelementptr inbounds [1 x ptr], ptr %[[VAL_1]], i32 0, i32 0 +// CHECK: call void @__tgt_target_data_begin_mapper(ptr @2, i64 -1, i32 1, ptr %[[VAL_10]], ptr %[[VAL_11]], ptr @.offload_sizes, ptr @.offload_maptypes, ptr @.offload_mapnames, ptr null) +// CHECK: %[[VAL_12:.*]] = load ptr, ptr %[[VAL_7]], align 8 +// CHECK: store ptr %[[VAL_12]], ptr %[[VAL_3]], align 8 +// CHECK: %[[VAL_13:.*]] = load ptr, ptr %[[VAL_3]], align 8 +// CHECK: store i32 10, ptr %[[VAL_13]], align 4 +// CHECK: %[[VAL_14:.*]] = getelementptr inbounds [1 x ptr], ptr %[[VAL_0]], i32 0, i32 0 +// CHECK: %[[VAL_15:.*]] = getelementptr inbounds [1 x ptr], ptr %[[VAL_1]], i32 0, i32 0 +// CHECK: call void @__tgt_target_data_end_mapper(ptr @2, i64 -1, i32 1, ptr %[[VAL_14]], ptr %[[VAL_15]], ptr @.offload_sizes, ptr @.offload_maptypes, ptr @.offload_mapnames, ptr null) +// CHECK: ret void + +// ----- + +llvm.func @_QPopenmp_target_use_dev_addr() { + %0 = llvm.mlir.constant(1 : i64) : i64 + %a = llvm.alloca %0 x !llvm.ptr> : (i64) -> !llvm.ptr> + omp.target_data map((from -> %a : !llvm.ptr>)) use_device_addr(%a : !llvm.ptr>) { + ^bb0(%arg0: !llvm.ptr>): + %1 = llvm.mlir.constant(10 : i32) : i32 + %2 = llvm.load %arg0 : !llvm.ptr> + llvm.store %1, %2 : !llvm.ptr + omp.terminator + } + llvm.return +} + +// CHECK: @.offload_sizes = private unnamed_addr constant [1 x i64] [i64 8] +// CHECK: @.offload_maptypes = private unnamed_addr constant [1 x i64] [i64 66] +// CHECK-LABEL: define void @_QPopenmp_target_use_dev_addr +// CHECK: %[[VAL_0:.*]] = alloca [1 x ptr], align 8 +// CHECK: %[[VAL_1:.*]] = alloca [1 x ptr], align 8 +// CHECK: %[[VAL_2:.*]] = alloca [1 x ptr], align 8 +// CHECK: %[[VAL_3:.*]] = alloca ptr, i64 1, align 8 +// CHECK: br label %[[VAL_4:.*]] +// CHECK: entry: ; preds = %[[VAL_5:.*]] +// CHECK: %[[VAL_6:.*]] = getelementptr inbounds [1 x ptr], ptr %[[VAL_0]], i32 0, i32 0 +// CHECK: store ptr %[[VAL_3]], ptr %[[VAL_6]], align 8 +// CHECK: %[[VAL_7:.*]] = getelementptr inbounds [1 x ptr], ptr %[[VAL_1]], i32 0, i32 0 +// CHECK: store ptr %[[VAL_3]], ptr %[[VAL_7]], align 8 +// CHECK: %[[VAL_8:.*]] = getelementptr inbounds [1 x ptr], ptr %[[VAL_2]], i64 0, i64 0 +// CHECK: store ptr null, ptr %[[VAL_8]], align 8 +// CHECK: %[[VAL_9:.*]] = getelementptr inbounds [1 x ptr], ptr %[[VAL_0]], i32 0, i32 0 +// CHECK: %[[VAL_10:.*]] = getelementptr inbounds [1 x ptr], ptr %[[VAL_1]], i32 0, i32 0 +// CHECK: call void @__tgt_target_data_begin_mapper(ptr @2, i64 -1, i32 1, ptr %[[VAL_9]], ptr %[[VAL_10]], ptr @.offload_sizes, ptr @.offload_maptypes, ptr @.offload_mapnames, ptr null) +// CHECK: %[[VAL_11:.*]] = load ptr, ptr %[[VAL_6]], align 8 +// CHECK: %[[VAL_12:.*]] = load ptr, ptr %[[VAL_11]], align 8 +// CHECK: store i32 10, ptr %[[VAL_12]], align 4 +// CHECK: %[[VAL_13:.*]] = getelementptr inbounds [1 x ptr], ptr %[[VAL_0]], i32 0, i32 0 +// CHECK: %[[VAL_14:.*]] = getelementptr inbounds [1 x ptr], ptr %[[VAL_1]], i32 0, i32 0 +// CHECK: call void @__tgt_target_data_end_mapper(ptr @2, i64 -1, i32 1, ptr %[[VAL_13]], ptr %[[VAL_14]], ptr @.offload_sizes, ptr @.offload_maptypes, ptr @.offload_mapnames, ptr null) +// CHECK: ret void + +// ----- + +llvm.func @_QPopenmp_target_use_dev_addr_no_ptr() { + %0 = llvm.mlir.constant(1 : i64) : i64 + %a = llvm.alloca %0 x !llvm.ptr : (i64) -> !llvm.ptr + omp.target_data map((tofrom -> %a : !llvm.ptr)) use_device_addr(%a : !llvm.ptr) { + ^bb0(%arg0: !llvm.ptr): + %1 = llvm.mlir.constant(10 : i32) : i32 + llvm.store %1, %arg0 : !llvm.ptr + omp.terminator + } + llvm.return +} + +// CHECK: @.offload_sizes = private unnamed_addr constant [1 x i64] [i64 4] +// CHECK: @.offload_maptypes = private unnamed_addr constant [1 x i64] [i64 67] +// CHECK-LABEL: define void @_QPopenmp_target_use_dev_addr_no_ptr +// CHECK: %[[VAL_0:.*]] = alloca [1 x ptr], align 8 +// CHECK: %[[VAL_1:.*]] = alloca [1 x ptr], align 8 +// CHECK: %[[VAL_2:.*]] = alloca [1 x ptr], align 8 +// CHECK: %[[VAL_3:.*]] = alloca i32, i64 1, align 4 +// CHECK: br label %[[VAL_4:.*]] +// CHECK: entry: ; preds = %[[VAL_5:.*]] +// CHECK: %[[VAL_6:.*]] = getelementptr inbounds [1 x ptr], ptr %[[VAL_0]], i32 0, i32 0 +// CHECK: store ptr %[[VAL_3]], ptr %[[VAL_6]], align 8 +// CHECK: %[[VAL_7:.*]] = getelementptr inbounds [1 x ptr], ptr %[[VAL_1]], i32 0, i32 0 +// CHECK: store ptr %[[VAL_3]], ptr %[[VAL_7]], align 8 +// CHECK: %[[VAL_8:.*]] = getelementptr inbounds [1 x ptr], ptr %[[VAL_2]], i64 0, i64 0 +// CHECK: store ptr null, ptr %[[VAL_8]], align 8 +// CHECK: %[[VAL_9:.*]] = getelementptr inbounds [1 x ptr], ptr %[[VAL_0]], i32 0, i32 0 +// CHECK: %[[VAL_10:.*]] = getelementptr inbounds [1 x ptr], ptr %[[VAL_1]], i32 0, i32 0 +// CHECK: call void @__tgt_target_data_begin_mapper(ptr @2, i64 -1, i32 1, ptr %[[VAL_9]], ptr %[[VAL_10]], ptr @.offload_sizes, ptr @.offload_maptypes, ptr @.offload_mapnames, ptr null) +// CHECK: %[[VAL_11:.*]] = load ptr, ptr %[[VAL_6]], align 8 +// CHECK: store i32 10, ptr %[[VAL_11]], align 4 +// CHECK: %[[VAL_12:.*]] = getelementptr inbounds [1 x ptr], ptr %[[VAL_0]], i32 0, i32 0 +// CHECK: %[[VAL_13:.*]] = getelementptr inbounds [1 x ptr], ptr %[[VAL_1]], i32 0, i32 0 +// CHECK: call void @__tgt_target_data_end_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: ret void + +// ----- + +llvm.func @_QPopenmp_target_use_dev_addr_nomap() { + %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 map((from -> %b : !llvm.ptr>)) use_device_addr(%a : !llvm.ptr>) { + ^bb0(%arg0: !llvm.ptr>): + %2 = llvm.mlir.constant(10 : i32) : i32 + %3 = llvm.load %arg0 : !llvm.ptr> + llvm.store %2, %3 : !llvm.ptr + %4 = llvm.mlir.constant(20 : i32) : i32 + %5 = llvm.load %b : !llvm.ptr> + llvm.store %4, %5 : !llvm.ptr + omp.terminator + } + llvm.return +} + +// CHECK: @.offload_sizes = private unnamed_addr constant [2 x i64] [i64 8, i64 0] +// CHECK: @.offload_maptypes = private unnamed_addr constant [2 x i64] [i64 2, i64 64] +// CHECK-LABEL: define void @_QPopenmp_target_use_dev_addr_nomap +// CHECK: %[[VAL_0:.*]] = alloca [2 x ptr], align 8 +// CHECK: %[[VAL_1:.*]] = alloca [2 x ptr], align 8 +// CHECK: %[[VAL_2:.*]] = alloca [2 x ptr], align 8 +// CHECK: %[[VAL_3:.*]] = alloca ptr, i64 1, align 8 +// CHECK: %[[VAL_4:.*]] = alloca ptr, i64 1, align 8 +// CHECK: br label %[[VAL_5:.*]] +// CHECK: entry: ; preds = %[[VAL_6:.*]] +// CHECK: %[[VAL_7:.*]] = getelementptr inbounds [2 x ptr], ptr %[[VAL_0]], i32 0, i32 0 +// CHECK: store ptr %[[VAL_4]], ptr %[[VAL_7]], align 8 +// CHECK: %[[VAL_8:.*]] = getelementptr inbounds [2 x ptr], ptr %[[VAL_1]], i32 0, i32 0 +// CHECK: store ptr %[[VAL_4]], ptr %[[VAL_8]], align 8 +// CHECK: %[[VAL_9:.*]] = getelementptr inbounds [2 x ptr], ptr %[[VAL_2]], i64 0, i64 0 +// CHECK: store ptr null, ptr %[[VAL_9]], align 8 +// CHECK: %[[VAL_10:.*]] = getelementptr inbounds [2 x ptr], ptr %[[VAL_0]], i32 0, i32 1 +// CHECK: store ptr %[[VAL_3]], ptr %[[VAL_10]], align 8 +// CHECK: %[[VAL_11:.*]] = getelementptr inbounds [2 x ptr], ptr %[[VAL_1]], i32 0, i32 1 +// CHECK: store ptr %[[VAL_3]], ptr %[[VAL_11]], align 8 +// CHECK: %[[VAL_12:.*]] = getelementptr inbounds [2 x ptr], ptr %[[VAL_2]], i64 0, i64 1 +// CHECK: store ptr null, ptr %[[VAL_12]], align 8 +// CHECK: %[[VAL_13:.*]] = getelementptr inbounds [2 x ptr], ptr %[[VAL_0]], i32 0, i32 0 +// CHECK: %[[VAL_14:.*]] = getelementptr inbounds [2 x ptr], ptr %[[VAL_1]], i32 0, i32 0 +// CHECK: call void @__tgt_target_data_begin_mapper(ptr @3, i64 -1, i32 2, ptr %[[VAL_13]], ptr %[[VAL_14]], ptr @.offload_sizes, ptr @.offload_maptypes, ptr @.offload_mapnames, ptr null) +// CHECK: %[[VAL_15:.*]] = load ptr, ptr %[[VAL_10]], align 8 +// CHECK: %[[VAL_16:.*]] = load ptr, ptr %[[VAL_15]], align 8 +// CHECK: store i32 10, ptr %[[VAL_16]], align 4 +// CHECK: %[[VAL_17:.*]] = load ptr, ptr %[[VAL_4]], align 8 +// CHECK: store i32 20, ptr %[[VAL_17]], align 4 +// CHECK: %[[VAL_18:.*]] = getelementptr inbounds [2 x ptr], ptr %[[VAL_0]], i32 0, i32 0 +// CHECK: %[[VAL_19:.*]] = getelementptr inbounds [2 x ptr], ptr %[[VAL_1]], i32 0, i32 0 +// CHECK: call void @__tgt_target_data_end_mapper(ptr @3, i64 -1, i32 2, ptr %[[VAL_18]], ptr %[[VAL_19]], ptr @.offload_sizes, ptr @.offload_maptypes, ptr @.offload_mapnames, ptr null) +// CHECK: ret void + +// ----- + +llvm.func @_QPopenmp_target_use_dev_both() { + %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 map((tofrom -> %a : !llvm.ptr>), (tofrom -> %b : !llvm.ptr>)) use_device_ptr(%a : !llvm.ptr>) use_device_addr(%b : !llvm.ptr>) { + ^bb0(%arg0: !llvm.ptr>, %arg1: !llvm.ptr>): + %2 = llvm.mlir.constant(10 : i32) : i32 + %3 = llvm.load %arg0 : !llvm.ptr> + llvm.store %2, %3 : !llvm.ptr + %4 = llvm.mlir.constant(20 : i32) : i32 + %5 = llvm.load %arg1 : !llvm.ptr> + llvm.store %4, %5 : !llvm.ptr + omp.terminator + } + llvm.return +} + +// CHECK: @.offload_sizes = private unnamed_addr constant [2 x i64] [i64 8, i64 8] +// CHECK: @.offload_maptypes = private unnamed_addr constant [2 x i64] [i64 67, i64 67] +// CHECK-LABEL: define void @_QPopenmp_target_use_dev_both +// CHECK: %[[VAL_0:.*]] = alloca [2 x ptr], align 8 +// CHECK: %[[VAL_1:.*]] = alloca [2 x ptr], align 8 +// CHECK: %[[VAL_2:.*]] = alloca [2 x ptr], align 8 +// CHECK: %[[VAL_3:.*]] = alloca ptr, align 8 +// CHECK: %[[VAL_4:.*]] = alloca ptr, i64 1, align 8 +// CHECK: %[[VAL_5:.*]] = alloca ptr, i64 1, align 8 +// CHECK: br label %[[VAL_6:.*]] +// CHECK: entry: ; preds = %[[VAL_7:.*]] +// CHECK: %[[VAL_8:.*]] = getelementptr inbounds [2 x ptr], ptr %[[VAL_0]], i32 0, i32 0 +// CHECK: store ptr %[[VAL_4]], ptr %[[VAL_8]], align 8 +// CHECK: %[[VAL_9:.*]] = getelementptr inbounds [2 x ptr], ptr %[[VAL_1]], i32 0, i32 0 +// CHECK: store ptr %[[VAL_4]], ptr %[[VAL_9]], align 8 +// CHECK: %[[VAL_10:.*]] = getelementptr inbounds [2 x ptr], ptr %[[VAL_2]], i64 0, i64 0 +// CHECK: store ptr null, ptr %[[VAL_10]], align 8 +// CHECK: %[[VAL_11:.*]] = getelementptr inbounds [2 x ptr], ptr %[[VAL_0]], i32 0, i32 1 +// CHECK: store ptr %[[VAL_5]], ptr %[[VAL_11]], align 8 +// CHECK: %[[VAL_12:.*]] = getelementptr inbounds [2 x ptr], ptr %[[VAL_1]], i32 0, i32 1 +// CHECK: store ptr %[[VAL_5]], ptr %[[VAL_12]], align 8 +// CHECK: %[[VAL_13:.*]] = getelementptr inbounds [2 x ptr], ptr %[[VAL_2]], i64 0, i64 1 +// CHECK: store ptr null, ptr %[[VAL_13]], align 8 +// CHECK: %[[VAL_14:.*]] = getelementptr inbounds [2 x ptr], ptr %[[VAL_0]], i32 0, i32 0 +// CHECK: %[[VAL_15:.*]] = getelementptr inbounds [2 x ptr], ptr %[[VAL_1]], i32 0, i32 0 +// CHECK: call void @__tgt_target_data_begin_mapper(ptr @3, i64 -1, i32 2, ptr %[[VAL_14]], ptr %[[VAL_15]], ptr @.offload_sizes, ptr @.offload_maptypes, ptr @.offload_mapnames, ptr null) +// CHECK: %[[VAL_16:.*]] = load ptr, ptr %[[VAL_8]], align 8 +// CHECK: store ptr %[[VAL_16]], ptr %[[VAL_3]], align 8 +// CHECK: %[[VAL_17:.*]] = load ptr, ptr %[[VAL_11]], align 8 +// CHECK: %[[VAL_18:.*]] = load ptr, ptr %[[VAL_3]], align 8 +// CHECK: store i32 10, ptr %[[VAL_18]], align 4 +// CHECK: %[[VAL_19:.*]] = load ptr, ptr %[[VAL_17]], align 8 +// CHECK: store i32 20, ptr %[[VAL_19]], align 4 +// CHECK: %[[VAL_20:.*]] = getelementptr inbounds [2 x ptr], ptr %[[VAL_0]], i32 0, i32 0 +// CHECK: %[[VAL_21:.*]] = getelementptr inbounds [2 x ptr], ptr %[[VAL_1]], i32 0, i32 0 +// CHECK: call void @__tgt_target_data_end_mapper(ptr @3, i64 -1, i32 2, ptr %[[VAL_20]], ptr %[[VAL_21]], ptr @.offload_sizes, ptr @.offload_maptypes, ptr @.offload_mapnames, ptr null) +// CHECK: ret void + +// -----