summaryrefslogtreecommitdiffstats
path: root/clang/lib/CodeGen
diff options
context:
space:
mode:
authorAlexey Bataev <a.bataev@hotmail.com>2014-09-22 10:01:53 +0000
committerAlexey Bataev <a.bataev@hotmail.com>2014-09-22 10:01:53 +0000
commit3a3bf0bbe35fee25219e075ee9b76abb8633c24b (patch)
tree3010cda60f887c06f50ed0323ed9ee4d6ec59c72 /clang/lib/CodeGen
parentb105a2c3e07f49e3af7400d7e58de52acfd2c733 (diff)
downloadbcm5719-llvm-3a3bf0bbe35fee25219e075ee9b76abb8633c24b.tar.gz
bcm5719-llvm-3a3bf0bbe35fee25219e075ee9b76abb8633c24b.zip
[OPENMP] Codegen for 'omp critical' directive.
This patch adds codegen for constructs: #pragma omp critical [name] <body> It generates global variable ".gomp_critical_user_[name].var" of type int32[8]. Then it generates library call "kmpc_critical(loc, gtid, .gomp_critical_user_[name].var)", code for <body> statement and final call "kmpc_end_critical(loc, gtid, .gomp_critical_user_[name].var)". Differential Revision: http://reviews.llvm.org/D5202 llvm-svn: 218239
Diffstat (limited to 'clang/lib/CodeGen')
-rw-r--r--clang/lib/CodeGen/CGOpenMPRuntime.cpp61
-rw-r--r--clang/lib/CodeGen/CGOpenMPRuntime.h44
-rw-r--r--clang/lib/CodeGen/CGStmtOpenMP.cpp18
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
OpenPOWER on IntegriCloud