diff options
author | Alexey Bataev <a.bataev@hotmail.com> | 2018-03-28 14:28:54 +0000 |
---|---|---|
committer | Alexey Bataev <a.bataev@hotmail.com> | 2018-03-28 14:28:54 +0000 |
commit | 34f8a7043badc630221606f21058a082acde3644 (patch) | |
tree | 0299d0bff5a1ede2f1046bc6c3897d09bfd117c6 /clang/lib/CodeGen/CGOpenMPRuntime.cpp | |
parent | dd2b929ffb07693f4885b18b47e8baf080c7be80 (diff) | |
download | bcm5719-llvm-34f8a7043badc630221606f21058a082acde3644.tar.gz bcm5719-llvm-34f8a7043badc630221606f21058a082acde3644.zip |
[OPENMP] Codegen for ctor|dtor of declare target variables.
When the declare target variables are emitted for the device,
constructors|destructors for these variables must emitted and registered
by the runtime in the offloading sections.
llvm-svn: 328705
Diffstat (limited to 'clang/lib/CodeGen/CGOpenMPRuntime.cpp')
-rw-r--r-- | clang/lib/CodeGen/CGOpenMPRuntime.cpp | 213 |
1 files changed, 164 insertions, 49 deletions
diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp index 891176b0097..4b1fac68277 100644 --- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp +++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp @@ -2522,6 +2522,139 @@ llvm::Function *CGOpenMPRuntime::emitThreadPrivateVarDefinition( return nullptr; } +/// \brief 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 void getTargetEntryUniqueInfo(ASTContext &C, SourceLocation Loc, + unsigned &DeviceID, unsigned &FileID, + unsigned &LineNum) { + + auto &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."); + assert(Loc.isFileID() && "Source location is expected to refer to a file."); + + PresumedLoc PLoc = SM.getPresumedLoc(Loc); + assert(PLoc.isValid() && "Source location is expected to be always valid."); + + llvm::sys::fs::UniqueID ID; + if (llvm::sys::fs::getUniqueID(PLoc.getFilename(), ID)) + llvm_unreachable("Source file with target region no longer exists!"); + + DeviceID = ID.getDevice(); + FileID = ID.getFile(); + LineNum = PLoc.getLine(); +} + +bool CGOpenMPRuntime::emitDeclareTargetVarDefinition(const VarDecl *VD, + llvm::GlobalVariable *Addr, + bool PerformInit) { + Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = + isDeclareTargetDeclaration(VD); + if (!Res || *Res == OMPDeclareTargetDeclAttr::MT_Link) + return false; + VD = VD->getDefinition(CGM.getContext()); + if (VD && !DeclareTargetWithDefinition.insert(VD).second) + return CGM.getLangOpts().OpenMPIsDevice; + + QualType ASTTy = VD->getType(); + + SourceLocation Loc = VD->getCanonicalDecl()->getLocStart(); + // 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. + unsigned DeviceID; + unsigned FileID; + unsigned Line; + getTargetEntryUniqueInfo(CGM.getContext(), Loc, DeviceID, FileID, Line); + SmallString<128> Buffer, Out; + { + llvm::raw_svector_ostream OS(Buffer); + OS << "__omp_offloading_" << llvm::format("_%x", DeviceID) + << llvm::format("_%x_", FileID) << VD->getName() << "_l" << Line; + } + + const Expr *Init = VD->getAnyInitializer(); + if (CGM.getLangOpts().CPlusPlus && PerformInit) { + llvm::Constant *Ctor; + llvm::Constant *ID; + if (CGM.getLangOpts().OpenMPIsDevice) { + // Generate function that re-emits the declaration's initializer into + // the threadprivate copy of the variable VD + CodeGenFunction CtorCGF(CGM); + + const CGFunctionInfo &FI = CGM.getTypes().arrangeNullaryFunction(); + llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); + llvm::Function *Fn = CGM.CreateGlobalInitOrDestructFunction( + FTy, Twine(Buffer, "_ctor"), FI, Loc); + auto NL = ApplyDebugLocation::CreateEmpty(CtorCGF); + CtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI, + FunctionArgList(), Loc, Loc); + auto AL = ApplyDebugLocation::CreateArtificial(CtorCGF); + CtorCGF.EmitAnyExprToMem(Init, + Address(Addr, CGM.getContext().getDeclAlign(VD)), + Init->getType().getQualifiers(), + /*IsInitializer=*/true); + CtorCGF.FinishFunction(); + Ctor = Fn; + ID = llvm::ConstantExpr::getBitCast(Fn, CGM.Int8PtrTy); + } else { + Ctor = new llvm::GlobalVariable( + CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true, + llvm::GlobalValue::PrivateLinkage, + llvm::Constant::getNullValue(CGM.Int8Ty), Twine(Buffer, "_ctor")); + ID = Ctor; + } + + // Register the information for the entry associated with the constructor. + Out.clear(); + OffloadEntriesInfoManager.registerTargetRegionEntryInfo( + DeviceID, FileID, Twine(Buffer, "_ctor").toStringRef(Out), Line, Ctor, + ID, OMPTargetRegionEntryCtor); + } + if (VD->getType().isDestructedType() != QualType::DK_none) { + llvm::Constant *Dtor; + llvm::Constant *ID; + if (CGM.getLangOpts().OpenMPIsDevice) { + // Generate function that emits destructor call for the threadprivate + // copy of the variable VD + CodeGenFunction DtorCGF(CGM); + + const CGFunctionInfo &FI = CGM.getTypes().arrangeNullaryFunction(); + llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); + llvm::Function *Fn = CGM.CreateGlobalInitOrDestructFunction( + FTy, Twine(Buffer, "_dtor"), FI, Loc); + auto NL = ApplyDebugLocation::CreateEmpty(DtorCGF); + DtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI, + FunctionArgList(), Loc, Loc); + // Create a scope with an artificial location for the body of this + // function. + auto AL = ApplyDebugLocation::CreateArtificial(DtorCGF); + DtorCGF.emitDestroy(Address(Addr, CGM.getContext().getDeclAlign(VD)), + ASTTy, DtorCGF.getDestroyer(ASTTy.isDestructedType()), + DtorCGF.needsEHCleanup(ASTTy.isDestructedType())); + DtorCGF.FinishFunction(); + Dtor = Fn; + ID = llvm::ConstantExpr::getBitCast(Fn, CGM.Int8PtrTy); + } else { + Dtor = new llvm::GlobalVariable( + CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true, + llvm::GlobalValue::PrivateLinkage, + llvm::Constant::getNullValue(CGM.Int8Ty), Twine(Buffer, "_dtor")); + ID = Dtor; + } + // Register the information for the entry associated with the destructor. + Out.clear(); + OffloadEntriesInfoManager.registerTargetRegionEntryInfo( + DeviceID, FileID, Twine(Buffer, "_dtor").toStringRef(Out), Line, Dtor, + ID, OMPTargetRegionEntryDtor); + } + return CGM.getLangOpts().OpenMPIsDevice; +} + Address CGOpenMPRuntime::getAddrOfArtificialThreadPrivate(CodeGenFunction &CGF, QualType VarType, StringRef Name) { @@ -3375,7 +3508,7 @@ void CGOpenMPRuntime::OffloadEntriesInfoManagerTy:: "code generation."); OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum] = OffloadEntryInfoTargetRegion(Order, /*Addr=*/nullptr, /*ID=*/nullptr, - /*Flags=*/0); + OMPTargetRegionEntryTargetRegion); ++OffloadingEntriesNum; } @@ -3383,7 +3516,7 @@ void CGOpenMPRuntime::OffloadEntriesInfoManagerTy:: registerTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID, StringRef ParentName, unsigned LineNum, llvm::Constant *Addr, llvm::Constant *ID, - int32_t Flags) { + OMPTargetRegionEntryKind Flags) { // If we are emitting code for a target, the entry is already initialized, // only has to be registered. if (CGM.getLangOpts().OpenMPIsDevice) { @@ -3641,12 +3774,12 @@ void CGOpenMPRuntime::createOffloadEntriesAndInfoMetadata() { llvm::NamedMDNode *MD = M.getOrInsertNamedMetadata("omp_offload.info"); // Auxiliary methods to create metadata values and strings. - auto getMDInt = [&](unsigned v) { + auto GetMdInt = [&C](unsigned V) { return llvm::ConstantAsMetadata::get( - llvm::ConstantInt::get(llvm::Type::getInt32Ty(C), v)); + llvm::ConstantInt::get(llvm::Type::getInt32Ty(C), V)); }; - auto getMDString = [&](StringRef v) { return llvm::MDString::get(C, v); }; + auto GetMdString = [&C](StringRef V) { return llvm::MDString::get(C, V); }; // Create function that emits metadata for each target region entry; auto &&TargetRegionMetadataEmitter = [&]( @@ -3662,12 +3795,12 @@ void CGOpenMPRuntime::createOffloadEntriesAndInfoMetadata() { // - Entry 4 -> Line in the file where the entry was identified. // - Entry 5 -> Order the entry was created. // The first element of the metadata node is the kind. - Ops.push_back(getMDInt(E.getKind())); - Ops.push_back(getMDInt(DeviceID)); - Ops.push_back(getMDInt(FileID)); - Ops.push_back(getMDString(ParentName)); - Ops.push_back(getMDInt(Line)); - Ops.push_back(getMDInt(E.getOrder())); + Ops.push_back(GetMdInt(E.getKind())); + Ops.push_back(GetMdInt(DeviceID)); + Ops.push_back(GetMdInt(FileID)); + Ops.push_back(GetMdString(ParentName)); + Ops.push_back(GetMdInt(Line)); + Ops.push_back(GetMdInt(E.getOrder())); // Save this entry in the right position of the ordered entries array. OrderedEntries[E.getOrder()] = &E; @@ -3686,7 +3819,8 @@ void CGOpenMPRuntime::createOffloadEntriesAndInfoMetadata() { E)) { assert(CE->getID() && CE->getAddress() && "Entry ID and Addr are invalid!"); - createOffloadEntry(CE->getID(), CE->getAddress(), /*Size=*/0); + createOffloadEntry(CE->getID(), CE->getAddress(), /*Size=*/0, + CE->getFlags()); } else llvm_unreachable("Unsupported entry kind."); } @@ -3720,27 +3854,27 @@ void CGOpenMPRuntime::loadOffloadInfoMetadata() { return; for (llvm::MDNode *MN : MD->operands()) { - auto getMDInt = [&](unsigned Idx) { + auto GetMdInt = [MN](unsigned Idx) { llvm::ConstantAsMetadata *V = cast<llvm::ConstantAsMetadata>(MN->getOperand(Idx)); return cast<llvm::ConstantInt>(V->getValue())->getZExtValue(); }; - auto getMDString = [&](unsigned Idx) { + auto GetMdString = [MN](unsigned Idx) { llvm::MDString *V = cast<llvm::MDString>(MN->getOperand(Idx)); return V->getString(); }; - switch (getMDInt(0)) { + switch (GetMdInt(0)) { default: llvm_unreachable("Unexpected metadata!"); break; case OffloadEntriesInfoManagerTy::OffloadEntryInfo:: - OFFLOAD_ENTRY_INFO_TARGET_REGION: + OffloadingEntryInfoTargetRegion: OffloadEntriesInfoManager.initializeTargetRegionEntryInfo( - /*DeviceID=*/getMDInt(1), /*FileID=*/getMDInt(2), - /*ParentName=*/getMDString(3), /*Line=*/getMDInt(4), - /*Order=*/getMDInt(5)); + /*DeviceID=*/GetMdInt(1), /*FileID=*/GetMdInt(2), + /*ParentName=*/GetMdString(3), /*Line=*/GetMdInt(4), + /*Order=*/GetMdInt(5)); break; } } @@ -5871,33 +6005,6 @@ void CGOpenMPRuntime::emitCancelCall(CodeGenFunction &CGF, SourceLocation Loc, } } -/// \brief 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 void getTargetEntryUniqueInfo(ASTContext &C, SourceLocation Loc, - unsigned &DeviceID, unsigned &FileID, - unsigned &LineNum) { - - auto &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."); - assert(Loc.isFileID() && "Source location is expected to refer to a file."); - - PresumedLoc PLoc = SM.getPresumedLoc(Loc); - assert(PLoc.isValid() && "Source location is expected to be always valid."); - - llvm::sys::fs::UniqueID ID; - if (llvm::sys::fs::getUniqueID(PLoc.getFilename(), ID)) - llvm_unreachable("Source file with target region no longer exists!"); - - DeviceID = ID.getDevice(); - FileID = ID.getFile(); - LineNum = PLoc.getLine(); -} - void CGOpenMPRuntime::emitTargetOutlinedFunction( const OMPExecutableDirective &D, StringRef ParentName, llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID, @@ -5970,7 +6077,7 @@ void CGOpenMPRuntime::emitTargetOutlinedFunctionHelper( // Register the information for the entry associated with this target region. OffloadEntriesInfoManager.registerTargetRegionEntryInfo( DeviceID, FileID, ParentName, Line, OutlinedFn, OutlinedFnID, - /*Flags=*/0); + OMPTargetRegionEntryTargetRegion); } /// discard all CompoundStmts intervening between two constructs @@ -7530,12 +7637,20 @@ CGOpenMPRuntime::DisableAutoDeclareTargetRAII::~DisableAutoDeclareTargetRAII() { bool CGOpenMPRuntime::markAsGlobalTarget(const FunctionDecl *D) { if (!CGM.getLangOpts().OpenMPIsDevice || !ShouldMarkAsGlobal) return true; + + const FunctionDecl *FD = D->getCanonicalDecl(); // Do not to emit function if it is marked as declare target as it was already // emitted. - if (isDeclareTargetDeclaration(D)) + if (isDeclareTargetDeclaration(D)) { + if (D->hasBody() && AlreadyEmittedTargetFunctions.count(FD) == 0) { + if (auto *F = dyn_cast_or_null<llvm::Function>( + CGM.GetGlobalValue(CGM.getMangledName(D)))) + return !F->isDeclaration(); + return false; + } return true; + } - const FunctionDecl *FD = D->getCanonicalDecl(); // Do not mark member functions except for static. if (const auto *Method = dyn_cast<CXXMethodDecl>(FD)) if (!Method->isStatic()) |