[OPENMP 4.0] Fixed codegen for 'cancellation point' construct.

Generate the next code for 'cancellation point':
if (__kmpc_cancellationpoint()) {
  __kmpc_cancel_barrier();
  <exit construct>;
}

llvm-svn: 241336
This commit is contained in:
Alexey Bataev 2015-07-03 09:56:58 +00:00
parent 40178c352e
commit 81c7ea0ec3
17 changed files with 230 additions and 145 deletions

View File

@ -45,14 +45,14 @@ public:
CGOpenMPRegionInfo(const CapturedStmt &CS,
const CGOpenMPRegionKind RegionKind,
const RegionCodeGenTy &CodeGen)
const RegionCodeGenTy &CodeGen, OpenMPDirectiveKind Kind)
: CGCapturedStmtInfo(CS, CR_OpenMP), RegionKind(RegionKind),
CodeGen(CodeGen) {}
CodeGen(CodeGen), Kind(Kind) {}
CGOpenMPRegionInfo(const CGOpenMPRegionKind RegionKind,
const RegionCodeGenTy &CodeGen)
: CGCapturedStmtInfo(CR_OpenMP), RegionKind(RegionKind),
CodeGen(CodeGen) {}
const RegionCodeGenTy &CodeGen, OpenMPDirectiveKind Kind)
: CGCapturedStmtInfo(CR_OpenMP), RegionKind(RegionKind), CodeGen(CodeGen),
Kind(Kind) {}
/// \brief Get a variable or parameter for storing global thread id
/// inside OpenMP construct.
@ -67,6 +67,8 @@ public:
CGOpenMPRegionKind getRegionKind() const { return RegionKind; }
OpenMPDirectiveKind getDirectiveKind() const { return Kind; }
static bool classof(const CGCapturedStmtInfo *Info) {
return Info->getKind() == CR_OpenMP;
}
@ -74,14 +76,16 @@ public:
protected:
CGOpenMPRegionKind RegionKind;
const RegionCodeGenTy &CodeGen;
OpenMPDirectiveKind Kind;
};
/// \brief API for captured statement code generation in OpenMP constructs.
class CGOpenMPOutlinedRegionInfo : public CGOpenMPRegionInfo {
public:
CGOpenMPOutlinedRegionInfo(const CapturedStmt &CS, const VarDecl *ThreadIDVar,
const RegionCodeGenTy &CodeGen)
: CGOpenMPRegionInfo(CS, ParallelOutlinedRegion, CodeGen),
const RegionCodeGenTy &CodeGen,
OpenMPDirectiveKind Kind)
: CGOpenMPRegionInfo(CS, ParallelOutlinedRegion, CodeGen, Kind),
ThreadIDVar(ThreadIDVar) {
assert(ThreadIDVar != nullptr && "No ThreadID in OpenMP region.");
}
@ -109,8 +113,9 @@ class CGOpenMPTaskOutlinedRegionInfo : public CGOpenMPRegionInfo {
public:
CGOpenMPTaskOutlinedRegionInfo(const CapturedStmt &CS,
const VarDecl *ThreadIDVar,
const RegionCodeGenTy &CodeGen)
: CGOpenMPRegionInfo(CS, TaskOutlinedRegion, CodeGen),
const RegionCodeGenTy &CodeGen,
OpenMPDirectiveKind Kind)
: CGOpenMPRegionInfo(CS, TaskOutlinedRegion, CodeGen, Kind),
ThreadIDVar(ThreadIDVar) {
assert(ThreadIDVar != nullptr && "No ThreadID in OpenMP region.");
}
@ -141,8 +146,9 @@ private:
class CGOpenMPInlinedRegionInfo : public CGOpenMPRegionInfo {
public:
CGOpenMPInlinedRegionInfo(CodeGenFunction::CGCapturedStmtInfo *OldCSI,
const RegionCodeGenTy &CodeGen)
: CGOpenMPRegionInfo(InlinedRegion, CodeGen), OldCSI(OldCSI),
const RegionCodeGenTy &CodeGen,
OpenMPDirectiveKind Kind)
: CGOpenMPRegionInfo(InlinedRegion, CodeGen, Kind), OldCSI(OldCSI),
OuterRegionInfo(dyn_cast_or_null<CGOpenMPRegionInfo>(OldCSI)) {}
// \brief Retrieve the value of the context parameter.
llvm::Value *getContextValue() const override {
@ -207,11 +213,12 @@ public:
/// \param CodeGen Code generation sequence for combined directives. Includes
/// a list of functions used for code generation of implicitly inlined
/// regions.
InlinedOpenMPRegionRAII(CodeGenFunction &CGF, const RegionCodeGenTy &CodeGen)
InlinedOpenMPRegionRAII(CodeGenFunction &CGF, const RegionCodeGenTy &CodeGen,
OpenMPDirectiveKind Kind)
: CGF(CGF) {
// Start emission for the construct.
CGF.CapturedStmtInfo =
new CGOpenMPInlinedRegionInfo(CGF.CapturedStmtInfo, CodeGen);
new CGOpenMPInlinedRegionInfo(CGF.CapturedStmtInfo, CodeGen, Kind);
}
~InlinedOpenMPRegionRAII() {
// Restore original CapturedStmtInfo only if we're done with code emission.
@ -273,28 +280,27 @@ void CGOpenMPRuntime::clear() {
InternalVars.clear();
}
llvm::Value *
CGOpenMPRuntime::emitParallelOutlinedFunction(const OMPExecutableDirective &D,
const VarDecl *ThreadIDVar,
const RegionCodeGenTy &CodeGen) {
llvm::Value *CGOpenMPRuntime::emitParallelOutlinedFunction(
const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) {
assert(ThreadIDVar->getType()->isPointerType() &&
"thread id variable must be of type kmp_int32 *");
const CapturedStmt *CS = cast<CapturedStmt>(D.getAssociatedStmt());
CodeGenFunction CGF(CGM, true);
CGOpenMPOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen);
CGOpenMPOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen, InnermostKind);
CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
return CGF.GenerateCapturedStmtFunction(*CS);
}
llvm::Value *
CGOpenMPRuntime::emitTaskOutlinedFunction(const OMPExecutableDirective &D,
const VarDecl *ThreadIDVar,
const RegionCodeGenTy &CodeGen) {
llvm::Value *CGOpenMPRuntime::emitTaskOutlinedFunction(
const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) {
assert(!ThreadIDVar->getType()->isPointerType() &&
"thread id variable must be of type kmp_int32 for tasks");
auto *CS = cast<CapturedStmt>(D.getAssociatedStmt());
CodeGenFunction CGF(CGM, true);
CGOpenMPTaskOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen);
CGOpenMPTaskOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen,
InnermostKind);
CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
return CGF.GenerateCapturedStmtFunction(*CS);
}
@ -530,6 +536,14 @@ CGOpenMPRuntime::createRuntimeFunction(OpenMPRTLFunction Function) {
RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name*/ "__kmpc_cancel_barrier");
break;
}
case OMPRTL__kmpc_barrier: {
// Build void __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");
break;
}
case OMPRTL__kmpc_for_static_fini: {
// Build void __kmpc_for_static_fini(ident_t *loc, kmp_int32 global_tid);
llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
@ -1246,11 +1260,12 @@ void CGOpenMPRuntime::emitCriticalRegion(CodeGenFunction &CGF,
CGF.EHStack.pushCleanup<CallEndCleanup<std::extent<decltype(Args)>::value>>(
NormalAndEHCleanup, createRuntimeFunction(OMPRTL__kmpc_end_critical),
llvm::makeArrayRef(Args));
emitInlinedDirective(CGF, CriticalOpGen);
emitInlinedDirective(CGF, OMPD_critical, CriticalOpGen);
}
}
static void emitIfStmt(CodeGenFunction &CGF, llvm::Value *IfCond,
OpenMPDirectiveKind Kind,
const RegionCodeGenTy &BodyOpGen) {
llvm::Value *CallBool = CGF.EmitScalarConversion(
IfCond,
@ -1262,7 +1277,7 @@ static void emitIfStmt(CodeGenFunction &CGF, llvm::Value *IfCond,
// Generate the branch (If-stmt)
CGF.Builder.CreateCondBr(CallBool, ThenBlock, ContBlock);
CGF.EmitBlock(ThenBlock);
CGF.CGM.getOpenMPRuntime().emitInlinedDirective(CGF, BodyOpGen);
CGF.CGM.getOpenMPRuntime().emitInlinedDirective(CGF, Kind, BodyOpGen);
// Emit the rest of bblocks/branches
CGF.EmitBranch(ContBlock);
CGF.EmitBlock(ContBlock, true);
@ -1281,7 +1296,7 @@ void CGOpenMPRuntime::emitMasterRegion(CodeGenFunction &CGF,
CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_master), Args);
typedef CallEndCleanup<std::extent<decltype(Args)>::value>
MasterCallEndCleanup;
emitIfStmt(CGF, IsMaster, [&](CodeGenFunction &CGF) -> void {
emitIfStmt(CGF, IsMaster, OMPD_master, [&](CodeGenFunction &CGF) -> void {
CodeGenFunction::RunCleanupsScope Scope(CGF);
CGF.EHStack.pushCleanup<MasterCallEndCleanup>(
NormalAndEHCleanup, createRuntimeFunction(OMPRTL__kmpc_end_master),
@ -1314,7 +1329,7 @@ void CGOpenMPRuntime::emitTaskgroupRegion(CodeGenFunction &CGF,
CGF.EHStack.pushCleanup<CallEndCleanup<std::extent<decltype(Args)>::value>>(
NormalAndEHCleanup, createRuntimeFunction(OMPRTL__kmpc_end_taskgroup),
llvm::makeArrayRef(Args));
emitInlinedDirective(CGF, TaskgroupOpGen);
emitInlinedDirective(CGF, OMPD_taskgroup, TaskgroupOpGen);
}
}
@ -1410,7 +1425,7 @@ void CGOpenMPRuntime::emitSingleRegion(CodeGenFunction &CGF,
CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_single), Args);
typedef CallEndCleanup<std::extent<decltype(Args)>::value>
SingleCallEndCleanup;
emitIfStmt(CGF, IsSingle, [&](CodeGenFunction &CGF) -> void {
emitIfStmt(CGF, IsSingle, OMPD_single, [&](CodeGenFunction &CGF) -> void {
CodeGenFunction::RunCleanupsScope Scope(CGF);
CGF.EHStack.pushCleanup<SingleCallEndCleanup>(
NormalAndEHCleanup, createRuntimeFunction(OMPRTL__kmpc_end_single),
@ -1478,13 +1493,15 @@ void CGOpenMPRuntime::emitOrderedRegion(CodeGenFunction &CGF,
CGF.EHStack.pushCleanup<CallEndCleanup<std::extent<decltype(Args)>::value>>(
NormalAndEHCleanup, createRuntimeFunction(OMPRTL__kmpc_end_ordered),
llvm::makeArrayRef(Args));
emitInlinedDirective(CGF, OrderedOpGen);
emitInlinedDirective(CGF, OMPD_ordered, OrderedOpGen);
}
}
void CGOpenMPRuntime::emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc,
OpenMPDirectiveKind Kind) {
OpenMPDirectiveKind Kind,
bool CheckForCancel) {
// Build call __kmpc_cancel_barrier(loc, thread_id);
// Build call __kmpc_barrier(loc, thread_id);
OpenMPLocationFlags Flags = OMP_IDENT_KMPC;
if (Kind == OMPD_for) {
Flags =
@ -1500,15 +1517,34 @@ void CGOpenMPRuntime::emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc,
} else {
Flags = static_cast<OpenMPLocationFlags>(Flags | 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.
// Build call __kmpc_cancel_barrier(loc, thread_id) or __kmpc_barrier(loc,
// thread_id);
llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc, Flags),
getThreadID(CGF, Loc)};
CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_cancel_barrier), Args);
if (auto *OMPRegionInfo =
dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) {
auto CancelDestination =
CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind());
if (CancelDestination.isValid()) {
auto *Result = CGF.EmitRuntimeCall(
createRuntimeFunction(OMPRTL__kmpc_cancel_barrier), Args);
if (CheckForCancel) {
// if (__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);
// exit from construct;
CGF.EmitBranchThroughCleanup(CancelDestination);
CGF.EmitBlock(ContBB, /*IsFinished=*/true);
}
return;
}
}
CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_barrier), Args);
}
/// \brief Schedule types for 'omp for' loops (these enumerators are taken from
@ -2681,8 +2717,9 @@ void CGOpenMPRuntime::emitTaskwaitCall(CodeGenFunction &CGF,
}
void CGOpenMPRuntime::emitInlinedDirective(CodeGenFunction &CGF,
OpenMPDirectiveKind InnerKind,
const RegionCodeGenTy &CodeGen) {
InlinedOpenMPRegionRAII Region(CGF, CodeGen);
InlinedOpenMPRegionRAII Region(CGF, CodeGen, InnerKind);
CGF.CapturedStmtInfo->EmitBody(CGF, /*S=*/nullptr);
}
@ -2708,25 +2745,32 @@ void CGOpenMPRuntime::emitCancellationPointCall(
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);
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)};
// Ignore return result until untied tasks are supported.
auto *Result = CGF.EmitRuntimeCall(
createRuntimeFunction(OMPRTL__kmpc_cancellationpoint), Args);
// if (__kmpc_cancellationpoint()) {
// __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);
}
}
CGF.EmitBlock(ContBB, /*IsFinished=*/true);
}

View File

@ -68,6 +68,8 @@ private:
// Call to kmp_int32 __kmpc_cancel_barrier(ident_t *loc, kmp_int32
// global_tid);
OMPRTL__kmpc_cancel_barrier,
// Call to void __kmpc_barrier(ident_t *loc, kmp_int32 global_tid);
OMPRTL__kmpc_barrier,
// Call to void __kmpc_for_static_fini(ident_t *loc, kmp_int32 global_tid);
OMPRTL__kmpc_for_static_fini,
// Call to void __kmpc_serialized_parallel(ident_t *loc, kmp_int32
@ -362,22 +364,25 @@ public:
/// kmp_int32 BoundID, struct context_vars*).
/// \param D OpenMP directive.
/// \param ThreadIDVar Variable for thread id in the current OpenMP region.
/// \param InnermostKind Kind of innermost directive (for simple directives it
/// is a directive itself, for combined - its innermost directive).
/// \param CodeGen Code generation sequence for the \a D directive.
virtual llvm::Value *
emitParallelOutlinedFunction(const OMPExecutableDirective &D,
const VarDecl *ThreadIDVar,
const RegionCodeGenTy &CodeGen);
virtual llvm::Value *emitParallelOutlinedFunction(
const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen);
/// \brief Emits outlined function for the OpenMP task directive \a D. This
/// outlined function has type void(*)(kmp_int32 ThreadID, kmp_int32
/// PartID, struct context_vars*).
/// \param D OpenMP directive.
/// \param ThreadIDVar Variable for thread id in the current OpenMP region.
/// \param InnermostKind Kind of innermost directive (for simple directives it
/// is a directive itself, for combined - its innermost directive).
/// \param CodeGen Code generation sequence for the \a D directive.
///
virtual llvm::Value *emitTaskOutlinedFunction(const OMPExecutableDirective &D,
const VarDecl *ThreadIDVar,
const RegionCodeGenTy &CodeGen);
virtual llvm::Value *emitTaskOutlinedFunction(
const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen);
/// \brief Cleans up references to the objects in finished function.
///
@ -444,9 +449,12 @@ public:
/// \brief Emit an implicit/explicit barrier for OpenMP threads.
/// \param Kind Directive for which this implicit barrier call must be
/// generated. Must be OMPD_barrier for explicit barrier generation.
/// \param CheckForCancel true if check for possible cancellation must be
/// performed, false otherwise.
///
virtual void emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc,
OpenMPDirectiveKind Kind);
OpenMPDirectiveKind Kind,
bool CheckForCancel = true);
/// \brief Check if the specified \a ScheduleKind is static non-chunked.
/// This kind of worksharing directive is emitted without outer loop.
@ -631,8 +639,11 @@ public:
/// \brief Emit code for the directive that does not require outlining.
///
/// \param InnermostKind Kind of innermost directive (for simple directives it
/// is a directive itself, for combined - its innermost directive).
/// \param CodeGen Code generation sequence for the \a D directive.
virtual void emitInlinedDirective(CodeGenFunction &CGF,
OpenMPDirectiveKind InnermostKind,
const RegionCodeGenTy &CodeGen);
/// \brief Emit a code for reduction clause. Next code should be emitted for
/// reduction:

View File

@ -451,11 +451,12 @@ void CodeGenFunction::EmitOMPReductionClauseFinal(
static void emitCommonOMPParallelDirective(CodeGenFunction &CGF,
const OMPExecutableDirective &S,
OpenMPDirectiveKind InnermostKind,
const RegionCodeGenTy &CodeGen) {
auto CS = cast<CapturedStmt>(S.getAssociatedStmt());
auto CapturedStruct = CGF.GenerateCapturedStmtArgument(*CS);
auto OutlinedFn = CGF.CGM.getOpenMPRuntime().emitParallelOutlinedFunction(
S, *CS->getCapturedDecl()->param_begin(), CodeGen);
S, *CS->getCapturedDecl()->param_begin(), InnermostKind, CodeGen);
if (auto C = S.getSingleClause(OMPC_num_threads)) {
CodeGenFunction::RunCleanupsScope NumThreadsScope(CGF);
auto NumThreadsClause = cast<OMPNumThreadsClause>(C);
@ -502,7 +503,7 @@ void CodeGenFunction::EmitOMPParallelDirective(const OMPParallelDirective &S) {
CGF.CGM.getOpenMPRuntime().emitBarrierCall(CGF, S.getLocStart(),
OMPD_unknown);
};
emitCommonOMPParallelDirective(*this, S, CodeGen);
emitCommonOMPParallelDirective(*this, S, OMPD_parallel, CodeGen);
}
void CodeGenFunction::EmitOMPLoopBody(const OMPLoopDirective &D,
@ -848,7 +849,7 @@ void CodeGenFunction::EmitOMPSimdDirective(const OMPSimdDirective &S) {
CGF.EmitBlock(ContBlock, true);
}
};
CGM.getOpenMPRuntime().emitInlinedDirective(*this, CodeGen);
CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_simd, CodeGen);
}
void CodeGenFunction::EmitOMPForOuterLoop(OpenMPScheduleClauseKind ScheduleKind,
@ -1186,7 +1187,7 @@ void CodeGenFunction::EmitOMPForDirective(const OMPForDirective &S) {
auto &&CodeGen = [&S, &HasLastprivates](CodeGenFunction &CGF) {
HasLastprivates = CGF.EmitOMPWorksharingLoop(S);
};
CGM.getOpenMPRuntime().emitInlinedDirective(*this, CodeGen);
CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_for, CodeGen);
// Emit an implicit barrier at the end.
if (!S.getSingleClause(OMPC_nowait) || HasLastprivates) {
@ -1200,7 +1201,7 @@ void CodeGenFunction::EmitOMPForSimdDirective(const OMPForSimdDirective &S) {
auto &&CodeGen = [&S, &HasLastprivates](CodeGenFunction &CGF) {
HasLastprivates = CGF.EmitOMPWorksharingLoop(S);
};
CGM.getOpenMPRuntime().emitInlinedDirective(*this, CodeGen);
CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_simd, CodeGen);
// Emit an implicit barrier at the end.
if (!S.getSingleClause(OMPC_nowait) || HasLastprivates) {
@ -1315,7 +1316,7 @@ CodeGenFunction::EmitSections(const OMPExecutableDirective &S) {
CGF.EmitLoadOfScalar(IL, S.getLocStart())));
};
CGM.getOpenMPRuntime().emitInlinedDirective(*this, CodeGen);
CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_sections, CodeGen);
// Emit barrier for lastprivates only if 'sections' directive has 'nowait'
// clause. Otherwise the barrier will be generated by the codegen for the
// directive.
@ -1343,13 +1344,7 @@ CodeGenFunction::EmitSections(const OMPExecutableDirective &S) {
CGF.EmitOMPPrivateClause(S, SingleScope);
(void)SingleScope.Privatize();
CGF.BreakContinueStack.push_back(
BreakContinue(CGF.getJumpDestInCurrentScope(
CGF.createBasicBlock("omp.sections.exit")),
JumpDest()));
CGF.EmitStmt(Stmt);
CGF.EmitBlock(CGF.BreakContinueStack.back().BreakBlock.getBlock());
CGF.BreakContinueStack.pop_back();
};
CGM.getOpenMPRuntime().emitSingleRegion(*this, CodeGen, S.getLocStart(),
llvm::None, llvm::None, llvm::None,
@ -1361,8 +1356,7 @@ CodeGenFunction::EmitSections(const OMPExecutableDirective &S) {
S.getSingleClause(OMPC_nowait)) {
// Emit implicit barrier to synchronize threads and avoid data races on
// initialization of firstprivate variables.
CGM.getOpenMPRuntime().emitBarrierCall(*this, S.getLocStart(),
OMPD_unknown);
CGM.getOpenMPRuntime().emitBarrierCall(*this, S.getLocStart(), OMPD_unknown);
}
return OMPD_single;
}
@ -1382,7 +1376,7 @@ void CodeGenFunction::EmitOMPSectionDirective(const OMPSectionDirective &S) {
CGF.EmitStmt(cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt());
CGF.EnsureInsertPoint();
};
CGM.getOpenMPRuntime().emitInlinedDirective(*this, CodeGen);
CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_section, CodeGen);
}
void CodeGenFunction::EmitOMPSingleDirective(const OMPSingleDirective &S) {
@ -1462,7 +1456,7 @@ void CodeGenFunction::EmitOMPParallelForDirective(
CGF.CGM.getOpenMPRuntime().emitBarrierCall(CGF, S.getLocStart(),
OMPD_parallel);
};
emitCommonOMPParallelDirective(*this, S, CodeGen);
emitCommonOMPParallelDirective(*this, S, OMPD_for, CodeGen);
}
void CodeGenFunction::EmitOMPParallelForSimdDirective(
@ -1479,7 +1473,7 @@ void CodeGenFunction::EmitOMPParallelForSimdDirective(
CGF.CGM.getOpenMPRuntime().emitBarrierCall(CGF, S.getLocStart(),
OMPD_parallel);
};
emitCommonOMPParallelDirective(*this, S, CodeGen);
emitCommonOMPParallelDirective(*this, S, OMPD_simd, CodeGen);
}
void CodeGenFunction::EmitOMPParallelSectionsDirective(
@ -1493,7 +1487,7 @@ void CodeGenFunction::EmitOMPParallelSectionsDirective(
CGF.CGM.getOpenMPRuntime().emitBarrierCall(CGF, S.getLocStart(),
OMPD_parallel);
};
emitCommonOMPParallelDirective(*this, S, CodeGen);
emitCommonOMPParallelDirective(*this, S, OMPD_sections, CodeGen);
}
void CodeGenFunction::EmitOMPTaskDirective(const OMPTaskDirective &S) {
@ -1593,8 +1587,8 @@ void CodeGenFunction::EmitOMPTaskDirective(const OMPTaskDirective &S) {
}
CGF.EmitStmt(CS->getCapturedStmt());
};
auto OutlinedFn =
CGM.getOpenMPRuntime().emitTaskOutlinedFunction(S, *I, CodeGen);
auto OutlinedFn = CGM.getOpenMPRuntime().emitTaskOutlinedFunction(
S, *I, OMPD_task, CodeGen);
// Check if we should emit tied or untied task.
bool Tied = !S.getSingleClause(OMPC_untied);
// Check if the task is final
@ -2096,7 +2090,7 @@ void CodeGenFunction::EmitOMPAtomicDirective(const OMPAtomicDirective &S) {
S.getV(), S.getExpr(), S.getUpdateExpr(),
S.isXLHSInRHSPart(), S.getLocStart());
};
CGM.getOpenMPRuntime().emitInlinedDirective(*this, CodeGen);
CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_atomic, CodeGen);
}
void CodeGenFunction::EmitOMPTargetDirective(const OMPTargetDirective &) {
@ -2117,3 +2111,12 @@ void CodeGenFunction::EmitOMPCancelDirective(const OMPCancelDirective &S) {
llvm_unreachable("CodeGen for 'omp cancel' is not supported yet.");
}
CodeGenFunction::JumpDest
CodeGenFunction::getOMPCancelDestination(OpenMPDirectiveKind Kind) {
if (Kind == OMPD_parallel || Kind == OMPD_task)
return ReturnBlock;
else if (Kind == OMPD_for || Kind == OMPD_section || Kind == OMPD_sections)
return BreakContinueStack.empty() ? JumpDest()
: BreakContinueStack.back().BreakBlock;
return JumpDest();
}

View File

@ -2222,6 +2222,8 @@ public:
const llvm::function_ref<void(CodeGenFunction &)> &BodyGen,
const llvm::function_ref<void(CodeGenFunction &)> &PostIncGen);
JumpDest getOMPCancelDestination(OpenMPDirectiveKind Kind);
private:
/// Helpers for the OpenMP loop directives.

View File

@ -24,7 +24,7 @@ int main(int argc, char **argv) {
static int a;
#pragma omp barrier
// CHECK: [[GTID:%.+]] = call i32 @__kmpc_global_thread_num([[IDENT_T]]* [[LOC]])
// CHECK: call i32 @__kmpc_cancel_barrier([[IDENT_T]]* [[EXPLICIT_BARRIER_LOC]], i32 [[GTID]])
// CHECK: call void @__kmpc_barrier([[IDENT_T]]* [[EXPLICIT_BARRIER_LOC]], i32 [[GTID]])
// CHECK: call {{.+}} [[TMAIN_INT:@.+]](i{{[0-9][0-9]}}
// CHECK: call {{.+}} [[TMAIN_CHAR:@.+]](i{{[0-9]}}
return tmain(argc) + tmain(argv[0][0]) + a;
@ -32,10 +32,10 @@ int main(int argc, char **argv) {
// CHECK: define {{.+}} [[TMAIN_INT]](
// CHECK: [[GTID:%.+]] = call i32 @__kmpc_global_thread_num([[IDENT_T]]* [[LOC]])
// CHECK: call i32 @__kmpc_cancel_barrier([[IDENT_T]]* [[EXPLICIT_BARRIER_LOC]], i32 [[GTID]])
// CHECK: call void @__kmpc_barrier([[IDENT_T]]* [[EXPLICIT_BARRIER_LOC]], i32 [[GTID]])
// CHECK: define {{.+}} [[TMAIN_CHAR]](
// CHECK: [[GTID:%.+]] = call i32 @__kmpc_global_thread_num([[IDENT_T]]* [[LOC]])
// CHECK: call i32 @__kmpc_cancel_barrier([[IDENT_T]]* [[EXPLICIT_BARRIER_LOC]], i32 [[GTID]])
// CHECK: call void @__kmpc_barrier([[IDENT_T]]* [[EXPLICIT_BARRIER_LOC]], i32 [[GTID]])
#endif

View File

@ -19,14 +19,35 @@ int main (int argc, char **argv) {
#pragma omp cancellation point sections
}
// CHECK: call i32 @__kmpc_single(
// CHECK-NOT: @__kmpc_cancellationpoint
// CHECK: call void @__kmpc_end_single(
// CHECK: call void @__kmpc_barrier(%ident_t*
#pragma omp sections
{
#pragma omp cancellation point sections
#pragma omp section
{
#pragma omp cancellation point sections
}
}
// CHECK: call void @__kmpc_for_static_init_4(
// 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: call i32 @__kmpc_cancel_barrier(%ident_t*
// CHECK: br label
// CHECK: [[CONTINUE]]
// CHECK: br label
// CHECK: call void @__kmpc_end_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: 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 cancellation point for
@ -36,10 +57,12 @@ for (int i = 0; i < argc; ++i) {
// 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 cancellation point taskgroup
@ -54,6 +77,7 @@ for (int i = 0; i < argc; ++i) {
// 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
@ -63,6 +87,7 @@ for (int i = 0; i < argc; ++i) {
// 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

View File

@ -50,7 +50,7 @@ void without_schedule_clause(float *a, float *b, float *c, float *d) {
}
// CHECK: [[LOOP1_END]]
// CHECK: call void @__kmpc_for_static_fini([[IDENT_T_TY]]* [[DEFAULT_LOC]], i32 [[GTID]])
// CHECK-NOT: __kmpc_cancel_barrier
// CHECK-NOT: __kmpc_barrier
// CHECK: ret void
}
@ -91,7 +91,7 @@ void static_not_chunked(float *a, float *b, float *c, float *d) {
}
// CHECK: [[LOOP1_END]]
// CHECK: call void @__kmpc_for_static_fini([[IDENT_T_TY]]* [[DEFAULT_LOC]], i32 [[GTID]])
// CHECK: call {{.+}} @__kmpc_cancel_barrier([[IDENT_T_TY]]* [[IMPLICIT_BARRIER_LOC]], i32 [[GTID]])
// CHECK: call {{.+}} @__kmpc_barrier([[IDENT_T_TY]]* [[IMPLICIT_BARRIER_LOC]], i32 [[GTID]])
// CHECK: ret void
}
@ -151,7 +151,7 @@ void static_chunked(float *a, float *b, float *c, float *d) {
// CHECK: [[O_LOOP1_END]]
// CHECK: call void @__kmpc_for_static_fini([[IDENT_T_TY]]* [[DEFAULT_LOC]], i32 [[GTID]])
// CHECK: call {{.+}} @__kmpc_cancel_barrier([[IDENT_T_TY]]* [[IMPLICIT_BARRIER_LOC]], i32 [[GTID]])
// CHECK: call {{.+}} @__kmpc_barrier([[IDENT_T_TY]]* [[IMPLICIT_BARRIER_LOC]], i32 [[GTID]])
// CHECK: ret void
}
@ -192,7 +192,7 @@ void dynamic1(float *a, float *b, float *c, float *d) {
}
// CHECK: [[LOOP1_END]]
// CHECK: [[O_LOOP1_END]]
// CHECK: call {{.+}} @__kmpc_cancel_barrier([[IDENT_T_TY]]* [[IMPLICIT_BARRIER_LOC]], i32 [[GTID]])
// CHECK: call {{.+}} @__kmpc_barrier([[IDENT_T_TY]]* [[IMPLICIT_BARRIER_LOC]], i32 [[GTID]])
// CHECK: ret void
}
@ -233,7 +233,7 @@ void guided7(float *a, float *b, float *c, float *d) {
}
// CHECK: [[LOOP1_END]]
// CHECK: [[O_LOOP1_END]]
// CHECK: call {{.+}} @__kmpc_cancel_barrier([[IDENT_T_TY]]* [[IMPLICIT_BARRIER_LOC]], i32 [[GTID]])
// CHECK: call {{.+}} @__kmpc_barrier([[IDENT_T_TY]]* [[IMPLICIT_BARRIER_LOC]], i32 [[GTID]])
// CHECK: ret void
}
@ -278,7 +278,7 @@ void test_auto(float *a, float *b, float *c, float *d) {
}
// CHECK: [[LOOP1_END]]
// CHECK: [[O_LOOP1_END]]
// CHECK: call {{.+}} @__kmpc_cancel_barrier([[IDENT_T_TY]]* [[IMPLICIT_BARRIER_LOC]], i32 [[GTID]])
// CHECK: call {{.+}} @__kmpc_barrier([[IDENT_T_TY]]* [[IMPLICIT_BARRIER_LOC]], i32 [[GTID]])
// CHECK: ret void
}
@ -320,7 +320,7 @@ void runtime(float *a, float *b, float *c, float *d) {
}
// CHECK: [[LOOP1_END]]
// CHECK: [[O_LOOP1_END]]
// CHECK: call {{.+}} @__kmpc_cancel_barrier([[IDENT_T_TY]]* [[IMPLICIT_BARRIER_LOC]], i32 [[GTID]])
// CHECK: call {{.+}} @__kmpc_barrier([[IDENT_T_TY]]* [[IMPLICIT_BARRIER_LOC]], i32 [[GTID]])
// CHECK: ret void
}

View File

@ -82,7 +82,7 @@ int main() {
// LAMBDA: [[G_PRIVATE_ADDR:%.+]] = alloca i{{[0-9]+}},
// LAMBDA: [[G_VAL:%.+]] = load volatile i{{[0-9]+}}, i{{[0-9]+}}* [[G]]
// LAMBDA: store i{{[0-9]+}} [[G_VAL]], i{{[0-9]+}}* [[G_PRIVATE_ADDR]]
// LAMBDA: call i32 @__kmpc_cancel_barrier(
// LAMBDA: call void @__kmpc_barrier(
g = 1;
// LAMBDA: call void @__kmpc_for_static_init_4(
// LAMBDA: store volatile i{{[0-9]+}} 1, i{{[0-9]+}}* [[G_PRIVATE_ADDR]],
@ -123,7 +123,7 @@ int main() {
// BLOCKS: [[G_PRIVATE_ADDR:%.+]] = alloca i{{[0-9]+}},
// BLOCKS: [[G_VAL:%.+]] = load volatile i{{[0-9]+}}, i{{[0-9]+}}* [[G]]
// BLOCKS: store i{{[0-9]+}} [[G_VAL]], i{{[0-9]+}}* [[G_PRIVATE_ADDR]]
// BLOCKS: call i32 @__kmpc_cancel_barrier(
// BLOCKS: call void @__kmpc_barrier(
g = 1;
// BLOCKS: call void @__kmpc_for_static_init_4(
// BLOCKS: store volatile i{{[0-9]+}} 1, i{{[0-9]+}}* [[G_PRIVATE_ADDR]],
@ -194,7 +194,7 @@ int main() {
// CHECK: call {{.*}} [[ST_TY_DESTR]]([[ST_TY]]* [[ST_TY_TEMP]])
// Synchronization for initialization.
// CHECK: call i32 @__kmpc_cancel_barrier(%{{.+}}* [[IMPLICIT_BARRIER_LOC]], i{{[0-9]+}} [[GTID]])
// CHECK: call void @__kmpc_barrier(%{{.+}}* [[IMPLICIT_BARRIER_LOC]], i{{[0-9]+}} [[GTID]])
// CHECK: call void @__kmpc_for_static_init_4(
// CHECK: call void @__kmpc_for_static_fini(
@ -202,7 +202,7 @@ int main() {
// ~(firstprivate var), ~(firstprivate s_arr)
// CHECK-DAG: call {{.*}} [[S_FLOAT_TY_DESTR]]([[S_FLOAT_TY]]* [[VAR_PRIV]])
// CHECK-DAG: call {{.*}} [[S_FLOAT_TY_DESTR]]([[S_FLOAT_TY]]*
// CHECK: call i32 @__kmpc_cancel_barrier(%{{.+}}* [[IMPLICIT_BARRIER_LOC]], i{{[0-9]+}} [[GTID]])
// CHECK: call void @__kmpc_barrier(%{{.+}}* [[IMPLICIT_BARRIER_LOC]], i{{[0-9]+}} [[GTID]])
// CHECK: = call {{.*}}i{{.+}} [[TMAIN_INT:@.+]]()
@ -264,7 +264,7 @@ int main() {
// Synchronization for initialization.
// CHECK: [[GTID_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[GTID_ADDR_ADDR]]
// CHECK: [[GTID:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[GTID_REF]]
// CHECK: call i32 @__kmpc_cancel_barrier(%{{.+}}* [[IMPLICIT_BARRIER_LOC]], i{{[0-9]+}} [[GTID]])
// CHECK: call void @__kmpc_barrier(%{{.+}}* [[IMPLICIT_BARRIER_LOC]], i{{[0-9]+}} [[GTID]])
// CHECK: call void @__kmpc_for_static_init_4(
// CHECK: call void @__kmpc_for_static_fini(

View File

@ -50,7 +50,7 @@ void simple(float *a, float *b, float *c, float *d) {
}
// CHECK: [[SIMPLE_LOOP1_END]]
// CHECK: call void @__kmpc_for_static_fini(%ident_t* {{.+}}, i32 %{{.+}})
// CHECK: call i32 @__kmpc_cancel_barrier(%ident_t* {{.+}}, i32 %{{.+}})
// CHECK: call void @__kmpc_barrier(%ident_t* {{.+}}, i32 %{{.+}})
long long k = get_val();
@ -101,7 +101,7 @@ void simple(float *a, float *b, float *c, float *d) {
// CHECK: [[LIN0_2:%.+]] = load i64, i64* [[LIN0]]
// CHECK-NEXT: [[LIN_ADD2:%.+]] = add nsw i64 [[LIN0_2]], 27
// CHECK-NEXT: store i64 [[LIN_ADD2]], i64* [[K_VAR]]
// CHECK: call i32 @__kmpc_cancel_barrier(%ident_t* {{.+}}, i32 %{{.+}})
// CHECK: call void @__kmpc_barrier(%ident_t* {{.+}}, i32 %{{.+}})
int lin = 12;
#pragma omp for simd linear(lin : get_val()), linear(g_ptr)
@ -172,7 +172,7 @@ void simple(float *a, float *b, float *c, float *d) {
// CHECK: store i32 {{.+}}, i32* [[LIN_VAR]],
// CHECK: [[GLINSTART:.+]] = load double*, double** [[GLIN_START]]
// CHECK: store double* {{.*}}[[GLIN_VAR]]
// CHECK: call i32 @__kmpc_cancel_barrier(%ident_t* {{.+}}, i32 %{{.+}})
// CHECK: call void @__kmpc_barrier(%ident_t* {{.+}}, i32 %{{.+}})
#pragma omp for simd
// CHECK: call void @__kmpc_for_static_init_4(%ident_t* {{[^,]+}}, i32 %{{[^,]+}}, i32 34, i32* %{{[^,]+}}, i32* [[LB:%[^,]+]], i32* [[UB:%[^,]+]], i32* [[STRIDE:%[^,]+]], i32 1, i32 1)
@ -209,7 +209,7 @@ void simple(float *a, float *b, float *c, float *d) {
}
// CHECK: [[SIMPLE_LOOP4_END]]
// CHECK: call void @__kmpc_for_static_fini(%ident_t* {{.+}}, i32 %{{.+}})
// CHECK: call i32 @__kmpc_cancel_barrier(%ident_t* {{.+}}, i32 %{{.+}})
// CHECK: call void @__kmpc_barrier(%ident_t* {{.+}}, i32 %{{.+}})
#pragma omp for simd
// CHECK: call void @__kmpc_for_static_init_4(%ident_t* {{[^,]+}}, i32 %{{[^,]+}}, i32 34, i32* %{{[^,]+}}, i32* [[LB:%[^,]+]], i32* [[UB:%[^,]+]], i32* [[STRIDE:%[^,]+]], i32 1, i32 1)
@ -246,7 +246,7 @@ void simple(float *a, float *b, float *c, float *d) {
}
// CHECK: [[SIMPLE_LOOP5_END]]
// CHECK: call void @__kmpc_for_static_fini(%ident_t* {{.+}}, i32 %{{.+}})
// CHECK: call i32 @__kmpc_cancel_barrier(%ident_t* {{.+}}, i32 %{{.+}})
// CHECK: call void @__kmpc_barrier(%ident_t* {{.+}}, i32 %{{.+}})
// CHECK-NOT: mul i32 %{{.+}}, 10
#pragma omp for simd
@ -413,7 +413,7 @@ int templ1(T a, T *z) {
// CHECK-NEXT: br label {{%.+}}
// CHECK: [[T1_END]]
// CHECK: call void @__kmpc_for_static_fini(%ident_t* {{.+}}, i32 %{{.+}})
// CHECK: call i32 @__kmpc_cancel_barrier(%ident_t* {{.+}}, i32 %{{.+}})
// CHECK: call void @__kmpc_barrier(%ident_t* {{.+}}, i32 %{{.+}})
// CHECK: ret i32 0
//
void inst_templ1() {
@ -505,7 +505,7 @@ void iter_simple(IterDouble ia, IterDouble ib, IterDouble ic) {
}
// CHECK: [[IT_END]]
// CHECK: call void @__kmpc_for_static_fini(%ident_t* {{.+}}, i32 %{{.+}})
// CHECK: call i32 @__kmpc_cancel_barrier(%ident_t* {{.+}}, i32 %{{.+}})
// CHECK: call void @__kmpc_barrier(%ident_t* {{.+}}, i32 %{{.+}})
// CHECK: ret void
}
@ -584,7 +584,7 @@ void collapsed(float *a, float *b, float *c, float *d) {
// CHECK-NEXT: store i32 3, i32* [[I:%[^,]+]]
// CHECK-NEXT: store i32 5, i32* [[I:%[^,]+]]
// CHECK-NEXT: store i16 9, i16* [[I:%[^,]+]]
// CHECK: call i32 @__kmpc_cancel_barrier(%ident_t* {{.+}}, i32 %{{.+}})
// CHECK: call void @__kmpc_barrier(%ident_t* {{.+}}, i32 %{{.+}})
// CHECK: ret void
}

View File

@ -53,7 +53,7 @@ void static_not_chunked(float *a, float *b, float *c, float *d) {
}
// CHECK: [[LOOP1_END]]
// CHECK: [[O_LOOP1_END]]
// CHECK: call {{.+}} @__kmpc_cancel_barrier([[IDENT_T_TY]]* [[IMPLICIT_BARRIER_LOC]], i32 [[GTID]])
// CHECK: call {{.+}} @__kmpc_barrier([[IDENT_T_TY]]* [[IMPLICIT_BARRIER_LOC]], i32 [[GTID]])
// CHECK: ret void
}
@ -104,7 +104,7 @@ void dynamic1(float *a, float *b, float *c, float *d) {
}
// CHECK: [[LOOP1_END]]
// CHECK: [[O_LOOP1_END]]
// CHECK: call {{.+}} @__kmpc_cancel_barrier([[IDENT_T_TY]]* [[IMPLICIT_BARRIER_LOC]], i32 [[GTID]])
// CHECK: call {{.+}} @__kmpc_barrier([[IDENT_T_TY]]* [[IMPLICIT_BARRIER_LOC]], i32 [[GTID]])
// CHECK: ret void
}
@ -158,7 +158,7 @@ void test_auto(float *a, float *b, float *c, float *d) {
}
// CHECK: [[LOOP1_END]]
// CHECK: [[O_LOOP1_END]]
// CHECK: call {{.+}} @__kmpc_cancel_barrier([[IDENT_T_TY]]* [[IMPLICIT_BARRIER_LOC]], i32 [[GTID]])
// CHECK: call {{.+}} @__kmpc_barrier([[IDENT_T_TY]]* [[IMPLICIT_BARRIER_LOC]], i32 [[GTID]])
// CHECK: ret void
}
@ -209,7 +209,7 @@ void runtime(float *a, float *b, float *c, float *d) {
}
// CHECK: [[LOOP1_END]]
// CHECK: [[O_LOOP1_END]]
// CHECK: call {{.+}} @__kmpc_cancel_barrier([[IDENT_T_TY]]* [[IMPLICIT_BARRIER_LOC]], i32 [[GTID]])
// CHECK: call {{.+}} @__kmpc_barrier([[IDENT_T_TY]]* [[IMPLICIT_BARRIER_LOC]], i32 [[GTID]])
// CHECK: ret void
}

View File

@ -27,7 +27,7 @@ void with_var_schedule() {
// CHECK: [[CHUNK_SIZE:%.+]] = sext i8 [[CHUNK_VAL]] to i64
// CHECK: call void @__kmpc_for_static_init_8u([[IDENT_T_TY]]* [[DEFAULT_LOC:@[^,]+]], i32 [[GTID:%[^,]+]], i32 33, i32* [[IS_LAST:%[^,]+]], i64* [[OMP_LB:%[^,]+]], i64* [[OMP_UB:%[^,]+]], i64* [[OMP_ST:%[^,]+]], i64 1, i64 [[CHUNK_SIZE]])
// CHECK: call void @__kmpc_for_static_fini([[IDENT_T_TY]]* [[DEFAULT_LOC]], i32 [[GTID]])
// CHECK: __kmpc_cancel_barrier
// CHECK: __kmpc_barrier
#pragma omp parallel for schedule(static, char(a))
for (unsigned long long i = 1; i < 2; ++i) {
}
@ -73,7 +73,7 @@ void without_schedule_clause(float *a, float *b, float *c, float *d) {
}
// CHECK: [[LOOP1_END]]
// CHECK: call void @__kmpc_for_static_fini([[IDENT_T_TY]]* [[DEFAULT_LOC]], i32 [[GTID]])
// CHECK: call {{.+}} @__kmpc_cancel_barrier([[IDENT_T_TY]]* [[DEFAULT_LOC_BARRIER:[@%].+]], i32 [[GTID]])
// CHECK: call {{.+}} @__kmpc_barrier([[IDENT_T_TY]]* [[DEFAULT_LOC_BARRIER:[@%].+]], i32 [[GTID]])
// CHECK: ret void
}
@ -117,7 +117,7 @@ void static_not_chunked(float *a, float *b, float *c, float *d) {
}
// CHECK: [[LOOP1_END]]
// CHECK: call void @__kmpc_for_static_fini([[IDENT_T_TY]]* [[DEFAULT_LOC]], i32 [[GTID]])
// CHECK: call {{.+}} @__kmpc_cancel_barrier([[IDENT_T_TY]]* [[DEFAULT_LOC_BARRIER:[@%].+]], i32 [[GTID]])
// CHECK: call {{.+}} @__kmpc_barrier([[IDENT_T_TY]]* [[DEFAULT_LOC_BARRIER:[@%].+]], i32 [[GTID]])
// CHECK: ret void
}
@ -180,7 +180,7 @@ void static_chunked(float *a, float *b, float *c, float *d) {
// CHECK: [[O_LOOP1_END]]
// CHECK: call void @__kmpc_for_static_fini([[IDENT_T_TY]]* [[DEFAULT_LOC]], i32 [[GTID]])
// CHECK: call {{.+}} @__kmpc_cancel_barrier([[IDENT_T_TY]]* [[DEFAULT_LOC_BARRIER:[@%].+]], i32 [[GTID]])
// CHECK: call {{.+}} @__kmpc_barrier([[IDENT_T_TY]]* [[DEFAULT_LOC_BARRIER:[@%].+]], i32 [[GTID]])
// CHECK: ret void
}
@ -225,7 +225,7 @@ void dynamic1(float *a, float *b, float *c, float *d) {
}
// CHECK: [[LOOP1_END]]
// CHECK: [[O_LOOP1_END]]
// CHECK: call {{.+}} @__kmpc_cancel_barrier([[IDENT_T_TY]]* [[DEFAULT_LOC_BARRIER:[@%].+]], i32 [[GTID]])
// CHECK: call {{.+}} @__kmpc_barrier([[IDENT_T_TY]]* [[DEFAULT_LOC_BARRIER:[@%].+]], i32 [[GTID]])
// CHECK: ret void
}
@ -270,7 +270,7 @@ void guided7(float *a, float *b, float *c, float *d) {
}
// CHECK: [[LOOP1_END]]
// CHECK: [[O_LOOP1_END]]
// CHECK: call {{.+}} @__kmpc_cancel_barrier([[IDENT_T_TY]]* [[DEFAULT_LOC_BARRIER:[@%].+]], i32 [[GTID]])
// CHECK: call {{.+}} @__kmpc_barrier([[IDENT_T_TY]]* [[DEFAULT_LOC_BARRIER:[@%].+]], i32 [[GTID]])
// CHECK: ret void
}
@ -322,7 +322,7 @@ void test_auto(float *a, float *b, float *c, float *d) {
// CHECK: [[O_LOOP1_END]]
// CHECK: [[GTID_REF:%.+]] = load i32*, i32** [[GTID_REF_ADDR]],
// CHECK: [[GTID:%.+]] = load i32, i32* [[GTID_REF]],
// CHECK: call {{.+}} @__kmpc_cancel_barrier([[IDENT_T_TY]]* [[DEFAULT_LOC_BARRIER:[@%].+]], i32 [[GTID]])
// CHECK: call {{.+}} @__kmpc_barrier([[IDENT_T_TY]]* [[DEFAULT_LOC_BARRIER:[@%].+]], i32 [[GTID]])
// CHECK: ret void
}
@ -369,7 +369,7 @@ void runtime(float *a, float *b, float *c, float *d) {
// CHECK: [[O_LOOP1_END]]
// CHECK: [[GTID_REF:%.+]] = load i32*, i32** [[GTID_REF_ADDR]],
// CHECK: [[GTID:%.+]] = load i32, i32* [[GTID_REF]],
// CHECK: call {{.+}} @__kmpc_cancel_barrier([[IDENT_T_TY]]* [[DEFAULT_LOC_BARRIER:[@%].+]], i32 [[GTID]])
// CHECK: call {{.+}} @__kmpc_barrier([[IDENT_T_TY]]* [[DEFAULT_LOC_BARRIER:[@%].+]], i32 [[GTID]])
// CHECK: ret void
}
@ -386,14 +386,14 @@ void parallel_for(float *a) {
// TERM_DEBUG: unwind label %[[TERM_LPAD:.+]],
// TERM_DEBUG-NOT: __kmpc_global_thread_num
// TERM_DEBUG: call void @__kmpc_for_static_fini({{.+}}), !dbg [[DBG_LOC_END:![0-9]+]]
// TERM_DEBUG: call {{.+}} @__kmpc_cancel_barrier({{.+}}), !dbg [[DBG_LOC_CANCEL:![0-9]+]]
// TERM_DEBUG: call {{.+}} @__kmpc_barrier({{.+}}), !dbg [[DBG_LOC_CANCEL:![0-9]+]]
// TERM_DEBUG: [[TERM_LPAD]]
// TERM_DEBUG: call void @__clang_call_terminate
// TERM_DEBUG: unreachable
// CLEANUP-NOT: __kmpc_global_thread_num
// CLEANUP: call void @__kmpc_for_static_init_4u({{.+}})
// CLEANUP: call void @__kmpc_for_static_fini({{.+}})
// CLEANUP: call {{.+}} @__kmpc_cancel_barrier({{.+}})
// CLEANUP: call {{.+}} @__kmpc_barrier({{.+}})
for (unsigned i = 131071; i <= 2147483647; i += 127)
a[i] += foo();
}

View File

@ -63,7 +63,7 @@ void simple(float *a, float *b, float *c, float *d) {
}
// CHECK: [[SIMPLE_LOOP1_END]]
// CHECK: call void @__kmpc_for_static_fini(%ident_t* {{.+}}, i32 %{{.+}})
// CHECK: call i32 @__kmpc_cancel_barrier(%ident_t* {{.+}}, i32 %{{.+}})
// CHECK: call void @__kmpc_barrier(%ident_t* {{.+}}, i32 %{{.+}})
long long k = get_val();
@ -112,7 +112,7 @@ void simple(float *a, float *b, float *c, float *d) {
// CHECK: [[LIN0_2:%.+]] = load i64, i64* [[LIN0]]
// CHECK-NEXT: [[LIN_ADD2:%.+]] = add nsw i64 [[LIN0_2]], 27
// CHECK-NEXT: store i64 [[LIN_ADD2]], i64* %{{.+}}
// CHECK: call i32 @__kmpc_cancel_barrier(%ident_t* {{.+}}, i32 %{{.+}})
// CHECK: call void @__kmpc_barrier(%ident_t* {{.+}}, i32 %{{.+}})
int lin = 12;
#pragma omp parallel for simd linear(lin : get_val()), linear(g_ptr)
@ -186,7 +186,7 @@ void simple(float *a, float *b, float *c, float *d) {
// CHECK: [[GLIN_VAR:%.+]] = load double**, double*** %
// CHECK: [[GLINSTART:.+]] = load double*, double** [[GLIN_START]]
// CHECK: store double* {{.*}}[[GLIN_VAR]]
// CHECK: call i32 @__kmpc_cancel_barrier(%ident_t* {{.+}}, i32 %{{.+}})
// CHECK: call void @__kmpc_barrier(%ident_t* {{.+}}, i32 %{{.+}})
#pragma omp parallel for simd
// CHECK: call void @__kmpc_for_static_init_4(%ident_t* {{[^,]+}}, i32 %{{[^,]+}}, i32 34, i32* %{{[^,]+}}, i32* [[LB:%[^,]+]], i32* [[UB:%[^,]+]], i32* [[STRIDE:%[^,]+]], i32 1, i32 1)
@ -223,7 +223,7 @@ void simple(float *a, float *b, float *c, float *d) {
}
// CHECK: [[SIMPLE_LOOP4_END]]
// CHECK: call void @__kmpc_for_static_fini(%ident_t* {{.+}}, i32 %{{.+}})
// CHECK: call i32 @__kmpc_cancel_barrier(%ident_t* {{.+}}, i32 %{{.+}})
// CHECK: call void @__kmpc_barrier(%ident_t* {{.+}}, i32 %{{.+}})
#pragma omp parallel for simd
// CHECK: call void @__kmpc_for_static_init_4(%ident_t* {{[^,]+}}, i32 %{{[^,]+}}, i32 34, i32* %{{[^,]+}}, i32* [[LB:%[^,]+]], i32* [[UB:%[^,]+]], i32* [[STRIDE:%[^,]+]], i32 1, i32 1)
@ -260,7 +260,7 @@ void simple(float *a, float *b, float *c, float *d) {
}
// CHECK: [[SIMPLE_LOOP5_END]]
// CHECK: call void @__kmpc_for_static_fini(%ident_t* {{.+}}, i32 %{{.+}})
// CHECK: call i32 @__kmpc_cancel_barrier(%ident_t* {{.+}}, i32 %{{.+}})
// CHECK: call void @__kmpc_barrier(%ident_t* {{.+}}, i32 %{{.+}})
// CHECK-NOT: mul i32 %{{.+}}, 10
#pragma omp parallel for simd
@ -315,7 +315,7 @@ void simple(float *a, float *b, float *c, float *d) {
// CHECK: [[A_PRIV_VAL:%.+]] = load i32, i32* [[A_PRIV]],
// CHECK-NEXT: store i32 [[A_PRIV_VAL]], i32* %{{.+}},
// CHECK-NEXT: br label
// CHECK: call i32 @__kmpc_cancel_barrier(%ident_t* {{.+}}, i32 %{{.+}})
// CHECK: call void @__kmpc_barrier(%ident_t* {{.+}}, i32 %{{.+}})
}
int R;
{
@ -364,7 +364,7 @@ void simple(float *a, float *b, float *c, float *d) {
// CHECK: [[RED:%.+]] = mul nsw i32 %{{.+}}, [[R_PRIV_VAL]]
// CHECK-NEXT: store i32 [[RED]], i32* %{{.+}},
// CHECK-NEXT: call void @__kmpc_end_reduce_nowait(
// CHECK: call i32 @__kmpc_cancel_barrier(%ident_t* {{.+}}, i32 %{{.+}})
// CHECK: call void @__kmpc_barrier(%ident_t* {{.+}}, i32 %{{.+}})
}
}
@ -473,7 +473,7 @@ void iter_simple(IterDouble ia, IterDouble ib, IterDouble ic) {
}
// CHECK: [[IT_END]]
// CHECK: call void @__kmpc_for_static_fini(%ident_t* {{.+}}, i32 %{{.+}})
// CHECK: call i32 @__kmpc_cancel_barrier(%ident_t* {{.+}}, i32 %{{.+}})
// CHECK: call void @__kmpc_barrier(%ident_t* {{.+}}, i32 %{{.+}})
// CHECK: ret void
}
@ -552,7 +552,7 @@ void collapsed(float *a, float *b, float *c, float *d) {
// CHECK: store i32 3, i32* [[I:%[^,]+]]
// CHECK: store i32 5, i32* [[I:%[^,]+]]
// CHECK: store i16 9, i16* [[I:%[^,]+]]
// CHECK: call i32 @__kmpc_cancel_barrier(%ident_t* {{.+}}, i32 %{{.+}})
// CHECK: call void @__kmpc_barrier(%ident_t* {{.+}}, i32 %{{.+}})
// CHECK: ret void
}
@ -672,7 +672,7 @@ void widened(float *a, float *b, float *c, float *d) {
// CHECK-NEXT: br label {{%.+}}
// CHECK: [[T1_END]]
// CHECK: call void @__kmpc_for_static_fini(%ident_t* {{.+}}, i32 %{{.+}})
// CHECK: call i32 @__kmpc_cancel_barrier(%ident_t* {{.+}}, i32 %{{.+}})
// CHECK: call void @__kmpc_barrier(%ident_t* {{.+}}, i32 %{{.+}})
// CHECK: ret void
//
// TERM_DEBUG-LABEL: bar

View File

@ -73,7 +73,7 @@ int main() {
// CHECK: [[INNER_LOOP_END]]
}
// CHECK: call void @__kmpc_for_static_fini(%{{.+}}* @{{.+}}, i32 [[GTID]])
// CHECK: call i32 @__kmpc_cancel_barrier(%{{.+}}* [[IMPLICIT_BARRIER_LOC]],
// CHECK: call void @__kmpc_barrier(%{{.+}}* [[IMPLICIT_BARRIER_LOC]],
return tmain<int>();
}
@ -89,7 +89,7 @@ int main() {
// CHECK: call void @__kmpc_end_single(
// CHECK-NEXT: br label %[[END]]
// CHECK: [[END]]
// CHECK-NEXT: call i32 @__kmpc_cancel_barrier(%{{.+}}* [[IMPLICIT_BARRIER_LOC]],
// CHECK-NEXT: call void @__kmpc_barrier(%{{.+}}* [[IMPLICIT_BARRIER_LOC]],
// CHECK-NEXT: ret
// CHECK: [[TERM_LPAD]]
// CHECK: call void @__clang_call_terminate(i8*

View File

@ -72,7 +72,7 @@ int main() {
// CHECK: [[INNER_LOOP_END]]
}
// CHECK: call void @__kmpc_for_static_fini(%{{.+}}* @{{.+}}, i32 [[GTID]])
// CHECK: call i32 @__kmpc_cancel_barrier(%{{.+}}* [[IMPLICIT_BARRIER_SECTIONS_LOC]],
// CHECK: call void @__kmpc_barrier(%{{.+}}* [[IMPLICIT_BARRIER_SECTIONS_LOC]],
#pragma omp sections nowait
{
foo();
@ -96,8 +96,8 @@ int main() {
// CHECK-NEXT: br label %[[END]]
// CHECK: [[END]]
// CHECK-NEXT: call i32 @__kmpc_cancel_barrier(%{{.+}}* [[IMPLICIT_BARRIER_SINGLE_LOC]],
// CHECK-NEXT: call i32 @__kmpc_cancel_barrier(
// CHECK-NEXT: ret
// CHECK: call i32 @__kmpc_cancel_barrier(
// CHECK: ret
// CHECK: [[TERM_LPAD]]
// CHECK: call void @__clang_call_terminate(i8*
// CHECK-NEXT: unreachable

View File

@ -84,7 +84,7 @@ int main() {
// LAMBDA: [[G_PRIVATE_ADDR:%.+]] = alloca i{{[0-9]+}},
// LAMBDA: [[G_VAL:%.+]] = load volatile i{{[0-9]+}}, i{{[0-9]+}}* [[G]]
// LAMBDA: store i{{[0-9]+}} [[G_VAL]], i{{[0-9]+}}* [[G_PRIVATE_ADDR]]
// LAMBDA: call i32 @__kmpc_cancel_barrier(
// LAMBDA: call void @__kmpc_barrier(
g = 1;
// LAMBDA: call void @__kmpc_for_static_init_4(
// LAMBDA: store volatile i{{[0-9]+}} 1, i{{[0-9]+}}* [[G_PRIVATE_ADDR]],
@ -126,7 +126,7 @@ int main() {
// BLOCKS: [[G_PRIVATE_ADDR:%.+]] = alloca i{{[0-9]+}},
// BLOCKS: [[G_VAL:%.+]] = load volatile i{{[0-9]+}}, i{{[0-9]+}}* [[G]]
// BLOCKS: store i{{[0-9]+}} [[G_VAL]], i{{[0-9]+}}* [[G_PRIVATE_ADDR]]
// BLOCKS: call i32 @__kmpc_cancel_barrier(
// BLOCKS: call void @__kmpc_barrier(
g = 1;
// BLOCKS: call void @__kmpc_for_static_init_4(
// BLOCKS: store volatile i{{[0-9]+}} 1, i{{[0-9]+}}* [[G_PRIVATE_ADDR]],
@ -199,7 +199,7 @@ int main() {
// CHECK-DAG: call {{.*}} [[S_FLOAT_TY_DESTR]]([[S_FLOAT_TY]]*
// CHECK: call void @__kmpc_end_single(
// CHECK: call i32 @__kmpc_cancel_barrier(%{{.+}}* [[IMPLICIT_BARRIER_LOC]], i{{[0-9]+}} [[GTID]])
// CHECK: call void @__kmpc_barrier(%{{.+}}* [[IMPLICIT_BARRIER_LOC]], i{{[0-9]+}} [[GTID]])
// CHECK: = call {{.*}}i{{.+}} [[TMAIN_INT:@.+]]()
@ -261,7 +261,7 @@ int main() {
// Synchronization for initialization.
// CHECK: [[GTID_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[GTID_ADDR_ADDR]]
// CHECK: [[GTID:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[GTID_REF]]
// CHECK: call i32 @__kmpc_cancel_barrier(%{{.+}}* [[IMPLICIT_BARRIER_LOC]], i{{[0-9]+}} [[GTID]])
// CHECK: call void @__kmpc_barrier(%{{.+}}* [[IMPLICIT_BARRIER_LOC]], i{{[0-9]+}} [[GTID]])
// CHECK: call void @__kmpc_for_static_init_4(
// CHECK: call void @__kmpc_for_static_fini(

View File

@ -63,7 +63,7 @@ int main() {
// CHECK-NEXT: call void @__kmpc_end_single([[IDENT_T_TY]]* [[DEFAULT_LOC]], i32 [[GTID]])
// CHECK-NEXT: br label {{%?}}[[EXIT]]
// CHECK: [[EXIT]]
// CHECK: call{{.*}} @__kmpc_cancel_barrier([[IDENT_T_TY]]* [[IMPLICIT_BARRIER_SINGLE_LOC]], i32 [[GTID]])
// CHECK: call{{.*}} @__kmpc_barrier([[IDENT_T_TY]]* [[IMPLICIT_BARRIER_SINGLE_LOC]], i32 [[GTID]])
#pragma omp single
a = 2;
// CHECK: store i32 0, i32* [[DID_IT]]

View File

@ -182,7 +182,7 @@ int main() {
// CHECK-DAG: call {{.*}} [[S_FLOAT_TY_DESTR]]([[S_FLOAT_TY]]*
// CHECK: call void @__kmpc_end_single(
// CHECK: call i32 @__kmpc_cancel_barrier(%{{.+}}* [[IMPLICIT_BARRIER_LOC]], i{{[0-9]+}} [[GTID]])
// CHECK: call void @__kmpc_barrier(%{{.+}}* [[IMPLICIT_BARRIER_LOC]], i{{[0-9]+}} [[GTID]])
// CHECK: = call {{.*}}i{{.+}} [[TMAIN_INT:@.+]]()