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