diff options
Diffstat (limited to 'clang/lib/CodeGen')
-rw-r--r-- | clang/lib/CodeGen/CGOpenMPRuntime.cpp | 61 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGOpenMPRuntime.h | 44 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGStmtOpenMP.cpp | 18 |
3 files changed, 118 insertions, 5 deletions
diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp index 7e68c4829e7..813c3681af7 100644 --- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp +++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp @@ -34,6 +34,7 @@ CGOpenMPRuntime::CGOpenMPRuntime(CodeGenModule &CGM) llvm::Type *MicroParams[] = {llvm::PointerType::getUnqual(CGM.Int32Ty), llvm::PointerType::getUnqual(CGM.Int32Ty)}; Kmpc_MicroTy = llvm::FunctionType::get(CGM.VoidTy, MicroParams, true); + KmpCriticalNameTy = llvm::ArrayType::get(CGM.Int32Ty, /*NumElements*/ 8); } llvm::Value * @@ -196,6 +197,66 @@ CGOpenMPRuntime::CreateRuntimeFunction(OpenMPRTLFunction Function) { RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_global_thread_num"); break; } + case OMPRTL__kmpc_critical: { + // Build void __kmpc_critical(ident_t ∗loc, kmp_int32 global_tid, + // kmp_critical_name ∗crit); + llvm::Type *TypeParams[] = { + getIdentTyPointerTy(), CGM.Int32Ty, + llvm::PointerType::getUnqual(KmpCriticalNameTy)}; + llvm::FunctionType *FnTy = + llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); + RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_critical"); + break; + } + case OMPRTL__kmpc_end_critical: { + // Build void __kmpc_end_critical(ident_t ∗loc, kmp_int32 global_tid, + // kmp_critical_name ∗crit); + llvm::Type *TypeParams[] = { + getIdentTyPointerTy(), CGM.Int32Ty, + llvm::PointerType::getUnqual(KmpCriticalNameTy)}; + llvm::FunctionType *FnTy = + llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); + RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_critical"); + break; + } } return RTLFn; } + +llvm::Value *CGOpenMPRuntime::GetCriticalRegionLock(StringRef CriticalName) { + SmallString<256> Buffer; + llvm::raw_svector_ostream Out(Buffer); + Out << ".gomp_critical_user_" << CriticalName << ".var"; + auto RuntimeCriticalName = Out.str(); + auto &Elem = CriticalRegionVarNames.GetOrCreateValue(RuntimeCriticalName); + if (Elem.getValue() != nullptr) + return Elem.getValue(); + + auto Lock = new llvm::GlobalVariable( + CGM.getModule(), KmpCriticalNameTy, /*IsConstant*/ false, + llvm::GlobalValue::CommonLinkage, + llvm::Constant::getNullValue(KmpCriticalNameTy), Elem.getKey()); + Elem.setValue(Lock); + return Lock; +} + +void CGOpenMPRuntime::EmitOMPCriticalRegionStart(CodeGenFunction &CGF, + llvm::Value *RegionLock, + SourceLocation Loc) { + // Prepare other arguments and build a call to __kmpc_critical + llvm::Value *Args[] = {EmitOpenMPUpdateLocation(CGF, Loc), + GetOpenMPGlobalThreadNum(CGF, Loc), RegionLock}; + auto RTLFn = CreateRuntimeFunction(CGOpenMPRuntime::OMPRTL__kmpc_critical); + CGF.EmitRuntimeCall(RTLFn, Args); +} + +void CGOpenMPRuntime::EmitOMPCriticalRegionEnd(CodeGenFunction &CGF, + llvm::Value *RegionLock, + SourceLocation Loc) { + // Prepare other arguments and build a call to __kmpc_critical + llvm::Value *Args[] = {EmitOpenMPUpdateLocation(CGF, Loc), + GetOpenMPGlobalThreadNum(CGF, Loc), RegionLock}; + auto RTLFn = + CreateRuntimeFunction(CGOpenMPRuntime::OMPRTL__kmpc_end_critical); + CGF.EmitRuntimeCall(RTLFn, Args); +} diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.h b/clang/lib/CodeGen/CGOpenMPRuntime.h index 3759a771039..d32c43a8b03 100644 --- a/clang/lib/CodeGen/CGOpenMPRuntime.h +++ b/clang/lib/CodeGen/CGOpenMPRuntime.h @@ -16,6 +16,7 @@ #include "clang/AST/Type.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/StringMap.h" #include "llvm/IR/Type.h" #include "llvm/IR/Value.h" @@ -27,6 +28,7 @@ class Constant; class Function; class Module; class StructLayout; +class ArrayType; class FunctionType; class StructType; class Type; @@ -67,8 +69,14 @@ public: // Call to void __kmpc_fork_call(ident_t *loc, kmp_int32 argc, kmpc_micro // microtask, ...); OMPRTL__kmpc_fork_call, - // Call to kmp_int32 kmpc_global_thread_num(ident_t *loc); - OMPRTL__kmpc_global_thread_num + // Call to __kmpc_int32 kmpc_global_thread_num(ident_t *loc); + OMPRTL__kmpc_global_thread_num, + // Call to void __kmpc_critical(ident_t ∗loc, kmp_int32 global_tid, + // kmp_critical_name ∗crit); + OMPRTL__kmpc_critical, + // Call to void __kmpc_end_critical(ident_t ∗loc, kmp_int32 global_tid, + // kmp_critical_name ∗crit); + OMPRTL__kmpc_end_critical }; private: @@ -134,10 +142,15 @@ private: /// \brief Map of local gtid and functions. typedef llvm::DenseMap<llvm::Function *, llvm::Value *> OpenMPGtidMapTy; OpenMPGtidMapTy OpenMPGtidMap; + /// \brief Type kmp_critical_name, originally defined as typedef kmp_int32 + /// kmp_critical_name[8]; + llvm::ArrayType *KmpCriticalNameTy; + /// \brief Map of critical regions names and the corresponding lock objects. + llvm::StringMap<llvm::Value *, llvm::BumpPtrAllocator> CriticalRegionVarNames; public: explicit CGOpenMPRuntime(CodeGenModule &CGM); - ~CGOpenMPRuntime() {} + virtual ~CGOpenMPRuntime() {} /// \brief Cleans up references to the objects in finished function. /// \param CGF Reference to finished CodeGenFunction. @@ -170,6 +183,31 @@ public: /// \param Function OpenMP runtime function. /// \return Specified function. llvm::Constant *CreateRuntimeFunction(OpenMPRTLFunction Function); + + /// \brief Returns corresponding lock object for the specified critical region + /// name. If the lock object does not exist it is created, otherwise the + /// reference to the existing copy is returned. + llvm::Value *GetCriticalRegionLock(StringRef CriticalName); + + /// \brief Emits start of the critical region by calling void + /// __kmpc_critical(ident_t ∗loc, kmp_int32 global_tid, kmp_critical_name + /// ∗\a RegionLock) + /// \param CGF Reference to current CodeGenFunction. + /// \param RegionLock The lock object for critical region. + /// \param Loc Location of the construct. + virtual void EmitOMPCriticalRegionStart(CodeGenFunction &CGF, + llvm::Value *RegionLock, + SourceLocation Loc); + + /// \brief Emits end of the critical region by calling void + /// __kmpc_end_critical(ident_t ∗loc, kmp_int32 global_tid, kmp_critical_name + /// ∗\a RegionLock) + /// \param CGF Reference to current CodeGenFunction. + /// \param RegionLock The lock object for critical region. + /// \param Loc Location of the construct. + virtual void EmitOMPCriticalRegionEnd(CodeGenFunction &CGF, + llvm::Value *RegionLock, + SourceLocation Loc); }; } // namespace CodeGen } // namespace clang diff --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp index 74b73a55603..6906044b62c 100644 --- a/clang/lib/CodeGen/CGStmtOpenMP.cpp +++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp @@ -98,8 +98,22 @@ void CodeGenFunction::EmitOMPMasterDirective(const OMPMasterDirective &) { llvm_unreachable("CodeGen for 'omp master' is not supported yet."); } -void CodeGenFunction::EmitOMPCriticalDirective(const OMPCriticalDirective &) { - llvm_unreachable("CodeGen for 'omp critical' is not supported yet."); +void CodeGenFunction::EmitOMPCriticalDirective(const OMPCriticalDirective &S) { + // __kmpc_critical(); + // <captured_body> + // __kmpc_end_critical(); + // + + auto Lock = CGM.getOpenMPRuntime().GetCriticalRegionLock( + S.getDirectiveName().getAsString()); + CGM.getOpenMPRuntime().EmitOMPCriticalRegionStart(*this, Lock, + S.getLocStart()); + { + RunCleanupsScope Scope(*this); + EmitStmt(cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt()); + EnsureInsertPoint(); + } + CGM.getOpenMPRuntime().EmitOMPCriticalRegionEnd(*this, Lock, S.getLocEnd()); } void |