clang API Documentation

CGOpenMPRuntime.cpp
Go to the documentation of this file.
00001 //===----- CGOpenMPRuntime.cpp - Interface to OpenMP Runtimes -------------===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 //
00010 // This provides a class for OpenMP runtime code generation.
00011 //
00012 //===----------------------------------------------------------------------===//
00013 
00014 #include "CGOpenMPRuntime.h"
00015 #include "CodeGenFunction.h"
00016 #include "clang/AST/StmtOpenMP.h"
00017 #include "clang/AST/Decl.h"
00018 #include "llvm/ADT/ArrayRef.h"
00019 #include "llvm/IR/CallSite.h"
00020 #include "llvm/IR/DerivedTypes.h"
00021 #include "llvm/IR/GlobalValue.h"
00022 #include "llvm/IR/Value.h"
00023 #include "llvm/Support/raw_ostream.h"
00024 #include <cassert>
00025 
00026 using namespace clang;
00027 using namespace CodeGen;
00028 
00029 namespace {
00030 /// \brief API for captured statement code generation in OpenMP constructs.
00031 class CGOpenMPRegionInfo : public CodeGenFunction::CGCapturedStmtInfo {
00032 public:
00033   CGOpenMPRegionInfo(const OMPExecutableDirective &D, const CapturedStmt &CS,
00034                      const VarDecl *ThreadIDVar)
00035       : CGCapturedStmtInfo(CS, CR_OpenMP), ThreadIDVar(ThreadIDVar),
00036         Directive(D) {
00037     assert(ThreadIDVar != nullptr && "No ThreadID in OpenMP region.");
00038   }
00039 
00040   /// \brief Gets a variable or parameter for storing global thread id
00041   /// inside OpenMP construct.
00042   const VarDecl *getThreadIDVariable() const { return ThreadIDVar; }
00043 
00044   /// \brief Gets an LValue for the current ThreadID variable.
00045   LValue getThreadIDVariableLValue(CodeGenFunction &CGF);
00046 
00047   static bool classof(const CGCapturedStmtInfo *Info) {
00048     return Info->getKind() == CR_OpenMP;
00049   }
00050 
00051   /// \brief Emit the captured statement body.
00052   void EmitBody(CodeGenFunction &CGF, Stmt *S) override;
00053 
00054   /// \brief Get the name of the capture helper.
00055   StringRef getHelperName() const override { return ".omp_outlined."; }
00056 
00057 private:
00058   /// \brief A variable or parameter storing global thread id for OpenMP
00059   /// constructs.
00060   const VarDecl *ThreadIDVar;
00061   /// \brief OpenMP executable directive associated with the region.
00062   const OMPExecutableDirective &Directive;
00063 };
00064 } // namespace
00065 
00066 LValue CGOpenMPRegionInfo::getThreadIDVariableLValue(CodeGenFunction &CGF) {
00067   return CGF.MakeNaturalAlignAddrLValue(
00068       CGF.GetAddrOfLocalVar(ThreadIDVar),
00069       CGF.getContext().getPointerType(ThreadIDVar->getType()));
00070 }
00071 
00072 void CGOpenMPRegionInfo::EmitBody(CodeGenFunction &CGF, Stmt *S) {
00073   CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
00074   CGF.EmitOMPPrivateClause(Directive, PrivateScope);
00075   CGF.EmitOMPFirstprivateClause(Directive, PrivateScope);
00076   if (PrivateScope.Privatize()) {
00077     // Emit implicit barrier to synchronize threads and avoid data races.
00078     auto Flags = static_cast<CGOpenMPRuntime::OpenMPLocationFlags>(
00079         CGOpenMPRuntime::OMP_IDENT_KMPC |
00080         CGOpenMPRuntime::OMP_IDENT_BARRIER_IMPL);
00081     CGF.CGM.getOpenMPRuntime().EmitOMPBarrierCall(CGF, Directive.getLocStart(),
00082                                                   Flags);
00083   }
00084   CGCapturedStmtInfo::EmitBody(CGF, S);
00085 }
00086 
00087 CGOpenMPRuntime::CGOpenMPRuntime(CodeGenModule &CGM)
00088     : CGM(CGM), DefaultOpenMPPSource(nullptr) {
00089   IdentTy = llvm::StructType::create(
00090       "ident_t", CGM.Int32Ty /* reserved_1 */, CGM.Int32Ty /* flags */,
00091       CGM.Int32Ty /* reserved_2 */, CGM.Int32Ty /* reserved_3 */,
00092       CGM.Int8PtrTy /* psource */, nullptr);
00093   // Build void (*kmpc_micro)(kmp_int32 *global_tid, kmp_int32 *bound_tid,...)
00094   llvm::Type *MicroParams[] = {llvm::PointerType::getUnqual(CGM.Int32Ty),
00095                                llvm::PointerType::getUnqual(CGM.Int32Ty)};
00096   Kmpc_MicroTy = llvm::FunctionType::get(CGM.VoidTy, MicroParams, true);
00097   KmpCriticalNameTy = llvm::ArrayType::get(CGM.Int32Ty, /*NumElements*/ 8);
00098 }
00099 
00100 llvm::Value *
00101 CGOpenMPRuntime::EmitOpenMPOutlinedFunction(const OMPExecutableDirective &D,
00102                                             const VarDecl *ThreadIDVar) {
00103   const CapturedStmt *CS = cast<CapturedStmt>(D.getAssociatedStmt());
00104   CodeGenFunction CGF(CGM, true);
00105   CGOpenMPRegionInfo CGInfo(D, *CS, ThreadIDVar);
00106   CGF.CapturedStmtInfo = &CGInfo;
00107   return CGF.GenerateCapturedStmtFunction(*CS);
00108 }
00109 
00110 llvm::Value *
00111 CGOpenMPRuntime::GetOrCreateDefaultOpenMPLocation(OpenMPLocationFlags Flags) {
00112   llvm::Value *Entry = OpenMPDefaultLocMap.lookup(Flags);
00113   if (!Entry) {
00114     if (!DefaultOpenMPPSource) {
00115       // Initialize default location for psource field of ident_t structure of
00116       // all ident_t objects. Format is ";file;function;line;column;;".
00117       // Taken from
00118       // http://llvm.org/svn/llvm-project/openmp/trunk/runtime/src/kmp_str.c
00119       DefaultOpenMPPSource =
00120           CGM.GetAddrOfConstantCString(";unknown;unknown;0;0;;");
00121       DefaultOpenMPPSource =
00122           llvm::ConstantExpr::getBitCast(DefaultOpenMPPSource, CGM.Int8PtrTy);
00123     }
00124     auto DefaultOpenMPLocation = new llvm::GlobalVariable(
00125         CGM.getModule(), IdentTy, /*isConstant*/ true,
00126         llvm::GlobalValue::PrivateLinkage, /*Initializer*/ nullptr);
00127     DefaultOpenMPLocation->setUnnamedAddr(true);
00128 
00129     llvm::Constant *Zero = llvm::ConstantInt::get(CGM.Int32Ty, 0, true);
00130     llvm::Constant *Values[] = {Zero,
00131                                 llvm::ConstantInt::get(CGM.Int32Ty, Flags),
00132                                 Zero, Zero, DefaultOpenMPPSource};
00133     llvm::Constant *Init = llvm::ConstantStruct::get(IdentTy, Values);
00134     DefaultOpenMPLocation->setInitializer(Init);
00135     OpenMPDefaultLocMap[Flags] = DefaultOpenMPLocation;
00136     return DefaultOpenMPLocation;
00137   }
00138   return Entry;
00139 }
00140 
00141 llvm::Value *CGOpenMPRuntime::EmitOpenMPUpdateLocation(
00142     CodeGenFunction &CGF, SourceLocation Loc, OpenMPLocationFlags Flags) {
00143   // If no debug info is generated - return global default location.
00144   if (CGM.getCodeGenOpts().getDebugInfo() == CodeGenOptions::NoDebugInfo ||
00145       Loc.isInvalid())
00146     return GetOrCreateDefaultOpenMPLocation(Flags);
00147 
00148   assert(CGF.CurFn && "No function in current CodeGenFunction.");
00149 
00150   llvm::Value *LocValue = nullptr;
00151   OpenMPLocThreadIDMapTy::iterator I = OpenMPLocThreadIDMap.find(CGF.CurFn);
00152   if (I != OpenMPLocThreadIDMap.end()) {
00153     LocValue = I->second.DebugLoc;
00154   } else {
00155     // Generate "ident_t .kmpc_loc.addr;"
00156     llvm::AllocaInst *AI = CGF.CreateTempAlloca(IdentTy, ".kmpc_loc.addr");
00157     AI->setAlignment(CGM.getDataLayout().getPrefTypeAlignment(IdentTy));
00158     auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn);
00159     Elem.second.DebugLoc = AI;
00160     LocValue = AI;
00161 
00162     CGBuilderTy::InsertPointGuard IPG(CGF.Builder);
00163     CGF.Builder.SetInsertPoint(CGF.AllocaInsertPt);
00164     CGF.Builder.CreateMemCpy(LocValue, GetOrCreateDefaultOpenMPLocation(Flags),
00165                              llvm::ConstantExpr::getSizeOf(IdentTy),
00166                              CGM.PointerAlignInBytes);
00167   }
00168 
00169   // char **psource = &.kmpc_loc_<flags>.addr.psource;
00170   llvm::Value *PSource =
00171       CGF.Builder.CreateConstInBoundsGEP2_32(LocValue, 0, IdentField_PSource);
00172 
00173   auto OMPDebugLoc = OpenMPDebugLocMap.lookup(Loc.getRawEncoding());
00174   if (OMPDebugLoc == nullptr) {
00175     SmallString<128> Buffer2;
00176     llvm::raw_svector_ostream OS2(Buffer2);
00177     // Build debug location
00178     PresumedLoc PLoc = CGF.getContext().getSourceManager().getPresumedLoc(Loc);
00179     OS2 << ";" << PLoc.getFilename() << ";";
00180     if (const FunctionDecl *FD =
00181             dyn_cast_or_null<FunctionDecl>(CGF.CurFuncDecl)) {
00182       OS2 << FD->getQualifiedNameAsString();
00183     }
00184     OS2 << ";" << PLoc.getLine() << ";" << PLoc.getColumn() << ";;";
00185     OMPDebugLoc = CGF.Builder.CreateGlobalStringPtr(OS2.str());
00186     OpenMPDebugLocMap[Loc.getRawEncoding()] = OMPDebugLoc;
00187   }
00188   // *psource = ";<File>;<Function>;<Line>;<Column>;;";
00189   CGF.Builder.CreateStore(OMPDebugLoc, PSource);
00190 
00191   return LocValue;
00192 }
00193 
00194 llvm::Value *CGOpenMPRuntime::GetOpenMPThreadID(CodeGenFunction &CGF,
00195                                                 SourceLocation Loc) {
00196   assert(CGF.CurFn && "No function in current CodeGenFunction.");
00197 
00198   llvm::Value *ThreadID = nullptr;
00199   // Check whether we've already cached a load of the thread id in this
00200   // function.
00201   OpenMPLocThreadIDMapTy::iterator I = OpenMPLocThreadIDMap.find(CGF.CurFn);
00202   if (I != OpenMPLocThreadIDMap.end()) {
00203     ThreadID = I->second.ThreadID;
00204     if (ThreadID != nullptr)
00205       return ThreadID;
00206   }
00207   if (auto OMPRegionInfo =
00208                  dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) {
00209     // Check if this an outlined function with thread id passed as argument.
00210     auto ThreadIDVar = OMPRegionInfo->getThreadIDVariable();
00211     auto LVal = OMPRegionInfo->getThreadIDVariableLValue(CGF);
00212     auto RVal = CGF.EmitLoadOfLValue(LVal, Loc);
00213     LVal = CGF.MakeNaturalAlignAddrLValue(RVal.getScalarVal(),
00214                                           ThreadIDVar->getType());
00215     ThreadID = CGF.EmitLoadOfLValue(LVal, Loc).getScalarVal();
00216     // If value loaded in entry block, cache it and use it everywhere in
00217     // function.
00218     if (CGF.Builder.GetInsertBlock() == CGF.AllocaInsertPt->getParent()) {
00219       auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn);
00220       Elem.second.ThreadID = ThreadID;
00221     }
00222   } else {
00223     // This is not an outlined function region - need to call __kmpc_int32
00224     // kmpc_global_thread_num(ident_t *loc).
00225     // Generate thread id value and cache this value for use across the
00226     // function.
00227     CGBuilderTy::InsertPointGuard IPG(CGF.Builder);
00228     CGF.Builder.SetInsertPoint(CGF.AllocaInsertPt);
00229     llvm::Value *Args[] = {EmitOpenMPUpdateLocation(CGF, Loc)};
00230     ThreadID = CGF.EmitRuntimeCall(
00231         CreateRuntimeFunction(OMPRTL__kmpc_global_thread_num), Args);
00232     auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn);
00233     Elem.second.ThreadID = ThreadID;
00234   }
00235   return ThreadID;
00236 }
00237 
00238 void CGOpenMPRuntime::FunctionFinished(CodeGenFunction &CGF) {
00239   assert(CGF.CurFn && "No function in current CodeGenFunction.");
00240   if (OpenMPLocThreadIDMap.count(CGF.CurFn))
00241     OpenMPLocThreadIDMap.erase(CGF.CurFn);
00242 }
00243 
00244 llvm::Type *CGOpenMPRuntime::getIdentTyPointerTy() {
00245   return llvm::PointerType::getUnqual(IdentTy);
00246 }
00247 
00248 llvm::Type *CGOpenMPRuntime::getKmpc_MicroPointerTy() {
00249   return llvm::PointerType::getUnqual(Kmpc_MicroTy);
00250 }
00251 
00252 llvm::Constant *
00253 CGOpenMPRuntime::CreateRuntimeFunction(OpenMPRTLFunction Function) {
00254   llvm::Constant *RTLFn = nullptr;
00255   switch (Function) {
00256   case OMPRTL__kmpc_fork_call: {
00257     // Build void __kmpc_fork_call(ident_t *loc, kmp_int32 argc, kmpc_micro
00258     // microtask, ...);
00259     llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
00260                                 getKmpc_MicroPointerTy()};
00261     llvm::FunctionType *FnTy =
00262         llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ true);
00263     RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_fork_call");
00264     break;
00265   }
00266   case OMPRTL__kmpc_global_thread_num: {
00267     // Build kmp_int32 __kmpc_global_thread_num(ident_t *loc);
00268     llvm::Type *TypeParams[] = {getIdentTyPointerTy()};
00269     llvm::FunctionType *FnTy =
00270         llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
00271     RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_global_thread_num");
00272     break;
00273   }
00274   case OMPRTL__kmpc_threadprivate_cached: {
00275     // Build void *__kmpc_threadprivate_cached(ident_t *loc,
00276     // kmp_int32 global_tid, void *data, size_t size, void ***cache);
00277     llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
00278                                 CGM.VoidPtrTy, CGM.SizeTy,
00279                                 CGM.VoidPtrTy->getPointerTo()->getPointerTo()};
00280     llvm::FunctionType *FnTy =
00281         llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg*/ false);
00282     RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_threadprivate_cached");
00283     break;
00284   }
00285   case OMPRTL__kmpc_critical: {
00286     // Build void __kmpc_critical(ident_t *loc, kmp_int32 global_tid,
00287     // kmp_critical_name *crit);
00288     llvm::Type *TypeParams[] = {
00289         getIdentTyPointerTy(), CGM.Int32Ty,
00290         llvm::PointerType::getUnqual(KmpCriticalNameTy)};
00291     llvm::FunctionType *FnTy =
00292         llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
00293     RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_critical");
00294     break;
00295   }
00296   case OMPRTL__kmpc_threadprivate_register: {
00297     // Build void __kmpc_threadprivate_register(ident_t *, void *data,
00298     // kmpc_ctor ctor, kmpc_cctor cctor, kmpc_dtor dtor);
00299     // typedef void *(*kmpc_ctor)(void *);
00300     auto KmpcCtorTy =
00301         llvm::FunctionType::get(CGM.VoidPtrTy, CGM.VoidPtrTy,
00302                                 /*isVarArg*/ false)->getPointerTo();
00303     // typedef void *(*kmpc_cctor)(void *, void *);
00304     llvm::Type *KmpcCopyCtorTyArgs[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
00305     auto KmpcCopyCtorTy =
00306         llvm::FunctionType::get(CGM.VoidPtrTy, KmpcCopyCtorTyArgs,
00307                                 /*isVarArg*/ false)->getPointerTo();
00308     // typedef void (*kmpc_dtor)(void *);
00309     auto KmpcDtorTy =
00310         llvm::FunctionType::get(CGM.VoidTy, CGM.VoidPtrTy, /*isVarArg*/ false)
00311             ->getPointerTo();
00312     llvm::Type *FnTyArgs[] = {getIdentTyPointerTy(), CGM.VoidPtrTy, KmpcCtorTy,
00313                               KmpcCopyCtorTy, KmpcDtorTy};
00314     auto FnTy = llvm::FunctionType::get(CGM.VoidTy, FnTyArgs,
00315                                         /*isVarArg*/ false);
00316     RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_threadprivate_register");
00317     break;
00318   }
00319   case OMPRTL__kmpc_end_critical: {
00320     // Build void __kmpc_end_critical(ident_t *loc, kmp_int32 global_tid,
00321     // kmp_critical_name *crit);
00322     llvm::Type *TypeParams[] = {
00323         getIdentTyPointerTy(), CGM.Int32Ty,
00324         llvm::PointerType::getUnqual(KmpCriticalNameTy)};
00325     llvm::FunctionType *FnTy =
00326         llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
00327     RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_critical");
00328     break;
00329   }
00330   case OMPRTL__kmpc_barrier: {
00331     // Build void __kmpc_barrier(ident_t *loc, kmp_int32 global_tid);
00332     llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
00333     llvm::FunctionType *FnTy =
00334         llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
00335     RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name*/ "__kmpc_barrier");
00336     break;
00337   }
00338   case OMPRTL__kmpc_push_num_threads: {
00339     // Build void __kmpc_push_num_threads(ident_t *loc, kmp_int32 global_tid,
00340     // kmp_int32 num_threads)
00341     llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
00342                                 CGM.Int32Ty};
00343     llvm::FunctionType *FnTy =
00344         llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
00345     RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_num_threads");
00346     break;
00347   }
00348   case OMPRTL__kmpc_serialized_parallel: {
00349     // Build void __kmpc_serialized_parallel(ident_t *loc, kmp_int32
00350     // global_tid);
00351     llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
00352     llvm::FunctionType *FnTy =
00353         llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
00354     RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_serialized_parallel");
00355     break;
00356   }
00357   case OMPRTL__kmpc_end_serialized_parallel: {
00358     // Build void __kmpc_end_serialized_parallel(ident_t *loc, kmp_int32
00359     // global_tid);
00360     llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
00361     llvm::FunctionType *FnTy =
00362         llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
00363     RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_serialized_parallel");
00364     break;
00365   }
00366   }
00367   return RTLFn;
00368 }
00369 
00370 llvm::Constant *
00371 CGOpenMPRuntime::getOrCreateThreadPrivateCache(const VarDecl *VD) {
00372   // Lookup the entry, lazily creating it if necessary.
00373   return GetOrCreateInternalVariable(CGM.Int8PtrPtrTy,
00374                                      Twine(CGM.getMangledName(VD)) + ".cache.");
00375 }
00376 
00377 llvm::Value *CGOpenMPRuntime::getOMPAddrOfThreadPrivate(CodeGenFunction &CGF,
00378                                                         const VarDecl *VD,
00379                                                         llvm::Value *VDAddr,
00380                                                         SourceLocation Loc) {
00381   auto VarTy = VDAddr->getType()->getPointerElementType();
00382   llvm::Value *Args[] = {EmitOpenMPUpdateLocation(CGF, Loc),
00383                          GetOpenMPThreadID(CGF, Loc),
00384                          CGF.Builder.CreatePointerCast(VDAddr, CGM.Int8PtrTy),
00385                          CGM.getSize(CGM.GetTargetTypeStoreSize(VarTy)),
00386                          getOrCreateThreadPrivateCache(VD)};
00387   return CGF.EmitRuntimeCall(
00388       CreateRuntimeFunction(OMPRTL__kmpc_threadprivate_cached), Args);
00389 }
00390 
00391 void CGOpenMPRuntime::EmitOMPThreadPrivateVarInit(
00392     CodeGenFunction &CGF, llvm::Value *VDAddr, llvm::Value *Ctor,
00393     llvm::Value *CopyCtor, llvm::Value *Dtor, SourceLocation Loc) {
00394   // Call kmp_int32 __kmpc_global_thread_num(&loc) to init OpenMP runtime
00395   // library.
00396   auto OMPLoc = EmitOpenMPUpdateLocation(CGF, Loc);
00397   CGF.EmitRuntimeCall(CreateRuntimeFunction(OMPRTL__kmpc_global_thread_num),
00398                       OMPLoc);
00399   // Call __kmpc_threadprivate_register(&loc, &var, ctor, cctor/*NULL*/, dtor)
00400   // to register constructor/destructor for variable.
00401   llvm::Value *Args[] = {OMPLoc,
00402                          CGF.Builder.CreatePointerCast(VDAddr, CGM.VoidPtrTy),
00403                          Ctor, CopyCtor, Dtor};
00404   CGF.EmitRuntimeCall(CreateRuntimeFunction(
00405                           CGOpenMPRuntime::OMPRTL__kmpc_threadprivate_register),
00406                       Args);
00407 }
00408 
00409 llvm::Function *CGOpenMPRuntime::EmitOMPThreadPrivateVarDefinition(
00410     const VarDecl *VD, llvm::Value *VDAddr, SourceLocation Loc,
00411     bool PerformInit, CodeGenFunction *CGF) {
00412   VD = VD->getDefinition(CGM.getContext());
00413   if (VD && ThreadPrivateWithDefinition.count(VD) == 0) {
00414     ThreadPrivateWithDefinition.insert(VD);
00415     QualType ASTTy = VD->getType();
00416 
00417     llvm::Value *Ctor = nullptr, *CopyCtor = nullptr, *Dtor = nullptr;
00418     auto Init = VD->getAnyInitializer();
00419     if (CGM.getLangOpts().CPlusPlus && PerformInit) {
00420       // Generate function that re-emits the declaration's initializer into the
00421       // threadprivate copy of the variable VD
00422       CodeGenFunction CtorCGF(CGM);
00423       FunctionArgList Args;
00424       ImplicitParamDecl Dst(CGM.getContext(), /*DC=*/nullptr, SourceLocation(),
00425                             /*Id=*/nullptr, CGM.getContext().VoidPtrTy);
00426       Args.push_back(&Dst);
00427 
00428       auto &FI = CGM.getTypes().arrangeFreeFunctionDeclaration(
00429           CGM.getContext().VoidPtrTy, Args, FunctionType::ExtInfo(),
00430           /*isVariadic=*/false);
00431       auto FTy = CGM.getTypes().GetFunctionType(FI);
00432       auto Fn = CGM.CreateGlobalInitOrDestructFunction(
00433           FTy, ".__kmpc_global_ctor_.", Loc);
00434       CtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidPtrTy, Fn, FI,
00435                             Args, SourceLocation());
00436       auto ArgVal = CtorCGF.EmitLoadOfScalar(
00437           CtorCGF.GetAddrOfLocalVar(&Dst),
00438           /*Volatile=*/false, CGM.PointerAlignInBytes,
00439           CGM.getContext().VoidPtrTy, Dst.getLocation());
00440       auto Arg = CtorCGF.Builder.CreatePointerCast(
00441           ArgVal,
00442           CtorCGF.ConvertTypeForMem(CGM.getContext().getPointerType(ASTTy)));
00443       CtorCGF.EmitAnyExprToMem(Init, Arg, Init->getType().getQualifiers(),
00444                                /*IsInitializer=*/true);
00445       ArgVal = CtorCGF.EmitLoadOfScalar(
00446           CtorCGF.GetAddrOfLocalVar(&Dst),
00447           /*Volatile=*/false, CGM.PointerAlignInBytes,
00448           CGM.getContext().VoidPtrTy, Dst.getLocation());
00449       CtorCGF.Builder.CreateStore(ArgVal, CtorCGF.ReturnValue);
00450       CtorCGF.FinishFunction();
00451       Ctor = Fn;
00452     }
00453     if (VD->getType().isDestructedType() != QualType::DK_none) {
00454       // Generate function that emits destructor call for the threadprivate copy
00455       // of the variable VD
00456       CodeGenFunction DtorCGF(CGM);
00457       FunctionArgList Args;
00458       ImplicitParamDecl Dst(CGM.getContext(), /*DC=*/nullptr, SourceLocation(),
00459                             /*Id=*/nullptr, CGM.getContext().VoidPtrTy);
00460       Args.push_back(&Dst);
00461 
00462       auto &FI = CGM.getTypes().arrangeFreeFunctionDeclaration(
00463           CGM.getContext().VoidTy, Args, FunctionType::ExtInfo(),
00464           /*isVariadic=*/false);
00465       auto FTy = CGM.getTypes().GetFunctionType(FI);
00466       auto Fn = CGM.CreateGlobalInitOrDestructFunction(
00467           FTy, ".__kmpc_global_dtor_.", Loc);
00468       DtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI, Args,
00469                             SourceLocation());
00470       auto ArgVal = DtorCGF.EmitLoadOfScalar(
00471           DtorCGF.GetAddrOfLocalVar(&Dst),
00472           /*Volatile=*/false, CGM.PointerAlignInBytes,
00473           CGM.getContext().VoidPtrTy, Dst.getLocation());
00474       DtorCGF.emitDestroy(ArgVal, ASTTy,
00475                           DtorCGF.getDestroyer(ASTTy.isDestructedType()),
00476                           DtorCGF.needsEHCleanup(ASTTy.isDestructedType()));
00477       DtorCGF.FinishFunction();
00478       Dtor = Fn;
00479     }
00480     // Do not emit init function if it is not required.
00481     if (!Ctor && !Dtor)
00482       return nullptr;
00483 
00484     llvm::Type *CopyCtorTyArgs[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
00485     auto CopyCtorTy =
00486         llvm::FunctionType::get(CGM.VoidPtrTy, CopyCtorTyArgs,
00487                                 /*isVarArg=*/false)->getPointerTo();
00488     // Copying constructor for the threadprivate variable.
00489     // Must be NULL - reserved by runtime, but currently it requires that this
00490     // parameter is always NULL. Otherwise it fires assertion.
00491     CopyCtor = llvm::Constant::getNullValue(CopyCtorTy);
00492     if (Ctor == nullptr) {
00493       auto CtorTy = llvm::FunctionType::get(CGM.VoidPtrTy, CGM.VoidPtrTy,
00494                                             /*isVarArg=*/false)->getPointerTo();
00495       Ctor = llvm::Constant::getNullValue(CtorTy);
00496     }
00497     if (Dtor == nullptr) {
00498       auto DtorTy = llvm::FunctionType::get(CGM.VoidTy, CGM.VoidPtrTy,
00499                                             /*isVarArg=*/false)->getPointerTo();
00500       Dtor = llvm::Constant::getNullValue(DtorTy);
00501     }
00502     if (!CGF) {
00503       auto InitFunctionTy =
00504           llvm::FunctionType::get(CGM.VoidTy, /*isVarArg*/ false);
00505       auto InitFunction = CGM.CreateGlobalInitOrDestructFunction(
00506           InitFunctionTy, ".__omp_threadprivate_init_.");
00507       CodeGenFunction InitCGF(CGM);
00508       FunctionArgList ArgList;
00509       InitCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, InitFunction,
00510                             CGM.getTypes().arrangeNullaryFunction(), ArgList,
00511                             Loc);
00512       EmitOMPThreadPrivateVarInit(InitCGF, VDAddr, Ctor, CopyCtor, Dtor, Loc);
00513       InitCGF.FinishFunction();
00514       return InitFunction;
00515     }
00516     EmitOMPThreadPrivateVarInit(*CGF, VDAddr, Ctor, CopyCtor, Dtor, Loc);
00517   }
00518   return nullptr;
00519 }
00520 
00521 void CGOpenMPRuntime::EmitOMPParallelCall(CodeGenFunction &CGF,
00522                                           SourceLocation Loc,
00523                                           llvm::Value *OutlinedFn,
00524                                           llvm::Value *CapturedStruct) {
00525   // Build call __kmpc_fork_call(loc, 1, microtask, captured_struct/*context*/)
00526   llvm::Value *Args[] = {
00527       EmitOpenMPUpdateLocation(CGF, Loc),
00528       CGF.Builder.getInt32(1), // Number of arguments after 'microtask' argument
00529       // (there is only one additional argument - 'context')
00530       CGF.Builder.CreateBitCast(OutlinedFn, getKmpc_MicroPointerTy()),
00531       CGF.EmitCastToVoidPtr(CapturedStruct)};
00532   auto RTLFn = CreateRuntimeFunction(CGOpenMPRuntime::OMPRTL__kmpc_fork_call);
00533   CGF.EmitRuntimeCall(RTLFn, Args);
00534 }
00535 
00536 void CGOpenMPRuntime::EmitOMPSerialCall(CodeGenFunction &CGF,
00537                                         SourceLocation Loc,
00538                                         llvm::Value *OutlinedFn,
00539                                         llvm::Value *CapturedStruct) {
00540   auto ThreadID = GetOpenMPThreadID(CGF, Loc);
00541   // Build calls:
00542   // __kmpc_serialized_parallel(&Loc, GTid);
00543   llvm::Value *SerArgs[] = {EmitOpenMPUpdateLocation(CGF, Loc), ThreadID};
00544   auto RTLFn =
00545       CreateRuntimeFunction(CGOpenMPRuntime::OMPRTL__kmpc_serialized_parallel);
00546   CGF.EmitRuntimeCall(RTLFn, SerArgs);
00547 
00548   // OutlinedFn(&GTid, &zero, CapturedStruct);
00549   auto ThreadIDAddr = EmitThreadIDAddress(CGF, Loc);
00550   auto Int32Ty =
00551       CGF.getContext().getIntTypeForBitwidth(/*DestWidth*/ 32, /*Signed*/ true);
00552   auto ZeroAddr = CGF.CreateMemTemp(Int32Ty, /*Name*/ ".zero.addr");
00553   CGF.InitTempAlloca(ZeroAddr, CGF.Builder.getInt32(/*C*/ 0));
00554   llvm::Value *OutlinedFnArgs[] = {ThreadIDAddr, ZeroAddr, CapturedStruct};
00555   CGF.EmitCallOrInvoke(OutlinedFn, OutlinedFnArgs);
00556 
00557   // __kmpc_end_serialized_parallel(&Loc, GTid);
00558   llvm::Value *EndSerArgs[] = {EmitOpenMPUpdateLocation(CGF, Loc), ThreadID};
00559   RTLFn = CreateRuntimeFunction(
00560       CGOpenMPRuntime::OMPRTL__kmpc_end_serialized_parallel);
00561   CGF.EmitRuntimeCall(RTLFn, EndSerArgs);
00562 }
00563 
00564 // If we're inside an (outlined) parallel region, use the region info's
00565 // thread-ID variable (it is passed in a first argument of the outlined function
00566 // as "kmp_int32 *gtid"). Otherwise, if we're not inside parallel region, but in
00567 // regular serial code region, get thread ID by calling kmp_int32
00568 // kmpc_global_thread_num(ident_t *loc), stash this thread ID in a temporary and
00569 // return the address of that temp.
00570 llvm::Value *CGOpenMPRuntime::EmitThreadIDAddress(CodeGenFunction &CGF,
00571                                                   SourceLocation Loc) {
00572   if (auto OMPRegionInfo =
00573           dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo))
00574     return CGF.EmitLoadOfLValue(OMPRegionInfo->getThreadIDVariableLValue(CGF),
00575                                 SourceLocation()).getScalarVal();
00576   auto ThreadID = GetOpenMPThreadID(CGF, Loc);
00577   auto Int32Ty =
00578       CGF.getContext().getIntTypeForBitwidth(/*DestWidth*/ 32, /*Signed*/ true);
00579   auto ThreadIDTemp = CGF.CreateMemTemp(Int32Ty, /*Name*/ ".threadid_temp.");
00580   CGF.EmitStoreOfScalar(ThreadID,
00581                         CGF.MakeNaturalAlignAddrLValue(ThreadIDTemp, Int32Ty));
00582 
00583   return ThreadIDTemp;
00584 }
00585 
00586 llvm::Constant *
00587 CGOpenMPRuntime::GetOrCreateInternalVariable(llvm::Type *Ty,
00588                                              const llvm::Twine &Name) {
00589   SmallString<256> Buffer;
00590   llvm::raw_svector_ostream Out(Buffer);
00591   Out << Name;
00592   auto RuntimeName = Out.str();
00593   auto &Elem = InternalVars.GetOrCreateValue(RuntimeName);
00594   if (Elem.getValue()) {
00595     assert(Elem.getValue()->getType()->getPointerElementType() == Ty &&
00596            "OMP internal variable has different type than requested");
00597     return &*Elem.getValue();
00598   }
00599 
00600   auto Item = new llvm::GlobalVariable(
00601       CGM.getModule(), Ty, /*IsConstant*/ false,
00602       llvm::GlobalValue::CommonLinkage,
00603       llvm::Constant::getNullValue(Ty), Elem.getKey());
00604   Elem.setValue(Item);
00605   return Item;
00606 }
00607 
00608 llvm::Value *CGOpenMPRuntime::GetCriticalRegionLock(StringRef CriticalName) {
00609   llvm::Twine Name(".gomp_critical_user_", CriticalName);
00610   return GetOrCreateInternalVariable(KmpCriticalNameTy, Name.concat(".var"));
00611 }
00612 
00613 void CGOpenMPRuntime::EmitOMPCriticalRegionStart(CodeGenFunction &CGF,
00614                                                  llvm::Value *RegionLock,
00615                                                  SourceLocation Loc) {
00616   // Prepare other arguments and build a call to __kmpc_critical
00617   llvm::Value *Args[] = {EmitOpenMPUpdateLocation(CGF, Loc),
00618                          GetOpenMPThreadID(CGF, Loc), RegionLock};
00619   auto RTLFn = CreateRuntimeFunction(CGOpenMPRuntime::OMPRTL__kmpc_critical);
00620   CGF.EmitRuntimeCall(RTLFn, Args);
00621 }
00622 
00623 void CGOpenMPRuntime::EmitOMPCriticalRegionEnd(CodeGenFunction &CGF,
00624                                                llvm::Value *RegionLock,
00625                                                SourceLocation Loc) {
00626   // Prepare other arguments and build a call to __kmpc_end_critical
00627   llvm::Value *Args[] = {EmitOpenMPUpdateLocation(CGF, Loc),
00628                          GetOpenMPThreadID(CGF, Loc), RegionLock};
00629   auto RTLFn =
00630       CreateRuntimeFunction(CGOpenMPRuntime::OMPRTL__kmpc_end_critical);
00631   CGF.EmitRuntimeCall(RTLFn, Args);
00632 }
00633 
00634 void CGOpenMPRuntime::EmitOMPBarrierCall(CodeGenFunction &CGF,
00635                                          SourceLocation Loc,
00636                                          OpenMPLocationFlags Flags) {
00637   // Build call __kmpc_barrier(loc, thread_id)
00638   llvm::Value *Args[] = {EmitOpenMPUpdateLocation(CGF, Loc, Flags),
00639                          GetOpenMPThreadID(CGF, Loc)};
00640   auto RTLFn = CreateRuntimeFunction(CGOpenMPRuntime::OMPRTL__kmpc_barrier);
00641   CGF.EmitRuntimeCall(RTLFn, Args);
00642 }
00643 
00644 void CGOpenMPRuntime::EmitOMPNumThreadsClause(CodeGenFunction &CGF,
00645                                               llvm::Value *NumThreads,
00646                                               SourceLocation Loc) {
00647   // Build call __kmpc_push_num_threads(&loc, global_tid, num_threads)
00648   llvm::Value *Args[] = {
00649       EmitOpenMPUpdateLocation(CGF, Loc), GetOpenMPThreadID(CGF, Loc),
00650       CGF.Builder.CreateIntCast(NumThreads, CGF.Int32Ty, /*isSigned*/ true)};
00651   llvm::Constant *RTLFn = CGF.CGM.getOpenMPRuntime().CreateRuntimeFunction(
00652       CGOpenMPRuntime::OMPRTL__kmpc_push_num_threads);
00653   CGF.EmitRuntimeCall(RTLFn, Args);
00654 }
00655