[OPENMP] Initial codegen for 'parallel sections' directive.
Emits code for outlined 'parallel' directive with the implicitly inlined 'sections' directive:
...
call __kmpc_fork_call(..., outlined_function, ...);
...
define internal void outlined_function(...) {
<code for implicit sections directive>;
}
Differential Revision: http://reviews.llvm.org/D8997
llvm-svn: 234849
diff --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp
index c8c0fd6..fd475ba 100644
--- a/clang/lib/CodeGen/CGStmtOpenMP.cpp
+++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp
@@ -883,8 +883,8 @@
return LVal;
}
-void CodeGenFunction::EmitOMPSectionsDirective(const OMPSectionsDirective &S) {
- LexicalScope Scope(*this, S.getSourceRange());
+static OpenMPDirectiveKind emitSections(CodeGenFunction &CGF,
+ const OMPExecutableDirective &S) {
auto *Stmt = cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt();
auto *CS = dyn_cast<CompoundStmt>(Stmt);
if (CS && CS->size() > 1) {
@@ -904,9 +904,9 @@
// Loop counter.
LValue IV = createSectionLVal(CGF, KmpInt32Ty, ".omp.sections.iv.");
OpaqueValueExpr IVRefExpr(S.getLocStart(), KmpInt32Ty, VK_LValue);
- OpaqueValueMapping OpaqueIV(CGF, &IVRefExpr, IV);
+ CodeGenFunction::OpaqueValueMapping OpaqueIV(CGF, &IVRefExpr, IV);
OpaqueValueExpr UBRefExpr(S.getLocStart(), KmpInt32Ty, VK_LValue);
- OpaqueValueMapping OpaqueUB(CGF, &UBRefExpr, UB);
+ CodeGenFunction::OpaqueValueMapping OpaqueUB(CGF, &UBRefExpr, UB);
// Generate condition for loop.
BinaryOperator Cond(&IVRefExpr, &UBRefExpr, BO_LE, C.BoolTy, VK_RValue,
OK_Ordinary, S.getLocStart(),
@@ -959,26 +959,27 @@
OMPC_SCHEDULE_static);
};
- CGM.getOpenMPRuntime().emitInlinedDirective(*this, CodeGen);
- } else {
- // If only one section is found - no need to generate loop, emit as a
- // single
- // region.
- auto &&CodeGen = [&S](CodeGenFunction &CGF) {
- CGF.EmitStmt(
- cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt());
- CGF.EnsureInsertPoint();
- };
- CGM.getOpenMPRuntime().emitSingleRegion(*this, CodeGen, S.getLocStart(),
- llvm::None, llvm::None, llvm::None,
- llvm::None);
+ CGF.CGM.getOpenMPRuntime().emitInlinedDirective(CGF, CodeGen);
+ return OMPD_sections;
}
+ // If only one section is found - no need to generate loop, emit as a single
+ // region.
+ auto &&CodeGen = [Stmt](CodeGenFunction &CGF) {
+ CGF.EmitStmt(Stmt);
+ CGF.EnsureInsertPoint();
+ };
+ CGF.CGM.getOpenMPRuntime().emitSingleRegion(CGF, CodeGen, S.getLocStart(),
+ llvm::None, llvm::None,
+ llvm::None, llvm::None);
+ return OMPD_single;
+}
+void CodeGenFunction::EmitOMPSectionsDirective(const OMPSectionsDirective &S) {
+ LexicalScope Scope(*this, S.getSourceRange());
+ OpenMPDirectiveKind EmittedAs = emitSections(*this, S);
// Emit an implicit barrier at the end.
if (!S.getSingleClause(OMPC_nowait)) {
- CGM.getOpenMPRuntime().emitBarrierCall(
- *this, S.getLocStart(),
- (CS && CS->size() > 1) ? OMPD_sections : OMPD_single);
+ CGM.getOpenMPRuntime().emitBarrierCall(*this, S.getLocStart(), EmittedAs);
}
}
@@ -1071,8 +1072,17 @@
}
void CodeGenFunction::EmitOMPParallelSectionsDirective(
- const OMPParallelSectionsDirective &) {
- llvm_unreachable("CodeGen for 'omp parallel sections' is not supported yet.");
+ const OMPParallelSectionsDirective &S) {
+ // Emit directive as a combined directive that consists of two implicit
+ // directives: 'parallel' with 'sections' directive.
+ LexicalScope Scope(*this, S.getSourceRange());
+ auto &&CodeGen = [&S](CodeGenFunction &CGF) {
+ (void)emitSections(CGF, S);
+ // Emit implicit barrier at the end of parallel region.
+ CGF.CGM.getOpenMPRuntime().emitBarrierCall(CGF, S.getLocStart(),
+ OMPD_parallel);
+ };
+ emitCommonOMPParallelDirective(*this, S, CodeGen);
}
void CodeGenFunction::EmitOMPTaskDirective(const OMPTaskDirective &S) {
diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h
index 087acc7..6ba3db0 100644
--- a/clang/lib/CodeGen/CodeGenFunction.h
+++ b/clang/lib/CodeGen/CodeGenFunction.h
@@ -2085,15 +2085,16 @@
void EmitOMPTargetDirective(const OMPTargetDirective &S);
void EmitOMPTeamsDirective(const OMPTeamsDirective &S);
+ void
+ EmitOMPInnerLoop(const Stmt &S, bool RequiresCleanup, const Expr *LoopCond,
+ const Expr *IncExpr,
+ const llvm::function_ref<void(CodeGenFunction &)> &BodyGen);
+
private:
/// Helpers for the OpenMP loop directives.
void EmitOMPLoopBody(const OMPLoopDirective &Directive,
bool SeparateIter = false);
- void
- EmitOMPInnerLoop(const Stmt &S, bool RequiresCleanup, const Expr *LoopCond,
- const Expr *IncExpr,
- const llvm::function_ref<void(CodeGenFunction &)> &BodyGen);
void EmitOMPSimdFinal(const OMPLoopDirective &S);
void EmitOMPWorksharingLoop(const OMPLoopDirective &S);
void EmitOMPForOuterLoop(OpenMPScheduleClauseKind ScheduleKind,