summaryrefslogtreecommitdiffstats
path: root/clang/lib/CodeGen
diff options
context:
space:
mode:
authorAlexey Bataev <a.bataev@hotmail.com>2015-04-27 05:04:13 +0000
committerAlexey Bataev <a.bataev@hotmail.com>2015-04-27 05:04:13 +0000
commita89adf22db0db5aaa561b20a5ae1845190c851a7 (patch)
treea4730f1c7d1cc88451de841c741d6382c6d3dfa4 /clang/lib/CodeGen
parent9efc03b6f7666e4d51627ed2e0198747769d091e (diff)
downloadbcm5719-llvm-a89adf22db0db5aaa561b20a5ae1845190c851a7.tar.gz
bcm5719-llvm-a89adf22db0db5aaa561b20a5ae1845190c851a7.zip
[OPENMP] Codegen for 'reduction' clause in 'sections' directive.
Emit a code for reduction clause. Next code should be emitted for reductions: static kmp_critical_name lock = { 0 }; void reduce_func(void *lhs[<n>], void *rhs[<n>]) { *(Type0*)lhs[0] = ReductionOperation0(*(Type0*)lhs[0], *(Type0*)rhs[0]); ... *(Type<n>-1*)lhs[<n>-1] = ReductionOperation<n>-1(*(Type<n>-1*)lhs[<n>-1], *(Type<n>-1*)rhs[<n>-1]); } ... void *RedList[<n>] = {&<RHSExprs>[0], ..., &<RHSExprs>[<n>-1]}; switch (__kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList), RedList, reduce_func, &<lock>)) { case 1: <LHSExprs>[0] = ReductionOperation0(*<LHSExprs>[0], *<RHSExprs>[0]); ... <LHSExprs>[<n>-1] = ReductionOperation<n>-1(*<LHSExprs>[<n>-1], *<RHSExprs>[<n>-1]); __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>); break; case 2: Atomic(<LHSExprs>[0] = ReductionOperation0(*<LHSExprs>[0], *<RHSExprs>[0])); ... Atomic(<LHSExprs>[<n>-1] = ReductionOperation<n>-1(*<LHSExprs>[<n>-1], *<RHSExprs>[<n>-1])); break; default:; } Reduction variables are a kind of a private variables, they have private copies, but initial values are chosen in accordance with the reduction operation. If sections directive has only single section, then original shared variables are used instead with barrier at the end of the directive. Differential Revision: http://reviews.llvm.org/D9242 llvm-svn: 235835
Diffstat (limited to 'clang/lib/CodeGen')
-rw-r--r--clang/lib/CodeGen/CGStmtOpenMP.cpp23
1 files changed, 17 insertions, 6 deletions
diff --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp
index 62fe4bcd1f2..22f6c3432a0 100644
--- a/clang/lib/CodeGen/CGStmtOpenMP.cpp
+++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp
@@ -1175,6 +1175,7 @@ static OpenMPDirectiveKind emitSections(CodeGenFunction &CGF,
}
CGF.EmitOMPPrivateClause(S, LoopScope);
HasLastprivates = CGF.EmitOMPLastprivateClauseInit(S, LoopScope);
+ CGF.EmitOMPReductionClauseInit(S, LoopScope);
(void)LoopScope.Privatize();
// Emit static non-chunked loop.
@@ -1194,6 +1195,7 @@ static OpenMPDirectiveKind emitSections(CodeGenFunction &CGF,
[](CodeGenFunction &) {});
// Tell the runtime we are done.
CGF.CGM.getOpenMPRuntime().emitForStaticFinish(CGF, S.getLocStart());
+ CGF.EmitOMPReductionClauseFinal(S);
// Emit final copy of the lastprivate variables if IsLastIter != 0.
if (HasLastprivates)
@@ -1217,6 +1219,14 @@ static OpenMPDirectiveKind emitSections(CodeGenFunction &CGF,
// If only one section is found - no need to generate loop, emit as a single
// region.
bool HasFirstprivates;
+ // No need to generate reductions for sections with single section region, we
+ // can use original shared variables for all operations.
+ auto ReductionFilter = [](const OMPClause *C) -> bool {
+ return C->getClauseKind() == OMPC_reduction;
+ };
+ OMPExecutableDirective::filtered_clause_iterator<decltype(ReductionFilter)> I(
+ S.clauses(), ReductionFilter);
+ bool HasReductions = I;
// 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.
@@ -1224,8 +1234,8 @@ static OpenMPDirectiveKind emitSections(CodeGenFunction &CGF,
return C->getClauseKind() == OMPC_lastprivate;
};
OMPExecutableDirective::filtered_clause_iterator<decltype(LastprivateFilter)>
- I(S.clauses(), LastprivateFilter);
- bool HasLastprivates = I;
+ I1(S.clauses(), LastprivateFilter);
+ bool HasLastprivates = I1;
auto &&CodeGen = [Stmt, &S, &HasFirstprivates](CodeGenFunction &CGF) {
CodeGenFunction::OMPPrivateScope SingleScope(CGF);
HasFirstprivates = CGF.EmitOMPFirstprivateClause(S, SingleScope);
@@ -1238,10 +1248,11 @@ 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 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 barrier for firstprivates, lastprivates or reductions only if
+ // 'sections' directive has 'nowait' clause. Otherwise the barrier will be
+ // generated by the codegen for the directive.
+ if ((HasFirstprivates || HasLastprivates || HasReductions) &&
+ 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(),
OpenPOWER on IntegriCloud