r339152 - [OPENMP] Mark variables captured in declare target region as implicitly

Alexey Bataev via cfe-commits cfe-commits at lists.llvm.org
Tue Aug 7 09:14:36 PDT 2018


Author: abataev
Date: Tue Aug  7 09:14:36 2018
New Revision: 339152

URL: http://llvm.org/viewvc/llvm-project?rev=339152&view=rev
Log:
[OPENMP] Mark variables captured in declare target region as implicitly
declare target.

According to OpenMP 5.0, variables captured in lambdas in declare target
regions must be considered as implicitly declare target.

Modified:
    cfe/trunk/include/clang/Sema/Sema.h
    cfe/trunk/lib/CodeGen/CGOpenMPRuntime.cpp
    cfe/trunk/lib/CodeGen/CGOpenMPRuntime.h
    cfe/trunk/lib/CodeGen/CodeGenModule.cpp
    cfe/trunk/lib/Sema/SemaOpenMP.cpp
    cfe/trunk/test/OpenMP/declare_target_ast_print.cpp
    cfe/trunk/test/OpenMP/declare_target_codegen.cpp

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=339152&r1=339151&r2=339152&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Tue Aug  7 09:14:36 2018
@@ -8662,7 +8662,7 @@ public:
   /// Check if the specified variable is used in one of the private
   /// clauses (private, firstprivate, lastprivate, reduction etc.) in OpenMP
   /// constructs.
-  VarDecl *isOpenMPCapturedDecl(ValueDecl *D) const;
+  VarDecl *isOpenMPCapturedDecl(ValueDecl *D);
   ExprResult getOpenMPCapturedExpr(VarDecl *Capture, ExprValueKind VK,
                                    ExprObjectKind OK, SourceLocation Loc);
 
@@ -8746,8 +8746,9 @@ public:
                                     OMPDeclareTargetDeclAttr::MapTypeTy MT,
                                     NamedDeclSetType &SameDirectiveDecls);
   /// Check declaration inside target region.
-  void checkDeclIsAllowedInOpenMPTarget(Expr *E, Decl *D,
-                                        SourceLocation IdLoc = SourceLocation());
+  void
+  checkDeclIsAllowedInOpenMPTarget(Expr *E, Decl *D,
+                                   SourceLocation IdLoc = SourceLocation());
   /// Return true inside OpenMP declare target region.
   bool isInOpenMPDeclareTargetContext() const {
     return IsInOpenMPDeclareTargetContext;

Modified: cfe/trunk/lib/CodeGen/CGOpenMPRuntime.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGOpenMPRuntime.cpp?rev=339152&r1=339151&r2=339152&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGOpenMPRuntime.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGOpenMPRuntime.cpp Tue Aug  7 09:14:36 2018
@@ -8106,7 +8106,12 @@ bool CGOpenMPRuntime::emitTargetGlobalVa
   // Do not to emit variable if it is not marked as declare target.
   llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
       isDeclareTargetDeclaration(cast<VarDecl>(GD.getDecl()));
-  return !Res || *Res == OMPDeclareTargetDeclAttr::MT_Link;
+  if (!Res || *Res == OMPDeclareTargetDeclAttr::MT_Link) {
+    if (CGM.getContext().DeclMustBeEmitted(GD.getDecl()))
+      DeferredGlobalVariables.insert(cast<VarDecl>(GD.getDecl()));
+    return true;
+  }
+  return false;
 }
 
 void CGOpenMPRuntime::registerTargetGlobalVariable(const VarDecl *VD,
@@ -8163,6 +8168,18 @@ bool CGOpenMPRuntime::emitTargetGlobal(G
   return emitTargetGlobalVariable(GD);
 }
 
+void CGOpenMPRuntime::emitDeferredTargetDecls() const {
+  for (const VarDecl *VD : DeferredGlobalVariables) {
+    llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
+        isDeclareTargetDeclaration(VD);
+    if (Res) {
+      assert(*Res != OMPDeclareTargetDeclAttr::MT_Link &&
+             "Implicit declare target variables must be only to().");
+      CGM.EmitGlobal(VD);
+    }
+  }
+}
+
 CGOpenMPRuntime::DisableAutoDeclareTargetRAII::DisableAutoDeclareTargetRAII(
     CodeGenModule &CGM)
     : CGM(CGM) {

Modified: cfe/trunk/lib/CodeGen/CGOpenMPRuntime.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGOpenMPRuntime.h?rev=339152&r1=339151&r2=339152&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGOpenMPRuntime.h (original)
+++ cfe/trunk/lib/CodeGen/CGOpenMPRuntime.h Tue Aug  7 09:14:36 2018
@@ -602,6 +602,10 @@ private:
   bool ShouldMarkAsGlobal = true;
   llvm::SmallDenseSet<const FunctionDecl *> AlreadyEmittedTargetFunctions;
 
+  /// List of variables that can become declare target implicitly and, thus,
+  /// must be emitted.
+  llvm::SmallDenseSet<const VarDecl *> DeferredGlobalVariables;
+
   /// Creates and registers offloading binary descriptor for the current
   /// compilation unit. The function that does the registration is returned.
   llvm::Function *createOffloadingBinaryDescriptorRegistration();
@@ -1509,6 +1513,8 @@ public:
   /// true, if it was marked already, and false, otherwise.
   bool markAsGlobalTarget(GlobalDecl GD);
 
+  /// Emit deferred declare target variables marked for deferred emission.
+  void emitDeferredTargetDecls() const;
 };
 
 /// Class supports emissionof SIMD-only code.

Modified: cfe/trunk/lib/CodeGen/CodeGenModule.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.cpp?rev=339152&r1=339151&r2=339152&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenModule.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenModule.cpp Tue Aug  7 09:14:36 2018
@@ -1747,6 +1747,10 @@ void CodeGenModule::EmitModuleLinkOption
 }
 
 void CodeGenModule::EmitDeferred() {
+  // Emit deferred declare target declarations.
+  if (getLangOpts().OpenMP && !getLangOpts().OpenMPSimd)
+    getOpenMPRuntime().emitDeferredTargetDecls();
+
   // Emit code for any potentially referenced deferred decls.  Since a
   // previously unused static decl may become used during the generation of code
   // for a static function, iterate until no changes are made.

Modified: cfe/trunk/lib/Sema/SemaOpenMP.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOpenMP.cpp?rev=339152&r1=339151&r2=339152&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaOpenMP.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOpenMP.cpp Tue Aug  7 09:14:36 2018
@@ -1417,7 +1417,7 @@ bool Sema::isInOpenMPTargetExecutionDire
              false);
 }
 
-VarDecl *Sema::isOpenMPCapturedDecl(ValueDecl *D) const {
+VarDecl *Sema::isOpenMPCapturedDecl(ValueDecl *D) {
   assert(LangOpts.OpenMP && "OpenMP is not allowed");
   D = getCanonicalDecl(D);
 
@@ -1425,13 +1425,22 @@ VarDecl *Sema::isOpenMPCapturedDecl(Valu
   // 'target' we return true so that this global is also mapped to the device.
   //
   auto *VD = dyn_cast<VarDecl>(D);
-  if (VD && !VD->hasLocalStorage() && isInOpenMPTargetExecutionDirective()) {
-    // If the declaration is enclosed in a 'declare target' directive,
-    // then it should not be captured.
-    //
-    if (isDeclareTargetDeclaration(VD))
+  if (VD && !VD->hasLocalStorage()) {
+    if (isInOpenMPDeclareTargetContext() &&
+        (getCurCapturedRegion() || getCurBlock() || getCurLambda())) {
+      // Try to mark variable as declare target if it is used in capturing
+      // regions.
+      if (!isDeclareTargetDeclaration(VD))
+        checkDeclIsAllowedInOpenMPTarget(nullptr, VD);
       return nullptr;
-    return VD;
+    } else if (isInOpenMPTargetExecutionDirective()) {
+      // If the declaration is enclosed in a 'declare target' directive,
+      // then it should not be captured.
+      //
+      if (isDeclareTargetDeclaration(VD))
+        return nullptr;
+      return VD;
+    }
   }
 
   if (DSAStack->getCurrentDirective() != OMPD_unknown &&

Modified: cfe/trunk/test/OpenMP/declare_target_ast_print.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/declare_target_ast_print.cpp?rev=339152&r1=339151&r2=339152&view=diff
==============================================================================
--- cfe/trunk/test/OpenMP/declare_target_ast_print.cpp (original)
+++ cfe/trunk/test/OpenMP/declare_target_ast_print.cpp Tue Aug  7 09:14:36 2018
@@ -10,6 +10,25 @@
 #ifndef HEADER
 #define HEADER
 
+int out_decl_target = 0;
+// CHECK: #pragma omp declare target{{$}}
+// CHECK: int out_decl_target = 0;
+// CHECK: #pragma omp end declare target{{$}}
+// CHECK: #pragma omp declare target{{$}}
+// CHECK: void lambda()
+// CHECK: #pragma omp end declare target{{$}}
+
+#pragma omp declare target
+void lambda () {
+#ifdef __cpp_lambdas
+  (void)[&] { ++out_decl_target; };
+#else
+  #pragma clang __debug captured
+  (void)out_decl_target;
+#endif
+};
+#pragma omp end declare target
+
 #pragma omp declare target
 // CHECK: #pragma omp declare target{{$}}
 void foo() {}

Modified: cfe/trunk/test/OpenMP/declare_target_codegen.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/declare_target_codegen.cpp?rev=339152&r1=339151&r2=339152&view=diff
==============================================================================
--- cfe/trunk/test/OpenMP/declare_target_codegen.cpp (original)
+++ cfe/trunk/test/OpenMP/declare_target_codegen.cpp Tue Aug  7 09:14:36 2018
@@ -20,17 +20,32 @@
 // CHECK-DAG: @globals = global %struct.S zeroinitializer,
 // CHECK-DAG: [[STAT:@.+stat]] = internal global %struct.S zeroinitializer,
 // CHECK-DAG: [[STAT_REF:@.+]] = internal constant %struct.S* [[STAT]]
-// CHECK-DAG: @llvm.used = appending global [2 x i8*] [i8* bitcast (void ()* @__omp_offloading__{{.+}}_globals_l[[@LINE+42]]_ctor to i8*), i8* bitcast (void ()* @__omp_offloading__{{.+}}_stat_l[[@LINE+43]]_ctor to i8*)],
+// CHECK-DAG: @out_decl_target = global i32 0,
+// CHECK-DAG: @llvm.used = appending global [2 x i8*] [i8* bitcast (void ()* @__omp_offloading__{{.+}}_globals_l[[@LINE+56]]_ctor to i8*), i8* bitcast (void ()* @__omp_offloading__{{.+}}_stat_l[[@LINE+57]]_ctor to i8*)],
 // CHECK-DAG: @llvm.compiler.used = appending global [1 x i8*] [i8* bitcast (%struct.S** [[STAT_REF]] to i8*)],
 
 // 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* %{{.*}})
-// CHECK-DAG: define {{.*}}void @__omp_offloading__{{.*}}_globals_l[[@LINE+36]]_ctor()
+// CHECK-DAG: define {{.*}}void @__omp_offloading__{{.*}}_globals_l[[@LINE+50]]_ctor()
 
 #ifndef HEADER
 #define HEADER
 
+int out_decl_target = 0;
+#pragma omp declare target
+void lambda () {
+#ifdef __cpp_lambdas
+  (void)[&] { (void)out_decl_target; };
+#else
+#pragma clang __debug captured
+  {
+    (void)out_decl_target;
+  }
+#endif
+};
+#pragma omp end declare target
+
 template <typename T>
 class TemplateClass {
   T a;




More information about the cfe-commits mailing list