forked from OSchip/llvm-project
[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
This commit is contained in:
parent
ab2cbad6fe
commit
bf8fe71b91
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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 &&
|
||||
|
|
|
@ -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() {}
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue