;
46using namespaceCodeGen;
47using namespacellvm::omp;
51classCGOpenMPRegionInfo :
publicCodeGenFunction::CGCapturedStmtInfo {
54 enumCGOpenMPRegionKind {
57ParallelOutlinedRegion,
68 constCGOpenMPRegionKind RegionKind,
71: CGCapturedStmtInfo(CS,
CR_OpenMP), RegionKind(RegionKind),
72CodeGen(CodeGen),
Kind(
Kind), HasCancel(HasCancel) {}
74CGOpenMPRegionInfo(
constCGOpenMPRegionKind RegionKind,
77: CGCapturedStmtInfo(
CR_OpenMP), RegionKind(RegionKind), CodeGen(CodeGen),
78 Kind(
Kind), HasCancel(HasCancel) {}
82 virtual const VarDecl*getThreadIDVariable()
const= 0;
93CGOpenMPRegionKind getRegionKind()
const{
returnRegionKind; }
97 boolhasCancel()
const{
returnHasCancel; }
99 static boolclassof(
constCGCapturedStmtInfo *Info) {
103~CGOpenMPRegionInfo()
override=
default;
106CGOpenMPRegionKind RegionKind;
113classCGOpenMPOutlinedRegionInfo final :
publicCGOpenMPRegionInfo {
118StringRef HelperName)
119: CGOpenMPRegionInfo(CS, ParallelOutlinedRegion, CodeGen,
Kind,
121ThreadIDVar(ThreadIDVar), HelperName(HelperName) {
122assert(ThreadIDVar !=
nullptr&&
"No ThreadID in OpenMP region.");
127 const VarDecl*getThreadIDVariable()
const override{
returnThreadIDVar; }
130StringRef getHelperName()
const override{
returnHelperName; }
132 static boolclassof(
constCGCapturedStmtInfo *Info) {
133 returnCGOpenMPRegionInfo::classof(Info) &&
134cast<CGOpenMPRegionInfo>(Info)->getRegionKind() ==
135ParallelOutlinedRegion;
142StringRef HelperName;
146classCGOpenMPTaskOutlinedRegionInfo final :
publicCGOpenMPRegionInfo {
152llvm::SwitchInst *UntiedSwitch =
nullptr;
155UntiedTaskActionTy(
boolTied,
const VarDecl*PartIDVar,
157: Untied(!Tied), PartIDVar(PartIDVar), UntiedCodeGen(UntiedCodeGen) {}
167UntiedSwitch = CGF.
Builder.CreateSwitch(Res, DoneBB);
171UntiedSwitch->addCase(CGF.
Builder.getInt32(0),
172CGF.
Builder.GetInsertBlock());
173emitUntiedSwitch(CGF);
184CodeGenFunction::JumpDest CurPoint =
188UntiedSwitch->addCase(CGF.
Builder.getInt32(UntiedSwitch->getNumCases()),
189CGF.
Builder.GetInsertBlock());
194 unsignedgetNumberOfParts()
const{
returnUntiedSwitch->getNumCases(); }
200 constUntiedTaskActionTy &Action)
201: CGOpenMPRegionInfo(CS, TaskOutlinedRegion, CodeGen,
Kind, HasCancel),
202ThreadIDVar(ThreadIDVar), Action(Action) {
203assert(ThreadIDVar !=
nullptr&&
"No ThreadID in OpenMP region.");
208 const VarDecl*getThreadIDVariable()
const override{
returnThreadIDVar; }
214StringRef getHelperName()
const override{
return ".omp_outlined."; }
217Action.emitUntiedSwitch(CGF);
220 static boolclassof(
constCGCapturedStmtInfo *Info) {
221 returnCGOpenMPRegionInfo::classof(Info) &&
222cast<CGOpenMPRegionInfo>(Info)->getRegionKind() ==
231 constUntiedTaskActionTy &Action;
236classCGOpenMPInlinedRegionInfo :
publicCGOpenMPRegionInfo {
238CGOpenMPInlinedRegionInfo(CodeGenFunction::CGCapturedStmtInfo *OldCSI,
241: CGOpenMPRegionInfo(InlinedRegion, CodeGen,
Kind, HasCancel),
243OuterRegionInfo(dyn_cast_or_null<CGOpenMPRegionInfo>(OldCSI)) {}
246llvm::Value *getContextValue()
const override{
248 returnOuterRegionInfo->getContextValue();
249llvm_unreachable(
"No context value for inlined OpenMP region");
252 voidsetContextValue(llvm::Value *
V)
override{
253 if(OuterRegionInfo) {
254OuterRegionInfo->setContextValue(
V);
257llvm_unreachable(
"No context value for inlined OpenMP region");
263 returnOuterRegionInfo->lookup(VD);
269 FieldDecl*getThisFieldDecl()
const override{
271 returnOuterRegionInfo->getThisFieldDecl();
277 const VarDecl*getThreadIDVariable()
const override{
279 returnOuterRegionInfo->getThreadIDVariable();
286 returnOuterRegionInfo->getThreadIDVariableLValue(CGF);
287llvm_unreachable(
"No LValue for inlined OpenMP construct");
291StringRef getHelperName()
const override{
292 if(
auto*OuterRegionInfo = getOldCSI())
293 returnOuterRegionInfo->getHelperName();
294llvm_unreachable(
"No helper name for inlined OpenMP construct");
299OuterRegionInfo->emitUntiedSwitch(CGF);
302CodeGenFunction::CGCapturedStmtInfo *getOldCSI()
const{
returnOldCSI; }
304 static boolclassof(
constCGCapturedStmtInfo *Info) {
305 returnCGOpenMPRegionInfo::classof(Info) &&
306cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == InlinedRegion;
309~CGOpenMPInlinedRegionInfo()
override=
default;
313CodeGenFunction::CGCapturedStmtInfo *OldCSI;
314CGOpenMPRegionInfo *OuterRegionInfo;
322classCGOpenMPTargetRegionInfo final :
publicCGOpenMPRegionInfo {
326: CGOpenMPRegionInfo(CS, TargetRegion, CodeGen, OMPD_target,
328HelperName(HelperName) {}
332 const VarDecl*getThreadIDVariable()
const override{
return nullptr; }
335StringRef getHelperName()
const override{
returnHelperName; }
337 static boolclassof(
constCGCapturedStmtInfo *Info) {
338 returnCGOpenMPRegionInfo::classof(Info) &&
339cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == TargetRegion;
343StringRef HelperName;
347llvm_unreachable(
"No codegen for expressions");
351classCGOpenMPInnerExprInfo final :
publicCGOpenMPInlinedRegionInfo {
354: CGOpenMPInlinedRegionInfo(CGF.CapturedStmtInfo, EmptyCodeGen,
361 for(
const auto&
C: CS.
captures()) {
362 if(!
C.capturesVariable() && !
C.capturesVariableByCopy())
365 const VarDecl*VD =
C.getCapturedVar();
375(void)PrivScope.Privatize();
380 if(
const FieldDecl*FD = CGOpenMPInlinedRegionInfo::lookup(VD))
387llvm_unreachable(
"No body for expressions");
392 const VarDecl*getThreadIDVariable()
const override{
393llvm_unreachable(
"No thread id for expressions");
397StringRef getHelperName()
const override{
398llvm_unreachable(
"No helper name for expressions");
401 static boolclassof(
constCGCapturedStmtInfo *Info) {
return false; }
405CodeGenFunction::OMPPrivateScope PrivScope;
409classInlinedOpenMPRegionRAII {
411llvm::DenseMap<const ValueDecl *, FieldDecl *> LambdaCaptureFields;
412 FieldDecl*LambdaThisCaptureField =
nullptr;
414 boolNoInheritance =
false;
423 boolNoInheritance =
true)
424: CGF(CGF), NoInheritance(NoInheritance) {
437~InlinedOpenMPRegionRAII() {
454enumOpenMPLocationFlags :
unsigned{
456OMP_IDENT_IMD = 0x01,
458OMP_IDENT_KMPC = 0x02,
460OMP_ATOMIC_REDUCE = 0x10,
462OMP_IDENT_BARRIER_EXPL = 0x20,
464OMP_IDENT_BARRIER_IMPL = 0x40,
466OMP_IDENT_BARRIER_IMPL_FOR = 0x40,
468OMP_IDENT_BARRIER_IMPL_SECTIONS = 0xC0,
470OMP_IDENT_BARRIER_IMPL_SINGLE = 0x140,
472OMP_IDENT_WORK_LOOP = 0x200,
474OMP_IDENT_WORK_SECTIONS = 0x400,
476OMP_IDENT_WORK_DISTRIBUTE = 0x800,
506enumIdentFieldIndex {
508IdentField_Reserved_1,
512IdentField_Reserved_2,
514IdentField_Reserved_3,
523enumOpenMPSchedType {
526OMP_sch_static_chunked = 33,
528OMP_sch_dynamic_chunked = 35,
529OMP_sch_guided_chunked = 36,
530OMP_sch_runtime = 37,
533OMP_sch_static_balanced_chunked = 45,
536OMP_ord_static_chunked = 65,
538OMP_ord_dynamic_chunked = 67,
539OMP_ord_guided_chunked = 68,
540OMP_ord_runtime = 69,
542OMP_sch_default = OMP_sch_static,
544OMP_dist_sch_static_chunked = 91,
545OMP_dist_sch_static = 92,
548OMP_sch_modifier_monotonic = (1 << 29),
550OMP_sch_modifier_nonmonotonic = (1 << 30),
573Callback(CodeGen, CGF, *PrePostAction);
576Callback(CodeGen, CGF, Action);
584 if(
const auto*CE = dyn_cast<CallExpr>(ReductionOp))
585 if(
const auto*OVE = dyn_cast<OpaqueValueExpr>(CE->getCallee()))
586 if(
const auto*DRE =
587dyn_cast<DeclRefExpr>(OVE->getSourceExpr()->IgnoreImpCasts()))
588 if(
const auto*DRD = dyn_cast<OMPDeclareReductionDecl>(DRE->getDecl()))
599std::pair<llvm::Function *, llvm::Function *>
Reduction=
601 const auto*CE = cast<CallExpr>(InitOp);
602 const auto*OVE = cast<OpaqueValueExpr>(CE->getCallee());
606cast<DeclRefExpr>(cast<UnaryOperator>(LHS)->getSubExpr());
608cast<DeclRefExpr>(cast<UnaryOperator>(RHS)->getSubExpr());
609CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
610PrivateScope.addPrivate(cast<VarDecl>(LHSDRE->getDecl()),
Private);
611PrivateScope.addPrivate(cast<VarDecl>(RHSDRE->getDecl()), Original);
612(void)PrivateScope.Privatize();
614CodeGenFunction::OpaqueValueMapping Map(CGF, OVE,
Func);
619 auto*GV =
newllvm::GlobalVariable(
621llvm::GlobalValue::PrivateLinkage,
Init, Name);
634CodeGenFunction::OpaqueValueMapping OpaqueMap(CGF, &OVE, LV);
641CodeGenFunction::OpaqueValueMapping OpaqueMap(CGF, &OVE, InitRVal);
662llvm::Value *NumElements = CGF.
emitArrayLength(ArrayTy, ElementTy, DestAddr);
666llvm::Value *SrcBegin =
nullptr;
668SrcBegin = SrcAddr.emitRawPointer(CGF);
671llvm::Value *DestEnd =
676llvm::Value *IsEmpty =
677CGF.
Builder.CreateICmpEQ(DestBegin, DestEnd,
"omp.arrayinit.isempty");
678CGF.
Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
681llvm::BasicBlock *EntryBB = CGF.
Builder.GetInsertBlock();
686llvm::PHINode *SrcElementPHI =
nullptr;
689SrcElementPHI = CGF.
Builder.CreatePHI(SrcBegin->getType(), 2,
690 "omp.arraycpy.srcElementPast");
691SrcElementPHI->addIncoming(SrcBegin, EntryBB);
693 Address(SrcElementPHI, SrcAddr.getElementType(),
694SrcAddr.getAlignment().alignmentOfArrayElement(ElementSize));
696llvm::PHINode *DestElementPHI = CGF.
Builder.CreatePHI(
697DestBegin->getType(), 2,
"omp.arraycpy.destElementPast");
698DestElementPHI->addIncoming(DestBegin, EntryBB);
705CodeGenFunction::RunCleanupsScope InitScope(CGF);
706 if(EmitDeclareReductionInit) {
708SrcElementCurrent, ElementTy);
716llvm::Value *SrcElementNext = CGF.
Builder.CreateConstGEP1_32(
717SrcAddr.getElementType(), SrcElementPHI,
1,
718 "omp.arraycpy.dest.element");
719SrcElementPHI->addIncoming(SrcElementNext, CGF.
Builder.GetInsertBlock());
723llvm::Value *DestElementNext = CGF.
Builder.CreateConstGEP1_32(
725 "omp.arraycpy.dest.element");
728CGF.
Builder.CreateICmpEQ(DestElementNext, DestEnd,
"omp.arraycpy.done");
729CGF.
Builder.CreateCondBr(Done, DoneBB, BodyBB);
730DestElementPHI->addIncoming(DestElementNext, CGF.
Builder.GetInsertBlock());
742 if(
const auto*OASE = dyn_cast<ArraySectionExpr>(
E))
747voidReductionCodeGen::emitAggregateInitialization(
753 const auto*PrivateVD =
754cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].
Private)->getDecl());
755 boolEmitDeclareReductionInit =
758EmitDeclareReductionInit,
759EmitDeclareReductionInit ? ClausesData[N].ReductionOp
760: PrivateVD->getInit(),
768ClausesData.reserve(Shareds.size());
769SharedAddresses.reserve(Shareds.size());
770Sizes.reserve(Shareds.size());
771BaseDecls.reserve(Shareds.size());
772 const auto*IOrig = Origs.begin();
773 const auto*IPriv = Privates.begin();
774 const auto*IRed = ReductionOps.begin();
775 for(
const Expr*Ref : Shareds) {
776ClausesData.emplace_back(Ref, *IOrig, *IPriv, *IRed);
777std::advance(IOrig, 1);
778std::advance(IPriv, 1);
779std::advance(IRed, 1);
784assert(SharedAddresses.size() == N && OrigAddresses.size() == N &&
785 "Number of generated lvalues must be exactly N.");
786 LValue First= emitSharedLValue(CGF, ClausesData[N].Shared);
787 LValueSecond = emitSharedLValueUB(CGF, ClausesData[N].Shared);
788SharedAddresses.emplace_back(
First, Second);
789 if(ClausesData[N].Shared == ClausesData[N].Ref) {
790OrigAddresses.emplace_back(
First, Second);
792 LValue First= emitSharedLValue(CGF, ClausesData[N].Ref);
793 LValueSecond = emitSharedLValueUB(CGF, ClausesData[N].Ref);
794OrigAddresses.emplace_back(
First, Second);
800 boolAsArraySection = isa<ArraySectionExpr>(ClausesData[N].Ref);
803CGF.
getTypeSize(OrigAddresses[N].first.getType().getNonReferenceType()),
808llvm::Value *SizeInChars;
809 auto*ElemType = OrigAddresses[N].first.getAddress().getElementType();
810 auto*ElemSizeOf = llvm::ConstantExpr::getSizeOf(ElemType);
811 if(AsArraySection) {
812Size = CGF.
Builder.CreatePtrDiff(ElemType,
813OrigAddresses[N].second.getPointer(CGF),
814OrigAddresses[N].first.getPointer(CGF));
815Size = CGF.
Builder.CreateNUWAdd(
816Size, llvm::ConstantInt::get(Size->getType(),
1));
817SizeInChars = CGF.
Builder.CreateNUWMul(Size, ElemSizeOf);
820CGF.
getTypeSize(OrigAddresses[N].first.getType().getNonReferenceType());
821Size = CGF.
Builder.CreateExactUDiv(SizeInChars, ElemSizeOf);
823Sizes.emplace_back(SizeInChars, Size);
826cast<OpaqueValueExpr>(
836assert(!Size && !Sizes[N].second &&
837 "Size should be nullptr for non-variably modified reduction " 843cast<OpaqueValueExpr>(
852assert(SharedAddresses.size() > N &&
"No variable was generated");
853 const auto*PrivateVD =
854cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].
Private)->getDecl());
859(void)DefaultInit(CGF);
860emitAggregateInitialization(CGF, N, PrivateAddr, SharedAddr, DRD);
861}
else if(DRD && (DRD->
getInitializer() || !PrivateVD->hasInit())) {
862(void)DefaultInit(CGF);
863 QualTypeSharedType = SharedAddresses[N].first.getType();
865PrivateAddr, SharedAddr, SharedType);
866}
else if(!DefaultInit(CGF) && PrivateVD->hasInit() &&
869PrivateVD->
getType().getQualifiers(),
887CGF.
pushDestroy(DTorKind, PrivateAddr, PrivateType);
911 AddressOriginalBaseAddress, llvm::Value *Addr) {
935Addr, OriginalBaseAddress.
getType());
940 const VarDecl*OrigVD =
nullptr;
941 if(
const auto*OASE = dyn_cast<ArraySectionExpr>(Ref)) {
942 const Expr*
Base= OASE->getBase()->IgnoreParenImpCasts();
943 while(
const auto*TempOASE = dyn_cast<ArraySectionExpr>(
Base))
944 Base= TempOASE->getBase()->IgnoreParenImpCasts();
945 while(
const auto*TempASE = dyn_cast<ArraySubscriptExpr>(
Base))
946 Base= TempASE->getBase()->IgnoreParenImpCasts();
947DE = cast<DeclRefExpr>(
Base);
948OrigVD = cast<VarDecl>(DE->
getDecl());
949}
else if(
const auto*ASE = dyn_cast<ArraySubscriptExpr>(Ref)) {
950 const Expr*
Base= ASE->getBase()->IgnoreParenImpCasts();
951 while(
const auto*TempASE = dyn_cast<ArraySubscriptExpr>(
Base))
952 Base= TempASE->getBase()->IgnoreParenImpCasts();
953DE = cast<DeclRefExpr>(
Base);
954OrigVD = cast<VarDecl>(DE->
getDecl());
963BaseDecls.emplace_back(OrigVD);
966 loadToBegin(CGF, OrigVD->getType(), SharedAddresses[N].first.getType(),
968 AddressSharedAddr = SharedAddresses[N].first.getAddress();
969llvm::Value *Adjustment = CGF.
Builder.CreatePtrDiff(
972llvm::Value *PrivatePointer =
978SharedAddresses[N].first.getType(),
981BaseDecls.emplace_back(
982cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Ref)->getDecl()));
995getThreadIDVariable()->getType()->castAs<PointerType>());
1013LValueCGOpenMPTaskOutlinedRegionInfo::getThreadIDVariableLValue(
1016getThreadIDVariable()->getType(),
1032: CGM(CGM), OMPBuilder(CGM.getModule()) {
1034llvm::OpenMPIRBuilderConfig Config(
1049 OMPBuilder.Config.setHasRequiresUnifiedSharedMemory(
true);
1057 if(!
Data.getValue().pointsToAliveValue())
1059 auto*GV = dyn_cast<llvm::GlobalVariable>(
Data.getValue());
1062 if(!GV->isDeclaration() || GV->getNumUses() > 0)
1064GV->eraseFromParent();
1069 return OMPBuilder.createPlatformSpecificName(Parts);
1072staticllvm::Function *
1074 const Expr*CombinerInitializer,
const VarDecl*In,
1075 const VarDecl*Out,
boolIsCombiner) {
1078 QualTypePtrTy =
C.getPointerType(Ty).withRestrict();
1084Args.push_back(&OmpOutParm);
1085Args.push_back(&OmpInParm);
1090{IsCombiner ?
"omp_combiner":
"omp_initializer",
""});
1091 auto*Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
1095Fn->removeFnAttr(llvm::Attribute::NoInline);
1096Fn->removeFnAttr(llvm::Attribute::OptimizeNone);
1097Fn->addFnAttr(llvm::Attribute::AlwaysInline);
1103Out->getLocation());
1104CodeGenFunction::OMPPrivateScope
Scope(CGF);
1113(void)
Scope.Privatize();
1114 if(!IsCombiner && Out->hasInit() &&
1117Out->getType().getQualifiers(),
1120 if(CombinerInitializer)
1122 Scope.ForceCleanup();
1132 CGM,
D->getType(),
D->getCombiner(),
1133cast<VarDecl>(cast<DeclRefExpr>(
D->getCombinerIn())->getDecl()),
1134cast<VarDecl>(cast<DeclRefExpr>(
D->getCombinerOut())->getDecl()),
1137 if(
const Expr*
Init=
D->getInitializer()) {
1139 CGM,
D->getType(),
1142cast<VarDecl>(cast<DeclRefExpr>(
D->getInitOrig())->getDecl()),
1143cast<VarDecl>(cast<DeclRefExpr>(
D->getInitPriv())->getDecl()),
1151std::pair<llvm::Function *, llvm::Function *>
1163structPushAndPopStackRAII {
1164PushAndPopStackRAII(llvm::OpenMPIRBuilder *OMPBuilder,
CodeGenFunction&CGF,
1165 boolHasCancel, llvm::omp::Directive
Kind)
1166: OMPBuilder(OMPBuilder) {
1182 autoFiniCB = [&CGF](llvm::OpenMPIRBuilder::InsertPointTy IP) {
1183assert(IP.getBlock()->end() == IP.getPoint() &&
1184 "Clang CG should cause non-terminated block!");
1185CGBuilderTy::InsertPointGuard IPG(CGF.
Builder);
1190 returnllvm::Error::success();
1195llvm::OpenMPIRBuilder::FinalizationInfo FI({FiniCB,
Kind, HasCancel});
1196OMPBuilder->pushFinalizationCB(std::move(FI));
1198~PushAndPopStackRAII() {
1200OMPBuilder->popFinalizationCB();
1202llvm::OpenMPIRBuilder *OMPBuilder;
1211 "thread id variable must be of type kmp_int32 *");
1213 boolHasCancel =
false;
1214 if(
const auto*OPD = dyn_cast<OMPParallelDirective>(&
D))
1215HasCancel = OPD->hasCancel();
1216 else if(
const auto*OPD = dyn_cast<OMPTargetParallelDirective>(&
D))
1217HasCancel = OPD->hasCancel();
1218 else if(
const auto*OPSD = dyn_cast<OMPParallelSectionsDirective>(&
D))
1219HasCancel = OPSD->hasCancel();
1220 else if(
const auto*OPFD = dyn_cast<OMPParallelForDirective>(&
D))
1221HasCancel = OPFD->hasCancel();
1222 else if(
const auto*OPFD = dyn_cast<OMPTargetParallelForDirective>(&
D))
1223HasCancel = OPFD->hasCancel();
1224 else if(
const auto*OPFD = dyn_cast<OMPDistributeParallelForDirective>(&
D))
1225HasCancel = OPFD->hasCancel();
1226 else if(
const auto*OPFD =
1227dyn_cast<OMPTeamsDistributeParallelForDirective>(&
D))
1228HasCancel = OPFD->hasCancel();
1229 else if(
const auto*OPFD =
1230dyn_cast<OMPTargetTeamsDistributeParallelForDirective>(&
D))
1231HasCancel = OPFD->hasCancel();
1236PushAndPopStackRAII PSR(&OMPBuilder, CGF, HasCancel, InnermostKind);
1237CGOpenMPOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen, InnermostKind,
1238HasCancel, OutlinedHelperName);
1239CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
1244std::string Suffix =
getName({
"omp_outlined"});
1245 return(Name + Suffix).str();
1253std::string Suffix =
getName({
"omp",
"reduction",
"reduction_func"});
1254 return(Name + Suffix).str();
1281 boolTied,
unsigned&NumberOfParts) {
1286llvm::Value *TaskArgs[] = {
1288CGF.EmitLoadOfPointerLValue(CGF.GetAddrOfLocalVar(TaskTVar),
1291CGF.EmitRuntimeCall(
OMPBuilder.getOrCreateRuntimeFunction(
1295CGOpenMPTaskOutlinedRegionInfo::UntiedTaskActionTy Action(Tied, PartIDVar,
1299 "thread id variable must be of type kmp_int32 for tasks");
1304 boolHasCancel =
false;
1305 if(
const auto*TD = dyn_cast<OMPTaskDirective>(&
D))
1306HasCancel = TD->hasCancel();
1307 else if(
const auto*TD = dyn_cast<OMPTaskLoopDirective>(&
D))
1308HasCancel = TD->hasCancel();
1309 else if(
const auto*TD = dyn_cast<OMPMasterTaskLoopDirective>(&
D))
1310HasCancel = TD->hasCancel();
1311 else if(
const auto*TD = dyn_cast<OMPParallelMasterTaskLoopDirective>(&
D))
1312HasCancel = TD->hasCancel();
1315CGOpenMPTaskOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen,
1316InnermostKind, HasCancel, Action);
1318llvm::Function *Res = CGF.GenerateCapturedStmtFunction(*CS);
1320NumberOfParts = Action.getNumberOfParts();
1325 boolAtCurrentPoint) {
1327assert(!Elem.ServiceInsertPt &&
"Insert point is set already.");
1329llvm::Value *Undef = llvm::UndefValue::get(CGF.
Int32Ty);
1330 if(AtCurrentPoint) {
1331Elem.ServiceInsertPt =
newllvm::BitCastInst(Undef, CGF.
Int32Ty,
"svcpt",
1332CGF.
Builder.GetInsertBlock());
1334Elem.ServiceInsertPt =
newllvm::BitCastInst(Undef, CGF.
Int32Ty,
"svcpt");
1335Elem.ServiceInsertPt->insertAfter(CGF.
AllocaInsertPt->getIterator());
1341 if(Elem.ServiceInsertPt) {
1342llvm::Instruction *Ptr = Elem.ServiceInsertPt;
1343Elem.ServiceInsertPt =
nullptr;
1344Ptr->eraseFromParent();
1351llvm::raw_svector_ostream OS(Buffer);
1355 if(
const auto*FD = dyn_cast_or_null<FunctionDecl>(CGF.
CurFuncDecl))
1356OS << FD->getQualifiedNameAsString();
1363 unsignedFlags,
boolEmitLoc) {
1364uint32_t SrcLocStrSize;
1365llvm::Constant *SrcLocStr;
1367llvm::codegenoptions::NoDebugInfo) ||
1369SrcLocStr =
OMPBuilder.getOrCreateDefaultSrcLocStr(SrcLocStrSize);
1371std::string FunctionName;
1372 if(
const auto*FD = dyn_cast_or_null<FunctionDecl>(CGF.
CurFuncDecl))
1373FunctionName = FD->getQualifiedNameAsString();
1383SrcLocStr, SrcLocStrSize, llvm::omp::IdentFlag(Flags), Reserved2Flags);
1388assert(CGF.
CurFn&&
"No function in current CodeGenFunction.");
1394uint32_t SrcLocStrSize;
1395 auto*SrcLocStr =
OMPBuilder.getOrCreateSrcLocStr(
1398 OMPBuilder.getOrCreateIdent(SrcLocStr, SrcLocStrSize));
1401llvm::Value *ThreadID =
nullptr;
1406ThreadID = I->second.ThreadID;
1407 if(ThreadID !=
nullptr)
1411 if(
auto*OMPRegionInfo =
1413 if(OMPRegionInfo->getThreadIDVariable()) {
1415 LValueLVal = OMPRegionInfo->getThreadIDVariableLValue(CGF);
1419CGF.
Builder.GetInsertBlock() == TopBlock ||
1420!isa<llvm::Instruction>(LVal.
getPointer(CGF)) ||
1421cast<llvm::Instruction>(LVal.
getPointer(CGF))->getParent() ==
1423cast<llvm::Instruction>(LVal.
getPointer(CGF))->getParent() ==
1424CGF.
Builder.GetInsertBlock()) {
1428 if(CGF.
Builder.GetInsertBlock() == TopBlock)
1440 if(!Elem.ServiceInsertPt)
1442CGBuilderTy::InsertPointGuard IPG(CGF.
Builder);
1443CGF.
Builder.SetInsertPoint(Elem.ServiceInsertPt);
1447OMPRTL___kmpc_global_thread_num),
1450Elem.ThreadID =
Call;
1455assert(CGF.
CurFn&&
"No function in current CodeGenFunction.");
1467 for(
const auto*
D: I->second)
1482llvm::Type *MicroParams[] = {llvm::PointerType::getUnqual(
CGM.
Int32Ty),
1483llvm::PointerType::getUnqual(
CGM.
Int32Ty)};
1489staticllvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseKind
1491std::optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
1492OMPDeclareTargetDeclAttr::getDeviceType(VD);
1494 returnllvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseNone;
1496 switch((
int)*DevTy) {
1497 caseOMPDeclareTargetDeclAttr::DT_Host:
1498 returnllvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseHost;
1500 caseOMPDeclareTargetDeclAttr::DT_NoHost:
1501 returnllvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseNoHost;
1503 caseOMPDeclareTargetDeclAttr::DT_Any:
1504 returnllvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseAny;
1507 returnllvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseNone;
1512staticllvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryKind
1514std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> MapType =
1515OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
1517 returnllvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryNone;
1518 switch((
int)*MapType) {
1519 caseOMPDeclareTargetDeclAttr::MapTypeTy::MT_To:
1520 returnllvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryTo;
1522 caseOMPDeclareTargetDeclAttr::MapTypeTy::MT_Enter:
1523 returnllvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryEnter;
1525 caseOMPDeclareTargetDeclAttr::MapTypeTy::MT_Link:
1526 returnllvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryLink;
1529 returnllvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryNone;
1538 autoFileInfoCallBack = [&]() {
1542llvm::sys::fs::UniqueID ID;
1543 if(llvm::sys::fs::getUniqueID(PLoc.
getFilename(), ID)) {
1544PLoc =
SM.getPresumedLoc(BeginLoc,
false);
1550 returnOMPBuilder.getTargetEntryUniqueInfo(FileInfoCallBack, ParentName);
1556 autoLinkageForVariable = [&VD,
this]() {
1560std::vector<llvm::GlobalVariable *> GeneratedRefs;
1564llvm::Constant *addr =
OMPBuilder.getAddrOfDeclareTargetVar(
1572LinkageForVariable);
1584std::string Suffix =
getName({
"cache",
""});
1585 return OMPBuilder.getOrCreateInternalVariable(
1598llvm::Value *Args[] = {
1606 CGM.
getModule(), OMPRTL___kmpc_threadprivate_cached),
1622llvm::Value *Args[] = {
1625Ctor, CopyCtor, Dtor};
1628 CGM.
getModule(), OMPRTL___kmpc_threadprivate_register),
1643llvm::Value *Ctor =
nullptr, *CopyCtor =
nullptr, *Dtor =
nullptr;
1653Args.push_back(&Dst);
1658std::string Name =
getName({
"__kmpc_global_ctor_",
""});
1659llvm::Function *Fn =
1685Args.push_back(&Dst);
1690std::string Name =
getName({
"__kmpc_global_dtor_",
""});
1691llvm::Function *Fn =
1716 if(Ctor ==
nullptr) {
1719 if(Dtor ==
nullptr) {
1723 auto*InitFunctionTy =
1724llvm::FunctionType::get(
CGM.
VoidTy,
false);
1725std::string Name =
getName({
"__omp_threadprivate_init_",
""});
1735 returnInitFunction;
1743llvm::GlobalValue *GV) {
1744std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr =
1745OMPDeclareTargetDeclAttr::getActiveAttr(FD);
1748 if(!ActiveAttr || !(*ActiveAttr)->getIndirect())
1755 OMPBuilder.OffloadInfoManager.getTargetRegionEntryFnName(Name, EntryInfo);
1761llvm::GlobalValue *Addr = GV;
1763Addr =
newllvm::GlobalVariable(
1765 true, llvm::GlobalValue::ExternalLinkage, GV, Name,
1766 nullptr, llvm::GlobalValue::NotThreadLocal,
1767 CGM.
getModule().getDataLayout().getDefaultGlobalsAddressSpace());
1768Addr->setVisibility(llvm::GlobalValue::ProtectedVisibility);
1771 OMPBuilder.OffloadInfoManager.registerDeviceGlobalVarEntryInfo(
1773llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryIndirect,
1774llvm::GlobalValue::WeakODRLinkage);
1780std::string Suffix =
getName({
"artificial",
""});
1782llvm::GlobalVariable *GAddr =
OMPBuilder.getOrCreateInternalVariable(
1783VarLVType, Twine(Name).concat(Suffix).str());
1786GAddr->setThreadLocal(
true);
1787 return Address(GAddr, GAddr->getValueType(),
1790std::string CacheSuffix =
getName({
"cache",
""});
1791llvm::Value *Args[] = {
1799Twine(Name).concat(Suffix).concat(CacheSuffix).str())};
1804 CGM.
getModule(), OMPRTL___kmpc_threadprivate_cached),
1850llvm::Function *OutlinedFn,
1853llvm::Value *NumThreads) {
1858 auto&&ThenGen = [&M, OutlinedFn, CapturedVars, RTLoc,
1862llvm::Value *Args[] = {
1864CGF.
Builder.getInt32(CapturedVars.size()),
1867RealArgs.append(std::begin(Args), std::end(Args));
1868RealArgs.append(CapturedVars.begin(), CapturedVars.end());
1870llvm::FunctionCallee RTLFn =
1871 OMPBuilder.getOrCreateRuntimeFunction(M, OMPRTL___kmpc_fork_call);
1874 auto&&ElseGen = [&M, OutlinedFn, CapturedVars, RTLoc,
Loc,
1880llvm::Value *Args[] = {RTLoc, ThreadID};
1882M, OMPRTL___kmpc_serialized_parallel),
1889 ".bound.zero.addr");
1894OutlinedFnArgs.push_back(ZeroAddrBound.
getPointer());
1895OutlinedFnArgs.append(CapturedVars.begin(), CapturedVars.end());
1903OutlinedFn->removeFnAttr(llvm::Attribute::AlwaysInline);
1904OutlinedFn->addFnAttr(llvm::Attribute::NoInline);
1910M, OMPRTL___kmpc_end_serialized_parallel),
1929 if(
auto*OMPRegionInfo =
1931 if(OMPRegionInfo->getThreadIDVariable())
1932 returnOMPRegionInfo->getThreadIDVariableLValue(CGF).getAddress();
1941 returnThreadIDTemp;
1945std::string Prefix = Twine(
"gomp_critical_user_", CriticalName).str();
1946std::string Name =
getName({Prefix,
"var"});
1953llvm::FunctionCallee EnterCallee;
1955llvm::FunctionCallee ExitCallee;
1958llvm::BasicBlock *ContBlock =
nullptr;
1961CommonActionTy(llvm::FunctionCallee EnterCallee,
1963llvm::FunctionCallee ExitCallee,
1965: EnterCallee(EnterCallee), EnterArgs(EnterArgs), ExitCallee(ExitCallee),
1966ExitArgs(ExitArgs), Conditional(Conditional) {}
1968llvm::Value *EnterRes = CGF.
EmitRuntimeCall(EnterCallee, EnterArgs);
1970llvm::Value *CallBool = CGF.
Builder.CreateIsNotNull(EnterRes);
1974CGF.
Builder.CreateCondBr(CallBool, ThenBlock, ContBlock);
1990StringRef CriticalName,
2004EnterArgs.push_back(CGF.
Builder.CreateIntCast(
2007CommonActionTy Action(
2010Hint ? OMPRTL___kmpc_critical_with_hint : OMPRTL___kmpc_critical),
2013OMPRTL___kmpc_end_critical),
2030CommonActionTy Action(
OMPBuilder.getOrCreateRuntimeFunction(
2052llvm::Value *FilterVal = Filter
2054: llvm::ConstantInt::get(
CGM.
Int32Ty,
0);
2059CommonActionTy Action(
OMPBuilder.getOrCreateRuntimeFunction(
2079llvm::Value *Args[] = {
2081llvm::ConstantInt::get(
CGM.
IntTy,
0,
true)};
2087 if(
auto*Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.
CapturedStmtInfo))
2088Region->emitUntiedSwitch(CGF);
2101CommonActionTy Action(
OMPBuilder.getOrCreateRuntimeFunction(
2114 unsignedIndex,
const VarDecl*Var) {
2135Args.push_back(&LHSArg);
2136Args.push_back(&RHSArg);
2142llvm::GlobalValue::InternalLinkage, Name,
2145Fn->setDoesNotRecurse();
2162 for(
unsignedI = 0,
E= AssignmentOps.size(); I <
E; ++I) {
2163 const auto*DestVar =
2164cast<VarDecl>(cast<DeclRefExpr>(DestExprs[I])->getDecl());
2167 const auto*SrcVar =
2168cast<VarDecl>(cast<DeclRefExpr>(SrcExprs[I])->getDecl());
2171 const auto*VD = cast<DeclRefExpr>(CopyprivateVars[I])->getDecl();
2173CGF.
EmitOMPCopy(
Type, DestAddr, SrcAddr, DestVar, SrcVar, AssignmentOps[I]);
2188assert(CopyprivateVars.size() == SrcExprs.size() &&
2189CopyprivateVars.size() == DstExprs.size() &&
2190CopyprivateVars.size() == AssignmentOps.size());
2202 if(!CopyprivateVars.empty()) {
2205 C.getIntTypeForBitwidth(
32,
1);
2206DidIt = CGF.
CreateMemTemp(KmpInt32Ty,
".omp.copyprivate.did_it");
2211CommonActionTy Action(
OMPBuilder.getOrCreateRuntimeFunction(
2228llvm::APInt ArraySize(
32, CopyprivateVars.size());
2229 QualTypeCopyprivateArrayTy =
C.getConstantArrayType(
2234CGF.
CreateMemTemp(CopyprivateArrayTy,
".omp.copyprivate.cpr_list");
2235 for(
unsignedI = 0,
E= CopyprivateVars.size(); I <
E; ++I) {
2247SrcExprs, DstExprs, AssignmentOps,
Loc);
2248llvm::Value *BufSize = CGF.
getTypeSize(CopyprivateArrayTy);
2252llvm::Value *Args[] = {
2277CommonActionTy Action(
OMPBuilder.getOrCreateRuntimeFunction(
2292 if(Kind == OMPD_for)
2293Flags = OMP_IDENT_BARRIER_IMPL_FOR;
2294 else if(Kind == OMPD_sections)
2295Flags = OMP_IDENT_BARRIER_IMPL_SECTIONS;
2296 else if(Kind == OMPD_single)
2297Flags = OMP_IDENT_BARRIER_IMPL_SINGLE;
2298 else if(Kind == OMPD_barrier)
2299Flags = OMP_IDENT_BARRIER_EXPL;
2301Flags = OMP_IDENT_BARRIER_IMPL;
2313ScheduleKind = OMPC_SCHEDULE_static;
2315llvm::APInt ChunkSize(32, 1);
2325 boolForceSimpleCall) {
2327 auto*OMPRegionInfo =
2330llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
2333CGF.
Builder.restoreIP(AfterIP);
2346 if(OMPRegionInfo) {
2347 if(!ForceSimpleCall && OMPRegionInfo->hasCancel()) {
2350OMPRTL___kmpc_cancel_barrier),
2359CGF.
Builder.CreateCondBr(Cmp, ExitBB, ContBB);
2376 Expr*ME,
boolIsFatal) {
2379: llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
2382llvm::Value *Args[] = {
2384llvm::ConstantInt::get(
CGM.
Int32Ty, IsFatal ? 2 : 1),
2393 boolChunked,
boolOrdered) {
2394 switch(ScheduleKind) {
2395 caseOMPC_SCHEDULE_static:
2396 returnChunked ? (Ordered ? OMP_ord_static_chunked : OMP_sch_static_chunked)
2397: (Ordered ? OMP_ord_static : OMP_sch_static);
2398 caseOMPC_SCHEDULE_dynamic:
2399 returnOrdered ? OMP_ord_dynamic_chunked : OMP_sch_dynamic_chunked;
2400 caseOMPC_SCHEDULE_guided:
2401 returnOrdered ? OMP_ord_guided_chunked : OMP_sch_guided_chunked;
2402 caseOMPC_SCHEDULE_runtime:
2403 returnOrdered ? OMP_ord_runtime : OMP_sch_runtime;
2404 caseOMPC_SCHEDULE_auto:
2405 returnOrdered ? OMP_ord_auto : OMP_sch_auto;
2407assert(!Chunked &&
"chunk was specified but schedule kind not known");
2408 returnOrdered ? OMP_ord_static : OMP_sch_static;
2410llvm_unreachable(
"Unexpected runtime schedule");
2414staticOpenMPSchedType
2417 returnChunked ? OMP_dist_sch_static_chunked : OMP_dist_sch_static;
2421 boolChunked)
const{
2422OpenMPSchedType Schedule =
2424 returnSchedule == OMP_sch_static;
2430 returnSchedule == OMP_dist_sch_static;
2434 boolChunked)
const{
2435OpenMPSchedType Schedule =
2437 returnSchedule == OMP_sch_static_chunked;
2443 returnSchedule == OMP_dist_sch_static_chunked;
2447OpenMPSchedType Schedule =
2449assert(Schedule != OMP_sch_static_chunked &&
"cannot be chunked here");
2450 returnSchedule != OMP_sch_static;
2458 caseOMPC_SCHEDULE_MODIFIER_monotonic:
2459Modifier = OMP_sch_modifier_monotonic;
2461 caseOMPC_SCHEDULE_MODIFIER_nonmonotonic:
2462Modifier = OMP_sch_modifier_nonmonotonic;
2464 caseOMPC_SCHEDULE_MODIFIER_simd:
2465 if(Schedule == OMP_sch_static_chunked)
2466Schedule = OMP_sch_static_balanced_chunked;
2473 caseOMPC_SCHEDULE_MODIFIER_monotonic:
2474Modifier = OMP_sch_modifier_monotonic;
2476 caseOMPC_SCHEDULE_MODIFIER_nonmonotonic:
2477Modifier = OMP_sch_modifier_nonmonotonic;
2479 caseOMPC_SCHEDULE_MODIFIER_simd:
2480 if(Schedule == OMP_sch_static_chunked)
2481Schedule = OMP_sch_static_balanced_chunked;
2493 if(CGM.
getLangOpts().OpenMP >= 50 && Modifier == 0) {
2494 if(!(Schedule == OMP_sch_static_chunked || Schedule == OMP_sch_static ||
2495Schedule == OMP_sch_static_balanced_chunked ||
2496Schedule == OMP_ord_static_chunked || Schedule == OMP_ord_static ||
2497Schedule == OMP_dist_sch_static_chunked ||
2498Schedule == OMP_dist_sch_static))
2499Modifier = OMP_sch_modifier_nonmonotonic;
2501 returnSchedule | Modifier;
2511ScheduleKind.
Schedule, DispatchValues.
Chunk!=
nullptr, Ordered);
2513(Schedule != OMP_sch_static && Schedule != OMP_sch_static_chunked &&
2514Schedule != OMP_ord_static && Schedule != OMP_ord_static_chunked &&
2515Schedule != OMP_sch_static_balanced_chunked));
2522llvm::Value *Chunk = DispatchValues.
Chunk? DispatchValues.
Chunk 2523: CGF.
Builder.getIntN(IVSize, 1);
2524llvm::Value *Args[] = {
2528 CGM, Schedule, ScheduleKind.
M1, ScheduleKind.
M2)),
2529DispatchValues.
LB,
2530DispatchValues.
UB,
2531CGF.
Builder.getIntN(IVSize, 1),
2548 CodeGenFunction&CGF, llvm::Value *UpdateLocation, llvm::Value *ThreadId,
2549llvm::FunctionCallee ForStaticInitFunction, OpenMPSchedType Schedule,
2556assert(Schedule == OMP_sch_static || Schedule == OMP_sch_static_chunked ||
2557Schedule == OMP_sch_static_balanced_chunked ||
2558Schedule == OMP_ord_static || Schedule == OMP_ord_static_chunked ||
2559Schedule == OMP_dist_sch_static ||
2560Schedule == OMP_dist_sch_static_chunked);
2567llvm::Value *Chunk = Values.
Chunk;
2568 if(Chunk ==
nullptr) {
2569assert((Schedule == OMP_sch_static || Schedule == OMP_ord_static ||
2570Schedule == OMP_dist_sch_static) &&
2571 "expected static non-chunked schedule");
2575assert((Schedule == OMP_sch_static_chunked ||
2576Schedule == OMP_sch_static_balanced_chunked ||
2577Schedule == OMP_ord_static_chunked ||
2578Schedule == OMP_dist_sch_static_chunked) &&
2579 "expected static chunked schedule");
2581llvm::Value *Args[] = {
2604 "Expected loop-based or sections-based directive.");
2607? OMP_IDENT_WORK_LOOP
2608: OMP_IDENT_WORK_SECTIONS);
2610llvm::FunctionCallee StaticInitFunction =
2615ScheduleNum, ScheduleKind.
M1, ScheduleKind.
M2, Values);
2622OpenMPSchedType ScheduleNum =
2624llvm::Value *UpdatedLocation =
2627llvm::FunctionCallee StaticInitFunction;
2628 boolisGPUDistribute =
2631StaticInitFunction =
OMPBuilder.createForStaticInitFunction(
2642assert((DKind == OMPD_distribute || DKind == OMPD_for ||
2643DKind == OMPD_sections) &&
2644 "Expected distribute, for, or sections directive kind");
2648llvm::Value *Args[] = {
2651(DKind == OMPD_target_teams_loop)
2652? OMP_IDENT_WORK_DISTRIBUTE
2654? OMP_IDENT_WORK_LOOP
2655: OMP_IDENT_WORK_SECTIONS),
2663 CGM.
getModule(), OMPRTL___kmpc_distribute_static_fini),
2692llvm::Value *Args[] = {
2700 OMPBuilder.createDispatchNextFunction(IVSize, IVSigned), Args);
2707llvm::Value *NumThreads,
2712llvm::Value *Args[] = {
2721ProcBindKind ProcBind,
2725assert(ProcBind != OMP_PROC_BIND_unknown &&
"Unsupported proc_bind value.");
2727llvm::Value *Args[] = {
2729llvm::ConstantInt::get(
CGM.
IntTy,
unsigned(ProcBind),
true)};
2751enumKmpTaskTFields {
2781llvm::OpenMPIRBuilder::EmitMetadataErrorReportFunctionTy &&ErrorReportFn =
2782[
this](llvm::OpenMPIRBuilder::EmitMetadataErrorKind Kind,
2783 constllvm::TargetRegionEntryInfo &EntryInfo) ->
void{
2785 if(Kind != llvm::OpenMPIRBuilder::EMIT_MD_GLOBAL_VAR_LINK_ERROR) {
2789 if(I->getFirst().getUniqueID().getDevice() == EntryInfo.DeviceID &&
2790I->getFirst().getUniqueID().getFile() == EntryInfo.FileID) {
2792I->getFirst(), EntryInfo.Line, 1);
2798 casellvm::OpenMPIRBuilder::EMIT_MD_TARGET_REGION_ERROR: {
2801 "%0 is incorrect: either the " 2802 "address or the ID is invalid.");
2805 casellvm::OpenMPIRBuilder::EMIT_MD_DECLARE_TARGET_ERROR: {
2808 "variable %0 is incorrect: the " 2809 "address is invalid.");
2812 casellvm::OpenMPIRBuilder::EMIT_MD_GLOBAL_VAR_LINK_ERROR: {
2815 "Offloading entry for declare target variable is incorrect: the " 2816 "address is invalid.");
2822 OMPBuilder.createOffloadEntriesAndInfoMetadata(ErrorReportFn);
2829 QualTypeKmpRoutineEntryTyArgs[] = {KmpInt32Ty,
C.VoidPtrTy};
2832 C.getFunctionType(KmpInt32Ty, KmpRoutineEntryTyArgs, EPI));
2838structPrivateHelpersTy {
2839PrivateHelpersTy(
const Expr*OriginalRef,
const VarDecl*Original,
2841: OriginalRef(OriginalRef), Original(Original), PrivateCopy(PrivateCopy),
2842PrivateElemInit(PrivateElemInit) {}
2843PrivateHelpersTy(
const VarDecl*Original) : Original(Original) {}
2844 const Expr*OriginalRef =
nullptr;
2845 const VarDecl*Original =
nullptr;
2846 const VarDecl*PrivateCopy =
nullptr;
2847 const VarDecl*PrivateElemInit =
nullptr;
2848 boolisLocalPrivate()
const{
2849 return!OriginalRef && !PrivateCopy && !PrivateElemInit;
2852typedefstd::pair<
CharUnits, PrivateHelpersTy> PrivateDataTy;
2857 if(!CVD->
hasAttr<OMPAllocateDeclAttr>())
2859 const auto*AA = CVD->
getAttr<OMPAllocateDeclAttr>();
2861 return!(AA->getAllocatorType() == OMPAllocateDeclAttr::OMPDefaultMemAlloc &&
2862!AA->getAllocator());
2867 if(!Privates.empty()) {
2872 RecordDecl*RD =
C.buildImplicitRecord(
".kmp_privates.t");
2874 for(
const auto&Pair : Privates) {
2875 const VarDecl*VD = Pair.second.Original;
2879 if(Pair.second.isLocalPrivate()) {
2902 QualTypeKmpRoutineEntryPointerQTy) {
2922 QualTypeKmpCmplrdataTy =
C.getRecordType(UD);
2923 RecordDecl*RD =
C.buildImplicitRecord(
"kmp_task_t");
2953 RecordDecl*RD =
C.buildImplicitRecord(
"kmp_task_t_with_privates");
2973staticllvm::Function *
2976 QualTypeKmpTaskTWithPrivatesPtrQTy,
2978 QualTypeSharedsPtrTy, llvm::Function *TaskFunction,
2979llvm::Value *TaskPrivatesMap) {
2987Args.push_back(&GtidArg);
2988Args.push_back(&TaskTypeArg);
2989 const auto&TaskEntryFnInfo =
2991llvm::FunctionType *TaskEntryTy =
2994 auto*TaskEntry = llvm::Function::Create(
2995TaskEntryTy, llvm::GlobalValue::InternalLinkage, Name, &CGM.
getModule());
2997TaskEntry->setDoesNotRecurse();
3012 const auto*KmpTaskTWithPrivatesQTyRD =
3013cast<RecordDecl>(KmpTaskTWithPrivatesQTy->
getAsTagDecl());
3016 const auto*KmpTaskTQTyRD = cast<RecordDecl>(KmpTaskTQTy->
getAsTagDecl());
3017 autoPartIdFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTPartId);
3019llvm::Value *PartidParam = PartIdLVal.
getPointer(CGF);
3021 autoSharedsFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTShareds);
3027 autoPrivatesFI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin(), 1);
3028llvm::Value *PrivatesParam;
3029 if(PrivatesFI != KmpTaskTWithPrivatesQTyRD->field_end()) {
3034PrivatesParam = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
3037llvm::Value *CommonArgs[] = {
3038GtidParam, PartidParam, PrivatesParam, TaskPrivatesMap,
3044std::end(CommonArgs));
3046 autoLBFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound);
3049 autoUBFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound);
3052 autoStFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTStride);
3055 autoLIFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLastIter);
3058 autoRFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTReductions);
3061CallArgs.push_back(LBParam);
3062CallArgs.push_back(UBParam);
3063CallArgs.push_back(StParam);
3064CallArgs.push_back(LIParam);
3065CallArgs.push_back(RParam);
3067CallArgs.push_back(SharedsParam);
3080 QualTypeKmpTaskTWithPrivatesPtrQTy,
3081 QualTypeKmpTaskTWithPrivatesQTy) {
3089Args.push_back(&GtidArg);
3090Args.push_back(&TaskTypeArg);
3091 const auto&DestructorFnInfo =
3093llvm::FunctionType *DestructorFnTy =
3097 auto*DestructorFn =
3098llvm::Function::Create(DestructorFnTy, llvm::GlobalValue::InternalLinkage,
3102DestructorFn->setDoesNotRecurse();
3110 const auto*KmpTaskTWithPrivatesQTyRD =
3111cast<RecordDecl>(KmpTaskTWithPrivatesQTy->
getAsTagDecl());
3112 autoFI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin());
3114 for(
const auto*Field :
3115cast<RecordDecl>(FI->getType()->getAsTagDecl())->fields()) {
3117Field->getType().isDestructedType()) {
3123 returnDestructorFn;
3143 C,
nullptr,
Loc,
nullptr,
3144 C.getPointerType(PrivatesQTy).withConst().withRestrict(),
3146Args.push_back(&TaskPrivatesArg);
3147llvm::DenseMap<CanonicalDeclPtr<const VarDecl>,
unsigned> PrivateVarsPos;
3148 unsignedCounter = 1;
3149 for(
const Expr*
E:
Data.PrivateVars) {
3151 C,
nullptr,
Loc,
nullptr,
3152 C.getPointerType(
C.getPointerType(
E->
getType()))
3156 const auto*VD = cast<VarDecl>(cast<DeclRefExpr>(
E)->getDecl());
3157PrivateVarsPos[VD] = Counter;
3160 for(
const Expr*
E:
Data.FirstprivateVars) {
3162 C,
nullptr,
Loc,
nullptr,
3163 C.getPointerType(
C.getPointerType(
E->
getType()))
3167 const auto*VD = cast<VarDecl>(cast<DeclRefExpr>(
E)->getDecl());
3168PrivateVarsPos[VD] = Counter;
3171 for(
const Expr*
E:
Data.LastprivateVars) {
3173 C,
nullptr,
Loc,
nullptr,
3174 C.getPointerType(
C.getPointerType(
E->
getType()))
3178 const auto*VD = cast<VarDecl>(cast<DeclRefExpr>(
E)->getDecl());
3179PrivateVarsPos[VD] = Counter;
3185Ty =
C.getPointerType(Ty);
3187Ty =
C.getPointerType(Ty);
3189 C,
nullptr,
Loc,
nullptr,
3190 C.getPointerType(
C.getPointerType(Ty)).withConst().withRestrict(),
3192PrivateVarsPos[VD] = Counter;
3195 const auto&TaskPrivatesMapFnInfo =
3197llvm::FunctionType *TaskPrivatesMapTy =
3201 auto*TaskPrivatesMap = llvm::Function::Create(
3202TaskPrivatesMapTy, llvm::GlobalValue::InternalLinkage, Name,
3205TaskPrivatesMapFnInfo);
3207TaskPrivatesMap->removeFnAttr(llvm::Attribute::NoInline);
3208TaskPrivatesMap->removeFnAttr(llvm::Attribute::OptimizeNone);
3209TaskPrivatesMap->addFnAttr(llvm::Attribute::AlwaysInline);
3213TaskPrivatesMapFnInfo, Args,
Loc,
Loc);
3219 const auto*PrivatesQTyRD = cast<RecordDecl>(PrivatesQTy->
getAsTagDecl());
3221 for(
const FieldDecl*Field : PrivatesQTyRD->fields()) {
3223 const VarDecl*VD = Args[PrivateVarsPos[Privates[Counter].second.Original]];
3232 returnTaskPrivatesMap;
3244 autoFI = std::next(KmpTaskTWithPrivatesQTyRD->
field_begin());
3250CodeGenFunction::CGCapturedStmtInfo CapturesInfo(CS);
3258 if((!IsTargetTask && !
Data.FirstprivateVars.empty() && ForDup) ||
3259(IsTargetTask && KmpTaskSharedsPtr.
isValid())) {
3266FI = cast<RecordDecl>(FI->getType()->getAsTagDecl())->field_begin();
3267 for(
constPrivateDataTy &Pair : Privates) {
3269 if(Pair.second.isLocalPrivate()) {
3273 const VarDecl*VD = Pair.second.PrivateCopy;
3275 if(
Init&& (!ForDup || (isa<CXXConstructExpr>(
Init) &&
3278 if(
const VarDecl*Elem = Pair.second.PrivateElemInit) {
3279 const VarDecl*OriginalVD = Pair.second.Original;
3284 const FieldDecl*SharedField = CapturesInfo.lookup(OriginalVD);
3285 if(IsTargetTask && !SharedField) {
3286assert(isa<ImplicitParamDecl>(OriginalVD) &&
3289->getNumParams() == 0 &&
3290isa<TranslationUnitDecl>(
3292->getDeclContext()) &&
3293 "Expected artificial target data variable.");
3296}
else if(ForDup) {
3300 C.getDeclAlign(OriginalVD)),
3304Pair.second.Original->getCanonicalDecl()) > 0 ||
3306SharedRefLValue = CGF.
EmitLValue(Pair.second.OriginalRef);
3309InlinedOpenMPRegionRAII Region(
3312SharedRefLValue = CGF.
EmitLValue(Pair.second.OriginalRef);
3324[&CGF, Elem,
Init, &CapturesInfo](
AddressDestElement,
3327CodeGenFunction::OMPPrivateScope InitScope(CGF);
3328InitScope.addPrivate(Elem, SrcElement);
3329(void)InitScope.Privatize();
3331CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(
3332CGF, &CapturesInfo);
3333CGF.EmitAnyExprToMem(Init, DestElement,
3334Init->getType().getQualifiers(),
3339CodeGenFunction::OMPPrivateScope InitScope(CGF);
3340InitScope.addPrivate(Elem, SharedRefLValue.
getAddress());
3341(void)InitScope.Privatize();
3342CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CapturesInfo);
3357 boolInitRequired =
false;
3358 for(
constPrivateDataTy &Pair : Privates) {
3359 if(Pair.second.isLocalPrivate())
3361 const VarDecl*VD = Pair.second.PrivateCopy;
3363InitRequired = InitRequired || (isa_and_nonnull<CXXConstructExpr>(
Init) &&
3368 returnInitRequired;
3385 QualTypeKmpTaskTWithPrivatesPtrQTy,
3393KmpTaskTWithPrivatesPtrQTy,
3396KmpTaskTWithPrivatesPtrQTy,
3400Args.push_back(&DstArg);
3401Args.push_back(&SrcArg);
3402Args.push_back(&LastprivArg);
3403 const auto&TaskDupFnInfo =
3407 auto*TaskDup = llvm::Function::Create(
3408TaskDupTy, llvm::GlobalValue::InternalLinkage, Name, &CGM.
getModule());
3410TaskDup->setDoesNotRecurse();
3420 autoLIFI = std::next(KmpTaskTQTyRD->
field_begin(), KmpTaskTLastIter);
3422TDBase, *KmpTaskTWithPrivatesQTyRD->
field_begin());
3430assert(!Privates.empty());
3432 if(!
Data.FirstprivateVars.empty()) {
3437TDBase, *KmpTaskTWithPrivatesQTyRD->
field_begin());
3445 emitPrivatesInit(CGF,
D, KmpTaskSharedsPtr, TDBase, KmpTaskTWithPrivatesQTyRD,
3446SharedsTy, SharedsPtrTy,
Data, Privates,
true);
3456 for(
constPrivateDataTy &
P: Privates) {
3457 if(
P.second.isLocalPrivate())
3459 QualTypeTy =
P.second.Original->getType().getNonReferenceType();
3468classOMPIteratorGeneratorScope final
3469:
publicCodeGenFunction::OMPPrivateScope {
3474OMPIteratorGeneratorScope() =
delete;
3475OMPIteratorGeneratorScope(OMPIteratorGeneratorScope &) =
delete;
3483 for(
unsignedI = 0, End =
E->numOfIterators(); I < End; ++I) {
3485 const auto*VD = cast<VarDecl>(
E->getIteratorDecl(I));
3494 for(
unsignedI = 0, End =
E->numOfIterators(); I < End; ++I) {
3503CodeGenFunction::JumpDest &ContDest =
3505CodeGenFunction::JumpDest &ExitDest =
3508llvm::Value *N = Uppers[I];
3516? CGF.
Builder.CreateICmpSLT(CVal, N)
3517: CGF.
Builder.CreateICmpULT(CVal, N);
3519CGF.
Builder.CreateCondBr(Cmp, BodyBB, ExitDest.getBlock());
3526~OMPIteratorGeneratorScope() {
3529 for(
unsignedI =
E->numOfIterators(); I > 0; --I) {
3536CGF.
EmitBlock(ExitDests[I - 1].getBlock(),
I == 1);
3542staticstd::pair<llvm::Value *, llvm::Value *>
3544 const auto*OASE = dyn_cast<OMPArrayShapingExpr>(
E);
3547 const Expr*
Base= OASE->getBase();
3552llvm::Value *SizeVal;
3555SizeVal = CGF.
getTypeSize(OASE->getBase()->getType()->getPointeeType());
3556 for(
const Expr*SE : OASE->getDimensions()) {
3560SizeVal = CGF.
Builder.CreateNUWMul(SizeVal, Sz);
3562}
else if(
const auto*ASE =
3566llvm::Value *UpAddr = CGF.
Builder.CreateConstGEP1_32(
3569llvm::Value *LowIntPtr = CGF.
Builder.CreatePtrToInt(Addr, CGF.
SizeTy);
3570llvm::Value *UpIntPtr = CGF.
Builder.CreatePtrToInt(UpAddr, CGF.
SizeTy);
3571SizeVal = CGF.
Builder.CreateNUWSub(UpIntPtr, LowIntPtr);
3575 returnstd::make_pair(Addr, SizeVal);
3580 QualTypeFlagsTy =
C.getIntTypeForBitwidth(32,
false);
3581 if(KmpTaskAffinityInfoTy.
isNull()) {
3583 C.buildImplicitRecord(
"kmp_task_affinity_info_t");
3589KmpTaskAffinityInfoTy =
C.getRecordType(KmpAffinityInfoRD);
3596llvm::Function *TaskFunction,
QualTypeSharedsTy,
3601 const auto*I =
Data.PrivateCopies.begin();
3602 for(
const Expr*
E:
Data.PrivateVars) {
3603 const auto*VD = cast<VarDecl>(cast<DeclRefExpr>(
E)->getDecl());
3604Privates.emplace_back(
3605 C.getDeclAlign(VD),
3606PrivateHelpersTy(
E, VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()),
3610I =
Data.FirstprivateCopies.begin();
3611 const auto*IElemInitRef =
Data.FirstprivateInits.begin();
3612 for(
const Expr*
E:
Data.FirstprivateVars) {
3613 const auto*VD = cast<VarDecl>(cast<DeclRefExpr>(
E)->getDecl());
3614Privates.emplace_back(
3615 C.getDeclAlign(VD),
3617 E, VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()),
3618cast<VarDecl>(cast<DeclRefExpr>(*IElemInitRef)->getDecl())));
3622I =
Data.LastprivateCopies.begin();
3623 for(
const Expr*
E:
Data.LastprivateVars) {
3624 const auto*VD = cast<VarDecl>(cast<DeclRefExpr>(
E)->getDecl());
3625Privates.emplace_back(
3626 C.getDeclAlign(VD),
3627PrivateHelpersTy(
E, VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()),
3635Privates.emplace_back(
C.getDeclAlign(VD), PrivateHelpersTy(VD));
3637llvm::stable_sort(Privates,
3638[](
constPrivateDataTy &L,
constPrivateDataTy &R) {
3639 returnL.first > R.first;
3641 QualTypeKmpInt32Ty =
C.getIntTypeForBitwidth(
32,
1);
3652assert((
D.getDirectiveKind() == OMPD_task ||
3655 "Expected taskloop, task or target directive");
3664 const RecordDecl*KmpTaskTWithPrivatesQTyRD =
3666 QualTypeKmpTaskTWithPrivatesQTy =
C.getRecordType(KmpTaskTWithPrivatesQTyRD);
3667 QualTypeKmpTaskTWithPrivatesPtrQTy =
3668 C.getPointerType(KmpTaskTWithPrivatesQTy);
3669llvm::Type *KmpTaskTWithPrivatesPtrTy = CGF.
Builder.getPtrTy(0);
3670llvm::Value *KmpTaskTWithPrivatesTySize =
3672 QualTypeSharedsPtrTy =
C.getPointerType(SharedsTy);
3675llvm::Value *TaskPrivatesMap =
nullptr;
3676llvm::Type *TaskPrivatesMapTy =
3677std::next(TaskFunction->arg_begin(), 3)->getType();
3678 if(!Privates.empty()) {
3679 autoFI = std::next(KmpTaskTWithPrivatesQTyRD->
field_begin());
3683TaskPrivatesMap, TaskPrivatesMapTy);
3685TaskPrivatesMap = llvm::ConstantPointerNull::get(
3686cast<llvm::PointerType>(TaskPrivatesMapTy));
3691 CGM,
Loc,
D.getDirectiveKind(), KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy,
3692KmpTaskTWithPrivatesQTy,
KmpTaskTQTy, SharedsPtrTy, TaskFunction,
3704DestructorsFlag = 0x8,
3705PriorityFlag = 0x20,
3706DetachableFlag = 0x40,
3708 unsignedFlags =
Data.Tied ? TiedFlag : 0;
3709 boolNeedsCleanup =
false;
3710 if(!Privates.empty()) {
3714Flags = Flags | DestructorsFlag;
3716 if(
Data.Priority.getInt())
3717Flags = Flags | PriorityFlag;
3719Flags = Flags | DetachableFlag;
3720llvm::Value *TaskFlags =
3721 Data.Final.getPointer()
3722? CGF.
Builder.CreateSelect(
Data.Final.getPointer(),
3723CGF.
Builder.getInt32(FinalFlag),
3725: CGF.
Builder.getInt32(
Data.Final.getInt() ? FinalFlag : 0);
3726TaskFlags = CGF.
Builder.CreateOr(TaskFlags, CGF.
Builder.getInt32(Flags));
3727llvm::Value *SharedsSize =
CGM.
getSize(
C.getTypeSizeInChars(SharedsTy));
3732llvm::Value *NewTask;
3739llvm::Value *DeviceID;
3744DeviceID = CGF.
Builder.getInt64(OMP_DEVICEID_UNDEF);
3745AllocArgs.push_back(DeviceID);
3748 CGM.
getModule(), OMPRTL___kmpc_omp_target_task_alloc),
3766llvm::Value *Tid =
getThreadID(CGF, DC->getBeginLoc());
3767Tid = CGF.
Builder.CreateIntCast(Tid, CGF.
IntTy,
false);
3770 CGM.
getModule(), OMPRTL___kmpc_task_allow_completion_event),
3771{Loc, Tid, NewTask});
3782llvm::Value *NumOfElements =
nullptr;
3783 unsignedNumAffinities = 0;
3785 if(
const Expr*Modifier =
C->getModifier()) {
3786 const auto*IE = cast<OMPIteratorExpr>(Modifier->IgnoreParenImpCasts());
3787 for(
unsignedI = 0,
E= IE->numOfIterators(); I <
E; ++I) {
3791NumOfElements ? CGF.
Builder.CreateNUWMul(NumOfElements, Sz) : Sz;
3794NumAffinities +=
C->varlist_size();
3799 enumRTLAffinityInfoFieldsTy { BaseAddr, Len, Flags };
3801 QualTypeKmpTaskAffinityInfoArrayTy;
3802 if(NumOfElements) {
3803NumOfElements = CGF.
Builder.CreateNUWAdd(
3804llvm::ConstantInt::get(CGF.
SizeTy, NumAffinities), NumOfElements);
3807 C.getIntTypeForBitwidth(
C.getTypeSize(
C.getSizeType()),
0),
3811KmpTaskAffinityInfoArrayTy =
C.getVariableArrayType(
3819NumOfElements = CGF.
Builder.CreateIntCast(NumOfElements, CGF.
Int32Ty,
3822KmpTaskAffinityInfoArrayTy =
C.getConstantArrayType(
3824llvm::APInt(
C.getTypeSize(
C.getSizeType()), NumAffinities),
nullptr,
3827CGF.
CreateMemTemp(KmpTaskAffinityInfoArrayTy,
".affs.arr.addr");
3829NumOfElements = llvm::ConstantInt::get(
CGM.
Int32Ty, NumAffinities,
3836 boolHasIterator =
false;
3838 if(
C->getModifier()) {
3839HasIterator =
true;
3842 for(
const Expr*
E:
C->varlist()) {
3851 Base, *std::next(KmpAffinityInfoRD->field_begin(), BaseAddr));
3856 Base, *std::next(KmpAffinityInfoRD->field_begin(), Len));
3870 const Expr*Modifier =
C->getModifier();
3873OMPIteratorGeneratorScope IteratorScope(
3875 for(
const Expr*
E:
C->varlist()) {
3885 Base, *std::next(KmpAffinityInfoRD->field_begin(), BaseAddr));
3890 Base, *std::next(KmpAffinityInfoRD->field_begin(), Len));
3892Idx = CGF.
Builder.CreateNUWAdd(
3893Idx, llvm::ConstantInt::get(Idx->getType(), 1));
3908 CGM.
getModule(), OMPRTL___kmpc_omp_reg_task_with_affinity),
3909{LocRef, GTid, NewTask, NumOfElements, AffinListPtr});
3911llvm::Value *NewTaskNewTaskTTy =
3913NewTask, KmpTaskTWithPrivatesPtrTy);
3915KmpTaskTWithPrivatesQTy);
3926*std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTShareds)),
3935 if(!Privates.empty()) {
3937SharedsTy, SharedsPtrTy,
Data, Privates,
3942 CGM,
Loc,
D, KmpTaskTWithPrivatesPtrQTy, KmpTaskTWithPrivatesQTyRD,
3943KmpTaskTQTyRD, SharedsTy, SharedsPtrTy,
Data, Privates,
3944!
Data.LastprivateVars.empty());
3948 enum{
Priority= 0, Destructors = 1 };
3950 autoFI = std::next(KmpTaskTQTyRD->field_begin(), Data1);
3952(*FI)->getType()->getAsUnionType()->getDecl();
3955 CGM,
Loc, KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy,
3956KmpTaskTWithPrivatesQTy);
3959Data1LV, *std::next(KmpCmplrdataUD->
field_begin(), Destructors));
3965 if(
Data.Priority.getInt()) {
3967TDBase, *std::next(KmpTaskTQTyRD->field_begin(), Data2));
3972 Result.NewTask = NewTask;
3973 Result.TaskEntry = TaskEntry;
3974 Result.NewTaskNewTaskTTy = NewTaskNewTaskTTy;
3976 Result.KmpTaskTQTyRD = KmpTaskTQTyRD;
3982RTLDependenceKindTy DepKind;
3984 caseOMPC_DEPEND_in:
3985DepKind = RTLDependenceKindTy::DepIn;
3988 caseOMPC_DEPEND_out:
3989 caseOMPC_DEPEND_inout:
3990DepKind = RTLDependenceKindTy::DepInOut;
3992 caseOMPC_DEPEND_mutexinoutset:
3993DepKind = RTLDependenceKindTy::DepMutexInOutSet;
3995 caseOMPC_DEPEND_inoutset:
3996DepKind = RTLDependenceKindTy::DepInOutSet;
3998 caseOMPC_DEPEND_outallmemory:
3999DepKind = RTLDependenceKindTy::DepOmpAllMem;
4001 caseOMPC_DEPEND_source:
4002 caseOMPC_DEPEND_sink:
4003 caseOMPC_DEPEND_depobj:
4004 caseOMPC_DEPEND_inoutallmemory:
4006llvm_unreachable(
"Unknown task dependence type");
4014FlagsTy =
C.getIntTypeForBitwidth(
C.getTypeSize(
C.BoolTy),
false);
4015 if(KmpDependInfoTy.
isNull()) {
4016 RecordDecl*KmpDependInfoRD =
C.buildImplicitRecord(
"kmp_depend_info");
4022KmpDependInfoTy =
C.getRecordType(KmpDependInfoRD);
4026std::pair<llvm::Value *, LValue>
4040CGF,
Base.getAddress(),
4041llvm::ConstantInt::get(CGF.
IntPtrTy, -1,
true));
4048 static_cast<unsigned int>(RTLDependInfoFields::BaseAddr)));
4050 returnstd::make_pair(NumDeps,
Base);
4054llvm::PointerUnion<unsigned *, LValue *> Pos,
4065OMPIteratorGeneratorScope IteratorScope(
4066CGF, cast_or_null<OMPIteratorExpr>(
4067 Data.IteratorExpr ?
Data.IteratorExpr->IgnoreParenImpCasts()
4069 for(
const Expr*
E:
Data.DepExprs) {
4078Addr = llvm::ConstantInt::get(CGF.
IntPtrTy, 0);
4079Size = llvm::ConstantInt::get(CGF.
SizeTy, 0);
4082 if(
unsigned*
P= dyn_cast<unsigned *>(Pos)) {
4086assert(
E&&
"Expected a non-null expression");
4087 LValue&PosLVal = *cast<LValue *>(Pos);
4096 static_cast<unsigned int>(RTLDependInfoFields::BaseAddr)));
4101 static_cast<unsigned int>(RTLDependInfoFields::Len)));
4108 static_cast<unsigned int>(RTLDependInfoFields::Flags)));
4110llvm::ConstantInt::get(LLVMFlagsTy,
static_cast<unsigned int>(DepKind)),
4112 if(
unsigned*
P= dyn_cast<unsigned *>(Pos)) {
4115 LValue&PosLVal = *cast<LValue *>(Pos);
4117Idx = CGF.
Builder.CreateNUWAdd(Idx,
4118llvm::ConstantInt::get(Idx->getType(), 1));
4127assert(
Data.DepKind == OMPC_DEPEND_depobj &&
4128 "Expected depobj dependency kind.");
4133OMPIteratorGeneratorScope IteratorScope(
4134CGF, cast_or_null<OMPIteratorExpr>(
4135 Data.IteratorExpr ?
Data.IteratorExpr->IgnoreParenImpCasts()
4137 for(
const Expr*
E:
Data.DepExprs) {
4138llvm::Value *NumDeps;
4141std::tie(NumDeps,
Base) =
4145 C.getUIntPtrType());
4149llvm::Value *Add = CGF.
Builder.CreateNUWAdd(PrevVal, NumDeps);
4151SizeLVals.push_back(NumLVal);
4154 for(
unsignedI = 0,
E= SizeLVals.size(); I <
E; ++I) {
4157Sizes.push_back(Size);
4167assert(
Data.DepKind == OMPC_DEPEND_depobj &&
4168 "Expected depobj dependency kind.");
4171OMPIteratorGeneratorScope IteratorScope(
4172CGF, cast_or_null<OMPIteratorExpr>(
4173 Data.IteratorExpr ?
Data.IteratorExpr->IgnoreParenImpCasts()
4175 for(
unsignedI = 0, End =
Data.DepExprs.size(); I < End; ++I) {
4177llvm::Value *NumDeps;
4180std::tie(NumDeps,
Base) =
4184llvm::Value *Size = CGF.
Builder.CreateNUWMul(
4186CGF.
Builder.CreateIntCast(NumDeps, CGF.
SizeTy,
false));
4193llvm::Value *Add = CGF.
Builder.CreateNUWAdd(Pos, NumDeps);
4203 return D.DepExprs.empty();
4209llvm::Value *NumOfElements =
nullptr;
4210 unsignedNumDependencies = std::accumulate(
4211Dependencies.begin(), Dependencies.end(), 0,
4213return D.DepKind == OMPC_DEPEND_depobj
4215: (V + (D.IteratorExpr ? 0 : D.DepExprs.size()));
4219 boolHasDepobjDeps =
false;
4220 boolHasRegularWithIterators =
false;
4221llvm::Value *NumOfDepobjElements = llvm::ConstantInt::get(CGF.
IntPtrTy, 0);
4222llvm::Value *NumOfRegularWithIterators =
4223llvm::ConstantInt::get(CGF.
IntPtrTy, 0);
4227 if(
D.DepKind == OMPC_DEPEND_depobj) {
4230 for(llvm::Value *Size : Sizes) {
4231NumOfDepobjElements =
4232CGF.
Builder.CreateNUWAdd(NumOfDepobjElements, Size);
4234HasDepobjDeps =
true;
4239 if(
const auto*IE = cast_or_null<OMPIteratorExpr>(
D.IteratorExpr)) {
4240llvm::Value *ClauseIteratorSpace =
4241llvm::ConstantInt::get(CGF.
IntPtrTy, 1);
4242 for(
unsignedI = 0,
E= IE->numOfIterators(); I <
E; ++I) {
4245ClauseIteratorSpace = CGF.
Builder.CreateNUWMul(Sz, ClauseIteratorSpace);
4247llvm::Value *NumClauseDeps = CGF.
Builder.CreateNUWMul(
4248ClauseIteratorSpace,
4249llvm::ConstantInt::get(CGF.
IntPtrTy,
D.DepExprs.size()));
4250NumOfRegularWithIterators =
4251CGF.
Builder.CreateNUWAdd(NumOfRegularWithIterators, NumClauseDeps);
4252HasRegularWithIterators =
true;
4258 if(HasDepobjDeps || HasRegularWithIterators) {
4259NumOfElements = llvm::ConstantInt::get(
CGM.
IntPtrTy, NumDependencies,
4261 if(HasDepobjDeps) {
4263CGF.
Builder.CreateNUWAdd(NumOfDepobjElements, NumOfElements);
4265 if(HasRegularWithIterators) {
4267CGF.
Builder.CreateNUWAdd(NumOfRegularWithIterators, NumOfElements);
4270 Loc,
C.getIntTypeForBitwidth(
64,
0),
4274KmpDependInfoArrayTy =
4283NumOfElements = CGF.
Builder.CreateIntCast(NumOfElements, CGF.
Int32Ty,
4286KmpDependInfoArrayTy =
C.getConstantArrayType(
4290CGF.
CreateMemTemp(KmpDependInfoArrayTy,
".dep.arr.addr");
4292NumOfElements = llvm::ConstantInt::get(
CGM.
Int32Ty, NumDependencies,
4296 for(
unsignedI = 0, End = Dependencies.size(); I < End; ++I) {
4297 if(Dependencies[I].DepKind == OMPC_DEPEND_depobj ||
4298Dependencies[I].IteratorExpr)
4305CGF.
CreateMemTemp(
C.getSizeType(),
"dep.counter.addr"),
C.getSizeType());
4307 for(
unsignedI = 0, End = Dependencies.size(); I < End; ++I) {
4308 if(Dependencies[I].DepKind == OMPC_DEPEND_depobj ||
4309!Dependencies[I].IteratorExpr)
4315 if(HasDepobjDeps) {
4316 for(
unsignedI = 0, End = Dependencies.size(); I < End; ++I) {
4317 if(Dependencies[I].DepKind != OMPC_DEPEND_depobj)
4325 returnstd::make_pair(NumOfElements, DependenciesArray);
4331 if(Dependencies.
DepExprs.empty())
4336 unsignedNumDependencies = Dependencies.
DepExprs.size();
4347llvm::Value *NumDepsVal;
4349 if(
const auto*IE =
4350cast_or_null<OMPIteratorExpr>(Dependencies.
IteratorExpr)) {
4351NumDepsVal = llvm::ConstantInt::get(CGF.
SizeTy, 1);
4352 for(
unsignedI = 0,
E= IE->numOfIterators(); I <
E; ++I) {
4355NumDepsVal = CGF.
Builder.CreateNUWMul(NumDepsVal, Sz);
4357Size = CGF.
Builder.CreateNUWAdd(llvm::ConstantInt::get(CGF.
SizeTy, 1),
4361llvm::Value *RecSize =
CGM.
getSize(SizeInBytes);
4362Size = CGF.
Builder.CreateNUWMul(Size, RecSize);
4366 QualTypeKmpDependInfoArrayTy =
C.getConstantArrayType(
4369 CharUnitsSz =
C.getTypeSizeInChars(KmpDependInfoArrayTy);
4371NumDepsVal = llvm::ConstantInt::get(CGF.
IntPtrTy, NumDependencies);
4376llvm::Value *Allocator = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
4377llvm::Value *Args[] = {ThreadID, Size, Allocator};
4382Args,
".dep.arr.addr");
4385Addr, CGF.
Builder.getPtrTy(0));
4386DependenciesArray =
Address(Addr, KmpDependInfoLlvmTy, Align);
4393 static_cast<unsigned int>(RTLDependInfoFields::BaseAddr)));
4395llvm::PointerUnion<unsigned *, LValue *> Pos;
4400CGF.
CreateMemTemp(
C.getSizeType(),
"iterator.counter.addr"),
4412 returnDependenciesArray;
4428llvm::ConstantInt::get(CGF.
IntPtrTy, -1,
true));
4433llvm::Value *Allocator = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
4434llvm::Value *Args[] = {ThreadID, DepObjAddr, Allocator};
4451llvm::Value *NumDeps;
4458 Begin.emitRawPointer(CGF), NumDeps);
4462llvm::BasicBlock *EntryBB = CGF.
Builder.GetInsertBlock();
4464llvm::PHINode *ElementPHI =
4465CGF.
Builder.CreatePHI(
Begin.getType(), 2,
"omp.elementPast");
4466ElementPHI->addIncoming(
Begin.emitRawPointer(CGF), EntryBB);
4469 Base.getTBAAInfo());
4474 static_cast<unsigned int>(RTLDependInfoFields::Flags)));
4476llvm::ConstantInt::get(LLVMFlagsTy,
static_cast<unsigned int>(DepKind)),
4480llvm::Value *ElementNext =
4483ElementPHI->addIncoming(ElementNext, CGF.
Builder.GetInsertBlock());
4484llvm::Value *IsEmpty =
4485CGF.
Builder.CreateICmpEQ(ElementNext, End,
"omp.isempty");
4486CGF.
Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
4493llvm::Function *TaskFunction,
4502llvm::Value *NewTask =
Result.NewTask;
4503llvm::Function *TaskEntry =
Result.TaskEntry;
4504llvm::Value *NewTaskNewTaskTTy =
Result.NewTaskNewTaskTTy;
4509llvm::Value *NumOfElements;
4510std::tie(NumOfElements, DependenciesArray) =
4521llvm::Value *TaskArgs[] = { UpLoc, ThreadID, NewTask };
4522llvm::Value *DepTaskArgs[7];
4523 if(!
Data.Dependences.empty()) {
4524DepTaskArgs[0] = UpLoc;
4525DepTaskArgs[1] = ThreadID;
4526DepTaskArgs[2] = NewTask;
4527DepTaskArgs[3] = NumOfElements;
4529DepTaskArgs[5] = CGF.
Builder.getInt32(0);
4530DepTaskArgs[6] = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
4532 auto&&ThenCodeGen = [
this, &
Data, TDBase, KmpTaskTQTyRD, &TaskArgs,
4535 autoPartIdFI = std::next(KmpTaskTQTyRD->
field_begin(), KmpTaskTPartId);
4539 if(!
Data.Dependences.empty()) {
4552Region->emitUntiedSwitch(CGF);
4555llvm::Value *DepWaitTaskArgs[7];
4556 if(!
Data.Dependences.empty()) {
4557DepWaitTaskArgs[0] = UpLoc;
4558DepWaitTaskArgs[1] = ThreadID;
4559DepWaitTaskArgs[2] = NumOfElements;
4561DepWaitTaskArgs[4] = CGF.
Builder.getInt32(0);
4562DepWaitTaskArgs[5] = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
4563DepWaitTaskArgs[6] =
4564llvm::ConstantInt::get(CGF.
Int32Ty,
Data.HasNowaitClause);
4567 auto&&ElseCodeGen = [
this, &M, &TaskArgs, ThreadID, NewTaskNewTaskTTy,
4568TaskEntry, &
Data, &DepWaitTaskArgs,
4575 if(!
Data.Dependences.empty())
4577M, OMPRTL___kmpc_omp_taskwait_deps_51),
4580 auto&&CodeGen = [TaskEntry, ThreadID, NewTaskNewTaskTTy,
4583llvm::Value *OutlinedFnArgs[] = {ThreadID, NewTaskNewTaskTTy};
4584CGF.CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF,
Loc, TaskEntry,
4593CommonActionTy Action(
OMPBuilder.getOrCreateRuntimeFunction(
4594M, OMPRTL___kmpc_omp_task_begin_if0),
4597M, OMPRTL___kmpc_omp_task_complete_if0),
4613llvm::Function *TaskFunction,
4633IfVal = llvm::ConstantInt::getSigned(CGF.
IntTy,
1);
4638*std::next(
Result.KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound));
4640cast<VarDecl>(cast<DeclRefExpr>(
D.getLowerBoundVariable())->getDecl());
4645*std::next(
Result.KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound));
4647cast<VarDecl>(cast<DeclRefExpr>(
D.getUpperBoundVariable())->getDecl());
4652*std::next(
Result.KmpTaskTQTyRD->field_begin(), KmpTaskTStride));
4654cast<VarDecl>(cast<DeclRefExpr>(
D.getStrideVariable())->getDecl());
4660*std::next(
Result.KmpTaskTQTyRD->field_begin(), KmpTaskTReductions));
4661 if(
Data.Reductions) {
4667 enum{ NoSchedule = 0, Grainsize = 1, NumTasks = 2 };
4676llvm::ConstantInt::getSigned(
4678llvm::ConstantInt::getSigned(
4679CGF.
IntTy,
Data.Schedule.getPointer()
4680?
Data.Schedule.getInt() ? NumTasks : Grainsize
4682 Data.Schedule.getPointer()
4685: llvm::ConstantInt::get(CGF.
Int64Ty,
0)};
4686 if(
Data.HasModifier)
4687TaskArgs.push_back(llvm::ConstantInt::get(CGF.
Int32Ty, 1));
4689TaskArgs.push_back(
Result.TaskDupFn
4692: llvm::ConstantPointerNull::get(CGF.
VoidPtrTy));
4695? OMPRTL___kmpc_taskloop_5
4696: OMPRTL___kmpc_taskloop),
4713 const Expr*,
const Expr*)> &RedOpGen,
4714 const Expr*XExpr =
nullptr,
const Expr*EExpr =
nullptr,
4715 const Expr*UpExpr =
nullptr) {
4723llvm::Value *NumElements = CGF.
emitArrayLength(ArrayTy, ElementTy, LHSAddr);
4728llvm::Value *LHSEnd =
4733llvm::Value *IsEmpty =
4734CGF.
Builder.CreateICmpEQ(LHSBegin, LHSEnd,
"omp.arraycpy.isempty");
4735CGF.
Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
4738llvm::BasicBlock *EntryBB = CGF.
Builder.GetInsertBlock();
4743llvm::PHINode *RHSElementPHI = CGF.
Builder.CreatePHI(
4744RHSBegin->getType(), 2,
"omp.arraycpy.srcElementPast");
4745RHSElementPHI->addIncoming(RHSBegin, EntryBB);
4750llvm::PHINode *LHSElementPHI = CGF.
Builder.CreatePHI(
4751LHSBegin->getType(), 2,
"omp.arraycpy.destElementPast");
4752LHSElementPHI->addIncoming(LHSBegin, EntryBB);
4758CodeGenFunction::OMPPrivateScope
Scope(CGF);
4759 Scope.addPrivate(LHSVar, LHSElementCurrent);
4760 Scope.addPrivate(RHSVar, RHSElementCurrent);
4762RedOpGen(CGF, XExpr, EExpr, UpExpr);
4763 Scope.ForceCleanup();
4766llvm::Value *LHSElementNext = CGF.
Builder.CreateConstGEP1_32(
4768 "omp.arraycpy.dest.element");
4769llvm::Value *RHSElementNext = CGF.
Builder.CreateConstGEP1_32(
4771 "omp.arraycpy.src.element");
4774CGF.
Builder.CreateICmpEQ(LHSElementNext, LHSEnd,
"omp.arraycpy.done");
4775CGF.
Builder.CreateCondBr(Done, DoneBB, BodyBB);
4776LHSElementPHI->addIncoming(LHSElementNext, CGF.
Builder.GetInsertBlock());
4777RHSElementPHI->addIncoming(RHSElementNext, CGF.
Builder.GetInsertBlock());
4787 const Expr*ReductionOp) {
4788 if(
const auto*CE = dyn_cast<CallExpr>(ReductionOp))
4789 if(
const auto*OVE = dyn_cast<OpaqueValueExpr>(CE->getCallee()))
4790 if(
const auto*DRE =
4791dyn_cast<DeclRefExpr>(OVE->getSourceExpr()->IgnoreImpCasts()))
4792 if(
const auto*DRD =
4793dyn_cast<OMPDeclareReductionDecl>(DRE->getDecl())) {
4794std::pair<llvm::Function *, llvm::Function *>
Reduction=
4797CodeGenFunction::OpaqueValueMapping Map(CGF, OVE,
Func);
4816Args.push_back(&LHSArg);
4817Args.push_back(&RHSArg);
4822llvm::GlobalValue::InternalLinkage, Name,
4825Fn->setDoesNotRecurse();
4844 const auto*IPriv = Privates.begin();
4846 for(
unsignedI = 0,
E= ReductionOps.size(); I <
E; ++I, ++IPriv, ++Idx) {
4847 const auto*RHSVar =
4848cast<VarDecl>(cast<DeclRefExpr>(RHSExprs[I])->getDecl());
4850 const auto*LHSVar =
4851cast<VarDecl>(cast<DeclRefExpr>(LHSExprs[I])->getDecl());
4853 QualTypePrivTy = (*IPriv)->getType();
4861 const auto*OVE = cast<OpaqueValueExpr>(VLA->
getSizeExpr());
4868IPriv = Privates.begin();
4869 const auto*ILHS = LHSExprs.begin();
4870 const auto*IRHS = RHSExprs.begin();
4871 for(
const Expr*
E: ReductionOps) {
4872 if((*IPriv)->getType()->isArrayType()) {
4874 const auto*LHSVar = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
4875 const auto*RHSVar = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
4877CGF, (*IPriv)->getType(), LHSVar, RHSVar,
4879emitReductionCombiner(CGF, E);
4889 Scope.ForceCleanup();
4895 const Expr*ReductionOp,
4896 const Expr*PrivateRef,
4901 const auto*LHSVar = cast<VarDecl>(LHS->
getDecl());
4902 const auto*RHSVar = cast<VarDecl>(RHS->
getDecl());
4904CGF, PrivateRef->
getType(), LHSVar, RHSVar,
4906emitReductionCombiner(CGF, ReductionOp);
4923 boolWithNowait = Options.WithNowait;
4924 boolSimpleReduction = Options.SimpleReduction;
4963 if(SimpleReduction) {
4965 const auto*IPriv = Privates.begin();
4966 const auto*ILHS = LHSExprs.begin();
4967 const auto*IRHS = RHSExprs.begin();
4968 for(
const Expr*
E: ReductionOps) {
4970cast<DeclRefExpr>(*IRHS));
4980 autoSize = RHSExprs.size();
4981 for(
const Expr*
E: Privates) {
4986llvm::APInt ArraySize(
32, Size);
4987 QualTypeReductionArrayTy =
C.getConstantArrayType(
4991CGF.
CreateMemTemp(ReductionArrayTy,
".omp.reduction.red_list");
4992 const auto*IPriv = Privates.begin();
4994 for(
unsignedI = 0,
E= RHSExprs.size(); I <
E; ++I, ++IPriv, ++Idx) {
5000 if((*IPriv)->getType()->isVariablyModifiedType()) {
5004llvm::Value *Size = CGF.
Builder.CreateIntCast(
5017Privates, LHSExprs, RHSExprs, ReductionOps);
5020std::string Name =
getName({
"reduction"});
5027llvm::Value *ReductionArrayTySize = CGF.
getTypeSize(ReductionArrayTy);
5030llvm::Value *Args[] = {
5033CGF.
Builder.getInt32(RHSExprs.size()),
5034ReductionArrayTySize,
5042WithNowait ? OMPRTL___kmpc_reduce_nowait : OMPRTL___kmpc_reduce),
5046llvm::BasicBlock *DefaultBB = CGF.
createBasicBlock(
".omp.reduction.default");
5047llvm::SwitchInst *SwInst =
5048CGF.
Builder.CreateSwitch(Res, DefaultBB,
2);
5056llvm::BasicBlock *Case1BB = CGF.
createBasicBlock(
".omp.reduction.case1");
5057SwInst->addCase(CGF.
Builder.getInt32(1), Case1BB);
5061llvm::Value *EndArgs[] = {
5066 auto&&CodeGen = [Privates, LHSExprs, RHSExprs, ReductionOps](
5069 const auto*IPriv = Privates.begin();
5070 const auto*ILHS = LHSExprs.begin();
5071 const auto*IRHS = RHSExprs.begin();
5072 for(
const Expr*
E: ReductionOps) {
5074cast<DeclRefExpr>(*IRHS));
5081CommonActionTy Action(
5084 CGM.
getModule(), WithNowait ? OMPRTL___kmpc_end_reduce_nowait
5085: OMPRTL___kmpc_end_reduce),
5097llvm::BasicBlock *Case2BB = CGF.
createBasicBlock(
".omp.reduction.case2");
5098SwInst->addCase(CGF.
Builder.getInt32(2), Case2BB);
5101 auto&&AtomicCodeGen = [
Loc, Privates, LHSExprs, RHSExprs, ReductionOps](
5103 const auto*ILHS = LHSExprs.begin();
5104 const auto*IRHS = RHSExprs.begin();
5105 const auto*IPriv = Privates.begin();
5106 for(
const Expr*
E: ReductionOps) {
5107 const Expr*XExpr =
nullptr;
5108 const Expr*EExpr =
nullptr;
5109 const Expr*UpExpr =
nullptr;
5111 if(
const auto*BO = dyn_cast<BinaryOperator>(
E)) {
5112 if(BO->getOpcode() == BO_Assign) {
5113XExpr = BO->getLHS();
5114UpExpr = BO->getRHS();
5118 const Expr*RHSExpr = UpExpr;
5121 if(
const auto*ACO = dyn_cast<AbstractConditionalOperator>(
5125RHSExpr = ACO->getCond();
5127 if(
const auto*BORHS =
5129EExpr = BORHS->getRHS();
5130BO = BORHS->getOpcode();
5134 const auto*VD = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
5135 auto&&AtomicRedGen = [BO, VD,
5137 const Expr*EExpr,
const Expr*UpExpr) {
5138 LValue X= CGF.EmitLValue(XExpr);
5141 E= CGF.EmitAnyExpr(EExpr);
5142CGF.EmitOMPAtomicSimpleUpdateExpr(
5144llvm::AtomicOrdering::Monotonic,
Loc,
5145[&CGF, UpExpr, VD,
Loc](
RValueXRValue) {
5147 AddressLHSTemp = CGF.CreateMemTemp(VD->getType());
5148CGF.emitOMPSimpleStore(
5149CGF.MakeAddrLValue(LHSTemp, VD->
getType()), XRValue,
5150VD->getType().getNonReferenceType(),
Loc);
5153 returnCGF.EmitAnyExpr(UpExpr);
5156 if((*IPriv)->getType()->isArrayType()) {
5158 const auto*RHSVar =
5159cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
5161AtomicRedGen, XExpr, EExpr, UpExpr);
5164AtomicRedGen(CGF, XExpr, EExpr, UpExpr);
5171std::string Name = RT.
getName({
"atomic_reduction"});
5175Action.
Enter(CGF);
5180 if((*IPriv)->getType()->isArrayType()) {
5181 const auto*LHSVar =
5182cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
5183 const auto*RHSVar =
5184cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
5188CritRedGen(CGF,
nullptr,
nullptr,
nullptr);
5199llvm::Value *EndArgs[] = {
5204CommonActionTy Action(
nullptr, {},
5223llvm::raw_svector_ostream Out(Buffer);
5227 D= cast<VarDecl>(cast<DeclRefExpr>(Ref)->getDecl());
5231Out << Prefix << Name <<
"_" 5233 returnstd::string(Out.str());
5255Args.emplace_back(&Param);
5256Args.emplace_back(&ParamOrig);
5257 const auto&FnInfo =
5261 auto*Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
5264Fn->setDoesNotRecurse();
5270 C.getPointerType(PrivateType)->castAs<
PointerType>());
5271llvm::Value *Size =
nullptr;
5314 const Expr*ReductionOp,
5316 const Expr*PrivateRef) {
5318 const auto*LHSVD = cast<VarDecl>(cast<DeclRefExpr>(LHS)->getDecl());
5319 const auto*RHSVD = cast<VarDecl>(cast<DeclRefExpr>(RHS)->getDecl());
5325Args.emplace_back(&ParamInOut);
5326Args.emplace_back(&ParamIn);
5327 const auto&FnInfo =
5331 auto*Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
5334Fn->setDoesNotRecurse();
5337llvm::Value *Size =
nullptr;
5351CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
5352PrivateScope.addPrivate(
5358 C.getPointerType(LHSVD->getType())->castAs<
PointerType>()));
5359PrivateScope.addPrivate(
5365 C.getPointerType(RHSVD->getType())->castAs<
PointerType>()));
5366PrivateScope.Privatize();
5371CGF, ReductionOp, PrivateRef, cast<DeclRefExpr>(LHS),
5372cast<DeclRefExpr>(RHS));
5394Args.emplace_back(&Param);
5395 const auto&FnInfo =
5399 auto*Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
5402Fn->setDoesNotRecurse();
5407llvm::Value *Size =
nullptr;
5442 RecordDecl*RD =
C.buildImplicitRecord(
"kmp_taskred_input_t");
5451 C, RD,
C.getIntTypeForBitwidth(
32,
false));
5454 unsignedSize =
Data.ReductionVars.size();
5455llvm::APInt ArraySize(
64, Size);
5457 C.getConstantArrayType(RDType, ArraySize,
nullptr,
5462 Data.ReductionCopies,
Data.ReductionOps);
5463 for(
unsignedCnt = 0; Cnt < Size; ++Cnt) {
5465llvm::Value *Idxs[] = {llvm::ConstantInt::get(
CGM.
SizeTy,
0),
5466llvm::ConstantInt::get(
CGM.
SizeTy, Cnt)};
5469 false,
false,
Loc,
5482llvm::Value *SizeValInChars;
5483llvm::Value *SizeVal;
5484std::tie(SizeValInChars, SizeVal) = RCG.
getSizes(Cnt);
5490 boolDelayedCreation = !!SizeVal;
5491SizeValInChars = CGF.
Builder.CreateIntCast(SizeValInChars,
CGM.
SizeTy,
5502llvm::Value *FiniAddr =
5503Fini ? Fini : llvm::ConstantPointerNull::get(
CGM.
VoidPtrTy);
5508 CGM,
Loc, RCG, Cnt,
Data.ReductionOps[Cnt], LHSExprs[Cnt],
5509RHSExprs[Cnt],
Data.ReductionCopies[Cnt]);
5513 if(DelayedCreation) {
5515llvm::ConstantInt::get(
CGM.
Int32Ty,
1,
true),
5520 if(
Data.IsReductionWithTaskMod) {
5526llvm::Value *Args[] = {
5528llvm::ConstantInt::get(
CGM.
IntTy,
Data.IsWorksharingReduction ? 1 : 0,
5530llvm::ConstantInt::get(
CGM.
IntTy, Size,
true),
5535 CGM.
getModule(), OMPRTL___kmpc_taskred_modifier_init),
5539llvm::Value *Args[] = {
5542llvm::ConstantInt::get(
CGM.
IntTy, Size,
true),
5552 boolIsWorksharingReduction) {
5558llvm::Value *Args[] = {IdentTLoc, GTid,
5559llvm::ConstantInt::get(
CGM.
IntTy,
5560IsWorksharingReduction ? 1 : 0,
5564 CGM.
getModule(), OMPRTL___kmpc_task_reduction_modifier_fini),
5576llvm::Value *SizeVal = CGF.
Builder.CreateIntCast(Sizes.second,
CGM.
SizeTy,
5587llvm::Value *ReductionsPtr,
5600 CGM.
getModule(), OMPRTL___kmpc_task_reduction_get_th_data),
5618llvm::Value *NumOfElements;
5619std::tie(NumOfElements, DependenciesArray) =
5621 if(!
Data.Dependences.empty()) {
5622llvm::Value *DepWaitTaskArgs[7];
5623DepWaitTaskArgs[0] = UpLoc;
5624DepWaitTaskArgs[1] = ThreadID;
5625DepWaitTaskArgs[2] = NumOfElements;
5627DepWaitTaskArgs[4] = CGF.
Builder.getInt32(0);
5628DepWaitTaskArgs[5] = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
5629DepWaitTaskArgs[6] =
5630llvm::ConstantInt::get(CGF.
Int32Ty,
Data.HasNowaitClause);
5639M, OMPRTL___kmpc_omp_taskwait_deps_51),
5646llvm::Value *Args[] = {UpLoc, ThreadID};
5649 OMPBuilder.getOrCreateRuntimeFunction(M, OMPRTL___kmpc_omp_taskwait),
5654 if(
auto*Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.
CapturedStmtInfo))
5655Region->emitUntiedSwitch(CGF);
5664InlinedOpenMPRegionRAII Region(CGF, CodeGen, InnerKind, HasCancel,
5665InnerKind != OMPD_critical &&
5666InnerKind != OMPD_master &&
5667InnerKind != OMPD_masked);
5682RTCancelKind CancelKind = CancelNoreq;
5683 if(CancelRegion == OMPD_parallel)
5684CancelKind = CancelParallel;
5685 else if(CancelRegion == OMPD_for)
5686CancelKind = CancelLoop;
5687 else if(CancelRegion == OMPD_sections)
5688CancelKind = CancelSections;
5690assert(CancelRegion == OMPD_taskgroup);
5691CancelKind = CancelTaskgroup;
5703 if(
auto*OMPRegionInfo =
5707 if(CancelRegion == OMPD_taskgroup || OMPRegionInfo->hasCancel()) {
5708llvm::Value *Args[] = {
5723CGF.
Builder.CreateCondBr(Cmp, ExitBB, ContBB);
5725 if(CancelRegion == OMPD_parallel)
5744 if(
auto*OMPRegionInfo =
5746 auto&&ThenGen = [
this, &M,
Loc, CancelRegion,
5749llvm::Value *Args[] = {
5753llvm::Value *
Result= CGF.EmitRuntimeCall(
5754 OMPBuilder.getOrCreateRuntimeFunction(M, OMPRTL___kmpc_cancel), Args);
5759llvm::BasicBlock *ExitBB = CGF.createBasicBlock(
".cancel.exit");
5760llvm::BasicBlock *ContBB = CGF.createBasicBlock(
".cancel.continue");
5761llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(
Result);
5762CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB);
5763CGF.EmitBlock(ExitBB);
5764 if(CancelRegion == OMPD_parallel)
5768CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind());
5769CGF.EmitBranchThroughCleanup(CancelDest);
5770CGF.EmitBlock(ContBB,
true);
5788OMPUsesAllocatorsActionTy(
5789 ArrayRef<std::pair<const Expr *, const Expr *>> Allocators)
5790: Allocators(Allocators) {}
5794 for(
const auto&AllocatorData : Allocators) {
5796CGF, AllocatorData.first, AllocatorData.second);
5802 for(
const auto&AllocatorData : Allocators) {
5804AllocatorData.first);
5812llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
5814assert(!ParentName.empty() &&
"Invalid target entry parent name!");
5818 for(
unsignedI = 0,
E=
C->getNumberOfAllocators(); I <
E; ++I) {
5820 if(!
D.AllocatorTraits)
5822Allocators.emplace_back(
D.Allocator,
D.AllocatorTraits);
5825OMPUsesAllocatorsActionTy UsesAllocatorAction(Allocators);
5826CodeGen.
setAction(UsesAllocatorAction);
5828IsOffloadEntry, CodeGen);
5832 const Expr*Allocator,
5833 const Expr*AllocatorTraits) {
5834llvm::Value *ThreadId =
getThreadID(CGF, Allocator->getExprLoc());
5835ThreadId = CGF.
Builder.CreateIntCast(ThreadId, CGF.
IntTy,
true);
5837llvm::Value *MemSpaceHandle = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
5838llvm::Value *NumTraits = llvm::ConstantInt::get(
5839CGF.
IntTy, cast<ConstantArrayType>(
5842.getLimitedValue());
5851llvm::Value *AllocatorVal =
5854{ThreadId, MemSpaceHandle, NumTraits, Traits});
5857cast<DeclRefExpr>(Allocator->IgnoreParenImpCasts())->getDecl()));
5861Allocator->getType(), Allocator->getExprLoc());
5866 const Expr*Allocator) {
5867llvm::Value *ThreadId =
getThreadID(CGF, Allocator->getExprLoc());
5868ThreadId = CGF.
Builder.CreateIntCast(ThreadId, CGF.
IntTy,
true);
5870llvm::Value *AllocatorVal =
5874Allocator->getExprLoc());
5877OMPRTL___kmpc_destroy_allocator),
5878{ThreadId, AllocatorVal});
5883llvm::OpenMPIRBuilder::TargetKernelDefaultAttrs &Attrs) {
5884assert(Attrs.MaxTeams.size() == 1 && Attrs.MaxThreads.size() == 1 &&
5885 "invalid default attrs structure");
5886int32_t &MaxTeamsVal = Attrs.MaxTeams.front();
5887int32_t &MaxThreadsVal = Attrs.MaxThreads.front();
5894 for(
auto*A :
C->getAttrs()) {
5895int32_t AttrMinThreadsVal = 1, AttrMaxThreadsVal = -1;
5896int32_t AttrMinBlocksVal = 1, AttrMaxBlocksVal = -1;
5897 if(
auto*
Attr= dyn_cast<CUDALaunchBoundsAttr>(A))
5899&AttrMinBlocksVal, &AttrMaxBlocksVal);
5900 else if(
auto*
Attr= dyn_cast<AMDGPUFlatWorkGroupSizeAttr>(A))
5902 nullptr,
Attr,
nullptr, &AttrMinThreadsVal,
5903&AttrMaxThreadsVal);
5907Attrs.MinThreads = std::max(Attrs.MinThreads, AttrMinThreadsVal);
5908 if(AttrMaxThreadsVal > 0)
5909MaxThreadsVal = MaxThreadsVal > 0
5910? std::min(MaxThreadsVal, AttrMaxThreadsVal)
5911: AttrMaxThreadsVal;
5912Attrs.MinTeams = std::max(Attrs.MinTeams, AttrMinBlocksVal);
5913 if(AttrMaxBlocksVal > 0)
5914MaxTeamsVal = MaxTeamsVal > 0 ? std::min(MaxTeamsVal, AttrMaxBlocksVal)
5922llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
5925llvm::TargetRegionEntryInfo EntryInfo =
5929llvm::OpenMPIRBuilder::FunctionGenCallback &&GenerateOutlinedFunction =
5930[&CGF, &
D, &CodeGen](StringRef EntryFnName) {
5933CGOpenMPTargetRegionInfo CGInfo(CS, CodeGen, EntryFnName);
5938cantFail(
OMPBuilder.emitTargetRegionFunction(
5939EntryInfo, GenerateOutlinedFunction, IsOffloadEntry, OutlinedFn,
5948 for(
auto*A :
C->getAttrs()) {
5949 if(
auto*
Attr= dyn_cast<AMDGPUWavesPerEUAttr>(A))
5968 while(
const auto*
C= dyn_cast_or_null<CompoundStmt>(Child)) {
5970 for(
const Stmt*S :
C->body()) {
5971 if(
const auto*
E= dyn_cast<Expr>(S)) {
5976 if(isa<AsmStmt>(S) || isa<NullStmt>(S) || isa<OMPFlushDirective>(S) ||
5977isa<OMPBarrierDirective>(S) || isa<OMPTaskyieldDirective>(S))
5980 if(
const auto*DS = dyn_cast<DeclStmt>(S)) {
5981 if(llvm::all_of(DS->decls(), [](
const Decl*
D) {
5982if (isa<EmptyDecl>(D) || isa<DeclContext>(D) ||
5983isa<TypeDecl>(D) || isa<PragmaCommentDecl>(D) ||
5984isa<PragmaDetectMismatchDecl>(D) || isa<UsingDecl>(D) ||
5985isa<UsingDirectiveDecl>(D) ||
5986isa<OMPDeclareReductionDecl>(D) ||
5987isa<OMPThreadPrivateDecl>(D) || isa<OMPAllocateDecl>(D))
5989const auto *VD = dyn_cast<VarDecl>(D);
5992return VD->hasGlobalStorage() || !VD->isUsed();
6002Child = Child->IgnoreContainers();
6009int32_t &MaxTeamsVal) {
6013 "Expected target-based executable directive.");
6014 switch(DirectiveKind) {
6016 const auto*CS =
D.getInnermostCapturedStmt();
6019 const Stmt*ChildStmt =
6021 if(
const auto*NestedDir =
6022dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) {
6029 if(
autoConstant =
6031MinTeamsVal = MaxTeamsVal = Constant->getExtValue();
6034MinTeamsVal = MaxTeamsVal = 0;
6037MinTeamsVal = MaxTeamsVal = 1;
6041MinTeamsVal = MaxTeamsVal = -1;
6044 caseOMPD_target_teams_loop:
6045 caseOMPD_target_teams:
6046 caseOMPD_target_teams_distribute:
6047 caseOMPD_target_teams_distribute_simd:
6048 caseOMPD_target_teams_distribute_parallel_for:
6049 caseOMPD_target_teams_distribute_parallel_for_simd: {
6051 const Expr*NumTeams =
6055MinTeamsVal = MaxTeamsVal = Constant->getExtValue();
6058MinTeamsVal = MaxTeamsVal = 0;
6061 caseOMPD_target_parallel:
6062 caseOMPD_target_parallel_for:
6063 caseOMPD_target_parallel_for_simd:
6064 caseOMPD_target_parallel_loop:
6065 caseOMPD_target_simd:
6066MinTeamsVal = MaxTeamsVal = 1;
6070 caseOMPD_parallel_for:
6071 caseOMPD_parallel_loop:
6072 caseOMPD_parallel_master:
6073 caseOMPD_parallel_sections:
6075 caseOMPD_parallel_for_simd:
6077 caseOMPD_cancellation_point:
6079 caseOMPD_threadprivate:
6090 caseOMPD_taskyield:
6093 caseOMPD_taskgroup:
6099 caseOMPD_target_data:
6100 caseOMPD_target_exit_data:
6101 caseOMPD_target_enter_data:
6102 caseOMPD_distribute:
6103 caseOMPD_distribute_simd:
6104 caseOMPD_distribute_parallel_for:
6105 caseOMPD_distribute_parallel_for_simd:
6106 caseOMPD_teams_distribute:
6107 caseOMPD_teams_distribute_simd:
6108 caseOMPD_teams_distribute_parallel_for:
6109 caseOMPD_teams_distribute_parallel_for_simd:
6110 caseOMPD_target_update:
6111 caseOMPD_declare_simd:
6112 caseOMPD_declare_variant:
6113 caseOMPD_begin_declare_variant:
6114 caseOMPD_end_declare_variant:
6115 caseOMPD_declare_target:
6116 caseOMPD_end_declare_target:
6117 caseOMPD_declare_reduction:
6118 caseOMPD_declare_mapper:
6120 caseOMPD_taskloop_simd:
6121 caseOMPD_master_taskloop:
6122 caseOMPD_master_taskloop_simd:
6123 caseOMPD_parallel_master_taskloop:
6124 caseOMPD_parallel_master_taskloop_simd:
6126 caseOMPD_metadirective:
6132llvm_unreachable(
"Unexpected directive kind.");
6137assert(!CGF.
getLangOpts().OpenMPIsTargetDevice &&
6138 "Clauses associated with the teams directive expected to be emitted " 6139 "only for the host!");
6141int32_t MinNT = -1, MaxNT = -1;
6142 const Expr*NumTeams =
6144 if(NumTeams !=
nullptr) {
6147 switch(DirectiveKind) {
6149 const auto*CS =
D.getInnermostCapturedStmt();
6150CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6154 returnBld.CreateIntCast(NumTeamsVal, CGF.
Int32Ty,
6157 caseOMPD_target_teams:
6158 caseOMPD_target_teams_distribute:
6159 caseOMPD_target_teams_distribute_simd:
6160 caseOMPD_target_teams_distribute_parallel_for:
6161 caseOMPD_target_teams_distribute_parallel_for_simd: {
6165 returnBld.CreateIntCast(NumTeamsVal, CGF.
Int32Ty,
6173assert(MinNT == MaxNT &&
"Num threads ranges require handling here.");
6174 returnllvm::ConstantInt::get(CGF.
Int32Ty, MinNT);
6182 const Expr**
E, int32_t &UpperBound,
6183 boolUpperBoundOnly, llvm::Value **CondVal) {
6186 const auto*Dir = dyn_cast_or_null<OMPExecutableDirective>(Child);
6193 if(CondVal && Dir->hasClausesOfKind<
OMPIfClause>()) {
6194CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6195CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
6197 for(
const auto*
C: Dir->getClausesOfKind<
OMPIfClause>()) {
6198 if(
C->getNameModifier() == OMPD_unknown ||
6199 C->getNameModifier() == OMPD_parallel) {
6214 if(
const auto*PreInit =
6216 for(
const auto*I : PreInit->decls()) {
6217 if(!I->hasAttr<OMPCaptureNoInitAttr>()) {
6220CodeGenFunction::AutoVarEmission Emission =
6233CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6234CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
6235 const auto*NumThreadsClause =
6237 const Expr*NTExpr = NumThreadsClause->getNumThreads();
6238 if(NTExpr->isIntegerConstantExpr(CGF.
getContext()))
6239 if(
autoConstant = NTExpr->getIntegerConstantExpr(CGF.
getContext()))
6242? Constant->getZExtValue()
6243: std::min(UpperBound,
6244 static_cast<int32_t
>(Constant->getZExtValue()));
6247 if(UpperBound == -1)
6251CodeGenFunction::LexicalScope
Scope(CGF, NTExpr->getSourceRange());
6252 if(
const auto*PreInit =
6253cast_or_null<DeclStmt>(NumThreadsClause->getPreInitStmt())) {
6254 for(
const auto*I : PreInit->decls()) {
6255 if(!I->hasAttr<OMPCaptureNoInitAttr>()) {
6258CodeGenFunction::AutoVarEmission Emission =
6274 boolUpperBoundOnly, llvm::Value **CondVal,
const Expr**ThreadLimitExpr) {
6275assert((!CGF.
getLangOpts().OpenMPIsTargetDevice || UpperBoundOnly) &&
6276 "Clauses associated with the teams directive expected to be emitted " 6277 "only for the host!");
6280 "Expected target-based executable directive.");
6282 const Expr*NT =
nullptr;
6283 const Expr**NTPtr = UpperBoundOnly ? nullptr : &NT;
6285 autoCheckForConstExpr = [&](
const Expr*
E,
const Expr**EPtr) {
6288UpperBound = UpperBound ? Constant->getZExtValue()
6289: std::min(UpperBound,
6290int32_t(Constant->getZExtValue()));
6294 if(UpperBound == -1)
6300 autoReturnSequential = [&]() {
6305 switch(DirectiveKind) {
6308 getNumThreads(CGF, CS, NTPtr, UpperBound, UpperBoundOnly, CondVal);
6314 if(
const auto*Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) {
6316ThreadLimitClause = TLC;
6317 if(ThreadLimitExpr) {
6318CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6322ThreadLimitClause->getThreadLimit().front()->getSourceRange());
6323 if(
const auto*PreInit =
6324cast_or_null<DeclStmt>(ThreadLimitClause->getPreInitStmt())) {
6325 for(
const auto*I : PreInit->decls()) {
6326 if(!I->hasAttr<OMPCaptureNoInitAttr>()) {
6338 if(ThreadLimitClause)
6339CheckForConstExpr(ThreadLimitClause->getThreadLimit().front(),
6341 if(
const auto*Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) {
6344CS = Dir->getInnermostCapturedStmt();
6347Dir = dyn_cast_or_null<OMPExecutableDirective>(Child);
6350CS = Dir->getInnermostCapturedStmt();
6351 getNumThreads(CGF, CS, NTPtr, UpperBound, UpperBoundOnly, CondVal);
6353 returnReturnSequential();
6357 caseOMPD_target_teams: {
6361CheckForConstExpr(ThreadLimitClause->getThreadLimit().front(),
6365 getNumThreads(CGF, CS, NTPtr, UpperBound, UpperBoundOnly, CondVal);
6368 if(
const auto*Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) {
6369 if(Dir->getDirectiveKind() == OMPD_distribute) {
6370CS = Dir->getInnermostCapturedStmt();
6371 getNumThreads(CGF, CS, NTPtr, UpperBound, UpperBoundOnly, CondVal);
6376 caseOMPD_target_teams_distribute:
6380CheckForConstExpr(ThreadLimitClause->getThreadLimit().front(),
6383 getNumThreads(CGF,
D.getInnermostCapturedStmt(), NTPtr, UpperBound,
6384UpperBoundOnly, CondVal);
6386 caseOMPD_target_teams_loop:
6387 caseOMPD_target_parallel_loop:
6388 caseOMPD_target_parallel:
6389 caseOMPD_target_parallel_for:
6390 caseOMPD_target_parallel_for_simd:
6391 caseOMPD_target_teams_distribute_parallel_for:
6392 caseOMPD_target_teams_distribute_parallel_for_simd: {
6395 for(
const auto*
C:
D.getClausesOfKind<
OMPIfClause>()) {
6396 if(
C->getNameModifier() == OMPD_unknown ||
6397 C->getNameModifier() == OMPD_parallel) {
6407 returnReturnSequential();
6417CheckForConstExpr(ThreadLimitClause->getThreadLimit().front(),
6423CheckForConstExpr(NumThreadsClause->getNumThreads(),
nullptr);
6424 returnNumThreadsClause->getNumThreads();
6428 caseOMPD_target_teams_distribute_simd:
6429 caseOMPD_target_simd:
6430 returnReturnSequential();
6434llvm_unreachable(
"Unsupported directive kind.");
6439llvm::Value *NumThreadsVal =
nullptr;
6440llvm::Value *CondVal =
nullptr;
6441llvm::Value *ThreadLimitVal =
nullptr;
6442 const Expr*ThreadLimitExpr =
nullptr;
6443int32_t UpperBound = -1;
6446CGF,
D, UpperBound,
false, &CondVal,
6450 if(ThreadLimitExpr) {
6453ThreadLimitVal = CGF.
Builder.CreateIntCast(ThreadLimitVal, CGF.
Int32Ty,
6458 if(UpperBound == 1) {
6459NumThreadsVal = CGF.
Builder.getInt32(UpperBound);
6462NumThreadsVal = CGF.
Builder.CreateIntCast(NumThreadsVal, CGF.
Int32Ty,
6464}
else if(ThreadLimitVal) {
6467NumThreadsVal = ThreadLimitVal;
6468ThreadLimitVal =
nullptr;
6471assert(!ThreadLimitVal &&
"Default not applicable with thread limit value");
6472NumThreadsVal = CGF.
Builder.getInt32(0);
6479NumThreadsVal = CGF.
Builder.CreateSelect(CondVal, NumThreadsVal,
6485 if(ThreadLimitVal) {
6486NumThreadsVal = CGF.
Builder.CreateSelect(
6487CGF.
Builder.CreateICmpULT(ThreadLimitVal, NumThreadsVal),
6488ThreadLimitVal, NumThreadsVal);
6491 returnNumThreadsVal;
6501classMappableExprsHandler {
6504 static unsignedgetFlagMemberOffset() {
6505 unsignedOffset = 0;
6506 for(uint64_t Remain =
6507 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
6508OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF);
6509!(Remain & 1); Remain = Remain >> 1)
6516 classMappingExprInfo {
6521 const Expr*MapExpr =
nullptr;
6524MappingExprInfo(
const ValueDecl*MapDecl,
const Expr*MapExpr =
nullptr)
6525: MapDecl(MapDecl), MapExpr(MapExpr) {}
6527 const ValueDecl*getMapDecl()
const{
returnMapDecl; }
6528 const Expr*getMapExpr()
const{
returnMapExpr; }
6531 usingDeviceInfoTy = llvm::OpenMPIRBuilder::DeviceInfoTy;
6532 usingMapBaseValuesArrayTy = llvm::OpenMPIRBuilder::MapValuesArrayTy;
6533 usingMapValuesArrayTy = llvm::OpenMPIRBuilder::MapValuesArrayTy;
6534 usingMapFlagsArrayTy = llvm::OpenMPIRBuilder::MapFlagsArrayTy;
6535 usingMapDimArrayTy = llvm::OpenMPIRBuilder::MapDimArrayTy;
6536 usingMapNonContiguousArrayTy =
6537llvm::OpenMPIRBuilder::MapNonContiguousArrayTy;
6544 structMapCombinedInfoTy : llvm::OpenMPIRBuilder::MapInfosTy {
6545MapExprsArrayTy Exprs;
6546MapValueDeclsArrayTy Mappers;
6547MapValueDeclsArrayTy DevicePtrDecls;
6550 voidappend(MapCombinedInfoTy &CurInfo) {
6551Exprs.append(CurInfo.Exprs.begin(), CurInfo.Exprs.end());
6552DevicePtrDecls.append(CurInfo.DevicePtrDecls.begin(),
6553CurInfo.DevicePtrDecls.end());
6554Mappers.append(CurInfo.Mappers.begin(), CurInfo.Mappers.end());
6555llvm::OpenMPIRBuilder::MapInfosTy::append(CurInfo);
6563 structStructRangeInfoTy {
6564MapCombinedInfoTy PreliminaryMapData;
6565std::pair<
unsigned,
Address> LowestElem = {
6567std::pair<
unsigned,
Address> HighestElem = {
6571 boolIsArraySection =
false;
6572 boolHasCompleteRecord =
false;
6582 boolReturnDevicePointer =
false;
6583 boolIsImplicit =
false;
6585 const Expr*VarRef =
nullptr;
6586 boolForDeviceAddr =
false;
6588MapInfo() =
default;
6594 boolReturnDevicePointer,
boolIsImplicit,
6595 const ValueDecl*Mapper =
nullptr,
const Expr*VarRef =
nullptr,
6596 boolForDeviceAddr =
false)
6597: Components(Components), MapType(MapType), MapModifiers(MapModifiers),
6598MotionModifiers(MotionModifiers),
6599ReturnDevicePointer(ReturnDevicePointer), IsImplicit(IsImplicit),
6600Mapper(Mapper), VarRef(VarRef), ForDeviceAddr(ForDeviceAddr) {}
6606 structDeferredDevicePtrEntryTy {
6607 const Expr*IE =
nullptr;
6609 boolForDeviceAddr =
false;
6611DeferredDevicePtrEntryTy(
const Expr*IE,
const ValueDecl*VD,
6613: IE(IE), VD(VD), ForDeviceAddr(ForDeviceAddr) {}
6628llvm::DenseMap<CanonicalDeclPtr<const VarDecl>,
bool> FirstPrivateDecls;
6645llvm::DenseMap<const ValueDecl *, const OMPMapClause *> LambdasMap;
6647llvm::Value *getExprTypeSize(
const Expr*
E)
const{
6651 if(
const auto*OAE = dyn_cast<OMPArrayShapingExpr>(
E)) {
6652llvm::Value *
Size=
6653CGF.
getTypeSize(OAE->getBase()->getType()->getPointeeType());
6654 for(
const Expr*SE : OAE->getDimensions()) {
6671 if(
const auto*OAE = dyn_cast<ArraySectionExpr>(
E)) {
6673OAE->getBase()->IgnoreParenImpCasts())
6679 if(!OAE->getLength() && OAE->getColonLocFirst().isValid() &&
6680!OAE->getLowerBound())
6683llvm::Value *ElemSize;
6685ElemSize = CGF.
getTypeSize(PTy->getPointeeType().getCanonicalType());
6687 const auto*ATy = cast<ArrayType>(BaseTy.
getTypePtr());
6688assert(ATy &&
"Expecting array type if not a pointer type.");
6689ElemSize = CGF.
getTypeSize(ATy->getElementType().getCanonicalType());
6694 if(!OAE->getLength() && OAE->getColonLocFirst().isInvalid())
6697 if(
const Expr*LenExpr = OAE->getLength()) {
6701LenExpr->getExprLoc());
6702 returnCGF.
Builder.CreateNUWMul(LengthVal, ElemSize);
6704assert(!OAE->getLength() && OAE->getColonLocFirst().isValid() &&
6705OAE->getLowerBound() &&
"expected array_section[lb:].");
6707llvm::Value *LengthVal = CGF.
getTypeSize(BaseTy);
6711OAE->getLowerBound()->getExprLoc());
6712LBVal = CGF.
Builder.CreateNUWMul(LBVal, ElemSize);
6713llvm::Value *Cmp = CGF.
Builder.CreateICmpUGT(LengthVal, LBVal);
6714llvm::Value *TrueVal = CGF.
Builder.CreateNUWSub(LengthVal, LBVal);
6715LengthVal = CGF.
Builder.CreateSelect(
6716Cmp, TrueVal, llvm::ConstantInt::get(CGF.
SizeTy, 0));
6726OpenMPOffloadMappingFlags getMapTypeBits(
6729 boolAddPtrFlag,
boolAddIsTargetParamFlag,
boolIsNonContiguous)
const{
6730OpenMPOffloadMappingFlags Bits =
6731IsImplicit ? OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT
6732: OpenMPOffloadMappingFlags::OMP_MAP_NONE;
6734 caseOMPC_MAP_alloc:
6735 caseOMPC_MAP_release:
6742Bits |= OpenMPOffloadMappingFlags::OMP_MAP_TO;
6745Bits |= OpenMPOffloadMappingFlags::OMP_MAP_FROM;
6747 caseOMPC_MAP_tofrom:
6748Bits |= OpenMPOffloadMappingFlags::OMP_MAP_TO |
6749OpenMPOffloadMappingFlags::OMP_MAP_FROM;
6751 caseOMPC_MAP_delete:
6752Bits |= OpenMPOffloadMappingFlags::OMP_MAP_DELETE;
6755llvm_unreachable(
"Unexpected map type!");
6758Bits |= OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ;
6759 if(AddIsTargetParamFlag)
6760Bits |= OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM;
6761 if(llvm::is_contained(MapModifiers, OMPC_MAP_MODIFIER_always))
6762Bits |= OpenMPOffloadMappingFlags::OMP_MAP_ALWAYS;
6763 if(llvm::is_contained(MapModifiers, OMPC_MAP_MODIFIER_close))
6764Bits |= OpenMPOffloadMappingFlags::OMP_MAP_CLOSE;
6765 if(llvm::is_contained(MapModifiers, OMPC_MAP_MODIFIER_present) ||
6766llvm::is_contained(MotionModifiers, OMPC_MOTION_MODIFIER_present))
6767Bits |= OpenMPOffloadMappingFlags::OMP_MAP_PRESENT;
6768 if(llvm::is_contained(MapModifiers, OMPC_MAP_MODIFIER_ompx_hold))
6769Bits |= OpenMPOffloadMappingFlags::OMP_MAP_OMPX_HOLD;
6770 if(IsNonContiguous)
6771Bits |= OpenMPOffloadMappingFlags::OMP_MAP_NON_CONTIG;
6777 boolisFinalArraySectionExpression(
const Expr*
E)
const{
6778 const auto*OASE = dyn_cast<ArraySectionExpr>(
E);
6785 if(OASE->getColonLocFirst().isInvalid())
6788 const Expr*Length = OASE->getLength();
6795OASE->getBase()->IgnoreParenImpCasts())
6797 if(
const auto*ATy = dyn_cast<ConstantArrayType>(BaseQTy.
getTypePtr()))
6798 returnATy->getSExtSize() != 1;
6807 if(!Length->EvaluateAsInt(Result, CGF.
getContext()))
6810llvm::APSInt ConstLength = Result.Val.getInt();
6811 returnConstLength.getSExtValue() != 1;
6819 voidgenerateInfoForComponentList(
6823MapCombinedInfoTy &CombinedInfo,
6824MapCombinedInfoTy &StructBaseCombinedInfo,
6825StructRangeInfoTy &PartialStruct,
boolIsFirstComponentList,
6826 boolIsImplicit,
boolGenerateAllInfoForClauses,
6827 const ValueDecl*Mapper =
nullptr,
boolForDeviceAddr =
false,
6828 const ValueDecl*BaseDecl =
nullptr,
const Expr*MapExpr =
nullptr,
6830OverlappedElements = {},
6831 boolAreBothBasePtrAndPteeMapped =
false)
const{
7013 boolIsCaptureFirstInfo = IsFirstComponentList;
7017 boolRequiresReference =
false;
7020 autoCI = Components.rbegin();
7021 autoCE = Components.rend();
7026 boolIsExpressionFirstInfo =
true;
7027 boolFirstPointerInComplexData =
false;
7029 const Expr*AssocExpr = I->getAssociatedExpression();
7030 const auto*AE = dyn_cast<ArraySubscriptExpr>(AssocExpr);
7031 const auto*OASE = dyn_cast<ArraySectionExpr>(AssocExpr);
7032 const auto*OAShE = dyn_cast<OMPArrayShapingExpr>(AssocExpr);
7034 if(AreBothBasePtrAndPteeMapped && std::next(I) == CE)
7036 if(isa<MemberExpr>(AssocExpr)) {
7040}
else if((AE && isa<CXXThisExpr>(AE->getBase()->IgnoreParenImpCasts())) ||
7042isa<CXXThisExpr>(OASE->getBase()->IgnoreParenImpCasts()))) {
7045isa<CXXThisExpr>(OAShE->getBase()->IgnoreParenCasts())) {
7054 if(
const auto*VD =
7055dyn_cast_or_null<VarDecl>(I->getAssociatedDeclaration())) {
7056 if(std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
7057OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD)) {
7058 if((*Res == OMPDeclareTargetDeclAttr::MT_Link) ||
7059((*Res == OMPDeclareTargetDeclAttr::MT_To ||
7060*Res == OMPDeclareTargetDeclAttr::MT_Enter) &&
7062RequiresReference =
true;
7072I->getAssociatedDeclaration()->getType().getNonReferenceType();
7077 const auto*VD = dyn_cast<VarDecl>(I->getAssociatedDeclaration());
7078 if(!AreBothBasePtrAndPteeMapped &&
7083FirstPointerInComplexData =
true;
7102 boolShouldBeMemberOf =
false;
7117 boolIsNonContiguous = CombinedInfo.NonContigInfo.IsNonContiguous;
7118 boolIsPrevMemberReference =
false;
7120 boolIsPartialMapped =
7121!PartialStruct.PreliminaryMapData.BasePointers.empty();
7128 boolIsMappingWholeStruct =
true;
7129 if(!GenerateAllInfoForClauses) {
7130IsMappingWholeStruct =
false;
7132 for(
autoTempI = I; TempI != CE; ++TempI) {
7134dyn_cast<MemberExpr>(TempI->getAssociatedExpression());
7136IsMappingWholeStruct =
false;
7142 for(; I != CE; ++I) {
7144 if(!EncounteredME) {
7145EncounteredME = dyn_cast<MemberExpr>(I->getAssociatedExpression());
7148 if(EncounteredME) {
7149ShouldBeMemberOf =
true;
7152 if(FirstPointerInComplexData) {
7154->getAssociatedDeclaration()
7156.getNonReferenceType();
7158FirstPointerInComplexData =
false;
7163 autoNext = std::next(I);
7173 boolIsFinalArraySection =
7175isFinalArraySectionExpression(I->getAssociatedExpression());
7179 const ValueDecl*MapDecl = (I->getAssociatedDeclaration())
7180? I->getAssociatedDeclaration()
7182MapExpr = (I->getAssociatedExpression()) ? I->getAssociatedExpression()
7189dyn_cast<ArraySectionExpr>(I->getAssociatedExpression());
7191dyn_cast<OMPArrayShapingExpr>(I->getAssociatedExpression());
7192 const auto*UO = dyn_cast<UnaryOperator>(I->getAssociatedExpression());
7193 const auto*BO = dyn_cast<BinaryOperator>(I->getAssociatedExpression());
7199I->getAssociatedExpression()->getType()->isAnyPointerType();
7200 boolIsMemberReference = isa<MemberExpr>(I->getAssociatedExpression()) &&
7203 boolIsNonDerefPointer = IsPointer &&
7204!(UO && UO->getOpcode() != UO_Deref) && !BO &&
7210 if(Next == CE || IsMemberReference || IsNonDerefPointer ||
7211IsFinalArraySection) {
7214assert((Next == CE ||
7215isa<MemberExpr>(Next->getAssociatedExpression()) ||
7216isa<ArraySubscriptExpr>(Next->getAssociatedExpression()) ||
7217isa<ArraySectionExpr>(Next->getAssociatedExpression()) ||
7218isa<OMPArrayShapingExpr>(Next->getAssociatedExpression()) ||
7219isa<UnaryOperator>(Next->getAssociatedExpression()) ||
7220isa<BinaryOperator>(Next->getAssociatedExpression())) &&
7221 "Unexpected expression");
7227 const Expr*BaseExpr =
E->getBase();
7231 if(
E->isArrow()) {
7247OAShE->getBase()->getType()->getPointeeType()),
7249OAShE->getBase()->getType()));
7250}
else if(IsMemberReference) {
7251 const auto*ME = cast<MemberExpr>(I->getAssociatedExpression());
7252 LValueBaseLVal = EmitMemberExprBase(CGF, ME);
7254BaseLVal, cast<FieldDecl>(MapDecl))
7267 boolIsMemberPointerOrAddr =
7269(((IsPointer || ForDeviceAddr) &&
7270I->getAssociatedExpression() == EncounteredME) ||
7271(IsPrevMemberReference && !IsPointer) ||
7272(IsMemberReference && Next != CE &&
7273!Next->getAssociatedExpression()->getType()->isPointerType()));
7274 if(!OverlappedElements.empty() && Next == CE) {
7276assert(!PartialStruct.Base.isValid() &&
"The base element is set.");
7277assert(!IsPointer &&
7278 "Unexpected base element with the pointer type.");
7281PartialStruct.LowestElem = {0, LowestElem};
7283I->getAssociatedExpression()->getType());
7288PartialStruct.HighestElem = {
7289std::numeric_limits<
decltype(
7290PartialStruct.HighestElem.first)>
::max(),
7292PartialStruct.Base = BP;
7293PartialStruct.LB = LB;
7295PartialStruct.PreliminaryMapData.BasePointers.empty() &&
7296 "Overlapped elements must be used only once for the variable.");
7297std::swap(PartialStruct.PreliminaryMapData, CombinedInfo);
7299OpenMPOffloadMappingFlags Flags =
7300OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF |
7301getMapTypeBits(MapType, MapModifiers, MotionModifiers, IsImplicit,
7303 false, IsNonContiguous);
7304llvm::Value *
Size=
nullptr;
7307Component : OverlappedElements) {
7311 if(
const ValueDecl*VD = MC.getAssociatedDeclaration()) {
7312 const auto*FD = dyn_cast<FieldDecl>(VD);
7313 if(FD && FD->getType()->isLValueReferenceType()) {
7315cast<MemberExpr>(MC.getAssociatedExpression());
7316 LValueBaseLVal = EmitMemberExprBase(CGF, ME);
7332assert(Size &&
"Failed to determine structure size");
7333CombinedInfo.Exprs.emplace_back(MapDecl, MapExpr);
7335CombinedInfo.DevicePtrDecls.push_back(
nullptr);
7336CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
7338CombinedInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
7340CombinedInfo.Types.push_back(Flags);
7341CombinedInfo.Mappers.push_back(
nullptr);
7342CombinedInfo.NonContigInfo.Dims.push_back(IsNonContiguous ? DimSize
7346CombinedInfo.Exprs.emplace_back(MapDecl, MapExpr);
7348CombinedInfo.DevicePtrDecls.push_back(
nullptr);
7349CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
7355CombinedInfo.Sizes.push_back(
7357CombinedInfo.Types.push_back(Flags);
7358CombinedInfo.Mappers.push_back(
nullptr);
7359CombinedInfo.NonContigInfo.Dims.push_back(IsNonContiguous ? DimSize
7363llvm::Value *
Size= getExprTypeSize(I->getAssociatedExpression());
7370 if((!IsMemberPointerOrAddr && !IsPartialMapped) ||
7372 if(!IsMappingWholeStruct) {
7373CombinedInfo.Exprs.emplace_back(MapDecl, MapExpr);
7375CombinedInfo.DevicePtrDecls.push_back(
nullptr);
7376CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
7378CombinedInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
7380CombinedInfo.NonContigInfo.Dims.push_back(IsNonContiguous ? DimSize
7383StructBaseCombinedInfo.Exprs.emplace_back(MapDecl, MapExpr);
7384StructBaseCombinedInfo.BasePointers.push_back(
7386StructBaseCombinedInfo.DevicePtrDecls.push_back(
nullptr);
7387StructBaseCombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
7388StructBaseCombinedInfo.Pointers.push_back(LB.
emitRawPointer(CGF));
7389StructBaseCombinedInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
7391StructBaseCombinedInfo.NonContigInfo.Dims.push_back(
7392IsNonContiguous ? DimSize : 1);
7396 boolHasMapper = Mapper && Next == CE;
7397 if(!IsMappingWholeStruct)
7398CombinedInfo.Mappers.push_back(HasMapper ? Mapper :
nullptr);
7400StructBaseCombinedInfo.Mappers.push_back(HasMapper ? Mapper
7407OpenMPOffloadMappingFlags Flags =
7408getMapTypeBits(MapType, MapModifiers, MotionModifiers, IsImplicit,
7409!IsExpressionFirstInfo || RequiresReference ||
7410FirstPointerInComplexData || IsMemberReference,
7411AreBothBasePtrAndPteeMapped ||
7412(IsCaptureFirstInfo && !RequiresReference),
7415 if(!IsExpressionFirstInfo || IsMemberReference) {
7418 if(IsPointer || (IsMemberReference && Next != CE))
7419Flags &= ~(OpenMPOffloadMappingFlags::OMP_MAP_TO |
7420OpenMPOffloadMappingFlags::OMP_MAP_FROM |
7421OpenMPOffloadMappingFlags::OMP_MAP_ALWAYS |
7422OpenMPOffloadMappingFlags::OMP_MAP_DELETE |
7423OpenMPOffloadMappingFlags::OMP_MAP_CLOSE);
7425 if(ShouldBeMemberOf) {
7428Flags |= OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF;
7431ShouldBeMemberOf =
false;
7435 if(!IsMappingWholeStruct)
7436CombinedInfo.Types.push_back(Flags);
7438StructBaseCombinedInfo.Types.push_back(Flags);
7444 if(EncounteredME) {
7445 const auto*FD = cast<FieldDecl>(EncounteredME->
getMemberDecl());
7446 unsignedFieldIndex = FD->getFieldIndex();
7449 if(!PartialStruct.Base.isValid()) {
7450PartialStruct.LowestElem = {FieldIndex, LowestElem};
7451 if(IsFinalArraySection) {
7455PartialStruct.HighestElem = {FieldIndex, HB};
7457PartialStruct.HighestElem = {FieldIndex, LowestElem};
7459PartialStruct.Base = BP;
7460PartialStruct.LB = BP;
7461}
else if(FieldIndex < PartialStruct.LowestElem.first) {
7462PartialStruct.LowestElem = {FieldIndex, LowestElem};
7463}
else if(FieldIndex > PartialStruct.HighestElem.first) {
7464 if(IsFinalArraySection) {
7468PartialStruct.HighestElem = {FieldIndex, HB};
7470PartialStruct.HighestElem = {FieldIndex, LowestElem};
7476 if(IsFinalArraySection || IsNonContiguous)
7477PartialStruct.IsArraySection =
true;
7480 if(IsFinalArraySection)
7485BP = IsMemberReference ? LowestElem : LB;
7486 if(!IsPartialMapped)
7487IsExpressionFirstInfo =
false;
7488IsCaptureFirstInfo =
false;
7489FirstPointerInComplexData =
false;
7490IsPrevMemberReference = IsMemberReference;
7491}
else if(FirstPointerInComplexData) {
7493->getAssociatedDeclaration()
7495.getNonReferenceType();
7497FirstPointerInComplexData =
false;
7503PartialStruct.HasCompleteRecord =
true;
7505 if(!IsNonContiguous)
7512MapValuesArrayTy CurOffsets = {llvm::ConstantInt::get(CGF.
CGM.
Int64Ty, 0)};
7513MapValuesArrayTy CurCounts = {llvm::ConstantInt::get(CGF.
CGM.
Int64Ty, 1)};
7514MapValuesArrayTy CurStrides;
7515MapValuesArrayTy DimSizes{llvm::ConstantInt::get(CGF.
CGM.
Int64Ty, 1)};
7523 const Expr*AssocExpr = Component.getAssociatedExpression();
7524 const auto*OASE = dyn_cast<ArraySectionExpr>(AssocExpr);
7534assert((VAT || CAT || &Component == &*Components.begin()) &&
7535 "Should be either ConstantArray or VariableArray if not the " 7536 "first Component");
7539 if(CurStrides.empty()) {
7540 const Type*ElementType =
nullptr;
7542ElementType = CAT->getElementType().getTypePtr();
7544ElementType = VAT->getElementType().getTypePtr();
7546assert(&Component == &*Components.begin() &&
7547 "Only expect pointer (non CAT or VAT) when this is the " 7548 "first Component");
7555 if(&Component != &*Components.begin())
7559CurStrides.push_back(
7560llvm::ConstantInt::get(CGF.
Int64Ty, ElementTypeSize));
7565 if(DimSizes.size() < Components.size() - 1) {
7568llvm::ConstantInt::get(CGF.
Int64Ty, CAT->getZExtSize()));
7570DimSizes.push_back(CGF.
Builder.CreateIntCast(
7577 auto*DI = DimSizes.begin() + 1;
7579llvm::Value *DimProd =
7580llvm::ConstantInt::get(CGF.
CGM.
Int64Ty, ElementTypeSize);
7591 const Expr*AssocExpr = Component.getAssociatedExpression();
7593 if(
const auto*AE = dyn_cast<ArraySubscriptExpr>(AssocExpr)) {
7594llvm::Value *Offset = CGF.
Builder.CreateIntCast(
7597CurOffsets.push_back(Offset);
7598CurCounts.push_back(llvm::ConstantInt::get(CGF.
Int64Ty,
1));
7599CurStrides.push_back(CurStrides.back());
7603 const auto*OASE = dyn_cast<ArraySectionExpr>(AssocExpr);
7609 const Expr*OffsetExpr = OASE->getLowerBound();
7610llvm::Value *Offset =
nullptr;
7613Offset = llvm::ConstantInt::get(CGF.
Int64Ty, 0);
7619CurOffsets.push_back(Offset);
7622 const Expr*CountExpr = OASE->getLength();
7623llvm::Value *Count =
nullptr;
7629 if(!OASE->getColonLocFirst().isValid() &&
7630!OASE->getColonLocSecond().isValid()) {
7631Count = llvm::ConstantInt::get(CGF.
Int64Ty, 1);
7637 const Expr*StrideExpr = OASE->getStride();
7638llvm::Value *Stride =
7644Count = CGF.
Builder.CreateUDiv(
7645CGF.
Builder.CreateNUWSub(*DI, Offset), Stride);
7647Count = CGF.
Builder.CreateNUWSub(*DI, Offset);
7652Count = CGF.
Builder.CreateIntCast(Count, CGF.
Int64Ty,
false);
7653CurCounts.push_back(Count);
7662 const Expr*StrideExpr = OASE->getStride();
7663llvm::Value *Stride =
7668DimProd = CGF.
Builder.CreateNUWMul(DimProd, *(DI - 1));
7670CurStrides.push_back(CGF.
Builder.CreateNUWMul(DimProd, Stride));
7672CurStrides.push_back(DimProd);
7673 if(DI != DimSizes.end())
7677CombinedInfo.NonContigInfo.Offsets.push_back(CurOffsets);
7678CombinedInfo.NonContigInfo.Counts.push_back(CurCounts);
7679CombinedInfo.NonContigInfo.Strides.push_back(CurStrides);
7685OpenMPOffloadMappingFlags
7687assert(Cap.
capturesVariable() &&
"Expected capture by reference only!");
7694 returnOpenMPOffloadMappingFlags::OMP_MAP_TO |
7695OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ;
7696 returnOpenMPOffloadMappingFlags::OMP_MAP_PRIVATE |
7697OpenMPOffloadMappingFlags::OMP_MAP_TO;
7700 if(I != LambdasMap.end())
7702 returngetMapTypeBits(
7703I->getSecond()->getMapType(), I->getSecond()->getMapTypeModifiers(),
7704{}, I->getSecond()->isImplicit(),
7708 returnOpenMPOffloadMappingFlags::OMP_MAP_TO |
7709OpenMPOffloadMappingFlags::OMP_MAP_FROM;
7714 boolAsBase)
const{
7717llvm::StructType *St =
7720 unsignedNumElements = St->getNumElements();
7722llvm::PointerUnion<const CXXRecordDecl *, const FieldDecl *>, 4>
7723RecordLayout(NumElements);
7726 for(
const auto&I : RD->
bases()) {
7741RecordLayout[FieldIndex] =
Base;
7744 for(
const auto&I : RD->
vbases()) {
7752 if(RecordLayout[FieldIndex])
7754RecordLayout[FieldIndex] =
Base;
7757assert(!RD->
isUnion() &&
"Unexpected union.");
7758 for(
const auto*Field : RD->
fields()) {
7761 if(!
Field->isBitField() &&
7764RecordLayout[FieldIndex] =
Field;
7767 for(
constllvm::PointerUnion<const CXXRecordDecl *, const FieldDecl *>
7768&
Data: RecordLayout) {
7769 if(
Data.isNull())
7771 if(
const auto*
Base= dyn_cast<const CXXRecordDecl *>(
Data))
7772getPlainLayout(
Base, Layout,
true);
7774Layout.push_back(cast<const FieldDecl *>(
Data));
7783 voidgenerateAllInfoForClauses(
7785llvm::OpenMPIRBuilder &OMPBuilder,
7792llvm::MapVector<CanonicalDeclPtr<const Decl>,
7799[&Info, &SkipVarSet](
7805 boolReturnDevicePointer,
boolIsImplicit,
const ValueDecl*Mapper,
7806 const Expr*VarRef =
nullptr,
boolForDeviceAddr =
false) {
7807 if(SkipVarSet.contains(
D))
7809 autoIt = Info.try_emplace(
D, Total).first;
7810It->second[
Kind].emplace_back(
7811L, MapType, MapModifiers, MotionModifiers, ReturnDevicePointer,
7812IsImplicit, Mapper, VarRef, ForDeviceAddr);
7815 for(
const auto*
Cl: Clauses) {
7816 const auto*
C= dyn_cast<OMPMapClause>(
Cl);
7820 if(llvm::is_contained(
C->getMapTypeModifiers(),
7821OMPC_MAP_MODIFIER_present))
7823 else if(
C->getMapType() == OMPC_MAP_alloc)
7825 const auto*EI =
C->getVarRefs().begin();
7826 for(
const autoL :
C->component_lists()) {
7827 const Expr*
E= (
C->getMapLoc().isValid()) ? *EI :
nullptr;
7828InfoGen(std::get<0>(L),
Kind, std::get<1>(L),
C->getMapType(),
7829 C->getMapTypeModifiers(), {},
7830 false,
C->isImplicit(), std::get<2>(L),
7835 for(
const auto*
Cl: Clauses) {
7836 const auto*
C= dyn_cast<OMPToClause>(
Cl);
7840 if(llvm::is_contained(
C->getMotionModifiers(),
7841OMPC_MOTION_MODIFIER_present))
7843 const auto*EI =
C->getVarRefs().begin();
7844 for(
const autoL :
C->component_lists()) {
7845InfoGen(std::get<0>(L),
Kind, std::get<1>(L), OMPC_MAP_to, {},
7846 C->getMotionModifiers(),
false,
7847 C->isImplicit(), std::get<2>(L), *EI);
7851 for(
const auto*
Cl: Clauses) {
7852 const auto*
C= dyn_cast<OMPFromClause>(
Cl);
7856 if(llvm::is_contained(
C->getMotionModifiers(),
7857OMPC_MOTION_MODIFIER_present))
7859 const auto*EI =
C->getVarRefs().begin();
7860 for(
const autoL :
C->component_lists()) {
7861InfoGen(std::get<0>(L),
Kind, std::get<1>(L), OMPC_MAP_from, {},
7862 C->getMotionModifiers(),
7863 false,
C->isImplicit(), std::get<2>(L),
7876llvm::MapVector<CanonicalDeclPtr<const Decl>,
7879MapCombinedInfoTy UseDeviceDataCombinedInfo;
7881 auto&&UseDeviceDataCombinedInfoGen =
7882[&UseDeviceDataCombinedInfo](
const ValueDecl*VD, llvm::Value *Ptr,
7884UseDeviceDataCombinedInfo.Exprs.push_back(VD);
7885UseDeviceDataCombinedInfo.BasePointers.emplace_back(Ptr);
7886UseDeviceDataCombinedInfo.DevicePtrDecls.emplace_back(VD);
7887UseDeviceDataCombinedInfo.DevicePointers.emplace_back(
7888IsDevAddr ? DeviceInfoTy::Address : DeviceInfoTy::Pointer);
7889UseDeviceDataCombinedInfo.Pointers.push_back(Ptr);
7890UseDeviceDataCombinedInfo.Sizes.push_back(
7891llvm::Constant::getNullValue(CGF.Int64Ty));
7892UseDeviceDataCombinedInfo.Types.push_back(
7893OpenMPOffloadMappingFlags::OMP_MAP_RETURN_PARAM);
7894UseDeviceDataCombinedInfo.Mappers.push_back(
nullptr);
7898[&DeferredInfo, &UseDeviceDataCombinedInfoGen,
7902 boolIsImplicit,
boolIsDevAddr) {
7906 if(isa<MemberExpr>(IE)) {
7915 false, IsImplicit,
nullptr,
nullptr,
7917DeferredInfo[
nullptr].emplace_back(IE, VD, IsDevAddr);
7921 if(IE->isGLValue())
7922Ptr = CGF.EmitLValue(IE).getPointer(CGF);
7924Ptr = CGF.EmitScalarExpr(IE);
7926Ptr = CGF.EmitLoadOfScalar(CGF.EmitLValue(IE), IE->getExprLoc());
7928UseDeviceDataCombinedInfoGen(VD, Ptr, CGF, IsDevAddr);
7933 const Expr*IE,
boolIsDevAddr) ->
bool{
7940 autoIt = Info.find(isa<MemberExpr>(IE) ? nullptr : VD);
7941 if(It != Info.end()) {
7942 bool Found=
false;
7943 for(
auto&
Data: It->second) {
7944 auto*CI = llvm::find_if(
Data, [VD](
constMapInfo &MI) {
7945 returnMI.Components.back().getAssociatedDeclaration() == VD;
7953 if(CI !=
Data.end()) {
7955CI->ForDeviceAddr = IsDevAddr;
7956CI->ReturnDevicePointer =
true;
7960 autoPrevCI = std::next(CI->Components.rbegin());
7961 const auto*VarD = dyn_cast<VarDecl>(VD);
7963isa<MemberExpr>(IE) ||
7964!VD->getType().getNonReferenceType()->isPointerType() ||
7965PrevCI == CI->Components.rend() ||
7966isa<MemberExpr>(PrevCI->getAssociatedExpression()) || !VarD ||
7967VarD->hasLocalStorage()) {
7968CI->ForDeviceAddr = IsDevAddr;
7969CI->ReturnDevicePointer =
true;
7987 for(
const auto*
Cl: Clauses) {
7988 const auto*
C= dyn_cast<OMPUseDevicePtrClause>(
Cl);
7991 for(
const autoL :
C->component_lists()) {
7994assert(!Components.empty() &&
7995 "Not expecting empty list of components!");
7996 const ValueDecl*VD = Components.back().getAssociatedDeclaration();
7998 const Expr*IE = Components.back().getAssociatedExpression();
7999 if(IsMapInfoExist(CGF, VD, IE,
false))
8001MapInfoGen(CGF, IE, VD, Components,
C->isImplicit(),
8006llvm::SmallDenseSet<CanonicalDeclPtr<const Decl>, 4> Processed;
8007 for(
const auto*
Cl: Clauses) {
8008 const auto*
C= dyn_cast<OMPUseDeviceAddrClause>(
Cl);
8011 for(
const autoL :
C->component_lists()) {
8014assert(!std::get<1>(L).empty() &&
8015 "Not expecting empty list of components!");
8016 const ValueDecl*VD = std::get<1>(L).back().getAssociatedDeclaration();
8017 if(!Processed.insert(VD).second)
8020 const Expr*IE = std::get<1>(L).back().getAssociatedExpression();
8021 if(IsMapInfoExist(CGF, VD, IE,
true))
8023MapInfoGen(CGF, IE, VD, Components,
C->isImplicit(),
8028 for(
const auto&
Data: Info) {
8029StructRangeInfoTy PartialStruct;
8031MapCombinedInfoTy CurInfo;
8033MapCombinedInfoTy StructBaseCurInfo;
8035 const ValueDecl*VD = cast_or_null<ValueDecl>(
D);
8036 boolHasMapBasePtr =
false;
8037 boolHasMapArraySec =
false;
8039 for(
const auto&M :
Data.second) {
8040HasMapBasePtr = any_of(M, [](
constMapInfo &L) {
8041 returnisa_and_present<DeclRefExpr>(L.VarRef);
8043HasMapArraySec = any_of(M, [](
constMapInfo &L) {
8044 returnisa_and_present<ArraySectionExpr, ArraySubscriptExpr>(
8047 if(HasMapBasePtr && HasMapArraySec)
8051 for(
const auto&M :
Data.second) {
8052 for(
constMapInfo &L : M) {
8053assert(!L.Components.empty() &&
8054 "Not expecting declaration with no component lists.");
8057 unsignedCurrentBasePointersIdx = CurInfo.BasePointers.size();
8058 unsignedStructBasePointersIdx =
8059StructBaseCurInfo.BasePointers.size();
8060CurInfo.NonContigInfo.IsNonContiguous =
8061L.Components.back().isNonContiguous();
8062generateInfoForComponentList(
8063L.MapType, L.MapModifiers, L.MotionModifiers, L.Components,
8064CurInfo, StructBaseCurInfo, PartialStruct,
8065 false, L.IsImplicit,
8066 true, L.Mapper, L.ForDeviceAddr, VD,
8068HasMapBasePtr && HasMapArraySec);
8072 if(L.ReturnDevicePointer) {
8076assert((CurrentBasePointersIdx < CurInfo.BasePointers.size() ||
8077StructBasePointersIdx <
8078StructBaseCurInfo.BasePointers.size()) &&
8079 "Unexpected number of mapped base pointers.");
8083L.Components.back().getAssociatedDeclaration();
8084assert(RelevantVD &&
8085 "No relevant declaration related with device pointer??");
8092 if(StructBasePointersIdx < StructBaseCurInfo.BasePointers.size()) {
8093StructBaseCurInfo.DevicePtrDecls[StructBasePointersIdx] =
8095StructBaseCurInfo.DevicePointers[StructBasePointersIdx] =
8096L.ForDeviceAddr ? DeviceInfoTy::Address
8097: DeviceInfoTy::Pointer;
8098StructBaseCurInfo.Types[StructBasePointersIdx] |=
8099OpenMPOffloadMappingFlags::OMP_MAP_RETURN_PARAM;
8101CurInfo.DevicePtrDecls[CurrentBasePointersIdx] = RelevantVD;
8102CurInfo.DevicePointers[CurrentBasePointersIdx] =
8103L.ForDeviceAddr ? DeviceInfoTy::Address
8104: DeviceInfoTy::Pointer;
8105CurInfo.Types[CurrentBasePointersIdx] |=
8106OpenMPOffloadMappingFlags::OMP_MAP_RETURN_PARAM;
8114 autoCI = DeferredInfo.find(
Data.first);
8115 if(CI != DeferredInfo.end()) {
8116 for(
constDeferredDevicePtrEntryTy &L : CI->second) {
8117llvm::Value *BasePtr;
8119 if(L.ForDeviceAddr) {
8120 if(L.IE->isGLValue())
8128CurInfo.Types.push_back(
8129OpenMPOffloadMappingFlags::OMP_MAP_RETURN_PARAM |
8130OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF);
8134L.IE->getExprLoc());
8138CurInfo.Types.push_back(
8139OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ |
8140OpenMPOffloadMappingFlags::OMP_MAP_RETURN_PARAM |
8141OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF);
8143CurInfo.Exprs.push_back(L.VD);
8144CurInfo.BasePointers.emplace_back(BasePtr);
8145CurInfo.DevicePtrDecls.emplace_back(L.VD);
8146CurInfo.DevicePointers.emplace_back(
8147L.ForDeviceAddr ? DeviceInfoTy::Address : DeviceInfoTy::Pointer);
8148CurInfo.Pointers.push_back(Ptr);
8149CurInfo.Sizes.push_back(
8150llvm::Constant::getNullValue(this->CGF.
Int64Ty));
8151CurInfo.Mappers.push_back(
nullptr);
8157MapCombinedInfoTy UnionCurInfo;
8158UnionCurInfo.append(StructBaseCurInfo);
8159UnionCurInfo.append(CurInfo);
8163 if(PartialStruct.Base.isValid()) {
8164UnionCurInfo.NonContigInfo.Dims.push_back(0);
8166emitCombinedEntry(CombinedInfo, UnionCurInfo.Types, PartialStruct,
8167!VD, OMPBuilder, VD);
8171CombinedInfo.append(UnionCurInfo);
8174CombinedInfo.append(UseDeviceDataCombinedInfo);
8179: CurDir(&Dir), CGF(CGF) {
8182 for(
const auto*
D:
C->varlist())
8183FirstPrivateDecls.try_emplace(
8184cast<VarDecl>(cast<DeclRefExpr>(
D)->getDecl()),
C->isImplicit());
8187 for(
unsignedI = 0,
E=
C->getNumberOfAllocators(); I <
E; ++I) {
8189 if(
const auto*DRE = dyn_cast_or_null<DeclRefExpr>(
D.AllocatorTraits))
8190FirstPrivateDecls.try_emplace(cast<VarDecl>(DRE->getDecl()),
8192 else if(
const auto*VD = dyn_cast<VarDecl>(
8193cast<DeclRefExpr>(
D.Allocator->IgnoreParenImpCasts())
8195FirstPrivateDecls.try_emplace(VD,
true);
8200 for(
autoL :
C->component_lists())
8201DevPointersMap[std::get<0>(L)].push_back(std::get<1>(L));
8204 for(
autoL :
C->component_lists())
8205HasDevAddrsMap[std::get<0>(L)].push_back(std::get<1>(L));
8208 if(
C->getMapType() != OMPC_MAP_to)
8210 for(
autoL :
C->component_lists()) {
8212 const auto*RD = VD ? VD->
getType()
8218LambdasMap.try_emplace(std::get<0>(L),
C);
8225: CurDir(&Dir), CGF(CGF) {}
8230 voidemitCombinedEntry(MapCombinedInfoTy &CombinedInfo,
8231MapFlagsArrayTy &CurTypes,
8232 constStructRangeInfoTy &PartialStruct,
boolIsMapThis,
8233llvm::OpenMPIRBuilder &OMPBuilder,
8235 boolNotTargetParams =
true)
const{
8236 if(CurTypes.size() == 1 &&
8237((CurTypes.back() & OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF) !=
8238OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF) &&
8239!PartialStruct.IsArraySection)
8241 AddressLBAddr = PartialStruct.LowestElem.second;
8242 AddressHBAddr = PartialStruct.HighestElem.second;
8243 if(PartialStruct.HasCompleteRecord) {
8244LBAddr = PartialStruct.LB;
8245HBAddr = PartialStruct.LB;
8247CombinedInfo.Exprs.push_back(VD);
8249CombinedInfo.BasePointers.push_back(PartialStruct.Base.emitRawPointer(CGF));
8250CombinedInfo.DevicePtrDecls.push_back(
nullptr);
8251CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
8257 boolHasBaseClass = RD && IsMapThis ? RD->
getNumBases() > 0 :
false;
8267CombinedInfo.Pointers.push_back(PartialStruct.Base.emitRawPointer(CGF));
8269llvm::Value *
Size=
8272CombinedInfo.Sizes.push_back(Size);
8274CombinedInfo.Pointers.push_back(LB);
8277llvm::Value *HAddr = CGF.
Builder.CreateConstGEP1_32(
8279llvm::Value *CLAddr = CGF.
Builder.CreatePointerCast(LB, CGF.
VoidPtrTy);
8280llvm::Value *CHAddr = CGF.
Builder.CreatePointerCast(HAddr, CGF.
VoidPtrTy);
8281llvm::Value *Diff = CGF.
Builder.CreatePtrDiff(CGF.
Int8Ty, CHAddr, CLAddr);
8284CombinedInfo.Sizes.push_back(Size);
8286CombinedInfo.Mappers.push_back(
nullptr);
8288CombinedInfo.Types.push_back(
8289NotTargetParams ? OpenMPOffloadMappingFlags::OMP_MAP_NONE
8290: !PartialStruct.PreliminaryMapData.BasePointers.empty()
8291? OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ
8292: OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM);
8295 if(CurTypes.end() !=
8296llvm::find_if(CurTypes, [](OpenMPOffloadMappingFlags
Type) {
8297return static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>>(
8298Type & OpenMPOffloadMappingFlags::OMP_MAP_PRESENT);
8300CombinedInfo.Types.back() |= OpenMPOffloadMappingFlags::OMP_MAP_PRESENT;
8302(*CurTypes.begin()) &= ~OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM;
8309 if(CurTypes.end() !=
8310llvm::find_if(CurTypes, [](OpenMPOffloadMappingFlags
Type) {
8311 return static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
8312 Type& OpenMPOffloadMappingFlags::OMP_MAP_OMPX_HOLD);
8314CombinedInfo.Types.back() |= OpenMPOffloadMappingFlags::OMP_MAP_OMPX_HOLD;
8315 for(
auto&M : CurTypes)
8316M |= OpenMPOffloadMappingFlags::OMP_MAP_OMPX_HOLD;
8322OpenMPOffloadMappingFlags MemberOfFlag =
8323OMPBuilder.getMemberOfFlag(CombinedInfo.BasePointers.size() - 1);
8324 for(
auto&M : CurTypes)
8325OMPBuilder.setCorrectMemberOfFlag(M, MemberOfFlag);
8333 voidgenerateAllInfo(
8334MapCombinedInfoTy &CombinedInfo, llvm::OpenMPIRBuilder &OMPBuilder,
8337assert(isa<const OMPExecutableDirective *>(CurDir) &&
8338 "Expect a executable directive");
8339 const auto*CurExecDir = cast<const OMPExecutableDirective *>(CurDir);
8340generateAllInfoForClauses(CurExecDir->clauses(), CombinedInfo, OMPBuilder,
8347 voidgenerateAllInfoForMapper(MapCombinedInfoTy &CombinedInfo,
8348llvm::OpenMPIRBuilder &OMPBuilder)
const{
8349assert(isa<const OMPDeclareMapperDecl *>(CurDir) &&
8350 "Expect a declare mapper directive");
8351 const auto*CurMapperDir = cast<const OMPDeclareMapperDecl *>(CurDir);
8352generateAllInfoForClauses(CurMapperDir->clauses(), CombinedInfo,
8357 voidgenerateInfoForLambdaCaptures(
8358 const ValueDecl*VD, llvm::Value *Arg, MapCombinedInfoTy &CombinedInfo,
8359llvm::DenseMap<llvm::Value *, llvm::Value *> &LambdaPointers)
const{
8367llvm::DenseMap<const ValueDecl *, FieldDecl *> Captures;
8374LambdaPointers.try_emplace(ThisLVal.
getPointer(CGF),
8376CombinedInfo.Exprs.push_back(VD);
8377CombinedInfo.BasePointers.push_back(ThisLVal.
getPointer(CGF));
8378CombinedInfo.DevicePtrDecls.push_back(
nullptr);
8379CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
8380CombinedInfo.Pointers.push_back(ThisLValVal.
getPointer(CGF));
8381CombinedInfo.Sizes.push_back(
8384CombinedInfo.Types.push_back(
8385OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ |
8386OpenMPOffloadMappingFlags::OMP_MAP_LITERAL |
8387OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF |
8388OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT);
8389CombinedInfo.Mappers.push_back(
nullptr);
8392 if(!LC.capturesVariable())
8394 const VarDecl*VD = cast<VarDecl>(LC.getCapturedVar());
8397 autoIt = Captures.find(VD);
8398assert(It != Captures.end() &&
"Found lambda capture without field.");
8400 if(LC.getCaptureKind() ==
LCK_ByRef) {
8402LambdaPointers.try_emplace(VarLVal.
getPointer(CGF),
8404CombinedInfo.Exprs.push_back(VD);
8405CombinedInfo.BasePointers.push_back(VarLVal.
getPointer(CGF));
8406CombinedInfo.DevicePtrDecls.push_back(
nullptr);
8407CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
8408CombinedInfo.Pointers.push_back(VarLValVal.
getPointer(CGF));
8409CombinedInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
8415LambdaPointers.try_emplace(VarLVal.
getPointer(CGF),
8417CombinedInfo.Exprs.push_back(VD);
8418CombinedInfo.BasePointers.push_back(VarLVal.
getPointer(CGF));
8419CombinedInfo.DevicePtrDecls.push_back(
nullptr);
8420CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
8421CombinedInfo.Pointers.push_back(VarRVal.
getScalarVal());
8422CombinedInfo.Sizes.push_back(llvm::ConstantInt::get(CGF.
Int64Ty, 0));
8424CombinedInfo.Types.push_back(
8425OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ |
8426OpenMPOffloadMappingFlags::OMP_MAP_LITERAL |
8427OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF |
8428OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT);
8429CombinedInfo.Mappers.push_back(
nullptr);
8434 voidadjustMemberOfForLambdaCaptures(
8435llvm::OpenMPIRBuilder &OMPBuilder,
8436 constllvm::DenseMap<llvm::Value *, llvm::Value *> &LambdaPointers,
8437MapBaseValuesArrayTy &BasePointers, MapValuesArrayTy &Pointers,
8438MapFlagsArrayTy &Types)
const{
8439 for(
unsignedI = 0,
E= Types.size(); I <
E; ++I) {
8441 if(Types[I] != (OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ |
8442OpenMPOffloadMappingFlags::OMP_MAP_LITERAL |
8443OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF |
8444OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT))
8446llvm::Value *BasePtr = LambdaPointers.lookup(BasePointers[I]);
8447assert(BasePtr &&
"Unable to find base lambda address.");
8449 for(
unsignedJ = I; J > 0; --J) {
8450 unsignedIdx = J - 1;
8451 if(Pointers[Idx] != BasePtr)
8456assert(TgtIdx != -1 &&
"Unable to find parent lambda.");
8460OpenMPOffloadMappingFlags MemberOfFlag =
8461OMPBuilder.getMemberOfFlag(TgtIdx);
8462OMPBuilder.setCorrectMemberOfFlag(Types[I], MemberOfFlag);
8469llvm::Value *Arg, MapCombinedInfoTy &CombinedInfo,
8470StructRangeInfoTy &PartialStruct)
const{
8472 "Not expecting to generate map info for a variable array type!");
8481 if(LambdasMap.count(VD))
8487 if(VD && (DevPointersMap.count(VD) || HasDevAddrsMap.count(VD))) {
8488CombinedInfo.Exprs.push_back(VD);
8489CombinedInfo.BasePointers.emplace_back(Arg);
8490CombinedInfo.DevicePtrDecls.emplace_back(VD);
8491CombinedInfo.DevicePointers.emplace_back(DeviceInfoTy::Pointer);
8492CombinedInfo.Pointers.push_back(Arg);
8493CombinedInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
8496CombinedInfo.Types.push_back(
8497OpenMPOffloadMappingFlags::OMP_MAP_LITERAL |
8498OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM);
8499CombinedInfo.Mappers.push_back(
nullptr);
8511 autoIt = DevPointersMap.find(VD);
8512 if(It != DevPointersMap.end())
8513 for(
const auto&MCL : It->second)
8514DeclComponentLists.emplace_back(MCL, OMPC_MAP_to,
Unknown,
8517 autoI = HasDevAddrsMap.find(VD);
8518 if(I != HasDevAddrsMap.end())
8519 for(
const auto&MCL : I->second)
8520DeclComponentLists.emplace_back(MCL, OMPC_MAP_tofrom,
Unknown,
8523assert(isa<const OMPExecutableDirective *>(CurDir) &&
8524 "Expect a executable directive");
8525 const auto*CurExecDir = cast<const OMPExecutableDirective *>(CurDir);
8526 boolHasMapBasePtr =
false;
8527 boolHasMapArraySec =
false;
8528 for(
const auto*
C: CurExecDir->getClausesOfKind<
OMPMapClause>()) {
8529 const auto*EI =
C->getVarRefs().begin();
8530 for(
const autoL :
C->decl_component_lists(VD)) {
8533 const Expr*
E= (
C->getMapLoc().isValid()) ? *EI :
nullptr;
8535std::tie(VDecl, Components, Mapper) = L;
8536assert(VDecl == VD &&
"We got information for the wrong declaration??");
8537assert(!Components.empty() &&
8538 "Not expecting declaration with no component lists.");
8540HasMapBasePtr =
true;
8542(isa<ArraySectionExpr>(
E) || isa<ArraySubscriptExpr>(
E)))
8543HasMapArraySec =
true;
8544DeclComponentLists.emplace_back(Components,
C->getMapType(),
8545 C->getMapTypeModifiers(),
8546 C->isImplicit(), Mapper,
E);
8550llvm::stable_sort(DeclComponentLists, [](
constMapData &LHS,
8551 constMapData &RHS) {
8555llvm::is_contained(MapModifiers, clang::OMPC_MAP_MODIFIER_present);
8556 boolHasAllocs = MapType == OMPC_MAP_alloc;
8557MapModifiers = std::get<2>(RHS);
8558MapType = std::get<1>(LHS);
8560llvm::is_contained(MapModifiers, clang::OMPC_MAP_MODIFIER_present);
8561 boolHasAllocsR = MapType == OMPC_MAP_alloc;
8562 return(HasPresent && !HasPresentR) || (HasAllocs && !HasAllocsR);
8566llvm::SmallDenseMap<
8573 for(
constMapData &L : DeclComponentLists) {
8580std::tie(Components, MapType, MapModifiers, IsImplicit, Mapper, VarRef) =
8583 for(
constMapData &L1 :
ArrayRef(DeclComponentLists).slice(Count)) {
8585std::tie(Components1, MapType, MapModifiers, IsImplicit, Mapper,
8587 autoCI = Components.rbegin();
8588 autoCE = Components.rend();
8589 autoSI = Components1.rbegin();
8590 autoSE = Components1.rend();
8591 for(; CI != CE && SI != SE; ++CI, ++SI) {
8592 if(CI->getAssociatedExpression()->getStmtClass() !=
8593SI->getAssociatedExpression()->getStmtClass())
8596 if(CI->getAssociatedDeclaration() != SI->getAssociatedDeclaration())
8601 if(CI == CE || SI == SE) {
8603 if(CI == CE && SI == SE)
8605 const autoIt = (SI == SE) ? CI : SI;
8611 if(!isa<MemberExpr>(It->getAssociatedExpression()) ||
8612(std::prev(It)->getAssociatedDeclaration() &&
8614->getAssociatedDeclaration()
8616->isPointerType()) ||
8617(It->getAssociatedDeclaration() &&
8618It->getAssociatedDeclaration()->getType()->isPointerType() &&
8619std::next(It) != CE && std::next(It) != SE))
8621 constMapData &BaseData = CI == CE ? L : L1;
8623SI == SE ? Components : Components1;
8624OverlappedData[&BaseData].push_back(SubData);
8630 if(!OverlappedData.empty()) {
8633 while(BaseType != OrigType) {
8639getPlainLayout(CRD, Layout,
false);
8645 for(
auto&Pair : OverlappedData) {
8652auto CI = First.rbegin();
8653auto CE = First.rend();
8654auto SI = Second.rbegin();
8655auto SE = Second.rend();
8656for (; CI != CE && SI != SE; ++CI, ++SI) {
8657if (CI->getAssociatedExpression()->getStmtClass() !=
8658SI->getAssociatedExpression()->getStmtClass())
8661if (CI->getAssociatedDeclaration() !=
8662SI->getAssociatedDeclaration())
8667 if(CI == CE && SI == SE)
8671 if(CI == CE || SI == SE)
8674 const auto*FD1 = cast<FieldDecl>(CI->getAssociatedDeclaration());
8675 const auto*FD2 = cast<FieldDecl>(SI->getAssociatedDeclaration());
8676 if(FD1->getParent() == FD2->getParent())
8677 returnFD1->getFieldIndex() < FD2->getFieldIndex();
8679llvm::find_if(Layout, [FD1, FD2](
const FieldDecl*FD) {
8680 returnFD == FD1 || FD == FD2;
8688 boolIsFirstComponentList =
true;
8689MapCombinedInfoTy StructBaseCombinedInfo;
8690 for(
const auto&Pair : OverlappedData) {
8691 constMapData &L = *Pair.getFirst();
8698std::tie(Components, MapType, MapModifiers, IsImplicit, Mapper, VarRef) =
8701OverlappedComponents = Pair.getSecond();
8702generateInfoForComponentList(
8703MapType, MapModifiers, {}, Components, CombinedInfo,
8704StructBaseCombinedInfo, PartialStruct, IsFirstComponentList,
8705IsImplicit,
false, Mapper,
8706 false, VD, VarRef, OverlappedComponents);
8707IsFirstComponentList =
false;
8710 for(
constMapData &L : DeclComponentLists) {
8717std::tie(Components, MapType, MapModifiers, IsImplicit, Mapper, VarRef) =
8719 autoIt = OverlappedData.find(&L);
8720 if(It == OverlappedData.end())
8721generateInfoForComponentList(
8722MapType, MapModifiers, {}, Components, CombinedInfo,
8723StructBaseCombinedInfo, PartialStruct, IsFirstComponentList,
8724IsImplicit,
false, Mapper,
8726{}, HasMapBasePtr && HasMapArraySec);
8727IsFirstComponentList =
false;
8735MapCombinedInfoTy &CombinedInfo)
const{
8736 boolIsImplicit =
true;
8739CombinedInfo.Exprs.push_back(
nullptr);
8740CombinedInfo.BasePointers.push_back(CV);
8741CombinedInfo.DevicePtrDecls.push_back(
nullptr);
8742CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
8743CombinedInfo.Pointers.push_back(CV);
8745CombinedInfo.Sizes.push_back(
8749CombinedInfo.Types.push_back(OpenMPOffloadMappingFlags::OMP_MAP_TO |
8750OpenMPOffloadMappingFlags::OMP_MAP_FROM);
8754CombinedInfo.BasePointers.push_back(CV);
8755CombinedInfo.DevicePtrDecls.push_back(
nullptr);
8756CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
8757CombinedInfo.Pointers.push_back(CV);
8761CombinedInfo.Types.push_back(
8762OpenMPOffloadMappingFlags::OMP_MAP_LITERAL);
8763CombinedInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
8768CombinedInfo.Types.push_back(OpenMPOffloadMappingFlags::OMP_MAP_NONE);
8769CombinedInfo.Sizes.push_back(llvm::Constant::getNullValue(CGF.
Int64Ty));
8771 autoI = FirstPrivateDecls.find(VD);
8772 if(I != FirstPrivateDecls.end())
8773IsImplicit = I->getSecond();
8778CombinedInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
8783CombinedInfo.Types.push_back(getMapModifiersForPrivateClauses(CI));
8785 autoI = FirstPrivateDecls.find(VD);
8787CombinedInfo.BasePointers.push_back(CV);
8788CombinedInfo.DevicePtrDecls.push_back(
nullptr);
8789CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
8796CombinedInfo.Pointers.push_back(CV);
8798 if(I != FirstPrivateDecls.end())
8799IsImplicit = I->getSecond();
8802CombinedInfo.Types.back() |=
8803OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM;
8807CombinedInfo.Types.back() |= OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT;
8810CombinedInfo.Mappers.push_back(
nullptr);
8822dyn_cast<MemberExpr>(OASE->getBase()->IgnoreParenImpCasts()))
8823 returnME->getMemberDecl();
8829staticllvm::Constant *
8831MappableExprsHandler::MappingExprInfo &MapExprs) {
8833uint32_t SrcLocStrSize;
8834 if(!MapExprs.getMapDecl() && !MapExprs.getMapExpr())
8835 returnOMPBuilder.getOrCreateDefaultSrcLocStr(SrcLocStrSize);
8838 if(!MapExprs.getMapDecl() && MapExprs.getMapExpr()) {
8842 Loc= MapExprs.getMapExpr()->getExprLoc();
8844 Loc= MapExprs.getMapDecl()->getLocation();
8847std::string ExprName;
8848 if(MapExprs.getMapExpr()) {
8850llvm::raw_string_ostream OS(ExprName);
8851MapExprs.getMapExpr()->printPretty(OS,
nullptr,
P);
8853ExprName = MapExprs.getMapDecl()->getNameAsString();
8857 returnOMPBuilder.getOrCreateSrcLocStr(PLoc.
getFilename(), ExprName,
8865 CodeGenFunction&CGF, MappableExprsHandler::MapCombinedInfoTy &CombinedInfo,
8867 boolIsNonContiguous =
false,
boolForEndCall =
false) {
8870 usingInsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
8873InsertPointTy CodeGenIP(CGF.
Builder.GetInsertBlock(),
8874CGF.
Builder.GetInsertPoint());
8876 autoDeviceAddrCB = [&](
unsigned intI, llvm::Value *NewDecl) {
8877 if(
const ValueDecl*DevVD = CombinedInfo.DevicePtrDecls[I]) {
8882 autoCustomMapperCB = [&](
unsigned intI) {
8883llvm::Value *MFunc =
nullptr;
8884 if(CombinedInfo.Mappers[I]) {
8885Info.HasMapper =
true;
8887cast<OMPDeclareMapperDecl>(CombinedInfo.Mappers[I]));
8891OMPBuilder.emitOffloadingArraysAndArgs(
8892AllocaIP, CodeGenIP, Info, Info.RTArgs, CombinedInfo, IsNonContiguous,
8893ForEndCall, DeviceAddrCB, CustomMapperCB);
8899 const auto*CS =
D.getInnermostCapturedStmt();
8902 const Stmt*ChildStmt =
8905 if(
const auto*NestedDir =
8906dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) {
8908 switch(
D.getDirectiveKind()) {
8914 if(DKind == OMPD_teams) {
8915Body = NestedDir->getInnermostCapturedStmt()->IgnoreContainers(
8920 if(
const auto*NND =
8921dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) {
8922DKind = NND->getDirectiveKind();
8928 caseOMPD_target_teams:
8932 caseOMPD_target_parallel:
8933 caseOMPD_target_simd:
8934 caseOMPD_target_parallel_for:
8935 caseOMPD_target_parallel_for_simd:
8937 caseOMPD_target_teams_distribute:
8938 caseOMPD_target_teams_distribute_simd:
8939 caseOMPD_target_teams_distribute_parallel_for:
8940 caseOMPD_target_teams_distribute_parallel_for_simd:
8943 caseOMPD_parallel_for:
8944 caseOMPD_parallel_master:
8945 caseOMPD_parallel_sections:
8947 caseOMPD_parallel_for_simd:
8949 caseOMPD_cancellation_point:
8951 caseOMPD_threadprivate:
8962 caseOMPD_taskyield:
8965 caseOMPD_taskgroup:
8971 caseOMPD_target_data:
8972 caseOMPD_target_exit_data:
8973 caseOMPD_target_enter_data:
8974 caseOMPD_distribute:
8975 caseOMPD_distribute_simd:
8976 caseOMPD_distribute_parallel_for:
8977 caseOMPD_distribute_parallel_for_simd:
8978 caseOMPD_teams_distribute:
8979 caseOMPD_teams_distribute_simd:
8980 caseOMPD_teams_distribute_parallel_for:
8981 caseOMPD_teams_distribute_parallel_for_simd:
8982 caseOMPD_target_update:
8983 caseOMPD_declare_simd:
8984 caseOMPD_declare_variant:
8985 caseOMPD_begin_declare_variant:
8986 caseOMPD_end_declare_variant:
8987 caseOMPD_declare_target:
8988 caseOMPD_end_declare_target:
8989 caseOMPD_declare_reduction:
8990 caseOMPD_declare_mapper:
8992 caseOMPD_taskloop_simd:
8993 caseOMPD_master_taskloop:
8994 caseOMPD_master_taskloop_simd:
8995 caseOMPD_parallel_master_taskloop:
8996 caseOMPD_parallel_master_taskloop_simd:
8998 caseOMPD_metadirective:
9001llvm_unreachable(
"Unexpected directive.");
9046 auto*MapperVarDecl =
9047cast<VarDecl>(cast<DeclRefExpr>(
D->getMapperVarRef())->getDecl());
9048 CharUnitsElementSize =
C.getTypeSizeInChars(Ty);
9052MappableExprsHandler::MapCombinedInfoTy CombinedInfo;
9053 autoPrivatizeAndGenMapInfoCB =
9054[&](llvm::OpenMPIRBuilder::InsertPointTy CodeGenIP, llvm::Value *PtrPHI,
9055llvm::Value *BeginArg) -> llvm::OpenMPIRBuilder::MapInfosTy & {
9056MapperCGF.
Builder.restoreIP(CodeGenIP);
9066 Scope.addPrivate(MapperVarDecl, PtrCurrent);
9067(void)
Scope.Privatize();
9070MappableExprsHandler MEHandler(*
D, MapperCGF);
9071MEHandler.generateAllInfoForMapper(CombinedInfo,
OMPBuilder);
9073 autoFillInfoMap = [&](MappableExprsHandler::MappingExprInfo &MapExpr) {
9077llvm::codegenoptions::NoDebugInfo) {
9078CombinedInfo.Names.resize(CombinedInfo.Exprs.size());
9079llvm::transform(CombinedInfo.Exprs, CombinedInfo.Names.begin(),
9083 returnCombinedInfo;
9086 autoCustomMapperCB = [&](
unsignedI, llvm::Function **MapperFunc) {
9087 if(CombinedInfo.Mappers[I]) {
9090cast<OMPDeclareMapperDecl>(CombinedInfo.Mappers[I]));
9091assert(*MapperFunc &&
"Expect a valid mapper function is available.");
9098llvm::raw_svector_ostream Out(TyStr);
9100std::string Name =
getName({
"omp_mapper", TyStr,
D->getName()});
9102 auto*NewFn =
OMPBuilder.emitUserDefinedMapper(PrivatizeAndGenMapInfoCB,
9103ElemTy, Name, CustomMapperCB);
9104 UDMMap.try_emplace(
D, NewFn);
9128Kind != OMPD_target_teams_loop)
9131 returnllvm::ConstantInt::get(CGF.
Int64Ty, 0);
9133 const auto*LD = cast<OMPLoopDirective>(TD);
9134 if(llvm::Value *NumIterations = SizeEmitter(CGF, *LD))
9135 returnNumIterations;
9136 returnllvm::ConstantInt::get(CGF.
Int64Ty, 0);
9145 if(OffloadingMandatory) {
9146CGF.
Builder.CreateUnreachable();
9148 if(RequiresOuterTask) {
9149CapturedVars.clear();
9158llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier>
Device,
9161llvm::Value *DeviceID;
9162 if(
Device.getPointer()) {
9164 Device.getInt() == OMPC_DEVICE_device_num) &&
9165 "Expected device_num modifier.");
9170DeviceID = CGF.
Builder.getInt64(OMP_DEVICEID_UNDEF);
9177llvm::Value *DynCGroupMem = CGF.
Builder.getInt32(0);
9180CodeGenFunction::RunCleanupsScope DynCGroupMemScope(CGF);
9182DynMemClause->getSize(),
true);
9183DynCGroupMem = CGF.
Builder.CreateIntCast(DynCGroupMemVal, CGF.
Int32Ty,
9186 returnDynCGroupMem;
9191llvm::OpenMPIRBuilder &OMPBuilder,
9193MappableExprsHandler::MapCombinedInfoTy &CombinedInfo) {
9195llvm::DenseMap<llvm::Value *, llvm::Value *> LambdaPointers;
9197 auto*CV = CapturedVars.begin();
9200CI != CE; ++CI, ++RI, ++CV) {
9201MappableExprsHandler::MapCombinedInfoTy CurInfo;
9202MappableExprsHandler::StructRangeInfoTy PartialStruct;
9207CurInfo.Exprs.push_back(
nullptr);
9208CurInfo.BasePointers.push_back(*CV);
9209CurInfo.DevicePtrDecls.push_back(
nullptr);
9210CurInfo.DevicePointers.push_back(
9211MappableExprsHandler::DeviceInfoTy::None);
9212CurInfo.Pointers.push_back(*CV);
9213CurInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
9216CurInfo.Types.push_back(OpenMPOffloadMappingFlags::OMP_MAP_LITERAL |
9217OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM |
9218OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT);
9219CurInfo.Mappers.push_back(
nullptr);
9223MEHandler.generateInfoForCapture(CI, *CV, CurInfo, PartialStruct);
9227MappedVarSet.insert(
nullptr);
9228 if(CurInfo.BasePointers.empty() && !PartialStruct.Base.isValid())
9229MEHandler.generateDefaultMapInfo(*CI, **RI, *CV, CurInfo);
9233MEHandler.generateInfoForLambdaCaptures(CI->
getCapturedVar(), *CV,
9234CurInfo, LambdaPointers);
9237assert((!CurInfo.BasePointers.empty() || PartialStruct.Base.isValid()) &&
9238 "Non-existing map pointer for capture!");
9239assert(CurInfo.BasePointers.size() == CurInfo.Pointers.size() &&
9240CurInfo.BasePointers.size() == CurInfo.Sizes.size() &&
9241CurInfo.BasePointers.size() == CurInfo.Types.size() &&
9242CurInfo.BasePointers.size() == CurInfo.Mappers.size() &&
9243 "Inconsistent map information sizes!");
9247 if(PartialStruct.Base.isValid()) {
9248CombinedInfo.append(PartialStruct.PreliminaryMapData);
9249MEHandler.emitCombinedEntry(CombinedInfo, CurInfo.Types, PartialStruct,
9255CombinedInfo.append(CurInfo);
9258MEHandler.adjustMemberOfForLambdaCaptures(
9259OMPBuilder, LambdaPointers, CombinedInfo.BasePointers,
9260CombinedInfo.Pointers, CombinedInfo.Types);
9264MappableExprsHandler::MapCombinedInfoTy &CombinedInfo,
9265llvm::OpenMPIRBuilder &OMPBuilder,
9272MEHandler.generateAllInfo(CombinedInfo, OMPBuilder, SkippedVarSet);
9274 autoFillInfoMap = [&](MappableExprsHandler::MappingExprInfo &MapExpr) {
9278llvm::codegenoptions::NoDebugInfo) {
9279CombinedInfo.Names.resize(CombinedInfo.Exprs.size());
9280llvm::transform(CombinedInfo.Exprs, CombinedInfo.Names.begin(),
9288llvm::OpenMPIRBuilder &OMPBuilder,
9289MappableExprsHandler::MapCombinedInfoTy &CombinedInfo) {
9291MappableExprsHandler MEHandler(
D, CGF);
9292llvm::DenseSet<CanonicalDeclPtr<const Decl>> MappedVarSet;
9295MappedVarSet, CombinedInfo);
9296 genMapInfo(MEHandler, CGF, CombinedInfo, OMPBuilder, MappedVarSet);
9299template<
typenameClauseTy>
9304 const auto*
C=
D.getSingleClause<ClauseTy>();
9305assert(!
C->varlist_empty() &&
9306 "ompx_bare requires explicit num_teams and thread_limit");
9307CodeGenFunction::RunCleanupsScope
Scope(CGF);
9308 for(
auto*
E:
C->varlist()) {
9320llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier>
Device,
9321llvm::Value *OutlinedFnID, CodeGenFunction::OMPTargetDataInfo &InputInfo,
9322llvm::Value *&MapTypesArray, llvm::Value *&MapNamesArray,
9327llvm::OpenMPIRBuilder &OMPBuilder = OMPRuntime->
getOMPBuilder();
9330MappableExprsHandler::MapCombinedInfoTy CombinedInfo;
9332 genMapInfo(
D, CGF, CS, CapturedVars, OMPBuilder, CombinedInfo);
9337InputInfo.NumberOfTargetItems = Info.NumberOfPtrs;
9338InputInfo.BasePointersArray =
Address(Info.RTArgs.BasePointersArray,
9340InputInfo.PointersArray =
9342InputInfo.SizesArray =
9344InputInfo.MappersArray =
9346MapTypesArray = Info.RTArgs.MapTypesArray;
9347MapNamesArray = Info.RTArgs.MapNamesArray;
9349 auto&&ThenGen = [&OMPRuntime, OutlinedFn, &
D, &CapturedVars,
9350RequiresOuterTask, &CS, OffloadingMandatory,
Device,
9351OutlinedFnID, &InputInfo, &MapTypesArray, &MapNamesArray,
9353 boolIsReverseOffloading =
Device.getInt() == OMPC_DEVICE_ancestor;
9355 if(IsReverseOffloading) {
9361RequiresOuterTask, CS, OffloadingMandatory, CGF);
9366 unsignedNumTargetItems = InputInfo.NumberOfTargetItems;
9368llvm::Value *BasePointersArray =
9369InputInfo.BasePointersArray.emitRawPointer(CGF);
9370llvm::Value *PointersArray = InputInfo.PointersArray.emitRawPointer(CGF);
9371llvm::Value *SizesArray = InputInfo.SizesArray.emitRawPointer(CGF);
9372llvm::Value *MappersArray = InputInfo.MappersArray.emitRawPointer(CGF);
9374 auto&&EmitTargetCallFallbackCB =
9375[&OMPRuntime, OutlinedFn, &
D, &CapturedVars, RequiresOuterTask, &CS,
9376OffloadingMandatory, &CGF](llvm::OpenMPIRBuilder::InsertPointTy IP)
9377-> llvm::OpenMPIRBuilder::InsertPointTy {
9380RequiresOuterTask, CS, OffloadingMandatory, CGF);
9381 returnCGF.
Builder.saveIP();
9388emitClauseForBareTargetDirective<OMPNumTeamsClause>(CGF,
D, NumTeams);
9389emitClauseForBareTargetDirective<OMPThreadLimitClause>(CGF,
D,
9393NumThreads.push_back(
9399llvm::Value *NumIterations =
9402llvm::OpenMPIRBuilder::InsertPointTy AllocaIP(
9405llvm::OpenMPIRBuilder::TargetDataRTArgs RTArgs(
9406BasePointersArray, PointersArray, SizesArray, MapTypesArray,
9407 nullptr, MappersArray, MapNamesArray);
9409llvm::OpenMPIRBuilder::TargetKernelArgs Args(
9410NumTargetItems, RTArgs, NumIterations, NumTeams, NumThreads,
9411DynCGGroupMem, HasNoWait);
9413llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
9415CGF.
Builder, OutlinedFnID, EmitTargetCallFallbackCB, Args, DeviceID,
9417CGF.
Builder.restoreIP(AfterIP);
9420 if(RequiresOuterTask)
9435[&OMPRuntime, OutlinedFn, &
D, &CapturedVars, RequiresOuterTask, &CS,
9438RequiresOuterTask, CS, OffloadingMandatory, CGF);
9441 if(RequiresOuterTask) {
9442CodeGenFunction::OMPTargetDataInfo InputInfo;
9451llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID,
const Expr*IfCond,
9452llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier>
Device,
9459 const boolOffloadingMandatory = !
CGM.
getLangOpts().OpenMPIsTargetDevice &&
9462assert((OffloadingMandatory || OutlinedFn) &&
"Invalid outlined function!");
9464 const boolRequiresOuterTask =
9480llvm::Value *MapTypesArray =
nullptr;
9481llvm::Value *MapNamesArray =
nullptr;
9483 auto&&TargetThenGen = [
this, OutlinedFn, &
D, &CapturedVars,
9484RequiresOuterTask, &CS, OffloadingMandatory,
Device,
9485OutlinedFnID, &InputInfo, &MapTypesArray,
9489RequiresOuterTask, CS, OffloadingMandatory,
9490 Device, OutlinedFnID, InputInfo, MapTypesArray,
9491MapNamesArray, SizeEmitter, CGF,
CGM);
9494 auto&&TargetElseGen =
9495[
this, OutlinedFn, &
D, &CapturedVars, RequiresOuterTask, &CS,
9498CS, OffloadingMandatory, CGF);
9507 emitIfClause(CGF, IfCond, TargetThenGen, TargetElseGen);
9519StringRef ParentName) {
9524 boolRequiresDeviceCodegen =
9525isa<OMPExecutableDirective>(S) &&
9527cast<OMPExecutableDirective>(S)->getDirectiveKind());
9529 if(RequiresDeviceCodegen) {
9530 const auto&
E= *cast<OMPExecutableDirective>(S);
9537 if(!
OMPBuilder.OffloadInfoManager.hasTargetRegionEntryInfo(EntryInfo))
9540 switch(
E.getDirectiveKind()) {
9543cast<OMPTargetDirective>(
E));
9545 caseOMPD_target_parallel:
9547 CGM, ParentName, cast<OMPTargetParallelDirective>(
E));
9549 caseOMPD_target_teams:
9551 CGM, ParentName, cast<OMPTargetTeamsDirective>(
E));
9553 caseOMPD_target_teams_distribute:
9555 CGM, ParentName, cast<OMPTargetTeamsDistributeDirective>(
E));
9557 caseOMPD_target_teams_distribute_simd:
9559 CGM, ParentName, cast<OMPTargetTeamsDistributeSimdDirective>(
E));
9561 caseOMPD_target_parallel_for:
9563 CGM, ParentName, cast<OMPTargetParallelForDirective>(
E));
9565 caseOMPD_target_parallel_for_simd:
9567 CGM, ParentName, cast<OMPTargetParallelForSimdDirective>(
E));
9569 caseOMPD_target_simd:
9571 CGM, ParentName, cast<OMPTargetSimdDirective>(
E));
9573 caseOMPD_target_teams_distribute_parallel_for:
9576cast<OMPTargetTeamsDistributeParallelForDirective>(
E));
9578 caseOMPD_target_teams_distribute_parallel_for_simd:
9582cast<OMPTargetTeamsDistributeParallelForSimdDirective>(
E));
9584 caseOMPD_target_teams_loop:
9586 CGM, ParentName, cast<OMPTargetTeamsGenericLoopDirective>(
E));
9588 caseOMPD_target_parallel_loop:
9590 CGM, ParentName, cast<OMPTargetParallelGenericLoopDirective>(
E));
9594 caseOMPD_parallel_for:
9595 caseOMPD_parallel_master:
9596 caseOMPD_parallel_sections:
9598 caseOMPD_parallel_for_simd:
9600 caseOMPD_cancellation_point:
9602 caseOMPD_threadprivate:
9613 caseOMPD_taskyield:
9616 caseOMPD_taskgroup:
9622 caseOMPD_target_data:
9623 caseOMPD_target_exit_data:
9624 caseOMPD_target_enter_data:
9625 caseOMPD_distribute:
9626 caseOMPD_distribute_simd:
9627 caseOMPD_distribute_parallel_for:
9628 caseOMPD_distribute_parallel_for_simd:
9629 caseOMPD_teams_distribute:
9630 caseOMPD_teams_distribute_simd:
9631 caseOMPD_teams_distribute_parallel_for:
9632 caseOMPD_teams_distribute_parallel_for_simd:
9633 caseOMPD_target_update:
9634 caseOMPD_declare_simd:
9635 caseOMPD_declare_variant:
9636 caseOMPD_begin_declare_variant:
9637 caseOMPD_end_declare_variant:
9638 caseOMPD_declare_target:
9639 caseOMPD_end_declare_target:
9640 caseOMPD_declare_reduction:
9641 caseOMPD_declare_mapper:
9643 caseOMPD_taskloop_simd:
9644 caseOMPD_master_taskloop:
9645 caseOMPD_master_taskloop_simd:
9646 caseOMPD_parallel_master_taskloop:
9647 caseOMPD_parallel_master_taskloop_simd:
9649 caseOMPD_metadirective:
9652llvm_unreachable(
"Unknown target directive for OpenMP device codegen.");
9657 if(
const auto*
E= dyn_cast<OMPExecutableDirective>(S)) {
9658 if(!
E->hasAssociatedStmt() || !
E->getAssociatedStmt())
9666 if(
const auto*L = dyn_cast<LambdaExpr>(S))
9670 for(
const Stmt*II : S->children())
9675std::optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
9676OMPDeclareTargetDeclAttr::getDeviceType(VD);
9680 if(!IsDevice && DevTy == OMPDeclareTargetDeclAttr::DT_NoHost)
9683 if(IsDevice && DevTy == OMPDeclareTargetDeclAttr::DT_Host)
9692 if(
const auto*FD = dyn_cast<FunctionDecl>(GD.
getDecl()))
9701 if(
const auto*FD = dyn_cast<FunctionDecl>(VD)) {
9710 return!OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD) &&
9728StringRef ParentName =
9733StringRef ParentName =
9740std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
9741OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(
9742cast<VarDecl>(GD.
getDecl()));
9743 if(!Res || *Res == OMPDeclareTargetDeclAttr::MT_Link ||
9744((*Res == OMPDeclareTargetDeclAttr::MT_To ||
9745*Res == OMPDeclareTargetDeclAttr::MT_Enter) &&
9754llvm::Constant *Addr) {
9759std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
9760OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
9764 if(Res && *Res != OMPDeclareTargetDeclAttr::MT_Link &&
9779 autoLinkageForVariable = [&VD,
this]() {
9783std::vector<llvm::GlobalVariable *> GeneratedRefs;
9796 for(
auto*ref : GeneratedRefs)
9801 if(isa<FunctionDecl>(GD.
getDecl()) ||
9802isa<OMPDeclareReductionDecl>(GD.
getDecl()))
9810std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
9811OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
9814 if((*Res == OMPDeclareTargetDeclAttr::MT_To ||
9815*Res == OMPDeclareTargetDeclAttr::MT_Enter) &&
9819assert((*Res == OMPDeclareTargetDeclAttr::MT_Link ||
9820((*Res == OMPDeclareTargetDeclAttr::MT_To ||
9821*Res == OMPDeclareTargetDeclAttr::MT_Enter) &&
9823 "Expected link clause or to clause with unified memory.");
9832 " Expected target-based directive.");
9836 for(
const OMPClause*Clause :
D->clauselists()) {
9837 if(Clause->getClauseKind() == OMPC_unified_shared_memory) {
9839 OMPBuilder.Config.setHasRequiresUnifiedSharedMemory(
true);
9840}
else if(
const auto*AC =
9841dyn_cast<OMPAtomicDefaultMemOrderClause>(Clause)) {
9842 switch(AC->getAtomicDefaultMemOrderKind()) {
9843 caseOMPC_ATOMIC_DEFAULT_MEM_ORDER_acq_rel:
9846 caseOMPC_ATOMIC_DEFAULT_MEM_ORDER_seq_cst:
9849 caseOMPC_ATOMIC_DEFAULT_MEM_ORDER_relaxed:
9865 if(!VD || !VD->
hasAttr<OMPAllocateDeclAttr>())
9867 const auto*A = VD->
getAttr<OMPAllocateDeclAttr>();
9868 switch(A->getAllocatorType()) {
9869 caseOMPAllocateDeclAttr::OMPNullMemAlloc:
9870 caseOMPAllocateDeclAttr::OMPDefaultMemAlloc:
9872 caseOMPAllocateDeclAttr::OMPLargeCapMemAlloc:
9873 caseOMPAllocateDeclAttr::OMPCGroupMemAlloc:
9874 caseOMPAllocateDeclAttr::OMPHighBWMemAlloc:
9875 caseOMPAllocateDeclAttr::OMPLowLatMemAlloc:
9876 caseOMPAllocateDeclAttr::OMPThreadMemAlloc:
9877 caseOMPAllocateDeclAttr::OMPConstMemAlloc:
9878 caseOMPAllocateDeclAttr::OMPPTeamMemAlloc:
9881 caseOMPAllocateDeclAttr::OMPUserDefinedMemAlloc:
9882llvm_unreachable(
"Expected predefined allocator for the variables with the " 9883 "static storage.");
9910 const auto*
D= cast<FunctionDecl>(GD.
getDecl());
9913 if(OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(
D)) {
9915 if(
auto*F = dyn_cast_or_null<llvm::Function>(
9917 return!F->isDeclaration();
9929llvm::Function *OutlinedFn,
9938llvm::Value *Args[] = {
9940CGF.
Builder.getInt32(CapturedVars.size()),
9943RealArgs.append(std::begin(Args), std::end(Args));
9944RealArgs.append(CapturedVars.begin(), CapturedVars.end());
9946llvm::FunctionCallee RTLFn =
OMPBuilder.getOrCreateRuntimeFunction(
9952 const Expr*NumTeams,
9953 const Expr*ThreadLimit,
9960llvm::Value *NumTeamsVal =
9966llvm::Value *ThreadLimitVal =
9973llvm::Value *PushNumTeamsArgs[] = {RTLoc,
getThreadID(CGF,
Loc), NumTeamsVal,
9981 const Expr*ThreadLimit,
9984llvm::Value *ThreadLimitVal =
9991llvm::Value *ThreadLimitArgs[] = {RTLoc,
getThreadID(CGF,
Loc),
10009 usingInsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
10011llvm::Value *IfCondVal =
nullptr;
10016llvm::Value *DeviceID =
nullptr;
10021DeviceID = CGF.
Builder.getInt64(OMP_DEVICEID_UNDEF);
10025MappableExprsHandler::MapCombinedInfoTy CombinedInfo;
10026 autoGenMapInfoCB =
10027[&](InsertPointTy CodeGenIP) -> llvm::OpenMPIRBuilder::MapInfosTy & {
10028CGF.
Builder.restoreIP(CodeGenIP);
10030MappableExprsHandler MEHandler(
D, CGF);
10031MEHandler.generateAllInfo(CombinedInfo,
OMPBuilder);
10033 autoFillInfoMap = [&](MappableExprsHandler::MappingExprInfo &MapExpr) {
10037llvm::codegenoptions::NoDebugInfo) {
10038CombinedInfo.Names.resize(CombinedInfo.Exprs.size());
10039llvm::transform(CombinedInfo.Exprs, CombinedInfo.Names.begin(),
10043 returnCombinedInfo;
10045 usingBodyGenTy = llvm::OpenMPIRBuilder::BodyGenTy;
10046 autoBodyCB = [&](InsertPointTy CodeGenIP, BodyGenTy BodyGenType) {
10047CGF.
Builder.restoreIP(CodeGenIP);
10048 switch(BodyGenType) {
10049 caseBodyGenTy::Priv:
10053 caseBodyGenTy::DupNoPriv:
10059 caseBodyGenTy::NoPriv:
10066 returnInsertPointTy(CGF.
Builder.GetInsertBlock(),
10067CGF.
Builder.GetInsertPoint());
10070 autoDeviceAddrCB = [&](
unsigned intI, llvm::Value *NewDecl) {
10071 if(
const ValueDecl*DevVD = CombinedInfo.DevicePtrDecls[I]) {
10076 autoCustomMapperCB = [&](
unsigned intI) {
10077llvm::Value *MFunc =
nullptr;
10078 if(CombinedInfo.Mappers[I]) {
10079Info.HasMapper =
true;
10081cast<OMPDeclareMapperDecl>(CombinedInfo.Mappers[I]));
10091InsertPointTy CodeGenIP(CGF.
Builder.GetInsertBlock(),
10092CGF.
Builder.GetInsertPoint());
10093llvm::OpenMPIRBuilder::LocationDescription OmpLoc(CodeGenIP);
10094llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
10096OmpLoc, AllocaIP, CodeGenIP, DeviceID, IfCondVal, Info, GenMapInfoCB,
10097 nullptr, BodyCB, DeviceAddrCB, CustomMapperCB, RTLoc));
10098CGF.
Builder.restoreIP(AfterIP);
10107assert((isa<OMPTargetEnterDataDirective>(
D) ||
10108isa<OMPTargetExitDataDirective>(
D) ||
10109isa<OMPTargetUpdateDirective>(
D)) &&
10110 "Expecting either target enter, exit data, or update directives.");
10113llvm::Value *MapTypesArray =
nullptr;
10114llvm::Value *MapNamesArray =
nullptr;
10116 auto&&ThenGen = [
this, &
D,
Device, &InputInfo, &MapTypesArray,
10119llvm::Value *DeviceID =
nullptr;
10124DeviceID = CGF.
Builder.getInt64(OMP_DEVICEID_UNDEF);
10128llvm::Constant *PointerNum =
10135{RTLoc, DeviceID, PointerNum,
10144RuntimeFunction RTLFn;
10145 switch(
D.getDirectiveKind()) {
10146 caseOMPD_target_enter_data:
10147RTLFn = HasNowait ? OMPRTL___tgt_target_data_begin_nowait_mapper
10148: OMPRTL___tgt_target_data_begin_mapper;
10150 caseOMPD_target_exit_data:
10151RTLFn = HasNowait ? OMPRTL___tgt_target_data_end_nowait_mapper
10152: OMPRTL___tgt_target_data_end_mapper;
10154 caseOMPD_target_update:
10155RTLFn = HasNowait ? OMPRTL___tgt_target_data_update_nowait_mapper
10156: OMPRTL___tgt_target_data_update_mapper;
10158 caseOMPD_parallel:
10160 caseOMPD_parallel_for:
10161 caseOMPD_parallel_master:
10162 caseOMPD_parallel_sections:
10163 caseOMPD_for_simd:
10164 caseOMPD_parallel_for_simd:
10166 caseOMPD_cancellation_point:
10168 caseOMPD_threadprivate:
10169 caseOMPD_allocate:
10174 caseOMPD_sections:
10178 caseOMPD_critical:
10179 caseOMPD_taskyield:
10181 caseOMPD_taskwait:
10182 caseOMPD_taskgroup:
10188 caseOMPD_target_data:
10189 caseOMPD_distribute:
10190 caseOMPD_distribute_simd:
10191 caseOMPD_distribute_parallel_for:
10192 caseOMPD_distribute_parallel_for_simd:
10193 caseOMPD_teams_distribute:
10194 caseOMPD_teams_distribute_simd:
10195 caseOMPD_teams_distribute_parallel_for:
10196 caseOMPD_teams_distribute_parallel_for_simd:
10197 caseOMPD_declare_simd:
10198 caseOMPD_declare_variant:
10199 caseOMPD_begin_declare_variant:
10200 caseOMPD_end_declare_variant:
10201 caseOMPD_declare_target:
10202 caseOMPD_end_declare_target:
10203 caseOMPD_declare_reduction:
10204 caseOMPD_declare_mapper:
10205 caseOMPD_taskloop:
10206 caseOMPD_taskloop_simd:
10207 caseOMPD_master_taskloop:
10208 caseOMPD_master_taskloop_simd:
10209 caseOMPD_parallel_master_taskloop:
10210 caseOMPD_parallel_master_taskloop_simd:
10212 caseOMPD_target_simd:
10213 caseOMPD_target_teams_distribute:
10214 caseOMPD_target_teams_distribute_simd:
10215 caseOMPD_target_teams_distribute_parallel_for:
10216 caseOMPD_target_teams_distribute_parallel_for_simd:
10217 caseOMPD_target_teams:
10218 caseOMPD_target_parallel:
10219 caseOMPD_target_parallel_for:
10220 caseOMPD_target_parallel_for_simd:
10221 caseOMPD_requires:
10222 caseOMPD_metadirective:
10225llvm_unreachable(
"Unexpected standalone target data directive.");
10229OffloadingArgs.push_back(llvm::Constant::getNullValue(CGF.
Int32Ty));
10230OffloadingArgs.push_back(llvm::Constant::getNullValue(CGF.
VoidPtrTy));
10231OffloadingArgs.push_back(llvm::Constant::getNullValue(CGF.
Int32Ty));
10232OffloadingArgs.push_back(llvm::Constant::getNullValue(CGF.
VoidPtrTy));
10239 auto&&TargetThenGen = [
this, &ThenGen, &
D, &InputInfo, &MapTypesArray,
10243MappableExprsHandler::MapCombinedInfoTy CombinedInfo;
10245MappableExprsHandler MEHandler(
D, CGF);
10262MapTypesArray = Info.RTArgs.MapTypesArray;
10263MapNamesArray = Info.RTArgs.MapNamesArray;
10264 if(RequiresOuterTask)
10290structParamAttrTy {
10292llvm::APSInt StrideOrArg;
10293llvm::APSInt Alignment;
10294 boolHasVarStride =
false;
10327 unsignedOffset = 0;
10328 if(
const auto*MD = dyn_cast<CXXMethodDecl>(FD)) {
10329 if(ParamAttrs[Offset].Kind ==
Vector)
10330CDT =
C.getPointerType(
C.getRecordType(MD->
getParent()));
10335 if(ParamAttrs[I + Offset].Kind ==
Vector) {
10347 return C.getTypeSize(CDT);
10355llvm::raw_svector_ostream Out(Buffer);
10356 for(
const auto&ParamAttr : ParamAttrs) {
10357 switch(ParamAttr.Kind) {
10377 if(ParamAttr.HasVarStride)
10378Out <<
"s"<< ParamAttr.StrideOrArg;
10379 else if(ParamAttr.Kind == Linear || ParamAttr.Kind == LinearRef ||
10380ParamAttr.Kind == LinearUVal || ParamAttr.Kind == LinearVal) {
10383 if(ParamAttr.StrideOrArg < 0)
10384Out <<
'n'<< -ParamAttr.StrideOrArg;
10385 else if(ParamAttr.StrideOrArg != 1)
10386Out << ParamAttr.StrideOrArg;
10389 if(!!ParamAttr.Alignment)
10390Out <<
'a'<< ParamAttr.Alignment;
10393 returnstd::string(Out.str());
10398 constllvm::APSInt &VLENVal,
10400OMPDeclareSimdDeclAttr::BranchStateTy State) {
10403 unsignedVecRegSize;
10405ISADataTy ISAData[] = {
10421 caseOMPDeclareSimdDeclAttr::BS_Undefined:
10422Masked.push_back(
'N');
10423Masked.push_back(
'M');
10425 caseOMPDeclareSimdDeclAttr::BS_Notinbranch:
10426Masked.push_back(
'N');
10428 caseOMPDeclareSimdDeclAttr::BS_Inbranch:
10429Masked.push_back(
'M');
10432 for(
charMask : Masked) {
10433 for(
constISADataTy &
Data: ISAData) {
10435llvm::raw_svector_ostream Out(Buffer);
10436Out <<
"_ZGV"<<
Data.ISA << Mask;
10439assert(NumElts &&
"Non-zero simdlen/cdtsize expected");
10440Out << llvm::APSInt::getUnsigned(
Data.VecRegSize / NumElts);
10445Out <<
'_'<< Fn->getName();
10446Fn->addFnAttr(Out.str());
10464 if(Kind == ParamKindTy::Uniform)
10467 if(Kind == ParamKindTy::LinearUVal || Kind == ParamKindTy::LinearRef)
10470 if((Kind == ParamKindTy::Linear || Kind == ParamKindTy::LinearVal) &&
10480 unsignedSize =
C.getTypeSize(QT);
10483 if(Size != 8 && Size != 16 && Size != 32 && Size != 64 && Size != 128)
10507 return C.getTypeSize(PTy);
10510 return C.getTypeSize(QT);
10512 return C.getTypeSize(
C.getUIntPtrType());
10518staticstd::tuple<unsigned, unsigned, bool>
10524 boolOutputBecomesInput =
false;
10528Sizes.push_back(
getAArch64LS(RetType, ParamKindTy::Vector,
C));
10530OutputBecomesInput =
true;
10534Sizes.push_back(
getAArch64LS(QT, ParamAttrs[I].Kind,
C));
10537assert(!Sizes.empty() &&
"Unable to determine NDS and WDS.");
10540assert(llvm::all_of(Sizes,
10541[](
unsignedSize) {
10542 returnSize == 8 || Size == 16 || Size == 32 ||
10543Size == 64 || Size == 128;
10547 returnstd::make_tuple(*std::min_element(std::begin(Sizes), std::end(Sizes)),
10548*std::max_element(std::begin(Sizes), std::end(Sizes)),
10549OutputBecomesInput);
10555template<
typenameT>
10557 charISA, StringRef ParSeq,
10558StringRef MangledName,
boolOutputBecomesInput,
10559llvm::Function *Fn) {
10561llvm::raw_svector_ostream Out(Buffer);
10562Out << Prefix << ISA << LMask << VLEN;
10563 if(OutputBecomesInput)
10565Out << ParSeq <<
"_"<< MangledName;
10566Fn->addFnAttr(Out.str());
10572StringRef Prefix,
charISA,
10573StringRef ParSeq, StringRef MangledName,
10574 boolOutputBecomesInput,
10575llvm::Function *Fn) {
10579OutputBecomesInput, Fn);
10581OutputBecomesInput, Fn);
10585OutputBecomesInput, Fn);
10587OutputBecomesInput, Fn);
10591OutputBecomesInput, Fn);
10593OutputBecomesInput, Fn);
10598OutputBecomesInput, Fn);
10601llvm_unreachable(
"Scalar type is too wide.");
10609OMPDeclareSimdDeclAttr::BranchStateTy State, StringRef MangledName,
10610 charISA,
unsignedVecRegSize, llvm::Function *Fn,
SourceLocationSLoc) {
10614 const unsignedNDS = std::get<0>(
Data);
10615 const unsignedWDS = std::get<1>(
Data);
10616 const boolOutputBecomesInput = std::get<2>(
Data);
10620 if(UserVLEN == 1) {
10623 "The clause simdlen(1) has no effect when targeting aarch64.");
10630 if(ISA ==
'n'&& UserVLEN && !llvm::isPowerOf2_32(UserVLEN)) {
10633 "power of 2 when targeting Advanced SIMD.");
10640 if(ISA ==
's'&& UserVLEN != 0) {
10641 if((UserVLEN * WDS > 2048) || (UserVLEN * WDS % 128 != 0)) {
10644 "lanes in the architectural constraints " 10645 "for SVE (min is 128-bit, max is " 10646 "2048-bit, by steps of 128-bit)");
10654StringRef Prefix =
"_ZGV";
10660OutputBecomesInput, Fn);
10662assert(ISA ==
'n'&&
"Expected ISA either 's' or 'n'.");
10666 caseOMPDeclareSimdDeclAttr::BS_Undefined:
10668OutputBecomesInput, Fn);
10670OutputBecomesInput, Fn);
10672 caseOMPDeclareSimdDeclAttr::BS_Notinbranch:
10674OutputBecomesInput, Fn);
10676 caseOMPDeclareSimdDeclAttr::BS_Inbranch:
10678OutputBecomesInput, Fn);
10688OutputBecomesInput, Fn);
10690assert(ISA ==
'n'&&
"Expected ISA either 's' or 'n'.");
10695 caseOMPDeclareSimdDeclAttr::BS_Undefined:
10697OutputBecomesInput, Fn);
10699OutputBecomesInput, Fn);
10701 caseOMPDeclareSimdDeclAttr::BS_Notinbranch:
10703OutputBecomesInput, Fn);
10705 caseOMPDeclareSimdDeclAttr::BS_Inbranch:
10707OutputBecomesInput, Fn);
10715llvm::Function *Fn) {
10720llvm::DenseMap<const Decl *, unsigned> ParamPositions;
10721 if(isa<CXXMethodDecl>(FD))
10722ParamPositions.try_emplace(FD, 0);
10723 unsignedParamPos = ParamPositions.size();
10725ParamPositions.try_emplace(
P->getCanonicalDecl(), ParamPos);
10731 for(
const Expr*
E:
Attr->uniforms()) {
10734 if(isa<CXXThisExpr>(
E)) {
10735Pos = ParamPositions[FD];
10737 const auto*PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(
E)->getDecl())
10738->getCanonicalDecl();
10739 autoIt = ParamPositions.find(PVD);
10740assert(It != ParamPositions.end() &&
"Function parameter not found");
10743ParamAttrs[Pos].Kind = Uniform;
10746 auto*NI =
Attr->alignments_begin();
10747 for(
const Expr*
E:
Attr->aligneds()) {
10751 if(isa<CXXThisExpr>(
E)) {
10752Pos = ParamPositions[FD];
10755 const auto*PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(
E)->getDecl())
10756->getCanonicalDecl();
10757 autoIt = ParamPositions.find(PVD);
10758assert(It != ParamPositions.end() &&
"Function parameter not found");
10760ParmTy = PVD->getType();
10762ParamAttrs[Pos].Alignment =
10764? (*NI)->EvaluateKnownConstInt(
C)
10765: llvm::APSInt::getUnsigned(
10766 C.toCharUnitsFromBits(
C.getOpenMPDefaultSimdAlign(ParmTy))
10771 auto*SI =
Attr->steps_begin();
10772 auto*MI =
Attr->modifiers_begin();
10773 for(
const Expr*
E:
Attr->linears()) {
10776 boolIsReferenceType =
false;
10779 unsignedPtrRescalingFactor = 1;
10780 if(isa<CXXThisExpr>(
E)) {
10781Pos = ParamPositions[FD];
10782 auto*
P= cast<PointerType>(
E->
getType());
10787 const auto*PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(
E)->getDecl())
10788->getCanonicalDecl();
10789 autoIt = ParamPositions.find(PVD);
10790assert(It != ParamPositions.end() &&
"Function parameter not found");
10792 if(
auto*
P= dyn_cast<PointerType>(PVD->getType()))
10796 else if(PVD->getType()->isReferenceType()) {
10797IsReferenceType =
true;
10798PtrRescalingFactor =
10804ParamAttrTy &ParamAttr = ParamAttrs[Pos];
10805 if(*MI == OMPC_LINEAR_ref)
10806ParamAttr.Kind = LinearRef;
10807 else if(*MI == OMPC_LINEAR_uval)
10808ParamAttr.Kind = LinearUVal;
10809 else if(IsReferenceType)
10810ParamAttr.Kind = LinearVal;
10812ParamAttr.Kind = Linear;
10814ParamAttr.StrideOrArg = llvm::APSInt::getUnsigned(1);
10818 if(
const auto*DRE =
10819cast<DeclRefExpr>((*SI)->IgnoreParenImpCasts())) {
10820 if(
const auto*StridePVD =
10821dyn_cast<ParmVarDecl>(DRE->getDecl())) {
10822ParamAttr.HasVarStride =
true;
10823 autoIt = ParamPositions.find(StridePVD->getCanonicalDecl());
10824assert(It != ParamPositions.end() &&
10825 "Function parameter not found");
10826ParamAttr.StrideOrArg = llvm::APSInt::getUnsigned(It->second);
10830ParamAttr.StrideOrArg =
Result.Val.getInt();
10836 if(!ParamAttr.HasVarStride &&
10837(ParamAttr.Kind == Linear || ParamAttr.Kind == LinearRef))
10838ParamAttr.StrideOrArg = ParamAttr.StrideOrArg * PtrRescalingFactor;
10842llvm::APSInt VLENVal;
10844 const Expr*VLENExpr =
Attr->getSimdlen();
10849OMPDeclareSimdDeclAttr::BranchStateTy State =
Attr->getBranchState();
10852}
else if(
CGM.
getTriple().getArch() == llvm::Triple::aarch64) {
10853 unsignedVLEN = VLENVal.getExtValue();
10854StringRef MangledName = Fn->getName();
10857MangledName,
's', 128, Fn, ExprLoc);
10860MangledName,
'n', 128, Fn, ExprLoc);
10871 static const intDoacrossFinArgs = 2;
10874llvm::FunctionCallee RTLFn;
10875llvm::Value *Args[DoacrossFinArgs];
10878DoacrossCleanupTy(llvm::FunctionCallee RTLFn,
10881assert(CallArgs.size() == DoacrossFinArgs);
10882std::copy(CallArgs.begin(), CallArgs.end(), std::begin(Args));
10899 QualTypeInt64Ty =
C.getIntTypeForBitwidth(
64,
true);
10907RD =
C.buildImplicitRecord(
"kmp_dim");
10917llvm::APInt Size(
32, NumIterations.size());
10923 enum{ LowerFD = 0, UpperFD, StrideFD };
10925 for(
unsignedI = 0,
E= NumIterations.size(); I <
E; ++I) {
10930DimsLVal, *std::next(RD->
field_begin(), UpperFD));
10932CGF.
EmitScalarExpr(NumIterations[I]), NumIterations[I]->getType(),
10933Int64Ty, NumIterations[I]->getExprLoc());
10937DimsLVal, *std::next(RD->
field_begin(), StrideFD));
10944llvm::Value *Args[] = {
10947llvm::ConstantInt::getSigned(
CGM.
Int32Ty, NumIterations.size()),
10952llvm::FunctionCallee RTLFn =
OMPBuilder.getOrCreateRuntimeFunction(
10955llvm::Value *FiniArgs[DoacrossCleanupTy::DoacrossFinArgs] = {
10957llvm::FunctionCallee FiniRTLFn =
OMPBuilder.getOrCreateRuntimeFunction(
10963template<
typenameT>
10965 const T*
C, llvm::Value *ULoc,
10966llvm::Value *ThreadID) {
10969llvm::APInt Size(
32,
C->getNumLoops());
10973 for(
unsignedI = 0,
E=
C->getNumLoops(); I <
E; ++I) {
10974 const Expr*CounterVal =
C->getLoopData(I);
10975assert(CounterVal);
10982llvm::Value *Args[] = {
10985llvm::FunctionCallee RTLFn;
10987OMPDoacrossKind<T> ODK;
10988 if(ODK.isSource(
C)) {
10990OMPRTL___kmpc_doacross_post);
10992assert(ODK.isSink(
C) &&
"Expect sink modifier.");
10994OMPRTL___kmpc_doacross_wait);
11001 returnEmitDoacrossOrdered<OMPDependClause>(
11008 returnEmitDoacrossOrdered<OMPDoacrossClause>(
11014llvm::FunctionCallee Callee,
11016assert(
Loc.
isValid() &&
"Outlined function call location must be valid.");
11019 if(
auto*Fn = dyn_cast<llvm::Function>(Callee.getCallee())) {
11020 if(Fn->doesNotThrow()) {
11035 if(
const auto*FD = dyn_cast<FunctionDecl>(
D))
11036 if(OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(FD))
11042 const VarDecl*TargetParam)
const{
11049 const Expr*Allocator) {
11050llvm::Value *AllocVal;
11057Allocator->getExprLoc());
11060AllocVal = llvm::Constant::getNullValue(
11070 if(!AllocateAlignment)
11073 returnllvm::ConstantInt::get(
CGM.
SizeTy, AllocateAlignment->getQuantity());
11086 autoI = UntiedData.find(VD);
11087 if(I != UntiedData.end()) {
11088UntiedAddr = I->second.first;
11089UntiedRealAddr = I->second.second;
11093 if(CVD->
hasAttr<OMPAllocateDeclAttr>()) {
11102Size = CGF.
Builder.CreateNUWAdd(
11111 const auto*AA = CVD->
getAttr<OMPAllocateDeclAttr>();
11112 const Expr*Allocator = AA->getAllocator();
11116Args.push_back(ThreadID);
11118Args.push_back(Alignment);
11119Args.push_back(Size);
11120Args.push_back(AllocVal);
11121llvm::omp::RuntimeFunction FnID =
11122Alignment ? OMPRTL___kmpc_aligned_alloc : OMPRTL___kmpc_alloc;
11126llvm::FunctionCallee FiniRTLFn =
OMPBuilder.getOrCreateRuntimeFunction(
11136llvm::FunctionCallee RTLFn;
11139 const Expr*AllocExpr;
11142OMPAllocateCleanupTy(llvm::FunctionCallee RTLFn,
11144 const Expr*AllocExpr)
11145: RTLFn(RTLFn), LocEncoding(LocEncoding), Addr(Addr),
11146AllocExpr(AllocExpr) {}
11150llvm::Value *Args[3];
11156Args[2] = AllocVal;
11164CGF.
EHStack.pushCleanup<OMPAllocateCleanupTy>(
11166VDAddr, Allocator);
11167 if(UntiedRealAddr.
isValid())
11168 if(
auto*Region =
11170Region->emitUntiedSwitch(CGF);
11187assert(CGM.
getLangOpts().OpenMP &&
"Not in OpenMP mode.");
11193 for(
const Stmt*Ref :
C->private_refs()) {
11194 const auto*SimpleRefExpr = cast<Expr>(Ref)->IgnoreParenImpCasts();
11196 if(
const auto*DRE = dyn_cast<DeclRefExpr>(SimpleRefExpr)) {
11197VD = DRE->getDecl();
11199 const auto*ME = cast<MemberExpr>(SimpleRefExpr);
11200assert((ME->isImplicitCXXThis() ||
11201isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts())) &&
11202 "Expected member of current class.");
11203VD = ME->getMemberDecl();
11219std::pair<Address, Address>> &LocalVars)
11220:
CGM(CGF.
CGM), NeedToPush(!LocalVars.empty()) {
11237 returnllvm::any_of(
11242voidCGOpenMPRuntime::LastprivateConditionalRAII::tryToDisableInnerAnalysis(
11246llvm::DenseSet<CanonicalDeclPtr<const Decl>> NeedToCheckForLPCs;
11252 const CapturedStmt*CS = S.getCapturedStmt(CaptureRegions.front());
11260 for(
const Expr*Ref :
C->varlist()) {
11261 if(!Ref->getType()->isScalarType())
11263 const auto*DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
11266NeedToCheckForLPCs.insert(DRE->getDecl());
11270 for(
const Expr*Ref :
C->varlist()) {
11271 if(!Ref->getType()->isScalarType())
11273 const auto*DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
11276NeedToCheckForLPCs.insert(DRE->getDecl());
11280 for(
const Expr*Ref :
C->varlist()) {
11281 if(!Ref->getType()->isScalarType())
11283 const auto*DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
11286NeedToCheckForLPCs.insert(DRE->getDecl());
11290 for(
const Expr*Ref :
C->varlist()) {
11291 if(!Ref->getType()->isScalarType())
11293 const auto*DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
11296NeedToCheckForLPCs.insert(DRE->getDecl());
11300 for(
const Expr*Ref :
C->varlist()) {
11301 if(!Ref->getType()->isScalarType())
11303 const auto*DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
11306NeedToCheckForLPCs.insert(DRE->getDecl());
11309 for(
const Decl*VD : NeedToCheckForLPCs) {
11310 for(
constLastprivateConditionalData &
Data:
11312 if(
Data.DeclToUniqueName.count(VD) > 0) {
11313 if(!
Data.Disabled)
11314NeedToAddForLPCsAsDisabled.insert(VD);
11321CGOpenMPRuntime::LastprivateConditionalRAII::LastprivateConditionalRAII(
11324Action((
CGM.getLangOpts().OpenMP >= 50 &&
11327 return C->getKind() ==
11328OMPC_LASTPRIVATE_conditional;
11330? ActionToDo::PushAsLastprivateConditional
11331: ActionToDo::DoNotPush) {
11333 if(
CGM.
getLangOpts().OpenMP < 50 || Action == ActionToDo::DoNotPush)
11335assert(Action == ActionToDo::PushAsLastprivateConditional &&
11336 "Expected a push action.");
11340 if(
C->getKind() != OMPC_LASTPRIVATE_conditional)
11343 for(
const Expr*Ref :
C->varlist()) {
11344 Data.DeclToUniqueName.insert(std::make_pair(
11345cast<DeclRefExpr>(Ref->IgnoreParenImpCasts())->getDecl(),
11349 Data.IVLVal = IVLVal;
11353CGOpenMPRuntime::LastprivateConditionalRAII::LastprivateConditionalRAII(
11355:
CGM(CGF.
CGM), Action(ActionToDo::DoNotPush) {
11356assert(CGM.
getLangOpts().OpenMP &&
"Not in OpenMP mode.");
11359llvm::DenseSet<CanonicalDeclPtr<const Decl>> NeedToAddForLPCsAsDisabled;
11360tryToDisableInnerAnalysis(S, NeedToAddForLPCsAsDisabled);
11361 if(!NeedToAddForLPCsAsDisabled.empty()) {
11362Action = ActionToDo::DisableLastprivateConditional;
11363LastprivateConditionalData &
Data=
11365 for(
const Decl*VD : NeedToAddForLPCsAsDisabled)
11368 Data.Disabled =
true;
11381 if(Action == ActionToDo::DisableLastprivateConditional) {
11383 "Expected list of disabled private vars.");
11386 if(Action == ActionToDo::PushAsLastprivateConditional) {
11389 "Expected list of lastprivate conditional vars.");
11402 autoVI = I->getSecond().find(VD);
11403 if(VI == I->getSecond().end()) {
11404 RecordDecl*RD =
C.buildImplicitRecord(
"lasprivate.conditional");
11409NewType =
C.getRecordType(RD);
11412I->getSecond().try_emplace(VD, NewType, VDField, FiredField, BaseLVal);
11414NewType = std::get<0>(VI->getSecond());
11415VDField = std::get<1>(VI->getSecond());
11416FiredField = std::get<2>(VI->getSecond());
11417BaseLVal = std::get<3>(VI->getSecond());
11429classLastprivateConditionalRefChecker final
11432 const Expr*FoundE =
nullptr;
11433 const Decl*FoundD =
nullptr;
11434StringRef UniqueDeclName;
11436llvm::Function *FoundFn =
nullptr;
11442llvm::reverse(LPM)) {
11443 autoIt =
D.DeclToUniqueName.find(
E->getDecl());
11444 if(It ==
D.DeclToUniqueName.end())
11449FoundD =
E->getDecl()->getCanonicalDecl();
11450UniqueDeclName = It->second;
11451IVLVal =
D.IVLVal;
11455 returnFoundE ==
E;
11458 if(!CodeGenFunction::IsWrappedCXXThis(
E->getBase()))
11461llvm::reverse(LPM)) {
11462 autoIt =
D.DeclToUniqueName.find(
E->getMemberDecl());
11463 if(It ==
D.DeclToUniqueName.end())
11468FoundD =
E->getMemberDecl()->getCanonicalDecl();
11469UniqueDeclName = It->second;
11470IVLVal =
D.IVLVal;
11474 returnFoundE ==
E;
11476 boolVisitStmt(
const Stmt*S) {
11477 for(
const Stmt*Child : S->children()) {
11480 if(
const auto*
E= dyn_cast<Expr>(Child))
11488 explicitLastprivateConditionalRefChecker(
11491std::tuple<const Expr *, const Decl *, StringRef, LValue, llvm::Function *>
11492getFoundData()
const{
11493 returnstd::make_tuple(FoundE, FoundD, UniqueDeclName, IVLVal, FoundFn);
11500StringRef UniqueDeclName,
11506llvm::Constant *LastIV =
OMPBuilder.getOrCreateInternalVariable(
11507LLIVTy,
getName({UniqueDeclName,
"iv"}));
11508cast<llvm::GlobalVariable>(LastIV)->setAlignment(
11515llvm::GlobalVariable *
Last=
OMPBuilder.getOrCreateInternalVariable(
11517cast<llvm::GlobalVariable>(
Last)->setAlignment(
11531 auto&&CodeGen = [&LastIVLVal, &IVLVal, IVVal, &LVal, &LastLVal,
11537llvm::Value *CmpRes;
11539CmpRes = CGF.
Builder.CreateICmpSLE(LastIVVal, IVVal);
11542 "Loop iteration variable must be integer.");
11543CmpRes = CGF.
Builder.CreateICmpULE(LastIVVal, IVVal);
11547CGF.
Builder.CreateCondBr(CmpRes, ThenBB, ExitBB);
11568 "Aggregates are not supported in lastprivate conditional.");
11591 if(!Checker.Visit(LHS))
11593 const Expr*FoundE;
11594 const Decl*FoundD;
11595StringRef UniqueDeclName;
11597llvm::Function *FoundFn;
11598std::tie(FoundE, FoundD, UniqueDeclName, IVLVal, FoundFn) =
11599Checker.getFoundData();
11600 if(FoundFn != CGF.
CurFn) {
11605 "Lastprivate conditional is not found in outer region.");
11606 QualTypeStructTy = std::get<0>(It->getSecond());
11607 const FieldDecl* FiredDecl = std::get<2>(It->getSecond());
11618FiredLVal, llvm::AtomicOrdering::Unordered,
11636 autoIt = llvm::find_if(
11638 if(It ==
Range.end() || It->Fn != CGF.
CurFn)
11642 "Lastprivates must be registered already.");
11645 const CapturedStmt*CS =
D.getCapturedStmt(CaptureRegions.back());
11646 for(
const auto&Pair : It->DeclToUniqueName) {
11647 const auto*VD = cast<VarDecl>(Pair.first->getCanonicalDecl());
11650 autoI = LPCI->getSecond().find(Pair.first);
11651assert(I != LPCI->getSecond().end() &&
11652 "Lastprivate must be rehistered already.");
11654 LValueBaseLVal = std::get<3>(I->getSecond());
11658llvm::Value *Cmp = CGF.
Builder.CreateIsNotNull(Res);
11662CGF.
Builder.CreateCondBr(Cmp, ThenBB, DoneBB);
11687 "Unknown lastprivate conditional variable.");
11688StringRef UniqueName = It->second;
11689llvm::GlobalVariable *GV =
CGM.
getModule().getNamedGlobal(UniqueName);
11703llvm_unreachable(
"Not supported in SIMD-only mode");
11710llvm_unreachable(
"Not supported in SIMD-only mode");
11717 boolTied,
unsigned&NumberOfParts) {
11718llvm_unreachable(
"Not supported in SIMD-only mode");
11723llvm::Function *OutlinedFn,
11725 const Expr*IfCond,
11726llvm::Value *NumThreads) {
11727llvm_unreachable(
"Not supported in SIMD-only mode");
11733 const Expr*Hint) {
11734llvm_unreachable(
"Not supported in SIMD-only mode");
11740llvm_unreachable(
"Not supported in SIMD-only mode");
11746 const Expr*Filter) {
11747llvm_unreachable(
"Not supported in SIMD-only mode");
11752llvm_unreachable(
"Not supported in SIMD-only mode");
11758llvm_unreachable(
"Not supported in SIMD-only mode");
11766llvm_unreachable(
"Not supported in SIMD-only mode");
11773llvm_unreachable(
"Not supported in SIMD-only mode");
11780 boolForceSimpleCall) {
11781llvm_unreachable(
"Not supported in SIMD-only mode");
11788llvm_unreachable(
"Not supported in SIMD-only mode");
11793llvm_unreachable(
"Not supported in SIMD-only mode");
11799llvm_unreachable(
"Not supported in SIMD-only mode");
11805llvm_unreachable(
"Not supported in SIMD-only mode");
11812llvm_unreachable(
"Not supported in SIMD-only mode");
11818llvm_unreachable(
"Not supported in SIMD-only mode");
11823 unsignedIVSize,
boolIVSigned,
11826llvm_unreachable(
"Not supported in SIMD-only mode");
11830llvm::Value *NumThreads,
11832llvm_unreachable(
"Not supported in SIMD-only mode");
11836ProcBindKind ProcBind,
11838llvm_unreachable(
"Not supported in SIMD-only mode");
11845llvm_unreachable(
"Not supported in SIMD-only mode");
11851llvm_unreachable(
"Not supported in SIMD-only mode");
11856llvm_unreachable(
"Not supported in SIMD-only mode");
11862llvm::AtomicOrdering AO) {
11863llvm_unreachable(
"Not supported in SIMD-only mode");
11868llvm::Function *TaskFunction,
11870 const Expr*IfCond,
11872llvm_unreachable(
"Not supported in SIMD-only mode");
11879llvm_unreachable(
"Not supported in SIMD-only mode");
11886assert(Options.SimpleReduction &&
"Only simple reduction is expected.");
11888ReductionOps, Options);
11894llvm_unreachable(
"Not supported in SIMD-only mode");
11899 boolIsWorksharingReduction) {
11900llvm_unreachable(
"Not supported in SIMD-only mode");
11907llvm_unreachable(
"Not supported in SIMD-only mode");
11912llvm::Value *ReductionsPtr,
11914llvm_unreachable(
"Not supported in SIMD-only mode");
11920llvm_unreachable(
"Not supported in SIMD-only mode");
11926llvm_unreachable(
"Not supported in SIMD-only mode");
11932llvm_unreachable(
"Not supported in SIMD-only mode");
11937llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
11939llvm_unreachable(
"Not supported in SIMD-only mode");
11944llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID,
const Expr*IfCond,
11945llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier>
Device,
11949llvm_unreachable(
"Not supported in SIMD-only mode");
11953llvm_unreachable(
"Not supported in SIMD-only mode");
11957llvm_unreachable(
"Not supported in SIMD-only mode");
11967llvm::Function *OutlinedFn,
11969llvm_unreachable(
"Not supported in SIMD-only mode");
11973 const Expr*NumTeams,
11974 const Expr*ThreadLimit,
11976llvm_unreachable(
"Not supported in SIMD-only mode");
11983llvm_unreachable(
"Not supported in SIMD-only mode");
11989llvm_unreachable(
"Not supported in SIMD-only mode");
11995llvm_unreachable(
"Not supported in SIMD-only mode");
12000llvm_unreachable(
"Not supported in SIMD-only mode");
12005llvm_unreachable(
"Not supported in SIMD-only mode");
12010 const VarDecl*NativeParam)
const{
12011llvm_unreachable(
"Not supported in SIMD-only mode");
12017 const VarDecl*TargetParam)
const{
12018llvm_unreachable(
"Not supported in SIMD-only mode");
static llvm::Value * emitCopyprivateCopyFunction(CodeGenModule &CGM, llvm::Type *ArgsElemType, ArrayRef< const Expr * > CopyprivateVars, ArrayRef< const Expr * > DestExprs, ArrayRef< const Expr * > SrcExprs, ArrayRef< const Expr * > AssignmentOps, SourceLocation Loc)
static StringRef getIdentStringFromSourceLocation(CodeGenFunction &CGF, SourceLocation Loc, SmallString< 128 > &Buffer)
static void emitOffloadingArraysAndArgs(CodeGenFunction &CGF, MappableExprsHandler::MapCombinedInfoTy &CombinedInfo, CGOpenMPRuntime::TargetDataInfo &Info, llvm::OpenMPIRBuilder &OMPBuilder, bool IsNonContiguous=false, bool ForEndCall=false)
Emit the arrays used to pass the captures and map information to the offloading runtime library.
static RecordDecl * createKmpTaskTWithPrivatesRecordDecl(CodeGenModule &CGM, QualType KmpTaskTQTy, ArrayRef< PrivateDataTy > Privates)
static void emitInitWithReductionInitializer(CodeGenFunction &CGF, const OMPDeclareReductionDecl *DRD, const Expr *InitOp, Address Private, Address Original, QualType Ty)
static Address castToBase(CodeGenFunction &CGF, QualType BaseTy, QualType ElTy, Address OriginalBaseAddress, llvm::Value *Addr)
static void emitPrivatesInit(CodeGenFunction &CGF, const OMPExecutableDirective &D, Address KmpTaskSharedsPtr, LValue TDBase, const RecordDecl *KmpTaskTWithPrivatesQTyRD, QualType SharedsTy, QualType SharedsPtrTy, const OMPTaskDataTy &Data, ArrayRef< PrivateDataTy > Privates, bool ForDup)
Emit initialization for private variables in task-based directives.
static void emitClauseForBareTargetDirective(CodeGenFunction &CGF, const OMPExecutableDirective &D, llvm::SmallVectorImpl< llvm::Value * > &Values)
static llvm::Value * emitDestructorsFunction(CodeGenModule &CGM, SourceLocation Loc, QualType KmpInt32Ty, QualType KmpTaskTWithPrivatesPtrQTy, QualType KmpTaskTWithPrivatesQTy)
static unsigned evaluateCDTSize(const FunctionDecl *FD, ArrayRef< ParamAttrTy > ParamAttrs)
static void EmitOMPAggregateReduction(CodeGenFunction &CGF, QualType Type, const VarDecl *LHSVar, const VarDecl *RHSVar, const llvm::function_ref< void(CodeGenFunction &CGF, const Expr *, const Expr *, const Expr *)> &RedOpGen, const Expr *XExpr=nullptr, const Expr *EExpr=nullptr, const Expr *UpExpr=nullptr)
Emit reduction operation for each element of array (required for array sections) LHS op = RHS.
static void emitTargetCallFallback(CGOpenMPRuntime *OMPRuntime, llvm::Function *OutlinedFn, const OMPExecutableDirective &D, llvm::SmallVectorImpl< llvm::Value * > &CapturedVars, bool RequiresOuterTask, const CapturedStmt &CS, bool OffloadingMandatory, CodeGenFunction &CGF)
static llvm::Value * emitReduceInitFunction(CodeGenModule &CGM, SourceLocation Loc, ReductionCodeGen &RCG, unsigned N)
Emits reduction initializer function:
static RTCancelKind getCancellationKind(OpenMPDirectiveKind CancelRegion)
static void emitDependData(CodeGenFunction &CGF, QualType &KmpDependInfoTy, llvm::PointerUnion< unsigned *, LValue * > Pos, const OMPTaskDataTy::DependData &Data, Address DependenciesArray)
static llvm::Value * emitTaskPrivateMappingFunction(CodeGenModule &CGM, SourceLocation Loc, const OMPTaskDataTy &Data, QualType PrivatesQTy, ArrayRef< PrivateDataTy > Privates)
Emit a privates mapping function for correct handling of private and firstprivate variables.
static llvm::Value * emitReduceCombFunction(CodeGenModule &CGM, SourceLocation Loc, ReductionCodeGen &RCG, unsigned N, const Expr *ReductionOp, const Expr *LHS, const Expr *RHS, const Expr *PrivateRef)
Emits reduction combiner function:
static RecordDecl * createPrivatesRecordDecl(CodeGenModule &CGM, ArrayRef< PrivateDataTy > Privates)
static llvm::Value * getAllocatorVal(CodeGenFunction &CGF, const Expr *Allocator)
Return allocator value from expression, or return a null allocator (default when no allocator specifi...
static llvm::Function * emitProxyTaskFunction(CodeGenModule &CGM, SourceLocation Loc, OpenMPDirectiveKind Kind, QualType KmpInt32Ty, QualType KmpTaskTWithPrivatesPtrQTy, QualType KmpTaskTWithPrivatesQTy, QualType KmpTaskTQTy, QualType SharedsPtrTy, llvm::Function *TaskFunction, llvm::Value *TaskPrivatesMap)
Emit a proxy function which accepts kmp_task_t as the second argument.
static void addAArch64VectorName(T VLEN, StringRef LMask, StringRef Prefix, char ISA, StringRef ParSeq, StringRef MangledName, bool OutputBecomesInput, llvm::Function *Fn)
static bool isAllocatableDecl(const VarDecl *VD)
static llvm::Value * getAlignmentValue(CodeGenModule &CGM, const VarDecl *VD)
Return the alignment from an allocate directive if present.
static void emitTargetCallKernelLaunch(CGOpenMPRuntime *OMPRuntime, llvm::Function *OutlinedFn, const OMPExecutableDirective &D, llvm::SmallVectorImpl< llvm::Value * > &CapturedVars, bool RequiresOuterTask, const CapturedStmt &CS, bool OffloadingMandatory, llvm::PointerIntPair< const Expr *, 2, OpenMPDeviceClauseModifier > Device, llvm::Value *OutlinedFnID, CodeGenFunction::OMPTargetDataInfo &InputInfo, llvm::Value *&MapTypesArray, llvm::Value *&MapNamesArray, llvm::function_ref< llvm::Value *(CodeGenFunction &CGF, const OMPLoopDirective &D)> SizeEmitter, CodeGenFunction &CGF, CodeGenModule &CGM)
static llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryKind convertCaptureClause(const VarDecl *VD)
static std::tuple< unsigned, unsigned, bool > getNDSWDS(const FunctionDecl *FD, ArrayRef< ParamAttrTy > ParamAttrs)
static const OMPExecutableDirective * getNestedDistributeDirective(ASTContext &Ctx, const OMPExecutableDirective &D)
Check for inner distribute directive.
static std::pair< llvm::Value *, llvm::Value * > getPointerAndSize(CodeGenFunction &CGF, const Expr *E)
static const VarDecl * getBaseDecl(const Expr *Ref, const DeclRefExpr *&DE)
static bool isTrivial(ASTContext &Ctx, const Expr *E)
Checks if the expression is constant or does not have non-trivial function calls.
static OpenMPSchedType getRuntimeSchedule(OpenMPScheduleClauseKind ScheduleKind, bool Chunked, bool Ordered)
Map the OpenMP loop schedule to the runtime enumeration.
static void getNumThreads(CodeGenFunction &CGF, const CapturedStmt *CS, const Expr **E, int32_t &UpperBound, bool UpperBoundOnly, llvm::Value **CondVal)
Check for a num threads constant value (stored in DefaultVal), or expression (stored in E).
static llvm::Value * emitDeviceID(llvm::PointerIntPair< const Expr *, 2, OpenMPDeviceClauseModifier > Device, CodeGenFunction &CGF)
static const OMPDeclareReductionDecl * getReductionInit(const Expr *ReductionOp)
Check if the combiner is a call to UDR combiner and if it is so return the UDR decl used for reductio...
static bool checkInitIsRequired(CodeGenFunction &CGF, ArrayRef< PrivateDataTy > Privates)
Check if duplication function is required for taskloops.
static bool checkDestructorsRequired(const RecordDecl *KmpTaskTWithPrivatesQTyRD, ArrayRef< PrivateDataTy > Privates)
Checks if destructor function is required to be generated.
static llvm::TargetRegionEntryInfo getEntryInfoFromPresumedLoc(CodeGenModule &CGM, llvm::OpenMPIRBuilder &OMPBuilder, SourceLocation BeginLoc, llvm::StringRef ParentName="")
static void genMapInfo(MappableExprsHandler &MEHandler, CodeGenFunction &CGF, MappableExprsHandler::MapCombinedInfoTy &CombinedInfo, llvm::OpenMPIRBuilder &OMPBuilder, const llvm::DenseSet< CanonicalDeclPtr< const Decl > > &SkippedVarSet=llvm::DenseSet< CanonicalDeclPtr< const Decl > >())
static std::string generateUniqueName(CodeGenModule &CGM, StringRef Prefix, const Expr *Ref)
Generates unique name for artificial threadprivate variables.
static void emitForStaticInitCall(CodeGenFunction &CGF, llvm::Value *UpdateLocation, llvm::Value *ThreadId, llvm::FunctionCallee ForStaticInitFunction, OpenMPSchedType Schedule, OpenMPScheduleClauseModifier M1, OpenMPScheduleClauseModifier M2, const CGOpenMPRuntime::StaticRTInput &Values)
static LValue loadToBegin(CodeGenFunction &CGF, QualType BaseTy, QualType ElTy, LValue BaseLV)
static void getKmpAffinityType(ASTContext &C, QualType &KmpTaskAffinityInfoTy)
Builds kmp_depend_info, if it is not built yet, and builds flags type.
static llvm::Constant * emitMappingInformation(CodeGenFunction &CGF, llvm::OpenMPIRBuilder &OMPBuilder, MappableExprsHandler::MappingExprInfo &MapExprs)
Emit a string constant containing the names of the values mapped to the offloading runtime library.
static void getDependTypes(ASTContext &C, QualType &KmpDependInfoTy, QualType &FlagsTy)
Builds kmp_depend_info, if it is not built yet, and builds flags type.
static llvm::Value * emitTaskDupFunction(CodeGenModule &CGM, SourceLocation Loc, const OMPExecutableDirective &D, QualType KmpTaskTWithPrivatesPtrQTy, const RecordDecl *KmpTaskTWithPrivatesQTyRD, const RecordDecl *KmpTaskTQTyRD, QualType SharedsTy, QualType SharedsPtrTy, const OMPTaskDataTy &Data, ArrayRef< PrivateDataTy > Privates, bool WithLastIter)
Emit task_dup function (for initialization of private/firstprivate/lastprivate vars and last_iter fla...
static llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseKind convertDeviceClause(const VarDecl *VD)
static llvm::Value * emitReduceFiniFunction(CodeGenModule &CGM, SourceLocation Loc, ReductionCodeGen &RCG, unsigned N)
Emits reduction finalizer function:
static void EmitOMPAggregateInit(CodeGenFunction &CGF, Address DestAddr, QualType Type, bool EmitDeclareReductionInit, const Expr *Init, const OMPDeclareReductionDecl *DRD, Address SrcAddr=Address::invalid())
Emit initialization of arrays of complex types.
static bool getAArch64PBV(QualType QT, ASTContext &C)
Pass By Value (PBV), as defined in 3.1.2 of the AAVFABI.
static unsigned getAArch64LS(QualType QT, ParamKindTy Kind, ASTContext &C)
Computes the lane size (LS) of a return type or of an input parameter, as defined by LS(P) in 3....
static void EmitDoacrossOrdered(CodeGenFunction &CGF, CodeGenModule &CGM, const T *C, llvm::Value *ULoc, llvm::Value *ThreadID)
static RTLDependenceKindTy translateDependencyKind(OpenMPDependClauseKind K)
Translates internal dependency kind into the runtime kind.
static void emitTargetCallElse(CGOpenMPRuntime *OMPRuntime, llvm::Function *OutlinedFn, const OMPExecutableDirective &D, llvm::SmallVectorImpl< llvm::Value * > &CapturedVars, bool RequiresOuterTask, const CapturedStmt &CS, bool OffloadingMandatory, CodeGenFunction &CGF)
static llvm::Function * emitCombinerOrInitializer(CodeGenModule &CGM, QualType Ty, const Expr *CombinerInitializer, const VarDecl *In, const VarDecl *Out, bool IsCombiner)
static void emitX86DeclareSimdFunction(const FunctionDecl *FD, llvm::Function *Fn, const llvm::APSInt &VLENVal, ArrayRef< ParamAttrTy > ParamAttrs, OMPDeclareSimdDeclAttr::BranchStateTy State)
static void emitReductionCombiner(CodeGenFunction &CGF, const Expr *ReductionOp)
Emit reduction combiner.
static std::string mangleVectorParameters(ArrayRef< ParamAttrTy > ParamAttrs)
Mangle the parameter part of the vector function name according to their OpenMP classification.
static llvm::Function * emitParallelOrTeamsOutlinedFunction(CodeGenModule &CGM, const OMPExecutableDirective &D, const CapturedStmt *CS, const VarDecl *ThreadIDVar, OpenMPDirectiveKind InnermostKind, const StringRef OutlinedHelperName, const RegionCodeGenTy &CodeGen)
static void emitAArch64DeclareSimdFunction(CodeGenModule &CGM, const FunctionDecl *FD, unsigned UserVLEN, ArrayRef< ParamAttrTy > ParamAttrs, OMPDeclareSimdDeclAttr::BranchStateTy State, StringRef MangledName, char ISA, unsigned VecRegSize, llvm::Function *Fn, SourceLocation SLoc)
Emit vector function attributes for AArch64, as defined in the AAVFABI.
static Address emitAddrOfVarFromArray(CodeGenFunction &CGF, Address Array, unsigned Index, const VarDecl *Var)
Given an array of pointers to variables, project the address of a given variable.
static llvm::Value * emitDynCGGroupMem(const OMPExecutableDirective &D, CodeGenFunction &CGF)
static bool isAssumedToBeNotEmitted(const ValueDecl *VD, bool IsDevice)
static void addAArch64AdvSIMDNDSNames(unsigned NDS, StringRef Mask, StringRef Prefix, char ISA, StringRef ParSeq, StringRef MangledName, bool OutputBecomesInput, llvm::Function *Fn)
static FieldDecl * addFieldToRecordDecl(ASTContext &C, DeclContext *DC, QualType FieldTy)
static ValueDecl * getDeclFromThisExpr(const Expr *E)
static void genMapInfoForCaptures(MappableExprsHandler &MEHandler, CodeGenFunction &CGF, const CapturedStmt &CS, llvm::SmallVectorImpl< llvm::Value * > &CapturedVars, llvm::OpenMPIRBuilder &OMPBuilder, llvm::DenseSet< CanonicalDeclPtr< const Decl > > &MappedVarSet, MappableExprsHandler::MapCombinedInfoTy &CombinedInfo)
static RecordDecl * createKmpTaskTRecordDecl(CodeGenModule &CGM, OpenMPDirectiveKind Kind, QualType KmpInt32Ty, QualType KmpRoutineEntryPointerQTy)
static int addMonoNonMonoModifier(CodeGenModule &CGM, OpenMPSchedType Schedule, OpenMPScheduleClauseModifier M1, OpenMPScheduleClauseModifier M2)
static bool getAArch64MTV(QualType QT, ParamKindTy Kind)
Maps To Vector (MTV), as defined in 4.1.1 of the AAVFABI (2021Q1).
enum clang::sema::@1704::IndirectLocalPathEntry::EntryKind Kind
@ LLVM_MARK_AS_BITMASK_ENUM
This file defines OpenMP AST classes for clauses.
Defines some OpenMP-specific enums and functions.
Defines the SourceManager interface.
This file defines OpenMP AST classes for executable directives and clauses.
__DEVICE__ int max(int __a, int __b)
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
SourceManager & getSourceManager()
const ConstantArrayType * getAsConstantArrayType(QualType T) const
CharUnits getTypeAlignInChars(QualType T) const
Return the ABI-specified alignment of a (complete) type T, in characters.
const ASTRecordLayout & getASTRecordLayout(const RecordDecl *D) const
Get or compute information about the layout of the specified record (struct/union/class) D,...
bool hasSameType(QualType T1, QualType T2) const
Determine whether the given types T1 and T2 are equivalent.
QualType getPointerType(QualType T) const
Return the uniqued reference to the type for a pointer to the specified type.
QualType getConstantArrayType(QualType EltTy, const llvm::APInt &ArySize, const Expr *SizeExpr, ArraySizeModifier ASM, unsigned IndexTypeQuals) const
Return the unique reference to the type for a constant array of the specified element type.
const LangOptions & getLangOpts() const
QualType getIntTypeForBitwidth(unsigned DestWidth, unsigned Signed) const
getIntTypeForBitwidth - sets integer QualTy according to specified details: bitwidth,...
CanQualType getSizeType() const
Return the unique type for "size_t" (C99 7.17), defined in <stddef.h>.
CharUnits getDeclAlign(const Decl *D, bool ForAlignof=false) const
Return a conservative estimate of the alignment of the specified decl D.
const ArrayType * getAsArrayType(QualType T) const
Type Query functions.
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
const VariableArrayType * getAsVariableArrayType(QualType T) const
const TargetInfo & getTargetInfo() const
CharUnits getNonVirtualSize() const
getNonVirtualSize - Get the non-virtual size (in chars) of an object, which is the size of the object...
static QualType getBaseOriginalType(const Expr *Base)
Return original type of the base expression for array section.
Represents an array type, per C99 6.7.5.2 - Array Declarators.
Attr - This represents one attribute.
Represents a C++ constructor within a class.
Represents a C++ destructor within a class.
Represents a static or instance method of a struct/union/class.
const CXXRecordDecl * getParent() const
Return the parent of this method declaration, which is the class in which this method is defined.
QualType getFunctionObjectParameterType() const
Represents a C++ struct/union/class.
bool isLambda() const
Determine whether this class describes a lambda function object.
void getCaptureFields(llvm::DenseMap< const ValueDecl *, FieldDecl * > &Captures, FieldDecl *&ThisCapture) const
For a closure type, retrieve the mapping from captured variables and this to the non-static data memb...
unsigned getNumBases() const
Retrieves the number of base classes of this class.
base_class_range vbases()
capture_const_range captures() const
CXXDestructorDecl * getDestructor() const
Returns the destructor decl for this class.
CanProxy< U > castAs() const
A wrapper class around a pointer that always points to its canonical declaration.
Describes the capture of either a variable, or 'this', or variable-length array type.
bool capturesVariableByCopy() const
Determine whether this capture handles a variable by copy.
VarDecl * getCapturedVar() const
Retrieve the declaration of the variable being captured.
bool capturesVariableArrayType() const
Determine whether this capture handles a variable-length array type.
bool capturesThis() const
Determine whether this capture handles the C++ 'this' pointer.
bool capturesVariable() const
Determine whether this capture handles a variable (by reference).
This captures a statement into a function.
capture_iterator capture_end() const
Retrieve an iterator pointing past the end of the sequence of captures.
const RecordDecl * getCapturedRecordDecl() const
Retrieve the record declaration for captured variables.
Stmt * getCapturedStmt()
Retrieve the statement being captured.
bool capturesVariable(const VarDecl *Var) const
True if this variable has been captured.
capture_iterator capture_begin()
Retrieve an iterator pointing to the first capture.
CharUnits - This is an opaque type for sizes expressed in character units.
bool isZero() const
isZero - Test whether the quantity equals zero.
llvm::Align getAsAlign() const
getAsAlign - Returns Quantity as a valid llvm::Align, Beware llvm::Align assumes power of two 8-bit b...
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
CharUnits alignmentOfArrayElement(CharUnits elementSize) const
Given that this is the alignment of the first element of an array, return the minimum alignment of an...
static CharUnits fromQuantity(QuantityType Quantity)
fromQuantity - Construct a CharUnits quantity from a raw integer type.
CharUnits alignTo(const CharUnits &Align) const
alignTo - Returns the next integer (mod 2**64) that is greater than or equal to this quantity and is ...
Like RawAddress, an abstract representation of an aligned address, but the pointer contained in this ...
llvm::Value * emitRawPointer(CodeGenFunction &CGF) const
Return the pointer contained in this class after authenticating it and adding offset to it if necessa...
CharUnits getAlignment() const
llvm::Type * getElementType() const
Return the type of the values stored in this address.
Address withPointer(llvm::Value *NewPointer, KnownNonNull_t IsKnownNonNull) const
Return address with different pointer, but same element type and alignment.
Address withElementType(llvm::Type *ElemTy) const
Return address with different element type, but same pointer and alignment.
Address withAlignment(CharUnits NewAlignment) const
Return address with different alignment, but same pointer and element type.
llvm::PointerType * getType() const
Return the type of the pointer value.
static ApplyDebugLocation CreateArtificial(CodeGenFunction &CGF)
Apply TemporaryLocation if it is valid.
static ApplyDebugLocation CreateDefaultArtificial(CodeGenFunction &CGF, SourceLocation TemporaryLocation)
Apply TemporaryLocation if it is valid.
static ApplyDebugLocation CreateEmpty(CodeGenFunction &CGF)
Set the IRBuilder to not attach debug locations.
CGBlockInfo - Information to generate a block literal.
llvm::StoreInst * CreateStore(llvm::Value *Val, Address Addr, bool IsVolatile=false)
Address CreateGEP(CodeGenFunction &CGF, Address Addr, llvm::Value *Index, const llvm::Twine &Name="")
Address CreatePointerBitCastOrAddrSpaceCast(Address Addr, llvm::Type *Ty, llvm::Type *ElementTy, const llvm::Twine &Name="")
Address CreateConstArrayGEP(Address Addr, uint64_t Index, const llvm::Twine &Name="")
Given addr = [n x T]* ... produce name = getelementptr inbounds addr, i64 0, i64 index where i64 is a...
llvm::LoadInst * CreateLoad(Address Addr, const llvm::Twine &Name="")
llvm::CallInst * CreateMemCpy(Address Dest, Address Src, llvm::Value *Size, bool IsVolatile=false)
Address CreateConstGEP(Address Addr, uint64_t Index, const llvm::Twine &Name="")
Given addr = T* ... produce name = getelementptr inbounds addr, i64 index where i64 is actually the t...
MangleContext & getMangleContext()
Gets the mangle context.
CGFunctionInfo - Class to encapsulate the information about a function definition.
DisableAutoDeclareTargetRAII(CodeGenModule &CGM)
~DisableAutoDeclareTargetRAII()
Manages list of lastprivate conditional decls for the specified directive.
~LastprivateConditionalRAII()
static LastprivateConditionalRAII disable(CodeGenFunction &CGF, const OMPExecutableDirective &S)
NontemporalDeclsRAII(CodeGenModule &CGM, const OMPLoopDirective &S)
Struct that keeps all the relevant information that should be kept throughout a 'target data' region.
llvm::DenseMap< const ValueDecl *, llvm::Value * > CaptureDeviceAddrMap
Map between the a declaration of a capture and the corresponding new llvm address where the runtime r...
~UntiedTaskLocalDeclsRAII()
UntiedTaskLocalDeclsRAII(CodeGenFunction &CGF, const llvm::MapVector< CanonicalDeclPtr< const VarDecl >, std::pair< Address, Address > > &LocalVars)
virtual Address emitThreadIDAddress(CodeGenFunction &CGF, SourceLocation Loc)
Emits address of the word in a memory where current thread id is stored.
llvm::FunctionType * Kmpc_MicroTy
The type for a microtask which gets passed to __kmpc_fork_call().
llvm::StringSet ThreadPrivateWithDefinition
Set of threadprivate variables with the generated initializer.
CGOpenMPRuntime(CodeGenModule &CGM)
virtual void emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc, const OMPExecutableDirective &D, llvm::Function *TaskFunction, QualType SharedsTy, Address Shareds, const Expr *IfCond, const OMPTaskDataTy &Data)
Emit task region for the task directive.
void createOffloadEntriesAndInfoMetadata()
Creates all the offload entries in the current compilation unit along with the associated metadata.
const Expr * getNumTeamsExprForTargetDirective(CodeGenFunction &CGF, const OMPExecutableDirective &D, int32_t &MinTeamsVal, int32_t &MaxTeamsVal)
Emit the number of teams for a target directive.
virtual Address getAddrOfThreadPrivate(CodeGenFunction &CGF, const VarDecl *VD, Address VDAddr, SourceLocation Loc)
Returns address of the threadprivate variable for the current thread.
void emitDeferredTargetDecls() const
Emit deferred declare target variables marked for deferred emission.
virtual llvm::Value * emitForNext(CodeGenFunction &CGF, SourceLocation Loc, unsigned IVSize, bool IVSigned, Address IL, Address LB, Address UB, Address ST)
Call __kmpc_dispatch_next( ident_t *loc, kmp_int32 tid, kmp_int32 *p_lastiter, kmp_int[32|64] *p_lowe...
bool markAsGlobalTarget(GlobalDecl GD)
Marks the declaration as already emitted for the device code and returns true, if it was marked alrea...
virtual void emitTargetDataStandAloneCall(CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, const Expr *Device)
Emit the data mapping/movement code associated with the directive D that should be of the form 'targe...
virtual void emitNumThreadsClause(CodeGenFunction &CGF, llvm::Value *NumThreads, SourceLocation Loc)
Emits call to void __kmpc_push_num_threads(ident_t *loc, kmp_int32 global_tid, kmp_int32 num_threads)...
QualType SavedKmpTaskloopTQTy
Saved kmp_task_t for taskloop-based directive.
virtual void emitSingleRegion(CodeGenFunction &CGF, const RegionCodeGenTy &SingleOpGen, SourceLocation Loc, ArrayRef< const Expr * > CopyprivateVars, ArrayRef< const Expr * > DestExprs, ArrayRef< const Expr * > SrcExprs, ArrayRef< const Expr * > AssignmentOps)
Emits a single region.
virtual bool emitTargetGlobal(GlobalDecl GD)
Emit the global GD if it is meaningful for the target.
void setLocThreadIdInsertPt(CodeGenFunction &CGF, bool AtCurrentPoint=false)
std::string getOutlinedHelperName(StringRef Name) const
Get the function name of an outlined region.
bool HasEmittedDeclareTargetRegion
Flag for keeping track of weather a device routine has been emitted.
llvm::Constant * getOrCreateThreadPrivateCache(const VarDecl *VD)
If the specified mangled name is not in the module, create and return threadprivate cache object.
virtual Address getTaskReductionItem(CodeGenFunction &CGF, SourceLocation Loc, llvm::Value *ReductionsPtr, LValue SharedLVal)
Get the address of void * type of the privatue copy of the reduction item specified by the SharedLVal...
virtual void emitForDispatchDeinit(CodeGenFunction &CGF, SourceLocation Loc)
This is used for non static scheduled types and when the ordered clause is present on the loop constr...
void emitCall(CodeGenFunction &CGF, SourceLocation Loc, llvm::FunctionCallee Callee, ArrayRef< llvm::Value * > Args={}) const
Emits Callee function call with arguments Args with location Loc.
virtual void getDefaultScheduleAndChunk(CodeGenFunction &CGF, const OMPLoopDirective &S, OpenMPScheduleClauseKind &ScheduleKind, const Expr *&ChunkExpr) const
Choose default schedule type and chunk value for the schedule clause.
virtual std::pair< llvm::Function *, llvm::Function * > getUserDefinedReduction(const OMPDeclareReductionDecl *D)
Get combiner/initializer for the specified user-defined reduction, if any.
virtual bool isGPU() const
Returns true if the current target is a GPU.
static const Stmt * getSingleCompoundChild(ASTContext &Ctx, const Stmt *Body)
Checks if the Body is the CompoundStmt and returns its child statement iff there is only one that is ...
virtual void emitDeclareTargetFunction(const FunctionDecl *FD, llvm::GlobalValue *GV)
Emit code for handling declare target functions in the runtime.
llvm::Type * getKmpc_MicroPointerTy()
Returns pointer to kmpc_micro type.
bool HasRequiresUnifiedSharedMemory
Flag for keeping track of weather a requires unified_shared_memory directive is present.
llvm::Value * emitUpdateLocation(CodeGenFunction &CGF, SourceLocation Loc, unsigned Flags=0, bool EmitLoc=false)
Emits object of ident_t type with info for source location.
bool isLocalVarInUntiedTask(CodeGenFunction &CGF, const VarDecl *VD) const
Returns true if the variable is a local variable in untied task.
virtual void emitTeamsCall(CodeGenFunction &CGF, const OMPExecutableDirective &D, SourceLocation Loc, llvm::Function *OutlinedFn, ArrayRef< llvm::Value * > CapturedVars)
Emits code for teams call of the OutlinedFn with variables captured in a record which address is stor...
virtual void emitCancellationPointCall(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind CancelRegion)
Emit code for 'cancellation point' construct.
virtual llvm::Function * emitThreadPrivateVarDefinition(const VarDecl *VD, Address VDAddr, SourceLocation Loc, bool PerformInit, CodeGenFunction *CGF=nullptr)
Emit a code for initialization of threadprivate variable.
FunctionUDMMapTy FunctionUDMMap
virtual ConstantAddress getAddrOfDeclareTargetVar(const VarDecl *VD)
Returns the address of the variable marked as declare target with link clause OR as declare target wi...
llvm::MapVector< CanonicalDeclPtr< const VarDecl >, std::pair< Address, Address > > UntiedLocalVarsAddressesMap
llvm::Function * getOrCreateUserDefinedMapperFunc(const OMPDeclareMapperDecl *D)
Get the function for the specified user-defined mapper.
OpenMPLocThreadIDMapTy OpenMPLocThreadIDMap
virtual void functionFinished(CodeGenFunction &CGF)
Cleans up references to the objects in finished function.
virtual llvm::Function * emitTeamsOutlinedFunction(CodeGenFunction &CGF, const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen)
Emits outlined function for the specified OpenMP teams directive D.
QualType KmpTaskTQTy
Type typedef struct kmp_task { void * shareds; /â**< pointer to block of pointers to shared vars â/ k...
llvm::OpenMPIRBuilder OMPBuilder
An OpenMP-IR-Builder instance.
virtual void emitDoacrossInit(CodeGenFunction &CGF, const OMPLoopDirective &D, ArrayRef< Expr * > NumIterations)
Emit initialization for doacross loop nesting support.
virtual void adjustTargetSpecificDataForLambdas(CodeGenFunction &CGF, const OMPExecutableDirective &D) const
Adjust some parameters for the target-based directives, like addresses of the variables captured by r...
FunctionUDRMapTy FunctionUDRMap
virtual void emitTargetDataCalls(CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, const Expr *Device, const RegionCodeGenTy &CodeGen, CGOpenMPRuntime::TargetDataInfo &Info)
Emit the target data mapping code associated with D.
virtual unsigned getDefaultLocationReserved2Flags() const
Returns additional flags that can be stored in reserved_2 field of the default location.
virtual Address getParameterAddress(CodeGenFunction &CGF, const VarDecl *NativeParam, const VarDecl *TargetParam) const
Gets the address of the native argument basing on the address of the target-specific parameter.
void emitUsesAllocatorsFini(CodeGenFunction &CGF, const Expr *Allocator)
Destroys user defined allocators specified in the uses_allocators clause.
QualType KmpTaskAffinityInfoTy
Type typedef struct kmp_task_affinity_info { kmp_intptr_t base_addr; size_t len; struct { bool flag1 ...
llvm::SmallVector< NontemporalDeclsSet, 4 > NontemporalDeclsStack
Stack for list of declarations in current context marked as nontemporal.
llvm::Value * emitNumTeamsForTargetDirective(CodeGenFunction &CGF, const OMPExecutableDirective &D)
virtual void emitTargetOutlinedFunctionHelper(const OMPExecutableDirective &D, StringRef ParentName, llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID, bool IsOffloadEntry, const RegionCodeGenTy &CodeGen)
Helper to emit outlined function for 'target' directive.
void scanForTargetRegionsFunctions(const Stmt *S, StringRef ParentName)
Start scanning from statement S and emit all target regions found along the way.
SmallVector< llvm::Value *, 4 > emitDepobjElementsSizes(CodeGenFunction &CGF, QualType &KmpDependInfoTy, const OMPTaskDataTy::DependData &Data)
virtual void emitTaskgroupRegion(CodeGenFunction &CGF, const RegionCodeGenTy &TaskgroupOpGen, SourceLocation Loc)
Emit a taskgroup region.
llvm::DenseMap< llvm::Function *, llvm::DenseMap< CanonicalDeclPtr< const Decl >, std::tuple< QualType, const FieldDecl *, const FieldDecl *, LValue > > > LastprivateConditionalToTypes
Maps local variables marked as lastprivate conditional to their internal types.
virtual bool emitTargetGlobalVariable(GlobalDecl GD)
Emit the global variable if it is a valid device global variable.
virtual void emitNumTeamsClause(CodeGenFunction &CGF, const Expr *NumTeams, const Expr *ThreadLimit, SourceLocation Loc)
Emits call to void __kmpc_push_num_teams(ident_t *loc, kmp_int32 global_tid, kmp_int32 num_teams,...
bool hasRequiresUnifiedSharedMemory() const
Return whether the unified_shared_memory has been specified.
virtual Address getAddrOfArtificialThreadPrivate(CodeGenFunction &CGF, QualType VarType, StringRef Name)
Creates artificial threadprivate variable with name Name and type VarType.
void emitUserDefinedMapper(const OMPDeclareMapperDecl *D, CodeGenFunction *CGF=nullptr)
Emit the function for the user defined mapper construct.
bool HasEmittedTargetRegion
Flag for keeping track of weather a target region has been emitted.
void emitDepobjElements(CodeGenFunction &CGF, QualType &KmpDependInfoTy, LValue PosLVal, const OMPTaskDataTy::DependData &Data, Address DependenciesArray)
std::string getReductionFuncName(StringRef Name) const
Get the function name of a reduction function.
virtual void processRequiresDirective(const OMPRequiresDecl *D)
Perform check on requires decl to ensure that target architecture supports unified addressing.
llvm::DenseSet< CanonicalDeclPtr< const Decl > > AlreadyEmittedTargetDecls
List of the emitted declarations.
virtual llvm::Value * emitTaskReductionInit(CodeGenFunction &CGF, SourceLocation Loc, ArrayRef< const Expr * > LHSExprs, ArrayRef< const Expr * > RHSExprs, const OMPTaskDataTy &Data)
Emit a code for initialization of task reduction clause.
llvm::Value * getThreadID(CodeGenFunction &CGF, SourceLocation Loc)
Gets thread id value for the current thread.
void emitUpdateClause(CodeGenFunction &CGF, LValue DepobjLVal, OpenMPDependClauseKind NewDepKind, SourceLocation Loc)
Updates the dependency kind in the specified depobj object.
virtual void emitLastprivateConditionalFinalUpdate(CodeGenFunction &CGF, LValue PrivLVal, const VarDecl *VD, SourceLocation Loc)
Gets the address of the global copy used for lastprivate conditional update, if any.
virtual void emitErrorCall(CodeGenFunction &CGF, SourceLocation Loc, Expr *ME, bool IsFatal)
Emit __kmpc_error call for error directive extern void __kmpc_error(ident_t *loc, int severity,...
void clearLocThreadIdInsertPt(CodeGenFunction &CGF)
virtual void emitTaskyieldCall(CodeGenFunction &CGF, SourceLocation Loc)
Emits code for a taskyield directive.
std::string getName(ArrayRef< StringRef > Parts) const
Get the platform-specific name separator.
QualType KmpRoutineEntryPtrQTy
void computeMinAndMaxThreadsAndTeams(const OMPExecutableDirective &D, CodeGenFunction &CGF, llvm::OpenMPIRBuilder::TargetKernelDefaultAttrs &Attrs)
Helper to determine the min/max number of threads/teams for D.
virtual void emitFlush(CodeGenFunction &CGF, ArrayRef< const Expr * > Vars, SourceLocation Loc, llvm::AtomicOrdering AO)
Emit flush of the variables specified in 'omp flush' directive.
virtual void emitTaskwaitCall(CodeGenFunction &CGF, SourceLocation Loc, const OMPTaskDataTy &Data)
Emit code for 'taskwait' directive.
virtual void emitProcBindClause(CodeGenFunction &CGF, llvm::omp::ProcBindKind ProcBind, SourceLocation Loc)
Emit call to void __kmpc_push_proc_bind(ident_t *loc, kmp_int32 global_tid, int proc_bind) to generat...
void emitLastprivateConditionalUpdate(CodeGenFunction &CGF, LValue IVLVal, StringRef UniqueDeclName, LValue LVal, SourceLocation Loc)
Emit update for lastprivate conditional data.
virtual void emitTaskLoopCall(CodeGenFunction &CGF, SourceLocation Loc, const OMPLoopDirective &D, llvm::Function *TaskFunction, QualType SharedsTy, Address Shareds, const Expr *IfCond, const OMPTaskDataTy &Data)
Emit task region for the taskloop directive.
virtual void emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind Kind, bool EmitChecks=true, bool ForceSimpleCall=false)
Emit an implicit/explicit barrier for OpenMP threads.
static unsigned getDefaultFlagsForBarriers(OpenMPDirectiveKind Kind)
Returns default flags for the barriers depending on the directive, for which this barier is going to ...
virtual bool emitTargetFunctions(GlobalDecl GD)
Emit the target regions enclosed in GD function definition or the function itself in case it is a val...
TaskResultTy emitTaskInit(CodeGenFunction &CGF, SourceLocation Loc, const OMPExecutableDirective &D, llvm::Function *TaskFunction, QualType SharedsTy, Address Shareds, const OMPTaskDataTy &Data)
Emit task region for the task directive.
llvm::Value * emitTargetNumIterationsCall(CodeGenFunction &CGF, const OMPExecutableDirective &D, llvm::function_ref< llvm::Value *(CodeGenFunction &CGF, const OMPLoopDirective &D)> SizeEmitter)
Return the trip count of loops associated with constructs / 'target teams distribute' and 'teams dist...
llvm::StringMap< llvm::AssertingVH< llvm::GlobalVariable >, llvm::BumpPtrAllocator > InternalVars
An ordered map of auto-generated variables to their unique names.
virtual void emitDistributeStaticInit(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDistScheduleClauseKind SchedKind, const StaticRTInput &Values)
llvm::SmallVector< UntiedLocalVarsAddressesMap, 4 > UntiedLocalVarsStack
virtual void emitForStaticFinish(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind DKind)
Call the appropriate runtime routine to notify that we finished all the work with current loop.
virtual void emitThreadLimitClause(CodeGenFunction &CGF, const Expr *ThreadLimit, SourceLocation Loc)
Emits call to void __kmpc_set_thread_limit(ident_t *loc, kmp_int32 global_tid, kmp_int32 thread_limit...
void emitIfClause(CodeGenFunction &CGF, const Expr *Cond, const RegionCodeGenTy &ThenGen, const RegionCodeGenTy &ElseGen)
Emits code for OpenMP 'if' clause using specified CodeGen function.
Address emitDepobjDependClause(CodeGenFunction &CGF, const OMPTaskDataTy::DependData &Dependencies, SourceLocation Loc)
Emits list of dependecies based on the provided data (array of dependence/expression pairs) for depob...
bool isNontemporalDecl(const ValueDecl *VD) const
Checks if the VD variable is marked as nontemporal declaration in current context.
virtual llvm::Function * emitParallelOutlinedFunction(CodeGenFunction &CGF, const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen)
Emits outlined function for the specified OpenMP parallel directive D.
const Expr * getNumThreadsExprForTargetDirective(CodeGenFunction &CGF, const OMPExecutableDirective &D, int32_t &UpperBound, bool UpperBoundOnly, llvm::Value **CondExpr=nullptr, const Expr **ThreadLimitExpr=nullptr)
Check for a number of threads upper bound constant value (stored in UpperBound), or expression (retur...
llvm::SmallVector< LastprivateConditionalData, 4 > LastprivateConditionalStack
Stack for list of addresses of declarations in current context marked as lastprivate conditional.
virtual void emitForStaticInit(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind DKind, const OpenMPScheduleTy &ScheduleKind, const StaticRTInput &Values)
Call the appropriate runtime routine to initialize it before start of loop.
virtual void emitDeclareSimdFunction(const FunctionDecl *FD, llvm::Function *Fn)
Marks function Fn with properly mangled versions of vector functions.
llvm::AtomicOrdering getDefaultMemoryOrdering() const
Gets default memory ordering as specified in requires directive.
llvm::SmallDenseSet< CanonicalDeclPtr< const Decl > > NontemporalDeclsSet
virtual bool isStaticNonchunked(OpenMPScheduleClauseKind ScheduleKind, bool Chunked) const
Check if the specified ScheduleKind is static non-chunked.
llvm::Value * getCriticalRegionLock(StringRef CriticalName)
Returns corresponding lock object for the specified critical region name.
virtual void emitCancelCall(CodeGenFunction &CGF, SourceLocation Loc, const Expr *IfCond, OpenMPDirectiveKind CancelRegion)
Emit code for 'cancel' construct.
QualType SavedKmpTaskTQTy
Saved kmp_task_t for task directive.
virtual void emitMasterRegion(CodeGenFunction &CGF, const RegionCodeGenTy &MasterOpGen, SourceLocation Loc)
Emits a master region.
virtual llvm::Function * emitTaskOutlinedFunction(const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, const VarDecl *PartIDVar, const VarDecl *TaskTVar, OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen, bool Tied, unsigned &NumberOfParts)
Emits outlined function for the OpenMP task directive D.
llvm::DenseMap< llvm::Function *, unsigned > FunctionToUntiedTaskStackMap
Maps function to the position of the untied task locals stack.
void emitDestroyClause(CodeGenFunction &CGF, LValue DepobjLVal, SourceLocation Loc)
Emits the code to destroy the dependency object provided in depobj directive.
virtual void emitTaskReductionFixups(CodeGenFunction &CGF, SourceLocation Loc, ReductionCodeGen &RCG, unsigned N)
Required to resolve existing problems in the runtime.
llvm::ArrayType * KmpCriticalNameTy
Type kmp_critical_name, originally defined as typedef kmp_int32 kmp_critical_name[8];.
virtual void emitDoacrossOrdered(CodeGenFunction &CGF, const OMPDependClause *C)
Emit code for doacross ordered directive with 'depend' clause.
llvm::DenseMap< const OMPDeclareMapperDecl *, llvm::Function * > UDMMap
Map from the user-defined mapper declaration to its corresponding functions.
virtual void checkAndEmitLastprivateConditional(CodeGenFunction &CGF, const Expr *LHS)
Checks if the provided LVal is lastprivate conditional and emits the code to update the value of the ...
std::pair< llvm::Value *, LValue > getDepobjElements(CodeGenFunction &CGF, LValue DepobjLVal, SourceLocation Loc)
Returns the number of the elements and the address of the depobj dependency array.
llvm::SmallDenseSet< const VarDecl * > DeferredGlobalVariables
List of variables that can become declare target implicitly and, thus, must be emitted.
void emitUsesAllocatorsInit(CodeGenFunction &CGF, const Expr *Allocator, const Expr *AllocatorTraits)
Initializes user defined allocators specified in the uses_allocators clauses.
llvm::Type * KmpRoutineEntryPtrTy
Type typedef kmp_int32 (* kmp_routine_entry_t)(kmp_int32, void *);.
llvm::Type * getIdentTyPointerTy()
Returns pointer to ident_t type.
void emitSingleReductionCombiner(CodeGenFunction &CGF, const Expr *ReductionOp, const Expr *PrivateRef, const DeclRefExpr *LHS, const DeclRefExpr *RHS)
Emits single reduction combiner.
llvm::OpenMPIRBuilder & getOMPBuilder()
virtual void emitTargetOutlinedFunction(const OMPExecutableDirective &D, StringRef ParentName, llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID, bool IsOffloadEntry, const RegionCodeGenTy &CodeGen)
Emit outilined function for 'target' directive.
virtual void emitCriticalRegion(CodeGenFunction &CGF, StringRef CriticalName, const RegionCodeGenTy &CriticalOpGen, SourceLocation Loc, const Expr *Hint=nullptr)
Emits a critical region.
virtual void emitForOrderedIterationEnd(CodeGenFunction &CGF, SourceLocation Loc, unsigned IVSize, bool IVSigned)
Call the appropriate runtime routine to notify that we finished iteration of the ordered loop with th...
virtual void emitOutlinedFunctionCall(CodeGenFunction &CGF, SourceLocation Loc, llvm::FunctionCallee OutlinedFn, ArrayRef< llvm::Value * > Args={}) const
Emits call of the outlined function with the provided arguments, translating these arguments to corre...
llvm::Value * emitNumThreadsForTargetDirective(CodeGenFunction &CGF, const OMPExecutableDirective &D)
Emit an expression that denotes the number of threads a target region shall use.
void emitThreadPrivateVarInit(CodeGenFunction &CGF, Address VDAddr, llvm::Value *Ctor, llvm::Value *CopyCtor, llvm::Value *Dtor, SourceLocation Loc)
Emits initialization code for the threadprivate variables.
virtual void emitUserDefinedReduction(CodeGenFunction *CGF, const OMPDeclareReductionDecl *D)
Emit code for the specified user defined reduction construct.
virtual void checkAndEmitSharedLastprivateConditional(CodeGenFunction &CGF, const OMPExecutableDirective &D, const llvm::DenseSet< CanonicalDeclPtr< const VarDecl > > &IgnoredDecls)
Checks if the lastprivate conditional was updated in inner region and writes the value.
QualType KmpDimTy
struct kmp_dim { // loop bounds info casted to kmp_int64 kmp_int64 lo; // lower kmp_int64 up; // uppe...
virtual void emitInlinedDirective(CodeGenFunction &CGF, OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen, bool HasCancel=false)
Emit code for the directive that does not require outlining.
virtual void registerTargetGlobalVariable(const VarDecl *VD, llvm::Constant *Addr)
Checks if the provided global decl GD is a declare target variable and registers it when emitting cod...
virtual void emitFunctionProlog(CodeGenFunction &CGF, const Decl *D)
Emits OpenMP-specific function prolog.
virtual void emitParallelCall(CodeGenFunction &CGF, SourceLocation Loc, llvm::Function *OutlinedFn, ArrayRef< llvm::Value * > CapturedVars, const Expr *IfCond, llvm::Value *NumThreads)
Emits code for parallel or serial call of the OutlinedFn with variables captured in a record which ad...
void emitKmpRoutineEntryT(QualType KmpInt32Ty)
Build type kmp_routine_entry_t (if not built yet).
virtual bool isStaticChunked(OpenMPScheduleClauseKind ScheduleKind, bool Chunked) const
Check if the specified ScheduleKind is static chunked.
virtual void emitTargetCall(CodeGenFunction &CGF, const OMPExecutableDirective &D, llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID, const Expr *IfCond, llvm::PointerIntPair< const Expr *, 2, OpenMPDeviceClauseModifier > Device, llvm::function_ref< llvm::Value *(CodeGenFunction &CGF, const OMPLoopDirective &D)> SizeEmitter)
Emit the target offloading code associated with D.
virtual bool hasAllocateAttributeForGlobalVar(const VarDecl *VD, LangAS &AS)
Checks if the variable has associated OMPAllocateDeclAttr attribute with the predefined allocator and...
llvm::AtomicOrdering RequiresAtomicOrdering
Atomic ordering from the omp requires directive.
virtual void emitReduction(CodeGenFunction &CGF, SourceLocation Loc, ArrayRef< const Expr * > Privates, ArrayRef< const Expr * > LHSExprs, ArrayRef< const Expr * > RHSExprs, ArrayRef< const Expr * > ReductionOps, ReductionOptionsTy Options)
Emit a code for reduction clause.
std::pair< llvm::Value *, Address > emitDependClause(CodeGenFunction &CGF, ArrayRef< OMPTaskDataTy::DependData > Dependencies, SourceLocation Loc)
Emits list of dependecies based on the provided data (array of dependence/expression pairs).
llvm::StringMap< llvm::WeakTrackingVH > EmittedNonTargetVariables
List of the global variables with their addresses that should not be emitted for the target.
virtual bool isDynamic(OpenMPScheduleClauseKind ScheduleKind) const
Check if the specified ScheduleKind is dynamic.
Address emitLastprivateConditionalInit(CodeGenFunction &CGF, const VarDecl *VD)
Create specialized alloca to handle lastprivate conditionals.
virtual void emitOrderedRegion(CodeGenFunction &CGF, const RegionCodeGenTy &OrderedOpGen, SourceLocation Loc, bool IsThreads)
Emit an ordered region.
virtual Address getAddressOfLocalVariable(CodeGenFunction &CGF, const VarDecl *VD)
Gets the OpenMP-specific address of the local variable.
virtual void emitTaskReductionFini(CodeGenFunction &CGF, SourceLocation Loc, bool IsWorksharingReduction)
Emits the following code for reduction clause with task modifier:
virtual void emitMaskedRegion(CodeGenFunction &CGF, const RegionCodeGenTy &MaskedOpGen, SourceLocation Loc, const Expr *Filter=nullptr)
Emits a masked region.
QualType KmpDependInfoTy
Type typedef struct kmp_depend_info { kmp_intptr_t base_addr; size_t len; struct { bool in:1; bool ou...
llvm::Function * emitReductionFunction(StringRef ReducerName, SourceLocation Loc, llvm::Type *ArgsElemType, ArrayRef< const Expr * > Privates, ArrayRef< const Expr * > LHSExprs, ArrayRef< const Expr * > RHSExprs, ArrayRef< const Expr * > ReductionOps)
Emits reduction function.
virtual void emitForDispatchInit(CodeGenFunction &CGF, SourceLocation Loc, const OpenMPScheduleTy &ScheduleKind, unsigned IVSize, bool IVSigned, bool Ordered, const DispatchRTInput &DispatchValues)
Call the appropriate runtime routine to initialize it before start of loop.
Address getTaskReductionItem(CodeGenFunction &CGF, SourceLocation Loc, llvm::Value *ReductionsPtr, LValue SharedLVal) override
Get the address of void * type of the privatue copy of the reduction item specified by the SharedLVal...
void emitCriticalRegion(CodeGenFunction &CGF, StringRef CriticalName, const RegionCodeGenTy &CriticalOpGen, SourceLocation Loc, const Expr *Hint=nullptr) override
Emits a critical region.
void emitDistributeStaticInit(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDistScheduleClauseKind SchedKind, const StaticRTInput &Values) override
void emitForStaticInit(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind DKind, const OpenMPScheduleTy &ScheduleKind, const StaticRTInput &Values) override
Call the appropriate runtime routine to initialize it before start of loop.
bool emitTargetGlobalVariable(GlobalDecl GD) override
Emit the global variable if it is a valid device global variable.
llvm::Value * emitForNext(CodeGenFunction &CGF, SourceLocation Loc, unsigned IVSize, bool IVSigned, Address IL, Address LB, Address UB, Address ST) override
Call __kmpc_dispatch_next( ident_t *loc, kmp_int32 tid, kmp_int32 *p_lastiter, kmp_int[32|64] *p_lowe...
llvm::Function * emitThreadPrivateVarDefinition(const VarDecl *VD, Address VDAddr, SourceLocation Loc, bool PerformInit, CodeGenFunction *CGF=nullptr) override
Emit a code for initialization of threadprivate variable.
void emitTargetDataStandAloneCall(CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, const Expr *Device) override
Emit the data mapping/movement code associated with the directive D that should be of the form 'targe...
llvm::Function * emitTeamsOutlinedFunction(CodeGenFunction &CGF, const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) override
Emits outlined function for the specified OpenMP teams directive D.
void emitReduction(CodeGenFunction &CGF, SourceLocation Loc, ArrayRef< const Expr * > Privates, ArrayRef< const Expr * > LHSExprs, ArrayRef< const Expr * > RHSExprs, ArrayRef< const Expr * > ReductionOps, ReductionOptionsTy Options) override
Emit a code for reduction clause.
void emitFlush(CodeGenFunction &CGF, ArrayRef< const Expr * > Vars, SourceLocation Loc, llvm::AtomicOrdering AO) override
Emit flush of the variables specified in 'omp flush' directive.
void emitDoacrossOrdered(CodeGenFunction &CGF, const OMPDependClause *C) override
Emit code for doacross ordered directive with 'depend' clause.
void emitTaskyieldCall(CodeGenFunction &CGF, SourceLocation Loc) override
Emits a masked region.
Address getAddrOfArtificialThreadPrivate(CodeGenFunction &CGF, QualType VarType, StringRef Name) override
Creates artificial threadprivate variable with name Name and type VarType.
Address getAddrOfThreadPrivate(CodeGenFunction &CGF, const VarDecl *VD, Address VDAddr, SourceLocation Loc) override
Returns address of the threadprivate variable for the current thread.
void emitSingleRegion(CodeGenFunction &CGF, const RegionCodeGenTy &SingleOpGen, SourceLocation Loc, ArrayRef< const Expr * > CopyprivateVars, ArrayRef< const Expr * > DestExprs, ArrayRef< const Expr * > SrcExprs, ArrayRef< const Expr * > AssignmentOps) override
Emits a single region.
void emitTaskReductionFixups(CodeGenFunction &CGF, SourceLocation Loc, ReductionCodeGen &RCG, unsigned N) override
Required to resolve existing problems in the runtime.
llvm::Function * emitParallelOutlinedFunction(CodeGenFunction &CGF, const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) override
Emits outlined function for the specified OpenMP parallel directive D.
void emitCancellationPointCall(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind CancelRegion) override
Emit code for 'cancellation point' construct.
void emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind Kind, bool EmitChecks=true, bool ForceSimpleCall=false) override
Emit an implicit/explicit barrier for OpenMP threads.
Address getParameterAddress(CodeGenFunction &CGF, const VarDecl *NativeParam, const VarDecl *TargetParam) const override
Gets the address of the native argument basing on the address of the target-specific parameter.
void emitTeamsCall(CodeGenFunction &CGF, const OMPExecutableDirective &D, SourceLocation Loc, llvm::Function *OutlinedFn, ArrayRef< llvm::Value * > CapturedVars) override
Emits code for teams call of the OutlinedFn with variables captured in a record which address is stor...
void emitForOrderedIterationEnd(CodeGenFunction &CGF, SourceLocation Loc, unsigned IVSize, bool IVSigned) override
Call the appropriate runtime routine to notify that we finished iteration of the ordered loop with th...
bool emitTargetGlobal(GlobalDecl GD) override
Emit the global GD if it is meaningful for the target.
void emitTaskReductionFini(CodeGenFunction &CGF, SourceLocation Loc, bool IsWorksharingReduction) override
Emits the following code for reduction clause with task modifier:
void emitOrderedRegion(CodeGenFunction &CGF, const RegionCodeGenTy &OrderedOpGen, SourceLocation Loc, bool IsThreads) override
Emit an ordered region.
void emitForStaticFinish(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind DKind) override
Call the appropriate runtime routine to notify that we finished all the work with current loop.
llvm::Value * emitTaskReductionInit(CodeGenFunction &CGF, SourceLocation Loc, ArrayRef< const Expr * > LHSExprs, ArrayRef< const Expr * > RHSExprs, const OMPTaskDataTy &Data) override
Emit a code for initialization of task reduction clause.
void emitParallelCall(CodeGenFunction &CGF, SourceLocation Loc, llvm::Function *OutlinedFn, ArrayRef< llvm::Value * > CapturedVars, const Expr *IfCond, llvm::Value *NumThreads) override
Emits code for parallel or serial call of the OutlinedFn with variables captured in a record which ad...
void emitProcBindClause(CodeGenFunction &CGF, llvm::omp::ProcBindKind ProcBind, SourceLocation Loc) override
Emit call to void __kmpc_push_proc_bind(ident_t *loc, kmp_int32 global_tid, int proc_bind) to generat...
void emitTargetOutlinedFunction(const OMPExecutableDirective &D, StringRef ParentName, llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID, bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) override
Emit outilined function for 'target' directive.
void emitMasterRegion(CodeGenFunction &CGF, const RegionCodeGenTy &MasterOpGen, SourceLocation Loc) override
Emits a master region.
void emitNumTeamsClause(CodeGenFunction &CGF, const Expr *NumTeams, const Expr *ThreadLimit, SourceLocation Loc) override
Emits call to void __kmpc_push_num_teams(ident_t *loc, kmp_int32 global_tid, kmp_int32 num_teams,...
void emitForDispatchDeinit(CodeGenFunction &CGF, SourceLocation Loc) override
This is used for non static scheduled types and when the ordered clause is present on the loop constr...
const VarDecl * translateParameter(const FieldDecl *FD, const VarDecl *NativeParam) const override
Translates the native parameter of outlined function if this is required for target.
void emitMaskedRegion(CodeGenFunction &CGF, const RegionCodeGenTy &MaskedOpGen, SourceLocation Loc, const Expr *Filter=nullptr) override
Emits a masked region.
void emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc, const OMPExecutableDirective &D, llvm::Function *TaskFunction, QualType SharedsTy, Address Shareds, const Expr *IfCond, const OMPTaskDataTy &Data) override
Emit task region for the task directive.
void emitTargetCall(CodeGenFunction &CGF, const OMPExecutableDirective &D, llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID, const Expr *IfCond, llvm::PointerIntPair< const Expr *, 2, OpenMPDeviceClauseModifier > Device, llvm::function_ref< llvm::Value *(CodeGenFunction &CGF, const OMPLoopDirective &D)> SizeEmitter) override
Emit the target offloading code associated with D.
bool emitTargetFunctions(GlobalDecl GD) override
Emit the target regions enclosed in GD function definition or the function itself in case it is a val...
void emitNumThreadsClause(CodeGenFunction &CGF, llvm::Value *NumThreads, SourceLocation Loc) override
Emits call to void __kmpc_push_num_threads(ident_t *loc, kmp_int32 global_tid, kmp_int32 num_threads)...
void emitDoacrossInit(CodeGenFunction &CGF, const OMPLoopDirective &D, ArrayRef< Expr * > NumIterations) override
Emit initialization for doacross loop nesting support.
void emitCancelCall(CodeGenFunction &CGF, SourceLocation Loc, const Expr *IfCond, OpenMPDirectiveKind CancelRegion) override
Emit code for 'cancel' construct.
void emitTaskwaitCall(CodeGenFunction &CGF, SourceLocation Loc, const OMPTaskDataTy &Data) override
Emit code for 'taskwait' directive.
void emitTaskgroupRegion(CodeGenFunction &CGF, const RegionCodeGenTy &TaskgroupOpGen, SourceLocation Loc) override
Emit a taskgroup region.
void emitTargetDataCalls(CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, const Expr *Device, const RegionCodeGenTy &CodeGen, CGOpenMPRuntime::TargetDataInfo &Info) override
Emit the target data mapping code associated with D.
void emitForDispatchInit(CodeGenFunction &CGF, SourceLocation Loc, const OpenMPScheduleTy &ScheduleKind, unsigned IVSize, bool IVSigned, bool Ordered, const DispatchRTInput &DispatchValues) override
This is used for non static scheduled types and when the ordered clause is present on the loop constr...
llvm::Function * emitTaskOutlinedFunction(const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, const VarDecl *PartIDVar, const VarDecl *TaskTVar, OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen, bool Tied, unsigned &NumberOfParts) override
Emits outlined function for the OpenMP task directive D.
void emitTaskLoopCall(CodeGenFunction &CGF, SourceLocation Loc, const OMPLoopDirective &D, llvm::Function *TaskFunction, QualType SharedsTy, Address Shareds, const Expr *IfCond, const OMPTaskDataTy &Data) override
Emit task region for the taskloop directive.
CGRecordLayout - This class handles struct and union layout info while lowering AST types to LLVM typ...
unsigned getNonVirtualBaseLLVMFieldNo(const CXXRecordDecl *RD) const
llvm::StructType * getLLVMType() const
Return the "complete object" LLVM type associated with this record.
llvm::StructType * getBaseSubobjectLLVMType() const
Return the "base subobject" LLVM type associated with this record.
unsigned getLLVMFieldNo(const FieldDecl *FD) const
Return llvm::StructType element number that corresponds to the field FD.
unsigned getVirtualBaseIndex(const CXXRecordDecl *base) const
Return the LLVM field index corresponding to the given virtual base.
virtual void EmitBody(CodeGenFunction &CGF, const Stmt *S)
Emit the captured statement body.
RAII for correct setting/restoring of CapturedStmtInfo.
The scope used to remap some variables as private in the OpenMP loop body (or other captured region e...
bool Privatize()
Privatizes local variables previously registered as private.
bool addPrivate(const VarDecl *LocalVD, Address Addr)
Registers LocalVD variable as a private with Addr as the address of the corresponding private variabl...
An RAII object to set (and then clear) a mapping for an OpaqueValueExpr.
Enters a new scope for capturing cleanups, all of which will be executed once the scope is exited.
CodeGenFunction - This class organizes the per-function state that is used while generating LLVM code...
void FinishFunction(SourceLocation EndLoc=SourceLocation())
FinishFunction - Complete IR generation of the current function.
void EmitNullInitialization(Address DestPtr, QualType Ty)
EmitNullInitialization - Generate code to set a value of the given type to null, If the type contains...
void EmitOMPAggregateAssign(Address DestAddr, Address SrcAddr, QualType OriginalType, const llvm::function_ref< void(Address, Address)> CopyGen)
Perform element by element copying of arrays with type OriginalType from SrcAddr to DestAddr using co...
static TypeEvaluationKind getEvaluationKind(QualType T)
getEvaluationKind - Return the TypeEvaluationKind of QualType T.
void EmitBranchOnBoolExpr(const Expr *Cond, llvm::BasicBlock *TrueBlock, llvm::BasicBlock *FalseBlock, uint64_t TrueCount, Stmt::Likelihood LH=Stmt::LH_None, const Expr *ConditionalOp=nullptr)
EmitBranchOnBoolExpr - Emit a branch on a boolean condition (e.g.
JumpDest getJumpDestInCurrentScope(llvm::BasicBlock *Target)
The given basic block lies in the current EH scope, but may be a target of a potentially scope-crossi...
void EmitOMPCopy(QualType OriginalType, Address DestAddr, Address SrcAddr, const VarDecl *DestVD, const VarDecl *SrcVD, const Expr *Copy)
Emit proper copying of data from one variable to another.
void EmitStoreThroughLValue(RValue Src, LValue Dst, bool isInit=false)
EmitStoreThroughLValue - Store the specified rvalue into the specified lvalue, where both are guarant...
static void EmitOMPTargetTeamsDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsDirective &S)
Emit device code for the target teams directive.
FieldDecl * LambdaThisCaptureField
CGCapturedStmtInfo * CapturedStmtInfo
static void EmitOMPTargetTeamsDistributeDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsDistributeDirective &S)
Emit device code for the target teams distribute directive.
Address EmitLoadOfPointer(Address Ptr, const PointerType *PtrTy, LValueBaseInfo *BaseInfo=nullptr, TBAAAccessInfo *TBAAInfo=nullptr)
Load a pointer with type PtrTy stored at address Ptr.
RawAddress CreateDefaultAlignTempAlloca(llvm::Type *Ty, const Twine &Name="tmp")
CreateDefaultAlignedTempAlloca - This creates an alloca with the default ABI alignment of the given L...
static void EmitOMPTargetParallelForSimdDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetParallelForSimdDirective &S)
Emit device code for the target parallel for simd directive.
llvm::Value * emitArrayLength(const ArrayType *arrayType, QualType &baseType, Address &addr)
emitArrayLength - Compute the length of an array, even if it's a VLA, and drill down to the base elem...
VlaSizePair getVLASize(const VariableArrayType *vla)
Returns an LLVM value that corresponds to the size, in non-variably-sized elements,...
JumpDest getOMPCancelDestination(OpenMPDirectiveKind Kind)
LValue EmitLValue(const Expr *E, KnownNonNull_t IsKnownNonNull=NotKnownNonNull)
EmitLValue - Emit code to compute a designator that specifies the location of the expression.
static void EmitOMPTargetDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetDirective &S)
Emit device code for the target directive.
void EmitVariablyModifiedType(QualType Ty)
EmitVLASize - Capture all the sizes for the VLA expressions in the given variably-modified type and s...
llvm::BasicBlock * createBasicBlock(const Twine &name="", llvm::Function *parent=nullptr, llvm::BasicBlock *before=nullptr)
createBasicBlock - Create an LLVM basic block.
const LangOptions & getLangOpts() const
static void EmitOMPTargetSimdDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetSimdDirective &S)
Emit device code for the target simd directive.
LValue EmitLValueForFieldInitialization(LValue Base, const FieldDecl *Field)
EmitLValueForFieldInitialization - Like EmitLValueForField, except that if the Field is a reference,...
void EmitBlock(llvm::BasicBlock *BB, bool IsFinished=false)
EmitBlock - Emit the given block.
const CodeGen::CGBlockInfo * BlockInfo
Address EmitLoadOfReference(LValue RefLVal, LValueBaseInfo *PointeeBaseInfo=nullptr, TBAAAccessInfo *PointeeTBAAInfo=nullptr)
void EmitExprAsInit(const Expr *init, const ValueDecl *D, LValue lvalue, bool capturedByInit)
EmitExprAsInit - Emits the code necessary to initialize a location in memory with the given initializ...
RValue EmitLoadOfLValue(LValue V, SourceLocation Loc)
EmitLoadOfLValue - Given an expression that represents a value lvalue, this method emits the address ...
void EmitAnyExprToMem(const Expr *E, Address Location, Qualifiers Quals, bool IsInitializer)
EmitAnyExprToMem - Emits the code necessary to evaluate an arbitrary expression into the given memory...
void EmitIgnoredExpr(const Expr *E)
EmitIgnoredExpr - Emit an expression in a context which ignores the result.
llvm::Type * ConvertTypeForMem(QualType T)
const Decl * CurCodeDecl
CurCodeDecl - This is the inner-most code context, which includes blocks.
llvm::AssertingVH< llvm::Instruction > AllocaInsertPt
AllocaInsertPoint - This is an instruction in the entry block before which we prefer to insert alloca...
void EmitAggregateAssign(LValue Dest, LValue Src, QualType EltTy)
Emit an aggregate assignment.
void GenerateOpenMPCapturedVars(const CapturedStmt &S, SmallVectorImpl< llvm::Value * > &CapturedVars)
JumpDest ReturnBlock
ReturnBlock - Unified return block.
static void EmitOMPTargetTeamsGenericLoopDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsGenericLoopDirective &S)
Emit device code for the target teams loop directive.
LValue EmitLValueForField(LValue Base, const FieldDecl *Field)
RawAddress CreateMemTemp(QualType T, const Twine &Name="tmp", RawAddress *Alloca=nullptr)
CreateMemTemp - Create a temporary memory object of the given type, with appropriate alignmen and cas...
Destroyer * getDestroyer(QualType::DestructionKind destructionKind)
static void EmitOMPTargetTeamsDistributeParallelForDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsDistributeParallelForDirective &S)
llvm::Value * getTypeSize(QualType Ty)
Returns calculated size of the specified type.
void emitDestroy(Address addr, QualType type, Destroyer *destroyer, bool useEHCleanupForArray)
Address EmitPointerWithAlignment(const Expr *Addr, LValueBaseInfo *BaseInfo=nullptr, TBAAAccessInfo *TBAAInfo=nullptr, KnownNonNull_t IsKnownNonNull=NotKnownNonNull)
EmitPointerWithAlignment - Given an expression with a pointer type, emit the value and compute our be...
void StartFunction(GlobalDecl GD, QualType RetTy, llvm::Function *Fn, const CGFunctionInfo &FnInfo, const FunctionArgList &Args, SourceLocation Loc=SourceLocation(), SourceLocation StartLoc=SourceLocation())
Emit code for the start of a function.
ComplexPairTy EmitLoadOfComplex(LValue src, SourceLocation loc)
EmitLoadOfComplex - Load a complex number from the specified l-value.
bool HaveInsertPoint() const
HaveInsertPoint - True if an insertion point is defined.
bool isTrivialInitializer(const Expr *Init)
Determine whether the given initializer is trivial in the sense that it requires no code to be genera...
void EmitBranch(llvm::BasicBlock *Block)
EmitBranch - Emit a branch to the specified basic block from the current insert block,...
LValue MakeRawAddrLValue(llvm::Value *V, QualType T, CharUnits Alignment, AlignmentSource Source=AlignmentSource::Type)
Same as MakeAddrLValue above except that the pointer is known to be unsigned.
void EmitAggregateCopy(LValue Dest, LValue Src, QualType EltTy, AggValueSlot::Overlap_t MayOverlap, bool isVolatile=false)
EmitAggregateCopy - Emit an aggregate copy.
LValue MakeNaturalAlignRawAddrLValue(llvm::Value *V, QualType T)
void EmitOMPTargetTaskBasedDirective(const OMPExecutableDirective &S, const RegionCodeGenTy &BodyGen, OMPTargetDataInfo &InputInfo)
static void EmitOMPTargetParallelForDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetParallelForDirective &S)
Emit device code for the target parallel for directive.
void EmitVarDecl(const VarDecl &D)
EmitVarDecl - Emit a local variable declaration.
llvm::CallInst * EmitNounwindRuntimeCall(llvm::FunctionCallee callee, const Twine &name="")
ASTContext & getContext() const
llvm::Value * EmitLoadOfScalar(Address Addr, bool Volatile, QualType Ty, SourceLocation Loc, AlignmentSource Source=AlignmentSource::Type, bool isNontemporal=false)
EmitLoadOfScalar - Load a scalar value from an address, taking care to appropriately convert from the...
const Decl * CurFuncDecl
CurFuncDecl - Holds the Decl for the current outermost non-closure context.
LValue EmitLoadOfPointerLValue(Address Ptr, const PointerType *PtrTy)
static void EmitOMPTargetTeamsDistributeSimdDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsDistributeSimdDirective &S)
Emit device code for the target teams distribute simd directive.
void EmitBranchThroughCleanup(JumpDest Dest)
EmitBranchThroughCleanup - Emit a branch from the current insert block through the normal cleanup han...
AutoVarEmission EmitAutoVarAlloca(const VarDecl &var)
void pushDestroy(QualType::DestructionKind dtorKind, Address addr, QualType type)
bool ConstantFoldsToSimpleInteger(const Expr *Cond, bool &Result, bool AllowLabels=false)
ConstantFoldsToSimpleInteger - If the specified expression does not fold to a constant,...
void EmitAutoVarCleanups(const AutoVarEmission &emission)
bool needsEHCleanup(QualType::DestructionKind kind)
Determines whether an EH cleanup is required to destroy a type with the given destruction kind.
llvm::DenseMap< const ValueDecl *, FieldDecl * > LambdaCaptureFields
llvm::CallInst * EmitRuntimeCall(llvm::FunctionCallee callee, const Twine &name="")
CodeGenTypes & getTypes() const
LValue EmitArraySectionExpr(const ArraySectionExpr *E, bool IsLowerBound=true)
static void EmitOMPTargetTeamsDistributeParallelForSimdDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsDistributeParallelForSimdDirective &S)
Emit device code for the target teams distribute parallel for simd directive.
LValue EmitStringLiteralLValue(const StringLiteral *E)
llvm::Value * EvaluateExprAsBool(const Expr *E)
EvaluateExprAsBool - Perform the usual unary conversions on the specified expression and compare the ...
Address LoadCXXThisAddress()
LValue EmitOMPSharedLValue(const Expr *E)
Emits the lvalue for the expression with possibly captured variable.
llvm::Value * EmitCheckedInBoundsGEP(llvm::Type *ElemTy, llvm::Value *Ptr, ArrayRef< llvm::Value * > IdxList, bool SignedIndices, bool IsSubtraction, SourceLocation Loc, const Twine &Name="")
Same as IRBuilder::CreateInBoundsGEP, but additionally emits a check to detect undefined behavior whe...
llvm::Function * GenerateOpenMPCapturedStmtFunction(const CapturedStmt &S, SourceLocation Loc)
LValue MakeAddrLValue(Address Addr, QualType T, AlignmentSource Source=AlignmentSource::Type)
void EmitStoreOfComplex(ComplexPairTy V, LValue dest, bool isInit)
EmitStoreOfComplex - Store a complex number into the specified l-value.
static void EmitOMPTargetParallelGenericLoopDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetParallelGenericLoopDirective &S)
Emit device code for the target parallel loop directive.
LValue EmitLoadOfReferenceLValue(LValue RefLVal)
Address GetAddrOfLocalVar(const VarDecl *VD)
GetAddrOfLocalVar - Return the address of a local variable.
void EmitAtomicStore(RValue rvalue, LValue lvalue, bool isInit)
llvm::Value * EmitScalarConversion(llvm::Value *Src, QualType SrcTy, QualType DstTy, SourceLocation Loc)
Emit a conversion from the specified type to the specified destination type, both of which are LLVM s...
std::pair< llvm::Value *, llvm::Value * > ComplexPairTy
Address ReturnValue
ReturnValue - The temporary alloca to hold the return value.
static void EmitOMPTargetParallelDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetParallelDirective &S)
llvm::Value * EmitScalarExpr(const Expr *E, bool IgnoreResultAssign=false)
EmitScalarExpr - Emit the computation of the specified expression of LLVM scalar type,...
void incrementProfileCounter(const Stmt *S, llvm::Value *StepV=nullptr)
Increment the profiler's counter for the given statement by StepV.
void EmitStoreOfScalar(llvm::Value *Value, Address Addr, bool Volatile, QualType Ty, AlignmentSource Source=AlignmentSource::Type, bool isInit=false, bool isNontemporal=false)
EmitStoreOfScalar - Store a scalar value to an address, taking care to appropriately convert from the...
This class organizes the cross-function state that is used while generating LLVM code.
void handleCUDALaunchBoundsAttr(llvm::Function *F, const CUDALaunchBoundsAttr *A, int32_t *MaxThreadsVal=nullptr, int32_t *MinBlocksVal=nullptr, int32_t *MaxClusterRankVal=nullptr)
Emit the IR encoding to attach the CUDA launch bounds attribute to F.
void SetInternalFunctionAttributes(GlobalDecl GD, llvm::Function *F, const CGFunctionInfo &FI)
Set the attributes on the LLVM function for the given decl and function info.
llvm::Module & getModule() const
void addCompilerUsedGlobal(llvm::GlobalValue *GV)
Add a global to a list to be added to the llvm.compiler.used metadata.
CharUnits GetTargetTypeStoreSize(llvm::Type *Ty) const
Return the store size, in character units, of the given LLVM type.
void handleAMDGPUWavesPerEUAttr(llvm::Function *F, const AMDGPUWavesPerEUAttr *A)
Emit the IR encoding to attach the AMD GPU waves-per-eu attribute to F.
DiagnosticsEngine & getDiags() const
const LangOptions & getLangOpts() const
CharUnits getNaturalTypeAlignment(QualType T, LValueBaseInfo *BaseInfo=nullptr, TBAAAccessInfo *TBAAInfo=nullptr, bool forPointeeType=false)
CodeGenTypes & getTypes()
const TargetInfo & getTarget() const
void EmitGlobal(GlobalDecl D)
Emit code for a single global function or var decl.
void handleAMDGPUFlatWorkGroupSizeAttr(llvm::Function *F, const AMDGPUFlatWorkGroupSizeAttr *A, const ReqdWorkGroupSizeAttr *ReqdWGS=nullptr, int32_t *MinThreadsVal=nullptr, int32_t *MaxThreadsVal=nullptr)
Emit the IR encoding to attach the AMD GPU flat-work-group-size attribute to F.
llvm::GlobalValue::LinkageTypes getLLVMLinkageVarDefinition(const VarDecl *VD)
Returns LLVM linkage for a declarator.
CGCXXABI & getCXXABI() const
CGOpenMPRuntime & getOpenMPRuntime()
Return a reference to the configured OpenMP runtime.
const llvm::Triple & getTriple() const
TBAAAccessInfo getTBAAInfoForSubobject(LValue Base, QualType AccessType)
getTBAAInfoForSubobject - Get TBAA information for an access with a given base lvalue.
llvm::Constant * GetAddrOfGlobal(GlobalDecl GD, ForDefinition_t IsForDefinition=NotForDefinition)
ASTContext & getContext() const
const TargetCodeGenInfo & getTargetCodeGenInfo()
const CodeGenOptions & getCodeGenOpts() const
StringRef getMangledName(GlobalDecl GD)
std::optional< CharUnits > getOMPAllocateAlignment(const VarDecl *VD)
Return the alignment specified in an allocate directive, if present.
llvm::GlobalValue * GetGlobalValue(StringRef Ref)
llvm::Constant * EmitNullConstant(QualType T)
Return the result of value-initializing the given type, i.e.
llvm::Function * CreateGlobalInitOrCleanUpFunction(llvm::FunctionType *ty, const Twine &name, const CGFunctionInfo &FI, SourceLocation Loc=SourceLocation(), bool TLS=false, llvm::GlobalVariable::LinkageTypes Linkage=llvm::GlobalVariable::InternalLinkage)
llvm::ConstantInt * getSize(CharUnits numChars)
Emit the given number of characters as a value of type size_t.
llvm::Type * ConvertType(QualType T)
ConvertType - Convert type T into a llvm::Type.
llvm::FunctionType * GetFunctionType(const CGFunctionInfo &Info)
GetFunctionType - Get the LLVM function type for.
const CGFunctionInfo & arrangeBuiltinFunctionDeclaration(QualType resultType, const FunctionArgList &args)
A builtin function is a freestanding function using the default C conventions.
const CGRecordLayout & getCGRecordLayout(const RecordDecl *)
getCGRecordLayout - Return record layout info for the given record decl.
llvm::Type * ConvertTypeForMem(QualType T)
ConvertTypeForMem - Convert type T into a llvm::Type.
const CGFunctionInfo & arrangeNullaryFunction()
A nullary function is a freestanding function of type 'void ()'.
A specialization of Address that requires the address to be an LLVM Constant.
static ConstantAddress invalid()
Information for lazily generating a cleanup.
bool requiresLandingPad() const
void popTerminate()
Pops a terminate handler off the stack.
void pushTerminate()
Push a terminate handler on the stack.
FunctionArgList - Type for representing both the decl and type of parameters to a function.
LValue - This represents an lvalue references.
CharUnits getAlignment() const
llvm::Value * getPointer(CodeGenFunction &CGF) const
const Qualifiers & getQuals() const
Address getAddress() const
LValueBaseInfo getBaseInfo() const
TBAAAccessInfo getTBAAInfo() const
A basic class for pre|post-action for advanced codegen sequence for OpenMP region.
virtual void Enter(CodeGenFunction &CGF)
RValue - This trivial value class is used to represent the result of an expression that is evaluated.
static RValue get(llvm::Value *V)
static RValue getComplex(llvm::Value *V1, llvm::Value *V2)
llvm::Value * getScalarVal() const
getScalarVal() - Return the Value* of this scalar value.
An abstract representation of an aligned address.
llvm::Type * getElementType() const
Return the type of the values stored in this address.
llvm::Value * getPointer() const
static RawAddress invalid()
Class intended to support codegen of all kind of the reduction clauses.
LValue getSharedLValue(unsigned N) const
Returns LValue for the reduction item.
const Expr * getRefExpr(unsigned N) const
Returns the base declaration of the reduction item.
LValue getOrigLValue(unsigned N) const
Returns LValue for the original reduction item.
bool needCleanups(unsigned N)
Returns true if the private copy requires cleanups.
void emitAggregateType(CodeGenFunction &CGF, unsigned N)
Emits the code for the variable-modified type, if required.
const VarDecl * getBaseDecl(unsigned N) const
Returns the base declaration of the reduction item.
QualType getPrivateType(unsigned N) const
Return the type of the private item.
bool usesReductionInitializer(unsigned N) const
Returns true if the initialization of the reduction item uses initializer from declare reduction cons...
void emitSharedOrigLValue(CodeGenFunction &CGF, unsigned N)
Emits lvalue for the shared and original reduction item.
void emitInitialization(CodeGenFunction &CGF, unsigned N, Address PrivateAddr, Address SharedAddr, llvm::function_ref< bool(CodeGenFunction &)> DefaultInit)
Performs initialization of the private copy for the reduction item.
std::pair< llvm::Value *, llvm::Value * > getSizes(unsigned N) const
Returns the size of the reduction item (in chars and total number of elements in the item),...
ReductionCodeGen(ArrayRef< const Expr * > Shareds, ArrayRef< const Expr * > Origs, ArrayRef< const Expr * > Privates, ArrayRef< const Expr * > ReductionOps)
void emitCleanups(CodeGenFunction &CGF, unsigned N, Address PrivateAddr)
Emits cleanup code for the reduction item.
Address adjustPrivateAddress(CodeGenFunction &CGF, unsigned N, Address PrivateAddr)
Adjusts PrivatedAddr for using instead of the original variable address in normal operations.
Class provides a way to call simple version of codegen for OpenMP region, or an advanced with possibl...
void operator()(CodeGenFunction &CGF) const
void setAction(PrePostActionTy &Action) const
virtual void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &M) const
setTargetAttributes - Provides a convenient hook to handle extra target-specific attributes for the g...
ConstStmtVisitor - This class implements a simple visitor for Stmt subclasses.
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
void addDecl(Decl *D)
Add the declaration D into this context.
A reference to a declared variable, function, enum, etc.
Decl - This represents one declaration (or definition), e.g.
SourceLocation getEndLoc() const LLVM_READONLY
ASTContext & getASTContext() const LLVM_READONLY
virtual bool hasBody() const
Returns true if this Decl represents a declaration for a body of code, such as a function or method d...
llvm::iterator_range< specific_attr_iterator< T > > specific_attrs() const
SourceLocation getLocation() const
DeclContext * getDeclContext()
SourceLocation getBeginLoc() const LLVM_READONLY
virtual Decl * getCanonicalDecl()
Retrieves the "canonical" declaration of the given declaration.
SourceLocation getBeginLoc() const LLVM_READONLY
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
unsigned getCustomDiagID(Level L, const char(&FormatString)[N])
Return an ID for a diagnostic with the specified format string and level.
The return type of classify().
This represents one expression.
@ SE_AllowSideEffects
Allow any unmodeled side effect.
@ SE_AllowUndefinedBehavior
Allow UB that we can give a value, but not arbitrary unmodeled side effects.
Expr * IgnoreParenCasts() LLVM_READONLY
Skip past any parentheses and casts which might surround this expression until reaching a fixed point...
llvm::APSInt EvaluateKnownConstInt(const ASTContext &Ctx, SmallVectorImpl< PartialDiagnosticAt > *Diag=nullptr) const
EvaluateKnownConstInt - Call EvaluateAsRValue and return the folded integer.
Expr * IgnoreParenImpCasts() LLVM_READONLY
Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...
bool isEvaluatable(const ASTContext &Ctx, SideEffectsKind AllowSideEffects=SE_NoSideEffects) const
isEvaluatable - Call EvaluateAsRValue to see if this expression can be constant folded without side-e...
bool HasSideEffects(const ASTContext &Ctx, bool IncludePossibleEffects=true) const
HasSideEffects - This routine returns true for all those expressions which have any effect other than...
bool isIntegerConstantExpr(const ASTContext &Ctx, SourceLocation *Loc=nullptr) const
bool EvaluateAsBooleanCondition(bool &Result, const ASTContext &Ctx, bool InConstantContext=false) const
EvaluateAsBooleanCondition - Return true if this is a constant which we can fold and convert to a boo...
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
std::optional< llvm::APSInt > getIntegerConstantExpr(const ASTContext &Ctx, SourceLocation *Loc=nullptr) const
isIntegerConstantExpr - Return the value if this expression is a valid integer constant expression.
bool hasNonTrivialCall(const ASTContext &Ctx) const
Determine whether this expression involves a call to any function that is not trivial.
Represents a member of a struct/union/class.
static FieldDecl * Create(const ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, const IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, Expr *BW, bool Mutable, InClassInitStyle InitStyle)
Represents a function declaration or definition.
const ParmVarDecl * getParamDecl(unsigned i) const
QualType getReturnType() const
ArrayRef< ParmVarDecl * > parameters() const
FunctionDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
unsigned getNumParams() const
Return the number of parameters this function must have based on its FunctionType.
GlobalDecl - represents a global declaration.
const Decl * getDecl() const
static ImplicitParamDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation IdLoc, IdentifierInfo *Id, QualType T, ImplicitParamKind ParamKind)
Create implicit parameter.
static IntegerLiteral * Create(const ASTContext &C, const llvm::APInt &V, QualType type, SourceLocation l)
Returns a new integer literal with value 'V' and type 'type'.
Describes the capture of a variable or of this, or of a C++1y init-capture.
std::string OMPHostIRFile
Name of the IR file that contains the result of the OpenMP target host code generation.
std::vector< llvm::Triple > OMPTargetTriples
Triples of the OpenMP targets that the host code codegen should take into account in order to generat...
virtual void mangleCanonicalTypeName(QualType T, raw_ostream &, bool NormalizeIntegers=false)=0
Generates a unique string for an externally visible type for use with TBAA or type uniquing.
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
ValueDecl * getMemberDecl() const
Retrieve the member declaration to which this expression refers.
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
bool isExternallyVisible() const
This represents clause 'affinity' in the '#pragma omp task'-based directives.
Class that represents a component of a mappable expression.
ArrayRef< MappableComponent > MappableExprComponentListRef
const Stmt * getPreInitStmt() const
Get pre-initialization statement for the clause.
This is a basic class for representing single OpenMP clause.
This represents '#pragma omp declare mapper ...' directive.
This represents '#pragma omp declare reduction ...' directive.
Expr * getInitializer()
Get initializer expression (if specified) of the declare reduction construct.
This represents implicit clause 'depend' for the '#pragma omp task' directive.
This represents 'detach' clause in the '#pragma omp task' directive.
This represents 'device' clause in the '#pragma omp ...' directive.
This represents the 'doacross' clause for the '#pragma omp ordered' directive.
This is a basic class for representing single OpenMP executable directive.
static llvm::iterator_range< specific_clause_iterator< SpecificClause > > getClausesOfKind(ArrayRef< OMPClause * > Clauses)
This represents clause 'firstprivate' in the '#pragma omp ...' directives.
This represents clause 'has_device_ptr' in the '#pragma omp ...' directives.
This represents 'if' clause in the '#pragma omp ...' directive.
Expr * getCondition() const
Returns condition.
This represents clause 'in_reduction' in the '#pragma omp task' directives.
This represents clause 'is_device_ptr' in the '#pragma omp ...' directives.
OpenMP 5.0 [2.1.6 Iterators] Iterators are identifiers that expand to multiple values in the clause o...
This represents clause 'lastprivate' in the '#pragma omp ...' directives.
This represents clause 'linear' in the '#pragma omp ...' directives.
This is a common base class for loop directives ('omp simd', 'omp for', 'omp for simd' etc....
This represents clause 'map' in the '#pragma omp ...' directives.
This represents clause 'nontemporal' in the '#pragma omp ...' directives.
This represents 'nowait' clause in the '#pragma omp ...' directive.
This represents 'num_teams' clause in the '#pragma omp ...' directive.
This represents 'num_threads' clause in the '#pragma omp ...' directive.
This represents 'ordered' clause in the '#pragma omp ...' directive.
This represents clause 'private' in the '#pragma omp ...' directives.
This represents clause 'reduction' in the '#pragma omp ...' directives.
This represents '#pragma omp requires...' directive.
This represents 'thread_limit' clause in the '#pragma omp ...' directive.
This represents clause 'uses_allocators' in the '#pragma omp target'-based directives.
This represents 'ompx_attribute' clause in a directive that might generate an outlined function.
This represents 'ompx_bare' clause in the '#pragma omp target teams ...' directive.
This represents 'ompx_dyn_cgroup_mem' clause in the '#pragma omp target ...' directive.
OpaqueValueExpr - An expression referring to an opaque object of a fixed type and value class.
Represents a parameter to a function.
PointerType - C99 6.7.5.1 - Pointer Declarators.
Represents an unpacked "presumed" location which can be presented to the user.
unsigned getColumn() const
Return the presumed column number of this location.
const char * getFilename() const
Return the presumed filename of this location.
unsigned getLine() const
Return the presumed line number of this location.
A (possibly-)qualified type.
void addRestrict()
Add the restrict qualifier to this QualType.
QualType withRestrict() const
bool isNull() const
Return true if this QualType doesn't point to a type yet.
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
Qualifiers getQualifiers() const
Retrieve the set of qualifiers applied to this type.
QualType getNonReferenceType() const
If Type is a reference type (e.g., const int&), returns the type that the reference refers to ("const...
QualType getCanonicalType() const
DestructionKind isDestructedType() const
Returns a nonzero value if objects of this type require non-trivial work to clean up after.
Represents a struct/union/class.
field_iterator field_end() const
field_range fields() const
virtual void completeDefinition()
Note that the definition of this type is now complete.
field_iterator field_begin() const
RecordDecl * getDecl() const
decl_type * getPreviousDecl()
Return the previous declaration of this declaration or NULL if this is the first declaration.
decl_type * getMostRecentDecl()
Returns the most recent (re)declaration of this declaration.
Base for LValueReferenceType and RValueReferenceType.
Scope - A scope is a transient data structure that is used while parsing the program.
Encodes a location in the source.
static SourceLocation getFromRawEncoding(UIntTy Encoding)
Turn a raw encoding of a SourceLocation object into a real SourceLocation.
bool isValid() const
Return true if this is a valid SourceLocation object.
UIntTy getRawEncoding() const
When a SourceLocation itself cannot be used, this returns an (opaque) 32-bit integer encoding for it.
This class handles loading and caching of source files into memory.
PresumedLoc getPresumedLoc(SourceLocation Loc, bool UseLineDirectives=true) const
Returns the "presumed" location of a SourceLocation specifies.
fileinfo_iterator fileinfo_end() const
SourceLocation translateFileLineCol(const FileEntry *SourceFile, unsigned Line, unsigned Col) const
Get the source location for the given file:line:col triplet.
fileinfo_iterator fileinfo_begin() const
A trivial tuple used to represent a source range.
Stmt - This represents one statement.
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Stmt * IgnoreContainers(bool IgnoreCaptured=false)
Skip no-op (attributed, compound) container stmts and skip captured stmt at the top,...
SourceLocation getBeginLoc() const LLVM_READONLY
void startDefinition()
Starts the definition of this tag declaration.
bool isTLSSupported() const
Whether the target supports thread-local storage.
virtual bool hasFeature(StringRef Feature) const
Determine whether the given target has the given feature.
The base class of the type hierarchy.
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
bool isSignedIntegerOrEnumerationType() const
Determines whether this is an integer type that is signed or an enumeration types whose underlying ty...
const Type * getPointeeOrArrayElementType() const
If this is a pointer type, return the pointee type.
bool isSignedIntegerType() const
Return true if this is an integer type that is signed, according to C99 6.2.5p4 [char,...
bool isPointerType() const
CanQualType getCanonicalTypeUnqualified() const
bool isIntegerType() const
isIntegerType() does not include complex integers (a GCC extension).
const T * castAs() const
Member-template castAs<specific type>.
bool isReferenceType() const
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
bool isLValueReferenceType() const
QualType getCanonicalTypeInternal() const
const RecordType * getAsStructureType() const
const Type * getBaseElementTypeUnsafe() const
Get the base element type of this type, potentially discarding type qualifiers.
bool isVariablyModifiedType() const
Whether this type is a variably-modified type (C99 6.7.5).
const ArrayType * getAsArrayTypeUnsafe() const
A variant of getAs<> for array types which silently discards qualifiers from the outermost type.
bool isFloatingType() const
bool isUnsignedIntegerType() const
Return true if this is an integer type that is unsigned, according to C99 6.2.5p6 [which returns true...
bool isAnyPointerType() const
const T * getAs() const
Member-template getAs<specific type>'.
bool isRecordType() const
TagDecl * getAsTagDecl() const
Retrieves the TagDecl that this type refers to, either because the type is a TagType or because it is...
RecordDecl * getAsRecordDecl() const
Retrieves the RecordDecl this type refers to.
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Represents a variable declaration or definition.
VarDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
VarDecl * getDefinition(ASTContext &)
Get the real (not just tentative) definition for this declaration.
bool hasExternalStorage() const
Returns true if a variable has extern or private_extern storage.
bool hasLocalStorage() const
Returns true if a variable with function scope is a non-static local variable.
@ DeclarationOnly
This declaration is only a declaration.
DefinitionKind hasDefinition(ASTContext &) const
Check whether this variable is defined in this translation unit.
bool isLocalVarDeclOrParm() const
Similar to isLocalVarDecl but also includes parameters.
const Expr * getAnyInitializer() const
Get the initializer for this variable, no matter which declaration it is attached to.
Represents a C array with a specified size that is not an integer-constant-expression.
Expr * getSizeExpr() const
specific_attr_iterator - Iterates over a subrange of an AttrVec, only providing attributes that are o...
bool isEmptyRecordForLayout(const ASTContext &Context, QualType T)
isEmptyRecordForLayout - Return true iff a structure contains only empty base classes (per isEmptyRec...
@ Decl
The l-value was an access to a declared entity or something equivalently strong, like the address of ...
bool isEmptyFieldForLayout(const ASTContext &Context, const FieldDecl *FD)
isEmptyFieldForLayout - Return true iff the field is "empty", that is, either a zero-width bit-field ...
The JSON file list parser is used to communicate input to InstallAPI.
bool isOpenMPWorksharingDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a worksharing directive.
bool needsTaskBasedThreadLimit(OpenMPDirectiveKind DKind)
Checks if the specified target directive, combined or not, needs task based thread_limit.
@ Ctor_Complete
Complete object ctor.
if(T->getSizeExpr()) TRY_TO(TraverseStmt(const_cast< Expr * >(T -> getSizeExpr())))
bool isOpenMPTargetDataManagementDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a target data offload directive.
llvm::omp::Directive OpenMPDirectiveKind
OpenMP directives.
@ ICIS_NoInit
No in-class initializer.
bool isOpenMPDistributeDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a distribute directive.
@ LCK_ByRef
Capturing by reference.
LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE()
@ Private
'private' clause, allowed on 'parallel', 'serial', 'loop', 'parallel loop', and 'serial loop' constru...
@ Vector
'vector' clause, allowed on 'loop', Combined, and 'routine' directives.
@ Reduction
'reduction' clause, allowed on Parallel, Serial, Loop, and the combined constructs.
@ Present
'present' clause, allowed on Compute and Combined constructs, plus 'data' and 'declare'.
OpenMPScheduleClauseModifier
OpenMP modifiers for 'schedule' clause.
@ OMPC_SCHEDULE_MODIFIER_last
@ OMPC_SCHEDULE_MODIFIER_unknown
bool isOpenMPParallelDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a parallel-kind directive.
OpenMPDistScheduleClauseKind
OpenMP attributes for 'dist_schedule' clause.
bool isOpenMPTaskingDirective(OpenMPDirectiveKind Kind)
Checks if the specified directive kind is one of tasking directives - task, taskloop,...
bool isOpenMPTargetExecutionDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a target code offload directive.
@ Result
The result type of a method or function.
bool isOpenMPTeamsDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a teams-kind directive.
OpenMPDependClauseKind
OpenMP attributes for 'depend' clause.
@ Dtor_Complete
Complete object dtor.
@ Union
The "union" keyword.
bool isOpenMPLoopDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a directive with an associated loop construct.
LangAS
Defines the address space values used by the address space qualifier of QualType.
bool isOpenMPSimdDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a simd directive.
@ VK_PRValue
A pr-value expression (in the C++11 taxonomy) produces a temporary value.
@ VK_LValue
An l-value expression is a reference to an object with independent storage.
const FunctionProtoType * T
void getOpenMPCaptureRegions(llvm::SmallVectorImpl< OpenMPDirectiveKind > &CaptureRegions, OpenMPDirectiveKind DKind)
Return the captured regions of an OpenMP directive.
@ OMPC_ATOMIC_DEFAULT_MEM_ORDER_unknown
OpenMPMapModifierKind
OpenMP modifier kind for 'map' clause.
@ OMPC_MAP_MODIFIER_unknown
@ Other
Other implicit parameter.
OpenMPScheduleClauseKind
OpenMP attributes for 'schedule' clause.
bool isOpenMPTaskLoopDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a taskloop directive.
OpenMPMapClauseKind
OpenMP mapping kind for 'map' clause.
Diagnostic wrappers for TextAPI types for error reporting.
struct with the values to be passed to the dispatch runtime function
llvm::Value * UB
Loop upper bound.
llvm::Value * LB
Loop lower bound.
llvm::Value * Chunk
Chunk size specified using 'schedule' clause (nullptr if chunk was not specified)
Maps the expression for the lastprivate variable to the global copy used to store new value because o...
Struct with the values to be passed to the static runtime function.
bool IVSigned
Sign of the iteration variable.
Address UB
Address of the output variable in which the upper iteration number is returned.
Address IL
Address of the output variable in which the flag of the last iteration is returned.
llvm::Value * Chunk
Value of the chunk for the static_chunked scheduled loop.
unsigned IVSize
Size of the iteration variable in bits.
Address ST
Address of the output variable in which the stride value is returned necessary to generated the stati...
bool Ordered
true if loop is ordered, false otherwise.
Address LB
Address of the output variable in which the lower iteration number is returned.
A jump destination is an abstract label, branching to which may require a jump out through normal cle...
llvm::BasicBlock * getBlock() const
unsigned NumberOfTargetItems
Address BasePointersArray
llvm::PointerType * VoidPtrTy
llvm::IntegerType * Int64Ty
llvm::PointerType * Int8PtrPtrTy
llvm::IntegerType * Int8Ty
i8, i16, i32, and i64
llvm::CallingConv::ID getRuntimeCC() const
llvm::IntegerType * SizeTy
llvm::PointerType * VoidPtrPtrTy
llvm::IntegerType * Int32Ty
llvm::IntegerType * IntPtrTy
llvm::IntegerType * IntTy
int
llvm::PointerType * Int8PtrTy
llvm::PointerType * UnqualPtrTy
CharUnits getPointerAlign() const
const Expr * IteratorExpr
SmallVector< const Expr *, 4 > DepExprs
EvalResult is a struct with detailed info about an evaluated expression.
Extra information about a function prototype.
Helper expressions and declaration for OMPIteratorExpr class for each iteration space.
Expr * CounterUpdate
Updater for the internal counter: ++CounterVD;.
Expr * Update
Update expression for the originally specified iteration variable, calculated as VD = Begin + Counter...
VarDecl * CounterVD
Internal normalized counter.
Data for list of allocators.
Scheduling data for loop-based OpenMP directives.
OpenMPScheduleClauseModifier M2
OpenMPScheduleClauseModifier M1
OpenMPScheduleClauseKind Schedule
Describes how types, statements, expressions, and declarations should be printed.
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4