summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/AST/ASTContext.cpp4
-rw-r--r--clang/lib/CodeGen/CGDecl.cpp11
-rw-r--r--clang/lib/CodeGen/CGOpenMPRuntime.cpp85
-rw-r--r--clang/lib/CodeGen/CGOpenMPRuntime.h23
-rw-r--r--clang/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp1
-rw-r--r--clang/lib/CodeGen/CodeGenModule.cpp15
-rw-r--r--clang/lib/CodeGen/CodeGenModule.h3
-rw-r--r--clang/lib/CodeGen/ModuleBuilder.cpp9
-rw-r--r--clang/lib/Sema/SemaExpr.cpp1
-rw-r--r--clang/lib/Serialization/ASTReaderDecl.cpp9
-rw-r--r--clang/lib/Serialization/ASTWriterDecl.cpp3
11 files changed, 144 insertions, 20 deletions
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index 4c9ccd7cc98..cd0eada9044 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -8508,7 +8508,9 @@ bool ASTContext::DeclMustBeEmitted(const Decl *D) {
else if (isa<PragmaDetectMismatchDecl>(D))
return true;
else if (isa<OMPThreadPrivateDecl>(D))
- return true;
+ return !D->getDeclContext()->isDependentContext();
+ else if (isa<OMPDeclareReductionDecl>(D))
+ return !D->getDeclContext()->isDependentContext();
else
return false;
diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp
index 36d20cca380..e0c297508fa 100644
--- a/clang/lib/CodeGen/CGDecl.cpp
+++ b/clang/lib/CodeGen/CGDecl.cpp
@@ -16,6 +16,7 @@
#include "CGCleanup.h"
#include "CGDebugInfo.h"
#include "CGOpenCLRuntime.h"
+#include "CGOpenMPRuntime.h"
#include "CodeGenModule.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/CharUnits.h"
@@ -120,7 +121,7 @@ void CodeGenFunction::EmitDecl(const Decl &D) {
}
case Decl::OMPDeclareReduction:
- return CGM.EmitOMPDeclareReduction(cast<OMPDeclareReductionDecl>(&D));
+ return CGM.EmitOMPDeclareReduction(cast<OMPDeclareReductionDecl>(&D), this);
case Decl::Typedef: // typedef int X;
case Decl::TypeAlias: { // using X = int; [C++0x]
@@ -1867,6 +1868,10 @@ void CodeGenFunction::EmitParmDecl(const VarDecl &D, ParamValue Arg,
EmitVarAnnotations(&D, DeclPtr.getPointer());
}
-void CodeGenModule::EmitOMPDeclareReduction(
- const OMPDeclareReductionDecl * /*D*/) {}
+void CodeGenModule::EmitOMPDeclareReduction(const OMPDeclareReductionDecl *D,
+ CodeGenFunction *CGF) {
+ if (!LangOpts.OpenMP || (!LangOpts.EmitAllDecls && !D->isUsed()))
+ return;
+ getOpenMPRuntime().emitUserDefinedReduction(CGF, D);
+}
diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
index 7213c4d079e..a38d6fdd3af 100644
--- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp
+++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
@@ -593,8 +593,7 @@ LValue CGOpenMPTaskOutlinedRegionInfo::getThreadIDVariableLValue(
}
CGOpenMPRuntime::CGOpenMPRuntime(CodeGenModule &CGM)
- : CGM(CGM), DefaultOpenMPPSource(nullptr), KmpRoutineEntryPtrTy(nullptr),
- OffloadEntriesInfoManager(CGM) {
+ : CGM(CGM), OffloadEntriesInfoManager(CGM) {
IdentTy = llvm::StructType::create(
"ident_t", CGM.Int32Ty /* reserved_1 */, CGM.Int32Ty /* flags */,
CGM.Int32Ty /* reserved_2 */, CGM.Int32Ty /* reserved_3 */,
@@ -612,6 +611,82 @@ void CGOpenMPRuntime::clear() {
InternalVars.clear();
}
+static llvm::Function *
+emitCombinerOrInitializer(CodeGenModule &CGM, QualType Ty,
+ const Expr *CombinerInitializer, const VarDecl *In,
+ const VarDecl *Out, bool IsCombiner) {
+ // void .omp_combiner.(Ty *in, Ty *out);
+ auto &C = CGM.getContext();
+ QualType PtrTy = C.getPointerType(Ty).withRestrict();
+ FunctionArgList Args;
+ ImplicitParamDecl OmpInParm(C, /*DC=*/nullptr, In->getLocation(),
+ /*Id=*/nullptr, PtrTy);
+ ImplicitParamDecl OmpOutParm(C, /*DC=*/nullptr, Out->getLocation(),
+ /*Id=*/nullptr, PtrTy);
+ Args.push_back(&OmpInParm);
+ Args.push_back(&OmpOutParm);
+ FunctionType::ExtInfo Info;
+ auto &FnInfo =
+ CGM.getTypes().arrangeFreeFunctionDeclaration(C.VoidTy, Args, Info,
+ /*isVariadic=*/false);
+ auto *FnTy = CGM.getTypes().GetFunctionType(FnInfo);
+ auto *Fn = llvm::Function::Create(
+ FnTy, llvm::GlobalValue::InternalLinkage,
+ IsCombiner ? ".omp_combiner." : ".omp_initializer.", &CGM.getModule());
+ CGM.SetInternalFunctionAttributes(/*D=*/nullptr, Fn, FnInfo);
+ CodeGenFunction CGF(CGM);
+ // Map "T omp_in;" variable to "*omp_in_parm" value in all expressions.
+ // Map "T omp_out;" variable to "*omp_out_parm" value in all expressions.
+ CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args);
+ CodeGenFunction::OMPPrivateScope Scope(CGF);
+ Address AddrIn = CGF.GetAddrOfLocalVar(&OmpInParm);
+ Scope.addPrivate(In, [&CGF, AddrIn, PtrTy]() -> Address {
+ return CGF.EmitLoadOfPointerLValue(AddrIn, PtrTy->castAs<PointerType>())
+ .getAddress();
+ });
+ Address AddrOut = CGF.GetAddrOfLocalVar(&OmpOutParm);
+ Scope.addPrivate(Out, [&CGF, AddrOut, PtrTy]() -> Address {
+ return CGF.EmitLoadOfPointerLValue(AddrOut, PtrTy->castAs<PointerType>())
+ .getAddress();
+ });
+ (void)Scope.Privatize();
+ CGF.EmitIgnoredExpr(CombinerInitializer);
+ Scope.ForceCleanup();
+ CGF.FinishFunction();
+ return Fn;
+}
+
+void CGOpenMPRuntime::emitUserDefinedReduction(
+ CodeGenFunction *CGF, const OMPDeclareReductionDecl *D) {
+ if (UDRMap.count(D) > 0)
+ return;
+ auto &C = CGM.getContext();
+ if (!In || !Out) {
+ In = &C.Idents.get("omp_in");
+ Out = &C.Idents.get("omp_out");
+ }
+ llvm::Function *Combiner = emitCombinerOrInitializer(
+ CGM, D->getType(), D->getCombiner(), cast<VarDecl>(D->lookup(In).front()),
+ cast<VarDecl>(D->lookup(Out).front()),
+ /*IsCombiner=*/true);
+ llvm::Function *Initializer = nullptr;
+ if (auto *Init = D->getInitializer()) {
+ if (!Priv || !Orig) {
+ Priv = &C.Idents.get("omp_priv");
+ Orig = &C.Idents.get("omp_orig");
+ }
+ Initializer = emitCombinerOrInitializer(
+ CGM, D->getType(), Init, cast<VarDecl>(D->lookup(Orig).front()),
+ cast<VarDecl>(D->lookup(Priv).front()),
+ /*IsCombiner=*/false);
+ }
+ UDRMap.insert(std::make_pair(D, std::make_pair(Combiner, Initializer)));
+ if (CGF) {
+ auto &Decls = FunctionUDRMap.FindAndConstruct(CGF->CurFn);
+ Decls.second.push_back(D);
+ }
+}
+
// Layout information for ident_t.
static CharUnits getIdentAlign(CodeGenModule &CGM) {
return CGM.getPointerAlign();
@@ -801,6 +876,12 @@ void CGOpenMPRuntime::functionFinished(CodeGenFunction &CGF) {
assert(CGF.CurFn && "No function in current CodeGenFunction.");
if (OpenMPLocThreadIDMap.count(CGF.CurFn))
OpenMPLocThreadIDMap.erase(CGF.CurFn);
+ if (FunctionUDRMap.count(CGF.CurFn) > 0) {
+ for(auto *D : FunctionUDRMap[CGF.CurFn]) {
+ UDRMap.erase(D);
+ }
+ FunctionUDRMap.erase(CGF.CurFn);
+ }
}
llvm::Type *CGOpenMPRuntime::getIdentTyPointerTy() {
diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.h b/clang/lib/CodeGen/CGOpenMPRuntime.h
index 6169dacb3fd..0044bb706f7 100644
--- a/clang/lib/CodeGen/CGOpenMPRuntime.h
+++ b/clang/lib/CodeGen/CGOpenMPRuntime.h
@@ -38,6 +38,8 @@ class Expr;
class GlobalDecl;
class OMPExecutableDirective;
class VarDecl;
+class OMPDeclareReductionDecl;
+class IdentifierInfo;
namespace CodeGen {
class Address;
@@ -50,7 +52,7 @@ class CGOpenMPRuntime {
CodeGenModule &CGM;
/// \brief Default const ident_t object used for initialization of all other
/// ident_t objects.
- llvm::Constant *DefaultOpenMPPSource;
+ llvm::Constant *DefaultOpenMPPSource = nullptr;
/// \brief Map of flags and corresponding default locations.
typedef llvm::DenseMap<unsigned, llvm::Value *> OpenMPDefaultLocMapTy;
OpenMPDefaultLocMapTy OpenMPDefaultLocMap;
@@ -73,6 +75,20 @@ class CGOpenMPRuntime {
typedef llvm::DenseMap<llvm::Function *, DebugLocThreadIdTy>
OpenMPLocThreadIDMapTy;
OpenMPLocThreadIDMapTy OpenMPLocThreadIDMap;
+ /// Map of UDRs and corresponding combiner/initializer.
+ typedef llvm::DenseMap<const OMPDeclareReductionDecl *,
+ std::pair<llvm::Function *, llvm::Function *>>
+ UDRMapTy;
+ UDRMapTy UDRMap;
+ /// Map of functions and locally defined UDRs.
+ typedef llvm::DenseMap<llvm::Function *,
+ SmallVector<const OMPDeclareReductionDecl *, 4>>
+ FunctionUDRMapTy;
+ FunctionUDRMapTy FunctionUDRMap;
+ IdentifierInfo *In = nullptr;
+ IdentifierInfo *Out = nullptr;
+ IdentifierInfo *Priv = nullptr;
+ IdentifierInfo *Orig = nullptr;
/// \brief Type kmp_critical_name, originally defined as typedef kmp_int32
/// kmp_critical_name[8];
llvm::ArrayType *KmpCriticalNameTy;
@@ -84,7 +100,7 @@ class CGOpenMPRuntime {
llvm::StringMap<llvm::AssertingVH<llvm::Constant>, llvm::BumpPtrAllocator>
InternalVars;
/// \brief Type typedef kmp_int32 (* kmp_routine_entry_t)(kmp_int32, void *);
- llvm::Type *KmpRoutineEntryPtrTy;
+ llvm::Type *KmpRoutineEntryPtrTy = nullptr;
QualType KmpRoutineEntryPtrQTy;
/// \brief Type typedef struct kmp_task {
/// void * shareds; /**< pointer to block of pointers to
@@ -364,6 +380,9 @@ public:
virtual ~CGOpenMPRuntime() {}
virtual void clear();
+ /// Emit code for the specified user defined reduction construct.
+ virtual void emitUserDefinedReduction(CodeGenFunction *CGF,
+ const OMPDeclareReductionDecl *D);
/// \brief Emits outlined function for the specified OpenMP parallel directive
/// \a D. This outlined function has type void(*)(kmp_int32 *ThreadID,
/// kmp_int32 BoundID, struct context_vars*).
diff --git a/clang/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp b/clang/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp
index 314a4b54494..680ed578134 100644
--- a/clang/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp
+++ b/clang/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp
@@ -13,6 +13,7 @@
//===----------------------------------------------------------------------===//
#include "CGOpenMPRuntimeNVPTX.h"
+#include "clang/AST/DeclOpenMP.h"
using namespace clang;
using namespace CodeGen;
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index e171abeacee..fad31995ed5 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -1543,10 +1543,17 @@ void CodeGenModule::EmitGlobal(GlobalDecl GD) {
}
}
- // If this is OpenMP device, check if it is legal to emit this global
- // normally.
- if (OpenMPRuntime && OpenMPRuntime->emitTargetGlobal(GD))
- return;
+ if (LangOpts.OpenMP) {
+ // If this is OpenMP device, check if it is legal to emit this global
+ // normally.
+ if (OpenMPRuntime && OpenMPRuntime->emitTargetGlobal(GD))
+ return;
+ if (auto *DRD = dyn_cast<OMPDeclareReductionDecl>(Global)) {
+ if (MustBeEmitted(Global))
+ EmitOMPDeclareReduction(DRD);
+ return;
+ }
+ }
// Ignore declarations, they will be emitted on their first use.
if (const auto *FD = dyn_cast<FunctionDecl>(Global)) {
diff --git a/clang/lib/CodeGen/CodeGenModule.h b/clang/lib/CodeGen/CodeGenModule.h
index 87183582e7d..8e662c25370 100644
--- a/clang/lib/CodeGen/CodeGenModule.h
+++ b/clang/lib/CodeGen/CodeGenModule.h
@@ -1112,7 +1112,8 @@ public:
void EmitOMPThreadPrivateDecl(const OMPThreadPrivateDecl *D);
/// \brief Emit a code for declare reduction construct.
- void EmitOMPDeclareReduction(const OMPDeclareReductionDecl *D);
+ void EmitOMPDeclareReduction(const OMPDeclareReductionDecl *D,
+ CodeGenFunction *CGF = nullptr);
/// Returns whether we need bit sets attached to vtables.
bool NeedVTableBitSets();
diff --git a/clang/lib/CodeGen/ModuleBuilder.cpp b/clang/lib/CodeGen/ModuleBuilder.cpp
index 041a15c5623..b5a5dfbe095 100644
--- a/clang/lib/CodeGen/ModuleBuilder.cpp
+++ b/clang/lib/CodeGen/ModuleBuilder.cpp
@@ -187,6 +187,15 @@ namespace {
}
}
}
+ // For OpenMP emit declare reduction functions, if required.
+ if (Ctx->getLangOpts().OpenMP) {
+ for (Decl *Member : D->decls()) {
+ if (auto *DRD = dyn_cast<OMPDeclareReductionDecl>(Member)) {
+ if (Ctx->DeclMustBeEmitted(DRD))
+ Builder->EmitGlobal(DRD);
+ }
+ }
+ }
}
void HandleTagDeclRequiredDefinition(const TagDecl *D) override {
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index b644ff215cd..a90fda8bfce 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -2861,6 +2861,7 @@ ExprResult Sema::BuildDeclarationNameExpr(
// Unresolved using declarations are dependent.
case Decl::EnumConstant:
case Decl::UnresolvedUsingValue:
+ case Decl::OMPDeclareReduction:
valueKind = VK_RValue;
break;
diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp
index 2389d671d42..1e93627df8d 100644
--- a/clang/lib/Serialization/ASTReaderDecl.cpp
+++ b/clang/lib/Serialization/ASTReaderDecl.cpp
@@ -2396,12 +2396,11 @@ void ASTDeclReader::VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl *D) {
}
void ASTDeclReader::VisitOMPDeclareReductionDecl(OMPDeclareReductionDecl *D) {
- VisitNamedDecl(D);
+ VisitValueDecl(D);
D->setLocation(Reader.ReadSourceLocation(F, Record, Idx));
D->setCombiner(Reader.ReadExpr(F));
D->setInitializer(Reader.ReadExpr(F));
D->PrevDeclInScope = Reader.ReadDeclID(F, Record, Idx);
- D->setType(Reader.readType(F, Record, Idx));
}
void ASTDeclReader::VisitOMPCapturedExprDecl(OMPCapturedExprDecl *D) {
@@ -2458,10 +2457,10 @@ static bool isConsumerInterestedIn(Decl *D, bool HasBody) {
isa<ObjCImplDecl>(D) ||
isa<ImportDecl>(D) ||
isa<PragmaCommentDecl>(D) ||
- isa<PragmaDetectMismatchDecl>(D) ||
- isa<OMPThreadPrivateDecl>(D) ||
- isa<OMPDeclareReductionDecl>(D))
+ isa<PragmaDetectMismatchDecl>(D))
return true;
+ if (isa<OMPThreadPrivateDecl>(D) || isa<OMPDeclareReductionDecl>(D))
+ return !D->getDeclContext()->isFunctionOrMethod();
if (VarDecl *Var = dyn_cast<VarDecl>(D))
return Var->isFileVarDecl() &&
Var->isThisDeclarationADefinition() == VarDecl::Definition;
diff --git a/clang/lib/Serialization/ASTWriterDecl.cpp b/clang/lib/Serialization/ASTWriterDecl.cpp
index 88b74a4b4c5..6c81b9e53c1 100644
--- a/clang/lib/Serialization/ASTWriterDecl.cpp
+++ b/clang/lib/Serialization/ASTWriterDecl.cpp
@@ -1655,12 +1655,11 @@ void ASTDeclWriter::VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl *D) {
}
void ASTDeclWriter::VisitOMPDeclareReductionDecl(OMPDeclareReductionDecl *D) {
- VisitNamedDecl(D);
+ VisitValueDecl(D);
Writer.AddSourceLocation(D->getLocStart(), Record);
Writer.AddStmt(D->getCombiner());
Writer.AddStmt(D->getInitializer());
Writer.AddDeclRef(D->getPrevDeclInScope(), Record);
- Writer.AddTypeRef(D->getType(), Record);
Code = serialization::DECL_OMP_DECLARE_REDUCTION;
}
OpenPOWER on IntegriCloud