r241239 - [OPENMP 4.0] Codegen for 'cancellation point' directive.
Alexey Bataev
a.bataev at hotmail.com
Wed Jul 1 21:17:08 PDT 2015
Author: abataev
Date: Wed Jul 1 23:17:07 2015
New Revision: 241239
URL: http://llvm.org/viewvc/llvm-project?rev=241239&view=rev
Log:
[OPENMP 4.0] Codegen for 'cancellation point' directive.
The next code is generated for this construct:
```
if (__kmpc_cancellationpoint(ident_t *loc, kmp_int32 global_tid, kmp_int32 cncl_kind) != 0)
<exit from outer innermost construct>;
```
Added:
cfe/trunk/test/OpenMP/cancellation_point_codegen.cpp (with props)
Modified:
cfe/trunk/lib/CodeGen/CGOpenMPRuntime.cpp
cfe/trunk/lib/CodeGen/CGOpenMPRuntime.h
cfe/trunk/lib/CodeGen/CGStmtOpenMP.cpp
cfe/trunk/lib/CodeGen/CodeGenFunction.h
Modified: cfe/trunk/lib/CodeGen/CGOpenMPRuntime.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGOpenMPRuntime.cpp?rev=241239&r1=241238&r2=241239&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGOpenMPRuntime.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGOpenMPRuntime.cpp Wed Jul 1 23:17:07 2015
@@ -806,6 +806,15 @@ CGOpenMPRuntime::createRuntimeFunction(O
RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_wait_deps");
break;
}
+ case OMPRTL__kmpc_cancellationpoint: {
+ // Build kmp_int32 __kmpc_cancellationpoint(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_cancellationpoint");
+ break;
+ }
}
return RTLFn;
}
@@ -2677,3 +2686,47 @@ 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;
+ if (CancelRegion == OMPD_parallel)
+ CancelKind = CancelParallel;
+ else if (CancelRegion == OMPD_for)
+ CancelKind = CancelLoop;
+ else if (CancelRegion == OMPD_sections)
+ CancelKind = CancelSections;
+ else {
+ assert(CancelRegion == OMPD_taskgroup);
+ CancelKind = CancelTaskgroup;
+ }
+ llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
+ CGF.Builder.getInt32(CancelKind)};
+ // Ignore return result until untied tasks are supported.
+ auto *Result = CGF.EmitRuntimeCall(
+ createRuntimeFunction(OMPRTL__kmpc_cancellationpoint), Args);
+ // if (__kmpc_cancellationpoint())
+ // 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);
+ if (CancelRegion == OMPD_parallel || CancelRegion == OMPD_taskgroup) {
+ CGF.EmitBranchThroughCleanup(CGF.ReturnBlock);
+ } else {
+ assert(CancelRegion == OMPD_for || CancelRegion == OMPD_sections);
+ BreakStmt PseudoBrStmt(Loc);
+ CGF.EmitBreakStmt(PseudoBrStmt);
+ }
+ CGF.EmitBlock(ContBB, /*IsFinished=*/true);
+}
+
Modified: cfe/trunk/lib/CodeGen/CGOpenMPRuntime.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGOpenMPRuntime.h?rev=241239&r1=241238&r2=241239&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGOpenMPRuntime.h (original)
+++ cfe/trunk/lib/CodeGen/CGOpenMPRuntime.h Wed Jul 1 23:17:07 2015
@@ -146,6 +146,9 @@ private:
// gtid, kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32
// ndeps_noalias, kmp_depend_info_t *noalias_dep_list);
OMPRTL__kmpc_omp_wait_deps,
+ // Call to kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32
+ // global_tid, kmp_int32 cncl_kind);
+ OMPRTL__kmpc_cancellationpoint,
};
/// \brief Values for bit flags used in the ident_t to describe the fields.
@@ -676,6 +679,14 @@ public:
/// \brief Emit code for 'taskwait' directive.
virtual void emitTaskwaitCall(CodeGenFunction &CGF, SourceLocation Loc);
+
+ /// \brief Emit code for 'cancellation point' construct.
+ /// \param CancelRegion Region kind for which the cancellation point must be
+ /// emitted.
+ ///
+ virtual void emitCancellationPointCall(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=241239&r1=241238&r2=241239&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGStmtOpenMP.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGStmtOpenMP.cpp Wed Jul 1 23:17:07 2015
@@ -505,7 +505,8 @@ void CodeGenFunction::EmitOMPParallelDir
emitCommonOMPParallelDirective(*this, S, CodeGen);
}
-void CodeGenFunction::EmitOMPLoopBody(const OMPLoopDirective &D) {
+void CodeGenFunction::EmitOMPLoopBody(const OMPLoopDirective &D,
+ JumpDest LoopExit) {
RunCleanupsScope BodyScope(*this);
// Update counters values on current iteration.
for (auto I : D.updates()) {
@@ -521,7 +522,7 @@ void CodeGenFunction::EmitOMPLoopBody(co
// On a continue in the body, jump to the end.
auto Continue = getJumpDestInCurrentScope("omp.body.continue");
- BreakContinueStack.push_back(BreakContinue(JumpDest(), Continue));
+ BreakContinueStack.push_back(BreakContinue(LoopExit, Continue));
// Emit loop body.
EmitStmt(D.getBody());
// The end (updates/cleanups).
@@ -827,10 +828,10 @@ void CodeGenFunction::EmitOMPSimdDirecti
CGF.EmitOMPReductionClauseInit(S, LoopScope);
HasLastprivateClause = CGF.EmitOMPLastprivateClauseInit(S, LoopScope);
(void)LoopScope.Privatize();
- CGF.EmitOMPInnerLoop(S, LoopScope.requiresCleanups(),
- S.getCond(), S.getInc(),
+ CGF.EmitOMPInnerLoop(S, LoopScope.requiresCleanups(), S.getCond(),
+ S.getInc(),
[&S](CodeGenFunction &CGF) {
- CGF.EmitOMPLoopBody(S);
+ CGF.EmitOMPLoopBody(S, JumpDest());
CGF.EmitStopPoint(&S);
},
[](CodeGenFunction &) {});
@@ -979,19 +980,17 @@ void CodeGenFunction::EmitOMPForOuterLoo
}
SourceLocation Loc = S.getLocStart();
- EmitOMPInnerLoop(
- S, LoopScope.requiresCleanups(), S.getCond(),
- S.getInc(),
- [&S](CodeGenFunction &CGF) {
- CGF.EmitOMPLoopBody(S);
- CGF.EmitStopPoint(&S);
- },
- [Ordered, IVSize, IVSigned, Loc](CodeGenFunction &CGF) {
- if (Ordered) {
- CGF.CGM.getOpenMPRuntime().emitForOrderedIterationEnd(
- CGF, Loc, IVSize, IVSigned);
- }
- });
+ EmitOMPInnerLoop(S, LoopScope.requiresCleanups(), S.getCond(), S.getInc(),
+ [&S, LoopExit](CodeGenFunction &CGF) {
+ CGF.EmitOMPLoopBody(S, LoopExit);
+ CGF.EmitStopPoint(&S);
+ },
+ [Ordered, IVSize, IVSigned, Loc](CodeGenFunction &CGF) {
+ if (Ordered) {
+ CGF.CGM.getOpenMPRuntime().emitForOrderedIterationEnd(
+ CGF, Loc, IVSize, IVSigned);
+ }
+ });
EmitBlock(Continue.getBlock());
BreakContinueStack.pop_back();
@@ -1140,6 +1139,7 @@ bool CodeGenFunction::EmitOMPWorksharing
RT.emitForInit(*this, S.getLocStart(), ScheduleKind, IVSize, IVSigned,
Ordered, IL.getAddress(), LB.getAddress(),
UB.getAddress(), ST.getAddress());
+ auto LoopExit = getJumpDestInCurrentScope(createBasicBlock("omp.loop.exit"));
// UB = min(UB, GlobalUB);
EmitIgnoredExpr(S.getEnsureUpperBound());
// IV = LB;
@@ -1147,11 +1147,12 @@ bool CodeGenFunction::EmitOMPWorksharing
// while (idx <= UB) { BODY; ++idx; }
EmitOMPInnerLoop(S, LoopScope.requiresCleanups(), S.getCond(),
S.getInc(),
- [&S](CodeGenFunction &CGF) {
- CGF.EmitOMPLoopBody(S);
+ [&S, LoopExit](CodeGenFunction &CGF) {
+ CGF.EmitOMPLoopBody(S, LoopExit);
CGF.EmitStopPoint(&S);
},
[](CodeGenFunction &) {});
+ EmitBlock(LoopExit.getBlock());
// Tell the runtime we are done.
RT.emitForStaticFinish(*this, S.getLocStart());
} else {
@@ -1216,8 +1217,8 @@ static LValue createSectionLVal(CodeGenF
return LVal;
}
-static OpenMPDirectiveKind emitSections(CodeGenFunction &CGF,
- const OMPExecutableDirective &S) {
+OpenMPDirectiveKind
+CodeGenFunction::EmitSections(const OMPExecutableDirective &S) {
auto *Stmt = cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt();
auto *CS = dyn_cast<CompoundStmt>(Stmt);
if (CS && CS->size() > 1) {
@@ -1313,15 +1314,15 @@ static OpenMPDirectiveKind emitSections(
CGF.EmitLoadOfScalar(IL, S.getLocStart())));
};
- CGF.CGM.getOpenMPRuntime().emitInlinedDirective(CGF, CodeGen);
+ CGM.getOpenMPRuntime().emitInlinedDirective(*this, CodeGen);
// Emit barrier for lastprivates only if 'sections' directive has 'nowait'
// clause. Otherwise the barrier will be generated by the codegen for the
// directive.
if (HasLastprivates && S.getSingleClause(OMPC_nowait)) {
// Emit implicit barrier to synchronize threads and avoid data races on
// initialization of firstprivate variables.
- CGF.CGM.getOpenMPRuntime().emitBarrierCall(CGF, S.getLocStart(),
- OMPD_unknown);
+ CGM.getOpenMPRuntime().emitBarrierCall(*this, S.getLocStart(),
+ OMPD_unknown);
}
return OMPD_sections;
}
@@ -1341,12 +1342,17 @@ static OpenMPDirectiveKind emitSections(
CGF.EmitOMPPrivateClause(S, SingleScope);
(void)SingleScope.Privatize();
+ CGF.BreakContinueStack.push_back(
+ BreakContinue(CGF.getJumpDestInCurrentScope(
+ CGF.createBasicBlock("omp.sections.exit")),
+ JumpDest()));
CGF.EmitStmt(Stmt);
- CGF.EnsureInsertPoint();
+ CGF.EmitBlock(CGF.BreakContinueStack.back().BreakBlock.getBlock());
+ CGF.BreakContinueStack.pop_back();
};
- CGF.CGM.getOpenMPRuntime().emitSingleRegion(CGF, CodeGen, S.getLocStart(),
- llvm::None, llvm::None,
- llvm::None, llvm::None);
+ CGM.getOpenMPRuntime().emitSingleRegion(*this, CodeGen, S.getLocStart(),
+ llvm::None, llvm::None, llvm::None,
+ llvm::None);
// Emit barrier for firstprivates, lastprivates or reductions only if
// 'sections' directive has 'nowait' clause. Otherwise the barrier will be
// generated by the codegen for the directive.
@@ -1354,15 +1360,15 @@ static OpenMPDirectiveKind emitSections(
S.getSingleClause(OMPC_nowait)) {
// Emit implicit barrier to synchronize threads and avoid data races on
// initialization of firstprivate variables.
- CGF.CGM.getOpenMPRuntime().emitBarrierCall(CGF, S.getLocStart(),
- OMPD_unknown);
+ CGM.getOpenMPRuntime().emitBarrierCall(*this, S.getLocStart(),
+ OMPD_unknown);
}
return OMPD_single;
}
void CodeGenFunction::EmitOMPSectionsDirective(const OMPSectionsDirective &S) {
LexicalScope Scope(*this, S.getSourceRange());
- OpenMPDirectiveKind EmittedAs = emitSections(*this, S);
+ OpenMPDirectiveKind EmittedAs = EmitSections(S);
// Emit an implicit barrier at the end.
if (!S.getSingleClause(OMPC_nowait)) {
CGM.getOpenMPRuntime().emitBarrierCall(*this, S.getLocStart(), EmittedAs);
@@ -1481,7 +1487,7 @@ void CodeGenFunction::EmitOMPParallelSec
// directives: 'parallel' with 'sections' directive.
LexicalScope Scope(*this, S.getSourceRange());
auto &&CodeGen = [&S](CodeGenFunction &CGF) {
- (void)emitSections(CGF, S);
+ (void)CGF.EmitSections(S);
// Emit implicit barrier at the end of parallel region.
CGF.CGM.getOpenMPRuntime().emitBarrierCall(CGF, S.getLocStart(),
OMPD_parallel);
@@ -2102,7 +2108,7 @@ void CodeGenFunction::EmitOMPTeamsDirect
void CodeGenFunction::EmitOMPCancellationPointDirective(
const OMPCancellationPointDirective &S) {
- llvm_unreachable(
- "CodeGen for 'omp cancellation point' is not supported yet.");
+ CGM.getOpenMPRuntime().emitCancellationPointCall(*this, S.getLocStart(),
+ S.getCancelRegion());
}
Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.h?rev=241239&r1=241238&r2=241239&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenFunction.h (original)
+++ cfe/trunk/lib/CodeGen/CodeGenFunction.h Wed Jul 1 23:17:07 2015
@@ -2236,7 +2236,7 @@ public:
private:
/// Helpers for the OpenMP loop directives.
- void EmitOMPLoopBody(const OMPLoopDirective &D);
+ void EmitOMPLoopBody(const OMPLoopDirective &D, JumpDest LoopExit);
void EmitOMPSimdInit(const OMPLoopDirective &D);
void EmitOMPSimdFinal(const OMPLoopDirective &D);
/// \brief Emit code for the worksharing loop-based directive.
@@ -2248,6 +2248,8 @@ private:
OMPPrivateScope &LoopScope, bool Ordered,
llvm::Value *LB, llvm::Value *UB, llvm::Value *ST,
llvm::Value *IL, llvm::Value *Chunk);
+ /// \brief Emit code for sections directive.
+ OpenMPDirectiveKind EmitSections(const OMPExecutableDirective &S);
public:
Added: cfe/trunk/test/OpenMP/cancellation_point_codegen.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/cancellation_point_codegen.cpp?rev=241239&view=auto
==============================================================================
--- cfe/trunk/test/OpenMP/cancellation_point_codegen.cpp (added)
+++ cfe/trunk/test/OpenMP/cancellation_point_codegen.cpp Wed Jul 1 23:17:07 2015
@@ -0,0 +1,70 @@
+// 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 -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 cancellation point parallel
+ argv[0][0] = argc;
+}
+// CHECK: call void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(
+#pragma omp sections
+{
+#pragma omp cancellation point sections
+}
+// CHECK: call i32 @__kmpc_single(
+// CHECK: [[RES:%.+]] = call i32 @__kmpc_cancellationpoint(%ident_t* {{[^,]+}}, i32 [[GTID]], i32 3)
+// CHECK: [[CMP:%.+]] = icmp ne i32 [[RES]], 0
+// CHECK: br i1 [[CMP]], label %[[EXIT:[^,].+]], label %[[CONTINUE:.+]]
+// CHECK: [[EXIT]]
+// CHECK: br label
+// CHECK: [[CONTINUE]]
+// CHECK: br label
+// CHECK: call void @__kmpc_end_single(
+#pragma omp for
+for (int i = 0; i < argc; ++i) {
+#pragma omp cancellation point for
+}
+// CHECK: call void @__kmpc_for_static_init_4(
+// CHECK: [[RES:%.+]] = call i32 @__kmpc_cancellationpoint(%ident_t* {{[^,]+}}, i32 [[GTID]], i32 2)
+// CHECK: [[CMP:%.+]] = icmp ne i32 [[RES]], 0
+// CHECK: br i1 [[CMP]], label %[[EXIT:[^,].+]], label %[[CONTINUE:.+]]
+// CHECK: [[EXIT]]
+// CHECK: br label
+// CHECK: [[CONTINUE]]
+// CHECK: br label
+// CHECK: call void @__kmpc_for_static_fini(
+#pragma omp task
+{
+#pragma omp cancellation point 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_cancellationpoint(%ident_t* {{[^,]+}}, i32 {{[^,]+}}, i32 1)
+// CHECK: [[CMP:%.+]] = icmp ne i32 [[RES]], 0
+// CHECK: br i1 [[CMP]], label %[[EXIT:[^,]+]],
+// CHECK: [[EXIT]]
+// CHECK: br label %[[RETURN:.+]]
+// CHECK: [[RETURN]]
+// CHECK: ret void
+
+// CHECK: define internal i32 @{{[^(]+}}(i32
+// CHECK: [[RES:%.+]] = call i32 @__kmpc_cancellationpoint(%ident_t* {{[^,]+}}, i32 {{[^,]+}}, i32 4)
+// CHECK: [[CMP:%.+]] = icmp ne i32 [[RES]], 0
+// CHECK: br i1 [[CMP]], label %[[EXIT:[^,]+]],
+// CHECK: [[EXIT]]
+// CHECK: br label %[[RETURN:.+]]
+// CHECK: [[RETURN]]
+// CHECK: ret i32 0
+
+#endif
Propchange: cfe/trunk/test/OpenMP/cancellation_point_codegen.cpp
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: cfe/trunk/test/OpenMP/cancellation_point_codegen.cpp
------------------------------------------------------------------------------
svn:keywords = Author Date Id Rev URL
Propchange: cfe/trunk/test/OpenMP/cancellation_point_codegen.cpp
------------------------------------------------------------------------------
svn:mime-type = text/plain
More information about the cfe-commits
mailing list