Index: lib/CodeGen/CGOpenMPRuntime.h =================================================================== --- lib/CodeGen/CGOpenMPRuntime.h +++ lib/CodeGen/CGOpenMPRuntime.h @@ -88,6 +88,9 @@ OMPRTL__kmpc_master, // Call to void __kmpc_end_master(ident_t *, kmp_int32 global_tid); OMPRTL__kmpc_end_master, + // Call to kmp_int32 __kmpc_omp_taskyield(ident_t *, kmp_int32 global_tid, + // int end_part); + OMPRTL__kmpc_omp_taskyield, }; /// \brief Values for bit flags used in the ident_t to describe the fields. @@ -306,6 +309,9 @@ const std::function &MasterOpGen, SourceLocation Loc); + /// \brief Emits code for a taskyield directive. + virtual void EmitOMPTaskyieldCall(CodeGenFunction &CGF, SourceLocation Loc); + /// \brief Emits explicit barrier for OpenMP threads. /// \param IsExplicit true, if it is explicitly specified barrier. /// Index: lib/CodeGen/CGOpenMPRuntime.cpp =================================================================== --- lib/CodeGen/CGOpenMPRuntime.cpp +++ lib/CodeGen/CGOpenMPRuntime.cpp @@ -475,6 +475,15 @@ RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_master"); break; } + case OMPRTL__kmpc_omp_taskyield: { + // Build kmp_int32 __kmpc_omp_taskyield(ident_t *, kmp_int32 global_tid, + // int end_part); + llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy}; + llvm::FunctionType *FnTy = + llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); + RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_taskyield"); + break; + } } return RTLFn; } @@ -786,6 +795,16 @@ }); } +void CGOpenMPRuntime::EmitOMPTaskyieldCall(CodeGenFunction &CGF, + SourceLocation Loc) { + // Build call __kmpc_omp_taskyield(loc, thread_id, 0); + llvm::Value *Args[] = { + EmitOpenMPUpdateLocation(CGF, Loc), GetOpenMPThreadID(CGF, Loc), + llvm::ConstantInt::get(CGM.IntTy, /*V=*/0, /*isSigned=*/true)}; + auto RTLFn = CreateRuntimeFunction(OMPRTL__kmpc_omp_taskyield); + CGF.EmitRuntimeCall(RTLFn, Args); +} + void CGOpenMPRuntime::EmitOMPBarrierCall(CodeGenFunction &CGF, SourceLocation Loc, bool IsExplicit) { // Build call __kmpc_cancel_barrier(loc, thread_id); Index: lib/CodeGen/CGStmtOpenMP.cpp =================================================================== --- lib/CodeGen/CGStmtOpenMP.cpp +++ lib/CodeGen/CGStmtOpenMP.cpp @@ -662,8 +662,9 @@ llvm_unreachable("CodeGen for 'omp task' is not supported yet."); } -void CodeGenFunction::EmitOMPTaskyieldDirective(const OMPTaskyieldDirective &) { - llvm_unreachable("CodeGen for 'omp taskyield' is not supported yet."); +void CodeGenFunction::EmitOMPTaskyieldDirective( + const OMPTaskyieldDirective &S) { + CGM.getOpenMPRuntime().EmitOMPTaskyieldCall(*this, S.getLocStart()); } void CodeGenFunction::EmitOMPBarrierDirective(const OMPBarrierDirective &S) { Index: test/OpenMP/taskyield_codegen.cpp =================================================================== --- test/OpenMP/taskyield_codegen.cpp +++ test/OpenMP/taskyield_codegen.cpp @@ -0,0 +1,39 @@ +// RUN: %clang_cc1 -verify -fopenmp=libiomp5 -x c++ -triple x86_64-unknown-unknown -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -fopenmp=libiomp5 -x c++ -std=c++11 -triple x86_64-unknown-unknown -emit-pch -o %t %s +// RUN: %clang_cc1 -fopenmp=libiomp5 -x c++ -triple x86_64-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s +// expected-no-diagnostics + +#ifndef HEADER +#define HEADER + +// CHECK: [[IDENT_T:%.+]] = type { i32, i32, i32, i32, i8* } + +void foo() {} + +template +T tmain(T argc) { + static T a; +#pragma omp taskyield + return a + argc; +} + +// CHECK-LABEL: @main +int main(int argc, char **argv) { + static int a; +#pragma omp taskyield + // CHECK: [[GTID:%.+]] = call i32 @__kmpc_global_thread_num([[IDENT_T]]* @{{.+}}) + // CHECK: call i32 @__kmpc_omp_taskyield([[IDENT_T]]* @{{.+}}, i32 [[GTID]], i32 0) + // CHECK: call {{.+}} [[TMAIN_INT:@.+]](i{{[0-9][0-9]}} + // CHECK: call {{.+}} [[TMAIN_CHAR:@.+]](i{{[0-9]}} + return tmain(argc) + tmain(argv[0][0]) + a; +} + +// CHECK: define {{.+}} [[TMAIN_INT]]( +// CHECK: [[GTID:%.+]] = call i32 @__kmpc_global_thread_num([[IDENT_T]]* @{{.+}}) +// CHECK: call i32 @__kmpc_omp_taskyield([[IDENT_T]]* @{{.+}}, i32 [[GTID]], i32 0) + +// CHECK: define {{.+}} [[TMAIN_CHAR]]( +// CHECK: [[GTID:%.+]] = call i32 @__kmpc_global_thread_num([[IDENT_T]]* @{{.+}}) +// CHECK: call i32 @__kmpc_omp_taskyield([[IDENT_T]]* @{{.+}}, i32 [[GTID]], i32 0) + +#endif