summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/CodeGen/CGOpenMPRuntime.cpp67
-rw-r--r--clang/lib/CodeGen/CGOpenMPRuntime.h13
-rw-r--r--clang/lib/CodeGen/CGStmtOpenMP.cpp9
3 files changed, 86 insertions, 3 deletions
diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
index cc4d7e2c9bb..65dd4d6559b 100644
--- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp
+++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
@@ -371,6 +371,22 @@ CGOpenMPRuntime::CreateRuntimeFunction(OpenMPRTLFunction Function) {
RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_flush");
break;
}
+ case OMPRTL__kmpc_master: {
+ // Build kmp_int32 __kmpc_master(ident_t *loc, kmp_int32 global_tid);
+ llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
+ llvm::FunctionType *FnTy =
+ llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
+ RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_master");
+ break;
+ }
+ case OMPRTL__kmpc_end_master: {
+ // Build void __kmpc_end_master(ident_t *loc, kmp_int32 global_tid);
+ llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
+ llvm::FunctionType *FnTy =
+ llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
+ RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_master");
+ break;
+ }
}
return RTLFn;
}
@@ -631,6 +647,57 @@ void CGOpenMPRuntime::EmitOMPCriticalRegion(
CGF.EmitRuntimeCall(RTLFn, Args);
}
+static void EmitOMPIfStmt(CodeGenFunction &CGF, llvm::Value *IfCond,
+ const std::function<void()> &BodyOpGen) {
+ llvm::Value *CallBool = CGF.EmitScalarConversion(
+ IfCond,
+ CGF.getContext().getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true),
+ CGF.getContext().BoolTy);
+
+ auto *ThenBlock = CGF.createBasicBlock("omp_if.then");
+ auto *ContBlock = CGF.createBasicBlock("omp_if.end");
+ // Generate the branch (If-stmt)
+ CGF.Builder.CreateCondBr(CallBool, ThenBlock, ContBlock);
+ CGF.EmitBlock(ThenBlock);
+ BodyOpGen();
+ // Emit the rest of bblocks/branches
+ CGF.EmitBranch(ContBlock);
+ CGF.EmitBlock(ContBlock, true);
+}
+
+void CGOpenMPRuntime::EmitOMPMasterRegion(
+ CodeGenFunction &CGF, const std::function<void()> &MasterOpGen,
+ SourceLocation Loc) {
+ // if(__kmpc_master(ident_t *, gtid)) {
+ // MasterOpGen();
+ // __kmpc_end_master(ident_t *, gtid);
+ // }
+ // Prepare arguments and build a call to __kmpc_master
+ llvm::Value *Args[] = {EmitOpenMPUpdateLocation(CGF, Loc),
+ GetOpenMPThreadID(CGF, Loc)};
+ auto RTLFn = CreateRuntimeFunction(OMPRTL__kmpc_master);
+ auto *IsMaster = CGF.EmitRuntimeCall(RTLFn, Args);
+ EmitOMPIfStmt(CGF, IsMaster, [&]() -> void {
+ MasterOpGen();
+ // Build a call to __kmpc_end_master.
+ // OpenMP [1.2.2 OpenMP Language Terminology]
+ // For C/C++, an executable statement, possibly compound, with a single
+ // entry at the top and a single exit at the bottom, or an OpenMP construct.
+ // * Access to the structured block must not be the result of a branch.
+ // * The point of exit cannot be a branch out of the structured block.
+ // * The point of entry must not be a call to setjmp().
+ // * longjmp() and throw() must not violate the entry/exit criteria.
+ // * An expression statement, iteration statement, selection statement, or
+ // try block is considered to be a structured block if the corresponding
+ // compound statement obtained by enclosing it in { and } would be a
+ // structured block.
+ // It is analyzed in Sema, so we can just call __kmpc_end_master() on
+ // fallthrough rather than pushing a normal cleanup for it.
+ RTLFn = CreateRuntimeFunction(OMPRTL__kmpc_end_master);
+ CGF.EmitRuntimeCall(RTLFn, Args);
+ });
+}
+
void CGOpenMPRuntime::EmitOMPBarrierCall(CodeGenFunction &CGF,
SourceLocation Loc,
OpenMPLocationFlags Flags) {
diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.h b/clang/lib/CodeGen/CGOpenMPRuntime.h
index d2597267313..65348c9c3a1 100644
--- a/clang/lib/CodeGen/CGOpenMPRuntime.h
+++ b/clang/lib/CodeGen/CGOpenMPRuntime.h
@@ -96,7 +96,11 @@ private:
// kmp_int32 num_threads);
OMPRTL__kmpc_push_num_threads,
// Call to void __kmpc_flush(ident_t *loc, ...);
- OMPRTL__kmpc_flush
+ OMPRTL__kmpc_flush,
+ // Call to kmp_int32 __kmpc_master(ident_t *, kmp_int32 global_tid);
+ OMPRTL__kmpc_master,
+ // Call to void __kmpc_end_master(ident_t *, kmp_int32 global_tid);
+ OMPRTL__kmpc_end_master,
};
CodeGenModule &CGM;
@@ -287,6 +291,13 @@ public:
const std::function<void()> &CriticalOpGen,
SourceLocation Loc);
+ /// \brief Emits a master region.
+ /// \param MasterOpGen Generator for the statement associated with the given
+ /// master region.
+ virtual void EmitOMPMasterRegion(CodeGenFunction &CGF,
+ const std::function<void()> &MasterOpGen,
+ SourceLocation Loc);
+
/// \brief Emits a barrier for OpenMP threads.
/// \param Flags Flags for the barrier.
///
diff --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp
index 79af4bc00df..90776e5a705 100644
--- a/clang/lib/CodeGen/CGStmtOpenMP.cpp
+++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp
@@ -490,8 +490,13 @@ void CodeGenFunction::EmitOMPSingleDirective(const OMPSingleDirective &) {
llvm_unreachable("CodeGen for 'omp single' is not supported yet.");
}
-void CodeGenFunction::EmitOMPMasterDirective(const OMPMasterDirective &) {
- llvm_unreachable("CodeGen for 'omp master' is not supported yet.");
+void CodeGenFunction::EmitOMPMasterDirective(const OMPMasterDirective &S) {
+ CGM.getOpenMPRuntime().EmitOMPMasterRegion(
+ *this, [&]() -> void {
+ RunCleanupsScope Scope(*this);
+ EmitStmt(cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt());
+ EnsureInsertPoint();
+ }, S.getLocStart());
}
void CodeGenFunction::EmitOMPCriticalDirective(const OMPCriticalDirective &S) {
OpenPOWER on IntegriCloud