Author: abataev Date: Mon Jul 6 00:50:32 2015 New Revision: 241429 URL: http://llvm.org/viewvc/llvm-project?rev=241429&view=rev Log: [OPENMP 4.0] Codegen for 'omp cancel' directive.
Add the next codegen for 'omp cancel' directive: if (__kmpc_cancel()) { __kmpc_cancel_barrier(); <exit construct>; } Added: cfe/trunk/test/OpenMP/cancel_codegen.cpp (with props) Modified: cfe/trunk/lib/CodeGen/CGOpenMPRuntime.cpp cfe/trunk/lib/CodeGen/CGOpenMPRuntime.h cfe/trunk/lib/CodeGen/CGStmtOpenMP.cpp Modified: cfe/trunk/lib/CodeGen/CGOpenMPRuntime.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGOpenMPRuntime.cpp?rev=241429&r1=241428&r2=241429&view=diff ============================================================================== --- cfe/trunk/lib/CodeGen/CGOpenMPRuntime.cpp (original) +++ cfe/trunk/lib/CodeGen/CGOpenMPRuntime.cpp Mon Jul 6 00:50:32 2015 @@ -537,7 +537,7 @@ CGOpenMPRuntime::createRuntimeFunction(O break; } case OMPRTL__kmpc_barrier: { - // Build void __kmpc_cancel_barrier(ident_t *loc, kmp_int32 global_tid); + // Build void __kmpc_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); @@ -829,6 +829,15 @@ CGOpenMPRuntime::createRuntimeFunction(O RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_cancellationpoint"); break; } + case OMPRTL__kmpc_cancel: { + // Build kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid, + // kmp_int32 cncl_kind) + llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy}; + llvm::FunctionType *FnTy = + llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); + RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_cancel"); + break; + } } return RTLFn; } @@ -2723,18 +2732,18 @@ void CGOpenMPRuntime::emitInlinedDirecti CGF.CapturedStmtInfo->EmitBody(CGF, /*S=*/nullptr); } -void CGOpenMPRuntime::emitCancellationPointCall( - CodeGenFunction &CGF, SourceLocation Loc, - OpenMPDirectiveKind CancelRegion) { - // Build call kmp_int32 OMPRTL__kmpc_cancellationpoint(ident_t *loc, kmp_int32 - // global_tid, kmp_int32 cncl_kind); - enum { - CancelNoreq = 0, - CancelParallel = 1, - CancelLoop = 2, - CancelSections = 3, - CancelTaskgroup = 4 - } CancelKind = CancelNoreq; +namespace { +enum RTCancelKind { + CancelNoreq = 0, + CancelParallel = 1, + CancelLoop = 2, + CancelSections = 3, + CancelTaskgroup = 4 +}; +} + +static RTCancelKind getCancellationKind(OpenMPDirectiveKind CancelRegion) { + RTCancelKind CancelKind = CancelNoreq; if (CancelRegion == OMPD_parallel) CancelKind = CancelParallel; else if (CancelRegion == OMPD_for) @@ -2745,14 +2754,22 @@ void CGOpenMPRuntime::emitCancellationPo assert(CancelRegion == OMPD_taskgroup); CancelKind = CancelTaskgroup; } + return CancelKind; +} + +void CGOpenMPRuntime::emitCancellationPointCall( + CodeGenFunction &CGF, SourceLocation Loc, + OpenMPDirectiveKind CancelRegion) { + // Build call kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32 + // global_tid, kmp_int32 cncl_kind); if (auto *OMPRegionInfo = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) { auto CancelDest = CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind()); if (CancelDest.isValid()) { - llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), - getThreadID(CGF, Loc), - CGF.Builder.getInt32(CancelKind)}; + llvm::Value *Args[] = { + emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), + CGF.Builder.getInt32(getCancellationKind(CancelRegion))}; // Ignore return result until untied tasks are supported. auto *Result = CGF.EmitRuntimeCall( createRuntimeFunction(OMPRTL__kmpc_cancellationpoint), Args); @@ -2760,6 +2777,39 @@ void CGOpenMPRuntime::emitCancellationPo // __kmpc_cancel_barrier(); // exit from construct; // } + auto *ExitBB = CGF.createBasicBlock(".cancel.exit"); + auto *ContBB = CGF.createBasicBlock(".cancel.continue"); + auto *Cmp = CGF.Builder.CreateIsNotNull(Result); + CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB); + CGF.EmitBlock(ExitBB); + // __kmpc_cancel_barrier(); + emitBarrierCall(CGF, Loc, OMPD_unknown, /*CheckForCancel=*/false); + // exit from construct; + CGF.EmitBranchThroughCleanup(CancelDest); + CGF.EmitBlock(ContBB, /*IsFinished=*/true); + } + } +} + +void CGOpenMPRuntime::emitCancelCall(CodeGenFunction &CGF, SourceLocation Loc, + OpenMPDirectiveKind CancelRegion) { + // Build call kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid, + // kmp_int32 cncl_kind); + if (auto *OMPRegionInfo = + dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) { + auto CancelDest = + CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind()); + if (CancelDest.isValid()) { + llvm::Value *Args[] = { + emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), + CGF.Builder.getInt32(getCancellationKind(CancelRegion))}; + // Ignore return result until untied tasks are supported. + auto *Result = + CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_cancel), Args); + // if (__kmpc_cancel()) { + // __kmpc_cancel_barrier(); + // exit from construct; + // } auto *ExitBB = CGF.createBasicBlock(".cancel.exit"); auto *ContBB = CGF.createBasicBlock(".cancel.continue"); auto *Cmp = CGF.Builder.CreateIsNotNull(Result); Modified: cfe/trunk/lib/CodeGen/CGOpenMPRuntime.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGOpenMPRuntime.h?rev=241429&r1=241428&r2=241429&view=diff ============================================================================== --- cfe/trunk/lib/CodeGen/CGOpenMPRuntime.h (original) +++ cfe/trunk/lib/CodeGen/CGOpenMPRuntime.h Mon Jul 6 00:50:32 2015 @@ -151,6 +151,9 @@ private: // Call to kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32 // global_tid, kmp_int32 cncl_kind); OMPRTL__kmpc_cancellationpoint, + // Call to kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid, + // kmp_int32 cncl_kind); + OMPRTL__kmpc_cancel, }; /// \brief Values for bit flags used in the ident_t to describe the fields. @@ -698,6 +701,12 @@ public: virtual void emitCancellationPointCall(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind CancelRegion); + + /// \brief Emit code for 'cancel' construct. + /// \param CancelRegion Region kind for which the cancel must be emitted. + /// + virtual void emitCancelCall(CodeGenFunction &CGF, SourceLocation Loc, + OpenMPDirectiveKind CancelRegion); }; } // namespace CodeGen Modified: cfe/trunk/lib/CodeGen/CGStmtOpenMP.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGStmtOpenMP.cpp?rev=241429&r1=241428&r2=241429&view=diff ============================================================================== --- cfe/trunk/lib/CodeGen/CGStmtOpenMP.cpp (original) +++ cfe/trunk/lib/CodeGen/CGStmtOpenMP.cpp Mon Jul 6 00:50:32 2015 @@ -2108,7 +2108,8 @@ void CodeGenFunction::EmitOMPCancellatio } void CodeGenFunction::EmitOMPCancelDirective(const OMPCancelDirective &S) { - llvm_unreachable("CodeGen for 'omp cancel' is not supported yet."); + CGM.getOpenMPRuntime().emitCancelCall(*this, S.getLocStart(), + S.getCancelRegion()); } CodeGenFunction::JumpDest Added: cfe/trunk/test/OpenMP/cancel_codegen.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/cancel_codegen.cpp?rev=241429&view=auto ============================================================================== --- cfe/trunk/test/OpenMP/cancel_codegen.cpp (added) +++ cfe/trunk/test/OpenMP/cancel_codegen.cpp Mon Jul 6 00:50:32 2015 @@ -0,0 +1,95 @@ +// RUN: %clang_cc1 -verify -fopenmp -triple x86_64-apple-darwin13.4.0 -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple x86_64-apple-darwin13.4.0 -emit-pch -o %t %s +// RUN: %clang_cc1 -fopenmp -std=c++11 -include-pch %t -fsyntax-only -verify %s -triple x86_64-apple-darwin13.4.0 -emit-llvm -o - | FileCheck %s +// expected-no-diagnostics + +#ifndef HEADER +#define HEADER + +int main (int argc, char **argv) { +// CHECK: [[GTID:%.+]] = call i32 @__kmpc_global_thread_num( +#pragma omp parallel +{ +#pragma omp cancel parallel + argv[0][0] = argc; +} +// CHECK: call void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call( +#pragma omp sections +{ +#pragma omp cancel sections +} +// CHECK: call i32 @__kmpc_single( +// CHECK-NOT: @__kmpc_cancel +// CHECK: call void @__kmpc_end_single( +// CHECK: call void @__kmpc_barrier(%ident_t* +#pragma omp sections +{ +#pragma omp cancel sections +#pragma omp section + { +#pragma omp cancel sections + } +} +// CHECK: call void @__kmpc_for_static_init_4( +// CHECK: [[RES:%.+]] = call i32 @__kmpc_cancel(%ident_t* {{[^,]+}}, i32 [[GTID]], i32 3) +// CHECK: [[CMP:%.+]] = icmp ne i32 [[RES]], 0 +// CHECK: br i1 [[CMP]], label %[[EXIT:[^,].+]], label %[[CONTINUE:.+]] +// CHECK: [[EXIT]] +// CHECK: call i32 @__kmpc_cancel_barrier(%ident_t* +// CHECK: br label +// CHECK: [[CONTINUE]] +// CHECK: br label +// CHECK: [[RES:%.+]] = call i32 @__kmpc_cancel(%ident_t* {{[^,]+}}, i32 [[GTID]], i32 3) +// CHECK: [[CMP:%.+]] = icmp ne i32 [[RES]], 0 +// CHECK: br i1 [[CMP]], label %[[EXIT:[^,].+]], label %[[CONTINUE:.+]] +// CHECK: [[EXIT]] +// CHECK: call i32 @__kmpc_cancel_barrier(%ident_t* +// CHECK: br label +// CHECK: [[CONTINUE]] +// CHECK: br label +// CHECK: call void @__kmpc_for_static_fini( +#pragma omp for +for (int i = 0; i < argc; ++i) { +#pragma omp cancel for +} +// CHECK: call void @__kmpc_for_static_init_4( +// CHECK: [[RES:%.+]] = call i32 @__kmpc_cancel(%ident_t* {{[^,]+}}, i32 [[GTID]], i32 2) +// CHECK: [[CMP:%.+]] = icmp ne i32 [[RES]], 0 +// CHECK: br i1 [[CMP]], label %[[EXIT:[^,].+]], label %[[CONTINUE:.+]] +// CHECK: [[EXIT]] +// CHECK: call i32 @__kmpc_cancel_barrier(%ident_t* +// CHECK: br label +// CHECK: [[CONTINUE]] +// CHECK: br label +// CHECK: call void @__kmpc_for_static_fini( +// CHECK: call void @__kmpc_barrier(%ident_t* +#pragma omp task +{ +#pragma omp cancel taskgroup +} +// CHECK: call i8* @__kmpc_omp_task_alloc( +// CHECK: call i32 @__kmpc_omp_task( + return argc; +} + +// CHECK: define internal void @{{[^(]+}}(i32* {{[^,]+}}, i32* {{[^,]+}}, +// CHECK: [[RES:%.+]] = call i32 @__kmpc_cancel(%ident_t* {{[^,]+}}, i32 {{[^,]+}}, i32 1) +// CHECK: [[CMP:%.+]] = icmp ne i32 [[RES]], 0 +// CHECK: br i1 [[CMP]], label %[[EXIT:[^,]+]], +// CHECK: [[EXIT]] +// CHECK: call i32 @__kmpc_cancel_barrier(%ident_t* +// CHECK: br label %[[RETURN:.+]] +// CHECK: [[RETURN]] +// CHECK: ret void + +// CHECK: define internal i32 @{{[^(]+}}(i32 +// CHECK: [[RES:%.+]] = call i32 @__kmpc_cancel(%ident_t* {{[^,]+}}, i32 {{[^,]+}}, i32 4) +// CHECK: [[CMP:%.+]] = icmp ne i32 [[RES]], 0 +// CHECK: br i1 [[CMP]], label %[[EXIT:[^,]+]], +// CHECK: [[EXIT]] +// CHECK: call i32 @__kmpc_cancel_barrier(%ident_t* +// CHECK: br label %[[RETURN:.+]] +// CHECK: [[RETURN]] +// CHECK: ret i32 0 + +#endif Propchange: cfe/trunk/test/OpenMP/cancel_codegen.cpp ------------------------------------------------------------------------------ svn:eol-style = native Propchange: cfe/trunk/test/OpenMP/cancel_codegen.cpp ------------------------------------------------------------------------------ svn:keywords = Author Date Id Rev URL Propchange: cfe/trunk/test/OpenMP/cancel_codegen.cpp ------------------------------------------------------------------------------ svn:mime-type = text/plain _______________________________________________ cfe-commits mailing list cfe-commits@cs.uiuc.edu http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits