/// Call to uint16_t __kmpc_parallel_level(ident_t *loc, kmp_int32
/// global_tid);
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.
"Parameter captured by value with variably modified type");
EscapedParameters.insert(VD);
}
- } else if (VD->getType()->isAnyPointerType() ||
- VD->getType()->isReferenceType())
+ } else if (VD->getType()->isReferenceType())
// Do not globalize variables with reference or pointer type.
return;
if (VD->getType()->isVariablyModifiedType())
return;
if (D->hasAssociatedStmt()) {
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);
+ }
}
}
void VisitCapturedStmt(const CapturedStmt *S) {
RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_parallel_level");
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;
}
RCG(CGF);
} else {
// Check for master and then parallelism:
- // if (is_master) {
+ // if (__kmpc_is_spmd_exec_mode()) {
+ // Serialized execution.
+ // } else if (is_master) {
// Worker call.
// } else if (__kmpc_parallel_level(loc, gtid)) {
// Serialized execution.
// }
CGBuilderTy &Bld = CGF.Builder;
llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".exit");
+ llvm::BasicBlock *SPMDCheckBB = CGF.createBasicBlock(".spmdcheck");
llvm::BasicBlock *MasterCheckBB = CGF.createBasicBlock(".mastercheck");
llvm::BasicBlock *ParallelCheckBB =
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 =
Bld.CreateICmpEQ(getNVPTXThreadID(CGF), getMasterThreadID(CGF));
- Bld.CreateCondBr(IsMaster, MasterCheckBB, ParallelCheckBB);
- CGF.EmitBlock(MasterCheckBB);
+ Bld.CreateCondBr(IsMaster, MasterThenBB, ParallelCheckBB);
+ CGF.EmitBlock(MasterThenBB);
L0ParallelGen(CGF, Action);
CGF.EmitBranch(ExitBB);
// There is no need to emit line number for unconditional branch.
// 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 [[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: br i1