From 2832eb798c5856b8836aaf23584736ba673c04cd Mon Sep 17 00:00:00 2001 From: Alexey Bataev <a.bataev@hotmail.com> Date: Fri, 5 Dec 2014 04:09:23 +0000 Subject: [PATCH] [OPENMP] Codegen for 'omp barrier' directive. Adds generation of call to "i32 kmpc_cancel_barrier(ident_t *, i32)" libcall for explicitly specified barriers (OMP_IDENT_BARRIER_EXPL flag is added to "flags" field of "ident_t" structure). Also this patch replaces all calls to "kmpc_barrier" function by calls of "__kmpc_cancel_barrier" function which provides additional functionality for OpenMP 4.0. Also, library specific enum OpenMPLocationFlags moved to private section of CGOpenMPRuntime class to make it more independent from library implementation. Differential Revision: http://reviews.llvm.org/D6447 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@223444 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGOpenMPRuntime.cpp | 33 +++++++----- lib/CodeGen/CGOpenMPRuntime.h | 53 ++++++++++--------- lib/CodeGen/CGStmtOpenMP.cpp | 4 +- test/OpenMP/parallel_firstprivate_codegen.cpp | 4 +- test/OpenMP/parallel_private_codegen.cpp | 4 +- 5 files changed, 52 insertions(+), 46 deletions(-) diff --git a/lib/CodeGen/CGOpenMPRuntime.cpp b/lib/CodeGen/CGOpenMPRuntime.cpp index 65dd4d6559b..206a86fe65d 100644 --- a/lib/CodeGen/CGOpenMPRuntime.cpp +++ b/lib/CodeGen/CGOpenMPRuntime.cpp @@ -73,14 +73,10 @@ void CGOpenMPRegionInfo::EmitBody(CodeGenFunction &CGF, Stmt *S) { CodeGenFunction::OMPPrivateScope PrivateScope(CGF); CGF.EmitOMPPrivateClause(Directive, PrivateScope); CGF.EmitOMPFirstprivateClause(Directive, PrivateScope); - if (PrivateScope.Privatize()) { + if (PrivateScope.Privatize()) // Emit implicit barrier to synchronize threads and avoid data races. - auto Flags = static_cast<CGOpenMPRuntime::OpenMPLocationFlags>( - CGOpenMPRuntime::OMP_IDENT_KMPC | - CGOpenMPRuntime::OMP_IDENT_BARRIER_IMPL); CGF.CGM.getOpenMPRuntime().EmitOMPBarrierCall(CGF, Directive.getLocStart(), - Flags); - } + /*IsExplicit=*/false); CGCapturedStmtInfo::EmitBody(CGF, S); } @@ -327,12 +323,13 @@ CGOpenMPRuntime::CreateRuntimeFunction(OpenMPRTLFunction Function) { RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_critical"); break; } - case OMPRTL__kmpc_barrier: { - // Build void __kmpc_barrier(ident_t *loc, kmp_int32 global_tid); + case OMPRTL__kmpc_cancel_barrier: { + // Build kmp_int32 __kmpc_cancel_barrier(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_barrier"); + llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); + RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name*/ "__kmpc_cancel_barrier"); break; } case OMPRTL__kmpc_push_num_threads: { @@ -699,12 +696,20 @@ void CGOpenMPRuntime::EmitOMPMasterRegion( } void CGOpenMPRuntime::EmitOMPBarrierCall(CodeGenFunction &CGF, - SourceLocation Loc, - OpenMPLocationFlags Flags) { - // Build call __kmpc_barrier(loc, thread_id) + SourceLocation Loc, bool IsExplicit) { + // Build call __kmpc_cancel_barrier(loc, thread_id); + auto Flags = static_cast<OpenMPLocationFlags>( + OMP_IDENT_KMPC | + (IsExplicit ? OMP_IDENT_BARRIER_EXPL : OMP_IDENT_BARRIER_IMPL)); + // Build call __kmpc_cancel_barrier(loc, thread_id); + // Replace __kmpc_barrier() function by __kmpc_cancel_barrier() because this + // one provides the same functionality and adds initial support for + // cancellation constructs introduced in OpenMP 4.0. __kmpc_cancel_barrier() + // is provided default by the runtime library so it safe to make such + // replacement. llvm::Value *Args[] = {EmitOpenMPUpdateLocation(CGF, Loc, Flags), GetOpenMPThreadID(CGF, Loc)}; - auto RTLFn = CreateRuntimeFunction(OMPRTL__kmpc_barrier); + auto RTLFn = CreateRuntimeFunction(OMPRTL__kmpc_cancel_barrier); CGF.EmitRuntimeCall(RTLFn, Args); } diff --git a/lib/CodeGen/CGOpenMPRuntime.h b/lib/CodeGen/CGOpenMPRuntime.h index 65348c9c3a1..45cadd2c94f 100644 --- a/lib/CodeGen/CGOpenMPRuntime.h +++ b/lib/CodeGen/CGOpenMPRuntime.h @@ -43,27 +43,6 @@ class CodeGenModule; class CGOpenMPRuntime { public: - /// \brief Values for bit flags used in the ident_t to describe the fields. - /// All enumeric elements are named and described in accordance with the code - /// from http://llvm.org/svn/llvm-project/openmp/trunk/runtime/src/kmp.h - enum OpenMPLocationFlags { - /// \brief Use trampoline for internal microtask. - OMP_IDENT_IMD = 0x01, - /// \brief Use c-style ident structure. - OMP_IDENT_KMPC = 0x02, - /// \brief Atomic reduction option for kmpc_reduce. - OMP_ATOMIC_REDUCE = 0x10, - /// \brief Explicit 'barrier' directive. - OMP_IDENT_BARRIER_EXPL = 0x20, - /// \brief Implicit barrier in code. - OMP_IDENT_BARRIER_IMPL = 0x40, - /// \brief Implicit barrier in 'for' directive. - OMP_IDENT_BARRIER_IMPL_FOR = 0x40, - /// \brief Implicit barrier in 'sections' directive. - OMP_IDENT_BARRIER_IMPL_SECTIONS = 0xC0, - /// \brief Implicit barrier in 'single' directive. - OMP_IDENT_BARRIER_IMPL_SINGLE = 0x140 - }; private: enum OpenMPRTLFunction { @@ -84,8 +63,9 @@ private: // Call to void __kmpc_end_critical(ident_t *loc, kmp_int32 global_tid, // kmp_critical_name *crit); OMPRTL__kmpc_end_critical, - // Call to void __kmpc_barrier(ident_t *loc, kmp_int32 global_tid); - OMPRTL__kmpc_barrier, + // Call to kmp_int32 __kmpc_cancel_barrier(ident_t *loc, kmp_int32 + // global_tid); + OMPRTL__kmpc_cancel_barrier, // Call to void __kmpc_serialized_parallel(ident_t *loc, kmp_int32 // global_tid); OMPRTL__kmpc_serialized_parallel, @@ -103,6 +83,27 @@ private: OMPRTL__kmpc_end_master, }; + /// \brief Values for bit flags used in the ident_t to describe the fields. + /// All enumeric elements are named and described in accordance with the code + /// from http://llvm.org/svn/llvm-project/openmp/trunk/runtime/src/kmp.h + enum OpenMPLocationFlags { + /// \brief Use trampoline for internal microtask. + OMP_IDENT_IMD = 0x01, + /// \brief Use c-style ident structure. + OMP_IDENT_KMPC = 0x02, + /// \brief Atomic reduction option for kmpc_reduce. + OMP_ATOMIC_REDUCE = 0x10, + /// \brief Explicit 'barrier' directive. + OMP_IDENT_BARRIER_EXPL = 0x20, + /// \brief Implicit barrier in code. + OMP_IDENT_BARRIER_IMPL = 0x40, + /// \brief Implicit barrier in 'for' directive. + OMP_IDENT_BARRIER_IMPL_FOR = 0x40, + /// \brief Implicit barrier in 'sections' directive. + OMP_IDENT_BARRIER_IMPL_SECTIONS = 0xC0, + /// \brief Implicit barrier in 'single' directive. + OMP_IDENT_BARRIER_IMPL_SINGLE = 0x140 + }; CodeGenModule &CGM; /// \brief Default const ident_t object used for initialization of all other /// ident_t objects. @@ -298,11 +299,11 @@ public: const std::function<void()> &MasterOpGen, SourceLocation Loc); - /// \brief Emits a barrier for OpenMP threads. - /// \param Flags Flags for the barrier. + /// \brief Emits explicit barrier for OpenMP threads. + /// \param IsExplicit true, if it is explicitly specified barrier. /// virtual void EmitOMPBarrierCall(CodeGenFunction &CGF, SourceLocation Loc, - OpenMPLocationFlags Flags); + bool IsExplicit = true); /// \brief Emits call to void __kmpc_push_num_threads(ident_t *loc, kmp_int32 /// global_tid, kmp_int32 num_threads) to generate code for 'num_threads' diff --git a/lib/CodeGen/CGStmtOpenMP.cpp b/lib/CodeGen/CGStmtOpenMP.cpp index 90776e5a705..cb00c69a66f 100644 --- a/lib/CodeGen/CGStmtOpenMP.cpp +++ b/lib/CodeGen/CGStmtOpenMP.cpp @@ -531,8 +531,8 @@ void CodeGenFunction::EmitOMPTaskyieldDirective(const OMPTaskyieldDirective &) { llvm_unreachable("CodeGen for 'omp taskyield' is not supported yet."); } -void CodeGenFunction::EmitOMPBarrierDirective(const OMPBarrierDirective &) { - llvm_unreachable("CodeGen for 'omp barrier' is not supported yet."); +void CodeGenFunction::EmitOMPBarrierDirective(const OMPBarrierDirective &S) { + CGM.getOpenMPRuntime().EmitOMPBarrierCall(*this, S.getLocStart()); } void CodeGenFunction::EmitOMPTaskwaitDirective(const OMPTaskwaitDirective &) { diff --git a/test/OpenMP/parallel_firstprivate_codegen.cpp b/test/OpenMP/parallel_firstprivate_codegen.cpp index d15616d781a..ecaa3c4f355 100644 --- a/test/OpenMP/parallel_firstprivate_codegen.cpp +++ b/test/OpenMP/parallel_firstprivate_codegen.cpp @@ -112,7 +112,7 @@ int main() { // CHECK: call {{.*}} [[ST_TY_DESTR]]([[ST_TY]]* [[ST_TY_TEMP]]) // CHECK: [[GTID_REF:%.+]] = load i{{[0-9]+}}** [[GTID_ADDR_ADDR]] // CHECK: [[GTID:%.+]] = load i{{[0-9]+}}* [[GTID_REF]] -// CHECK: call void @__kmpc_barrier(%{{.+}}* [[IMPLICIT_BARRIER_LOC]], i{{[0-9]+}} [[GTID]]) +// CHECK: call i32 @__kmpc_cancel_barrier(%{{.+}}* [[IMPLICIT_BARRIER_LOC]], i{{[0-9]+}} [[GTID]]) // CHECK-DAG: call {{.*}} [[S_FLOAT_TY_DESTR]]([[S_FLOAT_TY]]* [[VAR_PRIV]]) // CHECK-DAG: call {{.*}} [[S_FLOAT_TY_DESTR]]([[S_FLOAT_TY]]* // CHECK: ret void @@ -167,7 +167,7 @@ int main() { // CHECK: call {{.*}} [[ST_TY_DESTR]]([[ST_TY]]* [[ST_TY_TEMP]]) // CHECK: [[GTID_REF:%.+]] = load i{{[0-9]+}}** [[GTID_ADDR_ADDR]] // CHECK: [[GTID:%.+]] = load i{{[0-9]+}}* [[GTID_REF]] -// CHECK: call void @__kmpc_barrier(%{{.+}}* [[IMPLICIT_BARRIER_LOC]], i{{[0-9]+}} [[GTID]]) +// CHECK: call i32 @__kmpc_cancel_barrier(%{{.+}}* [[IMPLICIT_BARRIER_LOC]], i{{[0-9]+}} [[GTID]]) // CHECK-DAG: call {{.*}} [[S_INT_TY_DESTR]]([[S_INT_TY]]* [[VAR_PRIV]]) // CHECK-DAG: call {{.*}} [[S_INT_TY_DESTR]]([[S_INT_TY]]* // CHECK: ret void diff --git a/test/OpenMP/parallel_private_codegen.cpp b/test/OpenMP/parallel_private_codegen.cpp index 2db06740d3e..8298eee1f49 100644 --- a/test/OpenMP/parallel_private_codegen.cpp +++ b/test/OpenMP/parallel_private_codegen.cpp @@ -73,7 +73,7 @@ int main() { // CHECK: call {{.*}} [[S_FLOAT_TY_DEF_CONSTR]]([[S_FLOAT_TY]]* [[VAR_PRIV]]) // CHECK: [[GTID_REF:%.+]] = load i{{[0-9]+}}** [[GTID_ADDR_REF]] // CHECK: [[GTID:%.+]] = load i{{[0-9]+}}* [[GTID_REF]] -// CHECK: call void @__kmpc_barrier(%{{.+}}* [[IMPLICIT_BARRIER_LOC]], i{{[0-9]+}} [[GTID]]) +// CHECK: call i32 @__kmpc_cancel_barrier(%{{.+}}* [[IMPLICIT_BARRIER_LOC]], i{{[0-9]+}} [[GTID]]) // CHECK-DAG: call void [[S_FLOAT_TY_DESTR]]([[S_FLOAT_TY]]* [[VAR_PRIV]]) // CHECK-DAG: call void [[S_FLOAT_TY_DESTR]]([[S_FLOAT_TY]]* // CHECK: ret void @@ -101,7 +101,7 @@ int main() { // CHECK: call {{.*}} [[S_INT_TY_DEF_CONSTR]]([[S_INT_TY]]* [[VAR_PRIV]]) // CHECK: [[GTID_REF:%.+]] = load i{{[0-9]+}}** [[GTID_ADDR_REF]] // CHECK: [[GTID:%.+]] = load i{{[0-9]+}}* [[GTID_REF]] -// CHECK: call void @__kmpc_barrier(%{{.+}}* [[IMPLICIT_BARRIER_LOC]], i{{[0-9]+}} [[GTID]]) +// CHECK: call i32 @__kmpc_cancel_barrier(%{{.+}}* [[IMPLICIT_BARRIER_LOC]], i{{[0-9]+}} [[GTID]]) // CHECK-DAG: call void [[S_INT_TY_DESTR]]([[S_INT_TY]]* [[VAR_PRIV]]) // CHECK-DAG: call void [[S_INT_TY_DESTR]]([[S_INT_TY]]* // CHECK: ret void -- GitLab