diff options
author | Alexey Bataev <a.bataev@hotmail.com> | 2018-08-07 16:14:36 +0000 |
---|---|---|
committer | Alexey Bataev <a.bataev@hotmail.com> | 2018-08-07 16:14:36 +0000 |
commit | bf8fe71b91ae4f2f223c6a7aa7e51c6aa4d6f329 (patch) | |
tree | 7da9deb1e688a7716827e7104dee5076d1ae47ef | |
parent | ab2cbad6fecd0b874dc51aaed0f3fb7aab8ebe4b (diff) | |
download | bcm5719-llvm-bf8fe71b91ae4f2f223c6a7aa7e51c6aa4d6f329.tar.gz bcm5719-llvm-bf8fe71b91ae4f2f223c6a7aa7e51c6aa4d6f329.zip |
[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.
llvm-svn: 339152
-rw-r--r-- | clang/include/clang/Sema/Sema.h | 7 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGOpenMPRuntime.cpp | 19 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGOpenMPRuntime.h | 6 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenModule.cpp | 4 | ||||
-rw-r--r-- | clang/lib/Sema/SemaOpenMP.cpp | 23 | ||||
-rw-r--r-- | clang/test/OpenMP/declare_target_ast_print.cpp | 19 | ||||
-rw-r--r-- | clang/test/OpenMP/declare_target_codegen.cpp | 19 |
7 files changed, 84 insertions, 13 deletions
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index b1077c620f8..8fe16f81268 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -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; diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp index 4d9f495c16e..168504ccaf7 100644 --- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp +++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp @@ -8106,7 +8106,12 @@ bool CGOpenMPRuntime::emitTargetGlobalVariable(GlobalDecl GD) { // 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(GlobalDecl GD) { 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) { diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.h b/clang/lib/CodeGen/CGOpenMPRuntime.h index 01ff0c20fd6..ed2b56b5448 100644 --- a/clang/lib/CodeGen/CGOpenMPRuntime.h +++ b/clang/lib/CodeGen/CGOpenMPRuntime.h @@ -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. diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 8c5e0df0969..dedd57efbd9 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -1747,6 +1747,10 @@ void CodeGenModule::EmitModuleLinkOptions() { } 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. diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index e1a4c420d40..0b1c3308208 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -1417,7 +1417,7 @@ bool Sema::isInOpenMPTargetExecutionDirective() const { 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(ValueDecl *D) const { // '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 && diff --git a/clang/test/OpenMP/declare_target_ast_print.cpp b/clang/test/OpenMP/declare_target_ast_print.cpp index bd1acc28dc6..ae6c2963106 100644 --- a/clang/test/OpenMP/declare_target_ast_print.cpp +++ b/clang/test/OpenMP/declare_target_ast_print.cpp @@ -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() {} diff --git a/clang/test/OpenMP/declare_target_codegen.cpp b/clang/test/OpenMP/declare_target_codegen.cpp index 96bdc874ece..fbeb6fb47fc 100644 --- a/clang/test/OpenMP/declare_target_codegen.cpp +++ b/clang/test/OpenMP/declare_target_codegen.cpp @@ -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; |