diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/CodeGen/CGOpenMPRuntime.cpp | 49 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGOpenMPRuntime.h | 11 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGStmtOpenMP.cpp | 9 |
3 files changed, 67 insertions, 2 deletions
diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp index abc609aebb2..b7242d8979b 100644 --- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp +++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp @@ -484,6 +484,22 @@ CGOpenMPRuntime::CreateRuntimeFunction(OpenMPRTLFunction Function) { RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_taskyield"); break; } + case OMPRTL__kmpc_single: { + // Build kmp_int32 __kmpc_single(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_single"); + break; + } + case OMPRTL__kmpc_end_single: { + // Build void __kmpc_end_single(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_single"); + break; + } } return RTLFn; } @@ -805,6 +821,39 @@ void CGOpenMPRuntime::EmitOMPTaskyieldCall(CodeGenFunction &CGF, CGF.EmitRuntimeCall(RTLFn, Args); } +void CGOpenMPRuntime::EmitOMPSingleRegion( + CodeGenFunction &CGF, const std::function<void()> &SingleOpGen, + SourceLocation Loc) { + // if(__kmpc_single(ident_t *, gtid)) { + // SingleOpGen(); + // __kmpc_end_single(ident_t *, gtid); + // } + // Prepare arguments and build a call to __kmpc_single + llvm::Value *Args[] = {EmitOpenMPUpdateLocation(CGF, Loc), + GetOpenMPThreadID(CGF, Loc)}; + auto RTLFn = CreateRuntimeFunction(OMPRTL__kmpc_single); + auto *IsSingle = CGF.EmitRuntimeCall(RTLFn, Args); + EmitOMPIfStmt(CGF, IsSingle, [&]() -> void { + SingleOpGen(); + // Build a call to __kmpc_end_single. + // 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_single() on + // fallthrough rather than pushing a normal cleanup for it. + RTLFn = CreateRuntimeFunction(OMPRTL__kmpc_end_single); + CGF.EmitRuntimeCall(RTLFn, Args); + }); +} + void CGOpenMPRuntime::EmitOMPBarrierCall(CodeGenFunction &CGF, SourceLocation Loc, bool IsExplicit) { // Build call __kmpc_cancel_barrier(loc, thread_id); diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.h b/clang/lib/CodeGen/CGOpenMPRuntime.h index 5ff8dd654ef..76d4f2a6239 100644 --- a/clang/lib/CodeGen/CGOpenMPRuntime.h +++ b/clang/lib/CodeGen/CGOpenMPRuntime.h @@ -91,6 +91,10 @@ private: // Call to kmp_int32 __kmpc_omp_taskyield(ident_t *, kmp_int32 global_tid, // int end_part); OMPRTL__kmpc_omp_taskyield, + // Call to kmp_int32 __kmpc_single(ident_t *, kmp_int32 global_tid); + OMPRTL__kmpc_single, + // Call to void __kmpc_end_single(ident_t *, kmp_int32 global_tid); + OMPRTL__kmpc_end_single, }; /// \brief Values for bit flags used in the ident_t to describe the fields. @@ -312,6 +316,13 @@ public: /// \brief Emits code for a taskyield directive. virtual void EmitOMPTaskyieldCall(CodeGenFunction &CGF, SourceLocation Loc); + /// \brief Emits a single region. + /// \param SingleOpGen Generator for the statement associated with the given + /// single region. + virtual void EmitOMPSingleRegion(CodeGenFunction &CGF, + const std::function<void()> &SingleOpGen, + SourceLocation Loc); + /// \brief Emits explicit barrier for OpenMP threads. /// \param IsExplicit true, if it is explicitly specified barrier. /// diff --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp index 2518e55d4b3..b4dcadc5fdc 100644 --- a/clang/lib/CodeGen/CGStmtOpenMP.cpp +++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp @@ -707,8 +707,13 @@ void CodeGenFunction::EmitOMPSectionDirective(const OMPSectionDirective &) { llvm_unreachable("CodeGen for 'omp section' is not supported yet."); } -void CodeGenFunction::EmitOMPSingleDirective(const OMPSingleDirective &) { - llvm_unreachable("CodeGen for 'omp single' is not supported yet."); +void CodeGenFunction::EmitOMPSingleDirective(const OMPSingleDirective &S) { + CGM.getOpenMPRuntime().EmitOMPSingleRegion(*this, [&]() -> void { + InlinedOpenMPRegion Region(*this, S.getAssociatedStmt()); + RunCleanupsScope Scope(*this); + EmitStmt(cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt()); + EnsureInsertPoint(); + }, S.getLocStart()); } void CodeGenFunction::EmitOMPMasterDirective(const OMPMasterDirective &S) { |