r218239 - [OPENMP] Codegen for 'omp critical' directive.
Alexey Bataev
a.bataev at hotmail.com
Mon Sep 22 03:01:54 PDT 2014
Author: abataev
Date: Mon Sep 22 05:01:53 2014
New Revision: 218239
URL: http://llvm.org/viewvc/llvm-project?rev=218239&view=rev
Log:
[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
Added:
cfe/trunk/test/OpenMP/critical_codegen.cpp (with props)
Modified:
cfe/trunk/lib/CodeGen/CGOpenMPRuntime.cpp
cfe/trunk/lib/CodeGen/CGOpenMPRuntime.h
cfe/trunk/lib/CodeGen/CGStmtOpenMP.cpp
Modified: cfe/trunk/lib/CodeGen/CGOpenMPRuntime.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGOpenMPRuntime.cpp?rev=218239&r1=218238&r2=218239&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGOpenMPRuntime.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGOpenMPRuntime.cpp Mon Sep 22 05:01:53 2014
@@ -34,6 +34,7 @@ CGOpenMPRuntime::CGOpenMPRuntime(CodeGen
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(O
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);
+}
Modified: cfe/trunk/lib/CodeGen/CGOpenMPRuntime.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGOpenMPRuntime.h?rev=218239&r1=218238&r2=218239&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGOpenMPRuntime.h (original)
+++ cfe/trunk/lib/CodeGen/CGOpenMPRuntime.h Mon Sep 22 05:01:53 2014
@@ -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
Modified: cfe/trunk/lib/CodeGen/CGStmtOpenMP.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGStmtOpenMP.cpp?rev=218239&r1=218238&r2=218239&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGStmtOpenMP.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGStmtOpenMP.cpp Mon Sep 22 05:01:53 2014
@@ -98,8 +98,22 @@ void CodeGenFunction::EmitOMPMasterDirec
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
Added: cfe/trunk/test/OpenMP/critical_codegen.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/critical_codegen.cpp?rev=218239&view=auto
==============================================================================
--- cfe/trunk/test/OpenMP/critical_codegen.cpp (added)
+++ cfe/trunk/test/OpenMP/critical_codegen.cpp Mon Sep 22 05:01:53 2014
@@ -0,0 +1,38 @@
+// RUN: %clang_cc1 -verify -fopenmp=libiomp5 -x c++ -emit-llvm %s -fexceptions -fcxx-exceptions -o - | FileCheck %s
+// RUN: %clang_cc1 -fopenmp=libiomp5 -x c++ -std=c++11 -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp=libiomp5 -x c++ -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s
+// expected-no-diagnostics
+
+#ifndef HEADER
+#define HEADER
+
+// CHECK: [[IDENT_T_TY:%.+]] = type { i32, i32, i32, i32, i8* }
+// CHECK: [[UNNAMED_LOCK:@.+]] = common global [8 x i32] zeroinitializer
+// CHECK: [[THE_NAME_LOCK:@.+]] = common global [8 x i32] zeroinitializer
+
+// CHECK: define void [[FOO:@.+]]()
+
+void foo() {}
+
+// CHECK-LABEL: @main
+int main() {
+// CHECK: [[A_ADDR:%.+]] = alloca i8
+ char a;
+
+// CHECK: [[GTID:%.+]] = call i32 @__kmpc_global_thread_num([[IDENT_T_TY]]* [[DEFAULT_LOC:@.+]])
+// CHECK: call void @__kmpc_critical([[IDENT_T_TY]]* [[DEFAULT_LOC]], i32 [[GTID]], [8 x i32]* [[UNNAMED_LOCK]])
+// CHECK-NEXT: store i8 2, i8* [[A_ADDR]]
+// CHECK-NEXT: call void @__kmpc_end_critical([[IDENT_T_TY]]* [[DEFAULT_LOC]], i32 [[GTID]], [8 x i32]* [[UNNAMED_LOCK]])
+#pragma omp critical
+ a = 2;
+// CHECK: call void @__kmpc_critical([[IDENT_T_TY]]* [[DEFAULT_LOC]], i32 [[GTID]], [8 x i32]* [[THE_NAME_LOCK]])
+// CHECK-NEXT: call void [[FOO]]()
+// CHECK-NEXT: call void @__kmpc_end_critical([[IDENT_T_TY]]* [[DEFAULT_LOC]], i32 [[GTID]], [8 x i32]* [[THE_NAME_LOCK]])
+#pragma omp critical(the_name)
+ foo();
+// CHECK-NOT: call void @__kmpc_critical
+// CHECK-NOT: call void @__kmpc_end_critical
+ return a;
+}
+
+#endif
Propchange: cfe/trunk/test/OpenMP/critical_codegen.cpp
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: cfe/trunk/test/OpenMP/critical_codegen.cpp
------------------------------------------------------------------------------
svn:keywords = Author Date Id Rev URL
Propchange: cfe/trunk/test/OpenMP/critical_codegen.cpp
------------------------------------------------------------------------------
svn:mime-type = text/plain
More information about the cfe-commits
mailing list