[OPENMP] Generalize codegen for 'sections'-based directive.
If 'sections' directive has only one sub-section, the code for 'single'-based directive was emitted. Removed this codegen, because it causes crashes in different cases. llvm-svn: 258495
This commit is contained in:
parent
40038d2d1e
commit
3015bcc62a
|
@ -483,7 +483,7 @@ llvm::Value *CGOpenMPRuntime::getThreadID(CodeGenFunction &CGF,
|
|||
if (ThreadID != nullptr)
|
||||
return ThreadID;
|
||||
}
|
||||
if (auto OMPRegionInfo =
|
||||
if (auto *OMPRegionInfo =
|
||||
dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) {
|
||||
if (OMPRegionInfo->getThreadIDVariable()) {
|
||||
// Check if this an outlined function with thread id passed as argument.
|
||||
|
@ -1356,7 +1356,7 @@ void CGOpenMPRuntime::emitParallelCall(CodeGenFunction &CGF, SourceLocation Loc,
|
|||
// return the address of that temp.
|
||||
Address CGOpenMPRuntime::emitThreadIDAddress(CodeGenFunction &CGF,
|
||||
SourceLocation Loc) {
|
||||
if (auto OMPRegionInfo =
|
||||
if (auto *OMPRegionInfo =
|
||||
dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo))
|
||||
if (OMPRegionInfo->getThreadIDVariable())
|
||||
return OMPRegionInfo->getThreadIDVariableLValue(CGF).getAddress();
|
||||
|
@ -1717,15 +1717,10 @@ void CGOpenMPRuntime::emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc,
|
|||
}
|
||||
// Build call __kmpc_cancel_barrier(loc, thread_id) or __kmpc_barrier(loc,
|
||||
// thread_id);
|
||||
auto *OMPRegionInfo =
|
||||
dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo);
|
||||
// Do not emit barrier call in the single directive emitted in some rare cases
|
||||
// for sections directives.
|
||||
if (OMPRegionInfo && OMPRegionInfo->getDirectiveKind() == OMPD_single)
|
||||
return;
|
||||
llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc, Flags),
|
||||
getThreadID(CGF, Loc)};
|
||||
if (OMPRegionInfo) {
|
||||
if (auto *OMPRegionInfo =
|
||||
dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) {
|
||||
if (!ForceSimpleCall && OMPRegionInfo->hasCancel()) {
|
||||
auto *Result = CGF.EmitRuntimeCall(
|
||||
createRuntimeFunction(OMPRTL__kmpc_cancel_barrier), Args);
|
||||
|
@ -3649,8 +3644,6 @@ void CGOpenMPRuntime::emitCancellationPointCall(
|
|||
// global_tid, kmp_int32 cncl_kind);
|
||||
if (auto *OMPRegionInfo =
|
||||
dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) {
|
||||
if (OMPRegionInfo->getDirectiveKind() == OMPD_single)
|
||||
return;
|
||||
if (OMPRegionInfo->hasCancel()) {
|
||||
llvm::Value *Args[] = {
|
||||
emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
|
||||
|
|
|
@ -1657,50 +1657,51 @@ OpenMPDirectiveKind
|
|||
CodeGenFunction::EmitSections(const OMPExecutableDirective &S) {
|
||||
auto *Stmt = cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt();
|
||||
auto *CS = dyn_cast<CompoundStmt>(Stmt);
|
||||
if (CS && CS->size() > 1) {
|
||||
bool HasLastprivates = false;
|
||||
auto &&CodeGen = [&S, CS, &HasLastprivates](CodeGenFunction &CGF) {
|
||||
auto &C = CGF.CGM.getContext();
|
||||
auto KmpInt32Ty = C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1);
|
||||
// Emit helper vars inits.
|
||||
LValue LB = createSectionLVal(CGF, KmpInt32Ty, ".omp.sections.lb.",
|
||||
CGF.Builder.getInt32(0));
|
||||
auto *GlobalUBVal = CGF.Builder.getInt32(CS->size() - 1);
|
||||
LValue UB =
|
||||
createSectionLVal(CGF, KmpInt32Ty, ".omp.sections.ub.", GlobalUBVal);
|
||||
LValue ST = createSectionLVal(CGF, KmpInt32Ty, ".omp.sections.st.",
|
||||
CGF.Builder.getInt32(1));
|
||||
LValue IL = createSectionLVal(CGF, KmpInt32Ty, ".omp.sections.il.",
|
||||
CGF.Builder.getInt32(0));
|
||||
// Loop counter.
|
||||
LValue IV = createSectionLVal(CGF, KmpInt32Ty, ".omp.sections.iv.");
|
||||
OpaqueValueExpr IVRefExpr(S.getLocStart(), KmpInt32Ty, VK_LValue);
|
||||
CodeGenFunction::OpaqueValueMapping OpaqueIV(CGF, &IVRefExpr, IV);
|
||||
OpaqueValueExpr UBRefExpr(S.getLocStart(), KmpInt32Ty, VK_LValue);
|
||||
CodeGenFunction::OpaqueValueMapping OpaqueUB(CGF, &UBRefExpr, UB);
|
||||
// Generate condition for loop.
|
||||
BinaryOperator Cond(&IVRefExpr, &UBRefExpr, BO_LE, C.BoolTy, VK_RValue,
|
||||
OK_Ordinary, S.getLocStart(),
|
||||
/*fpContractable=*/false);
|
||||
// Increment for loop counter.
|
||||
UnaryOperator Inc(&IVRefExpr, UO_PreInc, KmpInt32Ty, VK_RValue,
|
||||
OK_Ordinary, S.getLocStart());
|
||||
auto BodyGen = [CS, &S, &IV](CodeGenFunction &CGF) {
|
||||
// Iterate through all sections and emit a switch construct:
|
||||
// switch (IV) {
|
||||
// case 0:
|
||||
// <SectionStmt[0]>;
|
||||
// break;
|
||||
// ...
|
||||
// case <NumSection> - 1:
|
||||
// <SectionStmt[<NumSection> - 1]>;
|
||||
// break;
|
||||
// }
|
||||
// .omp.sections.exit:
|
||||
auto *ExitBB = CGF.createBasicBlock(".omp.sections.exit");
|
||||
auto *SwitchStmt = CGF.Builder.CreateSwitch(
|
||||
CGF.EmitLoadOfLValue(IV, S.getLocStart()).getScalarVal(), ExitBB,
|
||||
CS->size());
|
||||
bool HasLastprivates = false;
|
||||
auto &&CodeGen = [&S, Stmt, CS, &HasLastprivates](CodeGenFunction &CGF) {
|
||||
auto &C = CGF.CGM.getContext();
|
||||
auto KmpInt32Ty = C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1);
|
||||
// Emit helper vars inits.
|
||||
LValue LB = createSectionLVal(CGF, KmpInt32Ty, ".omp.sections.lb.",
|
||||
CGF.Builder.getInt32(0));
|
||||
auto *GlobalUBVal = CS != nullptr ? CGF.Builder.getInt32(CS->size() - 1)
|
||||
: CGF.Builder.getInt32(0);
|
||||
LValue UB =
|
||||
createSectionLVal(CGF, KmpInt32Ty, ".omp.sections.ub.", GlobalUBVal);
|
||||
LValue ST = createSectionLVal(CGF, KmpInt32Ty, ".omp.sections.st.",
|
||||
CGF.Builder.getInt32(1));
|
||||
LValue IL = createSectionLVal(CGF, KmpInt32Ty, ".omp.sections.il.",
|
||||
CGF.Builder.getInt32(0));
|
||||
// Loop counter.
|
||||
LValue IV = createSectionLVal(CGF, KmpInt32Ty, ".omp.sections.iv.");
|
||||
OpaqueValueExpr IVRefExpr(S.getLocStart(), KmpInt32Ty, VK_LValue);
|
||||
CodeGenFunction::OpaqueValueMapping OpaqueIV(CGF, &IVRefExpr, IV);
|
||||
OpaqueValueExpr UBRefExpr(S.getLocStart(), KmpInt32Ty, VK_LValue);
|
||||
CodeGenFunction::OpaqueValueMapping OpaqueUB(CGF, &UBRefExpr, UB);
|
||||
// Generate condition for loop.
|
||||
BinaryOperator Cond(&IVRefExpr, &UBRefExpr, BO_LE, C.BoolTy, VK_RValue,
|
||||
OK_Ordinary, S.getLocStart(),
|
||||
/*fpContractable=*/false);
|
||||
// Increment for loop counter.
|
||||
UnaryOperator Inc(&IVRefExpr, UO_PreInc, KmpInt32Ty, VK_RValue, OK_Ordinary,
|
||||
S.getLocStart());
|
||||
auto BodyGen = [Stmt, CS, &S, &IV](CodeGenFunction &CGF) {
|
||||
// Iterate through all sections and emit a switch construct:
|
||||
// switch (IV) {
|
||||
// case 0:
|
||||
// <SectionStmt[0]>;
|
||||
// break;
|
||||
// ...
|
||||
// case <NumSection> - 1:
|
||||
// <SectionStmt[<NumSection> - 1]>;
|
||||
// break;
|
||||
// }
|
||||
// .omp.sections.exit:
|
||||
auto *ExitBB = CGF.createBasicBlock(".omp.sections.exit");
|
||||
auto *SwitchStmt = CGF.Builder.CreateSwitch(
|
||||
CGF.EmitLoadOfLValue(IV, S.getLocStart()).getScalarVal(), ExitBB,
|
||||
CS == nullptr ? 1 : CS->size());
|
||||
if (CS) {
|
||||
unsigned CaseNumber = 0;
|
||||
for (auto *SubStmt : CS->children()) {
|
||||
auto CaseBB = CGF.createBasicBlock(".omp.sections.case");
|
||||
|
@ -1710,103 +1711,72 @@ CodeGenFunction::EmitSections(const OMPExecutableDirective &S) {
|
|||
CGF.EmitBranch(ExitBB);
|
||||
++CaseNumber;
|
||||
}
|
||||
CGF.EmitBlock(ExitBB, /*IsFinished=*/true);
|
||||
};
|
||||
|
||||
CodeGenFunction::OMPPrivateScope LoopScope(CGF);
|
||||
if (CGF.EmitOMPFirstprivateClause(S, LoopScope)) {
|
||||
// Emit implicit barrier to synchronize threads and avoid data races on
|
||||
// initialization of firstprivate variables.
|
||||
CGF.CGM.getOpenMPRuntime().emitBarrierCall(
|
||||
CGF, S.getLocStart(), OMPD_unknown, /*EmitChecks=*/false,
|
||||
/*ForceSimpleCall=*/true);
|
||||
} else {
|
||||
auto CaseBB = CGF.createBasicBlock(".omp.sections.case");
|
||||
CGF.EmitBlock(CaseBB);
|
||||
SwitchStmt->addCase(CGF.Builder.getInt32(0), CaseBB);
|
||||
CGF.EmitStmt(Stmt);
|
||||
CGF.EmitBranch(ExitBB);
|
||||
}
|
||||
CGF.EmitOMPPrivateClause(S, LoopScope);
|
||||
HasLastprivates = CGF.EmitOMPLastprivateClauseInit(S, LoopScope);
|
||||
CGF.EmitOMPReductionClauseInit(S, LoopScope);
|
||||
(void)LoopScope.Privatize();
|
||||
|
||||
// Emit static non-chunked loop.
|
||||
CGF.CGM.getOpenMPRuntime().emitForStaticInit(
|
||||
CGF, S.getLocStart(), OMPC_SCHEDULE_static, /*IVSize=*/32,
|
||||
/*IVSigned=*/true, /*Ordered=*/false, IL.getAddress(),
|
||||
LB.getAddress(), UB.getAddress(), ST.getAddress());
|
||||
// UB = min(UB, GlobalUB);
|
||||
auto *UBVal = CGF.EmitLoadOfScalar(UB, S.getLocStart());
|
||||
auto *MinUBGlobalUB = CGF.Builder.CreateSelect(
|
||||
CGF.Builder.CreateICmpSLT(UBVal, GlobalUBVal), UBVal, GlobalUBVal);
|
||||
CGF.EmitStoreOfScalar(MinUBGlobalUB, UB);
|
||||
// IV = LB;
|
||||
CGF.EmitStoreOfScalar(CGF.EmitLoadOfScalar(LB, S.getLocStart()), IV);
|
||||
// while (idx <= UB) { BODY; ++idx; }
|
||||
CGF.EmitOMPInnerLoop(S, /*RequiresCleanup=*/false, &Cond, &Inc, BodyGen,
|
||||
[](CodeGenFunction &) {});
|
||||
// Tell the runtime we are done.
|
||||
CGF.CGM.getOpenMPRuntime().emitForStaticFinish(CGF, S.getLocStart());
|
||||
CGF.EmitOMPReductionClauseFinal(S);
|
||||
|
||||
// Emit final copy of the lastprivate variables if IsLastIter != 0.
|
||||
if (HasLastprivates)
|
||||
CGF.EmitOMPLastprivateClauseFinal(
|
||||
S, CGF.Builder.CreateIsNotNull(
|
||||
CGF.EmitLoadOfScalar(IL, S.getLocStart())));
|
||||
CGF.EmitBlock(ExitBB, /*IsFinished=*/true);
|
||||
};
|
||||
|
||||
bool HasCancel = false;
|
||||
if (auto *OSD = dyn_cast<OMPSectionsDirective>(&S))
|
||||
HasCancel = OSD->hasCancel();
|
||||
else if (auto *OPSD = dyn_cast<OMPParallelSectionsDirective>(&S))
|
||||
HasCancel = OPSD->hasCancel();
|
||||
CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_sections, CodeGen,
|
||||
HasCancel);
|
||||
// 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<OMPNowaitClause>()) {
|
||||
CodeGenFunction::OMPPrivateScope LoopScope(CGF);
|
||||
if (CGF.EmitOMPFirstprivateClause(S, LoopScope)) {
|
||||
// Emit implicit barrier to synchronize threads and avoid data races on
|
||||
// initialization of firstprivate variables.
|
||||
CGM.getOpenMPRuntime().emitBarrierCall(*this, S.getLocStart(),
|
||||
OMPD_unknown);
|
||||
CGF.CGM.getOpenMPRuntime().emitBarrierCall(
|
||||
CGF, S.getLocStart(), OMPD_unknown, /*EmitChecks=*/false,
|
||||
/*ForceSimpleCall=*/true);
|
||||
}
|
||||
return OMPD_sections;
|
||||
}
|
||||
// If only one section is found - no need to generate loop, emit as a single
|
||||
// region.
|
||||
bool HasFirstprivates;
|
||||
// No need to generate reductions for sections with single section region, we
|
||||
// can use original shared variables for all operations.
|
||||
bool HasReductions = S.hasClausesOfKind<OMPReductionClause>();
|
||||
// No need to generate lastprivates for sections with single section region,
|
||||
// we can use original shared variable for all calculations with barrier at
|
||||
// the end of the sections.
|
||||
bool HasLastprivates = S.hasClausesOfKind<OMPLastprivateClause>();
|
||||
auto &&CodeGen = [Stmt, &S, &HasFirstprivates](CodeGenFunction &CGF) {
|
||||
CodeGenFunction::OMPPrivateScope SingleScope(CGF);
|
||||
HasFirstprivates = CGF.EmitOMPFirstprivateClause(S, SingleScope);
|
||||
CGF.EmitOMPPrivateClause(S, SingleScope);
|
||||
(void)SingleScope.Privatize();
|
||||
CGF.EmitOMPPrivateClause(S, LoopScope);
|
||||
HasLastprivates = CGF.EmitOMPLastprivateClauseInit(S, LoopScope);
|
||||
CGF.EmitOMPReductionClauseInit(S, LoopScope);
|
||||
(void)LoopScope.Privatize();
|
||||
|
||||
auto Exit = CGF.getJumpDestInCurrentScope("omp.sections.exit");
|
||||
CGF.BreakContinueStack.push_back(BreakContinue(Exit, Exit));
|
||||
CGF.EmitStmt(Stmt);
|
||||
CGF.EmitBlock(Exit.getBlock());
|
||||
CGF.BreakContinueStack.pop_back();
|
||||
// Emit static non-chunked loop.
|
||||
CGF.CGM.getOpenMPRuntime().emitForStaticInit(
|
||||
CGF, S.getLocStart(), OMPC_SCHEDULE_static, /*IVSize=*/32,
|
||||
/*IVSigned=*/true, /*Ordered=*/false, IL.getAddress(), LB.getAddress(),
|
||||
UB.getAddress(), ST.getAddress());
|
||||
// UB = min(UB, GlobalUB);
|
||||
auto *UBVal = CGF.EmitLoadOfScalar(UB, S.getLocStart());
|
||||
auto *MinUBGlobalUB = CGF.Builder.CreateSelect(
|
||||
CGF.Builder.CreateICmpSLT(UBVal, GlobalUBVal), UBVal, GlobalUBVal);
|
||||
CGF.EmitStoreOfScalar(MinUBGlobalUB, UB);
|
||||
// IV = LB;
|
||||
CGF.EmitStoreOfScalar(CGF.EmitLoadOfScalar(LB, S.getLocStart()), IV);
|
||||
// while (idx <= UB) { BODY; ++idx; }
|
||||
CGF.EmitOMPInnerLoop(S, /*RequiresCleanup=*/false, &Cond, &Inc, BodyGen,
|
||||
[](CodeGenFunction &) {});
|
||||
// Tell the runtime we are done.
|
||||
CGF.CGM.getOpenMPRuntime().emitForStaticFinish(CGF, S.getLocStart());
|
||||
CGF.EmitOMPReductionClauseFinal(S);
|
||||
|
||||
// Emit final copy of the lastprivate variables if IsLastIter != 0.
|
||||
if (HasLastprivates)
|
||||
CGF.EmitOMPLastprivateClauseFinal(
|
||||
S, CGF.Builder.CreateIsNotNull(
|
||||
CGF.EmitLoadOfScalar(IL, S.getLocStart())));
|
||||
};
|
||||
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.
|
||||
if ((HasFirstprivates || HasLastprivates || HasReductions) &&
|
||||
S.getSingleClause<OMPNowaitClause>()) {
|
||||
|
||||
bool HasCancel = false;
|
||||
if (auto *OSD = dyn_cast<OMPSectionsDirective>(&S))
|
||||
HasCancel = OSD->hasCancel();
|
||||
else if (auto *OPSD = dyn_cast<OMPParallelSectionsDirective>(&S))
|
||||
HasCancel = OPSD->hasCancel();
|
||||
CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_sections, CodeGen,
|
||||
HasCancel);
|
||||
// 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<OMPNowaitClause>()) {
|
||||
// Emit implicit barrier to synchronize threads and avoid data races on
|
||||
// initialization of firstprivate variables.
|
||||
CGM.getOpenMPRuntime().emitBarrierCall(*this, S.getLocStart(), OMPD_unknown,
|
||||
/*EmitChecks=*/false,
|
||||
/*ForceSimpleCall=*/true);
|
||||
CGM.getOpenMPRuntime().emitBarrierCall(*this, S.getLocStart(),
|
||||
OMPD_unknown);
|
||||
}
|
||||
return OMPD_single;
|
||||
return OMPD_sections;
|
||||
}
|
||||
|
||||
void CodeGenFunction::EmitOMPSectionsDirective(const OMPSectionsDirective &S) {
|
||||
|
@ -2651,8 +2621,7 @@ CodeGenFunction::getOMPCancelDestination(OpenMPDirectiveKind Kind) {
|
|||
if (Kind == OMPD_parallel || Kind == OMPD_task)
|
||||
return ReturnBlock;
|
||||
assert(Kind == OMPD_for || Kind == OMPD_section || Kind == OMPD_sections ||
|
||||
Kind == OMPD_parallel_sections || Kind == OMPD_parallel_for ||
|
||||
Kind == OMPD_single);
|
||||
Kind == OMPD_parallel_sections || Kind == OMPD_parallel_for);
|
||||
return BreakContinueStack.back().BreakBlock;
|
||||
}
|
||||
|
||||
|
|
|
@ -19,9 +19,10 @@ int main (int argc, char **argv) {
|
|||
{
|
||||
#pragma omp cancel sections
|
||||
}
|
||||
// CHECK: call i32 @__kmpc_single(
|
||||
// CHECK: call void @__kmpc_for_static_init_4(
|
||||
// CHECK: call i32 @__kmpc_cancel(
|
||||
// CHECK: call void @__kmpc_end_single(
|
||||
// CHECK: call i32 @__kmpc_cancel_barrier(%ident_t*
|
||||
// CHECK: call void @__kmpc_for_static_fini(
|
||||
// CHECK: call void @__kmpc_barrier(%ident_t*
|
||||
#pragma omp sections
|
||||
{
|
||||
|
@ -125,9 +126,10 @@ for (int i = 0; i < argc; ++i) {
|
|||
// CHECK: ret i32 0
|
||||
|
||||
// CHECK: define internal void @{{[^(]+}}(i32* {{[^,]+}}, i32* {{[^,]+}})
|
||||
// CHECK: call i32 @__kmpc_single(
|
||||
// CHECK: call void @__kmpc_for_static_init_4(
|
||||
// CHECK: call i32 @__kmpc_cancel(
|
||||
// CHECK: call void @__kmpc_end_single(
|
||||
// CHECK: call i32 @__kmpc_cancel_barrier(%ident_t*
|
||||
// CHECK: call void @__kmpc_for_static_fini(
|
||||
// CHECK: ret void
|
||||
|
||||
// CHECK: define internal void @{{[^(]+}}(i32* {{[^,]+}}, i32* {{[^,]+}})
|
||||
|
|
|
@ -22,9 +22,16 @@ int main (int argc, char **argv) {
|
|||
#pragma omp cancel sections
|
||||
}
|
||||
}
|
||||
// CHECK: call i32 @__kmpc_single(
|
||||
// CHECK-NOT: @__kmpc_cancellationpoint
|
||||
// CHECK: call void @__kmpc_end_single(
|
||||
// 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_for_static_fini(
|
||||
// CHECK: call void @__kmpc_barrier(%ident_t*
|
||||
#pragma omp sections
|
||||
{
|
||||
|
@ -126,9 +133,16 @@ for (int i = 0; i < argc; ++i) {
|
|||
// CHECK: ret i32 0
|
||||
|
||||
// CHECK: define internal void @{{[^(]+}}(i32* {{[^,]+}}, i32* {{[^,]+}})
|
||||
// CHECK: call i32 @__kmpc_single(
|
||||
// CHECK-NOT: @__kmpc_cancellationpoint
|
||||
// CHECK: call void @__kmpc_end_single(
|
||||
// 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_for_static_fini(
|
||||
// CHECK: ret void
|
||||
|
||||
// CHECK: define internal void @{{[^(]+}}(i32* {{[^,]+}}, i32* {{[^,]+}})
|
||||
|
|
|
@ -78,15 +78,10 @@ int main() {
|
|||
// CHECK-LABEL: tmain
|
||||
// CHECK: call void {{.*}} @__kmpc_fork_call(
|
||||
// CHECK-NOT: __kmpc_global_thread_num
|
||||
// CHECK: [[RES:%.+]] = call i32 @__kmpc_single(
|
||||
// CHECK-NEXT: [[BOOLRES:%.+]] = icmp ne i32 [[RES]], 0
|
||||
// CHECK-NEXT: br i1 [[BOOLRES]], label %[[THEN:.+]], label %[[END:.+]]
|
||||
// CHECK: [[THEN]]
|
||||
// CHECK-NEXT: invoke void @{{.*}}foo{{.*}}()
|
||||
// CHECK: call void @__kmpc_for_static_init_4(
|
||||
// CHECK: invoke void @{{.*}}foo{{.*}}()
|
||||
// CHECK-NEXT: unwind label %[[TERM_LPAD:.+]]
|
||||
// CHECK: call void @__kmpc_end_single(
|
||||
// CHECK-NEXT: br label %[[END]]
|
||||
// CHECK: [[END]]
|
||||
// CHECK: call void @__kmpc_for_static_fini(
|
||||
// CHECK-NEXT: ret
|
||||
// CHECK: [[TERM_LPAD]]
|
||||
// CHECK: call void @__clang_call_terminate(i8*
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
#ifndef HEADER
|
||||
#define HEADER
|
||||
// CHECK: [[IMPLICIT_BARRIER_SECTIONS_LOC:@.+]] = private unnamed_addr constant %{{.+}} { i32 0, i32 194, i32 0, i32 0, i8*
|
||||
// CHECK: [[IMPLICIT_BARRIER_SINGLE_LOC:@.+]] = private unnamed_addr constant %{{.+}} { i32 0, i32 322, i32 0, i32 0, i8*
|
||||
// CHECK-LABEL: foo
|
||||
void foo() {};
|
||||
// CHECK-LABEL: bar
|
||||
|
@ -86,17 +85,12 @@ int main() {
|
|||
// CHECK-LABEL: tmain
|
||||
// CHECK: call void {{.*}} @__kmpc_fork_call(
|
||||
// CHECK-NOT: __kmpc_global_thread_num
|
||||
// CHECK: [[RES:%.+]] = call i32 @__kmpc_single(
|
||||
// CHECK-NEXT: [[BOOLRES:%.+]] = icmp ne i32 [[RES]], 0
|
||||
// CHECK-NEXT: br i1 [[BOOLRES]], label %[[THEN:.+]], label %[[END:.+]]
|
||||
// CHECK: [[THEN]]
|
||||
// CHECK-NEXT: invoke void @{{.*}}foo{{.*}}()
|
||||
// CHECK: call void @__kmpc_for_static_init_4(
|
||||
// CHECK: invoke void @{{.*}}foo{{.*}}()
|
||||
// CHECK-NEXT: unwind label %[[TERM_LPAD:.+]]
|
||||
// CHECK: call void @__kmpc_end_single(
|
||||
// CHECK-NEXT: br label %[[END]]
|
||||
// CHECK: [[END]]
|
||||
// CHECK-NEXT: call void @__kmpc_barrier(%{{.+}}* [[IMPLICIT_BARRIER_SINGLE_LOC]],
|
||||
// CHECK: ret
|
||||
// CHECK: call void @__kmpc_for_static_fini(
|
||||
// CHECK: call void @__kmpc_barrier(%{{.+}}* [[IMPLICIT_BARRIER_SECTIONS_LOC]],
|
||||
// CHECK: ret
|
||||
// CHECK: [[TERM_LPAD]]
|
||||
// CHECK: call void @__clang_call_terminate(i8*
|
||||
// CHECK-NEXT: unreachable
|
||||
|
|
|
@ -202,14 +202,18 @@ int main() {
|
|||
|
||||
// CHECK: define {{.*}}i{{[0-9]+}} @main()
|
||||
// CHECK: alloca i{{[0-9]+}},
|
||||
// CHECK: [[GTID:%.+]] = call i32 @__kmpc_global_thread_num(
|
||||
// CHECK: alloca i{{[0-9]+}},
|
||||
// CHECK: alloca i{{[0-9]+}},
|
||||
// CHECK: alloca i{{[0-9]+}},
|
||||
// CHECK: alloca i{{[0-9]+}},
|
||||
// CHECK: alloca i{{[0-9]+}},
|
||||
// CHECK: [[T_VAR_PRIV:%.+]] = alloca i{{[0-9]+}},
|
||||
// CHECK: [[VEC_PRIV:%.+]] = alloca [2 x i{{[0-9]+}}],
|
||||
// CHECK: [[S_ARR_PRIV:%.+]] = alloca [2 x [[S_FLOAT_TY]]],
|
||||
// CHECK: [[VAR_PRIV:%.+]] = alloca [[S_FLOAT_TY]],
|
||||
// CHECK: [[SIVAR_PRIV:%.+]] = alloca i{{[0-9]+}},
|
||||
// CHECK: [[GTID:%.+]] = call i32 @__kmpc_global_thread_num(
|
||||
|
||||
// CHECK: call i32 @__kmpc_single(
|
||||
// firstprivate t_var(t_var)
|
||||
// CHECK: [[T_VAR_VAL:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[T_VAR]],
|
||||
// CHECK: store i{{[0-9]+}} [[T_VAR_VAL]], i{{[0-9]+}}* [[T_VAR_PRIV]],
|
||||
|
@ -235,15 +239,16 @@ int main() {
|
|||
// CHECK: call {{.*}} [[ST_TY_DESTR]]([[ST_TY]]* [[ST_TY_TEMP]])
|
||||
|
||||
// firstprivate isvar
|
||||
// CHEC: [[SIVAR_VAL:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[SIVAR]],
|
||||
// CHEC: store i{{[0-9]+}} [[SIVAR_VAL]], i{{[0-9]+}}* [[SIVAR_PRIV]],
|
||||
// CHECK: [[SIVAR_VAL:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[SIVAR]],
|
||||
// CHECK: store i{{[0-9]+}} [[SIVAR_VAL]], i{{[0-9]+}}* [[SIVAR_PRIV]],
|
||||
|
||||
// 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(
|
||||
|
||||
// ~(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 void @__kmpc_end_single(
|
||||
|
||||
// CHECK: call void @__kmpc_barrier(%{{.+}}* [[IMPLICIT_BARRIER_LOC]], i{{[0-9]+}} [[GTID]])
|
||||
|
||||
// CHECK: = call {{.*}}i{{.+}} [[TMAIN_INT:@.+]]()
|
||||
|
||||
|
|
|
@ -23,7 +23,6 @@ volatile int g = 1212;
|
|||
// CHECK: [[S_FLOAT_TY:%.+]] = type { float }
|
||||
// CHECK [[CAP_MAIN_TY:%.+]] = type { i{{[0-9]+}}*, [2 x i{{[0-9]+}}]*, [2 x [[S_FLOAT_TY]]]*, [[S_FLOAT_TY]]*, i{{[0-9]+}}* }
|
||||
// CHECK: [[S_INT_TY:%.+]] = type { i32 }
|
||||
// CHECK-DAG: [[SINGLE_BARRIER_LOC:@.+]] = private unnamed_addr constant %{{.+}} { i32 0, i32 322, i32 0, i32 0, i8*
|
||||
// CHECK-DAG: [[SECTIONS_BARRIER_LOC:@.+]] = private unnamed_addr constant %{{.+}} { i32 0, i32 194, i32 0, i32 0, i8*
|
||||
// CHECK-DAG: [[X:@.+]] = global double 0.0
|
||||
template <typename T>
|
||||
|
@ -234,27 +233,29 @@ int main() {
|
|||
// CHECK: ret
|
||||
|
||||
// CHECK: define internal void [[MAIN_MICROTASK]](i{{[0-9]+}}* noalias [[GTID_ADDR:%.+]], i{{[0-9]+}}* noalias %{{.+}},
|
||||
// CHECK-NOT: alloca i{{[0-9]+}},
|
||||
// CHECK-NOT: alloca [2 x i{{[0-9]+}}],
|
||||
// CHECK-NOT: alloca [2 x [[S_FLOAT_TY]]],
|
||||
// CHECK-NOT: alloca [[S_FLOAT_TY]],
|
||||
// CHECK: alloca i{{[0-9]+}},
|
||||
// CHECK: alloca i{{[0-9]+}},
|
||||
// CHECK: alloca i{{[0-9]+}},
|
||||
// CHECK: alloca i{{[0-9]+}},
|
||||
// CHECK: alloca i{{[0-9]+}},
|
||||
// CHECK: alloca i{{[0-9]+}},
|
||||
// CHECK: alloca [2 x i{{[0-9]+}}],
|
||||
// CHECK: alloca [2 x [[S_FLOAT_TY]]],
|
||||
// CHECK: alloca [[S_FLOAT_TY]],
|
||||
// CHECK: alloca i{{[0-9]+}},
|
||||
// CHECK: store i{{[0-9]+}}* [[GTID_ADDR]], i{{[0-9]+}}** [[GTID_ADDR_REF:%.+]]
|
||||
|
||||
// CHECK: [[GTID_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[GTID_ADDR_REF]]
|
||||
// CHECK: [[GTID:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[GTID_REF]]
|
||||
// CHECK: call i32 @__kmpc_single(
|
||||
|
||||
// CHECK-DAG: getelementptr inbounds [2 x i32], [2 x i32]* %{{.+}}, i{{[0-9]+}} 0, i{{[0-9]+}} 0
|
||||
// CHECK-DAG: getelementptr inbounds [2 x [[S_FLOAT_TY]]], [2 x [[S_FLOAT_TY]]]* %{{.+}}, i{{[0-9]+}} 0, i{{[0-9]+}} 0
|
||||
|
||||
// CHECK: call void @__kmpc_for_static_init_4(
|
||||
// <Skip loop body>
|
||||
// CHECK: call void @__kmpc_for_static_fini(
|
||||
|
||||
// CHECK-NOT: call void [[S_FLOAT_TY_DESTR]]([[S_FLOAT_TY]]* [[VAR_PRIV]])
|
||||
// CHECK-NOT: call void [[S_FLOAT_TY_DESTR]]([[S_FLOAT_TY]]*
|
||||
// CHECK-DAG: call {{.*}} [[S_FLOAT_TY_DESTR]]([[S_FLOAT_TY]]*
|
||||
// CHECK-DAG: call {{.*}} [[S_FLOAT_TY_DESTR]]([[S_FLOAT_TY]]*
|
||||
|
||||
// CHECK: call void @__kmpc_end_single(
|
||||
|
||||
// CHECK: call void @__kmpc_barrier(%{{.+}}* [[SINGLE_BARRIER_LOC]], i{{[0-9]+}} [[GTID]])
|
||||
// CHECK: call void @__kmpc_barrier(
|
||||
// CHECK: ret void
|
||||
|
||||
//
|
||||
|
|
|
@ -157,6 +157,11 @@ int main() {
|
|||
// CHECK: ret
|
||||
//
|
||||
// CHECK: define internal void [[MAIN_MICROTASK]](i{{[0-9]+}}* noalias [[GTID_ADDR:%.+]], i{{[0-9]+}}* noalias %{{.+}})
|
||||
// CHECK: alloca i{{[0-9]+}},
|
||||
// CHECK: alloca i{{[0-9]+}},
|
||||
// CHECK: alloca i{{[0-9]+}},
|
||||
// CHECK: alloca i{{[0-9]+}},
|
||||
// CHECK: alloca i{{[0-9]+}},
|
||||
// CHECK: [[T_VAR_PRIV:%.+]] = alloca i{{[0-9]+}},
|
||||
// CHECK: [[VEC_PRIV:%.+]] = alloca [2 x i{{[0-9]+}}],
|
||||
// CHECK: [[S_ARR_PRIV:%.+]] = alloca [2 x [[S_FLOAT_TY]]],
|
||||
|
@ -165,7 +170,6 @@ int main() {
|
|||
// CHECK: [[SIVAR_PRIV:%.+]] = alloca i{{[0-9]+}},
|
||||
// CHECK-NOT: alloca [[S_FLOAT_TY]],
|
||||
// CHECK: store i{{[0-9]+}}* [[GTID_ADDR]], i{{[0-9]+}}** [[GTID_ADDR_REF:%.+]]
|
||||
// CHECK: call i32 @__kmpc_single(
|
||||
// CHECK-NOT: [[T_VAR_PRIV]]
|
||||
// CHECK-NOT: [[VEC_PRIV]]
|
||||
// CHECK-NOT: [[SIVAR_PRIV]]
|
||||
|
@ -175,9 +179,13 @@ int main() {
|
|||
// CHECK-NOT: [[T_VAR_PRIV]]
|
||||
// CHECK-NOT: [[VEC_PRIV]]
|
||||
// CHECK: call {{.*}} [[S_FLOAT_TY_DEF_CONSTR]]([[S_FLOAT_TY]]* [[VAR_PRIV]])
|
||||
|
||||
// CHECK: call void @__kmpc_for_static_init_4(
|
||||
// CHECK: call void @__kmpc_for_static_fini(
|
||||
|
||||
// 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: call void @__kmpc_end_single(
|
||||
// CHECK: call void @__kmpc_barrier(
|
||||
// CHECK: ret void
|
||||
|
||||
// CHECK: define {{.*}} i{{[0-9]+}} [[TMAIN_INT]]()
|
||||
|
|
|
@ -23,7 +23,6 @@ struct S {
|
|||
// CHECK-DAG: [[S_FLOAT_TY:%.+]] = type { float }
|
||||
// CHECK-DAG: [[S_INT_TY:%.+]] = type { i{{[0-9]+}} }
|
||||
// CHECK-DAG: [[ATOMIC_REDUCE_BARRIER_LOC:@.+]] = private unnamed_addr constant %{{.+}} { i32 0, i32 18, i32 0, i32 0, i8*
|
||||
// CHECK-DAG: [[SINGLE_BARRIER_LOC:@.+]] = private unnamed_addr constant %{{.+}} { i32 0, i32 322, i32 0, i32 0, i8*
|
||||
// CHECK-DAG: [[REDUCTION_LOC:@.+]] = private unnamed_addr constant %{{.+}} { i32 0, i32 18, i32 0, i32 0, i8*
|
||||
// CHECK-DAG: [[REDUCTION_LOCK:@.+]] = common global [8 x i32] zeroinitializer
|
||||
|
||||
|
@ -195,23 +194,23 @@ int main() {
|
|||
// CHECK: ret
|
||||
//
|
||||
// CHECK: define internal void [[MAIN_MICROTASK]](i{{[0-9]+}}* noalias [[GTID_ADDR:%.+]], i{{[0-9]+}}* noalias %{{.+}},
|
||||
// CHECK-NOT: alloca float,
|
||||
// CHECK-NOT: alloca [[S_FLOAT_TY]],
|
||||
// CHECK-NOT: alloca [[S_FLOAT_TY]],
|
||||
// CHECK-NOT: alloca float,
|
||||
// CHECK: alloca float,
|
||||
// CHECK: alloca [[S_FLOAT_TY]],
|
||||
// CHECK: alloca [[S_FLOAT_TY]],
|
||||
// CHECK: alloca float,
|
||||
|
||||
// CHECK: store i{{[0-9]+}}* [[GTID_ADDR]], i{{[0-9]+}}** [[GTID_ADDR_ADDR:%.+]],
|
||||
|
||||
// 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_single(
|
||||
|
||||
// CHECK-NOT: call {{.*}} [[S_FLOAT_TY_DESTR]]([[S_FLOAT_TY]]* [[VAR_PRIV]])
|
||||
// CHECK-NOT: call {{.*}} [[S_FLOAT_TY_DESTR]]([[S_FLOAT_TY]]*
|
||||
|
||||
// CHECK: call void @__kmpc_end_single(
|
||||
// CHECK: call void @__kmpc_for_static_init_4(
|
||||
// CHECK: call void @__kmpc_for_static_fini(
|
||||
|
||||
// CHECK: call void @__kmpc_barrier(%{{.+}}* [[SINGLE_BARRIER_LOC]], i{{[0-9]+}} [[GTID]])
|
||||
// CHECK: call void @__kmpc_barrier(
|
||||
|
||||
// CHECK: ret void
|
||||
|
||||
|
|
Loading…
Reference in New Issue