[OPENMP] Support C++ member functions in the device constructs.
authorAlexey Bataev <a.bataev@hotmail.com>
Wed, 2 May 2018 15:45:28 +0000 (15:45 +0000)
committerAlexey Bataev <a.bataev@hotmail.com>
Wed, 2 May 2018 15:45:28 +0000 (15:45 +0000)
Added correct emission of the C++ member functions for the device
function when they are used in the device constructs.

llvm-svn: 331365

clang/lib/CodeGen/CGOpenMPRuntime.cpp
clang/lib/CodeGen/CGOpenMPRuntime.h
clang/lib/CodeGen/CodeGenModule.cpp
clang/test/OpenMP/declare_target_codegen.cpp

index 2c66f69..18b51ea 100644 (file)
@@ -899,9 +899,6 @@ static void EmitOMPAggregateInit(CodeGenFunction &CGF, Address DestAddr,
 
 static llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy>
 isDeclareTargetDeclaration(const ValueDecl *VD) {
-  if (const auto *MD = dyn_cast<CXXMethodDecl>(VD))
-    if (!MD->isStatic())
-      return llvm::None;
   for (const Decl *D : VD->redecls()) {
     if (!D->hasAttrs())
       continue;
@@ -7934,28 +7931,24 @@ CGOpenMPRuntime::DisableAutoDeclareTargetRAII::~DisableAutoDeclareTargetRAII() {
     CGM.getOpenMPRuntime().ShouldMarkAsGlobal = SavedShouldMarkAsGlobal;
 }
 
-bool CGOpenMPRuntime::markAsGlobalTarget(const FunctionDecl *D) {
+bool CGOpenMPRuntime::markAsGlobalTarget(GlobalDecl GD) {
   if (!CGM.getLangOpts().OpenMPIsDevice || !ShouldMarkAsGlobal)
     return true;
 
+  const auto *D = cast<FunctionDecl>(GD.getDecl());
   const FunctionDecl *FD = D->getCanonicalDecl();
   // Do not to emit function if it is marked as declare target as it was already
   // emitted.
   if (isDeclareTargetDeclaration(D)) {
     if (D->hasBody() && AlreadyEmittedTargetFunctions.count(FD) == 0) {
       if (auto *F = dyn_cast_or_null<llvm::Function>(
-              CGM.GetGlobalValue(CGM.getMangledName(D))))
+              CGM.GetGlobalValue(CGM.getMangledName(GD))))
         return !F->isDeclaration();
       return false;
     }
     return true;
   }
 
-  // Do not mark member functions except for static.
-  if (const auto *Method = dyn_cast<CXXMethodDecl>(FD))
-    if (!Method->isStatic())
-      return true;
-
   return !AlreadyEmittedTargetFunctions.insert(FD).second;
 }
 
index e1ce09a..4546da4 100644 (file)
@@ -1505,7 +1505,7 @@ public:
 
   /// Marks the declaration as alread emitted for the device code and returns
   /// true, if it was marked already, and false, otherwise.
-  bool markAsGlobalTarget(const FunctionDecl *D);
+  bool markAsGlobalTarget(GlobalDecl GD);
 
 };
 
index 063b9be..6e3747a 100644 (file)
@@ -2398,7 +2398,7 @@ llvm::Constant *CodeGenModule::GetOrCreateLLVMFunction(
   if (const FunctionDecl *FD = cast_or_null<FunctionDecl>(D)) {
     // For the device mark the function as one that should be emitted.
     if (getLangOpts().OpenMPIsDevice && OpenMPRuntime &&
-        !OpenMPRuntime->markAsGlobalTarget(FD) && FD->isDefined() &&
+        !OpenMPRuntime->markAsGlobalTarget(GD) && FD->isDefined() &&
         !DontDefer && !IsForDefinition)
       addDeferredDeclToEmit(GD);
 
index 15b9f58..ce194ef 100644 (file)
 // CHECK-DAG: @d = global i32 0,
 // CHECK-DAG: @c = external global i32,
 
-// CHECK-DAG: define {{.*}}i32 @{{.*}}{{foo|bar|baz2|baz3|FA}}{{.*}}()
+// CHECK-DAG: define {{.*}}i32 @{{.*}}{{foo|bar|baz2|baz3|FA|f_method}}{{.*}}()
+// CHECK-DAG: define {{.*}}void @{{.*}}TemplateClass{{.*}}(%class.TemplateClass* %{{.*}})
+// CHECK-DAG: define {{.*}}i32 @{{.*}}TemplateClass{{.*}}f_method{{.*}}(%class.TemplateClass* %{{.*}})
 
 #ifndef HEADER
 #define HEADER
 
+template <typename T>
+class TemplateClass {
+  T a;
+public:
+  TemplateClass() {}
+  T f_method() const { return a; }
+};
+
 int foo();
 
 int baz1();
@@ -33,7 +43,8 @@ int baz4() { return 5; }
 
 template <typename T>
 T FA() {
-  return T();
+  TemplateClass<T> s;
+  return s.f_method();
 }
 
 #pragma omp declare target