diff options
| author | Alexey Bataev <a.bataev@hotmail.com> | 2015-05-05 04:05:12 +0000 |
|---|---|---|
| committer | Alexey Bataev <a.bataev@hotmail.com> | 2015-05-05 04:05:12 +0000 |
| commit | 9e03404d8d3fb6644daeb90d8977f0af9ba40f80 (patch) | |
| tree | bd547f99eda00c377310f34e4f41ae9f42bc1d98 /clang/lib | |
| parent | 9060e987a01ec4e84d08412cc9b2cfd563a16a29 (diff) | |
| download | bcm5719-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')
| -rw-r--r-- | clang/lib/CodeGen/CGOpenMPRuntime.cpp | 111 | ||||
| -rw-r--r-- | clang/lib/CodeGen/CGOpenMPRuntime.h | 14 | ||||
| -rw-r--r-- | clang/lib/CodeGen/CGStmtOpenMP.cpp | 28 |
3 files changed, 129 insertions, 24 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); diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.h b/clang/lib/CodeGen/CGOpenMPRuntime.h index 7c805626684..ea714d7d333 100644 --- a/clang/lib/CodeGen/CGOpenMPRuntime.h +++ b/clang/lib/CodeGen/CGOpenMPRuntime.h @@ -557,14 +557,24 @@ public: /// \param PrivateVars List of references to private variables for the task /// directive. /// \param PrivateCopies List of private copies for each private variable in - /// \a PrivateVars. + /// \p PrivateVars. + /// \param FirstprivateVars List of references to private variables for the + /// task directive. + /// \param FirstprivateCopies List of private copies for each private variable + /// in \p FirstprivateVars. + /// \param FirstprivateInits List of references to auto generated variables + /// used for initialization of a single array element. Used if firstprivate + /// variable is of array type. virtual void emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc, const OMPExecutableDirective &D, 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); /// \brief Emit code for the directive that does not require outlining. /// diff --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp index 2c2d7032e3d..1f06e244630 100644 --- a/clang/lib/CodeGen/CGStmtOpenMP.cpp +++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp @@ -1373,10 +1373,10 @@ void CodeGenFunction::EmitOMPTaskDirective(const OMPTaskDirective &S) { if (auto C = S.getSingleClause(OMPC_if)) { IfCond = cast<OMPIfClause>(C)->getCondition(); } + llvm::DenseSet<const VarDecl *> EmittedAsPrivate; // Get list of private variables. llvm::SmallVector<const Expr *, 8> Privates; llvm::SmallVector<const Expr *, 8> PrivateCopies; - llvm::DenseSet<const VarDecl *> EmittedAsPrivate; for (auto &&I = S.getClausesOfKind(OMPC_private); I; ++I) { auto *C = cast<OMPPrivateClause>(*I); auto IRef = C->varlist_begin(); @@ -1389,9 +1389,29 @@ void CodeGenFunction::EmitOMPTaskDirective(const OMPTaskDirective &S) { ++IRef; } } - CGM.getOpenMPRuntime().emitTaskCall(*this, S.getLocStart(), S, Tied, Final, - OutlinedFn, SharedsTy, CapturedStruct, - IfCond, Privates, PrivateCopies); + EmittedAsPrivate.clear(); + // Get list of firstprivate variables. + llvm::SmallVector<const Expr *, 8> FirstprivateVars; + llvm::SmallVector<const Expr *, 8> FirstprivateCopies; + llvm::SmallVector<const Expr *, 8> FirstprivateInits; + for (auto &&I = S.getClausesOfKind(OMPC_firstprivate); I; ++I) { + auto *C = cast<OMPFirstprivateClause>(*I); + auto IRef = C->varlist_begin(); + auto IElemInitRef = C->inits().begin(); + for (auto *IInit : C->private_copies()) { + auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl()); + if (EmittedAsPrivate.insert(OrigVD->getCanonicalDecl()).second) { + FirstprivateVars.push_back(*IRef); + FirstprivateCopies.push_back(IInit); + FirstprivateInits.push_back(*IElemInitRef); + } + ++IRef, ++IElemInitRef; + } + } + CGM.getOpenMPRuntime().emitTaskCall( + *this, S.getLocStart(), S, Tied, Final, OutlinedFn, SharedsTy, + CapturedStruct, IfCond, Privates, PrivateCopies, FirstprivateVars, + FirstprivateCopies, FirstprivateInits); } void CodeGenFunction::EmitOMPTaskyieldDirective( |

