diff options
author | Alexey Bataev <a.bataev@hotmail.com> | 2015-04-27 04:34:03 +0000 |
---|---|---|
committer | Alexey Bataev <a.bataev@hotmail.com> | 2015-04-27 04:34:03 +0000 |
commit | 9efc03b6f7666e4d51627ed2e0198747769d091e (patch) | |
tree | 8f3add3ef27d1b08c6c8e0b989a4c4fdfc806009 /clang/lib/CodeGen | |
parent | 7387083d95d595f4d5e883bd4cb20781c1b4e72b (diff) | |
download | bcm5719-llvm-9efc03b6f7666e4d51627ed2e0198747769d091e.tar.gz bcm5719-llvm-9efc03b6f7666e4d51627ed2e0198747769d091e.zip |
[OPENMP] Codegen for 'lastprivate' clause in 'sections' directive.
#pragma omp sections lastprivate(<var>)
<BODY>;
This construct is translated into something like:
<last_iter> = alloca i32
<init for lastprivates>;
<last_iter> = 0
; No initializer for simple variables or a default constructor is called for objects.
; For arrays perform element by element initialization by the call of the default constructor.
...
OMP_FOR_START(...,<last_iter>, ..); sets <last_iter> to 1 if this is the last iteration.
<BODY>
...
OMP_FOR_END
if (<last_iter> != 0) {
<final copy for lastprivate>; Update original variable with the lastprivate value.
}
call __kmpc_cancel_barrier() ; an implicit barrier to avoid possible data race.
If there is only one section, there is no special code generation, original shared variables are used + barrier is emitted at the end of the directive.
Differential Revision: http://reviews.llvm.org/D9240
llvm-svn: 235834
Diffstat (limited to 'clang/lib/CodeGen')
-rw-r--r-- | clang/lib/CodeGen/CGStmtOpenMP.cpp | 36 |
1 files changed, 31 insertions, 5 deletions
diff --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp index 0b54b1bbc56..62fe4bcd1f2 100644 --- a/clang/lib/CodeGen/CGStmtOpenMP.cpp +++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp @@ -1112,7 +1112,8 @@ static OpenMPDirectiveKind emitSections(CodeGenFunction &CGF, auto *Stmt = cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt(); auto *CS = dyn_cast<CompoundStmt>(Stmt); if (CS && CS->size() > 1) { - auto &&CodeGen = [&S, CS](CodeGenFunction &CGF) { + bool HasLastprivates = false; + auto &&CodeGen = [&S, CS, &HasLastprivates](CodeGenFunction &CGF) { auto &C = CGF.CGM.getContext(); auto KmpInt32Ty = C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1); // Emit helper vars inits. @@ -1173,6 +1174,7 @@ static OpenMPDirectiveKind emitSections(CodeGenFunction &CGF, OMPD_unknown); } CGF.EmitOMPPrivateClause(S, LoopScope); + HasLastprivates = CGF.EmitOMPLastprivateClauseInit(S, LoopScope); (void)LoopScope.Privatize(); // Emit static non-chunked loop. @@ -1192,14 +1194,38 @@ static OpenMPDirectiveKind emitSections(CodeGenFunction &CGF, [](CodeGenFunction &) {}); // Tell the runtime we are done. CGF.CGM.getOpenMPRuntime().emitForStaticFinish(CGF, S.getLocStart()); + + // Emit final copy of the lastprivate variables if IsLastIter != 0. + if (HasLastprivates) + CGF.EmitOMPLastprivateClauseFinal( + S, CGF.Builder.CreateIsNotNull( + CGF.EmitLoadOfScalar(IL, S.getLocStart()))); }; CGF.CGM.getOpenMPRuntime().emitInlinedDirective(CGF, CodeGen); + // Emit barrier for lastprivates only if 'sections' directive has 'nowait' + // clause. Otherwise the barrier will be generated by the codegen for the + // directive. + if (HasLastprivates && S.getSingleClause(OMPC_nowait)) { + // Emit implicit barrier to synchronize threads and avoid data races on + // initialization of firstprivate variables. + CGF.CGM.getOpenMPRuntime().emitBarrierCall(CGF, S.getLocStart(), + OMPD_unknown); + } return OMPD_sections; } // If only one section is found - no need to generate loop, emit as a single // region. bool HasFirstprivates; + // No need to generate lastprivates for sections with single section region, + // we can use original shared variable for all calculations with barrier at + // the end of the sections. + auto LastprivateFilter = [](const OMPClause *C) -> bool { + return C->getClauseKind() == OMPC_lastprivate; + }; + OMPExecutableDirective::filtered_clause_iterator<decltype(LastprivateFilter)> + I(S.clauses(), LastprivateFilter); + bool HasLastprivates = I; auto &&CodeGen = [Stmt, &S, &HasFirstprivates](CodeGenFunction &CGF) { CodeGenFunction::OMPPrivateScope SingleScope(CGF); HasFirstprivates = CGF.EmitOMPFirstprivateClause(S, SingleScope); @@ -1212,10 +1238,10 @@ static OpenMPDirectiveKind emitSections(CodeGenFunction &CGF, CGF.CGM.getOpenMPRuntime().emitSingleRegion(CGF, CodeGen, S.getLocStart(), llvm::None, llvm::None, llvm::None, llvm::None); - // Emit barrier for firstprivates only if 'sections' directive has 'nowait' - // clause. Otherwise the barrier will be generated by the codegen for the - // directive. - if (HasFirstprivates && S.getSingleClause(OMPC_nowait)) { + // Emit barrier for firstprivates or lastprivates only if 'sections' directive + // has 'nowait' clause. Otherwise the barrier will be generated by the codegen + // for the directive. + if ((HasFirstprivates || HasLastprivates) && S.getSingleClause(OMPC_nowait)) { // Emit implicit barrier to synchronize threads and avoid data races on // initialization of firstprivate variables. CGF.CGM.getOpenMPRuntime().emitBarrierCall(CGF, S.getLocStart(), |