summaryrefslogtreecommitdiffstats
path: root/clang/lib/CodeGen/CGOpenMPRuntime.cpp
diff options
context:
space:
mode:
authorAlexey Bataev <a.bataev@hotmail.com>2015-05-05 04:05:12 +0000
committerAlexey Bataev <a.bataev@hotmail.com>2015-05-05 04:05:12 +0000
commit9e03404d8d3fb6644daeb90d8977f0af9ba40f80 (patch)
treebd547f99eda00c377310f34e4f41ae9f42bc1d98 /clang/lib/CodeGen/CGOpenMPRuntime.cpp
parent9060e987a01ec4e84d08412cc9b2cfd563a16a29 (diff)
downloadbcm5719-llvm-9e03404d8d3fb6644daeb90d8977f0af9ba40f80.tar.gz
bcm5719-llvm-9e03404d8d3fb6644daeb90d8977f0af9ba40f80.zip
[OPENMP] Codegen for 'firstprivate' clause in 'task' directive.
For tasks codegen for private/firstprivate variables are different rather than for other directives. 1. Build an internal structure of privates for each private variable: struct .kmp_privates_t. { Ty1 var1; ... Tyn varn; }; 2. Add a new field to kmp_task_t type with list of privates. struct kmp_task_t { void * shareds; kmp_routine_entry_t routine; kmp_int32 part_id; kmp_routine_entry_t destructors; .kmp_privates_t. privates; }; 3. Create a function with destructors calls for all privates after end of task region. kmp_int32 .omp_task_destructor.(kmp_int32 gtid, kmp_task_t *tt) { ~Destructor(&tt->privates.var1); ... ~Destructor(&tt->privates.varn); return 0; } 4. Perform initialization of all firstprivate fields (by simple copying for POD data, copy constructor calls for classes) + provide address of a destructor function after kmpc_omp_task_alloc() and before kmpc_omp_task() calls. kmp_task_t *new_task = __kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid, kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds, kmp_routine_entry_t *task_entry); CopyConstructor(new_task->privates.var1, *new_task->shareds.var1_ref); new_task->shareds.var1_ref = &new_task->privates.var1; ... CopyConstructor(new_task->privates.varn, *new_task->shareds.varn_ref); new_task->shareds.varn_ref = &new_task->privates.varn; new_task->destructors = .omp_task_destructor.; kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t *new_task) Differential Revision: http://reviews.llvm.org/D9370 llvm-svn: 236479
Diffstat (limited to 'clang/lib/CodeGen/CGOpenMPRuntime.cpp')
-rw-r--r--clang/lib/CodeGen/CGOpenMPRuntime.cpp111
1 files changed, 93 insertions, 18 deletions
diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
index b89f0c0676c..a0c02ce8682 100644
--- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp
+++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
@@ -1630,12 +1630,21 @@ static void addFieldToRecordDecl(ASTContext &C, DeclContext *DC,
}
namespace {
-typedef std::pair<CharUnits /*Align*/,
- std::pair<const VarDecl *, const VarDecl *>> VDPair;
+struct PrivateHelpersTy {
+ PrivateHelpersTy(const VarDecl *Original, const VarDecl *PrivateCopy,
+ const VarDecl *PrivateElemInit)
+ : Original(Original), PrivateCopy(PrivateCopy),
+ PrivateElemInit(PrivateElemInit) {}
+ const VarDecl *Original;
+ const VarDecl *PrivateCopy;
+ const VarDecl *PrivateElemInit;
+};
+typedef std::pair<CharUnits /*Align*/, PrivateHelpersTy> PrivateDataTy;
} // namespace
-static RecordDecl *createPrivatesRecordDecl(CodeGenModule &CGM,
- const ArrayRef<VDPair> Privates) {
+static RecordDecl *
+createPrivatesRecordDecl(CodeGenModule &CGM,
+ const ArrayRef<PrivateDataTy> Privates) {
if (!Privates.empty()) {
auto &C = CGM.getContext();
// Build struct .kmp_privates_t. {
@@ -1644,8 +1653,8 @@ static RecordDecl *createPrivatesRecordDecl(CodeGenModule &CGM,
auto *RD = C.buildImplicitRecord(".kmp_privates.t");
RD->startDefinition();
for (auto &&Pair : Privates) {
- addFieldToRecordDecl(C, RD,
- Pair.second.first->getType().getNonReferenceType());
+ addFieldToRecordDecl(
+ C, RD, Pair.second.Original->getType().getNonReferenceType());
}
// TODO: add firstprivate fields.
RD->completeDefinition();
@@ -1654,10 +1663,10 @@ static RecordDecl *createPrivatesRecordDecl(CodeGenModule &CGM,
return nullptr;
}
-static RecordDecl *createKmpTaskTRecordDecl(CodeGenModule &CGM,
- QualType KmpInt32Ty,
- QualType KmpRoutineEntryPointerQTy,
- const ArrayRef<VDPair> Privates) {
+static RecordDecl *
+createKmpTaskTRecordDecl(CodeGenModule &CGM, QualType KmpInt32Ty,
+ QualType KmpRoutineEntryPointerQTy,
+ const ArrayRef<PrivateDataTy> Privates) {
auto &C = CGM.getContext();
// Build struct kmp_task_t {
// void * shareds;
@@ -1782,7 +1791,8 @@ emitDestructorsFunction(CodeGenModule &CGM, SourceLocation Loc,
return DestructorFn;
}
-static int array_pod_sort_comparator(const VDPair *P1, const VDPair *P2) {
+static int array_pod_sort_comparator(const PrivateDataTy *P1,
+ const PrivateDataTy *P2) {
return P1->first < P2->first ? 1 : (P2->first < P1->first ? -1 : 0);
}
@@ -1791,18 +1801,33 @@ void CGOpenMPRuntime::emitTaskCall(
bool Tied, llvm::PointerIntPair<llvm::Value *, 1, bool> Final,
llvm::Value *TaskFunction, QualType SharedsTy, llvm::Value *Shareds,
const Expr *IfCond, const ArrayRef<const Expr *> PrivateVars,
- const ArrayRef<const Expr *> PrivateCopies) {
+ const ArrayRef<const Expr *> PrivateCopies,
+ const ArrayRef<const Expr *> FirstprivateVars,
+ const ArrayRef<const Expr *> FirstprivateCopies,
+ const ArrayRef<const Expr *> FirstprivateInits) {
auto &C = CGM.getContext();
- llvm::SmallVector<VDPair, 8> Privates;
- auto I = PrivateCopies.begin();
+ llvm::SmallVector<PrivateDataTy, 8> Privates;
// Aggeregate privates and sort them by the alignment.
+ auto I = PrivateCopies.begin();
for (auto *E : PrivateVars) {
auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
Privates.push_back(std::make_pair(
C.getTypeAlignInChars(VD->getType()),
- std::make_pair(VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()))));
+ PrivateHelpersTy(VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()),
+ /*PrivateElemInit=*/nullptr)));
++I;
}
+ I = FirstprivateCopies.begin();
+ auto IElemInitRef = FirstprivateInits.begin();
+ for (auto *E : FirstprivateVars) {
+ auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
+ Privates.push_back(std::make_pair(
+ C.getTypeAlignInChars(VD->getType()),
+ PrivateHelpersTy(
+ VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()),
+ cast<VarDecl>(cast<DeclRefExpr>(*IElemInitRef)->getDecl()))));
+ ++I, ++IElemInitRef;
+ }
llvm::array_pod_sort(Privates.begin(), Privates.end(),
array_pod_sort_comparator);
auto KmpInt32Ty = C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1);
@@ -1872,11 +1897,61 @@ void CGOpenMPRuntime::emitTaskCall(
CodeGenFunction::CGCapturedStmtInfo CapturesInfo(
cast<CapturedStmt>(*D.getAssociatedStmt()));
for (auto &&Pair : Privates) {
- auto *VD = Pair.second.second;
+ auto *VD = Pair.second.PrivateCopy;
auto *Init = VD->getAnyInitializer();
LValue PrivateLValue = CGF.EmitLValueForField(Base, *FI);
if (Init) {
- CGF.EmitExprAsInit(Init, VD, PrivateLValue, /*capturedByInit=*/false);
+ if (auto *Elem = Pair.second.PrivateElemInit) {
+ auto *OriginalVD = Pair.second.Original;
+ auto *SharedField = CapturesInfo.lookup(OriginalVD);
+ auto SharedRefLValue =
+ CGF.EmitLValueForField(SharedsBase, SharedField);
+ if (OriginalVD->getType()->isArrayType()) {
+ // Initialize firstprivate array.
+ if (!isa<CXXConstructExpr>(Init) ||
+ CGF.isTrivialInitializer(Init)) {
+ // Perform simple memcpy.
+ CGF.EmitAggregateAssign(PrivateLValue.getAddress(),
+ SharedRefLValue.getAddress(),
+ OriginalVD->getType());
+ } else {
+ // Initialize firstprivate array using element-by-element
+ // intialization.
+ CGF.EmitOMPAggregateAssign(
+ PrivateLValue.getAddress(), SharedRefLValue.getAddress(),
+ OriginalVD->getType(),
+ [&CGF, Elem, Init, &CapturesInfo](llvm::Value *DestElement,
+ llvm::Value *SrcElement) {
+ // Clean up any temporaries needed by the initialization.
+ CodeGenFunction::OMPPrivateScope InitScope(CGF);
+ InitScope.addPrivate(Elem, [SrcElement]() -> llvm::Value *{
+ return SrcElement;
+ });
+ (void)InitScope.Privatize();
+ // Emit initialization for single element.
+ auto *OldCapturedStmtInfo = CGF.CapturedStmtInfo;
+ CGF.CapturedStmtInfo = &CapturesInfo;
+ CGF.EmitAnyExprToMem(Init, DestElement,
+ Init->getType().getQualifiers(),
+ /*IsInitializer=*/false);
+ CGF.CapturedStmtInfo = OldCapturedStmtInfo;
+ });
+ }
+ } else {
+ CodeGenFunction::OMPPrivateScope InitScope(CGF);
+ InitScope.addPrivate(Elem, [SharedRefLValue]() -> llvm::Value *{
+ return SharedRefLValue.getAddress();
+ });
+ (void)InitScope.Privatize();
+ auto *OldCapturedStmtInfo = CGF.CapturedStmtInfo;
+ CGF.CapturedStmtInfo = &CapturesInfo;
+ CGF.EmitExprAsInit(Init, VD, PrivateLValue,
+ /*capturedByInit=*/false);
+ CGF.CapturedStmtInfo = OldCapturedStmtInfo;
+ }
+ } else {
+ CGF.EmitExprAsInit(Init, VD, PrivateLValue, /*capturedByInit=*/false);
+ }
}
NeedsCleanup = NeedsCleanup || FI->getType().isDestructedType();
// Copy addresses of privates to corresponding references in the list of
@@ -1884,7 +1959,7 @@ void CGOpenMPRuntime::emitTaskCall(
// ...
// tt->shareds.var_addr = &tt->privates.private_var;
// ...
- auto *OriginalVD = Pair.second.first;
+ auto *OriginalVD = Pair.second.Original;
auto *SharedField = CapturesInfo.lookup(OriginalVD);
auto SharedRefLValue =
CGF.EmitLValueForFieldInitialization(SharedsBase, SharedField);
OpenPOWER on IntegriCloud