diff options
| author | Alexey Bataev <a.bataev@hotmail.com> | 2015-04-15 04:52:20 +0000 |
|---|---|---|
| committer | Alexey Bataev <a.bataev@hotmail.com> | 2015-04-15 04:52:20 +0000 |
| commit | 69c62a9bdbd81a3a2b48715aa1589d53c0d1fbc8 (patch) | |
| tree | deee2e85a25c567a2a2189491c690a50d5097438 /clang/lib/CodeGen | |
| parent | 042e35cab9e93324d44f5e182a7eb20d7fab08cb (diff) | |
| download | bcm5719-llvm-69c62a9bdbd81a3a2b48715aa1589d53c0d1fbc8.tar.gz bcm5719-llvm-69c62a9bdbd81a3a2b48715aa1589d53c0d1fbc8.zip | |
[OPENMP] Codegen for 'firstprivate' clause in 'for' directive.
Adds proper codegen for 'firstprivate' clause in for directive. Initially codegen for 'firstprivate' clause was implemented for 'parallel' directive only.
Also this patch emits sync point only after initialization of firstprivate variables, not all private variables. This sync point is not required for privates, lastprivates etc., only for initialization of firstprivate variables.
Differential Revision: http://reviews.llvm.org/D8660
llvm-svn: 234978
Diffstat (limited to 'clang/lib/CodeGen')
| -rw-r--r-- | clang/lib/CodeGen/CGOpenMPRuntime.cpp | 5 | ||||
| -rw-r--r-- | clang/lib/CodeGen/CGStmtOpenMP.cpp | 136 | ||||
| -rw-r--r-- | clang/lib/CodeGen/CodeGenFunction.h | 2 |
3 files changed, 83 insertions, 60 deletions
diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp index 86241955ade..5988c785154 100644 --- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp +++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp @@ -161,8 +161,9 @@ public: const FieldDecl *lookup(const VarDecl *VD) const override { if (OuterRegionInfo) return OuterRegionInfo->lookup(VD); - llvm_unreachable("Trying to reference VarDecl that is neither local nor " - "captured in outer OpenMP region"); + // If there is no outer outlined region,no need to lookup in a list of + // captured variables, we can use the original one. + return nullptr; } FieldDecl *getThisFieldDecl() const override { if (OuterRegionInfo) diff --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp index 9a25f2eed92..624d062d3a5 100644 --- a/clang/lib/CodeGen/CGStmtOpenMP.cpp +++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp @@ -158,68 +158,82 @@ void CodeGenFunction::EmitOMPCopy(CodeGenFunction &CGF, } } -void CodeGenFunction::EmitOMPFirstprivateClause( - const OMPExecutableDirective &D, - CodeGenFunction::OMPPrivateScope &PrivateScope) { - auto PrivateFilter = [](const OMPClause *C) -> bool { +bool CodeGenFunction::EmitOMPFirstprivateClause(const OMPExecutableDirective &D, + OMPPrivateScope &PrivateScope) { + auto FirstprivateFilter = [](const OMPClause *C) -> bool { return C->getClauseKind() == OMPC_firstprivate; }; - for (OMPExecutableDirective::filtered_clause_iterator<decltype(PrivateFilter)> - I(D.clauses(), PrivateFilter); I; ++I) { + llvm::DenseSet<const VarDecl *> EmittedAsFirstprivate; + for (OMPExecutableDirective::filtered_clause_iterator<decltype( + FirstprivateFilter)> I(D.clauses(), FirstprivateFilter); + I; ++I) { auto *C = cast<OMPFirstprivateClause>(*I); auto IRef = C->varlist_begin(); auto InitsRef = C->inits().begin(); for (auto IInit : C->private_copies()) { auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl()); - auto *VD = cast<VarDecl>(cast<DeclRefExpr>(IInit)->getDecl()); - bool IsRegistered; - if (*InitsRef != nullptr) { - // Emit VarDecl with copy init for arrays. - auto *FD = CapturedStmtInfo->lookup(OrigVD); - LValue Base = MakeNaturalAlignAddrLValue( - CapturedStmtInfo->getContextValue(), - getContext().getTagDeclType(FD->getParent())); - auto *OriginalAddr = EmitLValueForField(Base, FD).getAddress(); - auto VDInit = cast<VarDecl>(cast<DeclRefExpr>(*InitsRef)->getDecl()); - IsRegistered = PrivateScope.addPrivate(OrigVD, [&]() -> llvm::Value *{ - auto Emission = EmitAutoVarAlloca(*VD); - // Emit initialization of aggregate firstprivate vars. - auto *Init = VD->getInit(); - if (!isa<CXXConstructExpr>(Init) || isTrivialInitializer(Init)) { - // Perform simple memcpy. - EmitAggregateAssign(Emission.getAllocatedAddress(), OriginalAddr, - (*IRef)->getType()); - } else { - EmitOMPAggregateAssign( - Emission.getAllocatedAddress(), OriginalAddr, - (*IRef)->getType(), - [this, VDInit, Init](llvm::Value *DestElement, - llvm::Value *SrcElement) { - // Clean up any temporaries needed by the initialization. - RunCleanupsScope InitScope(*this); - // Emit initialization for single element. - LocalDeclMap[VDInit] = SrcElement; - EmitAnyExprToMem(Init, DestElement, - Init->getType().getQualifiers(), - /*IsInitializer*/ false); - LocalDeclMap.erase(VDInit); - }); - } - EmitAutoVarCleanups(Emission); - return Emission.getAllocatedAddress(); - }); - } else - IsRegistered = PrivateScope.addPrivate(OrigVD, [&]() -> llvm::Value *{ - // Emit private VarDecl with copy init. - EmitDecl(*VD); - return GetAddrOfLocalVar(VD); - }); - assert(IsRegistered && "firstprivate var already registered as private"); - // Silence the warning about unused variable. - (void)IsRegistered; + if (EmittedAsFirstprivate.count(OrigVD) == 0) { + EmittedAsFirstprivate.insert(OrigVD); + auto *VD = cast<VarDecl>(cast<DeclRefExpr>(IInit)->getDecl()); + auto *VDInit = cast<VarDecl>(cast<DeclRefExpr>(*InitsRef)->getDecl()); + bool IsRegistered; + DeclRefExpr DRE( + const_cast<VarDecl *>(OrigVD), + /*RefersToEnclosingVariableOrCapture=*/CapturedStmtInfo->lookup( + OrigVD) != nullptr, + (*IRef)->getType(), VK_LValue, (*IRef)->getExprLoc()); + auto *OriginalAddr = EmitLValue(&DRE).getAddress(); + if (OrigVD->getType()->isArrayType()) { + // Emit VarDecl with copy init for arrays. + // Get the address of the original variable captured in current + // captured region. + IsRegistered = PrivateScope.addPrivate(OrigVD, [&]() -> llvm::Value *{ + auto Emission = EmitAutoVarAlloca(*VD); + auto *Init = VD->getInit(); + if (!isa<CXXConstructExpr>(Init) || isTrivialInitializer(Init)) { + // Perform simple memcpy. + EmitAggregateAssign(Emission.getAllocatedAddress(), OriginalAddr, + (*IRef)->getType()); + } else { + EmitOMPAggregateAssign( + Emission.getAllocatedAddress(), OriginalAddr, + (*IRef)->getType(), + [this, VDInit, Init](llvm::Value *DestElement, + llvm::Value *SrcElement) { + // Clean up any temporaries needed by the initialization. + RunCleanupsScope InitScope(*this); + // Emit initialization for single element. + LocalDeclMap[VDInit] = SrcElement; + EmitAnyExprToMem(Init, DestElement, + Init->getType().getQualifiers(), + /*IsInitializer*/ false); + LocalDeclMap.erase(VDInit); + }); + } + EmitAutoVarCleanups(Emission); + return Emission.getAllocatedAddress(); + }); + } else { + IsRegistered = PrivateScope.addPrivate(OrigVD, [&]() -> llvm::Value *{ + // Emit private VarDecl with copy init. + // Remap temp VDInit variable to the address of the original + // variable + // (for proper handling of captured global variables). + LocalDeclMap[VDInit] = OriginalAddr; + EmitDecl(*VD); + LocalDeclMap.erase(VDInit); + return GetAddrOfLocalVar(VD); + }); + } + assert(IsRegistered && + "firstprivate var already registered as private"); + // Silence the warning about unused variable. + (void)IsRegistered; + } ++IRef, ++InitsRef; } } + return !EmittedAsFirstprivate.empty(); } void CodeGenFunction::EmitOMPPrivateClause( @@ -358,13 +372,15 @@ void CodeGenFunction::EmitOMPParallelDirective(const OMPParallelDirective &S) { // Emit parallel region as a standalone region. auto &&CodeGen = [&S](CodeGenFunction &CGF) { OMPPrivateScope PrivateScope(CGF); - CGF.EmitOMPPrivateClause(S, PrivateScope); - CGF.EmitOMPFirstprivateClause(S, PrivateScope); - CGF.EmitOMPReductionClauseInit(S, PrivateScope); - if (PrivateScope.Privatize()) - // Emit implicit barrier to synchronize threads and avoid data races. + if (CGF.EmitOMPFirstprivateClause(S, PrivateScope)) { + // Emit implicit barrier to synchronize threads and avoid data races on + // initialization of firstprivate variables. CGF.CGM.getOpenMPRuntime().emitBarrierCall(CGF, S.getLocStart(), OMPD_unknown); + } + CGF.EmitOMPPrivateClause(S, PrivateScope); + CGF.EmitOMPReductionClauseInit(S, PrivateScope); + (void)PrivateScope.Privatize(); CGF.EmitStmt(cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt()); CGF.EmitOMPReductionClauseFinal(S); // Emit implicit barrier at the end of the 'parallel' directive. @@ -844,6 +860,12 @@ void CodeGenFunction::EmitOMPWorksharingLoop(const OMPLoopDirective &S) { EmitOMPHelperVar(*this, cast<DeclRefExpr>(S.getIsLastIterVariable())); OMPPrivateScope LoopScope(*this); + if (EmitOMPFirstprivateClause(S, LoopScope)) { + // Emit implicit barrier to synchronize threads and avoid data races on + // initialization of firstprivate variables. + CGM.getOpenMPRuntime().emitBarrierCall(*this, S.getLocStart(), + OMPD_unknown); + } EmitPrivateLoopCounters(*this, LoopScope, S.counters()); (void)LoopScope.Privatize(); diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index 708929683b6..0aedac3b224 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -2064,7 +2064,7 @@ public: LValue X, RValue E, BinaryOperatorKind BO, bool IsXLHSInRHSPart, llvm::AtomicOrdering AO, SourceLocation Loc, const llvm::function_ref<RValue(RValue)> &CommonGen); - void EmitOMPFirstprivateClause(const OMPExecutableDirective &D, + bool EmitOMPFirstprivateClause(const OMPExecutableDirective &D, OMPPrivateScope &PrivateScope); void EmitOMPPrivateClause(const OMPExecutableDirective &D, OMPPrivateScope &PrivateScope); |

