[OPENMP, NVPTX] Add check for SPMD mode in orphaned parallel directives.

If the orphaned directive is executed in SPMD mode, we need to emit the
check for the SPMD mode and run the orphaned parallel directive in
sequential mode.

llvm-svn: 332467
This commit is contained in:
Alexey Bataev 2018-05-16 13:36:30 +00:00
parent 2ba8fd4914
commit 673110d5d5
2 changed files with 44 additions and 6 deletions

View File

@ -96,6 +96,8 @@ enum OpenMPRTLFunctionNVPTX {
/// Call to uint16_t __kmpc_parallel_level(ident_t *loc, kmp_int32 /// Call to uint16_t __kmpc_parallel_level(ident_t *loc, kmp_int32
/// global_tid); /// global_tid);
OMPRTL_NVPTX__kmpc_parallel_level, OMPRTL_NVPTX__kmpc_parallel_level,
/// Call to int8_t __kmpc_is_spmd_exec_mode();
OMPRTL_NVPTX__kmpc_is_spmd_exec_mode,
}; };
/// Pre(post)-action for different OpenMP constructs specialized for NVPTX. /// Pre(post)-action for different OpenMP constructs specialized for NVPTX.
@ -220,8 +222,7 @@ class CheckVarsEscapingDeclContext final
"Parameter captured by value with variably modified type"); "Parameter captured by value with variably modified type");
EscapedParameters.insert(VD); EscapedParameters.insert(VD);
} }
} else if (VD->getType()->isAnyPointerType() || } else if (VD->getType()->isReferenceType())
VD->getType()->isReferenceType())
// Do not globalize variables with reference or pointer type. // Do not globalize variables with reference or pointer type.
return; return;
if (VD->getType()->isVariablyModifiedType()) if (VD->getType()->isVariablyModifiedType())
@ -317,10 +318,20 @@ public:
return; return;
if (D->hasAssociatedStmt()) { if (D->hasAssociatedStmt()) {
if (const auto *S = if (const auto *S =
dyn_cast_or_null<CapturedStmt>(D->getAssociatedStmt())) dyn_cast_or_null<CapturedStmt>(D->getAssociatedStmt())) {
// Do not analyze directives that do not actually require capturing,
// like `omp for` or `omp simd` directives.
llvm::SmallVector<OpenMPDirectiveKind, 4> CaptureRegions;
getOpenMPCaptureRegions(CaptureRegions, D->getDirectiveKind());
if (CaptureRegions.size() == 1 &&
CaptureRegions.back() == OMPD_unknown) {
VisitStmt(S->getCapturedStmt());
return;
}
VisitOpenMPCapturedStmt(S); VisitOpenMPCapturedStmt(S);
} }
} }
}
void VisitCapturedStmt(const CapturedStmt *S) { void VisitCapturedStmt(const CapturedStmt *S) {
if (!S) if (!S)
return; return;
@ -1411,6 +1422,12 @@ CGOpenMPRuntimeNVPTX::createNVPTXRuntimeFunction(unsigned Function) {
RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_parallel_level"); RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_parallel_level");
break; break;
} }
case OMPRTL_NVPTX__kmpc_is_spmd_exec_mode: {
// Build int8_t __kmpc_is_spmd_exec_mode();
auto *FnTy = llvm::FunctionType::get(CGM.Int8Ty, /*isVarArg=*/false);
RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_is_spmd_exec_mode");
break;
}
} }
return RTLFn; return RTLFn;
} }
@ -1828,7 +1845,9 @@ void CGOpenMPRuntimeNVPTX::emitNonSPMDParallelCall(
RCG(CGF); RCG(CGF);
} else { } else {
// Check for master and then parallelism: // Check for master and then parallelism:
// if (is_master) { // if (__kmpc_is_spmd_exec_mode()) {
// Serialized execution.
// } else if (is_master) {
// Worker call. // Worker call.
// } else if (__kmpc_parallel_level(loc, gtid)) { // } else if (__kmpc_parallel_level(loc, gtid)) {
// Serialized execution. // Serialized execution.
@ -1837,13 +1856,22 @@ void CGOpenMPRuntimeNVPTX::emitNonSPMDParallelCall(
// } // }
CGBuilderTy &Bld = CGF.Builder; CGBuilderTy &Bld = CGF.Builder;
llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".exit"); llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".exit");
llvm::BasicBlock *SPMDCheckBB = CGF.createBasicBlock(".spmdcheck");
llvm::BasicBlock *MasterCheckBB = CGF.createBasicBlock(".mastercheck"); llvm::BasicBlock *MasterCheckBB = CGF.createBasicBlock(".mastercheck");
llvm::BasicBlock *ParallelCheckBB = llvm::BasicBlock *ParallelCheckBB =
CGF.createBasicBlock(".parallelcheck"); CGF.createBasicBlock(".parallelcheck");
llvm::Value *IsSPMD = Bld.CreateIsNotNull(CGF.EmitNounwindRuntimeCall(
createNVPTXRuntimeFunction(OMPRTL_NVPTX__kmpc_is_spmd_exec_mode)));
Bld.CreateCondBr(IsSPMD, SPMDCheckBB, MasterCheckBB);
CGF.EmitBlock(SPMDCheckBB);
SeqGen(CGF, Action);
CGF.EmitBranch(ExitBB);
CGF.EmitBlock(MasterCheckBB);
llvm::BasicBlock *MasterThenBB = CGF.createBasicBlock("master.then");
llvm::Value *IsMaster = llvm::Value *IsMaster =
Bld.CreateICmpEQ(getNVPTXThreadID(CGF), getMasterThreadID(CGF)); Bld.CreateICmpEQ(getNVPTXThreadID(CGF), getMasterThreadID(CGF));
Bld.CreateCondBr(IsMaster, MasterCheckBB, ParallelCheckBB); Bld.CreateCondBr(IsMaster, MasterThenBB, ParallelCheckBB);
CGF.EmitBlock(MasterCheckBB); CGF.EmitBlock(MasterThenBB);
L0ParallelGen(CGF, Action); L0ParallelGen(CGF, Action);
CGF.EmitBranch(ExitBB); CGF.EmitBranch(ExitBB);
// There is no need to emit line number for unconditional branch. // There is no need to emit line number for unconditional branch.

View File

@ -561,6 +561,16 @@ int baz(int f, double &a) {
// CHECK: [[F_PTR:%.+]] = getelementptr inbounds %struct._globalized_locals_ty, %struct._globalized_locals_ty* [[REC_ADDR]], i32 0, i32 0 // CHECK: [[F_PTR:%.+]] = getelementptr inbounds %struct._globalized_locals_ty, %struct._globalized_locals_ty* [[REC_ADDR]], i32 0, i32 0
// CHECK: store i32 %{{.+}}, i32* [[F_PTR]], // CHECK: store i32 %{{.+}}, i32* [[F_PTR]],
// CHECK: store i32 [[GTID]], i32* [[GTID_ADDR]], // CHECK: store i32 [[GTID]], i32* [[GTID_ADDR]],
// CHECK: [[RES:%.+]] = call i8 @__kmpc_is_spmd_exec_mode()
// CHECK: icmp ne i8 [[RES]], 0
// CHECK: br i1
// CHECK: call void @__kmpc_serialized_parallel(%struct.ident_t* @{{.+}}, i32 [[GTID]])
// CHECK: call void [[OUTLINED:@.+]](i32* [[GTID_ADDR]], i32* [[ZERO_ADDR]], i32* [[F_PTR]], double* %{{.+}})
// CHECK: call void @__kmpc_end_serialized_parallel(%struct.ident_t* @{{.+}}, i32 [[GTID]])
// CHECK: br label
// CHECK: icmp eq i32 // CHECK: icmp eq i32
// CHECK: br i1 // CHECK: br i1