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 @@ -1478,6 +1478,25 @@ /// Computes the size of type in bytes. Value *getSizeInBytes(Value *BasePtr); + // Emit a branch from the current block to the Target block only if + // the current block has a terminator. + void emitBranch(BasicBlock *Target); + + // If BB has no use then delete it and return. Else place BB after the current + // block, if possible, or else at the end of the function. Also add a branch + // from current block to BB if current block does not have a terminator. + void emitBlock(BasicBlock *BB, Function *CurFn, bool IsFinished = false); + + /// Emits code for OpenMP 'if' clause using specified \a BodyGenCallbackTy + /// Here is the logic: + /// if (Cond) { + /// ThenGen(); + /// } else { + /// ElseGen(); + /// } + void emitIfClause(Value *Cond, BodyGenCallbackTy ThenGen, + BodyGenCallbackTy ElseGen, InsertPointTy AllocaIP = {}); + /// Create the global variable holding the offload mappings information. GlobalVariable *createOffloadMaptypes(SmallVectorImpl &Mappings, std::string VarName); @@ -1987,29 +2006,41 @@ StringRef EntryFnName, StringRef EntryFnIDName, int32_t NumTeams, int32_t NumThreads); + /// Type of BodyGen to use for region codegen + /// + /// Priv: If device pointer privatization is required, emit the body of the + /// region here. It will have to be duplicated: with and without + /// privatization. + /// DupNoPriv: If we need device pointer privatization, we need + /// to emit the body of the region with no privatization in the 'else' branch + /// of the conditional. + /// NoPriv: If we don't require privatization of device + /// pointers, we emit the body in between the runtime calls. This avoids + /// duplicating the body code. + enum BodyGenTy { Priv, DupNoPriv, NoPriv }; /// Generator for '#omp target data' /// /// \param Loc The location where the target data construct was encountered. + /// \param AllocaIP The insertion points to be used for alloca instructions. /// \param CodeGenIP The insertion point at which the target directive code /// should be placed. - /// \param MapTypeFlags BitVector storing the mapType flags for the - /// mapOperands. - /// \param MapNames Names for the mapOperands. - /// \param MapperAllocas Pointers to the AllocInsts for the map clause. /// \param IsBegin If true then emits begin mapper call otherwise emits /// end mapper call. /// \param DeviceID Stores the DeviceID from the device clause. /// \param IfCond Value which corresponds to the if clause condition. - /// \param ProcessMapOpCB Callback that generates code for the map clause. - /// \param BodyGenCB Callback that will generate the region code. + /// \param Info Stores all information realted to the Target Data directive. + /// \param GenMapInfoCB Callback that populates the MapInfos and returns. + /// \param BodyGenCB Optional Callback to generate the region code. OpenMPIRBuilder::InsertPointTy createTargetData( - const LocationDescription &Loc, OpenMPIRBuilder::InsertPointTy CodeGenIP, - SmallVectorImpl &MapTypeFlags, - SmallVectorImpl &MapNames, - struct MapperAllocas &MapperAllocas, bool IsBegin, int64_t DeviceID, - Value *IfCond, BodyGenCallbackTy ProcessMapOpCB, - BodyGenCallbackTy BodyGenCB = {}); + const LocationDescription &Loc, InsertPointTy AllocaIP, + InsertPointTy CodeGenIP, Value *DeviceID, Value *IfCond, + TargetDataInfo &Info, + function_ref GenMapInfoCB, + omp::RuntimeFunction *MapperFunc = nullptr, + function_ref + BodyGenCB = nullptr); using TargetBodyGenCallbackTy = function_ref; 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 @@ -4078,73 +4078,121 @@ } OpenMPIRBuilder::InsertPointTy OpenMPIRBuilder::createTargetData( - const LocationDescription &Loc, OpenMPIRBuilder::InsertPointTy CodeGenIP, - SmallVectorImpl &MapTypeFlags, - SmallVectorImpl &MapNames, struct MapperAllocas &MapperAllocas, - bool IsBegin, int64_t DeviceID, Value *IfCond, - BodyGenCallbackTy ProcessMapOpCB, BodyGenCallbackTy BodyGenCB) { + const LocationDescription &Loc, InsertPointTy AllocaIP, + InsertPointTy CodeGenIP, Value *DeviceID, Value *IfCond, + TargetDataInfo &Info, + function_ref GenMapInfoCB, + omp::RuntimeFunction *MapperFunc, + function_ref + BodyGenCB) { if (!updateToLocation(Loc)) return InsertPointTy(); Builder.restoreIP(CodeGenIP); + bool IsStandAlone = !BodyGenCB; - // LLVM utilities like blocks with terminators. - // The UI acts as a resume point for code insertion after the BodyGen - auto *UI = Builder.CreateUnreachable(); - if (IfCond) { - auto *ThenTI = - SplitBlockAndInsertIfThen(IfCond, UI, /* Unreachable */ false); - ThenTI->getParent()->setName("omp_if.then"); - Builder.SetInsertPoint(ThenTI); - } else { - Builder.SetInsertPoint(UI); - } + // Generate the code for the opening of the data environment. Capture all the + // arguments of the runtime call by reference because they are used in the + // closing of the region. + auto BeginThenGen = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP) { + emitOffloadingArrays(AllocaIP, Builder.saveIP(), + GenMapInfoCB(Builder.saveIP()), Info, + /*IsNonContiguous=*/true); - ProcessMapOpCB(Builder.saveIP(), Builder.saveIP()); + TargetDataRTArgs RTArgs; + emitOffloadingArraysArgument(Builder, RTArgs, Info); - uint32_t SrcLocStrSize; - Constant *SrcLocStr = getOrCreateSrcLocStr(Loc, SrcLocStrSize); - Value *srcLocInfo = getOrCreateIdent(SrcLocStr, SrcLocStrSize); + // Emit the number of elements in the offloading arrays. + Value *PointerNum = Builder.getInt32(Info.NumberOfPtrs); - GlobalVariable *MapTypesGV = - createOffloadMaptypes(MapTypeFlags, ".offload_maptypes"); - Value *MapTypesArg = Builder.CreateConstInBoundsGEP2_32( - ArrayType::get(Builder.getInt64Ty(), MapTypeFlags.size()), MapTypesGV, - /*Idx0=*/0, /*Idx1=*/0); + // Source location for the ident struct + uint32_t SrcLocStrSize; + Constant *SrcLocStr = getOrCreateSrcLocStr(Loc, SrcLocStrSize); + Value *SrcLocInfo = getOrCreateIdent(SrcLocStr, SrcLocStrSize); + + Value *OffloadingArgs[] = {SrcLocInfo, DeviceID, + PointerNum, RTArgs.BasePointersArray, + RTArgs.PointersArray, RTArgs.SizesArray, + RTArgs.MapTypesArray, RTArgs.MapNamesArray, + RTArgs.MappersArray}; + + if (IsStandAlone) { + assert(MapperFunc && "MapperFunc missing for standalone target data"); + Builder.CreateCall(getOrCreateRuntimeFunctionPtr(*MapperFunc), + OffloadingArgs); + } else { + Function *BeginMapperFunc = getOrCreateRuntimeFunctionPtr( + omp::OMPRTL___tgt_target_data_begin_mapper); - GlobalVariable *MapNamesGV = - createOffloadMapnames(MapNames, ".offload_mapnames"); - Value *MapNamesArg = Builder.CreateConstInBoundsGEP2_32( - ArrayType::get(Builder.getInt8PtrTy(), MapNames.size()), MapNamesGV, - /*Idx0=*/0, /*Idx1=*/0); + Builder.CreateCall(BeginMapperFunc, OffloadingArgs); + + // If device pointer privatization is required, emit the body of the + // region here. It will have to be duplicated: with and without + // privatization. + Builder.restoreIP(BodyGenCB(Builder.saveIP(), BodyGenTy::Priv)); + } + }; + + // If we need device pointer privatization, we need to emit the body of the + // region with no privatization in the 'else' branch of the conditional. + // Otherwise, we don't have to do anything. + auto BeginElseGen = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP) { + Builder.restoreIP(BodyGenCB(Builder.saveIP(), BodyGenTy::DupNoPriv)); + }; + + // Generate code for the closing of the data region. + auto EndThenGen = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP) { + TargetDataRTArgs RTArgs; + emitOffloadingArraysArgument(Builder, RTArgs, Info, /*EmitDebug=*/false, + /*ForEndCall=*/true); + + // Emit the number of elements in the offloading arrays. + Value *PointerNum = Builder.getInt32(Info.NumberOfPtrs); + + // Source location for the ident struct + uint32_t SrcLocStrSize; + Constant *SrcLocStr = getOrCreateSrcLocStr(Loc, SrcLocStrSize); + Value *SrcLocInfo = getOrCreateIdent(SrcLocStr, SrcLocStrSize); + + Value *OffloadingArgs[] = {SrcLocInfo, DeviceID, + PointerNum, RTArgs.BasePointersArray, + RTArgs.PointersArray, RTArgs.SizesArray, + RTArgs.MapTypesArray, RTArgs.MapNamesArray, + RTArgs.MappersArray}; + Function *EndMapperFunc = + getOrCreateRuntimeFunctionPtr(omp::OMPRTL___tgt_target_data_end_mapper); + + Builder.CreateCall(EndMapperFunc, OffloadingArgs); + }; - Function *beginMapperFunc = - getOrCreateRuntimeFunctionPtr(omp::OMPRTL___tgt_target_data_begin_mapper); - Function *endMapperFunc = - getOrCreateRuntimeFunctionPtr(omp::OMPRTL___tgt_target_data_end_mapper); + // We don't have to do anything to close the region if the if clause evaluates + // to false. + auto EndElseGen = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP) {}; if (BodyGenCB) { - // Create call to start the data region. - emitMapperCall(Builder.saveIP(), beginMapperFunc, srcLocInfo, MapTypesArg, - MapNamesArg, MapperAllocas, DeviceID, MapTypeFlags.size()); + if (IfCond) { + emitIfClause(IfCond, BeginThenGen, BeginElseGen, AllocaIP); + } else { + BeginThenGen(AllocaIP, Builder.saveIP()); + } - BodyGenCB(Builder.saveIP(), Builder.saveIP()); + // If we don't require privatization of device pointers, we emit the body in + // between the runtime calls. This avoids duplicating the body code. + Builder.restoreIP(BodyGenCB(Builder.saveIP(), BodyGenTy::NoPriv)); - Builder.SetInsertPoint(UI->getParent()); - // Create call to end the data region. - emitMapperCall(Builder.saveIP(), endMapperFunc, srcLocInfo, MapTypesArg, - MapNamesArg, MapperAllocas, DeviceID, MapTypeFlags.size()); + if (IfCond) { + emitIfClause(IfCond, EndThenGen, EndElseGen, AllocaIP); + } else { + EndThenGen(AllocaIP, Builder.saveIP()); + } } else { - emitMapperCall(Builder.saveIP(), IsBegin ? beginMapperFunc : endMapperFunc, - srcLocInfo, MapTypesArg, MapNamesArg, MapperAllocas, - DeviceID, MapTypeFlags.size()); + if (IfCond) { + emitIfClause(IfCond, BeginThenGen, EndElseGen, AllocaIP); + } else { + BeginThenGen(AllocaIP, Builder.saveIP()); + } } - // Update the insertion point and remove the terminator we introduced. - Builder.SetInsertPoint(UI->getParent()); - if (IfCond) - UI->getParent()->setName("omp_if.end"); - UI->eraseFromParent(); return Builder.saveIP(); } @@ -4668,6 +4716,77 @@ emitNonContiguousDescriptor(AllocaIP, CodeGenIP, CombinedInfo, Info); } +void OpenMPIRBuilder::emitBranch(BasicBlock *Target) { + BasicBlock *CurBB = Builder.GetInsertBlock(); + + if (!CurBB || CurBB->getTerminator()) { + // If there is no insert point or the previous block is already + // terminated, don't touch it. + } else { + // Otherwise, create a fall-through branch. + Builder.CreateBr(Target); + } + + Builder.ClearInsertionPoint(); +} + +void OpenMPIRBuilder::emitBlock(BasicBlock *BB, Function *CurFn, + bool IsFinished) { + BasicBlock *CurBB = Builder.GetInsertBlock(); + + // Fall out of the current block (if necessary). + emitBranch(BB); + + if (IsFinished && BB->use_empty()) { + BB->eraseFromParent(); + return; + } + + // Place the block after the current block, if possible, or else at + // the end of the function. + if (CurBB && CurBB->getParent()) + CurFn->insert(std::next(CurBB->getIterator()), BB); + else + CurFn->insert(CurFn->end(), BB); + Builder.SetInsertPoint(BB); +} + +void OpenMPIRBuilder::emitIfClause(Value *Cond, BodyGenCallbackTy ThenGen, + BodyGenCallbackTy ElseGen, + InsertPointTy AllocaIP) { + // If the condition constant folds and can be elided, try to avoid emitting + // the condition and the dead arm of the if/else. + if (auto *CI = dyn_cast(Cond)) { + auto CondConstant = CI->getSExtValue(); + if (CondConstant) + ThenGen(AllocaIP, Builder.saveIP()); + else + ElseGen(AllocaIP, Builder.saveIP()); + return; + } + + Function *CurFn = Builder.GetInsertBlock()->getParent(); + + // Otherwise, the condition did not fold, or we couldn't elide it. Just + // emit the conditional branch. + BasicBlock *ThenBlock = BasicBlock::Create(M.getContext(), "omp_if.then"); + BasicBlock *ElseBlock = BasicBlock::Create(M.getContext(), "omp_if.else"); + BasicBlock *ContBlock = BasicBlock::Create(M.getContext(), "omp_if.end"); + Builder.CreateCondBr(Cond, ThenBlock, ElseBlock); + // Emit the 'then' code. + emitBlock(ThenBlock, CurFn); + ThenGen(AllocaIP, Builder.saveIP()); + emitBranch(ContBlock); + // Emit the 'else' code if present. + // There is no need to emit line number for unconditional branch. + emitBlock(ElseBlock, CurFn); + ElseGen(AllocaIP, Builder.saveIP()); + // There is no need to emit line number for unconditional branch. + emitBranch(ContBlock); + // Emit the continuation block for code after the if. + emitBlock(ContBlock, CurFn, /*IsFinished=*/true); +} + bool OpenMPIRBuilder::checkAndEmitFlushAfterAtomic( const LocationDescription &Loc, llvm::AtomicOrdering AO, AtomicKind AK) { assert(!(AO == AtomicOrdering::NotAtomic || 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 @@ -4886,18 +4886,9 @@ OMPBuilder.initialize(); F->setName("func"); IRBuilder<> Builder(BB); - OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL}); - unsigned NumDataOperands = 1; int64_t DeviceID = 2; - struct OpenMPIRBuilder::MapperAllocas MapperAllocas; - SmallVector MapTypeFlagsTo = {1}; - SmallVector MapNames; - auto *I8PtrTy = Builder.getInt8PtrTy(); - auto *ArrI8PtrTy = ArrayType::get(I8PtrTy, NumDataOperands); - auto *I64Ty = Builder.getInt64Ty(); - auto *ArrI64Ty = ArrayType::get(I64Ty, NumDataOperands); AllocaInst *Val1 = Builder.CreateAlloca(Builder.getInt32Ty(), Builder.getInt64(1)); @@ -4905,44 +4896,34 @@ IRBuilder<>::InsertPoint AllocaIP(&F->getEntryBlock(), F->getEntryBlock().getFirstInsertionPt()); - OMPBuilder.createMapperAllocas(Builder.saveIP(), AllocaIP, NumDataOperands, - MapperAllocas); + llvm::OpenMPIRBuilder::MapInfosTy CombinedInfo; using InsertPointTy = OpenMPIRBuilder::InsertPointTy; - auto ProcessMapOpCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP) { - Value *DataValue = Val1; - Value *DataPtrBase; - Value *DataPtr; - DataPtrBase = DataValue; - DataPtr = DataValue; - Builder.restoreIP(CodeGenIP); + auto GenMapInfoCB = + [&](InsertPointTy codeGenIP) -> llvm::OpenMPIRBuilder::MapInfosTy & { + // Get map clause information. + Builder.restoreIP(codeGenIP); - Value *Null = Constant::getNullValue(DataValue->getType()->getPointerTo()); - Value *SizeGep = - Builder.CreateGEP(DataValue->getType(), Null, Builder.getInt32(1)); - Value *SizePtrToInt = Builder.CreatePtrToInt(SizeGep, I64Ty); - - Value *PtrBaseGEP = - Builder.CreateInBoundsGEP(ArrI8PtrTy, MapperAllocas.ArgsBase, - {Builder.getInt32(0), Builder.getInt32(0)}); - Value *PtrBaseCast = Builder.CreateBitCast( - PtrBaseGEP, DataPtrBase->getType()->getPointerTo()); - Builder.CreateStore(DataPtrBase, PtrBaseCast); - Value *PtrGEP = - Builder.CreateInBoundsGEP(ArrI8PtrTy, MapperAllocas.Args, - {Builder.getInt32(0), Builder.getInt32(0)}); - Value *PtrCast = - Builder.CreateBitCast(PtrGEP, DataPtr->getType()->getPointerTo()); - Builder.CreateStore(DataPtr, PtrCast); - Value *SizeGEP = - Builder.CreateInBoundsGEP(ArrI64Ty, MapperAllocas.ArgSizes, - {Builder.getInt32(0), Builder.getInt32(0)}); - Builder.CreateStore(SizePtrToInt, SizeGEP); + CombinedInfo.BasePointers.emplace_back(Val1); + CombinedInfo.Pointers.emplace_back(Val1); + CombinedInfo.Sizes.emplace_back(Builder.getInt64(4)); + CombinedInfo.Types.emplace_back(llvm::omp::OpenMPOffloadMappingFlags(1)); + uint32_t temp; + CombinedInfo.Names.emplace_back( + OMPBuilder.getOrCreateSrcLocStr("unknown", temp)); + return CombinedInfo; }; + llvm::OpenMPIRBuilder::TargetDataInfo Info( + /*RequiresDevicePointerInfo=*/false, + /*SeparateBeginEndCalls=*/true); + + OMPBuilder.Config.setIsTargetCodegen(true); + + llvm::omp::RuntimeFunction RTLFunc = OMPRTL___tgt_target_data_begin_mapper; Builder.restoreIP(OMPBuilder.createTargetData( - Loc, Builder.saveIP(), MapTypeFlagsTo, MapNames, MapperAllocas, - /* IsBegin= */ true, DeviceID, /* IfCond= */ nullptr, ProcessMapOpCB)); + Loc, AllocaIP, Builder.saveIP(), Builder.getInt64(DeviceID), + /* IfCond= */ nullptr, Info, GenMapInfoCB, &RTLFunc)); CallInst *TargetDataCall = dyn_cast(&BB->back()); EXPECT_NE(TargetDataCall, nullptr); @@ -4962,18 +4943,9 @@ OMPBuilder.initialize(); F->setName("func"); IRBuilder<> Builder(BB); - OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL}); - unsigned NumDataOperands = 1; int64_t DeviceID = 2; - struct OpenMPIRBuilder::MapperAllocas MapperAllocas; - SmallVector MapTypeFlagsFrom = {2}; - SmallVector MapNames; - auto *I8PtrTy = Builder.getInt8PtrTy(); - auto *ArrI8PtrTy = ArrayType::get(I8PtrTy, NumDataOperands); - auto *I64Ty = Builder.getInt64Ty(); - auto *ArrI64Ty = ArrayType::get(I64Ty, NumDataOperands); AllocaInst *Val1 = Builder.CreateAlloca(Builder.getInt32Ty(), Builder.getInt64(1)); @@ -4981,44 +4953,34 @@ IRBuilder<>::InsertPoint AllocaIP(&F->getEntryBlock(), F->getEntryBlock().getFirstInsertionPt()); - OMPBuilder.createMapperAllocas(Builder.saveIP(), AllocaIP, NumDataOperands, - MapperAllocas); + llvm::OpenMPIRBuilder::MapInfosTy CombinedInfo; using InsertPointTy = OpenMPIRBuilder::InsertPointTy; - auto ProcessMapOpCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP) { - Value *DataValue = Val1; - Value *DataPtrBase; - Value *DataPtr; - DataPtrBase = DataValue; - DataPtr = DataValue; - Builder.restoreIP(CodeGenIP); + auto GenMapInfoCB = + [&](InsertPointTy codeGenIP) -> llvm::OpenMPIRBuilder::MapInfosTy & { + // Get map clause information. + Builder.restoreIP(codeGenIP); - Value *Null = Constant::getNullValue(DataValue->getType()->getPointerTo()); - Value *SizeGep = - Builder.CreateGEP(DataValue->getType(), Null, Builder.getInt32(1)); - Value *SizePtrToInt = Builder.CreatePtrToInt(SizeGep, I64Ty); - - Value *PtrBaseGEP = - Builder.CreateInBoundsGEP(ArrI8PtrTy, MapperAllocas.ArgsBase, - {Builder.getInt32(0), Builder.getInt32(0)}); - Value *PtrBaseCast = Builder.CreateBitCast( - PtrBaseGEP, DataPtrBase->getType()->getPointerTo()); - Builder.CreateStore(DataPtrBase, PtrBaseCast); - Value *PtrGEP = - Builder.CreateInBoundsGEP(ArrI8PtrTy, MapperAllocas.Args, - {Builder.getInt32(0), Builder.getInt32(0)}); - Value *PtrCast = - Builder.CreateBitCast(PtrGEP, DataPtr->getType()->getPointerTo()); - Builder.CreateStore(DataPtr, PtrCast); - Value *SizeGEP = - Builder.CreateInBoundsGEP(ArrI64Ty, MapperAllocas.ArgSizes, - {Builder.getInt32(0), Builder.getInt32(0)}); - Builder.CreateStore(SizePtrToInt, SizeGEP); + CombinedInfo.BasePointers.emplace_back(Val1); + CombinedInfo.Pointers.emplace_back(Val1); + CombinedInfo.Sizes.emplace_back(Builder.getInt64(4)); + CombinedInfo.Types.emplace_back(llvm::omp::OpenMPOffloadMappingFlags(2)); + uint32_t temp; + CombinedInfo.Names.emplace_back( + OMPBuilder.getOrCreateSrcLocStr("unknown", temp)); + return CombinedInfo; }; + llvm::OpenMPIRBuilder::TargetDataInfo Info( + /*RequiresDevicePointerInfo=*/false, + /*SeparateBeginEndCalls=*/true); + + OMPBuilder.Config.setIsTargetCodegen(true); + + llvm::omp::RuntimeFunction RTLFunc = OMPRTL___tgt_target_data_end_mapper; Builder.restoreIP(OMPBuilder.createTargetData( - Loc, Builder.saveIP(), MapTypeFlagsFrom, MapNames, MapperAllocas, - /* IsBegin= */ false, DeviceID, /* IfCond= */ nullptr, ProcessMapOpCB)); + Loc, AllocaIP, Builder.saveIP(), Builder.getInt64(DeviceID), + /* IfCond= */ nullptr, Info, GenMapInfoCB, &RTLFunc)); CallInst *TargetDataCall = dyn_cast(&BB->back()); EXPECT_NE(TargetDataCall, nullptr); @@ -5038,18 +5000,9 @@ OMPBuilder.initialize(); F->setName("func"); IRBuilder<> Builder(BB); - OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL}); - unsigned NumDataOperands = 1; int64_t DeviceID = 2; - struct OpenMPIRBuilder::MapperAllocas MapperAllocas; - SmallVector MapTypeFlagsToFrom = {3}; - SmallVector MapNames; - auto *I8PtrTy = Builder.getInt8PtrTy(); - auto *ArrI8PtrTy = ArrayType::get(I8PtrTy, NumDataOperands); - auto *I64Ty = Builder.getInt64Ty(); - auto *ArrI64Ty = ArrayType::get(I64Ty, NumDataOperands); AllocaInst *Val1 = Builder.CreateAlloca(Builder.getInt32Ty(), Builder.getInt64(1)); @@ -5057,57 +5010,52 @@ IRBuilder<>::InsertPoint AllocaIP(&F->getEntryBlock(), F->getEntryBlock().getFirstInsertionPt()); - OMPBuilder.createMapperAllocas(Builder.saveIP(), AllocaIP, NumDataOperands, - MapperAllocas); + llvm::OpenMPIRBuilder::MapInfosTy CombinedInfo; using InsertPointTy = OpenMPIRBuilder::InsertPointTy; - auto ProcessMapOpCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP) { - Value *DataValue = Val1; - Value *DataPtrBase; - Value *DataPtr; - DataPtrBase = DataValue; - DataPtr = DataValue; - Builder.restoreIP(CodeGenIP); + auto GenMapInfoCB = + [&](InsertPointTy codeGenIP) -> llvm::OpenMPIRBuilder::MapInfosTy & { + // Get map clause information. + Builder.restoreIP(codeGenIP); - Value *Null = Constant::getNullValue(DataValue->getType()->getPointerTo()); - Value *SizeGep = - Builder.CreateGEP(DataValue->getType(), Null, Builder.getInt32(1)); - Value *SizePtrToInt = Builder.CreatePtrToInt(SizeGep, I64Ty); - - Value *PtrBaseGEP = - Builder.CreateInBoundsGEP(ArrI8PtrTy, MapperAllocas.ArgsBase, - {Builder.getInt32(0), Builder.getInt32(0)}); - Value *PtrBaseCast = Builder.CreateBitCast( - PtrBaseGEP, DataPtrBase->getType()->getPointerTo()); - Builder.CreateStore(DataPtrBase, PtrBaseCast); - Value *PtrGEP = - Builder.CreateInBoundsGEP(ArrI8PtrTy, MapperAllocas.Args, - {Builder.getInt32(0), Builder.getInt32(0)}); - Value *PtrCast = - Builder.CreateBitCast(PtrGEP, DataPtr->getType()->getPointerTo()); - Builder.CreateStore(DataPtr, PtrCast); - Value *SizeGEP = - Builder.CreateInBoundsGEP(ArrI64Ty, MapperAllocas.ArgSizes, - {Builder.getInt32(0), Builder.getInt32(0)}); - Builder.CreateStore(SizePtrToInt, SizeGEP); + CombinedInfo.BasePointers.emplace_back(Val1); + CombinedInfo.Pointers.emplace_back(Val1); + 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)); + return CombinedInfo; }; - auto BodyCB = [&](InsertPointTy allocaIP, InsertPointTy codeGenIP) { - Builder.restoreIP(codeGenIP); - auto *SI = Builder.CreateStore(Builder.getInt32(99), Val1); - auto *newBB = SplitBlock(Builder.GetInsertBlock(), SI); - Builder.SetInsertPoint(newBB); - auto *UI = &Builder.GetInsertBlock()->back(); - SplitBlock(Builder.GetInsertBlock(), UI); + llvm::OpenMPIRBuilder::TargetDataInfo Info( + /*RequiresDevicePointerInfo=*/false, + /*SeparateBeginEndCalls=*/true); + + OMPBuilder.Config.setIsTargetCodegen(true); + + auto BodyCB = [&](InsertPointTy CodeGenIP, int BodyGenType) { + if (BodyGenType == 3) { + Builder.restoreIP(CodeGenIP); + CallInst *TargetDataCall = dyn_cast(&BB->back()); + EXPECT_NE(TargetDataCall, nullptr); + EXPECT_EQ(TargetDataCall->arg_size(), 9U); + EXPECT_EQ(TargetDataCall->getCalledFunction()->getName(), + "__tgt_target_data_begin_mapper"); + 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); + Builder.CreateStore(Builder.getInt32(99), Val1); + } + return Builder.saveIP(); }; Builder.restoreIP(OMPBuilder.createTargetData( - Loc, Builder.saveIP(), MapTypeFlagsToFrom, MapNames, MapperAllocas, - /* IsBegin= */ false, DeviceID, /* IfCond= */ nullptr, ProcessMapOpCB, - BodyCB)); + Loc, AllocaIP, Builder.saveIP(), Builder.getInt64(DeviceID), + /* IfCond= */ nullptr, Info, GenMapInfoCB, nullptr, BodyCB)); - CallInst *TargetDataCall = - dyn_cast(&Builder.GetInsertBlock()->back()); + CallInst *TargetDataCall = dyn_cast(&BB->back()); EXPECT_NE(TargetDataCall, nullptr); EXPECT_EQ(TargetDataCall->arg_size(), 9U); EXPECT_EQ(TargetDataCall->getCalledFunction()->getName(), 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 @@ -1361,78 +1361,55 @@ return success(); } -/// Process MapOperands for Target Data directives. -static LogicalResult processMapOperand( - llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation, - const SmallVector &mapOperands, const ArrayAttr &mapTypes, - SmallVector &mapTypeFlags, - SmallVectorImpl &mapNames, - struct llvm::OpenMPIRBuilder::MapperAllocas &mapperAllocas) { - auto numMapOperands = mapOperands.size(); - llvm::OpenMPIRBuilder *ompBuilder = moduleTranslation.getOpenMPBuilder(); - llvm::PointerType *i8PtrTy = builder.getInt8PtrTy(); - llvm::ArrayType *arrI8PtrTy = llvm::ArrayType::get(i8PtrTy, numMapOperands); - llvm::IntegerType *i64Ty = builder.getInt64Ty(); - llvm::ArrayType *arrI64Ty = llvm::ArrayType::get(i64Ty, numMapOperands); +int64_t getSizeInBytes(DataLayout &DL, const mlir::Type &type) { + if (isa(type)) + return DL.getTypeSize(cast(type).getElementType()); + + return 0; +} +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. + llvm::OpenMPIRBuilder *ompBuilder = moduleTranslation.getOpenMPBuilder(); unsigned index = 0; for (const auto &mapOp : mapOperands) { - const auto &mapTypeOp = mapTypes[index]; - - llvm::Value *mapOpValue = moduleTranslation.lookupValue(mapOp); - llvm::Value *mapOpPtrBase; - llvm::Value *mapOpPtr; - llvm::Value *mapOpSize; - - if (isa(mapOp.getType())) { - mapOpPtrBase = mapOpValue; - mapOpPtr = mapOpValue; - mapOpSize = ompBuilder->getSizeInBytes(mapOpValue); - } else { - return failure(); + 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; } - // Store base pointer extracted from operand into the i-th position of - // argBase. - llvm::Value *ptrBaseGEP = builder.CreateInBoundsGEP( - arrI8PtrTy, mapperAllocas.ArgsBase, - {builder.getInt32(0), builder.getInt32(index)}); - llvm::Value *ptrBaseCast = builder.CreateBitCast( - ptrBaseGEP, mapOpPtrBase->getType()->getPointerTo()); - builder.CreateStore(mapOpPtrBase, ptrBaseCast); - - // Store pointer extracted from operand into the i-th position of args. - llvm::Value *ptrGEP = builder.CreateInBoundsGEP( - arrI8PtrTy, mapperAllocas.Args, - {builder.getInt32(0), builder.getInt32(index)}); - llvm::Value *ptrCast = - builder.CreateBitCast(ptrGEP, mapOpPtr->getType()->getPointerTo()); - builder.CreateStore(mapOpPtr, ptrCast); - - // Store size extracted from operand into the i-th position of argSizes. - llvm::Value *sizeGEP = builder.CreateInBoundsGEP( - arrI64Ty, mapperAllocas.ArgSizes, - {builder.getInt32(0), builder.getInt32(index)}); - builder.CreateStore(mapOpSize, sizeGEP); - - mapTypeFlags.push_back(dyn_cast(mapTypeOp).getInt()); - llvm::Constant *mapName = - mlir::LLVM::createMappingInformation(mapOp.getLoc(), *ompBuilder); - mapNames.push_back(mapName); - ++index; + llvm::Value *mapOpValue = moduleTranslation.lookupValue(mapOp); + combinedInfo.BasePointers.emplace_back(mapOpValue); + combinedInfo.Pointers.emplace_back(mapOpValue); + combinedInfo.Names.emplace_back( + mlir::LLVM::createMappingInformation(mapOp.getLoc(), *ompBuilder)); + combinedInfo.Types.emplace_back(llvm::omp::OpenMPOffloadMappingFlags( + mapTypes[index].dyn_cast().getInt())); + combinedInfo.Sizes.emplace_back( + builder.getInt64(getSizeInBytes(DL, mapOp.getType()))); + index++; } - - return success(); } static LogicalResult convertOmpTargetData(Operation *op, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation) { - unsigned numMapOperands; llvm::Value *ifCond = nullptr; int64_t deviceID = llvm::omp::OMP_DEVICEID_UNDEF; SmallVector mapOperands; ArrayAttr mapTypes; + llvm::omp::RuntimeFunction RTLFn; + DataLayout DL = DataLayout(op->getParentOfType()); llvm::OpenMPIRBuilder *ompBuilder = moduleTranslation.getOpenMPBuilder(); @@ -1453,7 +1430,6 @@ dyn_cast(constOp.getValue())) deviceID = intAttr.getInt(); - numMapOperands = dataOp.getMapOperands().size(); mapOperands = dataOp.getMapOperands(); mapTypes = dataOp.getMapTypes(); return success(); @@ -1471,8 +1447,7 @@ if (auto intAttr = dyn_cast(constOp.getValue())) deviceID = intAttr.getInt(); - - numMapOperands = enterDataOp.getMapOperands().size(); + RTLFn = llvm::omp::OMPRTL___tgt_target_data_begin_mapper; mapOperands = enterDataOp.getMapOperands(); mapTypes = enterDataOp.getMapTypes(); return success(); @@ -1491,7 +1466,7 @@ dyn_cast(constOp.getValue())) deviceID = intAttr.getInt(); - numMapOperands = exitDataOp.getMapOperands().size(); + RTLFn = llvm::omp::OMPRTL___tgt_target_data_end_mapper; mapOperands = exitDataOp.getMapOperands(); mapTypes = exitDataOp.getMapTypes(); return success(); @@ -1504,46 +1479,55 @@ if (failed(result)) return failure(); - llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder); - llvm::OpenMPIRBuilder::InsertPointTy allocaIP = - findAllocaInsertPoint(builder, moduleTranslation); - - struct llvm::OpenMPIRBuilder::MapperAllocas mapperAllocas; - SmallVector mapTypeFlags; - SmallVector mapNames; - ompBuilder->createMapperAllocas(builder.saveIP(), allocaIP, numMapOperands, - mapperAllocas); - using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy; - LogicalResult processMapOpStatus = success(); - auto processMapOpCB = [&](InsertPointTy allocaIP, InsertPointTy codeGenIP) { + + // Fill up the arrays with all the mapped variables. + llvm::OpenMPIRBuilder::MapInfosTy combinedInfo; + auto genMapInfoCB = + [&](InsertPointTy codeGenIP) -> llvm::OpenMPIRBuilder::MapInfosTy & { builder.restoreIP(codeGenIP); - processMapOpStatus = - processMapOperand(builder, moduleTranslation, mapOperands, mapTypes, - mapTypeFlags, mapNames, mapperAllocas); + genMapInfos(builder, moduleTranslation, DL, combinedInfo, mapOperands, + mapTypes); + return combinedInfo; }; LogicalResult bodyGenStatus = success(); - auto bodyCB = [&](InsertPointTy allocaIP, InsertPointTy codeGenIP) { - // DataOp has only one region associated with it. - auto ®ion = cast(op).getRegion(); - builder.restoreIP(codeGenIP); - bodyGenStatus = inlineConvertOmpRegions(region, "omp.data.region", builder, - moduleTranslation); + using BodyGenTy = llvm::OpenMPIRBuilder::BodyGenTy; + auto bodyGenCB = [&](InsertPointTy codeGenIP, BodyGenTy bodyGenType) { + switch (bodyGenType) { + case BodyGenTy::Priv: + 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); + } + } + return builder.saveIP(); }; + 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, builder.saveIP(), mapTypeFlags, mapNames, mapperAllocas, - /*IsBegin=*/false, deviceID, ifCond, processMapOpCB, bodyCB)); + ompLoc, allocaIP, builder.saveIP(), builder.getInt64(deviceID), ifCond, + info, genMapInfoCB, nullptr, bodyGenCB)); } else { builder.restoreIP(ompBuilder->createTargetData( - ompLoc, builder.saveIP(), mapTypeFlags, mapNames, mapperAllocas, - isa(op), deviceID, ifCond, processMapOpCB)); + ompLoc, allocaIP, builder.saveIP(), builder.getInt64(deviceID), ifCond, + info, genMapInfoCB, &RTLFn)); } - if (failed(processMapOpStatus)) - return processMapOpStatus; return bodyGenStatus; } @@ -1554,7 +1538,7 @@ LLVM::ModuleTranslation &moduleTranslation) { if (!cast(op)) return failure(); - + llvm::OpenMPIRBuilder *ompBuilder = moduleTranslation.getOpenMPBuilder(); ompBuilder->createGlobalFlag( 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 @@ -11,29 +11,28 @@ 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 3] // CHECK-LABEL: define void @_QPopenmp_target_data() { // CHECK: %[[VAL_0:.*]] = alloca [1 x ptr], align 8 // CHECK: %[[VAL_1:.*]] = alloca [1 x ptr], align 8 -// CHECK: %[[VAL_2:.*]] = alloca [1 x i64], 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: [[VAL_4]]: -// CHECK: %[[VAL_5:.*]] = getelementptr inbounds [1 x ptr], ptr %[[VAL_0]], i32 0, i32 0 -// CHECK: store ptr %[[VAL_3]], ptr %[[VAL_5]], align 8 -// CHECK: %[[VAL_6:.*]] = getelementptr inbounds [1 x ptr], ptr %[[VAL_1]], i32 0, i32 0 +// 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 i64], ptr %[[VAL_2]], i32 0, i32 0 -// CHECK: store i64 ptrtoint (ptr getelementptr (ptr, ptr null, i32 1) to i64), ptr %[[VAL_7]], align 4 -// CHECK: %[[VAL_8:.*]] = getelementptr inbounds [1 x ptr], ptr %[[VAL_0]], i32 0, i32 0 -// CHECK: %[[VAL_9:.*]] = getelementptr inbounds [1 x ptr], ptr %[[VAL_1]], i32 0, i32 0 -// CHECK: %[[VAL_10:.*]] = getelementptr inbounds [1 x i64], ptr %[[VAL_2]], i32 0, i32 0 -// CHECK: call void @__tgt_target_data_begin_mapper(ptr @2, i64 -1, i32 1, ptr %[[VAL_8]], ptr %[[VAL_9]], ptr %[[VAL_10]], ptr @.offload_maptypes, ptr @.offload_mapnames, ptr null) +// 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 null, ptr null) // CHECK: store i32 99, ptr %[[VAL_3]], align 4 // CHECK: %[[VAL_11:.*]] = getelementptr inbounds [1 x ptr], ptr %[[VAL_0]], i32 0, i32 0 // CHECK: %[[VAL_12:.*]] = getelementptr inbounds [1 x ptr], ptr %[[VAL_1]], i32 0, i32 0 -// CHECK: %[[VAL_13:.*]] = getelementptr inbounds [1 x i64], ptr %[[VAL_2]], i32 0, i32 0 -// CHECK: call void @__tgt_target_data_end_mapper(ptr @2, i64 -1, i32 1, ptr %[[VAL_11]], ptr %[[VAL_12]], ptr %[[VAL_13]], ptr @.offload_maptypes, ptr @.offload_mapnames, ptr null) +// CHECK: call void @__tgt_target_data_end_mapper(ptr @2, i64 -1, i32 1, ptr %[[VAL_11]], ptr %[[VAL_12]], ptr @.offload_sizes, ptr @.offload_maptypes, ptr null, ptr null) // CHECK: ret void // ----- @@ -51,35 +50,34 @@ llvm.return } +// CHECK: @.offload_sizes = private unnamed_addr constant [1 x i64] [i64 4096] // CHECK: @.offload_maptypes = private unnamed_addr constant [1 x i64] [i64 2] // CHECK-LABEL: define void @_QPopenmp_target_data_region // CHECK: (ptr %[[ARG_0:.*]]) { // CHECK: %[[VAL_0:.*]] = alloca [1 x ptr], align 8 // CHECK: %[[VAL_1:.*]] = alloca [1 x ptr], align 8 -// CHECK: %[[VAL_2:.*]] = alloca [1 x i64], align 8 +// CHECK: %[[VAL_2:.*]] = alloca [1 x ptr], align 8 // CHECK: br label %[[VAL_3:.*]] -// CHECK: [[VAL_3]]: -// CHECK: %[[VAL_4:.*]] = getelementptr inbounds [1 x ptr], ptr %[[VAL_0]], i32 0, i32 0 -// CHECK: store ptr %[[VAL_5:.*]], ptr %[[VAL_4]], align 8 -// CHECK: %[[VAL_6:.*]] = getelementptr inbounds [1 x ptr], ptr %[[VAL_1]], i32 0, i32 0 -// CHECK: store ptr %[[VAL_5]], ptr %[[VAL_6]], align 8 -// CHECK: %[[VAL_7:.*]] = getelementptr inbounds [1 x i64], ptr %[[VAL_2]], i32 0, i32 0 -// CHECK: store i64 ptrtoint (ptr getelementptr (ptr, ptr null, i32 1) to i64), ptr %[[VAL_7]], align 4 -// CHECK: %[[VAL_8:.*]] = getelementptr inbounds [1 x ptr], ptr %[[VAL_0]], i32 0, i32 0 -// CHECK: %[[VAL_9:.*]] = getelementptr inbounds [1 x ptr], ptr %[[VAL_1]], i32 0, i32 0 -// CHECK: %[[VAL_10:.*]] = getelementptr inbounds [1 x i64], ptr %[[VAL_2]], i32 0, i32 0 -// CHECK: call void @__tgt_target_data_begin_mapper(ptr @2, i64 -1, i32 1, ptr %[[VAL_8]], ptr %[[VAL_9]], ptr %[[VAL_10]], ptr @.offload_maptypes, ptr @.offload_mapnames, ptr null) -// CHECK: %[[VAL_11:.*]] = getelementptr [1024 x i32], ptr %[[VAL_5]], i32 0, i64 0 +// CHECK: entry: ; preds = %[[VAL_4:.*]] +// CHECK: %[[VAL_5:.*]] = getelementptr inbounds [1 x ptr], ptr %[[VAL_0]], i32 0, i32 0 +// CHECK: store ptr %[[VAL_6:.*]], ptr %[[VAL_5]], align 8 +// CHECK: %[[VAL_7:.*]] = getelementptr inbounds [1 x ptr], ptr %[[VAL_1]], i32 0, i32 0 +// CHECK: store ptr %[[VAL_6]], 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 null, ptr null) +// CHECK: %[[VAL_11:.*]] = getelementptr [1024 x i32], ptr %[[VAL_6]], i32 0, i64 0 // CHECK: store i32 99, 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: %[[VAL_14:.*]] = getelementptr inbounds [1 x i64], ptr %[[VAL_2]], 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 %[[VAL_14]], ptr @.offload_maptypes, ptr @.offload_mapnames, ptr null) +// 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 null, ptr null) // CHECK: ret void // ----- -llvm.func @_QPomp_target_enter_exit(%1 : !llvm.ptr>, %3 : !llvm.ptr>) { +llvm.func @_QPomp_target_enter_exit(%1 : !llvm.ptr>, %3 : !llvm.ptr>) { %4 = llvm.mlir.constant(1 : i64) : i64 %5 = llvm.alloca %4 x i32 {bindc_name = "dvc", in_type = i32, operand_segment_sizes = array, uniq_name = "_QFomp_target_enter_exitEdvc"} : (i64) -> !llvm.ptr %6 = llvm.mlir.constant(1 : i64) : i64 @@ -92,25 +90,27 @@ %11 = llvm.mlir.constant(10 : i32) : i32 %12 = llvm.icmp "slt" %10, %11 : i32 %13 = llvm.load %5 : !llvm.ptr - omp.target_enter_data if(%12 : i1) device(%13 : i32) map((to -> %1 : !llvm.ptr>), (alloc -> %3 : !llvm.ptr>)) + omp.target_enter_data if(%12 : i1) device(%13 : i32) map((to -> %1 : !llvm.ptr>), (alloc -> %3 : !llvm.ptr>)) %14 = llvm.load %7 : !llvm.ptr %15 = llvm.mlir.constant(10 : i32) : i32 %16 = llvm.icmp "sgt" %14, %15 : i32 %17 = llvm.load %5 : !llvm.ptr - omp.target_exit_data if(%16 : i1) device(%17 : i32) map((from -> %1 : !llvm.ptr>), (release -> %3 : !llvm.ptr>)) + omp.target_exit_data if(%16 : i1) device(%17 : i32) map((from -> %1 : !llvm.ptr>), (release -> %3 : !llvm.ptr>)) llvm.return } +// CHECK: @.offload_sizes = private unnamed_addr constant [2 x i64] [i64 4096, i64 2048] // CHECK: @.offload_maptypes = private unnamed_addr constant [2 x i64] [i64 1, i64 0] -// CHECK: @.offload_maptypes.1 = private unnamed_addr constant [2 x i64] [i64 2, i64 0] +// CHECK: @.offload_sizes.1 = private unnamed_addr constant [2 x i64] [i64 4096, i64 2048] +// CHECK: @.offload_maptypes.2 = private unnamed_addr constant [2 x i64] [i64 2, i64 0] // CHECK-LABEL: define void @_QPomp_target_enter_exit // CHECK: (ptr %[[ARG_0:.*]], ptr %[[ARG_1:.*]]) { // CHECK: %[[VAL_0:.*]] = alloca [2 x ptr], align 8 // CHECK: %[[VAL_1:.*]] = alloca [2 x ptr], align 8 -// CHECK: %[[VAL_2:.*]] = alloca [2 x i64], align 8 +// CHECK: %[[VAL_2:.*]] = alloca [2 x ptr], align 8 // CHECK: %[[VAL_3:.*]] = alloca [2 x ptr], align 8 // CHECK: %[[VAL_4:.*]] = alloca [2 x ptr], align 8 -// CHECK: %[[VAL_5:.*]] = alloca [2 x i64], align 8 +// CHECK: %[[VAL_5:.*]] = alloca [2 x ptr], align 8 // CHECK: %[[VAL_6:.*]] = alloca i32, i64 1, align 4 // CHECK: %[[VAL_7:.*]] = alloca i32, i64 1, align 4 // CHECK: store i32 5, ptr %[[VAL_7]], align 4 @@ -126,44 +126,45 @@ // CHECK: store ptr %[[VAL_16:.*]], ptr %[[VAL_15]], align 8 // CHECK: %[[VAL_17:.*]] = getelementptr inbounds [2 x ptr], ptr %[[VAL_4]], i32 0, i32 0 // CHECK: store ptr %[[VAL_16]], ptr %[[VAL_17]], align 8 -// CHECK: %[[VAL_18:.*]] = getelementptr inbounds [2 x i64], ptr %[[VAL_5]], i32 0, i32 0 -// CHECK: store i64 ptrtoint (ptr getelementptr (ptr, ptr null, i32 1) to i64), ptr %[[VAL_18]], align 4 +// CHECK: %[[VAL_18:.*]] = getelementptr inbounds [2 x ptr], ptr %[[VAL_5]], i64 0, i64 0 +// CHECK: store ptr null, ptr %[[VAL_18]], align 8 // CHECK: %[[VAL_19:.*]] = getelementptr inbounds [2 x ptr], ptr %[[VAL_3]], i32 0, i32 1 // CHECK: store ptr %[[VAL_20:.*]], ptr %[[VAL_19]], align 8 // CHECK: %[[VAL_21:.*]] = getelementptr inbounds [2 x ptr], ptr %[[VAL_4]], i32 0, i32 1 // CHECK: store ptr %[[VAL_20]], ptr %[[VAL_21]], align 8 -// CHECK: %[[VAL_22:.*]] = getelementptr inbounds [2 x i64], ptr %[[VAL_5]], i32 0, i32 1 -// CHECK: store i64 ptrtoint (ptr getelementptr (ptr, ptr null, i32 1) to i64), ptr %[[VAL_22]], align 4 +// CHECK: %[[VAL_22:.*]] = getelementptr inbounds [2 x ptr], ptr %[[VAL_5]], i64 0, i64 1 +// CHECK: store ptr null, ptr %[[VAL_22]], align 8 // CHECK: %[[VAL_23:.*]] = getelementptr inbounds [2 x ptr], ptr %[[VAL_3]], i32 0, i32 0 // CHECK: %[[VAL_24:.*]] = getelementptr inbounds [2 x ptr], ptr %[[VAL_4]], i32 0, i32 0 -// CHECK: %[[VAL_25:.*]] = getelementptr inbounds [2 x i64], ptr %[[VAL_5]], i32 0, i32 0 -// CHECK: call void @__tgt_target_data_begin_mapper(ptr @3, i64 -1, i32 2, ptr %[[VAL_23]], ptr %[[VAL_24]], ptr %[[VAL_25]], ptr @.offload_maptypes, ptr @.offload_mapnames, ptr null) -// CHECK: br label %[[VAL_14]] -// CHECK: omp_if.end: ; preds = %[[VAL_11]], %[[VAL_13]] +// CHECK: call void @__tgt_target_data_begin_mapper(ptr @3, i64 -1, i32 2, ptr %[[VAL_23]], ptr %[[VAL_24]], ptr @.offload_sizes, ptr @.offload_maptypes, ptr null, ptr null) +// CHECK: br label %[[VAL_25:.*]] +// CHECK: omp_if.else: ; preds = %[[VAL_11]] +// CHECK: br label %[[VAL_25]] +// CHECK: omp_if.end: ; preds = %[[VAL_14]], %[[VAL_13]] // CHECK: %[[VAL_26:.*]] = load i32, ptr %[[VAL_7]], align 4 // CHECK: %[[VAL_27:.*]] = icmp sgt i32 %[[VAL_26]], 10 // CHECK: %[[VAL_28:.*]] = load i32, ptr %[[VAL_6]], align 4 // CHECK: br i1 %[[VAL_27]], label %[[VAL_29:.*]], label %[[VAL_30:.*]] -// CHECK: omp_if.then4: ; preds = %[[VAL_14]] +// CHECK: omp_if.then1: ; preds = %[[VAL_25]] // CHECK: %[[VAL_31:.*]] = getelementptr inbounds [2 x ptr], ptr %[[VAL_0]], i32 0, i32 0 // CHECK: store ptr %[[VAL_16]], ptr %[[VAL_31]], align 8 // CHECK: %[[VAL_32:.*]] = getelementptr inbounds [2 x ptr], ptr %[[VAL_1]], i32 0, i32 0 // CHECK: store ptr %[[VAL_16]], ptr %[[VAL_32]], align 8 -// CHECK: %[[VAL_33:.*]] = getelementptr inbounds [2 x i64], ptr %[[VAL_2]], i32 0, i32 0 -// CHECK: store i64 ptrtoint (ptr getelementptr (ptr, ptr null, i32 1) to i64), ptr %[[VAL_33]], align 4 +// CHECK: %[[VAL_33:.*]] = getelementptr inbounds [2 x ptr], ptr %[[VAL_2]], i64 0, i64 0 +// CHECK: store ptr null, ptr %[[VAL_33]], align 8 // CHECK: %[[VAL_34:.*]] = getelementptr inbounds [2 x ptr], ptr %[[VAL_0]], i32 0, i32 1 // CHECK: store ptr %[[VAL_20]], ptr %[[VAL_34]], align 8 // CHECK: %[[VAL_35:.*]] = getelementptr inbounds [2 x ptr], ptr %[[VAL_1]], i32 0, i32 1 // CHECK: store ptr %[[VAL_20]], ptr %[[VAL_35]], align 8 -// CHECK: %[[VAL_36:.*]] = getelementptr inbounds [2 x i64], ptr %[[VAL_2]], i32 0, i32 1 -// CHECK: store i64 ptrtoint (ptr getelementptr (ptr, ptr null, i32 1) to i64), ptr %[[VAL_36]], align 4 +// CHECK: %[[VAL_36:.*]] = getelementptr inbounds [2 x ptr], ptr %[[VAL_2]], i64 0, i64 1 +// CHECK: store ptr null, ptr %[[VAL_36]], align 8 // CHECK: %[[VAL_37:.*]] = getelementptr inbounds [2 x ptr], ptr %[[VAL_0]], i32 0, i32 0 // CHECK: %[[VAL_38:.*]] = getelementptr inbounds [2 x ptr], ptr %[[VAL_1]], i32 0, i32 0 -// CHECK: %[[VAL_39:.*]] = getelementptr inbounds [2 x i64], ptr %[[VAL_2]], i32 0, i32 0 -// CHECK: call void @__tgt_target_data_end_mapper(ptr @3, i64 -1, i32 2, ptr %[[VAL_37]], ptr %[[VAL_38]], ptr %[[VAL_39]], ptr @.offload_maptypes.1, ptr @.offload_mapnames.2, ptr null) -// CHECK: br label %[[VAL_30]] -// CHECK: omp_if.end5: ; preds = %[[VAL_14]], %[[VAL_29]] +// CHECK: call void @__tgt_target_data_end_mapper(ptr @3, i64 -1, i32 2, ptr %[[VAL_37]], ptr %[[VAL_38]], ptr @.offload_sizes.1, ptr @.offload_maptypes.2, ptr null, ptr null) +// CHECK: br label %[[VAL_39:.*]] +// CHECK: omp_if.else5: ; preds = %[[VAL_25]] +// CHECK: br label %[[VAL_39]] +// CHECK: omp_if.end6: ; preds = %[[VAL_30]], %[[VAL_29]] // CHECK: ret void // ----- -