This revision was automatically updated to reflect the committed changes. Closed by commit rGcda46cc4f921: [Clang][OpenMP][IRBuilder] Move registerTargetGlobalVariable &… (authored by agozillon).
Changed prior to commit: https://reviews.llvm.org/D149162?vs=524279&id=529258#toc Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D149162/new/ https://reviews.llvm.org/D149162 Files: clang/lib/CodeGen/CGOpenMPRuntime.cpp llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp llvm/unittests/Frontend/OpenMPIRBuilderTest.cpp
Index: llvm/unittests/Frontend/OpenMPIRBuilderTest.cpp =================================================================== --- llvm/unittests/Frontend/OpenMPIRBuilderTest.cpp +++ llvm/unittests/Frontend/OpenMPIRBuilderTest.cpp @@ -5855,4 +5855,84 @@ GlobalValue::WeakAnyLinkage); EXPECT_TRUE(InfoManager.hasDeviceGlobalVarEntryInfo("gvar")); } + +// Tests both registerTargetGlobalVariable and getAddrOfDeclareTargetVar as they +// call each other (recursively in some cases). The test case test these +// functions by utilising them for host code generation for declare target +// global variables +TEST_F(OpenMPIRBuilderTest, registerTargetGlobalVariable) { + OpenMPIRBuilder OMPBuilder(*M); + OMPBuilder.initialize(); + OpenMPIRBuilderConfig Config(false, false, false, false); + OMPBuilder.setConfig(Config); + + std::vector<llvm::Triple> TargetTriple; + TargetTriple.emplace_back("amdgcn-amd-amdhsa"); + + TargetRegionEntryInfo EntryInfo("", 42, 4711, 17); + std::vector<GlobalVariable *> RefsGathered; + + std::vector<Constant *> Globals; + auto *IntTy = Type::getInt32Ty(Ctx); + for (int I = 0; I < 2; ++I) { + Globals.push_back(M->getOrInsertGlobal( + "test_data_int_" + std::to_string(I), IntTy, [&]() -> GlobalVariable * { + return new GlobalVariable( + *M, IntTy, false, GlobalValue::LinkageTypes::WeakAnyLinkage, + ConstantInt::get(IntTy, I), "test_data_int_" + std::to_string(I)); + })); + } + + OMPBuilder.registerTargetGlobalVariable( + OffloadEntriesInfoManager::OMPTargetGlobalVarEntryTo, + OffloadEntriesInfoManager::OMPTargetDeviceClauseAny, false, true, + EntryInfo, Globals[0]->getName(), RefsGathered, false, TargetTriple, + nullptr, nullptr, Globals[0]->getType(), Globals[0]); + + OMPBuilder.registerTargetGlobalVariable( + OffloadEntriesInfoManager::OMPTargetGlobalVarEntryLink, + OffloadEntriesInfoManager::OMPTargetDeviceClauseAny, false, true, + EntryInfo, Globals[1]->getName(), RefsGathered, false, TargetTriple, + nullptr, nullptr, Globals[1]->getType(), Globals[1]); + + llvm::OpenMPIRBuilder::EmitMetadataErrorReportFunctionTy &&ErrorReportfn = + [](llvm::OpenMPIRBuilder::EmitMetadataErrorKind Kind, + const llvm::TargetRegionEntryInfo &EntryInfo) -> void { + // If this is invoked, then we want to emit an error, even if it is not + // neccesarily the most readable, as something has went wrong. The + // test-suite unfortunately eats up all error output + ASSERT_EQ(Kind, Kind); + }; + + OMPBuilder.createOffloadEntriesAndInfoMetadata(ErrorReportfn); + + // Clauses for data_int_0 with To + Any clauses for the host + std::vector<GlobalVariable *> OffloadEntries; + OffloadEntries.push_back(M->getNamedGlobal(".omp_offloading.entry_name")); + OffloadEntries.push_back( + M->getNamedGlobal(".omp_offloading.entry.test_data_int_0")); + + // Clauses for data_int_1 with Link + Any clauses for the host + OffloadEntries.push_back( + M->getNamedGlobal("test_data_int_1_decl_tgt_ref_ptr")); + OffloadEntries.push_back(M->getNamedGlobal(".omp_offloading.entry_name.1")); + OffloadEntries.push_back(M->getNamedGlobal( + ".omp_offloading.entry.test_data_int_1_decl_tgt_ref_ptr")); + + for (unsigned I = 0; I < OffloadEntries.size(); ++I) + EXPECT_NE(OffloadEntries[I], nullptr); + + // Metadata generated for the host offload module + NamedMDNode *OffloadMetadata = M->getNamedMetadata("omp_offload.info"); + EXPECT_NE(OffloadMetadata, nullptr); + if (OffloadMetadata) { + EXPECT_EQ(OffloadMetadata->getOperand(0)->getOperand(1).equalsStr( + "test_data_int_0"), + true); + EXPECT_EQ(OffloadMetadata->getOperand(1)->getOperand(1).equalsStr( + "test_data_int_1_decl_tgt_ref_ptr"), + true); + } +} + } // namespace Index: llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp =================================================================== --- llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp +++ llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp @@ -34,6 +34,7 @@ #include "llvm/IR/Value.h" #include "llvm/MC/TargetRegistry.h" #include "llvm/Support/CommandLine.h" +#include "llvm/Support/FileSystem.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetOptions.h" #include "llvm/Transforms/Utils/BasicBlockUtils.h" @@ -5132,7 +5133,8 @@ static_cast<OffloadEntriesInfoManager::OMPTargetGlobalVarEntryKind>( CE->getFlags()); switch (Flags) { - case OffloadEntriesInfoManager::OMPTargetGlobalVarEntryTo: { + case OffloadEntriesInfoManager::OMPTargetGlobalVarEntryEnter: + case OffloadEntriesInfoManager::OMPTargetGlobalVarEntryTo: if (Config.isEmbedded() && Config.hasRequiresUnifiedSharedMemory()) continue; if (!CE->getAddress()) { @@ -5143,7 +5145,6 @@ if (CE->getVarSize() == 0) continue; break; - } case OffloadEntriesInfoManager::OMPTargetGlobalVarEntryLink: assert(((Config.isEmbedded() && !CE->getAddress()) || (!Config.isEmbedded() && CE->getAddress())) && @@ -5155,6 +5156,8 @@ continue; } break; + default: + break; } // Hidden or internal symbols on the device are not externally visible. @@ -5191,6 +5194,152 @@ EntryInfo.Line, NewCount); } +TargetRegionEntryInfo +OpenMPIRBuilder::getTargetEntryUniqueInfo(StringRef FileName, uint64_t Line, + StringRef ParentName) { + sys::fs::UniqueID ID; + if (auto EC = sys::fs::getUniqueID(FileName, ID)) { + assert(EC && + "Unable to get unique ID for file, during getTargetEntryUniqueInfo"); + } + return TargetRegionEntryInfo(ParentName, ID.getDevice(), ID.getFile(), Line); +} + +Constant *OpenMPIRBuilder::getAddrOfDeclareTargetVar( + OffloadEntriesInfoManager::OMPTargetGlobalVarEntryKind CaptureClause, + OffloadEntriesInfoManager::OMPTargetDeviceClauseKind DeviceClause, + bool IsDeclaration, bool IsExternallyVisible, + TargetRegionEntryInfo EntryInfo, StringRef MangledName, + std::vector<GlobalVariable *> &GeneratedRefs, bool OpenMPSIMD, + std::vector<Triple> TargetTriple, Type *LlvmPtrTy, + std::function<Constant *()> GlobalInitializer, + std::function<GlobalValue::LinkageTypes()> VariableLinkage) { + // TODO: convert this to utilise the IRBuilder Config rather than + // a passed down argument. + if (OpenMPSIMD) + return nullptr; + + if (CaptureClause == OffloadEntriesInfoManager::OMPTargetGlobalVarEntryLink || + ((CaptureClause == OffloadEntriesInfoManager::OMPTargetGlobalVarEntryTo || + CaptureClause == + OffloadEntriesInfoManager::OMPTargetGlobalVarEntryEnter) && + Config.hasRequiresUnifiedSharedMemory())) { + SmallString<64> PtrName; + { + raw_svector_ostream OS(PtrName); + OS << MangledName; + if (!IsExternallyVisible) + OS << format("_%x", EntryInfo.FileID); + OS << "_decl_tgt_ref_ptr"; + } + + Value *Ptr = M.getNamedValue(PtrName); + + if (!Ptr) { + GlobalValue *GlobalValue = M.getNamedValue(MangledName); + Ptr = getOrCreateInternalVariable(LlvmPtrTy, PtrName); + + auto *GV = cast<GlobalVariable>(Ptr); + GV->setLinkage(GlobalValue::WeakAnyLinkage); + + if (!Config.isEmbedded()) { + if (GlobalInitializer) + GV->setInitializer(GlobalInitializer()); + else + GV->setInitializer(GlobalValue); + } + + registerTargetGlobalVariable( + CaptureClause, DeviceClause, IsDeclaration, IsExternallyVisible, + EntryInfo, MangledName, GeneratedRefs, OpenMPSIMD, TargetTriple, + GlobalInitializer, VariableLinkage, LlvmPtrTy, cast<Constant>(Ptr)); + } + + return cast<Constant>(Ptr); + } + + return nullptr; +} + +void OpenMPIRBuilder::registerTargetGlobalVariable( + OffloadEntriesInfoManager::OMPTargetGlobalVarEntryKind CaptureClause, + OffloadEntriesInfoManager::OMPTargetDeviceClauseKind DeviceClause, + bool IsDeclaration, bool IsExternallyVisible, + TargetRegionEntryInfo EntryInfo, StringRef MangledName, + std::vector<GlobalVariable *> &GeneratedRefs, bool OpenMPSIMD, + std::vector<Triple> TargetTriple, + std::function<Constant *()> GlobalInitializer, + std::function<GlobalValue::LinkageTypes()> VariableLinkage, Type *LlvmPtrTy, + Constant *Addr) { + if (DeviceClause != OffloadEntriesInfoManager::OMPTargetDeviceClauseAny || + (TargetTriple.empty() && !Config.isEmbedded())) + return; + + OffloadEntriesInfoManager::OMPTargetGlobalVarEntryKind Flags; + StringRef VarName; + int64_t VarSize; + GlobalValue::LinkageTypes Linkage; + + if ((CaptureClause == OffloadEntriesInfoManager::OMPTargetGlobalVarEntryTo || + CaptureClause == + OffloadEntriesInfoManager::OMPTargetGlobalVarEntryEnter) && + !Config.hasRequiresUnifiedSharedMemory()) { + Flags = OffloadEntriesInfoManager::OMPTargetGlobalVarEntryTo; + VarName = MangledName; + GlobalValue *LlvmVal = M.getNamedValue(VarName); + + if (!IsDeclaration) + VarSize = divideCeil( + M.getDataLayout().getTypeSizeInBits(LlvmVal->getValueType()), 8); + else + VarSize = 0; + Linkage = (VariableLinkage) ? VariableLinkage() : LlvmVal->getLinkage(); + + // This is a workaround carried over from Clang which prevents undesired + // optimisation of internal variables. + if (Config.isEmbedded() && + (!IsExternallyVisible || Linkage == GlobalValue::LinkOnceODRLinkage)) { + // Do not create a "ref-variable" if the original is not also available + // on the host. + if (!OffloadInfoManager.hasDeviceGlobalVarEntryInfo(VarName)) + return; + + std::string RefName = createPlatformSpecificName({VarName, "ref"}); + + if (!M.getNamedValue(RefName)) { + Constant *AddrRef = + getOrCreateInternalVariable(Addr->getType(), RefName); + auto *GvAddrRef = cast<GlobalVariable>(AddrRef); + GvAddrRef->setConstant(true); + GvAddrRef->setLinkage(GlobalValue::InternalLinkage); + GvAddrRef->setInitializer(Addr); + GeneratedRefs.push_back(GvAddrRef); + } + } + } else { + if (CaptureClause == OffloadEntriesInfoManager::OMPTargetGlobalVarEntryLink) + Flags = OffloadEntriesInfoManager::OMPTargetGlobalVarEntryLink; + else + Flags = OffloadEntriesInfoManager::OMPTargetGlobalVarEntryTo; + + if (Config.isEmbedded()) { + VarName = (Addr) ? Addr->getName() : ""; + Addr = nullptr; + } else { + Addr = getAddrOfDeclareTargetVar( + CaptureClause, DeviceClause, IsDeclaration, IsExternallyVisible, + EntryInfo, MangledName, GeneratedRefs, OpenMPSIMD, TargetTriple, + LlvmPtrTy, GlobalInitializer, VariableLinkage); + VarName = (Addr) ? Addr->getName() : ""; + } + VarSize = M.getDataLayout().getPointerSize(); + Linkage = GlobalValue::WeakAnyLinkage; + } + + OffloadInfoManager.registerDeviceGlobalVarEntryInfo(VarName, Addr, VarSize, + Flags, Linkage); +} + /// Loads all the offload entries information from the host IR /// metadata. void OpenMPIRBuilder::loadOffloadInfoMetadata(Module &M) { Index: llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h =================================================================== --- llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h +++ llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h @@ -323,6 +323,26 @@ OMPTargetGlobalVarEntryTo = 0x0, /// Mark the entry as a to declare target link. OMPTargetGlobalVarEntryLink = 0x1, + /// Mark the entry as a declare target enter. + OMPTargetGlobalVarEntryEnter = 0x2, + /// Mark the entry as having no declare target entry kind. + OMPTargetGlobalVarEntryNone = 0x3, + }; + + /// Kind of device clause for declare target variables + /// and functions + /// NOTE: Currently not used as a part of a variable entry + /// used for Flang and Clang to interface with the variable + /// related registration functions + enum OMPTargetDeviceClauseKind : uint32_t { + /// The target is marked for all devices + OMPTargetDeviceClauseAny = 0x0, + /// The target is marked for non-host devices + OMPTargetDeviceClauseNoHost = 0x1, + /// The target is marked for host devices + OMPTargetDeviceClauseHost = 0x2, + /// The target is marked as having no clause + OMPTargetDeviceClauseNone = 0x3 }; /// Device global variable entries info. @@ -761,6 +781,95 @@ static unsigned getOpenMPDefaultSimdAlign(const Triple &TargetTriple, const StringMap<bool> &Features); + /// Retrieve (or create if non-existent) the address of a declare + /// target variable, used in conjunction with registerTargetGlobalVariable + /// to create declare target global variables. + /// + /// \param CaptureClause - enumerator corresponding to the OpenMP capture + /// clause used in conjunction with the variable being registered (link, + /// to, enter). + /// \param DeviceClause - enumerator corresponding to the OpenMP capture + /// clause used in conjunction with the variable being registered (nohost, + /// host, any) + /// \param IsDeclaration - boolean stating if the variable being registered + /// is a declaration-only and not a definition + /// \param IsExternallyVisible - boolean stating if the variable is externally + /// visible + /// \param EntryInfo - Unique entry information for the value generated + /// using getTargetEntryUniqueInfo, used to name generated pointer references + /// to the declare target variable + /// \param MangledName - the mangled name of the variable being registered + /// \param GeneratedRefs - references generated by invocations of + /// registerTargetGlobalVariable invoked from getAddrOfDeclareTargetVar, + /// these are required by Clang for book keeping. + /// \param OpenMPSIMD - if OpenMP SIMD mode is currently enabled + /// \param TargetTriple - The OpenMP device target triple we are compiling + /// for + /// \param LlvmPtrTy - The type of the variable we are generating or + /// retrieving an address for + /// \param GlobalInitializer - a lambda function which creates a constant + /// used for initializing a pointer reference to the variable in certain + /// cases. If a nullptr is passed, it will default to utilising the original + /// variable to initialize the pointer reference. + /// \param VariableLinkage - a lambda function which returns the variables + /// linkage type, if unspecified and a nullptr is given, it will instead + /// utilise the linkage stored on the existing global variable in the + /// LLVMModule. + Constant *getAddrOfDeclareTargetVar( + OffloadEntriesInfoManager::OMPTargetGlobalVarEntryKind CaptureClause, + OffloadEntriesInfoManager::OMPTargetDeviceClauseKind DeviceClause, + bool IsDeclaration, bool IsExternallyVisible, + TargetRegionEntryInfo EntryInfo, StringRef MangledName, + std::vector<GlobalVariable *> &GeneratedRefs, bool OpenMPSIMD, + std::vector<Triple> TargetTriple, Type *LlvmPtrTy, + std::function<Constant *()> GlobalInitializer, + std::function<GlobalValue::LinkageTypes()> VariableLinkage); + + /// Registers a target variable for device or host. + /// + /// \param CaptureClause - enumerator corresponding to the OpenMP capture + /// clause used in conjunction with the variable being registered (link, + /// to, enter). + /// \param DeviceClause - enumerator corresponding to the OpenMP capture + /// clause used in conjunction with the variable being registered (nohost, + /// host, any) + /// \param IsDeclaration - boolean stating if the variable being registered + /// is a declaration-only and not a definition + /// \param IsExternallyVisible - boolean stating if the variable is externally + /// visible + /// \param EntryInfo - Unique entry information for the value generated + /// using getTargetEntryUniqueInfo, used to name generated pointer references + /// to the declare target variable + /// \param MangledName - the mangled name of the variable being registered + /// \param GeneratedRefs - references generated by invocations of + /// registerTargetGlobalVariable these are required by Clang for book + /// keeping. + /// \param OpenMPSIMD - if OpenMP SIMD mode is currently enabled + /// \param TargetTriple - The OpenMP device target triple we are compiling + /// for + /// \param GlobalInitializer - a lambda function which creates a constant + /// used for initializing a pointer reference to the variable in certain + /// cases. If a nullptr is passed, it will default to utilising the original + /// variable to initialize the pointer reference. + /// \param VariableLinkage - a lambda function which returns the variables + /// linkage type, if unspecified and a nullptr is given, it will instead + /// utilise the linkage stored on the existing global variable in the + /// LLVMModule. + /// \param LlvmPtrTy - The type of the variable we are generating or + /// retrieving an address for + /// \param Addr - the original llvm value (addr) of the variable to be + /// registered + void registerTargetGlobalVariable( + OffloadEntriesInfoManager::OMPTargetGlobalVarEntryKind CaptureClause, + OffloadEntriesInfoManager::OMPTargetDeviceClauseKind DeviceClause, + bool IsDeclaration, bool IsExternallyVisible, + TargetRegionEntryInfo EntryInfo, StringRef MangledName, + std::vector<GlobalVariable *> &GeneratedRefs, bool OpenMPSIMD, + std::vector<Triple> TargetTriple, + std::function<Constant *()> GlobalInitializer, + std::function<GlobalValue::LinkageTypes()> VariableLinkage, + Type *LlvmPtrTy, Constant *Addr); + private: /// Modifies the canonical loop to be a statically-scheduled workshare loop. /// @@ -1046,6 +1155,17 @@ InsertPointTy AllocaIP, BodyGenCallbackTy BodyGenCB); + /// Creates a unique info for a target entry when provided a filename and + /// line number from. + /// + /// \param FileName The name of the file the target entry resides in + /// \param Line The line number where the target entry resides + /// \param ParentName The name of the parent the target entry resides in, if + /// any. + static TargetRegionEntryInfo + getTargetEntryUniqueInfo(StringRef FileName, uint64_t Line, + StringRef ParentName = ""); + /// Functions used to generate reductions. Such functions take two Values /// representing LHS and RHS of the reduction, respectively, and a reference /// to the value that is updated to refer to the reduction result. Index: clang/lib/CodeGen/CGOpenMPRuntime.cpp =================================================================== --- clang/lib/CodeGen/CGOpenMPRuntime.cpp +++ clang/lib/CodeGen/CGOpenMPRuntime.cpp @@ -1601,71 +1601,79 @@ return CGM.CreateRuntimeFunction(FnTy, Name); } -/// Obtain information that uniquely identifies a target entry. This -/// consists of the file and device IDs as well as line number associated with -/// the relevant entry source location. -static llvm::TargetRegionEntryInfo -getTargetEntryUniqueInfo(ASTContext &C, SourceLocation Loc, - StringRef ParentName = "") { - SourceManager &SM = C.getSourceManager(); - - // The loc should be always valid and have a file ID (the user cannot use - // #pragma directives in macros) - - assert(Loc.isValid() && "Source location is expected to be always valid."); - - PresumedLoc PLoc = SM.getPresumedLoc(Loc); - assert(PLoc.isValid() && "Source location is expected to be always valid."); +llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseKind +convertDeviceClause(const VarDecl *VD) { + std::optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy = + OMPDeclareTargetDeclAttr::getDeviceType(VD); + if (!DevTy) + return llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseNone; - llvm::sys::fs::UniqueID ID; - if (auto EC = llvm::sys::fs::getUniqueID(PLoc.getFilename(), ID)) { - PLoc = SM.getPresumedLoc(Loc, /*UseLineDirectives=*/false); - assert(PLoc.isValid() && "Source location is expected to be always valid."); - if (auto EC = llvm::sys::fs::getUniqueID(PLoc.getFilename(), ID)) - SM.getDiagnostics().Report(diag::err_cannot_open_file) - << PLoc.getFilename() << EC.message(); + switch (*DevTy) { + case OMPDeclareTargetDeclAttr::DT_Host: + return llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseHost; + break; + case OMPDeclareTargetDeclAttr::DT_NoHost: + return llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseNoHost; + break; + case OMPDeclareTargetDeclAttr::DT_Any: + return llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseAny; + break; + default: + return llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseNone; + break; } +} - return llvm::TargetRegionEntryInfo(ParentName, ID.getDevice(), ID.getFile(), - PLoc.getLine()); +llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryKind +convertCaptureClause(const VarDecl *VD) { + std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> MapType = + OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); + if (!MapType) + return llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryNone; + switch (*MapType) { + case OMPDeclareTargetDeclAttr::MapTypeTy::MT_To: + return llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryTo; + break; + case OMPDeclareTargetDeclAttr::MapTypeTy::MT_Enter: + return llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryEnter; + break; + case OMPDeclareTargetDeclAttr::MapTypeTy::MT_Link: + return llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryLink; + break; + default: + return llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryNone; + break; + } } Address CGOpenMPRuntime::getAddrOfDeclareTargetVar(const VarDecl *VD) { - if (CGM.getLangOpts().OpenMPSimd) - return Address::invalid(); - std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = - OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); - if (Res && (*Res == OMPDeclareTargetDeclAttr::MT_Link || - ((*Res == OMPDeclareTargetDeclAttr::MT_To || - *Res == OMPDeclareTargetDeclAttr::MT_Enter) && - HasRequiresUnifiedSharedMemory))) { - SmallString<64> PtrName; - { - llvm::raw_svector_ostream OS(PtrName); - OS << CGM.getMangledName(GlobalDecl(VD)); - if (!VD->isExternallyVisible()) { - auto EntryInfo = getTargetEntryUniqueInfo( - CGM.getContext(), VD->getCanonicalDecl()->getBeginLoc()); - OS << llvm::format("_%x", EntryInfo.FileID); - } - OS << "_decl_tgt_ref_ptr"; - } - llvm::Value *Ptr = CGM.getModule().getNamedValue(PtrName); - QualType PtrTy = CGM.getContext().getPointerType(VD->getType()); - llvm::Type *LlvmPtrTy = CGM.getTypes().ConvertTypeForMem(PtrTy); - if (!Ptr) { - Ptr = OMPBuilder.getOrCreateInternalVariable(LlvmPtrTy, PtrName); + auto AddrOfGlobal = [&VD, this]() { return CGM.GetAddrOfGlobal(VD); }; - auto *GV = cast<llvm::GlobalVariable>(Ptr); - GV->setLinkage(llvm::GlobalValue::WeakAnyLinkage); + auto LinkageForVariable = [&VD, this]() { + return CGM.getLLVMLinkageVarDefinition(VD, /*IsConstant=*/false); + }; - if (!CGM.getLangOpts().OpenMPIsDevice) - GV->setInitializer(CGM.GetAddrOfGlobal(VD)); - registerTargetGlobalVariable(VD, cast<llvm::Constant>(Ptr)); - } - return Address(Ptr, LlvmPtrTy, CGM.getContext().getDeclAlign(VD)); - } - return Address::invalid(); + std::vector<llvm::GlobalVariable *> GeneratedRefs; + auto PLoc = CGM.getContext().getSourceManager().getPresumedLoc( + VD->getCanonicalDecl()->getBeginLoc()); + if (PLoc.isInvalid()) + PLoc = CGM.getContext().getSourceManager().getPresumedLoc( + VD->getCanonicalDecl()->getBeginLoc(), /*UseLineDirectives=*/false); + + llvm::Type *LlvmPtrTy = CGM.getTypes().ConvertTypeForMem( + CGM.getContext().getPointerType(VD->getType())); + llvm::Constant *addr = OMPBuilder.getAddrOfDeclareTargetVar( + convertCaptureClause(VD), convertDeviceClause(VD), + VD->hasDefinition(CGM.getContext()) == VarDecl::DeclarationOnly, + VD->isExternallyVisible(), + OMPBuilder.getTargetEntryUniqueInfo(PLoc.getFilename(), PLoc.getLine()), + CGM.getMangledName(VD), GeneratedRefs, CGM.getLangOpts().OpenMPSimd, + CGM.getLangOpts().OMPTargetTriples, LlvmPtrTy, AddrOfGlobal, + LinkageForVariable); + + if (!addr) + return Address::invalid(); + return Address(addr, LlvmPtrTy, CGM.getContext().getDeclAlign(VD)); } llvm::Constant * @@ -1841,6 +1849,19 @@ return nullptr; } +static llvm::TargetRegionEntryInfo getEntryInfoFromPresumedLoc( + CodeGenModule &CGM, llvm::OpenMPIRBuilder &OMPBuilder, + SourceLocation BeginLoc, llvm::StringRef ParentName) { + + auto PLoc = CGM.getContext().getSourceManager().getPresumedLoc(BeginLoc); + if (PLoc.isInvalid()) + PLoc = CGM.getContext().getSourceManager().getPresumedLoc( + BeginLoc, /*UseLineDirectives=*/false); + + return OMPBuilder.getTargetEntryUniqueInfo(PLoc.getFilename(), PLoc.getLine(), + ParentName); +} + bool CGOpenMPRuntime::emitDeclareTargetVarDefinition(const VarDecl *VD, llvm::GlobalVariable *Addr, bool PerformInit) { @@ -1866,8 +1887,8 @@ // Produce the unique prefix to identify the new target regions. We use // the source location of the variable declaration which we know to not // conflict with any target region. - auto EntryInfo = - getTargetEntryUniqueInfo(CGM.getContext(), Loc, VD->getName()); + llvm::TargetRegionEntryInfo EntryInfo = + getEntryInfoFromPresumedLoc(CGM, OMPBuilder, Loc, VD->getName()); SmallString<128> Buffer, Out; OMPBuilder.OffloadInfoManager.getTargetRegionEntryFnName(Buffer, EntryInfo); @@ -6075,8 +6096,8 @@ llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID, bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) { - auto EntryInfo = - getTargetEntryUniqueInfo(CGM.getContext(), D.getBeginLoc(), ParentName); + llvm::TargetRegionEntryInfo EntryInfo = + getEntryInfoFromPresumedLoc(CGM, OMPBuilder, D.getBeginLoc(), ParentName); CodeGenFunction CGF(CGM, true); llvm::OpenMPIRBuilder::FunctionGenCallback &&GenerateOutlinedFunction = @@ -10090,8 +10111,9 @@ if (RequiresDeviceCodegen) { const auto &E = *cast<OMPExecutableDirective>(S); - auto EntryInfo = - getTargetEntryUniqueInfo(CGM.getContext(), E.getBeginLoc(), ParentName); + + llvm::TargetRegionEntryInfo EntryInfo = getEntryInfoFromPresumedLoc( + CGM, OMPBuilder, E.getBeginLoc(), ParentName); // Is this a target region that should not be emitted as an entry point? If // so just signal we are done with this target region. @@ -10309,12 +10331,6 @@ !CGM.getLangOpts().OpenMPIsDevice) return; - // If we have host/nohost variables, they do not need to be registered. - std::optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy = - OMPDeclareTargetDeclAttr::getDeviceType(VD); - if (DevTy && *DevTy != OMPDeclareTargetDeclAttr::DT_Any) - return; - std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); if (!Res) { @@ -10326,68 +10342,33 @@ } return; } - // Register declare target variables. - llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryKind Flags; - StringRef VarName; - int64_t VarSize; - llvm::GlobalValue::LinkageTypes Linkage; - - if ((*Res == OMPDeclareTargetDeclAttr::MT_To || - *Res == OMPDeclareTargetDeclAttr::MT_Enter) && - !HasRequiresUnifiedSharedMemory) { - Flags = llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryTo; - VarName = CGM.getMangledName(VD); - if (VD->hasDefinition(CGM.getContext()) != VarDecl::DeclarationOnly) { - VarSize = - CGM.getContext().getTypeSizeInChars(VD->getType()).getQuantity(); - assert(VarSize != 0 && "Expected non-zero size of the variable"); - } else { - VarSize = 0; - } - Linkage = CGM.getLLVMLinkageVarDefinition(VD, /*IsConstant=*/false); - // Temp solution to prevent optimizations of the internal variables. - if (CGM.getLangOpts().OpenMPIsDevice && - (!VD->isExternallyVisible() || - Linkage == llvm::GlobalValue::LinkOnceODRLinkage)) { - // Do not create a "ref-variable" if the original is not also available - // on the host. - if (!OMPBuilder.OffloadInfoManager.hasDeviceGlobalVarEntryInfo(VarName)) - return; - std::string RefName = getName({VarName, "ref"}); - if (!CGM.GetGlobalValue(RefName)) { - llvm::Constant *AddrRef = - OMPBuilder.getOrCreateInternalVariable(Addr->getType(), RefName); - auto *GVAddrRef = cast<llvm::GlobalVariable>(AddrRef); - GVAddrRef->setConstant(/*Val=*/true); - GVAddrRef->setLinkage(llvm::GlobalValue::InternalLinkage); - GVAddrRef->setInitializer(Addr); - CGM.addCompilerUsedGlobal(GVAddrRef); - } - } - } else { - assert(((*Res == OMPDeclareTargetDeclAttr::MT_Link) || - ((*Res == OMPDeclareTargetDeclAttr::MT_To || - *Res == OMPDeclareTargetDeclAttr::MT_Enter) && - HasRequiresUnifiedSharedMemory)) && - "Declare target attribute must link or to with unified memory."); - if (*Res == OMPDeclareTargetDeclAttr::MT_Link) - Flags = llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryLink; - else - Flags = llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryTo; - if (CGM.getLangOpts().OpenMPIsDevice) { - VarName = Addr->getName(); - Addr = nullptr; - } else { - VarName = getAddrOfDeclareTargetVar(VD).getName(); - Addr = cast<llvm::Constant>(getAddrOfDeclareTargetVar(VD).getPointer()); - } - VarSize = CGM.getPointerSize().getQuantity(); - Linkage = llvm::GlobalValue::WeakAnyLinkage; - } + auto AddrOfGlobal = [&VD, this]() { return CGM.GetAddrOfGlobal(VD); }; + auto LinkageForVariable = [&VD, this]() { + return CGM.getLLVMLinkageVarDefinition(VD, /*IsConstant=*/false); + }; - OMPBuilder.OffloadInfoManager.registerDeviceGlobalVarEntryInfo( - VarName, Addr, VarSize, Flags, Linkage); + std::vector<llvm::GlobalVariable *> GeneratedRefs; + auto PLoc = CGM.getContext().getSourceManager().getPresumedLoc( + VD->getCanonicalDecl()->getBeginLoc()); + if (PLoc.isInvalid()) + PLoc = CGM.getContext().getSourceManager().getPresumedLoc( + VD->getCanonicalDecl()->getBeginLoc(), /*UseLineDirectives=*/false); + OMPBuilder.registerTargetGlobalVariable( + convertCaptureClause(VD), convertDeviceClause(VD), + VD->hasDefinition(CGM.getContext()) == VarDecl::DeclarationOnly, + VD->isExternallyVisible(), + OMPBuilder.getTargetEntryUniqueInfo(PLoc.getFilename(), PLoc.getLine()), + CGM.getMangledName(VD), GeneratedRefs, CGM.getLangOpts().OpenMPSimd, + CGM.getLangOpts().OMPTargetTriples, AddrOfGlobal, LinkageForVariable, + CGM.getTypes().ConvertTypeForMem( + CGM.getContext().getPointerType(VD->getType())), + Addr); + + for (auto *ref : GeneratedRefs) + CGM.addCompilerUsedGlobal(ref); + + return; } bool CGOpenMPRuntime::emitTargetGlobal(GlobalDecl GD) {
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits