[OPENMP] Fix processing of declare target construct.

The attribute marked as inheritable since OpenMP 5.0 supports it +
additional fixes to support new functionality.

llvm-svn: 339704
This commit is contained in:
Alexey Bataev 2018-08-14 18:31:20 +00:00
parent 60a1e4dddc
commit 97b722121e
7 changed files with 59 additions and 72 deletions

View File

@ -2956,9 +2956,10 @@ def OMPDeclareSimdDecl : Attr {
}];
}
def OMPDeclareTargetDecl : Attr {
def OMPDeclareTargetDecl : InheritableAttr {
let Spellings = [Pragma<"omp", "declare target">];
let SemaHandler = 0;
let Subjects = SubjectList<[Function, SharedVar]>;
let Documentation = [OMPDeclareTargetDocs];
let Args = [
EnumArgument<"MapType", "MapTypeTy",
@ -2971,6 +2972,15 @@ def OMPDeclareTargetDecl : Attr {
if (getMapType() != MT_To)
OS << ' ' << ConvertMapTypeTyToStr(getMapType());
}
static llvm::Optional<MapTypeTy>
isDeclareTargetDeclaration(const ValueDecl *VD) {
if (!VD->hasAttrs())
return llvm::None;
if (const auto *Attr = VD->getAttr<OMPDeclareTargetDeclAttr>())
return Attr->getMapType();
return llvm::None;
}
}];
}

View File

@ -9806,13 +9806,9 @@ bool ASTContext::DeclMustBeEmitted(const Decl *D) {
return true;
// If the decl is marked as `declare target`, it should be emitted.
for (const auto *Decl : D->redecls()) {
if (!Decl->hasAttrs())
continue;
if (const auto *Attr = Decl->getAttr<OMPDeclareTargetDeclAttr>())
if (Attr->getMapType() != OMPDeclareTargetDeclAttr::MT_Link)
return true;
}
if (const llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD))
return *Res != OMPDeclareTargetDeclAttr::MT_Link;
return false;
}

View File

@ -1091,6 +1091,10 @@ void DeclPrinter::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
printTemplateParameters(FD->getTemplateParameterList(I));
}
VisitRedeclarableTemplateDecl(D);
// Declare target attribute is special one, natural spelling for the pragma
// assumes "ending" construct so print it here.
if (D->getTemplatedDecl()->hasAttr<OMPDeclareTargetDeclAttr>())
Out << "#pragma omp end declare target\n";
// Never print "instantiations" for deduction guides (they don't really
// have them).

View File

@ -897,25 +897,6 @@ static void EmitOMPAggregateInit(CodeGenFunction &CGF, Address DestAddr,
CGF.EmitBlock(DoneBB, /*IsFinished=*/true);
}
static llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy>
isDeclareTargetDeclaration(const ValueDecl *VD) {
for (const Decl *D : VD->redecls()) {
if (!D->hasAttrs())
continue;
if (const auto *Attr = D->getAttr<OMPDeclareTargetDeclAttr>())
return Attr->getMapType();
}
if (const auto *V = dyn_cast<VarDecl>(VD)) {
if (const VarDecl *TD = V->getTemplateInstantiationPattern())
return isDeclareTargetDeclaration(TD);
} else if (const auto *FD = dyn_cast<FunctionDecl>(VD)) {
if (const auto *TD = FD->getTemplateInstantiationPattern())
return isDeclareTargetDeclaration(TD);
}
return llvm::None;
}
LValue ReductionCodeGen::emitSharedLValue(CodeGenFunction &CGF, const Expr *E) {
return CGF.EmitOMPSharedLValue(E);
}
@ -2417,7 +2398,7 @@ Address CGOpenMPRuntime::getAddrOfDeclareTargetLink(const VarDecl *VD) {
if (CGM.getLangOpts().OpenMPSimd)
return Address::invalid();
llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
isDeclareTargetDeclaration(VD);
OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
if (Res && *Res == OMPDeclareTargetDeclAttr::MT_Link) {
SmallString<64> PtrName;
{
@ -2639,7 +2620,7 @@ bool CGOpenMPRuntime::emitDeclareTargetVarDefinition(const VarDecl *VD,
llvm::GlobalVariable *Addr,
bool PerformInit) {
Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
isDeclareTargetDeclaration(VD);
OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
if (!Res || *Res == OMPDeclareTargetDeclAttr::MT_Link)
return false;
VD = VD->getDefinition(CGM.getContext());
@ -6957,7 +6938,7 @@ private:
if (const auto *VD =
dyn_cast_or_null<VarDecl>(I->getAssociatedDeclaration())) {
if (llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
isDeclareTargetDeclaration(VD))
OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD))
if (*Res == OMPDeclareTargetDeclAttr::MT_Link) {
IsLink = true;
BP = CGF.CGM.getOpenMPRuntime().getAddrOfDeclareTargetLink(VD);
@ -7448,7 +7429,7 @@ public:
if (!VD)
continue;
llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
isDeclareTargetDeclaration(VD);
OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
if (!Res || *Res != OMPDeclareTargetDeclAttr::MT_Link)
continue;
StructRangeInfoTy PartialStruct;
@ -8078,7 +8059,7 @@ bool CGOpenMPRuntime::emitTargetFunctions(GlobalDecl GD) {
scanForTargetRegionsFunctions(FD->getBody(), CGM.getMangledName(GD));
// Do not to emit function if it is not marked as declare target.
return !isDeclareTargetDeclaration(FD) &&
return !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(FD) &&
AlreadyEmittedTargetFunctions.count(FD->getCanonicalDecl()) == 0;
}
@ -8105,7 +8086,8 @@ 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()));
OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(
cast<VarDecl>(GD.getDecl()));
if (!Res || *Res == OMPDeclareTargetDeclAttr::MT_Link) {
if (CGM.getContext().DeclMustBeEmitted(GD.getDecl()))
DeferredGlobalVariables.insert(cast<VarDecl>(GD.getDecl()));
@ -8117,7 +8099,7 @@ bool CGOpenMPRuntime::emitTargetGlobalVariable(GlobalDecl GD) {
void CGOpenMPRuntime::registerTargetGlobalVariable(const VarDecl *VD,
llvm::Constant *Addr) {
if (llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
isDeclareTargetDeclaration(VD)) {
OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD)) {
OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind Flags;
StringRef VarName;
CharUnits VarSize;
@ -8171,7 +8153,7 @@ bool CGOpenMPRuntime::emitTargetGlobal(GlobalDecl GD) {
void CGOpenMPRuntime::emitDeferredTargetDecls() const {
for (const VarDecl *VD : DeferredGlobalVariables) {
llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
isDeclareTargetDeclaration(VD);
OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
if (Res) {
assert(*Res != OMPDeclareTargetDeclAttr::MT_Link &&
"Implicit declare target variables must be only to().");
@ -8202,7 +8184,7 @@ bool CGOpenMPRuntime::markAsGlobalTarget(GlobalDecl GD) {
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 (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(D)) {
if (D->hasBody() && AlreadyEmittedTargetFunctions.count(FD) == 0) {
if (auto *F = dyn_cast_or_null<llvm::Function>(
CGM.GetGlobalValue(CGM.getMangledName(GD))))

View File

@ -191,20 +191,10 @@ class CheckVarsEscapingDeclContext final
bool AllEscaped = false;
bool IsForCombinedParallelRegion = false;
static llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy>
isDeclareTargetDeclaration(const ValueDecl *VD) {
for (const Decl *D : VD->redecls()) {
if (!D->hasAttrs())
continue;
if (const auto *Attr = D->getAttr<OMPDeclareTargetDeclAttr>())
return Attr->getMapType();
}
return llvm::None;
}
void markAsEscaped(const ValueDecl *VD) {
// Do not globalize declare target variables.
if (!isa<VarDecl>(VD) || isDeclareTargetDeclaration(VD))
if (!isa<VarDecl>(VD) ||
OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD))
return;
VD = cast<ValueDecl>(VD->getCanonicalDecl());
// Variables captured by value must be globalized.

View File

@ -1258,17 +1258,6 @@ void Sema::popOpenMPFunctionRegion(const FunctionScopeInfo *OldFSI) {
DSAStack->popFunction(OldFSI);
}
static llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy>
isDeclareTargetDeclaration(const ValueDecl *VD) {
for (const Decl *D : VD->redecls()) {
if (!D->hasAttrs())
continue;
if (const auto *Attr = D->getAttr<OMPDeclareTargetDeclAttr>())
return Attr->getMapType();
}
return llvm::None;
}
bool Sema::isOpenMPCapturedByRef(const ValueDecl *D, unsigned Level) const {
assert(LangOpts.OpenMP && "OpenMP is not allowed");
@ -1449,14 +1438,14 @@ VarDecl *Sema::isOpenMPCapturedDecl(ValueDecl *D) {
(getCurCapturedRegion() || getCurBlock() || getCurLambda())) {
// Try to mark variable as declare target if it is used in capturing
// regions.
if (!isDeclareTargetDeclaration(VD))
if (!OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD))
checkDeclIsAllowedInOpenMPTarget(nullptr, VD);
return nullptr;
} else if (isInOpenMPTargetExecutionDirective()) {
// If the declaration is enclosed in a 'declare target' directive,
// then it should not be captured.
//
if (isDeclareTargetDeclaration(VD))
if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD))
return nullptr;
return VD;
}
@ -1996,7 +1985,7 @@ public:
// Skip internally declared static variables.
llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
isDeclareTargetDeclaration(VD);
OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
if (VD->hasGlobalStorage() && !CS->capturesVariable(VD) &&
(!Res || *Res != OMPDeclareTargetDeclAttr::MT_Link))
return;
@ -13152,6 +13141,8 @@ void Sema::checkDeclIsAllowedInOpenMPTarget(Expr *E, Decl *D,
return;
}
}
if (const auto *FTD = dyn_cast<FunctionTemplateDecl>(D))
D = FTD->getTemplatedDecl();
if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
if (FD->hasAttr<OMPDeclareTargetDeclAttr>() &&
(FD->getAttr<OMPDeclareTargetDeclAttr>()->getMapType() ==
@ -13162,16 +13153,6 @@ void Sema::checkDeclIsAllowedInOpenMPTarget(Expr *E, Decl *D,
return;
}
}
if (const auto *FTD = dyn_cast<FunctionTemplateDecl>(D)) {
if (FTD->hasAttr<OMPDeclareTargetDeclAttr>() &&
(FTD->getAttr<OMPDeclareTargetDeclAttr>()->getMapType() ==
OMPDeclareTargetDeclAttr::MT_Link)) {
assert(IdLoc.isValid() && "Source location is expected");
Diag(IdLoc, diag::err_omp_function_in_link_clause);
Diag(FTD->getLocation(), diag::note_defined_here) << FTD;
return;
}
}
if (!E) {
// Checking declaration inside declare target region.
if (!D->hasAttr<OMPDeclareTargetDeclAttr>() &&

View File

@ -169,11 +169,35 @@ struct SSSTt {
// CHECK: #pragma omp end declare target
// CHECK: int b;
#pragma omp declare target
template <typename T>
T baz() { return T(); }
#pragma omp end declare target
template <>
int baz() { return 1; }
// CHECK: #pragma omp declare target
// CHECK: template <typename T> T baz() {
// CHECK: return T();
// CHECK: }
// CHECK: #pragma omp end declare target
// CHECK: #pragma omp declare target
// CHECK: template<> float baz<float>() {
// CHECK: return float();
// CHECK: }
// CHECK: template<> int baz<int>() {
// CHECK: return 1;
// CHECK: }
// CHECK: #pragma omp end declare target
int main (int argc, char **argv) {
foo();
foo_c();
foo_cpp();
test1();
baz<float>();
baz<int>();
return (0);
}