31#include "llvm/ADT/ArrayRef.h"
32#include "llvm/ADT/SmallSet.h"
33#include "llvm/ADT/SmallVector.h"
34#include "llvm/ADT/StringExtras.h"
35#include "llvm/Bitcode/BitcodeReader.h"
36#include "llvm/IR/Constants.h"
37#include "llvm/IR/DerivedTypes.h"
38#include "llvm/IR/GlobalValue.h"
39#include "llvm/IR/InstrTypes.h"
40#include "llvm/IR/Value.h"
41#include "llvm/Support/AtomicOrdering.h"
42#include "llvm/Support/raw_ostream.h"
50using namespace llvm::omp;
57 enum CGOpenMPRegionKind {
60 ParallelOutlinedRegion,
70 CGOpenMPRegionInfo(
const CapturedStmt &CS,
71 const CGOpenMPRegionKind RegionKind,
74 : CGCapturedStmtInfo(CS,
CR_OpenMP), RegionKind(RegionKind),
75 CodeGen(CodeGen), Kind(Kind), HasCancel(HasCancel) {}
77 CGOpenMPRegionInfo(
const CGOpenMPRegionKind RegionKind,
80 : CGCapturedStmtInfo(
CR_OpenMP), RegionKind(RegionKind), CodeGen(CodeGen),
81 Kind(Kind), HasCancel(HasCancel) {}
85 virtual const VarDecl *getThreadIDVariable()
const = 0;
88 void EmitBody(CodeGenFunction &CGF,
const Stmt *S)
override;
92 virtual LValue getThreadIDVariableLValue(CodeGenFunction &CGF);
94 virtual void emitUntiedSwitch(CodeGenFunction & ) {}
96 CGOpenMPRegionKind getRegionKind()
const {
return RegionKind; }
100 bool hasCancel()
const {
return HasCancel; }
102 static bool classof(
const CGCapturedStmtInfo *Info) {
106 ~CGOpenMPRegionInfo()
override =
default;
109 CGOpenMPRegionKind RegionKind;
110 RegionCodeGenTy CodeGen;
116class CGOpenMPOutlinedRegionInfo final :
public CGOpenMPRegionInfo {
118 CGOpenMPOutlinedRegionInfo(
const CapturedStmt &CS,
const VarDecl *ThreadIDVar,
119 const RegionCodeGenTy &CodeGen,
121 StringRef HelperName)
122 : CGOpenMPRegionInfo(CS, ParallelOutlinedRegion, CodeGen,
Kind,
124 ThreadIDVar(ThreadIDVar), HelperName(HelperName) {
125 assert(ThreadIDVar !=
nullptr &&
"No ThreadID in OpenMP region.");
130 const VarDecl *getThreadIDVariable()
const override {
return ThreadIDVar; }
133 StringRef getHelperName()
const override {
return HelperName; }
135 static bool classof(
const CGCapturedStmtInfo *Info) {
136 return CGOpenMPRegionInfo::classof(Info) &&
138 ParallelOutlinedRegion;
144 const VarDecl *ThreadIDVar;
145 StringRef HelperName;
149class CGOpenMPTaskOutlinedRegionInfo final :
public CGOpenMPRegionInfo {
151 class UntiedTaskActionTy final :
public PrePostActionTy {
153 const VarDecl *PartIDVar;
154 const RegionCodeGenTy UntiedCodeGen;
155 llvm::SwitchInst *UntiedSwitch =
nullptr;
158 UntiedTaskActionTy(
bool Tied,
const VarDecl *PartIDVar,
159 const RegionCodeGenTy &UntiedCodeGen)
160 : Untied(!Tied), PartIDVar(PartIDVar), UntiedCodeGen(UntiedCodeGen) {}
161 void Enter(CodeGenFunction &CGF)
override {
166 PartIDVar->
getType()->castAs<PointerType>());
170 UntiedSwitch = CGF.
Builder.CreateSwitch(Res, DoneBB);
174 UntiedSwitch->addCase(CGF.
Builder.getInt32(0),
176 emitUntiedSwitch(CGF);
179 void emitUntiedSwitch(CodeGenFunction &CGF)
const {
183 PartIDVar->
getType()->castAs<PointerType>());
187 CodeGenFunction::JumpDest CurPoint =
191 UntiedSwitch->addCase(CGF.
Builder.getInt32(UntiedSwitch->getNumCases()),
197 unsigned getNumberOfParts()
const {
return UntiedSwitch->getNumCases(); }
199 CGOpenMPTaskOutlinedRegionInfo(
const CapturedStmt &CS,
200 const VarDecl *ThreadIDVar,
201 const RegionCodeGenTy &CodeGen,
203 const UntiedTaskActionTy &Action)
204 : CGOpenMPRegionInfo(CS, TaskOutlinedRegion, CodeGen,
Kind, HasCancel),
205 ThreadIDVar(ThreadIDVar), Action(Action) {
206 assert(ThreadIDVar !=
nullptr &&
"No ThreadID in OpenMP region.");
211 const VarDecl *getThreadIDVariable()
const override {
return ThreadIDVar; }
214 LValue getThreadIDVariableLValue(CodeGenFunction &CGF)
override;
217 StringRef getHelperName()
const override {
return ".omp_outlined."; }
219 void emitUntiedSwitch(CodeGenFunction &CGF)
override {
220 Action.emitUntiedSwitch(CGF);
223 static bool classof(
const CGCapturedStmtInfo *Info) {
224 return CGOpenMPRegionInfo::classof(Info) &&
232 const VarDecl *ThreadIDVar;
234 const UntiedTaskActionTy &Action;
239class CGOpenMPInlinedRegionInfo :
public CGOpenMPRegionInfo {
241 CGOpenMPInlinedRegionInfo(CodeGenFunction::CGCapturedStmtInfo *OldCSI,
242 const RegionCodeGenTy &CodeGen,
244 : CGOpenMPRegionInfo(InlinedRegion, CodeGen,
Kind, HasCancel),
246 OuterRegionInfo(dyn_cast_or_null<CGOpenMPRegionInfo>(OldCSI)) {}
249 llvm::Value *getContextValue()
const override {
251 return OuterRegionInfo->getContextValue();
252 llvm_unreachable(
"No context value for inlined OpenMP region");
255 void setContextValue(llvm::Value *
V)
override {
256 if (OuterRegionInfo) {
257 OuterRegionInfo->setContextValue(
V);
260 llvm_unreachable(
"No context value for inlined OpenMP region");
264 const FieldDecl *lookup(
const VarDecl *VD)
const override {
266 return OuterRegionInfo->lookup(VD);
272 FieldDecl *getThisFieldDecl()
const override {
274 return OuterRegionInfo->getThisFieldDecl();
280 const VarDecl *getThreadIDVariable()
const override {
282 return OuterRegionInfo->getThreadIDVariable();
287 LValue getThreadIDVariableLValue(CodeGenFunction &CGF)
override {
289 return OuterRegionInfo->getThreadIDVariableLValue(CGF);
290 llvm_unreachable(
"No LValue for inlined OpenMP construct");
294 StringRef getHelperName()
const override {
295 if (
auto *OuterRegionInfo = getOldCSI())
296 return OuterRegionInfo->getHelperName();
297 llvm_unreachable(
"No helper name for inlined OpenMP construct");
300 void emitUntiedSwitch(CodeGenFunction &CGF)
override {
302 OuterRegionInfo->emitUntiedSwitch(CGF);
305 CodeGenFunction::CGCapturedStmtInfo *getOldCSI()
const {
return OldCSI; }
307 static bool classof(
const CGCapturedStmtInfo *Info) {
308 return CGOpenMPRegionInfo::classof(Info) &&
312 ~CGOpenMPInlinedRegionInfo()
override =
default;
316 CodeGenFunction::CGCapturedStmtInfo *OldCSI;
317 CGOpenMPRegionInfo *OuterRegionInfo;
325class CGOpenMPTargetRegionInfo final :
public CGOpenMPRegionInfo {
327 CGOpenMPTargetRegionInfo(
const CapturedStmt &CS,
328 const RegionCodeGenTy &CodeGen, StringRef HelperName)
329 : CGOpenMPRegionInfo(CS, TargetRegion, CodeGen, OMPD_target,
331 HelperName(HelperName) {}
335 const VarDecl *getThreadIDVariable()
const override {
return nullptr; }
338 StringRef getHelperName()
const override {
return HelperName; }
340 static bool classof(
const CGCapturedStmtInfo *Info) {
341 return CGOpenMPRegionInfo::classof(Info) &&
346 StringRef HelperName;
350 llvm_unreachable(
"No codegen for expressions");
354class CGOpenMPInnerExprInfo final :
public CGOpenMPInlinedRegionInfo {
356 CGOpenMPInnerExprInfo(CodeGenFunction &CGF,
const CapturedStmt &CS)
357 : CGOpenMPInlinedRegionInfo(CGF.CapturedStmtInfo, EmptyCodeGen,
365 if (!C.capturesVariable() && !C.capturesVariableByCopy())
368 const VarDecl *VD = C.getCapturedVar();
369 if (VD->isLocalVarDeclOrParm())
372 DeclRefExpr DRE(CGF.getContext(), const_cast<VarDecl *>(VD),
374 VD->getType().getNonReferenceType(), VK_LValue,
376 PrivScope.addPrivate(VD, CGF.EmitLValue(&DRE).getAddress());
378 (
void)PrivScope.Privatize();
382 const FieldDecl *lookup(
const VarDecl *VD)
const override {
383 if (
const FieldDecl *FD = CGOpenMPInlinedRegionInfo::lookup(VD))
389 void EmitBody(CodeGenFunction &CGF,
const Stmt *S)
override {
390 llvm_unreachable(
"No body for expressions");
395 const VarDecl *getThreadIDVariable()
const override {
396 llvm_unreachable(
"No thread id for expressions");
400 StringRef getHelperName()
const override {
401 llvm_unreachable(
"No helper name for expressions");
404 static bool classof(
const CGCapturedStmtInfo *Info) {
return false; }
408 CodeGenFunction::OMPPrivateScope PrivScope;
412class InlinedOpenMPRegionRAII {
413 CodeGenFunction &CGF;
414 llvm::DenseMap<const ValueDecl *, FieldDecl *> LambdaCaptureFields;
415 FieldDecl *LambdaThisCaptureField =
nullptr;
416 const CodeGen::CGBlockInfo *BlockInfo =
nullptr;
417 bool NoInheritance =
false;
424 InlinedOpenMPRegionRAII(CodeGenFunction &CGF,
const RegionCodeGenTy &CodeGen,
426 bool NoInheritance =
true)
427 : CGF(CGF), NoInheritance(NoInheritance) {
429 CGF.CapturedStmtInfo =
new CGOpenMPInlinedRegionInfo(
430 CGF.CapturedStmtInfo, CodeGen, Kind, HasCancel);
432 std::swap(CGF.LambdaCaptureFields, LambdaCaptureFields);
433 LambdaThisCaptureField = CGF.LambdaThisCaptureField;
434 CGF.LambdaThisCaptureField =
nullptr;
435 BlockInfo = CGF.BlockInfo;
436 CGF.BlockInfo =
nullptr;
440 ~InlinedOpenMPRegionRAII() {
444 delete CGF.CapturedStmtInfo;
445 CGF.CapturedStmtInfo = OldCSI;
447 std::swap(CGF.LambdaCaptureFields, LambdaCaptureFields);
448 CGF.LambdaThisCaptureField = LambdaThisCaptureField;
449 CGF.BlockInfo = BlockInfo;
457enum OpenMPLocationFlags :
unsigned {
459 OMP_IDENT_IMD = 0x01,
461 OMP_IDENT_KMPC = 0x02,
463 OMP_ATOMIC_REDUCE = 0x10,
465 OMP_IDENT_BARRIER_EXPL = 0x20,
467 OMP_IDENT_BARRIER_IMPL = 0x40,
469 OMP_IDENT_BARRIER_IMPL_FOR = 0x40,
471 OMP_IDENT_BARRIER_IMPL_SECTIONS = 0xC0,
473 OMP_IDENT_BARRIER_IMPL_SINGLE = 0x140,
475 OMP_IDENT_WORK_LOOP = 0x200,
477 OMP_IDENT_WORK_SECTIONS = 0x400,
479 OMP_IDENT_WORK_DISTRIBUTE = 0x800,
509enum IdentFieldIndex {
511 IdentField_Reserved_1,
515 IdentField_Reserved_2,
517 IdentField_Reserved_3,
526enum OpenMPSchedType {
529 OMP_sch_static_chunked = 33,
531 OMP_sch_dynamic_chunked = 35,
532 OMP_sch_guided_chunked = 36,
533 OMP_sch_runtime = 37,
536 OMP_sch_static_balanced_chunked = 45,
539 OMP_ord_static_chunked = 65,
541 OMP_ord_dynamic_chunked = 67,
542 OMP_ord_guided_chunked = 68,
543 OMP_ord_runtime = 69,
545 OMP_sch_default = OMP_sch_static,
547 OMP_dist_sch_static_chunked = 91,
548 OMP_dist_sch_static = 92,
551 OMP_sch_modifier_monotonic = (1 << 29),
553 OMP_sch_modifier_nonmonotonic = (1 << 30),
558class CleanupTy final :
public EHScopeStack::Cleanup {
559 PrePostActionTy *Action;
562 explicit CleanupTy(PrePostActionTy *Action) : Action(Action) {}
563 void Emit(CodeGenFunction &CGF, Flags )
override {
576 Callback(CodeGen, CGF, *PrePostAction);
579 Callback(CodeGen, CGF, Action);
587 if (
const auto *CE = dyn_cast<CallExpr>(ReductionOp))
588 if (
const auto *OVE = dyn_cast<OpaqueValueExpr>(CE->getCallee()))
589 if (
const auto *DRE =
590 dyn_cast<DeclRefExpr>(OVE->getSourceExpr()->IgnoreImpCasts()))
591 if (
const auto *DRD = dyn_cast<OMPDeclareReductionDecl>(DRE->getDecl()))
602 std::pair<llvm::Function *, llvm::Function *>
Reduction =
622 auto *GV =
new llvm::GlobalVariable(
624 llvm::GlobalValue::PrivateLinkage,
Init, Name);
665 llvm::Value *NumElements = CGF.
emitArrayLength(ArrayTy, ElementTy, DestAddr);
669 llvm::Value *SrcBegin =
nullptr;
671 SrcBegin = SrcAddr.emitRawPointer(CGF);
674 llvm::Value *DestEnd =
679 llvm::Value *IsEmpty =
680 CGF.
Builder.CreateICmpEQ(DestBegin, DestEnd,
"omp.arrayinit.isempty");
681 CGF.
Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
684 llvm::BasicBlock *EntryBB = CGF.
Builder.GetInsertBlock();
689 llvm::PHINode *SrcElementPHI =
nullptr;
692 SrcElementPHI = CGF.
Builder.CreatePHI(SrcBegin->getType(), 2,
693 "omp.arraycpy.srcElementPast");
694 SrcElementPHI->addIncoming(SrcBegin, EntryBB);
696 Address(SrcElementPHI, SrcAddr.getElementType(),
697 SrcAddr.getAlignment().alignmentOfArrayElement(ElementSize));
699 llvm::PHINode *DestElementPHI = CGF.
Builder.CreatePHI(
700 DestBegin->getType(), 2,
"omp.arraycpy.destElementPast");
701 DestElementPHI->addIncoming(DestBegin, EntryBB);
709 if (EmitDeclareReductionInit) {
711 SrcElementCurrent, ElementTy);
719 llvm::Value *SrcElementNext = CGF.
Builder.CreateConstGEP1_32(
720 SrcAddr.getElementType(), SrcElementPHI, 1,
721 "omp.arraycpy.dest.element");
722 SrcElementPHI->addIncoming(SrcElementNext, CGF.
Builder.GetInsertBlock());
726 llvm::Value *DestElementNext = CGF.
Builder.CreateConstGEP1_32(
728 "omp.arraycpy.dest.element");
731 CGF.
Builder.CreateICmpEQ(DestElementNext, DestEnd,
"omp.arraycpy.done");
732 CGF.
Builder.CreateCondBr(Done, DoneBB, BodyBB);
733 DestElementPHI->addIncoming(DestElementNext, CGF.
Builder.GetInsertBlock());
745 if (
const auto *OASE = dyn_cast<ArraySectionExpr>(E))
750void ReductionCodeGen::emitAggregateInitialization(
752 const OMPDeclareReductionDecl *DRD) {
756 const auto *PrivateVD =
758 bool EmitDeclareReductionInit =
761 EmitDeclareReductionInit,
762 EmitDeclareReductionInit ? ClausesData[N].ReductionOp
763 : PrivateVD->getInit(),
771 ClausesData.reserve(Shareds.size());
772 SharedAddresses.reserve(Shareds.size());
773 Sizes.reserve(Shareds.size());
774 BaseDecls.reserve(Shareds.size());
775 const auto *IOrig = Origs.begin();
776 const auto *IPriv =
Privates.begin();
777 const auto *IRed = ReductionOps.begin();
778 for (
const Expr *Ref : Shareds) {
779 ClausesData.emplace_back(Ref, *IOrig, *IPriv, *IRed);
780 std::advance(IOrig, 1);
781 std::advance(IPriv, 1);
782 std::advance(IRed, 1);
787 assert(SharedAddresses.size() == N && OrigAddresses.size() == N &&
788 "Number of generated lvalues must be exactly N.");
789 LValue First = emitSharedLValue(CGF, ClausesData[N].Shared);
790 LValue Second = emitSharedLValueUB(CGF, ClausesData[N].Shared);
791 SharedAddresses.emplace_back(
First, Second);
792 if (ClausesData[N].Shared == ClausesData[N].Ref) {
793 OrigAddresses.emplace_back(
First, Second);
795 LValue First = emitSharedLValue(CGF, ClausesData[N].Ref);
796 LValue Second = emitSharedLValueUB(CGF, ClausesData[N].Ref);
797 OrigAddresses.emplace_back(
First, Second);
806 CGF.
getTypeSize(OrigAddresses[N].first.getType().getNonReferenceType()),
811 llvm::Value *SizeInChars;
812 auto *ElemType = OrigAddresses[N].first.getAddress().getElementType();
813 auto *ElemSizeOf = llvm::ConstantExpr::getSizeOf(ElemType);
814 if (AsArraySection) {
815 Size = CGF.
Builder.CreatePtrDiff(ElemType,
816 OrigAddresses[N].second.getPointer(CGF),
817 OrigAddresses[N].first.getPointer(CGF));
818 Size = CGF.
Builder.CreateZExtOrTrunc(Size, ElemSizeOf->getType());
819 Size = CGF.
Builder.CreateNUWAdd(
820 Size, llvm::ConstantInt::get(Size->getType(), 1));
821 SizeInChars = CGF.
Builder.CreateNUWMul(Size, ElemSizeOf);
824 CGF.
getTypeSize(OrigAddresses[N].first.getType().getNonReferenceType());
825 Size = CGF.
Builder.CreateExactUDiv(SizeInChars, ElemSizeOf);
827 Sizes.emplace_back(SizeInChars, Size);
840 assert(!Size && !Sizes[N].second &&
841 "Size should be nullptr for non-variably modified reduction "
856 assert(SharedAddresses.size() > N &&
"No variable was generated");
857 const auto *PrivateVD =
863 (void)DefaultInit(CGF);
864 emitAggregateInitialization(CGF, N, PrivateAddr, SharedAddr, DRD);
865 }
else if (DRD && (DRD->
getInitializer() || !PrivateVD->hasInit())) {
866 (void)DefaultInit(CGF);
867 QualType SharedType = SharedAddresses[N].first.getType();
869 PrivateAddr, SharedAddr, SharedType);
870 }
else if (!DefaultInit(CGF) && PrivateVD->hasInit() &&
873 PrivateVD->
getType().getQualifiers(),
891 CGF.
pushDestroy(DTorKind, PrivateAddr, PrivateType);
910 BaseLV.getType(), BaseLV.getBaseInfo(),
944 const VarDecl *OrigVD =
nullptr;
945 if (
const auto *OASE = dyn_cast<ArraySectionExpr>(Ref)) {
946 const Expr *
Base = OASE->getBase()->IgnoreParenImpCasts();
947 while (
const auto *TempOASE = dyn_cast<ArraySectionExpr>(
Base))
948 Base = TempOASE->getBase()->IgnoreParenImpCasts();
949 while (
const auto *TempASE = dyn_cast<ArraySubscriptExpr>(
Base))
950 Base = TempASE->getBase()->IgnoreParenImpCasts();
953 }
else if (
const auto *ASE = dyn_cast<ArraySubscriptExpr>(Ref)) {
954 const Expr *
Base = ASE->getBase()->IgnoreParenImpCasts();
955 while (
const auto *TempASE = dyn_cast<ArraySubscriptExpr>(
Base))
956 Base = TempASE->getBase()->IgnoreParenImpCasts();
967 BaseDecls.emplace_back(OrigVD);
970 loadToBegin(CGF, OrigVD->getType(), SharedAddresses[N].first.getType(),
972 Address SharedAddr = SharedAddresses[N].first.getAddress();
973 llvm::Value *Adjustment = CGF.
Builder.CreatePtrDiff(
976 llvm::Value *PrivatePointer =
982 SharedAddresses[N].first.getType(),
985 BaseDecls.emplace_back(
999 getThreadIDVariable()->
getType()->castAs<PointerType>());
1017LValue CGOpenMPTaskOutlinedRegionInfo::getThreadIDVariableLValue(
1020 getThreadIDVariable()->
getType(),
1038 llvm::OpenMPIRBuilderConfig Config(
1039 CGM.getLangOpts().OpenMPIsTargetDevice,
isGPU(),
1040 CGM.getLangOpts().OpenMPOffloadMandatory,
1043 Config.setDefaultTargetAS(
1045 Config.setRuntimeCC(
CGM.getRuntimeCC());
1050 CGM.getLangOpts().OpenMPIsTargetDevice
1051 ?
CGM.getLangOpts().OMPHostIRFile
1056 if (
CGM.getLangOpts().OpenMPForceUSM) {
1058 OMPBuilder.Config.setHasRequiresUnifiedSharedMemory(
true);
1066 if (!
Data.getValue().pointsToAliveValue())
1068 auto *GV = dyn_cast<llvm::GlobalVariable>(
Data.getValue());
1071 if (!GV->isDeclaration() || GV->getNumUses() > 0)
1073 GV->eraseFromParent();
1078 return OMPBuilder.createPlatformSpecificName(Parts);
1081static llvm::Function *
1083 const Expr *CombinerInitializer,
const VarDecl *In,
1084 const VarDecl *Out,
bool IsCombiner) {
1087 QualType PtrTy =
C.getPointerType(Ty).withRestrict();
1093 Args.push_back(&OmpOutParm);
1094 Args.push_back(&OmpInParm);
1099 {IsCombiner ?
"omp_combiner" :
"omp_initializer",
""});
1100 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
1104 Fn->addFnAttr(
"sample-profile-suffix-elision-policy",
"selected");
1106 Fn->removeFnAttr(llvm::Attribute::NoInline);
1107 Fn->removeFnAttr(llvm::Attribute::OptimizeNone);
1108 Fn->addFnAttr(llvm::Attribute::AlwaysInline);
1114 Out->getLocation());
1124 (void)
Scope.Privatize();
1125 if (!IsCombiner && Out->hasInit() &&
1128 Out->getType().getQualifiers(),
1131 if (CombinerInitializer)
1133 Scope.ForceCleanup();
1162std::pair<llvm::Function *, llvm::Function *>
1174struct PushAndPopStackRAII {
1175 PushAndPopStackRAII(llvm::OpenMPIRBuilder *OMPBuilder,
CodeGenFunction &CGF,
1176 bool HasCancel, llvm::omp::Directive Kind)
1177 : OMPBuilder(OMPBuilder) {
1193 auto FiniCB = [&CGF](llvm::OpenMPIRBuilder::InsertPointTy IP) {
1194 assert(IP.getBlock()->end() == IP.getPoint() &&
1195 "Clang CG should cause non-terminated block!");
1196 CGBuilderTy::InsertPointGuard IPG(CGF.
Builder);
1201 return llvm::Error::success();
1206 llvm::OpenMPIRBuilder::FinalizationInfo FI({FiniCB, Kind, HasCancel});
1207 OMPBuilder->pushFinalizationCB(std::move(FI));
1209 ~PushAndPopStackRAII() {
1211 OMPBuilder->popFinalizationCB();
1213 llvm::OpenMPIRBuilder *OMPBuilder;
1222 "thread id variable must be of type kmp_int32 *");
1224 bool HasCancel =
false;
1225 if (
const auto *OPD = dyn_cast<OMPParallelDirective>(&D))
1226 HasCancel = OPD->hasCancel();
1227 else if (
const auto *OPD = dyn_cast<OMPTargetParallelDirective>(&D))
1228 HasCancel = OPD->hasCancel();
1229 else if (
const auto *OPSD = dyn_cast<OMPParallelSectionsDirective>(&D))
1230 HasCancel = OPSD->hasCancel();
1231 else if (
const auto *OPFD = dyn_cast<OMPParallelForDirective>(&D))
1232 HasCancel = OPFD->hasCancel();
1233 else if (
const auto *OPFD = dyn_cast<OMPTargetParallelForDirective>(&D))
1234 HasCancel = OPFD->hasCancel();
1235 else if (
const auto *OPFD = dyn_cast<OMPDistributeParallelForDirective>(&D))
1236 HasCancel = OPFD->hasCancel();
1237 else if (
const auto *OPFD =
1238 dyn_cast<OMPTeamsDistributeParallelForDirective>(&D))
1239 HasCancel = OPFD->hasCancel();
1240 else if (
const auto *OPFD =
1241 dyn_cast<OMPTargetTeamsDistributeParallelForDirective>(&D))
1242 HasCancel = OPFD->hasCancel();
1247 PushAndPopStackRAII PSR(&OMPBuilder, CGF, HasCancel, InnermostKind);
1248 CGOpenMPOutlinedRegionInfo CGInfo(*CS, ThreadIDVar,
CodeGen, InnermostKind,
1249 HasCancel, OutlinedHelperName);
1255 std::string Suffix =
getName({
"omp_outlined"});
1256 return (Name + Suffix).str();
1264 std::string Suffix =
getName({
"omp",
"reduction",
"reduction_func"});
1265 return (Name + Suffix).str();
1272 const CapturedStmt *CS = D.getCapturedStmt(OMPD_parallel);
1282 const CapturedStmt *CS = D.getCapturedStmt(OMPD_teams);
1292 bool Tied,
unsigned &NumberOfParts) {
1295 llvm::Value *ThreadID =
getThreadID(CGF, D.getBeginLoc());
1297 llvm::Value *TaskArgs[] = {
1299 CGF.EmitLoadOfPointerLValue(CGF.GetAddrOfLocalVar(TaskTVar),
1302 CGF.EmitRuntimeCall(
OMPBuilder.getOrCreateRuntimeFunction(
1303 CGM.getModule(), OMPRTL___kmpc_omp_task),
1306 CGOpenMPTaskOutlinedRegionInfo::UntiedTaskActionTy Action(Tied, PartIDVar,
1310 "thread id variable must be of type kmp_int32 for tasks");
1315 bool HasCancel =
false;
1316 if (
const auto *TD = dyn_cast<OMPTaskDirective>(&D))
1317 HasCancel = TD->hasCancel();
1318 else if (
const auto *TD = dyn_cast<OMPTaskLoopDirective>(&D))
1319 HasCancel = TD->hasCancel();
1320 else if (
const auto *TD = dyn_cast<OMPMasterTaskLoopDirective>(&D))
1321 HasCancel = TD->hasCancel();
1322 else if (
const auto *TD = dyn_cast<OMPParallelMasterTaskLoopDirective>(&D))
1323 HasCancel = TD->hasCancel();
1326 CGOpenMPTaskOutlinedRegionInfo CGInfo(*CS, ThreadIDVar,
CodeGen,
1327 InnermostKind, HasCancel, Action);
1329 llvm::Function *Res = CGF.GenerateCapturedStmtFunction(*CS);
1331 NumberOfParts = Action.getNumberOfParts();
1336 bool AtCurrentPoint) {
1338 assert(!Elem.ServiceInsertPt &&
"Insert point is set already.");
1340 llvm::Value *Undef = llvm::UndefValue::get(CGF.
Int32Ty);
1341 if (AtCurrentPoint) {
1342 Elem.ServiceInsertPt =
new llvm::BitCastInst(Undef, CGF.
Int32Ty,
"svcpt",
1343 CGF.
Builder.GetInsertBlock());
1345 Elem.ServiceInsertPt =
new llvm::BitCastInst(Undef, CGF.
Int32Ty,
"svcpt");
1346 Elem.ServiceInsertPt->insertAfter(CGF.
AllocaInsertPt->getIterator());
1352 if (Elem.ServiceInsertPt) {
1353 llvm::Instruction *Ptr = Elem.ServiceInsertPt;
1354 Elem.ServiceInsertPt =
nullptr;
1355 Ptr->eraseFromParent();
1362 llvm::raw_svector_ostream OS(Buffer);
1371 if (
const auto *FD = dyn_cast_or_null<FunctionDecl>(CGF.
CurFuncDecl))
1372 OS << FD->getQualifiedNameAsString();
1379 unsigned Flags,
bool EmitLoc) {
1380 uint32_t SrcLocStrSize;
1381 llvm::Constant *SrcLocStr;
1382 if ((!EmitLoc &&
CGM.getCodeGenOpts().getDebugInfo() ==
1383 llvm::codegenoptions::NoDebugInfo) ||
1385 SrcLocStr =
OMPBuilder.getOrCreateDefaultSrcLocStr(SrcLocStrSize);
1387 std::string FunctionName;
1389 if (
const auto *FD = dyn_cast_or_null<FunctionDecl>(CGF.
CurFuncDecl))
1390 FunctionName = FD->getQualifiedNameAsString();
1403 SrcLocStr, SrcLocStrSize, llvm::omp::IdentFlag(Flags), Reserved2Flags);
1408 assert(CGF.
CurFn &&
"No function in current CodeGenFunction.");
1411 if (
CGM.getLangOpts().OpenMPIRBuilder) {
1414 uint32_t SrcLocStrSize;
1415 auto *SrcLocStr =
OMPBuilder.getOrCreateSrcLocStr(
1418 OMPBuilder.getOrCreateIdent(SrcLocStr, SrcLocStrSize));
1421 llvm::Value *ThreadID =
nullptr;
1426 ThreadID = I->second.ThreadID;
1427 if (ThreadID !=
nullptr)
1431 if (
auto *OMPRegionInfo =
1433 if (OMPRegionInfo->getThreadIDVariable()) {
1435 LValue LVal = OMPRegionInfo->getThreadIDVariableLValue(CGF);
1439 CGF.
Builder.GetInsertBlock() == TopBlock ||
1444 CGF.
Builder.GetInsertBlock()) {
1448 if (CGF.
Builder.GetInsertBlock() == TopBlock)
1460 if (!Elem.ServiceInsertPt)
1462 CGBuilderTy::InsertPointGuard IPG(CGF.
Builder);
1463 CGF.
Builder.SetInsertPoint(Elem.ServiceInsertPt);
1467 OMPRTL___kmpc_global_thread_num),
1470 Elem.ThreadID =
Call;
1475 assert(CGF.
CurFn &&
"No function in current CodeGenFunction.");
1481 for (
const auto *D : I->second)
1486 for (
const auto *D : I->second)
1498static llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseKind
1500 std::optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
1501 OMPDeclareTargetDeclAttr::getDeviceType(VD);
1503 return llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseNone;
1505 switch ((
int)*DevTy) {
1506 case OMPDeclareTargetDeclAttr::DT_Host:
1507 return llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseHost;
1509 case OMPDeclareTargetDeclAttr::DT_NoHost:
1510 return llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseNoHost;
1512 case OMPDeclareTargetDeclAttr::DT_Any:
1513 return llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseAny;
1516 return llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseNone;
1521static llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryKind
1523 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> MapType =
1524 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
1526 return llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryNone;
1527 switch ((
int)*MapType) {
1528 case OMPDeclareTargetDeclAttr::MapTypeTy::MT_To:
1529 return llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryTo;
1531 case OMPDeclareTargetDeclAttr::MapTypeTy::MT_Enter:
1532 case OMPDeclareTargetDeclAttr::MapTypeTy::MT_Local:
1533 return llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryEnter;
1535 case OMPDeclareTargetDeclAttr::MapTypeTy::MT_Link:
1536 return llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryLink;
1539 return llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryNone;
1548 auto FileInfoCallBack = [&]() {
1553 PLoc =
SM.getPresumedLoc(BeginLoc,
false);
1558 return OMPBuilder.getTargetEntryUniqueInfo(FileInfoCallBack,
1563 auto AddrOfGlobal = [&VD,
this]() {
return CGM.GetAddrOfGlobal(VD); };
1565 auto LinkageForVariable = [&VD,
this]() {
1566 return CGM.getLLVMLinkageVarDefinition(VD);
1569 std::vector<llvm::GlobalVariable *> GeneratedRefs;
1571 llvm::Type *LlvmPtrTy =
CGM.getTypes().ConvertTypeForMem(
1572 CGM.getContext().getPointerType(VD->
getType()));
1573 llvm::Constant *addr =
OMPBuilder.getAddrOfDeclareTargetVar(
1579 CGM.getMangledName(VD), GeneratedRefs,
CGM.getLangOpts().OpenMPSimd,
1580 CGM.getLangOpts().OMPTargetTriples, LlvmPtrTy, AddrOfGlobal,
1581 LinkageForVariable);
1590 assert(!
CGM.getLangOpts().OpenMPUseTLS ||
1591 !
CGM.getContext().getTargetInfo().isTLSSupported());
1593 std::string Suffix =
getName({
"cache",
""});
1594 return OMPBuilder.getOrCreateInternalVariable(
1595 CGM.Int8PtrPtrTy, Twine(
CGM.getMangledName(VD)).concat(Suffix).str());
1602 if (
CGM.getLangOpts().OpenMPUseTLS &&
1603 CGM.getContext().getTargetInfo().isTLSSupported())
1607 llvm::Value *Args[] = {
1610 CGM.getSize(
CGM.GetTargetTypeStoreSize(VarTy)),
1615 CGM.getModule(), OMPRTL___kmpc_threadprivate_cached),
1627 CGM.getModule(), OMPRTL___kmpc_global_thread_num),
1631 llvm::Value *Args[] = {
1634 Ctor, CopyCtor, Dtor};
1637 CGM.getModule(), OMPRTL___kmpc_threadprivate_register),
1644 if (
CGM.getLangOpts().OpenMPUseTLS &&
1645 CGM.getContext().getTargetInfo().isTLSSupported())
1652 llvm::Value *Ctor =
nullptr, *CopyCtor =
nullptr, *Dtor =
nullptr;
1654 if (
CGM.getLangOpts().CPlusPlus && PerformInit) {
1660 nullptr,
CGM.getContext().VoidPtrTy,
1662 Args.push_back(&Dst);
1664 const auto &FI =
CGM.getTypes().arrangeBuiltinFunctionDeclaration(
1665 CGM.getContext().VoidPtrTy, Args);
1666 llvm::FunctionType *FTy =
CGM.getTypes().GetFunctionType(FI);
1667 std::string Name =
getName({
"__kmpc_global_ctor_",
""});
1668 llvm::Function *Fn =
1669 CGM.CreateGlobalInitOrCleanUpFunction(FTy, Name, FI, Loc);
1692 nullptr,
CGM.getContext().VoidPtrTy,
1694 Args.push_back(&Dst);
1696 const auto &FI =
CGM.getTypes().arrangeBuiltinFunctionDeclaration(
1697 CGM.getContext().VoidTy, Args);
1698 llvm::FunctionType *FTy =
CGM.getTypes().GetFunctionType(FI);
1699 std::string Name =
getName({
"__kmpc_global_dtor_",
""});
1700 llvm::Function *Fn =
1701 CGM.CreateGlobalInitOrCleanUpFunction(FTy, Name, FI, Loc);
1724 CopyCtor = llvm::Constant::getNullValue(
CGM.DefaultPtrTy);
1725 if (Ctor ==
nullptr) {
1726 Ctor = llvm::Constant::getNullValue(
CGM.DefaultPtrTy);
1728 if (Dtor ==
nullptr) {
1729 Dtor = llvm::Constant::getNullValue(
CGM.DefaultPtrTy);
1732 auto *InitFunctionTy =
1733 llvm::FunctionType::get(
CGM.VoidTy,
false);
1734 std::string Name =
getName({
"__omp_threadprivate_init_",
""});
1735 llvm::Function *InitFunction =
CGM.CreateGlobalInitOrCleanUpFunction(
1736 InitFunctionTy, Name,
CGM.getTypes().arrangeNullaryFunction());
1740 CGM.getTypes().arrangeNullaryFunction(), ArgList,
1744 return InitFunction;
1752 llvm::GlobalValue *GV) {
1753 std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr =
1754 OMPDeclareTargetDeclAttr::getActiveAttr(FD);
1757 if (!ActiveAttr || !(*ActiveAttr)->getIndirect())
1764 OMPBuilder.OffloadInfoManager.getTargetRegionEntryFnName(Name, EntryInfo);
1770 llvm::GlobalValue *
Addr = GV;
1771 if (
CGM.getLangOpts().OpenMPIsTargetDevice) {
1772 llvm::PointerType *FnPtrTy = llvm::PointerType::get(
1773 CGM.getLLVMContext(),
1774 CGM.getModule().getDataLayout().getProgramAddressSpace());
1775 Addr =
new llvm::GlobalVariable(
1776 CGM.getModule(), FnPtrTy,
1777 true, llvm::GlobalValue::ExternalLinkage, GV, Name,
1778 nullptr, llvm::GlobalValue::NotThreadLocal,
1779 CGM.getModule().getDataLayout().getDefaultGlobalsAddressSpace());
1780 Addr->setVisibility(llvm::GlobalValue::ProtectedVisibility);
1787 OMPBuilder.OffloadInfoManager.registerDeviceGlobalVarEntryInfo(
1788 Name,
Addr,
CGM.GetTargetTypeStoreSize(
CGM.VoidPtrTy).getQuantity(),
1789 llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryIndirect,
1790 llvm::GlobalValue::WeakODRLinkage);
1803 llvm::OpenMPIRBuilder &
OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
1819 llvm::GlobalVariable *
Addr = VTable;
1821 OMPBuilder.OffloadInfoManager.getTargetRegionEntryFnName(AddrName, EntryInfo);
1822 AddrName.append(
"addr");
1824 if (
CGM.getLangOpts().OpenMPIsTargetDevice) {
1825 Addr =
new llvm::GlobalVariable(
1826 CGM.getModule(), VTable->getType(),
1827 true, llvm::GlobalValue::ExternalLinkage, VTable,
1829 nullptr, llvm::GlobalValue::NotThreadLocal,
1830 CGM.getModule().getDataLayout().getDefaultGlobalsAddressSpace());
1831 Addr->setVisibility(llvm::GlobalValue::ProtectedVisibility);
1833 OMPBuilder.OffloadInfoManager.registerDeviceGlobalVarEntryInfo(
1835 CGM.getDataLayout().getTypeAllocSize(VTable->getInitializer()->getType()),
1836 llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryIndirectVTable,
1837 llvm::GlobalValue::WeakODRLinkage);
1846 !
CGM.getOpenMPRuntime().VTableDeclMap.contains(
CXXRecord)) {
1847 auto Res =
CGM.getOpenMPRuntime().VTableDeclMap.try_emplace(
CXXRecord, VD);
1852 assert(VTablesAddr &&
"Expected non-null VTable address");
1853 CGM.getOpenMPRuntime().registerVTableOffloadEntry(VTablesAddr, VD);
1871 auto GetVTableDecl = [](
const Expr *E) {
1882 if (
auto *DRE = dyn_cast<DeclRefExpr>(E)) {
1884 }
else if (
auto *MRE = dyn_cast<MemberExpr>(E)) {
1885 if (
auto *BaseDRE = dyn_cast<DeclRefExpr>(MRE->getBase())) {
1886 if (
auto *BaseVD = dyn_cast<VarDecl>(BaseDRE->getDecl()))
1890 return std::pair<CXXRecordDecl *, const VarDecl *>(
CXXRecord, VD);
1894 for (
const auto *E :
C->varlist()) {
1895 auto DeclPair = GetVTableDecl(E);
1897 if (DeclPair.second)
1906 std::string Suffix =
getName({
"artificial",
""});
1908 llvm::GlobalVariable *GAddr =
OMPBuilder.getOrCreateInternalVariable(
1909 VarLVType, Twine(Name).concat(Suffix).str());
1910 if (
CGM.getLangOpts().OpenMP &&
CGM.getLangOpts().OpenMPUseTLS &&
1911 CGM.getTarget().isTLSSupported()) {
1912 GAddr->setThreadLocal(
true);
1913 return Address(GAddr, GAddr->getValueType(),
1914 CGM.getContext().getTypeAlignInChars(VarType));
1916 std::string CacheSuffix =
getName({
"cache",
""});
1917 llvm::Value *Args[] = {
1925 Twine(Name).concat(Suffix).concat(CacheSuffix).str())};
1930 CGM.getModule(), OMPRTL___kmpc_threadprivate_cached),
1933 VarLVType,
CGM.getContext().getTypeAlignInChars(VarType));
1983 auto &M =
CGM.getModule();
1984 auto &&ThenGen = [&M, OutlinedFn, CapturedVars, RTLoc,
1987 llvm::Value *Args[] = {
1989 CGF.
Builder.getInt32(CapturedVars.size()),
1992 RealArgs.append(std::begin(Args), std::end(Args));
1993 RealArgs.append(CapturedVars.begin(), CapturedVars.end());
1995 llvm::FunctionCallee RTLFn =
1996 OMPBuilder.getOrCreateRuntimeFunction(M, OMPRTL___kmpc_fork_call);
1999 auto &&ElseGen = [&M, OutlinedFn, CapturedVars, RTLoc, Loc,
2005 llvm::Value *Args[] = {RTLoc, ThreadID};
2007 M, OMPRTL___kmpc_serialized_parallel),
2014 ".bound.zero.addr");
2019 OutlinedFnArgs.push_back(ZeroAddrBound.
getPointer());
2020 OutlinedFnArgs.append(CapturedVars.begin(), CapturedVars.end());
2028 OutlinedFn->removeFnAttr(llvm::Attribute::AlwaysInline);
2029 OutlinedFn->addFnAttr(llvm::Attribute::NoInline);
2035 M, OMPRTL___kmpc_end_serialized_parallel),
2054 if (
auto *OMPRegionInfo =
2056 if (OMPRegionInfo->getThreadIDVariable())
2057 return OMPRegionInfo->getThreadIDVariableLValue(CGF).getAddress();
2066 return ThreadIDTemp;
2070 std::string Prefix = Twine(
"gomp_critical_user_", CriticalName).str();
2071 std::string Name =
getName({Prefix,
"var"});
2078 llvm::FunctionCallee EnterCallee;
2080 llvm::FunctionCallee ExitCallee;
2083 llvm::BasicBlock *ContBlock =
nullptr;
2086 CommonActionTy(llvm::FunctionCallee EnterCallee,
2088 llvm::FunctionCallee ExitCallee,
2090 : EnterCallee(EnterCallee), EnterArgs(EnterArgs), ExitCallee(ExitCallee),
2095 llvm::Value *CallBool = CGF.
Builder.CreateIsNotNull(EnterRes);
2099 CGF.
Builder.CreateCondBr(CallBool, ThenBlock, ContBlock);
2103 void Done(CodeGenFunction &CGF) {
2108 void Exit(CodeGenFunction &CGF)
override {
2115 StringRef CriticalName,
2124 llvm::FunctionCallee RuntimeFcn =
OMPBuilder.getOrCreateRuntimeFunction(
2126 Hint ? OMPRTL___kmpc_critical_with_hint : OMPRTL___kmpc_critical);
2128 unsigned LockVarArgIdx = 2;
2130 RuntimeFcn.getFunctionType()
2131 ->getParamType(LockVarArgIdx)
2132 ->getPointerAddressSpace())
2134 LockVar, RuntimeFcn.getFunctionType()->getParamType(LockVarArgIdx));
2140 EnterArgs.push_back(CGF.
Builder.CreateIntCast(
2143 CommonActionTy Action(RuntimeFcn, EnterArgs,
2145 CGM.getModule(), OMPRTL___kmpc_end_critical),
2162 CommonActionTy Action(
OMPBuilder.getOrCreateRuntimeFunction(
2163 CGM.getModule(), OMPRTL___kmpc_master),
2166 CGM.getModule(), OMPRTL___kmpc_end_master),
2184 llvm::Value *FilterVal = Filter
2186 : llvm::ConstantInt::get(
CGM.Int32Ty, 0);
2191 CommonActionTy Action(
OMPBuilder.getOrCreateRuntimeFunction(
2192 CGM.getModule(), OMPRTL___kmpc_masked),
2195 CGM.getModule(), OMPRTL___kmpc_end_masked),
2211 llvm::Value *Args[] = {
2213 llvm::ConstantInt::get(
CGM.IntTy, 0,
true)};
2215 CGM.getModule(), OMPRTL___kmpc_omp_taskyield),
2219 if (
auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.
CapturedStmtInfo))
2220 Region->emitUntiedSwitch(CGF);
2233 CommonActionTy Action(
OMPBuilder.getOrCreateRuntimeFunction(
2234 CGM.getModule(), OMPRTL___kmpc_taskgroup),
2237 CGM.getModule(), OMPRTL___kmpc_end_taskgroup),
2246 unsigned Index,
const VarDecl *Var) {
2267 Args.push_back(&LHSArg);
2268 Args.push_back(&RHSArg);
2274 llvm::GlobalValue::InternalLinkage, Name,
2278 Fn->addFnAttr(
"sample-profile-suffix-elision-policy",
"selected");
2279 Fn->setDoesNotRecurse();
2296 for (
unsigned I = 0, E = AssignmentOps.size(); I < E; ++I) {
2297 const auto *DestVar =
2301 const auto *SrcVar =
2307 CGF.
EmitOMPCopy(
Type, DestAddr, SrcAddr, DestVar, SrcVar, AssignmentOps[I]);
2322 assert(CopyprivateVars.size() == SrcExprs.size() &&
2323 CopyprivateVars.size() == DstExprs.size() &&
2324 CopyprivateVars.size() == AssignmentOps.size());
2336 if (!CopyprivateVars.empty()) {
2339 C.getIntTypeForBitwidth(32, 1);
2340 DidIt = CGF.
CreateMemTemp(KmpInt32Ty,
".omp.copyprivate.did_it");
2345 CommonActionTy Action(
OMPBuilder.getOrCreateRuntimeFunction(
2346 CGM.getModule(), OMPRTL___kmpc_single),
2349 CGM.getModule(), OMPRTL___kmpc_end_single),
2362 llvm::APInt ArraySize(32, CopyprivateVars.size());
2363 QualType CopyprivateArrayTy =
C.getConstantArrayType(
2368 CGF.
CreateMemTemp(CopyprivateArrayTy,
".omp.copyprivate.cpr_list");
2369 for (
unsigned I = 0, E = CopyprivateVars.size(); I < E; ++I) {
2381 SrcExprs, DstExprs, AssignmentOps, Loc);
2382 llvm::Value *BufSize = CGF.
getTypeSize(CopyprivateArrayTy);
2386 llvm::Value *Args[] = {
2390 CL.emitRawPointer(CGF),
2395 CGM.getModule(), OMPRTL___kmpc_copyprivate),
2411 CommonActionTy Action(
OMPBuilder.getOrCreateRuntimeFunction(
2412 CGM.getModule(), OMPRTL___kmpc_ordered),
2415 CGM.getModule(), OMPRTL___kmpc_end_ordered),
2426 if (Kind == OMPD_for)
2427 Flags = OMP_IDENT_BARRIER_IMPL_FOR;
2428 else if (Kind == OMPD_sections)
2429 Flags = OMP_IDENT_BARRIER_IMPL_SECTIONS;
2430 else if (Kind == OMPD_single)
2431 Flags = OMP_IDENT_BARRIER_IMPL_SINGLE;
2432 else if (Kind == OMPD_barrier)
2433 Flags = OMP_IDENT_BARRIER_EXPL;
2435 Flags = OMP_IDENT_BARRIER_IMPL;
2445 S.getClausesOfKind<OMPOrderedClause>(),
2446 [](
const OMPOrderedClause *
C) { return C->getNumForLoops(); })) {
2447 ScheduleKind = OMPC_SCHEDULE_static;
2449 llvm::APInt ChunkSize(32, 1);
2459 bool ForceSimpleCall) {
2461 auto *OMPRegionInfo =
2464 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
2467 CGF.
Builder.restoreIP(AfterIP);
2480 if (OMPRegionInfo) {
2481 if (!ForceSimpleCall && OMPRegionInfo->hasCancel()) {
2484 OMPRTL___kmpc_cancel_barrier),
2493 CGF.
Builder.CreateCondBr(
Cmp, ExitBB, ContBB);
2505 CGM.getModule(), OMPRTL___kmpc_barrier),
2510 Expr *ME,
bool IsFatal) {
2512 : llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
2515 llvm::Value *Args[] = {
2517 llvm::ConstantInt::get(
CGM.Int32Ty, IsFatal ? 2 : 1),
2518 CGF.
Builder.CreatePointerCast(MVL,
CGM.Int8PtrTy)};
2520 CGM.getModule(), OMPRTL___kmpc_error),
2526 bool Chunked,
bool Ordered) {
2527 switch (ScheduleKind) {
2528 case OMPC_SCHEDULE_static:
2529 return Chunked ? (Ordered ? OMP_ord_static_chunked : OMP_sch_static_chunked)
2530 : (Ordered ? OMP_ord_static : OMP_sch_static);
2531 case OMPC_SCHEDULE_dynamic:
2532 return Ordered ? OMP_ord_dynamic_chunked : OMP_sch_dynamic_chunked;
2533 case OMPC_SCHEDULE_guided:
2534 return Ordered ? OMP_ord_guided_chunked : OMP_sch_guided_chunked;
2535 case OMPC_SCHEDULE_runtime:
2536 return Ordered ? OMP_ord_runtime : OMP_sch_runtime;
2537 case OMPC_SCHEDULE_auto:
2538 return Ordered ? OMP_ord_auto : OMP_sch_auto;
2540 assert(!Chunked &&
"chunk was specified but schedule kind not known");
2541 return Ordered ? OMP_ord_static : OMP_sch_static;
2543 llvm_unreachable(
"Unexpected runtime schedule");
2547static OpenMPSchedType
2550 return Chunked ? OMP_dist_sch_static_chunked : OMP_dist_sch_static;
2554 bool Chunked)
const {
2555 OpenMPSchedType Schedule =
2557 return Schedule == OMP_sch_static;
2563 return Schedule == OMP_dist_sch_static;
2567 bool Chunked)
const {
2568 OpenMPSchedType Schedule =
2570 return Schedule == OMP_sch_static_chunked;
2576 return Schedule == OMP_dist_sch_static_chunked;
2580 OpenMPSchedType Schedule =
2582 assert(Schedule != OMP_sch_static_chunked &&
"cannot be chunked here");
2583 return Schedule != OMP_sch_static;
2591 case OMPC_SCHEDULE_MODIFIER_monotonic:
2592 Modifier = OMP_sch_modifier_monotonic;
2594 case OMPC_SCHEDULE_MODIFIER_nonmonotonic:
2595 Modifier = OMP_sch_modifier_nonmonotonic;
2597 case OMPC_SCHEDULE_MODIFIER_simd:
2598 if (Schedule == OMP_sch_static_chunked)
2599 Schedule = OMP_sch_static_balanced_chunked;
2606 case OMPC_SCHEDULE_MODIFIER_monotonic:
2607 Modifier = OMP_sch_modifier_monotonic;
2609 case OMPC_SCHEDULE_MODIFIER_nonmonotonic:
2610 Modifier = OMP_sch_modifier_nonmonotonic;
2612 case OMPC_SCHEDULE_MODIFIER_simd:
2613 if (Schedule == OMP_sch_static_chunked)
2614 Schedule = OMP_sch_static_balanced_chunked;
2626 if (CGM.
getLangOpts().OpenMP >= 50 && Modifier == 0) {
2627 if (!(Schedule == OMP_sch_static_chunked || Schedule == OMP_sch_static ||
2628 Schedule == OMP_sch_static_balanced_chunked ||
2629 Schedule == OMP_ord_static_chunked || Schedule == OMP_ord_static ||
2630 Schedule == OMP_dist_sch_static_chunked ||
2631 Schedule == OMP_dist_sch_static))
2632 Modifier = OMP_sch_modifier_nonmonotonic;
2634 return Schedule | Modifier;
2644 ScheduleKind.
Schedule, DispatchValues.
Chunk !=
nullptr, Ordered);
2646 (Schedule != OMP_sch_static && Schedule != OMP_sch_static_chunked &&
2647 Schedule != OMP_ord_static && Schedule != OMP_ord_static_chunked &&
2648 Schedule != OMP_sch_static_balanced_chunked));
2655 llvm::Value *Chunk = DispatchValues.
Chunk ? DispatchValues.
Chunk
2656 : CGF.
Builder.getIntN(IVSize, 1);
2657 llvm::Value *Args[] = {
2661 CGM, Schedule, ScheduleKind.
M1, ScheduleKind.
M2)),
2664 CGF.
Builder.getIntN(IVSize, 1),
2681 CodeGenFunction &CGF, llvm::Value *UpdateLocation, llvm::Value *ThreadId,
2682 llvm::FunctionCallee ForStaticInitFunction, OpenMPSchedType Schedule,
2689 assert(Schedule == OMP_sch_static || Schedule == OMP_sch_static_chunked ||
2690 Schedule == OMP_sch_static_balanced_chunked ||
2691 Schedule == OMP_ord_static || Schedule == OMP_ord_static_chunked ||
2692 Schedule == OMP_dist_sch_static ||
2693 Schedule == OMP_dist_sch_static_chunked);
2700 llvm::Value *Chunk = Values.
Chunk;
2701 if (Chunk ==
nullptr) {
2702 assert((Schedule == OMP_sch_static || Schedule == OMP_ord_static ||
2703 Schedule == OMP_dist_sch_static) &&
2704 "expected static non-chunked schedule");
2708 assert((Schedule == OMP_sch_static_chunked ||
2709 Schedule == OMP_sch_static_balanced_chunked ||
2710 Schedule == OMP_ord_static_chunked ||
2711 Schedule == OMP_dist_sch_static_chunked) &&
2712 "expected static chunked schedule");
2714 llvm::Value *Args[] = {
2737 "Expected loop-based or sections-based directive.");
2740 ? OMP_IDENT_WORK_LOOP
2741 : OMP_IDENT_WORK_SECTIONS);
2743 llvm::FunctionCallee StaticInitFunction =
2748 ScheduleNum, ScheduleKind.
M1, ScheduleKind.
M2, Values);
2755 OpenMPSchedType ScheduleNum =
2757 llvm::Value *UpdatedLocation =
2760 llvm::FunctionCallee StaticInitFunction;
2761 bool isGPUDistribute =
2762 CGM.getLangOpts().OpenMPIsTargetDevice &&
CGM.getTriple().isGPU();
2763 StaticInitFunction =
OMPBuilder.createForStaticInitFunction(
2774 assert((DKind == OMPD_distribute || DKind == OMPD_for ||
2775 DKind == OMPD_sections) &&
2776 "Expected distribute, for, or sections directive kind");
2780 llvm::Value *Args[] = {
2783 (DKind == OMPD_target_teams_loop)
2784 ? OMP_IDENT_WORK_DISTRIBUTE
2786 ? OMP_IDENT_WORK_LOOP
2787 : OMP_IDENT_WORK_SECTIONS),
2791 CGM.getLangOpts().OpenMPIsTargetDevice &&
CGM.getTriple().isGPU())
2794 CGM.getModule(), OMPRTL___kmpc_distribute_static_fini),
2798 CGM.getModule(), OMPRTL___kmpc_for_static_fini),
2823 llvm::Value *Args[] = {
2831 OMPBuilder.createDispatchNextFunction(IVSize, IVSigned), Args);
2838 const Expr *Message,
2841 return llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
2850 return llvm::ConstantInt::get(
CGM.Int32Ty,
2851 Severity == OMPC_SEVERITY_warning ? 1 : 2);
2867 RuntimeFunction FnID = OMPRTL___kmpc_push_num_threads;
2868 if (Modifier == OMPC_NUMTHREADS_strict) {
2869 FnID = OMPRTL___kmpc_push_num_threads_strict;
2874 OMPBuilder.getOrCreateRuntimeFunction(
CGM.getModule(), FnID), Args);
2878 ProcBindKind ProcBind,
2882 assert(ProcBind != OMP_PROC_BIND_unknown &&
"Unsupported proc_bind value.");
2884 llvm::Value *Args[] = {
2886 llvm::ConstantInt::get(
CGM.IntTy,
unsigned(ProcBind),
true)};
2888 CGM.getModule(), OMPRTL___kmpc_push_proc_bind),
2901 CGM.getModule(), OMPRTL___kmpc_flush),
2908enum KmpTaskTFields {
2935 if (
CGM.getLangOpts().OpenMPSimd ||
OMPBuilder.OffloadInfoManager.empty())
2938 llvm::OpenMPIRBuilder::EmitMetadataErrorReportFunctionTy &&ErrorReportFn =
2939 [
this](llvm::OpenMPIRBuilder::EmitMetadataErrorKind Kind,
2940 const llvm::TargetRegionEntryInfo &EntryInfo) ->
void {
2942 if (Kind != llvm::OpenMPIRBuilder::EMIT_MD_GLOBAL_VAR_LINK_ERROR) {
2943 for (
auto I =
CGM.getContext().getSourceManager().fileinfo_begin(),
2944 E =
CGM.getContext().getSourceManager().fileinfo_end();
2946 if (I->getFirst().getUniqueID().getDevice() == EntryInfo.DeviceID &&
2947 I->getFirst().getUniqueID().getFile() == EntryInfo.FileID) {
2948 Loc =
CGM.getContext().getSourceManager().translateFileLineCol(
2949 I->getFirst(), EntryInfo.Line, 1);
2955 case llvm::OpenMPIRBuilder::EMIT_MD_TARGET_REGION_ERROR: {
2956 CGM.getDiags().Report(Loc,
2957 diag::err_target_region_offloading_entry_incorrect)
2958 << EntryInfo.ParentName;
2960 case llvm::OpenMPIRBuilder::EMIT_MD_DECLARE_TARGET_ERROR: {
2961 CGM.getDiags().Report(
2962 Loc, diag::err_target_var_offloading_entry_incorrect_with_parent)
2963 << EntryInfo.ParentName;
2965 case llvm::OpenMPIRBuilder::EMIT_MD_GLOBAL_VAR_LINK_ERROR: {
2966 CGM.getDiags().Report(diag::err_target_var_offloading_entry_incorrect);
2968 case llvm::OpenMPIRBuilder::EMIT_MD_GLOBAL_VAR_INDIRECT_ERROR: {
2969 unsigned DiagID =
CGM.getDiags().getCustomDiagID(
2971 "target variable is incorrect: the "
2972 "address is invalid.");
2973 CGM.getDiags().Report(DiagID);
2978 OMPBuilder.createOffloadEntriesAndInfoMetadata(ErrorReportFn);
2985 QualType KmpRoutineEntryTyArgs[] = {KmpInt32Ty,
C.VoidPtrTy};
2988 C.getFunctionType(KmpInt32Ty, KmpRoutineEntryTyArgs, EPI));
2994struct PrivateHelpersTy {
2995 PrivateHelpersTy(
const Expr *OriginalRef,
const VarDecl *Original,
2997 : OriginalRef(OriginalRef), Original(Original), PrivateCopy(PrivateCopy),
2998 PrivateElemInit(PrivateElemInit) {}
2999 PrivateHelpersTy(
const VarDecl *Original) : Original(Original) {}
3000 const Expr *OriginalRef =
nullptr;
3001 const VarDecl *Original =
nullptr;
3002 const VarDecl *PrivateCopy =
nullptr;
3003 const VarDecl *PrivateElemInit =
nullptr;
3004 bool isLocalPrivate()
const {
3005 return !OriginalRef && !PrivateCopy && !PrivateElemInit;
3008typedef std::pair<CharUnits , PrivateHelpersTy> PrivateDataTy;
3013 if (!CVD->
hasAttr<OMPAllocateDeclAttr>())
3015 const auto *AA = CVD->
getAttr<OMPAllocateDeclAttr>();
3017 return !(AA->getAllocatorType() == OMPAllocateDeclAttr::OMPDefaultMemAlloc &&
3018 !AA->getAllocator());
3028 RecordDecl *RD =
C.buildImplicitRecord(
".kmp_privates.t");
3030 for (
const auto &Pair :
Privates) {
3031 const VarDecl *VD = Pair.second.Original;
3035 if (Pair.second.isLocalPrivate()) {
3058 QualType KmpRoutineEntryPointerQTy) {
3078 CanQualType KmpCmplrdataTy =
C.getCanonicalTagType(UD);
3079 RecordDecl *RD =
C.buildImplicitRecord(
"kmp_task_t");
3109 RecordDecl *RD =
C.buildImplicitRecord(
"kmp_task_t_with_privates");
3129static llvm::Function *
3132 QualType KmpTaskTWithPrivatesPtrQTy,
3134 QualType SharedsPtrTy, llvm::Function *TaskFunction,
3135 llvm::Value *TaskPrivatesMap) {
3143 Args.push_back(&GtidArg);
3144 Args.push_back(&TaskTypeArg);
3145 const auto &TaskEntryFnInfo =
3147 llvm::FunctionType *TaskEntryTy =
3150 auto *TaskEntry = llvm::Function::Create(
3151 TaskEntryTy, llvm::GlobalValue::InternalLinkage, Name, &CGM.
getModule());
3154 TaskEntry->addFnAttr(
"sample-profile-suffix-elision-policy",
"selected");
3155 TaskEntry->setDoesNotRecurse();
3170 const auto *KmpTaskTWithPrivatesQTyRD =
3175 auto PartIdFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTPartId);
3177 llvm::Value *PartidParam = PartIdLVal.getPointer(CGF);
3179 auto SharedsFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTShareds);
3185 auto PrivatesFI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin(), 1);
3186 llvm::Value *PrivatesParam;
3187 if (PrivatesFI != KmpTaskTWithPrivatesQTyRD->field_end()) {
3190 PrivatesLVal.getPointer(CGF), CGF.
VoidPtrTy);
3192 PrivatesParam = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
3195 llvm::Value *CommonArgs[] = {
3196 GtidParam, PartidParam, PrivatesParam, TaskPrivatesMap,
3202 std::end(CommonArgs));
3204 auto LBFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound);
3207 auto UBFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound);
3210 auto StFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTStride);
3213 auto LIFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLastIter);
3216 auto RFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTReductions);
3219 CallArgs.push_back(LBParam);
3220 CallArgs.push_back(UBParam);
3221 CallArgs.push_back(StParam);
3222 CallArgs.push_back(LIParam);
3223 CallArgs.push_back(RParam);
3225 CallArgs.push_back(SharedsParam);
3238 QualType KmpTaskTWithPrivatesPtrQTy,
3239 QualType KmpTaskTWithPrivatesQTy) {
3247 Args.push_back(&GtidArg);
3248 Args.push_back(&TaskTypeArg);
3249 const auto &DestructorFnInfo =
3251 llvm::FunctionType *DestructorFnTy =
3255 auto *DestructorFn =
3256 llvm::Function::Create(DestructorFnTy, llvm::GlobalValue::InternalLinkage,
3261 DestructorFn->addFnAttr(
"sample-profile-suffix-elision-policy",
"selected");
3262 DestructorFn->setDoesNotRecurse();
3270 const auto *KmpTaskTWithPrivatesQTyRD =
3272 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin());
3274 for (
const auto *Field : FI->getType()->castAsRecordDecl()->fields()) {
3276 Field->getType().isDestructedType()) {
3278 CGF.
pushDestroy(DtorKind, FieldLValue.getAddress(), Field->getType());
3282 return DestructorFn;
3302 C,
nullptr, Loc,
nullptr,
3303 C.getPointerType(PrivatesQTy).withConst().withRestrict(),
3305 Args.push_back(&TaskPrivatesArg);
3306 llvm::DenseMap<CanonicalDeclPtr<const VarDecl>,
unsigned> PrivateVarsPos;
3307 unsigned Counter = 1;
3308 for (
const Expr *E :
Data.PrivateVars) {
3310 C,
nullptr, Loc,
nullptr,
3311 C.getPointerType(
C.getPointerType(E->
getType()))
3316 PrivateVarsPos[VD] = Counter;
3319 for (
const Expr *E :
Data.FirstprivateVars) {
3321 C,
nullptr, Loc,
nullptr,
3322 C.getPointerType(
C.getPointerType(E->
getType()))
3327 PrivateVarsPos[VD] = Counter;
3330 for (
const Expr *E :
Data.LastprivateVars) {
3332 C,
nullptr, Loc,
nullptr,
3333 C.getPointerType(
C.getPointerType(E->
getType()))
3338 PrivateVarsPos[VD] = Counter;
3344 Ty =
C.getPointerType(Ty);
3346 Ty =
C.getPointerType(Ty);
3348 C,
nullptr, Loc,
nullptr,
3349 C.getPointerType(
C.getPointerType(Ty)).withConst().withRestrict(),
3351 PrivateVarsPos[VD] = Counter;
3354 const auto &TaskPrivatesMapFnInfo =
3356 llvm::FunctionType *TaskPrivatesMapTy =
3360 auto *TaskPrivatesMap = llvm::Function::Create(
3361 TaskPrivatesMapTy, llvm::GlobalValue::InternalLinkage, Name,
3364 TaskPrivatesMapFnInfo);
3366 TaskPrivatesMap->addFnAttr(
"sample-profile-suffix-elision-policy",
3369 TaskPrivatesMap->removeFnAttr(llvm::Attribute::NoInline);
3370 TaskPrivatesMap->removeFnAttr(llvm::Attribute::OptimizeNone);
3371 TaskPrivatesMap->addFnAttr(llvm::Attribute::AlwaysInline);
3375 TaskPrivatesMapFnInfo, Args, Loc, Loc);
3383 for (
const FieldDecl *Field : PrivatesQTyRD->fields()) {
3385 const VarDecl *VD = Args[PrivateVarsPos[
Privates[Counter].second.Original]];
3389 RefLVal.getAddress(), RefLVal.getType()->castAs<
PointerType>());
3394 return TaskPrivatesMap;
3400 Address KmpTaskSharedsPtr, LValue TDBase,
3406 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->
field_begin());
3420 if ((!IsTargetTask && !
Data.FirstprivateVars.empty() && ForDup) ||
3421 (IsTargetTask && KmpTaskSharedsPtr.
isValid())) {
3428 FI = FI->getType()->castAsRecordDecl()->field_begin();
3429 for (
const PrivateDataTy &Pair :
Privates) {
3431 if (Pair.second.isLocalPrivate()) {
3435 const VarDecl *VD = Pair.second.PrivateCopy;
3440 if (
const VarDecl *Elem = Pair.second.PrivateElemInit) {
3441 const VarDecl *OriginalVD = Pair.second.Original;
3444 LValue SharedRefLValue;
3447 if (IsTargetTask && !SharedField) {
3451 ->getNumParams() == 0 &&
3454 ->getDeclContext()) &&
3455 "Expected artificial target data variable.");
3458 }
else if (ForDup) {
3461 SharedRefLValue.getAddress().withAlignment(
3462 C.getDeclAlign(OriginalVD)),
3464 SharedRefLValue.getTBAAInfo());
3466 Pair.second.Original->getCanonicalDecl()) > 0 ||
3468 SharedRefLValue = CGF.
EmitLValue(Pair.second.OriginalRef);
3471 InlinedOpenMPRegionRAII Region(
3474 SharedRefLValue = CGF.
EmitLValue(Pair.second.OriginalRef);
3485 PrivateLValue.getAddress(), SharedRefLValue.getAddress(),
Type,
3486 [&CGF, Elem,
Init, &CapturesInfo](
Address DestElement,
3489 CodeGenFunction::OMPPrivateScope InitScope(CGF);
3490 InitScope.addPrivate(Elem, SrcElement);
3491 (void)InitScope.Privatize();
3493 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(
3494 CGF, &CapturesInfo);
3495 CGF.EmitAnyExprToMem(Init, DestElement,
3496 Init->getType().getQualifiers(),
3502 InitScope.addPrivate(Elem, SharedRefLValue.getAddress());
3503 (void)InitScope.Privatize();
3519 bool InitRequired =
false;
3520 for (
const PrivateDataTy &Pair :
Privates) {
3521 if (Pair.second.isLocalPrivate())
3523 const VarDecl *VD = Pair.second.PrivateCopy;
3525 InitRequired = InitRequired || (isa_and_nonnull<CXXConstructExpr>(
Init) &&
3530 return InitRequired;
3547 QualType KmpTaskTWithPrivatesPtrQTy,
3555 KmpTaskTWithPrivatesPtrQTy,
3558 KmpTaskTWithPrivatesPtrQTy,
3562 Args.push_back(&DstArg);
3563 Args.push_back(&SrcArg);
3564 Args.push_back(&LastprivArg);
3565 const auto &TaskDupFnInfo =
3569 auto *TaskDup = llvm::Function::Create(
3570 TaskDupTy, llvm::GlobalValue::InternalLinkage, Name, &CGM.
getModule());
3573 TaskDup->addFnAttr(
"sample-profile-suffix-elision-policy",
"selected");
3574 TaskDup->setDoesNotRecurse();
3584 auto LIFI = std::next(KmpTaskTQTyRD->
field_begin(), KmpTaskTLastIter);
3586 TDBase, *KmpTaskTWithPrivatesQTyRD->
field_begin());
3596 if (!
Data.FirstprivateVars.empty()) {
3601 TDBase, *KmpTaskTWithPrivatesQTyRD->
field_begin());
3609 emitPrivatesInit(CGF, D, KmpTaskSharedsPtr, TDBase, KmpTaskTWithPrivatesQTyRD,
3620 for (
const PrivateDataTy &P :
Privates) {
3621 if (P.second.isLocalPrivate())
3623 QualType Ty = P.second.Original->getType().getNonReferenceType();
3632class OMPIteratorGeneratorScope final
3634 CodeGenFunction &CGF;
3635 const OMPIteratorExpr *E =
nullptr;
3636 SmallVector<CodeGenFunction::JumpDest, 4> ContDests;
3637 SmallVector<CodeGenFunction::JumpDest, 4> ExitDests;
3638 OMPIteratorGeneratorScope() =
delete;
3639 OMPIteratorGeneratorScope(OMPIteratorGeneratorScope &) =
delete;
3642 OMPIteratorGeneratorScope(CodeGenFunction &CGF,
const OMPIteratorExpr *E)
3643 : CodeGenFunction::OMPPrivateScope(CGF), CGF(CGF), E(E) {
3646 SmallVector<llvm::Value *, 4> Uppers;
3648 Uppers.push_back(CGF.EmitScalarExpr(E->getHelper(I).Upper));
3649 const auto *VD = cast<VarDecl>(E->getIteratorDecl(I));
3650 addPrivate(VD, CGF.CreateMemTemp(VD->getType(), VD->getName()));
3651 const OMPIteratorHelperData &HelperData = E->getHelper(I);
3653 HelperData.CounterVD,
3654 CGF.CreateMemTemp(HelperData.CounterVD->getType(),
"counter.addr"));
3659 const OMPIteratorHelperData &HelperData = E->getHelper(I);
3661 CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(HelperData.CounterVD),
3662 HelperData.CounterVD->getType());
3664 CGF.EmitStoreOfScalar(
3665 llvm::ConstantInt::get(CLVal.getAddress().getElementType(), 0),
3667 CodeGenFunction::JumpDest &ContDest =
3668 ContDests.emplace_back(CGF.getJumpDestInCurrentScope(
"iter.cont"));
3669 CodeGenFunction::JumpDest &ExitDest =
3670 ExitDests.emplace_back(CGF.getJumpDestInCurrentScope(
"iter.exit"));
3672 llvm::Value *N = Uppers[I];
3675 CGF.EmitBlock(ContDest.getBlock());
3677 CGF.EmitLoadOfScalar(CLVal, HelperData.CounterVD->getLocation());
3679 HelperData.CounterVD->getType()->isSignedIntegerOrEnumerationType()
3680 ? CGF.Builder.CreateICmpSLT(CVal, N)
3681 : CGF.Builder.CreateICmpULT(CVal, N);
3682 llvm::BasicBlock *BodyBB = CGF.createBasicBlock(
"iter.body");
3683 CGF.Builder.CreateCondBr(Cmp, BodyBB, ExitDest.getBlock());
3685 CGF.EmitBlock(BodyBB);
3687 CGF.EmitIgnoredExpr(HelperData.Update);
3690 ~OMPIteratorGeneratorScope() {
3695 const OMPIteratorHelperData &HelperData = E->
getHelper(I - 1);
3700 CGF.
EmitBlock(ExitDests[I - 1].getBlock(), I == 1);
3706static std::pair<llvm::Value *, llvm::Value *>
3708 const auto *OASE = dyn_cast<OMPArrayShapingExpr>(E);
3711 const Expr *
Base = OASE->getBase();
3716 llvm::Value *SizeVal;
3719 SizeVal = CGF.
getTypeSize(OASE->getBase()->getType()->getPointeeType());
3720 for (
const Expr *SE : OASE->getDimensions()) {
3724 SizeVal = CGF.
Builder.CreateNUWMul(SizeVal, Sz);
3726 }
else if (
const auto *ASE =
3729 Address UpAddrAddress = UpAddrLVal.getAddress();
3730 llvm::Value *UpAddr = CGF.
Builder.CreateConstGEP1_32(
3733 SizeVal = CGF.
Builder.CreatePtrDiff(UpAddr,
Addr,
"",
true);
3737 return std::make_pair(
Addr, SizeVal);
3742 QualType FlagsTy =
C.getIntTypeForBitwidth(32,
false);
3743 if (KmpTaskAffinityInfoTy.
isNull()) {
3745 C.buildImplicitRecord(
"kmp_task_affinity_info_t");
3751 KmpTaskAffinityInfoTy =
C.getCanonicalTagType(KmpAffinityInfoRD);
3758 llvm::Function *TaskFunction,
QualType SharedsTy,
3763 const auto *I =
Data.PrivateCopies.begin();
3764 for (
const Expr *E :
Data.PrivateVars) {
3772 I =
Data.FirstprivateCopies.begin();
3773 const auto *IElemInitRef =
Data.FirstprivateInits.begin();
3774 for (
const Expr *E :
Data.FirstprivateVars) {
3784 I =
Data.LastprivateCopies.begin();
3785 for (
const Expr *E :
Data.LastprivateVars) {
3795 Privates.emplace_back(
CGM.getPointerAlign(), PrivateHelpersTy(VD));
3797 Privates.emplace_back(
C.getDeclAlign(VD), PrivateHelpersTy(VD));
3800 [](
const PrivateDataTy &L,
const PrivateDataTy &R) {
3801 return L.first > R.first;
3803 QualType KmpInt32Ty =
C.getIntTypeForBitwidth(32, 1);
3814 assert((D.getDirectiveKind() == OMPD_task ||
3817 "Expected taskloop, task or target directive");
3824 const auto *KmpTaskTQTyRD =
KmpTaskTQTy->castAsRecordDecl();
3826 const RecordDecl *KmpTaskTWithPrivatesQTyRD =
3829 C.getCanonicalTagType(KmpTaskTWithPrivatesQTyRD);
3830 QualType KmpTaskTWithPrivatesPtrQTy =
3831 C.getPointerType(KmpTaskTWithPrivatesQTy);
3832 llvm::Type *KmpTaskTWithPrivatesPtrTy = CGF.
Builder.getPtrTy(0);
3833 llvm::Value *KmpTaskTWithPrivatesTySize =
3835 QualType SharedsPtrTy =
C.getPointerType(SharedsTy);
3838 llvm::Value *TaskPrivatesMap =
nullptr;
3839 llvm::Type *TaskPrivatesMapTy =
3840 std::next(TaskFunction->arg_begin(), 3)->getType();
3842 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->
field_begin());
3846 TaskPrivatesMap, TaskPrivatesMapTy);
3848 TaskPrivatesMap = llvm::ConstantPointerNull::get(
3854 CGM, Loc, D.getDirectiveKind(), KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy,
3855 KmpTaskTWithPrivatesQTy,
KmpTaskTQTy, SharedsPtrTy, TaskFunction,
3867 DestructorsFlag = 0x8,
3868 PriorityFlag = 0x20,
3869 DetachableFlag = 0x40,
3870 FreeAgentFlag = 0x80,
3871 TransparentFlag = 0x100,
3873 unsigned Flags =
Data.Tied ? TiedFlag : 0;
3874 bool NeedsCleanup =
false;
3879 Flags = Flags | DestructorsFlag;
3883 if (Kind == OMPC_THREADSET_omp_pool)
3884 Flags = Flags | FreeAgentFlag;
3886 if (D.getSingleClause<OMPTransparentClause>())
3887 Flags |= TransparentFlag;
3889 if (
Data.Priority.getInt())
3890 Flags = Flags | PriorityFlag;
3892 Flags = Flags | DetachableFlag;
3893 llvm::Value *TaskFlags =
3894 Data.Final.getPointer()
3895 ? CGF.
Builder.CreateSelect(
Data.Final.getPointer(),
3896 CGF.
Builder.getInt32(FinalFlag),
3898 : CGF.
Builder.getInt32(
Data.Final.getInt() ? FinalFlag : 0);
3899 TaskFlags = CGF.
Builder.CreateOr(TaskFlags, CGF.
Builder.getInt32(Flags));
3900 llvm::Value *SharedsSize =
CGM.getSize(
C.getTypeSizeInChars(SharedsTy));
3902 getThreadID(CGF, Loc), TaskFlags, KmpTaskTWithPrivatesTySize,
3905 llvm::Value *NewTask;
3906 if (D.hasClausesOfKind<OMPNowaitClause>()) {
3912 llvm::Value *DeviceID;
3917 DeviceID = CGF.
Builder.getInt64(OMP_DEVICEID_UNDEF);
3918 AllocArgs.push_back(DeviceID);
3921 CGM.getModule(), OMPRTL___kmpc_omp_target_task_alloc),
3926 CGM.getModule(), OMPRTL___kmpc_omp_task_alloc),
3939 llvm::Value *Tid =
getThreadID(CGF, DC->getBeginLoc());
3940 Tid = CGF.
Builder.CreateIntCast(Tid, CGF.
IntTy,
false);
3943 CGM.getModule(), OMPRTL___kmpc_task_allow_completion_event),
3944 {Loc, Tid, NewTask});
3955 llvm::Value *NumOfElements =
nullptr;
3956 unsigned NumAffinities = 0;
3958 if (
const Expr *Modifier =
C->getModifier()) {
3960 for (
unsigned I = 0, E = IE->numOfIterators(); I < E; ++I) {
3964 NumOfElements ? CGF.
Builder.CreateNUWMul(NumOfElements, Sz) : Sz;
3967 NumAffinities +=
C->varlist_size();
3972 enum RTLAffinityInfoFieldsTy { BaseAddr, Len, Flags };
3974 QualType KmpTaskAffinityInfoArrayTy;
3975 if (NumOfElements) {
3976 NumOfElements = CGF.
Builder.CreateNUWAdd(
3977 llvm::ConstantInt::get(CGF.
SizeTy, NumAffinities), NumOfElements);
3980 C.getIntTypeForBitwidth(
C.getTypeSize(
C.getSizeType()), 0),
3984 KmpTaskAffinityInfoArrayTy =
C.getVariableArrayType(
3992 NumOfElements = CGF.
Builder.CreateIntCast(NumOfElements, CGF.
Int32Ty,
3995 KmpTaskAffinityInfoArrayTy =
C.getConstantArrayType(
3997 llvm::APInt(
C.getTypeSize(
C.getSizeType()), NumAffinities),
nullptr,
4000 CGF.
CreateMemTemp(KmpTaskAffinityInfoArrayTy,
".affs.arr.addr");
4002 NumOfElements = llvm::ConstantInt::get(
CGM.Int32Ty, NumAffinities,
4009 bool HasIterator =
false;
4011 if (
C->getModifier()) {
4015 for (
const Expr *E :
C->varlist()) {
4024 Base, *std::next(KmpAffinityInfoRD->field_begin(), BaseAddr));
4029 Base, *std::next(KmpAffinityInfoRD->field_begin(), Len));
4043 const Expr *Modifier =
C->getModifier();
4046 OMPIteratorGeneratorScope IteratorScope(
4048 for (
const Expr *E :
C->varlist()) {
4058 Base, *std::next(KmpAffinityInfoRD->field_begin(), BaseAddr));
4063 Base, *std::next(KmpAffinityInfoRD->field_begin(), Len));
4065 Idx = CGF.
Builder.CreateNUWAdd(
4066 Idx, llvm::ConstantInt::get(Idx->getType(), 1));
4081 CGM.getModule(), OMPRTL___kmpc_omp_reg_task_with_affinity),
4082 {LocRef, GTid, NewTask, NumOfElements, AffinListPtr});
4084 llvm::Value *NewTaskNewTaskTTy =
4086 NewTask, KmpTaskTWithPrivatesPtrTy);
4088 KmpTaskTWithPrivatesQTy);
4099 *std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTShareds)),
4101 CGF.
Int8Ty,
CGM.getNaturalTypeAlignment(SharedsTy));
4115 CGM, Loc, D, KmpTaskTWithPrivatesPtrQTy, KmpTaskTWithPrivatesQTyRD,
4116 KmpTaskTQTyRD, SharedsTy, SharedsPtrTy,
Data,
Privates,
4117 !
Data.LastprivateVars.empty());
4121 enum { Priority = 0, Destructors = 1 };
4123 auto FI = std::next(KmpTaskTQTyRD->field_begin(), Data1);
4124 const auto *KmpCmplrdataUD = (*FI)->getType()->castAsRecordDecl();
4125 assert(KmpCmplrdataUD->isUnion());
4128 CGM, Loc, KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy,
4129 KmpTaskTWithPrivatesQTy);
4132 Data1LV, *std::next(KmpCmplrdataUD->field_begin(), Destructors));
4138 if (
Data.Priority.getInt()) {
4140 TDBase, *std::next(KmpTaskTQTyRD->field_begin(), Data2));
4142 Data2LV, *std::next(KmpCmplrdataUD->field_begin(), Priority));
4145 Result.NewTask = NewTask;
4146 Result.TaskEntry = TaskEntry;
4147 Result.NewTaskNewTaskTTy = NewTaskNewTaskTTy;
4149 Result.KmpTaskTQTyRD = KmpTaskTQTyRD;
4155 RTLDependenceKindTy DepKind;
4157 case OMPC_DEPEND_in:
4158 DepKind = RTLDependenceKindTy::DepIn;
4161 case OMPC_DEPEND_out:
4162 case OMPC_DEPEND_inout:
4163 DepKind = RTLDependenceKindTy::DepInOut;
4165 case OMPC_DEPEND_mutexinoutset:
4166 DepKind = RTLDependenceKindTy::DepMutexInOutSet;
4168 case OMPC_DEPEND_inoutset:
4169 DepKind = RTLDependenceKindTy::DepInOutSet;
4171 case OMPC_DEPEND_outallmemory:
4172 DepKind = RTLDependenceKindTy::DepOmpAllMem;
4174 case OMPC_DEPEND_source:
4175 case OMPC_DEPEND_sink:
4176 case OMPC_DEPEND_depobj:
4177 case OMPC_DEPEND_inoutallmemory:
4179 llvm_unreachable(
"Unknown task dependence type");
4187 FlagsTy =
C.getIntTypeForBitwidth(
C.getTypeSize(
C.BoolTy),
false);
4188 if (KmpDependInfoTy.
isNull()) {
4189 RecordDecl *KmpDependInfoRD =
C.buildImplicitRecord(
"kmp_depend_info");
4195 KmpDependInfoTy =
C.getCanonicalTagType(KmpDependInfoRD);
4199std::pair<llvm::Value *, LValue>
4212 CGF,
Base.getAddress(),
4213 llvm::ConstantInt::get(CGF.
IntPtrTy, -1,
true));
4219 *std::next(KmpDependInfoRD->field_begin(),
4220 static_cast<unsigned int>(RTLDependInfoFields::BaseAddr)));
4222 return std::make_pair(NumDeps,
Base);
4226 llvm::PointerUnion<unsigned *, LValue *> Pos,
4236 OMPIteratorGeneratorScope IteratorScope(
4237 CGF, cast_or_null<OMPIteratorExpr>(
4238 Data.IteratorExpr ?
Data.IteratorExpr->IgnoreParenImpCasts()
4240 for (
const Expr *E :
Data.DepExprs) {
4250 Size = llvm::ConstantInt::get(CGF.
SizeTy, 0);
4253 if (
unsigned *P = dyn_cast<unsigned *>(Pos)) {
4257 assert(E &&
"Expected a non-null expression");
4266 *std::next(KmpDependInfoRD->field_begin(),
4267 static_cast<unsigned int>(RTLDependInfoFields::BaseAddr)));
4271 Base, *std::next(KmpDependInfoRD->field_begin(),
4272 static_cast<unsigned int>(RTLDependInfoFields::Len)));
4278 *std::next(KmpDependInfoRD->field_begin(),
4279 static_cast<unsigned int>(RTLDependInfoFields::Flags)));
4281 llvm::ConstantInt::get(LLVMFlagsTy,
static_cast<unsigned int>(DepKind)),
4283 if (
unsigned *P = dyn_cast<unsigned *>(Pos)) {
4288 Idx = CGF.
Builder.CreateNUWAdd(Idx,
4289 llvm::ConstantInt::get(Idx->getType(), 1));
4298 assert(
Data.DepKind == OMPC_DEPEND_depobj &&
4299 "Expected depobj dependency kind.");
4304 OMPIteratorGeneratorScope IteratorScope(
4305 CGF, cast_or_null<OMPIteratorExpr>(
4306 Data.IteratorExpr ?
Data.IteratorExpr->IgnoreParenImpCasts()
4308 for (
const Expr *E :
Data.DepExprs) {
4309 llvm::Value *NumDeps;
4312 std::tie(NumDeps,
Base) =
4316 C.getUIntPtrType());
4320 llvm::Value *Add = CGF.
Builder.CreateNUWAdd(PrevVal, NumDeps);
4322 SizeLVals.push_back(NumLVal);
4325 for (
unsigned I = 0, E = SizeLVals.size(); I < E; ++I) {
4328 Sizes.push_back(Size);
4338 assert(
Data.DepKind == OMPC_DEPEND_depobj &&
4339 "Expected depobj dependency kind.");
4342 OMPIteratorGeneratorScope IteratorScope(
4343 CGF, cast_or_null<OMPIteratorExpr>(
4344 Data.IteratorExpr ?
Data.IteratorExpr->IgnoreParenImpCasts()
4346 for (
const Expr *E :
Data.DepExprs) {
4347 llvm::Value *NumDeps;
4350 std::tie(NumDeps,
Base) =
4354 llvm::Value *Size = CGF.
Builder.CreateNUWMul(
4363 llvm::Value *Add = CGF.
Builder.CreateNUWAdd(Pos, NumDeps);
4379 llvm::Value *NumOfElements =
nullptr;
4380 unsigned NumDependencies = std::accumulate(
4381 Dependencies.begin(), Dependencies.end(), 0,
4383 return D.DepKind == OMPC_DEPEND_depobj
4385 : (V + (D.IteratorExpr ? 0 : D.DepExprs.size()));
4389 bool HasDepobjDeps =
false;
4390 bool HasRegularWithIterators =
false;
4391 llvm::Value *NumOfDepobjElements = llvm::ConstantInt::get(CGF.
IntPtrTy, 0);
4392 llvm::Value *NumOfRegularWithIterators =
4393 llvm::ConstantInt::get(CGF.
IntPtrTy, 0);
4397 if (D.
DepKind == OMPC_DEPEND_depobj) {
4400 for (llvm::Value *Size : Sizes) {
4401 NumOfDepobjElements =
4402 CGF.
Builder.CreateNUWAdd(NumOfDepobjElements, Size);
4404 HasDepobjDeps =
true;
4409 if (
const auto *IE = cast_or_null<OMPIteratorExpr>(D.
IteratorExpr)) {
4410 llvm::Value *ClauseIteratorSpace =
4411 llvm::ConstantInt::get(CGF.
IntPtrTy, 1);
4415 ClauseIteratorSpace = CGF.
Builder.CreateNUWMul(Sz, ClauseIteratorSpace);
4417 llvm::Value *NumClauseDeps = CGF.
Builder.CreateNUWMul(
4418 ClauseIteratorSpace,
4420 NumOfRegularWithIterators =
4421 CGF.
Builder.CreateNUWAdd(NumOfRegularWithIterators, NumClauseDeps);
4422 HasRegularWithIterators =
true;
4428 if (HasDepobjDeps || HasRegularWithIterators) {
4429 NumOfElements = llvm::ConstantInt::get(
CGM.IntPtrTy, NumDependencies,
4431 if (HasDepobjDeps) {
4433 CGF.
Builder.CreateNUWAdd(NumOfDepobjElements, NumOfElements);
4435 if (HasRegularWithIterators) {
4437 CGF.
Builder.CreateNUWAdd(NumOfRegularWithIterators, NumOfElements);
4440 Loc,
C.getIntTypeForBitwidth(64, 0),
4444 KmpDependInfoArrayTy =
4453 NumOfElements = CGF.
Builder.CreateIntCast(NumOfElements, CGF.
Int32Ty,
4456 KmpDependInfoArrayTy =
C.getConstantArrayType(
4462 NumOfElements = llvm::ConstantInt::get(
CGM.Int32Ty, NumDependencies,
4467 if (Dep.DepKind == OMPC_DEPEND_depobj || Dep.IteratorExpr)
4473 CGF.
CreateMemTemp(
C.getSizeType(),
"dep.counter.addr"),
C.getSizeType());
4476 if (Dep.DepKind == OMPC_DEPEND_depobj || !Dep.IteratorExpr)
4481 if (HasDepobjDeps) {
4483 if (Dep.DepKind != OMPC_DEPEND_depobj)
4490 return std::make_pair(NumOfElements, DependenciesArray);
4501 unsigned NumDependencies = Dependencies.
DepExprs.size();
4511 llvm::Value *NumDepsVal;
4513 if (
const auto *IE =
4514 cast_or_null<OMPIteratorExpr>(Dependencies.
IteratorExpr)) {
4515 NumDepsVal = llvm::ConstantInt::get(CGF.
SizeTy, 1);
4519 NumDepsVal = CGF.
Builder.CreateNUWMul(NumDepsVal, Sz);
4521 Size = CGF.
Builder.CreateNUWAdd(llvm::ConstantInt::get(CGF.
SizeTy, 1),
4525 llvm::Value *RecSize =
CGM.getSize(SizeInBytes);
4526 Size = CGF.
Builder.CreateNUWMul(Size, RecSize);
4530 QualType KmpDependInfoArrayTy =
C.getConstantArrayType(
4533 CharUnits Sz =
C.getTypeSizeInChars(KmpDependInfoArrayTy);
4535 NumDepsVal = llvm::ConstantInt::get(CGF.
IntPtrTy, NumDependencies);
4540 llvm::Value *Allocator = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
4541 llvm::Value *Args[] = {ThreadID, Size, Allocator};
4545 CGM.getModule(), OMPRTL___kmpc_alloc),
4546 Args,
".dep.arr.addr");
4550 DependenciesArray =
Address(
Addr, KmpDependInfoLlvmTy, Align);
4556 *std::next(KmpDependInfoRD->field_begin(),
4557 static_cast<unsigned int>(RTLDependInfoFields::BaseAddr)));
4559 llvm::PointerUnion<unsigned *, LValue *> Pos;
4576 return DependenciesArray;
4591 Addr.getElementType(),
Addr.emitRawPointer(CGF),
4592 llvm::ConstantInt::get(CGF.
IntPtrTy, -1,
true));
4597 llvm::Value *Allocator = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
4598 llvm::Value *Args[] = {ThreadID, DepObjAddr, Allocator};
4602 CGM.getModule(), OMPRTL___kmpc_free),
4614 llvm::Value *NumDeps;
4625 llvm::BasicBlock *EntryBB = CGF.
Builder.GetInsertBlock();
4627 llvm::PHINode *ElementPHI =
4632 Base.getTBAAInfo());
4636 Base, *std::next(KmpDependInfoRD->field_begin(),
4637 static_cast<unsigned int>(RTLDependInfoFields::Flags)));
4639 llvm::ConstantInt::get(LLVMFlagsTy,
static_cast<unsigned int>(DepKind)),
4643 llvm::Value *ElementNext =
4646 ElementPHI->addIncoming(ElementNext, CGF.
Builder.GetInsertBlock());
4647 llvm::Value *IsEmpty =
4648 CGF.
Builder.CreateICmpEQ(ElementNext, End,
"omp.isempty");
4649 CGF.
Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
4656 llvm::Function *TaskFunction,
4665 llvm::Value *NewTask =
Result.NewTask;
4666 llvm::Function *TaskEntry =
Result.TaskEntry;
4667 llvm::Value *NewTaskNewTaskTTy =
Result.NewTaskNewTaskTTy;
4672 llvm::Value *NumOfElements;
4673 std::tie(NumOfElements, DependenciesArray) =
4684 llvm::Value *TaskArgs[] = { UpLoc, ThreadID, NewTask };
4685 llvm::Value *DepTaskArgs[7];
4686 if (!
Data.Dependences.empty()) {
4687 DepTaskArgs[0] = UpLoc;
4688 DepTaskArgs[1] = ThreadID;
4689 DepTaskArgs[2] = NewTask;
4690 DepTaskArgs[3] = NumOfElements;
4692 DepTaskArgs[5] = CGF.
Builder.getInt32(0);
4693 DepTaskArgs[6] = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
4695 auto &&ThenCodeGen = [
this, &
Data, TDBase, KmpTaskTQTyRD, &TaskArgs,
4698 auto PartIdFI = std::next(KmpTaskTQTyRD->
field_begin(), KmpTaskTPartId);
4702 if (!
Data.Dependences.empty()) {
4705 CGM.getModule(), OMPRTL___kmpc_omp_task_with_deps),
4709 CGM.getModule(), OMPRTL___kmpc_omp_task),
4715 Region->emitUntiedSwitch(CGF);
4718 llvm::Value *DepWaitTaskArgs[7];
4719 if (!
Data.Dependences.empty()) {
4720 DepWaitTaskArgs[0] = UpLoc;
4721 DepWaitTaskArgs[1] = ThreadID;
4722 DepWaitTaskArgs[2] = NumOfElements;
4724 DepWaitTaskArgs[4] = CGF.
Builder.getInt32(0);
4725 DepWaitTaskArgs[5] = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
4726 DepWaitTaskArgs[6] =
4727 llvm::ConstantInt::get(CGF.
Int32Ty,
Data.HasNowaitClause);
4729 auto &M =
CGM.getModule();
4730 auto &&ElseCodeGen = [
this, &M, &TaskArgs, ThreadID, NewTaskNewTaskTTy,
4731 TaskEntry, &
Data, &DepWaitTaskArgs,
4738 if (!
Data.Dependences.empty())
4740 M, OMPRTL___kmpc_omp_taskwait_deps_51),
4743 auto &&
CodeGen = [TaskEntry, ThreadID, NewTaskNewTaskTTy,
4746 llvm::Value *OutlinedFnArgs[] = {ThreadID, NewTaskNewTaskTTy};
4747 CGF.CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, Loc, TaskEntry,
4756 CommonActionTy Action(
OMPBuilder.getOrCreateRuntimeFunction(
4757 M, OMPRTL___kmpc_omp_task_begin_if0),
4760 M, OMPRTL___kmpc_omp_task_complete_if0),
4776 llvm::Function *TaskFunction,
4796 IfVal = llvm::ConstantInt::getSigned(CGF.
IntTy, 1);
4801 *std::next(
Result.KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound));
4808 *std::next(
Result.KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound));
4815 *std::next(
Result.KmpTaskTQTyRD->field_begin(), KmpTaskTStride));
4823 *std::next(
Result.KmpTaskTQTyRD->field_begin(), KmpTaskTReductions));
4824 if (
Data.Reductions) {
4830 enum { NoSchedule = 0, Grainsize = 1, NumTasks = 2 };
4839 llvm::ConstantInt::getSigned(
4841 llvm::ConstantInt::getSigned(
4843 ?
Data.Schedule.getInt() ? NumTasks : Grainsize
4845 Data.Schedule.getPointer()
4848 : llvm::ConstantInt::get(CGF.
Int64Ty, 0)};
4849 if (
Data.HasModifier)
4850 TaskArgs.push_back(llvm::ConstantInt::get(CGF.
Int32Ty, 1));
4852 TaskArgs.push_back(
Result.TaskDupFn
4855 : llvm::ConstantPointerNull::get(CGF.
VoidPtrTy));
4857 CGM.getModule(),
Data.HasModifier
4858 ? OMPRTL___kmpc_taskloop_5
4859 : OMPRTL___kmpc_taskloop),
4876 const Expr *,
const Expr *)> &RedOpGen,
4877 const Expr *XExpr =
nullptr,
const Expr *EExpr =
nullptr,
4878 const Expr *UpExpr =
nullptr) {
4886 llvm::Value *NumElements = CGF.
emitArrayLength(ArrayTy, ElementTy, LHSAddr);
4891 llvm::Value *LHSEnd =
4896 llvm::Value *IsEmpty =
4897 CGF.
Builder.CreateICmpEQ(LHSBegin, LHSEnd,
"omp.arraycpy.isempty");
4898 CGF.
Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
4901 llvm::BasicBlock *EntryBB = CGF.
Builder.GetInsertBlock();
4906 llvm::PHINode *RHSElementPHI = CGF.
Builder.CreatePHI(
4907 RHSBegin->getType(), 2,
"omp.arraycpy.srcElementPast");
4908 RHSElementPHI->addIncoming(RHSBegin, EntryBB);
4913 llvm::PHINode *LHSElementPHI = CGF.
Builder.CreatePHI(
4914 LHSBegin->getType(), 2,
"omp.arraycpy.destElementPast");
4915 LHSElementPHI->addIncoming(LHSBegin, EntryBB);
4922 Scope.addPrivate(LHSVar, LHSElementCurrent);
4923 Scope.addPrivate(RHSVar, RHSElementCurrent);
4925 RedOpGen(CGF, XExpr, EExpr, UpExpr);
4926 Scope.ForceCleanup();
4929 llvm::Value *LHSElementNext = CGF.
Builder.CreateConstGEP1_32(
4931 "omp.arraycpy.dest.element");
4932 llvm::Value *RHSElementNext = CGF.
Builder.CreateConstGEP1_32(
4934 "omp.arraycpy.src.element");
4937 CGF.
Builder.CreateICmpEQ(LHSElementNext, LHSEnd,
"omp.arraycpy.done");
4938 CGF.
Builder.CreateCondBr(Done, DoneBB, BodyBB);
4939 LHSElementPHI->addIncoming(LHSElementNext, CGF.
Builder.GetInsertBlock());
4940 RHSElementPHI->addIncoming(RHSElementNext, CGF.
Builder.GetInsertBlock());
4950 const Expr *ReductionOp) {
4951 if (
const auto *CE = dyn_cast<CallExpr>(ReductionOp))
4952 if (
const auto *OVE = dyn_cast<OpaqueValueExpr>(CE->getCallee()))
4953 if (
const auto *DRE =
4954 dyn_cast<DeclRefExpr>(OVE->getSourceExpr()->IgnoreImpCasts()))
4955 if (
const auto *DRD =
4956 dyn_cast<OMPDeclareReductionDecl>(DRE->getDecl())) {
4957 std::pair<llvm::Function *, llvm::Function *>
Reduction =
4968 StringRef ReducerName,
SourceLocation Loc, llvm::Type *ArgsElemType,
4979 Args.push_back(&LHSArg);
4980 Args.push_back(&RHSArg);
4982 CGM.getTypes().arrangeBuiltinFunctionDeclaration(
C.VoidTy, Args);
4984 auto *Fn = llvm::Function::Create(
CGM.getTypes().GetFunctionType(CGFI),
4985 llvm::GlobalValue::InternalLinkage, Name,
4988 if (!
CGM.getCodeGenOpts().SampleProfileFile.empty())
4989 Fn->addFnAttr(
"sample-profile-suffix-elision-policy",
"selected");
4990 Fn->setDoesNotRecurse();
5009 const auto *IPriv =
Privates.begin();
5011 for (
unsigned I = 0, E = ReductionOps.size(); I < E; ++I, ++IPriv, ++Idx) {
5012 const auto *RHSVar =
5015 const auto *LHSVar =
5018 QualType PrivTy = (*IPriv)->getType();
5034 const auto *ILHS = LHSExprs.begin();
5035 const auto *IRHS = RHSExprs.begin();
5036 for (
const Expr *E : ReductionOps) {
5037 if ((*IPriv)->getType()->isArrayType()) {
5042 CGF, (*IPriv)->getType(), LHSVar, RHSVar,
5044 emitReductionCombiner(CGF, E);
5054 Scope.ForceCleanup();
5060 const Expr *ReductionOp,
5061 const Expr *PrivateRef,
5069 CGF, PrivateRef->
getType(), LHSVar, RHSVar,
5071 emitReductionCombiner(CGF, ReductionOp);
5080 llvm::StringRef Prefix,
const Expr *Ref);
5084 const Expr *LHSExprs,
const Expr *RHSExprs,
const Expr *ReductionOps) {
5111 std::string ReductionVarNameStr;
5112 if (
const auto *DRE = dyn_cast<DeclRefExpr>(
Privates->IgnoreParenCasts()))
5113 ReductionVarNameStr =
5116 ReductionVarNameStr =
"unnamed_priv_var";
5119 std::string SharedName =
5120 CGM.getOpenMPRuntime().getName({
"internal_pivate_", ReductionVarNameStr});
5121 llvm::GlobalVariable *SharedVar =
OMPBuilder.getOrCreateInternalVariable(
5122 LLVMType,
".omp.reduction." + SharedName);
5124 SharedVar->setAlignment(
5132 llvm::Value *BarrierArgs[] = {BarrierLoc, ThreadId};
5137 llvm::Value *IsWorker = CGF.
Builder.CreateICmpEQ(
5138 ThreadId, llvm::ConstantInt::get(ThreadId->getType(), 0));
5139 CGF.
Builder.CreateCondBr(IsWorker, InitBB, InitEndBB);
5143 auto EmitSharedInit = [&]() {
5146 std::pair<llvm::Function *, llvm::Function *> FnPair =
5148 llvm::Function *InitializerFn = FnPair.second;
5149 if (InitializerFn) {
5150 if (
const auto *CE =
5151 dyn_cast<CallExpr>(UDRInitExpr->IgnoreParenImpCasts())) {
5158 LocalScope.addPrivate(OutVD, SharedResult);
5160 (void)LocalScope.Privatize();
5161 if (
const auto *OVE = dyn_cast<OpaqueValueExpr>(
5162 CE->getCallee()->IgnoreParenImpCasts())) {
5188 if (
const auto *DRE = dyn_cast<DeclRefExpr>(
Privates)) {
5189 if (
const auto *VD = dyn_cast<VarDecl>(DRE->getDecl())) {
5200 CGF.
Builder.CreateBr(InitEndBB);
5204 CGM.getModule(), OMPRTL___kmpc_barrier),
5207 const Expr *ReductionOp = ReductionOps;
5212 auto EmitCriticalReduction = [&](
auto ReductionGen) {
5213 std::string CriticalName =
getName({
"reduction_critical"});
5221 std::pair<llvm::Function *, llvm::Function *> FnPair =
5224 if (
const auto *CE = dyn_cast<CallExpr>(ReductionOp)) {
5236 (void)LocalScope.Privatize();
5241 EmitCriticalReduction(ReductionGen);
5246 if (
const auto *Cleanup = dyn_cast<ExprWithCleanups>(ReductionClauseExpr))
5249 const Expr *AssignRHS =
nullptr;
5250 if (
const auto *BinOp = dyn_cast<BinaryOperator>(ReductionClauseExpr)) {
5251 if (BinOp->getOpcode() == BO_Assign)
5252 AssignRHS = BinOp->getRHS();
5253 }
else if (
const auto *OpCall =
5254 dyn_cast<CXXOperatorCallExpr>(ReductionClauseExpr)) {
5255 if (OpCall->getOperator() == OO_Equal)
5256 AssignRHS = OpCall->getArg(1);
5260 "Private Variable Reduction : Invalid ReductionOp expression");
5265 const auto *OmpOutDRE =
5267 const auto *OmpInDRE =
5270 OmpOutDRE && OmpInDRE &&
5271 "Private Variable Reduction : LHSExpr/RHSExpr must be DeclRefExprs");
5275 LocalScope.addPrivate(OmpOutVD, SharedLV.
getAddress());
5276 LocalScope.addPrivate(OmpInVD, LHSLV.
getAddress());
5277 (void)LocalScope.Privatize();
5281 EmitCriticalReduction(ReductionGen);
5285 CGM.getModule(), OMPRTL___kmpc_barrier),
5291 llvm::Value *FinalResultVal =
nullptr;
5295 FinalResultAddr = SharedResult;
5309 CGM.getModule(), OMPRTL___kmpc_barrier),
5320 EmitCriticalReduction(OriginalListCombiner);
5372 if (SimpleReduction) {
5374 const auto *IPriv = OrgPrivates.begin();
5375 const auto *ILHS = OrgLHSExprs.begin();
5376 const auto *IRHS = OrgRHSExprs.begin();
5377 for (
const Expr *E : OrgReductionOps) {
5390 FilteredRHSExprs, FilteredReductionOps;
5391 for (
unsigned I : llvm::seq<unsigned>(
5392 std::min(OrgReductionOps.size(), OrgLHSExprs.size()))) {
5394 FilteredPrivates.emplace_back(OrgPrivates[I]);
5395 FilteredLHSExprs.emplace_back(OrgLHSExprs[I]);
5396 FilteredRHSExprs.emplace_back(OrgRHSExprs[I]);
5397 FilteredReductionOps.emplace_back(OrgReductionOps[I]);
5409 auto Size = RHSExprs.size();
5415 llvm::APInt ArraySize(32, Size);
5416 QualType ReductionArrayTy =
C.getConstantArrayType(
5420 CGF.
CreateMemTemp(ReductionArrayTy,
".omp.reduction.red_list");
5421 const auto *IPriv =
Privates.begin();
5423 for (
unsigned I = 0, E = RHSExprs.size(); I < E; ++I, ++IPriv, ++Idx) {
5429 if ((*IPriv)->getType()->isVariablyModifiedType()) {
5433 llvm::Value *Size = CGF.
Builder.CreateIntCast(
5446 Privates, LHSExprs, RHSExprs, ReductionOps);
5449 std::string Name =
getName({
"reduction"});
5456 llvm::Value *ReductionArrayTySize = CGF.
getTypeSize(ReductionArrayTy);
5459 llvm::Value *Args[] = {
5462 CGF.
Builder.getInt32(RHSExprs.size()),
5463 ReductionArrayTySize,
5471 WithNowait ? OMPRTL___kmpc_reduce_nowait : OMPRTL___kmpc_reduce),
5475 llvm::BasicBlock *DefaultBB = CGF.
createBasicBlock(
".omp.reduction.default");
5476 llvm::SwitchInst *SwInst =
5477 CGF.
Builder.CreateSwitch(Res, DefaultBB, 2);
5486 SwInst->addCase(CGF.
Builder.getInt32(1), Case1BB);
5490 llvm::Value *EndArgs[] = {
5498 const auto *IPriv =
Privates.begin();
5499 const auto *ILHS = LHSExprs.begin();
5500 const auto *IRHS = RHSExprs.begin();
5501 for (
const Expr *E : ReductionOps) {
5510 CommonActionTy Action(
5513 CGM.getModule(), WithNowait ? OMPRTL___kmpc_end_reduce_nowait
5514 : OMPRTL___kmpc_end_reduce),
5527 SwInst->addCase(CGF.
Builder.getInt32(2), Case2BB);
5530 auto &&AtomicCodeGen = [Loc,
Privates, LHSExprs, RHSExprs, ReductionOps](
5532 const auto *ILHS = LHSExprs.begin();
5533 const auto *IRHS = RHSExprs.begin();
5534 const auto *IPriv =
Privates.begin();
5535 for (
const Expr *E : ReductionOps) {
5536 const Expr *XExpr =
nullptr;
5537 const Expr *EExpr =
nullptr;
5538 const Expr *UpExpr =
nullptr;
5540 if (
const auto *BO = dyn_cast<BinaryOperator>(E)) {
5541 if (BO->getOpcode() == BO_Assign) {
5542 XExpr = BO->getLHS();
5543 UpExpr = BO->getRHS();
5547 const Expr *RHSExpr = UpExpr;
5550 if (
const auto *ACO = dyn_cast<AbstractConditionalOperator>(
5554 RHSExpr = ACO->getCond();
5556 if (
const auto *BORHS =
5558 EExpr = BORHS->getRHS();
5559 BO = BORHS->getOpcode();
5564 auto &&AtomicRedGen = [BO, VD,
5566 const Expr *EExpr,
const Expr *UpExpr) {
5567 LValue X = CGF.EmitLValue(XExpr);
5570 E = CGF.EmitAnyExpr(EExpr);
5571 CGF.EmitOMPAtomicSimpleUpdateExpr(
5573 llvm::AtomicOrdering::Monotonic, Loc,
5574 [&CGF, UpExpr, VD, Loc](
RValue XRValue) {
5576 Address LHSTemp = CGF.CreateMemTemp(VD->getType());
5577 CGF.emitOMPSimpleStore(
5578 CGF.MakeAddrLValue(LHSTemp, VD->
getType()), XRValue,
5579 VD->getType().getNonReferenceType(), Loc);
5582 return CGF.EmitAnyExpr(UpExpr);
5585 if ((*IPriv)->getType()->isArrayType()) {
5587 const auto *RHSVar =
5590 AtomicRedGen, XExpr, EExpr, UpExpr);
5593 AtomicRedGen(CGF, XExpr, EExpr, UpExpr);
5600 std::string Name = RT.
getName({
"atomic_reduction"});
5609 if ((*IPriv)->getType()->isArrayType()) {
5610 const auto *LHSVar =
5612 const auto *RHSVar =
5617 CritRedGen(CGF,
nullptr,
nullptr,
nullptr);
5628 llvm::Value *EndArgs[] = {
5633 CommonActionTy Action(
nullptr, {},
5635 CGM.getModule(), OMPRTL___kmpc_end_reduce),
5645 assert(OrgLHSExprs.size() == OrgPrivates.size() &&
5646 "PrivateVarReduction: Privates size mismatch");
5647 assert(OrgLHSExprs.size() == OrgReductionOps.size() &&
5648 "PrivateVarReduction: ReductionOps size mismatch");
5649 for (
unsigned I : llvm::seq<unsigned>(
5650 std::min(OrgReductionOps.size(), OrgLHSExprs.size()))) {
5653 OrgRHSExprs[I], OrgReductionOps[I]);
5662 llvm::raw_svector_ostream Out(Buffer);
5670 Out << Prefix << Name <<
"_"
5672 return std::string(Out.str());
5694 Args.emplace_back(&Param);
5695 Args.emplace_back(&ParamOrig);
5696 const auto &FnInfo =
5700 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
5704 Fn->addFnAttr(
"sample-profile-suffix-elision-policy",
"selected");
5705 Fn->setDoesNotRecurse();
5712 llvm::Value *Size =
nullptr;
5755 const Expr *ReductionOp,
5757 const Expr *PrivateRef) {
5766 Args.emplace_back(&ParamInOut);
5767 Args.emplace_back(&ParamIn);
5768 const auto &FnInfo =
5772 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
5776 Fn->addFnAttr(
"sample-profile-suffix-elision-policy",
"selected");
5777 Fn->setDoesNotRecurse();
5780 llvm::Value *Size =
nullptr;
5801 C.getPointerType(LHSVD->getType())->castAs<
PointerType>()));
5808 C.getPointerType(RHSVD->getType())->castAs<
PointerType>()));
5837 Args.emplace_back(&Param);
5838 const auto &FnInfo =
5842 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
5846 Fn->addFnAttr(
"sample-profile-suffix-elision-policy",
"selected");
5847 Fn->setDoesNotRecurse();
5852 llvm::Value *Size =
nullptr;
5887 RecordDecl *RD =
C.buildImplicitRecord(
"kmp_taskred_input_t");
5896 C, RD,
C.getIntTypeForBitwidth(32,
false));
5899 unsigned Size =
Data.ReductionVars.size();
5900 llvm::APInt ArraySize(64, Size);
5902 C.getConstantArrayType(RDType, ArraySize,
nullptr,
5907 Data.ReductionCopies,
Data.ReductionOps);
5908 for (
unsigned Cnt = 0; Cnt < Size; ++Cnt) {
5910 llvm::Value *Idxs[] = {llvm::ConstantInt::get(
CGM.SizeTy, 0),
5911 llvm::ConstantInt::get(
CGM.SizeTy, Cnt)};
5927 llvm::Value *SizeValInChars;
5928 llvm::Value *SizeVal;
5929 std::tie(SizeValInChars, SizeVal) = RCG.
getSizes(Cnt);
5935 bool DelayedCreation = !!SizeVal;
5936 SizeValInChars = CGF.
Builder.CreateIntCast(SizeValInChars,
CGM.SizeTy,
5947 llvm::Value *FiniAddr =
5948 Fini ? Fini : llvm::ConstantPointerNull::get(
CGM.VoidPtrTy);
5953 CGM, Loc, RCG, Cnt,
Data.ReductionOps[Cnt], LHSExprs[Cnt],
5954 RHSExprs[Cnt],
Data.ReductionCopies[Cnt]);
5958 if (DelayedCreation) {
5960 llvm::ConstantInt::get(
CGM.Int32Ty, 1,
true),
5965 if (
Data.IsReductionWithTaskMod) {
5971 llvm::Value *Args[] = {
5973 llvm::ConstantInt::get(
CGM.IntTy,
Data.IsWorksharingReduction ? 1 : 0,
5975 llvm::ConstantInt::get(
CGM.IntTy, Size,
true),
5980 CGM.getModule(), OMPRTL___kmpc_taskred_modifier_init),
5984 llvm::Value *Args[] = {
5987 llvm::ConstantInt::get(
CGM.IntTy, Size,
true),
5991 CGM.getModule(), OMPRTL___kmpc_taskred_init),
5997 bool IsWorksharingReduction) {
6003 llvm::Value *Args[] = {IdentTLoc, GTid,
6004 llvm::ConstantInt::get(
CGM.IntTy,
6005 IsWorksharingReduction ? 1 : 0,
6009 CGM.getModule(), OMPRTL___kmpc_task_reduction_modifier_fini),
6021 llvm::Value *SizeVal = CGF.
Builder.CreateIntCast(Sizes.second,
CGM.SizeTy,
6024 CGF,
CGM.getContext().getSizeType(),
6032 llvm::Value *ReductionsPtr,
6045 CGM.getModule(), OMPRTL___kmpc_task_reduction_get_th_data),
6061 auto &M =
CGM.getModule();
6063 llvm::Value *NumOfElements;
6064 std::tie(NumOfElements, DependenciesArray) =
6066 if (!
Data.Dependences.empty()) {
6067 llvm::Value *DepWaitTaskArgs[7];
6068 DepWaitTaskArgs[0] = UpLoc;
6069 DepWaitTaskArgs[1] = ThreadID;
6070 DepWaitTaskArgs[2] = NumOfElements;
6072 DepWaitTaskArgs[4] = CGF.
Builder.getInt32(0);
6073 DepWaitTaskArgs[5] = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
6074 DepWaitTaskArgs[6] =
6075 llvm::ConstantInt::get(CGF.
Int32Ty,
Data.HasNowaitClause);
6084 M, OMPRTL___kmpc_omp_taskwait_deps_51),
6091 llvm::Value *Args[] = {UpLoc, ThreadID};
6094 OMPBuilder.getOrCreateRuntimeFunction(M, OMPRTL___kmpc_omp_taskwait),
6099 if (
auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.
CapturedStmtInfo))
6100 Region->emitUntiedSwitch(CGF);
6109 InlinedOpenMPRegionRAII Region(CGF,
CodeGen, InnerKind, HasCancel,
6110 InnerKind != OMPD_critical &&
6111 InnerKind != OMPD_master &&
6112 InnerKind != OMPD_masked);
6127 RTCancelKind CancelKind = CancelNoreq;
6128 if (CancelRegion == OMPD_parallel)
6129 CancelKind = CancelParallel;
6130 else if (CancelRegion == OMPD_for)
6131 CancelKind = CancelLoop;
6132 else if (CancelRegion == OMPD_sections)
6133 CancelKind = CancelSections;
6135 assert(CancelRegion == OMPD_taskgroup);
6136 CancelKind = CancelTaskgroup;
6148 if (
auto *OMPRegionInfo =
6152 if (CancelRegion == OMPD_taskgroup || OMPRegionInfo->hasCancel()) {
6153 llvm::Value *Args[] = {
6159 CGM.getModule(), OMPRTL___kmpc_cancellationpoint),
6168 CGF.
Builder.CreateCondBr(
Cmp, ExitBB, ContBB);
6170 if (CancelRegion == OMPD_parallel)
6188 auto &M =
CGM.getModule();
6189 if (
auto *OMPRegionInfo =
6191 auto &&ThenGen = [
this, &M, Loc, CancelRegion,
6194 llvm::Value *Args[] = {
6198 llvm::Value *
Result = CGF.EmitRuntimeCall(
6199 OMPBuilder.getOrCreateRuntimeFunction(M, OMPRTL___kmpc_cancel), Args);
6204 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(
".cancel.exit");
6205 llvm::BasicBlock *ContBB = CGF.createBasicBlock(
".cancel.continue");
6206 llvm::Value *
Cmp = CGF.Builder.CreateIsNotNull(
Result);
6207 CGF.Builder.CreateCondBr(
Cmp, ExitBB, ContBB);
6208 CGF.EmitBlock(ExitBB);
6209 if (CancelRegion == OMPD_parallel)
6213 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind());
6214 CGF.EmitBranchThroughCleanup(CancelDest);
6215 CGF.EmitBlock(ContBB,
true);
6233 OMPUsesAllocatorsActionTy(
6234 ArrayRef<std::pair<const Expr *, const Expr *>> Allocators)
6235 : Allocators(Allocators) {}
6239 for (
const auto &AllocatorData : Allocators) {
6241 CGF, AllocatorData.first, AllocatorData.second);
6244 void Exit(CodeGenFunction &CGF)
override {
6247 for (
const auto &AllocatorData : Allocators) {
6249 AllocatorData.first);
6257 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
6259 assert(!ParentName.empty() &&
"Invalid target entry parent name!");
6263 for (
unsigned I = 0, E =
C->getNumberOfAllocators(); I < E; ++I) {
6270 OMPUsesAllocatorsActionTy UsesAllocatorAction(Allocators);
6271 CodeGen.setAction(UsesAllocatorAction);
6277 const Expr *Allocator,
6278 const Expr *AllocatorTraits) {
6280 ThreadId = CGF.
Builder.CreateIntCast(ThreadId, CGF.
IntTy,
true);
6282 llvm::Value *MemSpaceHandle = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
6283 llvm::Value *NumTraits = llvm::ConstantInt::get(
6287 .getLimitedValue());
6294 llvm::Value *Traits =
Addr.emitRawPointer(CGF);
6296 llvm::Value *AllocatorVal =
6298 CGM.getModule(), OMPRTL___kmpc_init_allocator),
6299 {ThreadId, MemSpaceHandle, NumTraits, Traits});
6311 const Expr *Allocator) {
6313 ThreadId = CGF.
Builder.CreateIntCast(ThreadId, CGF.
IntTy,
true);
6315 llvm::Value *AllocatorVal =
6322 OMPRTL___kmpc_destroy_allocator),
6323 {ThreadId, AllocatorVal});
6328 llvm::OpenMPIRBuilder::TargetKernelDefaultAttrs &Attrs) {
6329 assert(Attrs.MaxTeams.size() == 1 && Attrs.MaxThreads.size() == 1 &&
6330 "invalid default attrs structure");
6331 int32_t &MaxTeamsVal = Attrs.MaxTeams.front();
6332 int32_t &MaxThreadsVal = Attrs.MaxThreads.front();
6339 for (
auto *A :
C->getAttrs()) {
6340 int32_t AttrMinThreadsVal = 1, AttrMaxThreadsVal = -1;
6341 int32_t AttrMinBlocksVal = 1, AttrMaxBlocksVal = -1;
6342 if (
auto *
Attr = dyn_cast<CUDALaunchBoundsAttr>(A))
6343 CGM.handleCUDALaunchBoundsAttr(
nullptr,
Attr, &AttrMaxThreadsVal,
6344 &AttrMinBlocksVal, &AttrMaxBlocksVal);
6345 else if (
auto *
Attr = dyn_cast<AMDGPUFlatWorkGroupSizeAttr>(A))
6346 CGM.handleAMDGPUFlatWorkGroupSizeAttr(
6347 nullptr,
Attr,
nullptr, &AttrMinThreadsVal,
6348 &AttrMaxThreadsVal);
6352 Attrs.MinThreads = std::max(Attrs.MinThreads, AttrMinThreadsVal);
6353 if (AttrMaxThreadsVal > 0)
6354 MaxThreadsVal = MaxThreadsVal > 0
6355 ? std::min(MaxThreadsVal, AttrMaxThreadsVal)
6356 : AttrMaxThreadsVal;
6357 Attrs.MinTeams = std::max(Attrs.MinTeams, AttrMinBlocksVal);
6358 if (AttrMaxBlocksVal > 0)
6359 MaxTeamsVal = MaxTeamsVal > 0 ? std::min(MaxTeamsVal, AttrMaxBlocksVal)
6367 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
6370 llvm::TargetRegionEntryInfo EntryInfo =
6374 llvm::OpenMPIRBuilder::FunctionGenCallback &&GenerateOutlinedFunction =
6375 [&CGF, &D, &
CodeGen,
this](StringRef EntryFnName) {
6376 const CapturedStmt &CS = *D.getCapturedStmt(OMPD_target);
6378 CGOpenMPTargetRegionInfo CGInfo(CS,
CodeGen, EntryFnName);
6380 if (
CGM.getLangOpts().OpenMPIsTargetDevice && !
isGPU())
6385 cantFail(
OMPBuilder.emitTargetRegionFunction(
6386 EntryInfo, GenerateOutlinedFunction, IsOffloadEntry, OutlinedFn,
6392 CGM.getTargetCodeGenInfo().setTargetAttributes(
nullptr, OutlinedFn,
CGM);
6395 for (
auto *A :
C->getAttrs()) {
6396 if (
auto *
Attr = dyn_cast<AMDGPUWavesPerEUAttr>(A))
6397 CGM.handleAMDGPUWavesPerEUAttr(OutlinedFn,
Attr);
6416 while (
const auto *
C = dyn_cast_or_null<CompoundStmt>(Child)) {
6418 for (
const Stmt *S :
C->body()) {
6419 if (
const auto *E = dyn_cast<Expr>(S)) {
6428 if (
const auto *DS = dyn_cast<DeclStmt>(S)) {
6429 if (llvm::all_of(DS->decls(), [](
const Decl *D) {
6430 if (isa<EmptyDecl>(D) || isa<DeclContext>(D) ||
6431 isa<TypeDecl>(D) || isa<PragmaCommentDecl>(D) ||
6432 isa<PragmaDetectMismatchDecl>(D) || isa<UsingDecl>(D) ||
6433 isa<UsingDirectiveDecl>(D) ||
6434 isa<OMPDeclareReductionDecl>(D) ||
6435 isa<OMPThreadPrivateDecl>(D) || isa<OMPAllocateDecl>(D))
6437 const auto *VD = dyn_cast<VarDecl>(D);
6440 return VD->hasGlobalStorage() || !VD->isUsed();
6450 Child = Child->IgnoreContainers();
6457 int32_t &MaxTeamsVal) {
6461 "Expected target-based executable directive.");
6462 switch (DirectiveKind) {
6464 const auto *CS = D.getInnermostCapturedStmt();
6467 const Stmt *ChildStmt =
6469 if (
const auto *NestedDir =
6470 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) {
6479 MinTeamsVal = MaxTeamsVal = Constant->getExtValue();
6482 MinTeamsVal = MaxTeamsVal = 0;
6485 MinTeamsVal = MaxTeamsVal = 1;
6489 MinTeamsVal = MaxTeamsVal = -1;
6492 case OMPD_target_teams_loop:
6493 case OMPD_target_teams:
6494 case OMPD_target_teams_distribute:
6495 case OMPD_target_teams_distribute_simd:
6496 case OMPD_target_teams_distribute_parallel_for:
6497 case OMPD_target_teams_distribute_parallel_for_simd: {
6499 const Expr *NumTeams =
6503 MinTeamsVal = MaxTeamsVal = Constant->getExtValue();
6506 MinTeamsVal = MaxTeamsVal = 0;
6509 case OMPD_target_parallel:
6510 case OMPD_target_parallel_for:
6511 case OMPD_target_parallel_for_simd:
6512 case OMPD_target_parallel_loop:
6513 case OMPD_target_simd:
6514 MinTeamsVal = MaxTeamsVal = 1;
6518 case OMPD_parallel_for:
6519 case OMPD_parallel_loop:
6520 case OMPD_parallel_master:
6521 case OMPD_parallel_sections:
6523 case OMPD_parallel_for_simd:
6525 case OMPD_cancellation_point:
6527 case OMPD_threadprivate:
6538 case OMPD_taskyield:
6541 case OMPD_taskgroup:
6547 case OMPD_target_data:
6548 case OMPD_target_exit_data:
6549 case OMPD_target_enter_data:
6550 case OMPD_distribute:
6551 case OMPD_distribute_simd:
6552 case OMPD_distribute_parallel_for:
6553 case OMPD_distribute_parallel_for_simd:
6554 case OMPD_teams_distribute:
6555 case OMPD_teams_distribute_simd:
6556 case OMPD_teams_distribute_parallel_for:
6557 case OMPD_teams_distribute_parallel_for_simd:
6558 case OMPD_target_update:
6559 case OMPD_declare_simd:
6560 case OMPD_declare_variant:
6561 case OMPD_begin_declare_variant:
6562 case OMPD_end_declare_variant:
6563 case OMPD_declare_target:
6564 case OMPD_end_declare_target:
6565 case OMPD_declare_reduction:
6566 case OMPD_declare_mapper:
6568 case OMPD_taskloop_simd:
6569 case OMPD_master_taskloop:
6570 case OMPD_master_taskloop_simd:
6571 case OMPD_parallel_master_taskloop:
6572 case OMPD_parallel_master_taskloop_simd:
6574 case OMPD_metadirective:
6580 llvm_unreachable(
"Unexpected directive kind.");
6586 "Clauses associated with the teams directive expected to be emitted "
6587 "only for the host!");
6589 int32_t MinNT = -1, MaxNT = -1;
6590 const Expr *NumTeams =
6592 if (NumTeams !=
nullptr) {
6595 switch (DirectiveKind) {
6597 const auto *CS = D.getInnermostCapturedStmt();
6598 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6602 return Bld.CreateIntCast(NumTeamsVal, CGF.
Int32Ty,
6605 case OMPD_target_teams:
6606 case OMPD_target_teams_distribute:
6607 case OMPD_target_teams_distribute_simd:
6608 case OMPD_target_teams_distribute_parallel_for:
6609 case OMPD_target_teams_distribute_parallel_for_simd: {
6613 return Bld.CreateIntCast(NumTeamsVal, CGF.
Int32Ty,
6621 assert(MinNT == MaxNT &&
"Num threads ranges require handling here.");
6622 return llvm::ConstantInt::getSigned(CGF.
Int32Ty, MinNT);
6630 const Expr **E, int32_t &UpperBound,
6631 bool UpperBoundOnly, llvm::Value **CondVal) {
6634 const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child);
6641 if (CondVal && Dir->hasClausesOfKind<
OMPIfClause>()) {
6642 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6645 for (
const auto *
C : Dir->getClausesOfKind<
OMPIfClause>()) {
6646 if (
C->getNameModifier() == OMPD_unknown ||
6647 C->getNameModifier() == OMPD_parallel) {
6662 if (
const auto *PreInit =
6664 for (
const auto *I : PreInit->decls()) {
6665 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
6681 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6683 const auto *NumThreadsClause =
6685 const Expr *NTExpr = NumThreadsClause->getNumThreads();
6686 if (NTExpr->isIntegerConstantExpr(CGF.
getContext()))
6687 if (
auto Constant = NTExpr->getIntegerConstantExpr(CGF.
getContext()))
6690 ? Constant->getZExtValue()
6691 : std::min(UpperBound,
6692 static_cast<int32_t
>(Constant->getZExtValue()));
6695 if (UpperBound == -1)
6700 if (
const auto *PreInit =
6701 cast_or_null<DeclStmt>(NumThreadsClause->getPreInitStmt())) {
6702 for (
const auto *I : PreInit->decls()) {
6703 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
6722 bool UpperBoundOnly, llvm::Value **CondVal,
const Expr **ThreadLimitExpr) {
6723 assert((!CGF.
getLangOpts().OpenMPIsTargetDevice || UpperBoundOnly) &&
6724 "Clauses associated with the teams directive expected to be emitted "
6725 "only for the host!");
6728 "Expected target-based executable directive.");
6730 const Expr *NT =
nullptr;
6731 const Expr **NTPtr = UpperBoundOnly ?
nullptr : &NT;
6733 auto CheckForConstExpr = [&](
const Expr *E,
const Expr **EPtr) {
6736 UpperBound = UpperBound ? Constant->getZExtValue()
6737 : std::min(UpperBound,
6738 int32_t(Constant->getZExtValue()));
6742 if (UpperBound == -1)
6748 auto ReturnSequential = [&]() {
6753 switch (DirectiveKind) {
6756 getNumThreads(CGF, CS, NTPtr, UpperBound, UpperBoundOnly, CondVal);
6762 if (
const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) {
6764 ThreadLimitClause = TLC;
6765 if (ThreadLimitExpr) {
6766 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6770 ThreadLimitClause->getThreadLimit().front()->getSourceRange());
6771 if (
const auto *PreInit =
6772 cast_or_null<DeclStmt>(ThreadLimitClause->getPreInitStmt())) {
6773 for (
const auto *I : PreInit->decls()) {
6774 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
6786 if (ThreadLimitClause)
6787 CheckForConstExpr(ThreadLimitClause->getThreadLimit().front(),
6789 if (
const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) {
6792 CS = Dir->getInnermostCapturedStmt();
6795 Dir = dyn_cast_or_null<OMPExecutableDirective>(Child);
6798 CS = Dir->getInnermostCapturedStmt();
6799 getNumThreads(CGF, CS, NTPtr, UpperBound, UpperBoundOnly, CondVal);
6801 return ReturnSequential();
6805 case OMPD_target_teams: {
6809 CheckForConstExpr(ThreadLimitClause->getThreadLimit().front(),
6813 getNumThreads(CGF, CS, NTPtr, UpperBound, UpperBoundOnly, CondVal);
6816 if (
const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) {
6817 if (Dir->getDirectiveKind() == OMPD_distribute) {
6818 CS = Dir->getInnermostCapturedStmt();
6819 getNumThreads(CGF, CS, NTPtr, UpperBound, UpperBoundOnly, CondVal);
6824 case OMPD_target_teams_distribute:
6828 CheckForConstExpr(ThreadLimitClause->getThreadLimit().front(),
6831 getNumThreads(CGF, D.getInnermostCapturedStmt(), NTPtr, UpperBound,
6832 UpperBoundOnly, CondVal);
6834 case OMPD_target_teams_loop:
6835 case OMPD_target_parallel_loop:
6836 case OMPD_target_parallel:
6837 case OMPD_target_parallel_for:
6838 case OMPD_target_parallel_for_simd:
6839 case OMPD_target_teams_distribute_parallel_for:
6840 case OMPD_target_teams_distribute_parallel_for_simd: {
6841 if (CondVal && D.hasClausesOfKind<
OMPIfClause>()) {
6843 for (
const auto *
C : D.getClausesOfKind<
OMPIfClause>()) {
6844 if (
C->getNameModifier() == OMPD_unknown ||
6845 C->getNameModifier() == OMPD_parallel) {
6855 return ReturnSequential();
6865 CheckForConstExpr(ThreadLimitClause->getThreadLimit().front(),
6871 CheckForConstExpr(NumThreadsClause->getNumThreads(),
nullptr);
6872 return NumThreadsClause->getNumThreads();
6876 case OMPD_target_teams_distribute_simd:
6877 case OMPD_target_simd:
6878 return ReturnSequential();
6882 llvm_unreachable(
"Unsupported directive kind.");
6887 llvm::Value *NumThreadsVal =
nullptr;
6888 llvm::Value *CondVal =
nullptr;
6889 llvm::Value *ThreadLimitVal =
nullptr;
6890 const Expr *ThreadLimitExpr =
nullptr;
6891 int32_t UpperBound = -1;
6894 CGF, D, UpperBound,
false, &CondVal,
6898 if (ThreadLimitExpr) {
6901 ThreadLimitVal = CGF.
Builder.CreateIntCast(ThreadLimitVal, CGF.
Int32Ty,
6906 if (UpperBound == 1) {
6907 NumThreadsVal = CGF.
Builder.getInt32(UpperBound);
6910 NumThreadsVal = CGF.
Builder.CreateIntCast(NumThreadsVal, CGF.
Int32Ty,
6912 }
else if (ThreadLimitVal) {
6915 NumThreadsVal = ThreadLimitVal;
6916 ThreadLimitVal =
nullptr;
6919 assert(!ThreadLimitVal &&
"Default not applicable with thread limit value");
6920 NumThreadsVal = CGF.
Builder.getInt32(0);
6927 NumThreadsVal = CGF.
Builder.CreateSelect(CondVal, NumThreadsVal,
6933 if (ThreadLimitVal) {
6934 NumThreadsVal = CGF.
Builder.CreateSelect(
6935 CGF.
Builder.CreateICmpULT(ThreadLimitVal, NumThreadsVal),
6936 ThreadLimitVal, NumThreadsVal);
6939 return NumThreadsVal;
6949class MappableExprsHandler {
6955 struct AttachPtrExprComparator {
6956 const MappableExprsHandler &Handler;
6958 mutable llvm::DenseMap<std::pair<const Expr *, const Expr *>,
bool>
6959 CachedEqualityComparisons;
6961 AttachPtrExprComparator(
const MappableExprsHandler &H) : Handler(H) {}
6962 AttachPtrExprComparator() =
delete;
6965 bool operator()(
const Expr *LHS,
const Expr *RHS)
const {
6970 const auto ItLHS = Handler.AttachPtrComponentDepthMap.find(LHS);
6971 const auto ItRHS = Handler.AttachPtrComponentDepthMap.find(RHS);
6973 std::optional<size_t> DepthLHS =
6974 (ItLHS != Handler.AttachPtrComponentDepthMap.end()) ? ItLHS->second
6976 std::optional<size_t> DepthRHS =
6977 (ItRHS != Handler.AttachPtrComponentDepthMap.end()) ? ItRHS->second
6981 if (!DepthLHS.has_value() && !DepthRHS.has_value()) {
6983 if (areEqual(LHS, RHS))
6986 return wasComputedBefore(LHS, RHS);
6988 if (!DepthLHS.has_value())
6990 if (!DepthRHS.has_value())
6994 if (DepthLHS.value() != DepthRHS.value())
6995 return DepthLHS.value() < DepthRHS.value();
6998 if (areEqual(LHS, RHS))
7001 return wasComputedBefore(LHS, RHS);
7007 bool areEqual(
const Expr *LHS,
const Expr *RHS)
const {
7009 const auto CachedResultIt = CachedEqualityComparisons.find({LHS, RHS});
7010 if (CachedResultIt != CachedEqualityComparisons.end())
7011 return CachedResultIt->second;
7025 bool wasComputedBefore(
const Expr *LHS,
const Expr *RHS)
const {
7026 const size_t &OrderLHS = Handler.AttachPtrComputationOrderMap.at(LHS);
7027 const size_t &OrderRHS = Handler.AttachPtrComputationOrderMap.at(RHS);
7029 return OrderLHS < OrderRHS;
7038 bool areSemanticallyEqual(
const Expr *LHS,
const Expr *RHS)
const {
7060 if (
const auto *LD = dyn_cast<DeclRefExpr>(LHS)) {
7061 const auto *RD = dyn_cast<DeclRefExpr>(RHS);
7064 return LD->getDecl()->getCanonicalDecl() ==
7065 RD->getDecl()->getCanonicalDecl();
7069 if (
const auto *LA = dyn_cast<ArraySubscriptExpr>(LHS)) {
7070 const auto *RA = dyn_cast<ArraySubscriptExpr>(RHS);
7073 return areSemanticallyEqual(LA->getBase(), RA->getBase()) &&
7074 areSemanticallyEqual(LA->getIdx(), RA->getIdx());
7078 if (
const auto *LM = dyn_cast<MemberExpr>(LHS)) {
7079 const auto *RM = dyn_cast<MemberExpr>(RHS);
7082 if (LM->getMemberDecl()->getCanonicalDecl() !=
7083 RM->getMemberDecl()->getCanonicalDecl())
7085 return areSemanticallyEqual(LM->getBase(), RM->getBase());
7089 if (
const auto *LU = dyn_cast<UnaryOperator>(LHS)) {
7090 const auto *RU = dyn_cast<UnaryOperator>(RHS);
7093 if (LU->getOpcode() != RU->getOpcode())
7095 return areSemanticallyEqual(LU->getSubExpr(), RU->getSubExpr());
7099 if (
const auto *LB = dyn_cast<BinaryOperator>(LHS)) {
7100 const auto *RB = dyn_cast<BinaryOperator>(RHS);
7103 if (LB->getOpcode() != RB->getOpcode())
7105 return areSemanticallyEqual(LB->getLHS(), RB->getLHS()) &&
7106 areSemanticallyEqual(LB->getRHS(), RB->getRHS());
7112 if (
const auto *LAS = dyn_cast<ArraySectionExpr>(LHS)) {
7113 const auto *RAS = dyn_cast<ArraySectionExpr>(RHS);
7116 return areSemanticallyEqual(LAS->getBase(), RAS->getBase()) &&
7117 areSemanticallyEqual(LAS->getLowerBound(),
7118 RAS->getLowerBound()) &&
7119 areSemanticallyEqual(LAS->getLength(), RAS->getLength());
7123 if (
const auto *LC = dyn_cast<CastExpr>(LHS)) {
7124 const auto *RC = dyn_cast<CastExpr>(RHS);
7127 if (LC->getCastKind() != RC->getCastKind())
7129 return areSemanticallyEqual(LC->getSubExpr(), RC->getSubExpr());
7137 if (
const auto *LI = dyn_cast<IntegerLiteral>(LHS)) {
7138 const auto *RI = dyn_cast<IntegerLiteral>(RHS);
7141 return LI->getValue() == RI->getValue();
7145 if (
const auto *LC = dyn_cast<CharacterLiteral>(LHS)) {
7146 const auto *RC = dyn_cast<CharacterLiteral>(RHS);
7149 return LC->getValue() == RC->getValue();
7153 if (
const auto *LF = dyn_cast<FloatingLiteral>(LHS)) {
7154 const auto *RF = dyn_cast<FloatingLiteral>(RHS);
7158 return LF->getValue().bitwiseIsEqual(RF->getValue());
7162 if (
const auto *LS = dyn_cast<StringLiteral>(LHS)) {
7163 const auto *RS = dyn_cast<StringLiteral>(RHS);
7166 return LS->getString() == RS->getString();
7174 if (
const auto *LB = dyn_cast<CXXBoolLiteralExpr>(LHS)) {
7175 const auto *RB = dyn_cast<CXXBoolLiteralExpr>(RHS);
7178 return LB->getValue() == RB->getValue();
7187 static unsigned getFlagMemberOffset() {
7188 unsigned Offset = 0;
7189 for (uint64_t Remain =
7190 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
7191 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF);
7192 !(Remain & 1); Remain = Remain >> 1)
7199 class MappingExprInfo {
7201 const ValueDecl *MapDecl =
nullptr;
7204 const Expr *MapExpr =
nullptr;
7207 MappingExprInfo(
const ValueDecl *MapDecl,
const Expr *MapExpr =
nullptr)
7208 : MapDecl(MapDecl), MapExpr(MapExpr) {}
7210 const ValueDecl *getMapDecl()
const {
return MapDecl; }
7211 const Expr *getMapExpr()
const {
return MapExpr; }
7214 using DeviceInfoTy = llvm::OpenMPIRBuilder::DeviceInfoTy;
7215 using MapBaseValuesArrayTy = llvm::OpenMPIRBuilder::MapValuesArrayTy;
7216 using MapValuesArrayTy = llvm::OpenMPIRBuilder::MapValuesArrayTy;
7217 using MapFlagsArrayTy = llvm::OpenMPIRBuilder::MapFlagsArrayTy;
7218 using MapDimArrayTy = llvm::OpenMPIRBuilder::MapDimArrayTy;
7219 using MapNonContiguousArrayTy =
7220 llvm::OpenMPIRBuilder::MapNonContiguousArrayTy;
7221 using MapExprsArrayTy = SmallVector<MappingExprInfo, 4>;
7222 using MapValueDeclsArrayTy = SmallVector<const ValueDecl *, 4>;
7226 bool ,
const ValueDecl *,
const Expr *>;
7227 using MapDataArrayTy = SmallVector<MapData, 4>;
7232 struct MapCombinedInfoTy : llvm::OpenMPIRBuilder::MapInfosTy {
7233 MapExprsArrayTy Exprs;
7234 MapValueDeclsArrayTy Mappers;
7235 MapValueDeclsArrayTy DevicePtrDecls;
7238 void append(MapCombinedInfoTy &CurInfo) {
7239 Exprs.append(CurInfo.Exprs.begin(), CurInfo.Exprs.end());
7240 DevicePtrDecls.append(CurInfo.DevicePtrDecls.begin(),
7241 CurInfo.DevicePtrDecls.end());
7242 Mappers.append(CurInfo.Mappers.begin(), CurInfo.Mappers.end());
7243 llvm::OpenMPIRBuilder::MapInfosTy::append(CurInfo);
7251 struct StructRangeInfoTy {
7252 MapCombinedInfoTy PreliminaryMapData;
7253 std::pair<
unsigned , Address > LowestElem = {
7255 std::pair<
unsigned , Address > HighestElem = {
7259 bool IsArraySection =
false;
7260 bool HasCompleteRecord =
false;
7265 struct AttachInfoTy {
7268 const ValueDecl *AttachPtrDecl =
nullptr;
7269 const Expr *AttachMapExpr =
nullptr;
7271 bool isValid()
const {
7278 bool hasAttachEntryForCapturedVar(
const ValueDecl *VD)
const {
7279 for (
const auto &AttachEntry : AttachPtrExprMap) {
7280 if (AttachEntry.second) {
7283 if (
const auto *DRE = dyn_cast<DeclRefExpr>(AttachEntry.second))
7284 if (DRE->getDecl() == VD)
7292 const Expr *getAttachPtrExpr(
7295 const auto It = AttachPtrExprMap.find(Components);
7296 if (It != AttachPtrExprMap.end())
7307 ArrayRef<OpenMPMapModifierKind> MapModifiers;
7308 ArrayRef<OpenMPMotionModifierKind> MotionModifiers;
7309 bool ReturnDevicePointer =
false;
7310 bool IsImplicit =
false;
7311 const ValueDecl *Mapper =
nullptr;
7312 const Expr *VarRef =
nullptr;
7313 bool ForDeviceAddr =
false;
7314 bool HasUdpFbNullify =
false;
7316 MapInfo() =
default;
7320 ArrayRef<OpenMPMapModifierKind> MapModifiers,
7321 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
7322 bool ReturnDevicePointer,
bool IsImplicit,
7323 const ValueDecl *Mapper =
nullptr,
const Expr *VarRef =
nullptr,
7324 bool ForDeviceAddr =
false,
bool HasUdpFbNullify =
false)
7325 : Components(Components), MapType(MapType), MapModifiers(MapModifiers),
7326 MotionModifiers(MotionModifiers),
7327 ReturnDevicePointer(ReturnDevicePointer), IsImplicit(IsImplicit),
7328 Mapper(Mapper), VarRef(VarRef), ForDeviceAddr(ForDeviceAddr),
7329 HasUdpFbNullify(HasUdpFbNullify) {}
7334 llvm::PointerUnion<
const OMPExecutableDirective *,
7335 const OMPDeclareMapperDecl *>
7339 CodeGenFunction &CGF;
7344 llvm::DenseMap<CanonicalDeclPtr<const VarDecl>,
bool> FirstPrivateDecls;
7347 llvm::SmallSet<OpenMPDefaultmapClauseKind, 4> DefaultmapFirstprivateKinds;
7353 SmallVector<OMPClauseMappableExprCommon::MappableExprComponentListRef, 4>>
7360 SmallVector<OMPClauseMappableExprCommon::MappableExprComponentListRef, 4>>
7364 llvm::DenseMap<const ValueDecl *, const OMPMapClause *> LambdasMap;
7379 llvm::DenseMap<const Expr *, std::optional<size_t>>
7380 AttachPtrComponentDepthMap = {{
nullptr, std::nullopt}};
7384 llvm::DenseMap<const Expr *, size_t> AttachPtrComputationOrderMap = {
7389 AttachPtrExprComparator AttachPtrComparator;
7391 llvm::Value *getExprTypeSize(
const Expr *E)
const {
7395 if (
const auto *OAE = dyn_cast<OMPArrayShapingExpr>(E)) {
7397 CGF.
getTypeSize(OAE->getBase()->getType()->getPointeeType());
7398 for (
const Expr *SE : OAE->getDimensions()) {
7409 if (
const auto *RefTy = ExprTy->
getAs<ReferenceType>())
7415 if (
const auto *OAE = dyn_cast<ArraySectionExpr>(E)) {
7417 OAE->getBase()->IgnoreParenImpCasts())
7423 if (!OAE->getLength() && OAE->getColonLocFirst().isValid() &&
7424 !OAE->getLowerBound())
7427 llvm::Value *ElemSize;
7428 if (
const auto *PTy = BaseTy->
getAs<PointerType>()) {
7429 ElemSize = CGF.
getTypeSize(PTy->getPointeeType().getCanonicalType());
7432 assert(ATy &&
"Expecting array type if not a pointer type.");
7433 ElemSize = CGF.
getTypeSize(ATy->getElementType().getCanonicalType());
7438 if (!OAE->getLength() && OAE->getColonLocFirst().isInvalid())
7441 if (
const Expr *LenExpr = OAE->getLength()) {
7445 LenExpr->getExprLoc());
7446 return CGF.
Builder.CreateNUWMul(LengthVal, ElemSize);
7448 assert(!OAE->getLength() && OAE->getColonLocFirst().isValid() &&
7449 OAE->getLowerBound() &&
"expected array_section[lb:].");
7455 OAE->getLowerBound()->getExprLoc());
7456 LBVal = CGF.
Builder.CreateNUWMul(LBVal, ElemSize);
7457 llvm::Value *
Cmp = CGF.
Builder.CreateICmpUGT(LengthVal, LBVal);
7458 llvm::Value *TrueVal = CGF.
Builder.CreateNUWSub(LengthVal, LBVal);
7459 LengthVal = CGF.
Builder.CreateSelect(
7460 Cmp, TrueVal, llvm::ConstantInt::get(CGF.
SizeTy, 0));
7470 OpenMPOffloadMappingFlags getMapTypeBits(
7472 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
bool IsImplicit,
7473 bool AddPtrFlag,
bool AddIsTargetParamFlag,
bool IsNonContiguous)
const {
7474 OpenMPOffloadMappingFlags Bits =
7475 IsImplicit ? OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT
7476 : OpenMPOffloadMappingFlags::OMP_MAP_NONE;
7478 case OMPC_MAP_alloc:
7479 case OMPC_MAP_release:
7486 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_TO;
7489 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_FROM;
7491 case OMPC_MAP_tofrom:
7492 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_TO |
7493 OpenMPOffloadMappingFlags::OMP_MAP_FROM;
7495 case OMPC_MAP_delete:
7496 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_DELETE;
7499 llvm_unreachable(
"Unexpected map type!");
7502 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ;
7503 if (AddIsTargetParamFlag)
7504 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM;
7505 if (llvm::is_contained(MapModifiers, OMPC_MAP_MODIFIER_always))
7506 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_ALWAYS;
7507 if (llvm::is_contained(MapModifiers, OMPC_MAP_MODIFIER_close))
7508 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_CLOSE;
7509 if (llvm::is_contained(MapModifiers, OMPC_MAP_MODIFIER_present) ||
7510 llvm::is_contained(MotionModifiers, OMPC_MOTION_MODIFIER_present))
7511 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_PRESENT;
7512 if (llvm::is_contained(MapModifiers, OMPC_MAP_MODIFIER_ompx_hold))
7513 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_OMPX_HOLD;
7514 if (IsNonContiguous)
7515 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_NON_CONTIG;
7521 bool isFinalArraySectionExpression(
const Expr *E)
const {
7522 const auto *OASE = dyn_cast<ArraySectionExpr>(E);
7529 if (OASE->getColonLocFirst().isInvalid())
7532 const Expr *Length = OASE->getLength();
7539 OASE->getBase()->IgnoreParenImpCasts())
7541 if (
const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.
getTypePtr()))
7542 return ATy->getSExtSize() != 1;
7554 llvm::APSInt ConstLength =
Result.Val.getInt();
7555 return ConstLength.getSExtValue() != 1;
7562 void emitAttachEntry(CodeGenFunction &CGF, MapCombinedInfoTy &CombinedInfo,
7563 const AttachInfoTy &AttachInfo)
const {
7564 assert(AttachInfo.isValid() &&
7565 "Expected valid attach pointer/pointee information!");
7569 llvm::Value *PointerSize = CGF.
Builder.CreateIntCast(
7570 llvm::ConstantInt::get(
7576 CombinedInfo.Exprs.emplace_back(AttachInfo.AttachPtrDecl,
7577 AttachInfo.AttachMapExpr);
7578 CombinedInfo.BasePointers.push_back(
7579 AttachInfo.AttachPtrAddr.emitRawPointer(CGF));
7580 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
7581 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
7582 CombinedInfo.Pointers.push_back(
7583 AttachInfo.AttachPteeAddr.emitRawPointer(CGF));
7584 CombinedInfo.Sizes.push_back(PointerSize);
7585 CombinedInfo.Types.push_back(OpenMPOffloadMappingFlags::OMP_MAP_ATTACH);
7586 CombinedInfo.Mappers.push_back(
nullptr);
7587 CombinedInfo.NonContigInfo.Dims.push_back(1);
7594 class CopyOverlappedEntryGaps {
7595 CodeGenFunction &CGF;
7596 MapCombinedInfoTy &CombinedInfo;
7597 OpenMPOffloadMappingFlags Flags = OpenMPOffloadMappingFlags::OMP_MAP_NONE;
7598 const ValueDecl *MapDecl =
nullptr;
7599 const Expr *MapExpr =
nullptr;
7601 bool IsNonContiguous =
false;
7605 const RecordDecl *LastParent =
nullptr;
7607 unsigned LastIndex = -1u;
7611 CopyOverlappedEntryGaps(CodeGenFunction &CGF,
7612 MapCombinedInfoTy &CombinedInfo,
7613 OpenMPOffloadMappingFlags Flags,
7614 const ValueDecl *MapDecl,
const Expr *MapExpr,
7615 Address BP, Address LB,
bool IsNonContiguous,
7617 : CGF(CGF), CombinedInfo(CombinedInfo), Flags(Flags), MapDecl(MapDecl),
7618 MapExpr(MapExpr), BP(BP), IsNonContiguous(IsNonContiguous),
7619 DimSize(DimSize), LB(LB) {}
7622 const OMPClauseMappableExprCommon::MappableComponent &MC,
7623 const FieldDecl *FD,
7624 llvm::function_ref<LValue(CodeGenFunction &,
const MemberExpr *)>
7625 EmitMemberExprBase) {
7635 LValue BaseLVal = EmitMemberExprBase(CGF, ME);
7647 copyUntilField(FD, ComponentLB);
7650 if (((int64_t)FieldOffset - (int64_t)Cursor) > 0)
7651 copyUntilField(FD, ComponentLB);
7653 Cursor = FieldOffset + FieldSize;
7658 void copyUntilField(
const FieldDecl *FD, Address ComponentLB) {
7661 llvm::Value *
Size = CGF.
Builder.CreatePtrDiff(ComponentLBPtr, LBPtr);
7662 copySizedChunk(LBPtr, Size);
7665 void copyUntilEnd(Address HB) {
7667 const ASTRecordLayout &RL =
7675 copySizedChunk(LBPtr, Size);
7678 void copySizedChunk(llvm::Value *Base, llvm::Value *Size) {
7679 CombinedInfo.Exprs.emplace_back(MapDecl, MapExpr);
7681 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
7682 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
7683 CombinedInfo.Pointers.push_back(Base);
7684 CombinedInfo.Sizes.push_back(
7686 CombinedInfo.Types.push_back(Flags);
7687 CombinedInfo.Mappers.push_back(
nullptr);
7688 CombinedInfo.NonContigInfo.Dims.push_back(IsNonContiguous ? DimSize : 1);
7697 void generateInfoForComponentList(
7699 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
7701 MapCombinedInfoTy &CombinedInfo,
7702 MapCombinedInfoTy &StructBaseCombinedInfo,
7703 StructRangeInfoTy &PartialStruct, AttachInfoTy &AttachInfo,
7704 bool IsFirstComponentList,
bool IsImplicit,
7705 bool GenerateAllInfoForClauses,
const ValueDecl *Mapper =
nullptr,
7706 bool ForDeviceAddr =
false,
const ValueDecl *BaseDecl =
nullptr,
7707 const Expr *MapExpr =
nullptr,
7708 ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef>
7709 OverlappedElements = {})
const {
7927 bool IsCaptureFirstInfo = IsFirstComponentList;
7931 bool RequiresReference =
false;
7934 auto CI = Components.rbegin();
7935 auto CE = Components.rend();
7940 bool IsExpressionFirstInfo =
true;
7941 bool FirstPointerInComplexData =
false;
7944 const Expr *AssocExpr = I->getAssociatedExpression();
7945 const auto *AE = dyn_cast<ArraySubscriptExpr>(AssocExpr);
7946 const auto *OASE = dyn_cast<ArraySectionExpr>(AssocExpr);
7947 const auto *OAShE = dyn_cast<OMPArrayShapingExpr>(AssocExpr);
7950 const Expr *AttachPtrExpr = getAttachPtrExpr(Components);
7951 auto [AttachPtrAddr, AttachPteeBaseAddr] =
7952 getAttachPtrAddrAndPteeBaseAddr(AttachPtrExpr, CGF);
7954 bool HasAttachPtr = AttachPtrExpr !=
nullptr;
7955 bool FirstComponentIsForAttachPtr = AssocExpr == AttachPtrExpr;
7956 bool SeenAttachPtr = FirstComponentIsForAttachPtr;
7958 if (FirstComponentIsForAttachPtr) {
7966 }
else if ((AE &&
isa<CXXThisExpr>(AE->getBase()->IgnoreParenImpCasts())) ||
7980 if (
const auto *VD =
7981 dyn_cast_or_null<VarDecl>(I->getAssociatedDeclaration())) {
7982 if (std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
7983 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD)) {
7984 if ((*Res == OMPDeclareTargetDeclAttr::MT_Link) ||
7985 ((*Res == OMPDeclareTargetDeclAttr::MT_To ||
7986 *Res == OMPDeclareTargetDeclAttr::MT_Enter ||
7987 *Res == OMPDeclareTargetDeclAttr::MT_Local) &&
7989 RequiresReference =
true;
7999 I->getAssociatedDeclaration()->
getType().getNonReferenceType();
8004 const auto *VD = dyn_cast<VarDecl>(I->getAssociatedDeclaration());
8006 !VD || VD->hasLocalStorage() || HasAttachPtr)
8009 FirstPointerInComplexData =
true;
8028 bool ShouldBeMemberOf =
false;
8037 const MemberExpr *EncounteredME =
nullptr;
8049 bool IsNonContiguous =
8050 CombinedInfo.NonContigInfo.IsNonContiguous ||
8051 any_of(Components, [&](
const auto &Component) {
8053 dyn_cast<ArraySectionExpr>(Component.getAssociatedExpression());
8057 const Expr *StrideExpr = OASE->getStride();
8062 "Stride expression must be of integer type");
8066 const auto Constant =
8072 return !Constant->isOne();
8075 bool IsPrevMemberReference =
false;
8077 bool IsPartialMapped =
8078 !PartialStruct.PreliminaryMapData.BasePointers.empty();
8085 bool IsMappingWholeStruct =
true;
8086 if (!GenerateAllInfoForClauses) {
8087 IsMappingWholeStruct =
false;
8089 for (
auto TempI = I; TempI != CE; ++TempI) {
8090 const MemberExpr *PossibleME =
8091 dyn_cast<MemberExpr>(TempI->getAssociatedExpression());
8093 IsMappingWholeStruct =
false;
8099 bool SeenFirstNonBinOpExprAfterAttachPtr =
false;
8100 for (; I != CE; ++I) {
8103 if (HasAttachPtr && !SeenAttachPtr) {
8104 SeenAttachPtr = I->getAssociatedExpression() == AttachPtrExpr;
8111 if (HasAttachPtr && !SeenFirstNonBinOpExprAfterAttachPtr) {
8112 const auto *BO = dyn_cast<BinaryOperator>(I->getAssociatedExpression());
8117 SeenFirstNonBinOpExprAfterAttachPtr =
true;
8118 BP = AttachPteeBaseAddr;
8122 if (!EncounteredME) {
8123 EncounteredME = dyn_cast<MemberExpr>(I->getAssociatedExpression());
8126 if (EncounteredME) {
8127 ShouldBeMemberOf =
true;
8130 if (FirstPointerInComplexData) {
8131 QualType Ty = std::prev(I)
8132 ->getAssociatedDeclaration()
8134 .getNonReferenceType();
8136 FirstPointerInComplexData =
false;
8141 auto Next = std::next(I);
8151 bool IsFinalArraySection =
8153 isFinalArraySectionExpression(I->getAssociatedExpression());
8157 const ValueDecl *MapDecl = (I->getAssociatedDeclaration())
8158 ? I->getAssociatedDeclaration()
8160 MapExpr = (I->getAssociatedExpression()) ? I->getAssociatedExpression()
8167 dyn_cast<ArraySectionExpr>(I->getAssociatedExpression());
8169 dyn_cast<OMPArrayShapingExpr>(I->getAssociatedExpression());
8170 const auto *UO = dyn_cast<UnaryOperator>(I->getAssociatedExpression());
8171 const auto *BO = dyn_cast<BinaryOperator>(I->getAssociatedExpression());
8177 I->getAssociatedExpression()->getType()->isAnyPointerType();
8178 bool IsMemberReference =
isa<MemberExpr>(I->getAssociatedExpression()) &&
8181 bool IsNonDerefPointer = IsPointer &&
8182 !(UO && UO->getOpcode() != UO_Deref) && !BO &&
8188 if (
Next == CE || IsMemberReference || IsNonDerefPointer ||
8189 IsFinalArraySection) {
8192 assert((
Next == CE ||
8199 "Unexpected expression");
8203 auto &&EmitMemberExprBase = [](CodeGenFunction &CGF,
8204 const MemberExpr *E) {
8205 const Expr *BaseExpr = E->getBase();
8210 LValueBaseInfo BaseInfo;
8211 TBAAAccessInfo TBAAInfo;
8225 OAShE->getBase()->getType()->getPointeeType()),
8227 OAShE->getBase()->getType()));
8228 }
else if (IsMemberReference) {
8230 LValue BaseLVal = EmitMemberExprBase(CGF, ME);
8245 FinalLowestElem = LowestElem;
8250 bool IsMemberPointerOrAddr =
8252 (((IsPointer || ForDeviceAddr) &&
8253 I->getAssociatedExpression() == EncounteredME) ||
8254 (IsPrevMemberReference && !IsPointer) ||
8255 (IsMemberReference &&
Next != CE &&
8256 !
Next->getAssociatedExpression()->getType()->isPointerType()));
8257 if (!OverlappedElements.empty() &&
Next == CE) {
8259 assert(!PartialStruct.Base.isValid() &&
"The base element is set.");
8260 assert(!IsPointer &&
8261 "Unexpected base element with the pointer type.");
8264 PartialStruct.LowestElem = {0, LowestElem};
8266 I->getAssociatedExpression()->getType());
8271 PartialStruct.HighestElem = {
8272 std::numeric_limits<
decltype(
8273 PartialStruct.HighestElem.first)>
::max(),
8275 PartialStruct.Base = BP;
8276 PartialStruct.LB = LB;
8278 PartialStruct.PreliminaryMapData.BasePointers.empty() &&
8279 "Overlapped elements must be used only once for the variable.");
8280 std::swap(PartialStruct.PreliminaryMapData, CombinedInfo);
8282 OpenMPOffloadMappingFlags Flags =
8283 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF |
8284 getMapTypeBits(MapType, MapModifiers, MotionModifiers, IsImplicit,
8286 false, IsNonContiguous);
8287 CopyOverlappedEntryGaps CopyGaps(CGF, CombinedInfo, Flags, MapDecl,
8288 MapExpr, BP, LB, IsNonContiguous,
8292 Component : OverlappedElements) {
8293 for (
const OMPClauseMappableExprCommon::MappableComponent &MC :
8296 if (
const auto *FD = dyn_cast<FieldDecl>(VD)) {
8297 CopyGaps.processField(MC, FD, EmitMemberExprBase);
8302 CopyGaps.copyUntilEnd(HB);
8305 llvm::Value *
Size = getExprTypeSize(I->getAssociatedExpression());
8312 if ((!IsMemberPointerOrAddr && !IsPartialMapped) ||
8314 if (!IsMappingWholeStruct) {
8315 CombinedInfo.Exprs.emplace_back(MapDecl, MapExpr);
8317 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
8318 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
8320 CombinedInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
8322 CombinedInfo.NonContigInfo.Dims.push_back(IsNonContiguous ? DimSize
8325 StructBaseCombinedInfo.Exprs.emplace_back(MapDecl, MapExpr);
8326 StructBaseCombinedInfo.BasePointers.push_back(
8328 StructBaseCombinedInfo.DevicePtrDecls.push_back(
nullptr);
8329 StructBaseCombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
8330 StructBaseCombinedInfo.Pointers.push_back(LB.
emitRawPointer(CGF));
8331 StructBaseCombinedInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
8333 StructBaseCombinedInfo.NonContigInfo.Dims.push_back(
8334 IsNonContiguous ? DimSize : 1);
8338 bool HasMapper = Mapper &&
Next == CE;
8339 if (!IsMappingWholeStruct)
8340 CombinedInfo.Mappers.push_back(HasMapper ? Mapper :
nullptr);
8342 StructBaseCombinedInfo.Mappers.push_back(HasMapper ? Mapper
8349 OpenMPOffloadMappingFlags Flags = getMapTypeBits(
8350 MapType, MapModifiers, MotionModifiers, IsImplicit,
8351 !IsExpressionFirstInfo || RequiresReference ||
8352 FirstPointerInComplexData || IsMemberReference,
8353 IsCaptureFirstInfo && !RequiresReference, IsNonContiguous);
8355 if (!IsExpressionFirstInfo || IsMemberReference) {
8358 if (IsPointer || (IsMemberReference &&
Next != CE))
8359 Flags &= ~(OpenMPOffloadMappingFlags::OMP_MAP_TO |
8360 OpenMPOffloadMappingFlags::OMP_MAP_FROM |
8361 OpenMPOffloadMappingFlags::OMP_MAP_ALWAYS |
8362 OpenMPOffloadMappingFlags::OMP_MAP_DELETE |
8363 OpenMPOffloadMappingFlags::OMP_MAP_CLOSE);
8365 if (ShouldBeMemberOf) {
8368 Flags |= OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF;
8371 ShouldBeMemberOf =
false;
8375 if (!IsMappingWholeStruct)
8376 CombinedInfo.Types.push_back(Flags);
8378 StructBaseCombinedInfo.Types.push_back(Flags);
8384 if (EncounteredME) {
8389 if (!PartialStruct.Base.isValid()) {
8390 PartialStruct.LowestElem = {FieldIndex, LowestElem};
8391 if (IsFinalArraySection && OASE) {
8395 PartialStruct.HighestElem = {FieldIndex, HB};
8397 PartialStruct.HighestElem = {FieldIndex, LowestElem};
8399 PartialStruct.Base = BP;
8400 PartialStruct.LB = BP;
8401 }
else if (FieldIndex < PartialStruct.LowestElem.first) {
8402 PartialStruct.LowestElem = {FieldIndex, LowestElem};
8403 }
else if (FieldIndex > PartialStruct.HighestElem.first) {
8404 if (IsFinalArraySection && OASE) {
8408 PartialStruct.HighestElem = {FieldIndex, HB};
8410 PartialStruct.HighestElem = {FieldIndex, LowestElem};
8416 if (IsFinalArraySection || IsNonContiguous)
8417 PartialStruct.IsArraySection =
true;
8420 if (IsFinalArraySection)
8425 BP = IsMemberReference ? LowestElem : LB;
8426 if (!IsPartialMapped)
8427 IsExpressionFirstInfo =
false;
8428 IsCaptureFirstInfo =
false;
8429 FirstPointerInComplexData =
false;
8430 IsPrevMemberReference = IsMemberReference;
8431 }
else if (FirstPointerInComplexData) {
8432 QualType Ty = Components.rbegin()
8433 ->getAssociatedDeclaration()
8435 .getNonReferenceType();
8437 FirstPointerInComplexData =
false;
8443 PartialStruct.HasCompleteRecord =
true;
8446 if (shouldEmitAttachEntry(AttachPtrExpr, BaseDecl, CGF, CurDir)) {
8447 AttachInfo.AttachPtrAddr = AttachPtrAddr;
8448 AttachInfo.AttachPteeAddr = FinalLowestElem;
8449 AttachInfo.AttachPtrDecl = BaseDecl;
8450 AttachInfo.AttachMapExpr = MapExpr;
8453 if (!IsNonContiguous)
8456 const ASTContext &Context = CGF.
getContext();
8460 MapValuesArrayTy CurOffsets = {llvm::ConstantInt::get(CGF.
CGM.
Int64Ty, 0)};
8461 MapValuesArrayTy CurCounts;
8462 MapValuesArrayTy CurStrides = {llvm::ConstantInt::get(CGF.
CGM.
Int64Ty, 1)};
8463 MapValuesArrayTy DimSizes{llvm::ConstantInt::get(CGF.
CGM.
Int64Ty, 1)};
8469 for (
const OMPClauseMappableExprCommon::MappableComponent &Component :
8471 const Expr *AssocExpr = Component.getAssociatedExpression();
8472 const auto *OASE = dyn_cast<ArraySectionExpr>(AssocExpr);
8482 assert((VAT || CAT || &Component == &*Components.begin()) &&
8483 "Should be either ConstantArray or VariableArray if not the "
8487 if (CurCounts.empty()) {
8488 const Type *ElementType =
nullptr;
8490 ElementType = CAT->getElementType().getTypePtr();
8492 ElementType = VAT->getElementType().getTypePtr();
8493 else if (&Component == &*Components.begin()) {
8500 if (
const auto *PtrType = Ty->
getAs<PointerType>())
8507 "Non-first components should not be raw pointers");
8515 if (&Component != &*Components.begin())
8519 CurCounts.push_back(
8520 llvm::ConstantInt::get(CGF.
Int64Ty, ElementTypeSize));
8525 if (DimSizes.size() < Components.size() - 1) {
8528 llvm::ConstantInt::get(CGF.
Int64Ty, CAT->getZExtSize()));
8530 DimSizes.push_back(CGF.
Builder.CreateIntCast(
8537 auto *DI = DimSizes.begin() + 1;
8539 llvm::Value *DimProd =
8540 llvm::ConstantInt::get(CGF.
CGM.
Int64Ty, ElementTypeSize);
8549 for (
const OMPClauseMappableExprCommon::MappableComponent &Component :
8551 const Expr *AssocExpr = Component.getAssociatedExpression();
8553 if (
const auto *AE = dyn_cast<ArraySubscriptExpr>(AssocExpr)) {
8554 llvm::Value *Offset = CGF.
Builder.CreateIntCast(
8557 CurOffsets.push_back(Offset);
8558 CurCounts.push_back(llvm::ConstantInt::get(CGF.
Int64Ty, 1));
8559 CurStrides.push_back(CurStrides.back());
8563 const auto *OASE = dyn_cast<ArraySectionExpr>(AssocExpr);
8569 const Expr *OffsetExpr = OASE->getLowerBound();
8570 llvm::Value *Offset =
nullptr;
8573 Offset = llvm::ConstantInt::get(CGF.
Int64Ty, 0);
8581 const Expr *CountExpr = OASE->getLength();
8582 llvm::Value *Count =
nullptr;
8588 if (!OASE->getColonLocFirst().isValid() &&
8589 !OASE->getColonLocSecond().isValid()) {
8590 Count = llvm::ConstantInt::get(CGF.
Int64Ty, 1);
8596 const Expr *StrideExpr = OASE->getStride();
8597 llvm::Value *Stride =
8603 Count = CGF.
Builder.CreateUDiv(
8604 CGF.
Builder.CreateNUWSub(*DI, Offset), Stride);
8606 Count = CGF.
Builder.CreateNUWSub(*DI, Offset);
8612 CurCounts.push_back(Count);
8622 const Expr *StrideExpr = OASE->getStride();
8623 llvm::Value *Stride =
8628 DimProd = CGF.
Builder.CreateNUWMul(DimProd, *(DI - 1));
8630 CurStrides.push_back(CGF.
Builder.CreateNUWMul(DimProd, Stride));
8632 CurStrides.push_back(DimProd);
8634 Offset = CGF.
Builder.CreateNUWMul(DimProd, Offset);
8635 CurOffsets.push_back(Offset);
8637 if (DI != DimSizes.end())
8641 CombinedInfo.NonContigInfo.Offsets.push_back(CurOffsets);
8642 CombinedInfo.NonContigInfo.Counts.push_back(CurCounts);
8643 CombinedInfo.NonContigInfo.Strides.push_back(CurStrides);
8649 OpenMPOffloadMappingFlags
8650 getMapModifiersForPrivateClauses(
const CapturedStmt::Capture &Cap)
const {
8658 return OpenMPOffloadMappingFlags::OMP_MAP_TO |
8659 OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ;
8660 return OpenMPOffloadMappingFlags::OMP_MAP_PRIVATE |
8661 OpenMPOffloadMappingFlags::OMP_MAP_TO;
8664 if (I != LambdasMap.end())
8666 return getMapTypeBits(
8667 I->getSecond()->getMapType(), I->getSecond()->getMapTypeModifiers(),
8668 {}, I->getSecond()->isImplicit(),
8672 return OpenMPOffloadMappingFlags::OMP_MAP_TO |
8673 OpenMPOffloadMappingFlags::OMP_MAP_FROM;
8676 void getPlainLayout(
const CXXRecordDecl *RD,
8677 llvm::SmallVectorImpl<const FieldDecl *> &Layout,
8678 bool AsBase)
const {
8681 llvm::StructType *St =
8684 unsigned NumElements = St->getNumElements();
8686 llvm::PointerUnion<const CXXRecordDecl *, const FieldDecl *>, 4>
8687 RecordLayout(NumElements);
8690 for (
const auto &I : RD->
bases()) {
8694 QualType BaseTy = I.getType();
8705 RecordLayout[FieldIndex] =
Base;
8708 for (
const auto &I : RD->
vbases()) {
8709 QualType BaseTy = I.getType();
8716 if (RecordLayout[FieldIndex])
8718 RecordLayout[FieldIndex] =
Base;
8721 assert(!RD->
isUnion() &&
"Unexpected union.");
8722 for (
const auto *Field : RD->
fields()) {
8725 if (!
Field->isBitField() &&
8728 RecordLayout[FieldIndex] =
Field;
8731 for (
const llvm::PointerUnion<const CXXRecordDecl *, const FieldDecl *>
8732 &
Data : RecordLayout) {
8735 if (
const auto *Base = dyn_cast<const CXXRecordDecl *>(
Data))
8736 getPlainLayout(Base, Layout,
true);
8743 static Address getAttachPtrAddr(
const Expr *PointerExpr,
8744 CodeGenFunction &CGF) {
8745 assert(PointerExpr &&
"Cannot get addr from null attach-ptr expr");
8748 if (
auto *DRE = dyn_cast<DeclRefExpr>(PointerExpr)) {
8751 }
else if (
auto *OASE = dyn_cast<ArraySectionExpr>(PointerExpr)) {
8754 }
else if (
auto *ASE = dyn_cast<ArraySubscriptExpr>(PointerExpr)) {
8756 }
else if (
auto *ME = dyn_cast<MemberExpr>(PointerExpr)) {
8758 }
else if (
auto *UO = dyn_cast<UnaryOperator>(PointerExpr)) {
8759 assert(UO->getOpcode() == UO_Deref &&
8760 "Unexpected unary-operator on attach-ptr-expr");
8763 assert(AttachPtrAddr.
isValid() &&
8764 "Failed to get address for attach pointer expression");
8765 return AttachPtrAddr;
8772 static std::pair<Address, Address>
8773 getAttachPtrAddrAndPteeBaseAddr(
const Expr *AttachPtrExpr,
8774 CodeGenFunction &CGF) {
8779 Address AttachPtrAddr = getAttachPtrAddr(AttachPtrExpr, CGF);
8780 assert(AttachPtrAddr.
isValid() &&
"Invalid attach pointer addr");
8782 QualType AttachPtrType =
8787 AttachPtrAddr, AttachPtrType->
castAs<PointerType>());
8788 assert(AttachPteeBaseAddr.
isValid() &&
"Invalid attach pointee base addr");
8790 return {AttachPtrAddr, AttachPteeBaseAddr};
8796 shouldEmitAttachEntry(
const Expr *PointerExpr,
const ValueDecl *MapBaseDecl,
8797 CodeGenFunction &CGF,
8798 llvm::PointerUnion<
const OMPExecutableDirective *,
8799 const OMPDeclareMapperDecl *>
8809 ->getDirectiveKind());
8818 void collectAttachPtrExprInfo(
8820 llvm::PointerUnion<
const OMPExecutableDirective *,
8821 const OMPDeclareMapperDecl *>
8826 ? OMPD_declare_mapper
8829 const auto &[AttachPtrExpr, Depth] =
8833 AttachPtrComputationOrderMap.try_emplace(
8834 AttachPtrExpr, AttachPtrComputationOrderMap.size());
8835 AttachPtrComponentDepthMap.try_emplace(AttachPtrExpr, Depth);
8836 AttachPtrExprMap.try_emplace(Components, AttachPtrExpr);
8844 void generateAllInfoForClauses(
8845 ArrayRef<const OMPClause *> Clauses, MapCombinedInfoTy &CombinedInfo,
8846 llvm::OpenMPIRBuilder &OMPBuilder,
8847 const llvm::DenseSet<CanonicalDeclPtr<const Decl>> &SkipVarSet =
8848 llvm::DenseSet<CanonicalDeclPtr<const Decl>>())
const {
8853 llvm::MapVector<CanonicalDeclPtr<const Decl>,
8854 SmallVector<SmallVector<MapInfo, 8>, 4>>
8860 [&Info, &SkipVarSet](
8861 const ValueDecl *D, MapKind
Kind,
8864 ArrayRef<OpenMPMapModifierKind> MapModifiers,
8865 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
8866 bool ReturnDevicePointer,
bool IsImplicit,
const ValueDecl *Mapper,
8867 const Expr *VarRef =
nullptr,
bool ForDeviceAddr =
false) {
8868 if (SkipVarSet.contains(D))
8870 auto It = Info.try_emplace(D, Total).first;
8871 It->second[
Kind].emplace_back(
8872 L, MapType, MapModifiers, MotionModifiers, ReturnDevicePointer,
8873 IsImplicit, Mapper, VarRef, ForDeviceAddr);
8876 for (
const auto *
Cl : Clauses) {
8877 const auto *
C = dyn_cast<OMPMapClause>(
Cl);
8881 if (llvm::is_contained(
C->getMapTypeModifiers(),
8882 OMPC_MAP_MODIFIER_present))
8884 else if (
C->getMapType() == OMPC_MAP_alloc)
8886 const auto *EI =
C->getVarRefs().begin();
8887 for (
const auto L :
C->component_lists()) {
8888 const Expr *E = (
C->getMapLoc().isValid()) ? *EI :
nullptr;
8889 InfoGen(std::get<0>(L), Kind, std::get<1>(L),
C->getMapType(),
8890 C->getMapTypeModifiers(), {},
8891 false,
C->isImplicit(), std::get<2>(L),
8896 for (
const auto *
Cl : Clauses) {
8897 const auto *
C = dyn_cast<OMPToClause>(
Cl);
8901 if (llvm::is_contained(
C->getMotionModifiers(),
8902 OMPC_MOTION_MODIFIER_present))
8904 if (llvm::is_contained(
C->getMotionModifiers(),
8905 OMPC_MOTION_MODIFIER_iterator)) {
8906 if (
auto *IteratorExpr = dyn_cast<OMPIteratorExpr>(
8907 C->getIteratorModifier()->IgnoreParenImpCasts())) {
8908 const auto *VD =
cast<VarDecl>(IteratorExpr->getIteratorDecl(0));
8913 const auto *EI =
C->getVarRefs().begin();
8914 for (
const auto L :
C->component_lists()) {
8915 InfoGen(std::get<0>(L), Kind, std::get<1>(L), OMPC_MAP_to, {},
8916 C->getMotionModifiers(),
false,
8917 C->isImplicit(), std::get<2>(L), *EI);
8921 for (
const auto *
Cl : Clauses) {
8922 const auto *
C = dyn_cast<OMPFromClause>(
Cl);
8926 if (llvm::is_contained(
C->getMotionModifiers(),
8927 OMPC_MOTION_MODIFIER_present))
8929 if (llvm::is_contained(
C->getMotionModifiers(),
8930 OMPC_MOTION_MODIFIER_iterator)) {
8931 if (
auto *IteratorExpr = dyn_cast<OMPIteratorExpr>(
8932 C->getIteratorModifier()->IgnoreParenImpCasts())) {
8933 const auto *VD =
cast<VarDecl>(IteratorExpr->getIteratorDecl(0));
8938 const auto *EI =
C->getVarRefs().begin();
8939 for (
const auto L :
C->component_lists()) {
8940 InfoGen(std::get<0>(L), Kind, std::get<1>(L), OMPC_MAP_from, {},
8941 C->getMotionModifiers(),
8942 false,
C->isImplicit(), std::get<2>(L),
8955 MapCombinedInfoTy UseDeviceDataCombinedInfo;
8957 auto &&UseDeviceDataCombinedInfoGen =
8958 [&UseDeviceDataCombinedInfo](
const ValueDecl *VD, llvm::Value *Ptr,
8959 CodeGenFunction &CGF,
bool IsDevAddr,
8960 bool HasUdpFbNullify =
false) {
8961 UseDeviceDataCombinedInfo.Exprs.push_back(VD);
8962 UseDeviceDataCombinedInfo.BasePointers.emplace_back(Ptr);
8963 UseDeviceDataCombinedInfo.DevicePtrDecls.emplace_back(VD);
8964 UseDeviceDataCombinedInfo.DevicePointers.emplace_back(
8965 IsDevAddr ? DeviceInfoTy::Address : DeviceInfoTy::Pointer);
8971 UseDeviceDataCombinedInfo.Pointers.push_back(Ptr);
8972 UseDeviceDataCombinedInfo.Sizes.push_back(
8973 llvm::Constant::getNullValue(CGF.Int64Ty));
8974 OpenMPOffloadMappingFlags Flags =
8975 OpenMPOffloadMappingFlags::OMP_MAP_RETURN_PARAM;
8976 if (HasUdpFbNullify)
8977 Flags |= OpenMPOffloadMappingFlags::OMP_MAP_FB_NULLIFY;
8978 UseDeviceDataCombinedInfo.Types.push_back(Flags);
8979 UseDeviceDataCombinedInfo.Mappers.push_back(
nullptr);
8983 [&UseDeviceDataCombinedInfoGen](
8984 CodeGenFunction &CGF,
const Expr *IE,
const ValueDecl *VD,
8987 bool IsDevAddr,
bool IEIsAttachPtrForDevAddr =
false,
8988 bool HasUdpFbNullify =
false) {
8992 if (IsDevAddr && !IEIsAttachPtrForDevAddr) {
8993 if (IE->isGLValue())
9000 bool TreatDevAddrAsDevPtr = IEIsAttachPtrForDevAddr;
9007 UseDeviceDataCombinedInfoGen(VD, Ptr, CGF, IsDevAddr &&
9008 !TreatDevAddrAsDevPtr,
9012 auto &&IsMapInfoExist =
9013 [&Info,
this](CodeGenFunction &CGF,
const ValueDecl *VD,
const Expr *IE,
9014 const Expr *DesiredAttachPtrExpr,
bool IsDevAddr,
9015 bool HasUdpFbNullify =
false) ->
bool {
9023 if (It != Info.end()) {
9025 for (
auto &
Data : It->second) {
9026 MapInfo *CI =
nullptr;
9030 auto *It = llvm::find_if(
Data, [&](
const MapInfo &MI) {
9031 if (MI.Components.back().getAssociatedDeclaration() != VD)
9034 const Expr *MapAttachPtr = getAttachPtrExpr(MI.Components);
9035 bool Match = AttachPtrComparator.areEqual(MapAttachPtr,
9036 DesiredAttachPtrExpr);
9040 if (It !=
Data.end())
9045 CI->ForDeviceAddr =
true;
9046 CI->ReturnDevicePointer =
true;
9047 CI->HasUdpFbNullify = HasUdpFbNullify;
9051 auto PrevCI = std::next(CI->Components.rbegin());
9052 const auto *VarD = dyn_cast<VarDecl>(VD);
9053 const Expr *AttachPtrExpr = getAttachPtrExpr(CI->Components);
9054 if (CGF.CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory() ||
9056 !VD->getType().getNonReferenceType()->isPointerType() ||
9057 PrevCI == CI->Components.rend() ||
9059 VarD->hasLocalStorage() ||
9060 (isa_and_nonnull<DeclRefExpr>(AttachPtrExpr) &&
9062 CI->ForDeviceAddr = IsDevAddr;
9063 CI->ReturnDevicePointer =
true;
9064 CI->HasUdpFbNullify = HasUdpFbNullify;
9082 for (
const auto *
Cl : Clauses) {
9083 const auto *
C = dyn_cast<OMPUseDevicePtrClause>(
Cl);
9086 bool HasUdpFbNullify =
9087 C->getFallbackModifier() == OMPC_USE_DEVICE_PTR_FALLBACK_fb_nullify;
9088 for (
const auto L :
C->component_lists()) {
9091 assert(!Components.empty() &&
9092 "Not expecting empty list of components!");
9093 const ValueDecl *VD = Components.back().getAssociatedDeclaration();
9095 const Expr *IE = Components.back().getAssociatedExpression();
9103 const Expr *UDPOperandExpr =
9104 Components.front().getAssociatedExpression();
9105 if (IsMapInfoExist(CGF, VD, IE,
9107 false, HasUdpFbNullify))
9109 MapInfoGen(CGF, IE, VD, Components,
false,
9110 false, HasUdpFbNullify);
9114 llvm::SmallDenseSet<CanonicalDeclPtr<const Decl>, 4> Processed;
9115 for (
const auto *
Cl : Clauses) {
9116 const auto *
C = dyn_cast<OMPUseDeviceAddrClause>(
Cl);
9119 for (
const auto L :
C->component_lists()) {
9122 assert(!std::get<1>(L).empty() &&
9123 "Not expecting empty list of components!");
9124 const ValueDecl *VD = std::get<1>(L).back().getAssociatedDeclaration();
9125 if (!Processed.insert(VD).second)
9146 const Expr *UDAAttachPtrExpr = getAttachPtrExpr(Components);
9147 const Expr *IE = std::get<1>(L).back().getAssociatedExpression();
9148 assert((!UDAAttachPtrExpr || UDAAttachPtrExpr == IE) &&
9149 "use_device_addr operand has an attach-ptr, but does not match "
9150 "last component's expr.");
9151 if (IsMapInfoExist(CGF, VD, IE,
9155 MapInfoGen(CGF, IE, VD, Components,
9157 UDAAttachPtrExpr !=
nullptr);
9161 for (
const auto &
Data : Info) {
9162 MapCombinedInfoTy CurInfo;
9164 const ValueDecl *VD = cast_or_null<ValueDecl>(D);
9171 SmallVector<std::pair<const Expr *, MapInfo>, 16> AttachPtrMapInfoPairs;
9174 for (
const auto &M :
Data.second) {
9175 for (
const MapInfo &L : M) {
9176 assert(!L.Components.empty() &&
9177 "Not expecting declaration with no component lists.");
9179 const Expr *AttachPtrExpr = getAttachPtrExpr(L.Components);
9180 AttachPtrMapInfoPairs.emplace_back(AttachPtrExpr, L);
9185 llvm::stable_sort(AttachPtrMapInfoPairs,
9186 [
this](
const auto &LHS,
const auto &RHS) {
9187 return AttachPtrComparator(LHS.first, RHS.first);
9192 auto *It = AttachPtrMapInfoPairs.begin();
9193 while (It != AttachPtrMapInfoPairs.end()) {
9194 const Expr *AttachPtrExpr = It->first;
9196 SmallVector<MapInfo, 8> GroupLists;
9197 while (It != AttachPtrMapInfoPairs.end() &&
9198 (It->first == AttachPtrExpr ||
9199 AttachPtrComparator.areEqual(It->first, AttachPtrExpr))) {
9200 GroupLists.push_back(It->second);
9203 assert(!GroupLists.empty() &&
"GroupLists should not be empty");
9205 StructRangeInfoTy PartialStruct;
9206 AttachInfoTy AttachInfo;
9207 MapCombinedInfoTy GroupCurInfo;
9209 MapCombinedInfoTy GroupStructBaseCurInfo;
9210 for (
const MapInfo &L : GroupLists) {
9212 unsigned CurrentBasePointersIdx = GroupCurInfo.BasePointers.size();
9213 unsigned StructBasePointersIdx =
9214 GroupStructBaseCurInfo.BasePointers.size();
9216 GroupCurInfo.NonContigInfo.IsNonContiguous =
9217 L.Components.back().isNonContiguous();
9218 generateInfoForComponentList(
9219 L.MapType, L.MapModifiers, L.MotionModifiers, L.Components,
9220 GroupCurInfo, GroupStructBaseCurInfo, PartialStruct, AttachInfo,
9221 false, L.IsImplicit,
9222 true, L.Mapper, L.ForDeviceAddr, VD,
9227 if (L.ReturnDevicePointer) {
9231 assert((CurrentBasePointersIdx < GroupCurInfo.BasePointers.size() ||
9232 StructBasePointersIdx <
9233 GroupStructBaseCurInfo.BasePointers.size()) &&
9234 "Unexpected number of mapped base pointers.");
9237 const ValueDecl *RelevantVD =
9238 L.Components.back().getAssociatedDeclaration();
9239 assert(RelevantVD &&
9240 "No relevant declaration related with device pointer??");
9247 auto SetDevicePointerInfo = [&](MapCombinedInfoTy &Info,
9249 Info.DevicePtrDecls[Idx] = RelevantVD;
9250 Info.DevicePointers[Idx] = L.ForDeviceAddr
9251 ? DeviceInfoTy::Address
9252 : DeviceInfoTy::Pointer;
9254 OpenMPOffloadMappingFlags::OMP_MAP_RETURN_PARAM;
9255 if (L.HasUdpFbNullify)
9257 OpenMPOffloadMappingFlags::OMP_MAP_FB_NULLIFY;
9260 if (StructBasePointersIdx <
9261 GroupStructBaseCurInfo.BasePointers.size())
9262 SetDevicePointerInfo(GroupStructBaseCurInfo,
9263 StructBasePointersIdx);
9265 SetDevicePointerInfo(GroupCurInfo, CurrentBasePointersIdx);
9271 MapCombinedInfoTy GroupUnionCurInfo;
9272 GroupUnionCurInfo.append(GroupStructBaseCurInfo);
9273 GroupUnionCurInfo.append(GroupCurInfo);
9277 if (PartialStruct.Base.isValid()) {
9285 GroupUnionCurInfo.NonContigInfo.Dims.insert(
9286 GroupUnionCurInfo.NonContigInfo.Dims.begin(), 1);
9288 CurInfo, GroupUnionCurInfo.Types, PartialStruct, AttachInfo,
9289 !VD, OMPBuilder, VD,
9290 CombinedInfo.BasePointers.size(),
9296 CurInfo.append(GroupUnionCurInfo);
9297 if (AttachInfo.isValid())
9298 emitAttachEntry(CGF, CurInfo, AttachInfo);
9302 CombinedInfo.append(CurInfo);
9305 CombinedInfo.append(UseDeviceDataCombinedInfo);
9309 MappableExprsHandler(
const OMPExecutableDirective &Dir, CodeGenFunction &CGF)
9310 : CurDir(&Dir), CGF(CGF), AttachPtrComparator(*this) {
9312 for (
const auto *
C : Dir.getClausesOfKind<OMPFirstprivateClause>())
9313 for (
const auto *D :
C->varlist())
9314 FirstPrivateDecls.try_emplace(
9317 for (
const auto *
C : Dir.getClausesOfKind<OMPUsesAllocatorsClause>()) {
9318 for (unsigned I = 0, E = C->getNumberOfAllocators(); I < E; ++I) {
9319 OMPUsesAllocatorsClause::Data D = C->getAllocatorData(I);
9320 if (const auto *DRE = dyn_cast_or_null<DeclRefExpr>(D.AllocatorTraits))
9321 FirstPrivateDecls.try_emplace(cast<VarDecl>(DRE->getDecl()),
9323 else if (const auto *VD = dyn_cast<VarDecl>(
9324 cast<DeclRefExpr>(D.Allocator->IgnoreParenImpCasts())
9326 FirstPrivateDecls.try_emplace(VD, true);
9330 for (
const auto *
C : Dir.getClausesOfKind<OMPDefaultmapClause>())
9331 if (
C->getDefaultmapModifier() == OMPC_DEFAULTMAP_MODIFIER_firstprivate)
9332 DefaultmapFirstprivateKinds.insert(
C->getDefaultmapKind());
9334 for (
const auto *
C : Dir.getClausesOfKind<OMPIsDevicePtrClause>())
9335 for (
auto L :
C->component_lists())
9336 DevPointersMap[std::get<0>(L)].push_back(std::get<1>(L));
9338 for (
const auto *
C : Dir.getClausesOfKind<OMPHasDeviceAddrClause>())
9339 for (
auto L :
C->component_lists())
9340 HasDevAddrsMap[std::get<0>(L)].push_back(std::get<1>(L));
9342 for (
const auto *
C : Dir.getClausesOfKind<OMPMapClause>()) {
9343 if (C->getMapType() != OMPC_MAP_to)
9345 for (auto L : C->component_lists()) {
9346 const ValueDecl *VD = std::get<0>(L);
9347 const auto *RD = VD ? VD->getType()
9349 .getNonReferenceType()
9350 ->getAsCXXRecordDecl()
9352 if (RD && RD->isLambda())
9353 LambdasMap.try_emplace(std::get<0>(L), C);
9357 auto CollectAttachPtrExprsForClauseComponents = [
this](
const auto *
C) {
9358 for (
auto L :
C->component_lists()) {
9361 if (!Components.empty())
9362 collectAttachPtrExprInfo(Components, CurDir);
9368 for (
const auto *
C : Dir.getClausesOfKind<OMPMapClause>())
9369 CollectAttachPtrExprsForClauseComponents(
C);
9370 for (
const auto *
C : Dir.getClausesOfKind<OMPToClause>())
9371 CollectAttachPtrExprsForClauseComponents(
C);
9372 for (
const auto *
C : Dir.getClausesOfKind<OMPFromClause>())
9373 CollectAttachPtrExprsForClauseComponents(
C);
9374 for (
const auto *
C : Dir.getClausesOfKind<OMPUseDevicePtrClause>())
9375 CollectAttachPtrExprsForClauseComponents(
C);
9376 for (
const auto *
C : Dir.getClausesOfKind<OMPUseDeviceAddrClause>())
9377 CollectAttachPtrExprsForClauseComponents(
C);
9378 for (
const auto *
C : Dir.getClausesOfKind<OMPIsDevicePtrClause>())
9379 CollectAttachPtrExprsForClauseComponents(
C);
9380 for (
const auto *
C : Dir.getClausesOfKind<OMPHasDeviceAddrClause>())
9381 CollectAttachPtrExprsForClauseComponents(
C);
9385 MappableExprsHandler(
const OMPDeclareMapperDecl &Dir,
CodeGenFunction &CGF)
9386 : CurDir(&Dir), CGF(CGF), AttachPtrComparator(*this) {}
9396 void emitCombinedEntry(MapCombinedInfoTy &CombinedInfo,
9397 MapFlagsArrayTy &CurTypes,
9398 const StructRangeInfoTy &PartialStruct,
9399 AttachInfoTy &AttachInfo,
bool IsMapThis,
9400 llvm::OpenMPIRBuilder &OMPBuilder,
const ValueDecl *VD,
9401 unsigned OffsetForMemberOfFlag,
9402 bool NotTargetParams)
const {
9403 if (CurTypes.size() == 1 &&
9404 ((CurTypes.back() & OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF) !=
9405 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF) &&
9406 !PartialStruct.IsArraySection)
9408 Address LBAddr = PartialStruct.LowestElem.second;
9409 Address HBAddr = PartialStruct.HighestElem.second;
9410 if (PartialStruct.HasCompleteRecord) {
9411 LBAddr = PartialStruct.LB;
9412 HBAddr = PartialStruct.LB;
9414 CombinedInfo.Exprs.push_back(VD);
9416 CombinedInfo.BasePointers.push_back(PartialStruct.Base.emitRawPointer(CGF));
9417 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
9418 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
9421 const CXXMethodDecl *MD =
9423 const CXXRecordDecl *RD = MD ? MD->
getParent() :
nullptr;
9424 bool HasBaseClass = RD && IsMapThis ? RD->
getNumBases() > 0 :
false;
9434 CombinedInfo.Pointers.push_back(PartialStruct.Base.emitRawPointer(CGF));
9439 CombinedInfo.Sizes.push_back(Size);
9441 CombinedInfo.Pointers.push_back(LB);
9444 llvm::Value *HAddr = CGF.
Builder.CreateConstGEP1_32(
9448 llvm::Value *Diff = CGF.
Builder.CreatePtrDiff(CHAddr, CLAddr);
9451 CombinedInfo.Sizes.push_back(Size);
9453 CombinedInfo.Mappers.push_back(
nullptr);
9455 CombinedInfo.Types.push_back(
9456 NotTargetParams ? OpenMPOffloadMappingFlags::OMP_MAP_NONE
9457 : !PartialStruct.PreliminaryMapData.BasePointers.empty()
9458 ? OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ
9459 : OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM);
9462 if (CurTypes.end() !=
9463 llvm::find_if(CurTypes, [](OpenMPOffloadMappingFlags
Type) {
9464 return static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>>(
9465 Type & OpenMPOffloadMappingFlags::OMP_MAP_PRESENT);
9467 CombinedInfo.Types.back() |= OpenMPOffloadMappingFlags::OMP_MAP_PRESENT;
9469 (*CurTypes.begin()) &= ~OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM;
9476 if (CurTypes.end() !=
9477 llvm::find_if(CurTypes, [](OpenMPOffloadMappingFlags
Type) {
9478 return static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>>(
9479 Type & OpenMPOffloadMappingFlags::OMP_MAP_OMPX_HOLD);
9481 CombinedInfo.Types.back() |= OpenMPOffloadMappingFlags::OMP_MAP_OMPX_HOLD;
9482 for (
auto &M : CurTypes)
9483 M |= OpenMPOffloadMappingFlags::OMP_MAP_OMPX_HOLD;
9490 OpenMPOffloadMappingFlags MemberOfFlag = OMPBuilder.getMemberOfFlag(
9491 OffsetForMemberOfFlag + CombinedInfo.BasePointers.size() - 1);
9492 for (
auto &M : CurTypes)
9493 OMPBuilder.setCorrectMemberOfFlag(M, MemberOfFlag);
9510 if (AttachInfo.isValid())
9511 AttachInfo.AttachPteeAddr = LBAddr;
9519 void generateAllInfo(
9520 MapCombinedInfoTy &CombinedInfo, llvm::OpenMPIRBuilder &OMPBuilder,
9521 const llvm::DenseSet<CanonicalDeclPtr<const Decl>> &SkipVarSet =
9522 llvm::DenseSet<CanonicalDeclPtr<const Decl>>())
const {
9524 "Expect a executable directive");
9526 generateAllInfoForClauses(CurExecDir->clauses(), CombinedInfo, OMPBuilder,
9533 void generateAllInfoForMapper(MapCombinedInfoTy &CombinedInfo,
9534 llvm::OpenMPIRBuilder &OMPBuilder)
const {
9536 "Expect a declare mapper directive");
9538 generateAllInfoForClauses(CurMapperDir->clauses(), CombinedInfo,
9543 void generateInfoForLambdaCaptures(
9544 const ValueDecl *VD, llvm::Value *Arg, MapCombinedInfoTy &CombinedInfo,
9545 llvm::DenseMap<llvm::Value *, llvm::Value *> &LambdaPointers)
const {
9553 llvm::DenseMap<const ValueDecl *, FieldDecl *> Captures;
9554 FieldDecl *ThisCapture =
nullptr;
9560 LambdaPointers.try_emplace(ThisLVal.getPointer(CGF),
9561 VDLVal.getPointer(CGF));
9562 CombinedInfo.Exprs.push_back(VD);
9563 CombinedInfo.BasePointers.push_back(ThisLVal.getPointer(CGF));
9564 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
9565 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
9566 CombinedInfo.Pointers.push_back(ThisLValVal.getPointer(CGF));
9567 CombinedInfo.Sizes.push_back(
9570 CombinedInfo.Types.push_back(
9571 OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ |
9572 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL |
9573 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF |
9574 OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT);
9575 CombinedInfo.Mappers.push_back(
nullptr);
9577 for (
const LambdaCapture &LC : RD->
captures()) {
9578 if (!LC.capturesVariable())
9583 auto It = Captures.find(VD);
9584 assert(It != Captures.end() &&
"Found lambda capture without field.");
9588 LambdaPointers.try_emplace(VarLVal.getPointer(CGF),
9589 VDLVal.getPointer(CGF));
9590 CombinedInfo.Exprs.push_back(VD);
9591 CombinedInfo.BasePointers.push_back(VarLVal.getPointer(CGF));
9592 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
9593 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
9594 CombinedInfo.Pointers.push_back(VarLValVal.getPointer(CGF));
9595 CombinedInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
9601 LambdaPointers.try_emplace(VarLVal.getPointer(CGF),
9602 VDLVal.getPointer(CGF));
9603 CombinedInfo.Exprs.push_back(VD);
9604 CombinedInfo.BasePointers.push_back(VarLVal.getPointer(CGF));
9605 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
9606 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
9607 CombinedInfo.Pointers.push_back(VarRVal.
getScalarVal());
9608 CombinedInfo.Sizes.push_back(llvm::ConstantInt::get(CGF.
Int64Ty, 0));
9610 CombinedInfo.Types.push_back(
9611 OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ |
9612 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL |
9613 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF |
9614 OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT);
9615 CombinedInfo.Mappers.push_back(
nullptr);
9620 void adjustMemberOfForLambdaCaptures(
9621 llvm::OpenMPIRBuilder &OMPBuilder,
9622 const llvm::DenseMap<llvm::Value *, llvm::Value *> &LambdaPointers,
9623 MapBaseValuesArrayTy &BasePointers, MapValuesArrayTy &Pointers,
9624 MapFlagsArrayTy &Types)
const {
9625 for (
unsigned I = 0, E = Types.size(); I < E; ++I) {
9627 if (Types[I] != (OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ |
9628 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL |
9629 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF |
9630 OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT))
9632 llvm::Value *BasePtr = LambdaPointers.lookup(BasePointers[I]);
9633 assert(BasePtr &&
"Unable to find base lambda address.");
9635 for (
unsigned J = I; J > 0; --J) {
9636 unsigned Idx = J - 1;
9637 if (Pointers[Idx] != BasePtr)
9642 assert(TgtIdx != -1 &&
"Unable to find parent lambda.");
9646 OpenMPOffloadMappingFlags MemberOfFlag =
9647 OMPBuilder.getMemberOfFlag(TgtIdx);
9648 OMPBuilder.setCorrectMemberOfFlag(Types[I], MemberOfFlag);
9654 void populateComponentListsForNonLambdaCaptureFromClauses(
9655 const ValueDecl *VD, MapDataArrayTy &DeclComponentLists,
9657 SmallVector<OMPClauseMappableExprCommon::MappableComponent, 8>>
9658 &StorageForImplicitlyAddedComponentLists)
const {
9659 if (VD && LambdasMap.count(VD))
9665 auto It = DevPointersMap.find(VD);
9666 if (It != DevPointersMap.end())
9667 for (
const auto &MCL : It->second)
9668 DeclComponentLists.emplace_back(MCL, OMPC_MAP_to,
Unknown,
9671 auto I = HasDevAddrsMap.find(VD);
9672 if (I != HasDevAddrsMap.end())
9673 for (
const auto &MCL : I->second)
9674 DeclComponentLists.emplace_back(MCL, OMPC_MAP_tofrom,
Unknown,
9678 "Expect a executable directive");
9680 for (
const auto *
C : CurExecDir->getClausesOfKind<OMPMapClause>()) {
9681 const auto *EI =
C->getVarRefs().begin();
9682 for (
const auto L :
C->decl_component_lists(VD)) {
9683 const ValueDecl *VDecl, *Mapper;
9685 const Expr *E = (
C->getMapLoc().isValid()) ? *EI :
nullptr;
9687 std::tie(VDecl, Components, Mapper) = L;
9688 assert(VDecl == VD &&
"We got information for the wrong declaration??");
9689 assert(!Components.empty() &&
9690 "Not expecting declaration with no component lists.");
9691 DeclComponentLists.emplace_back(Components,
C->getMapType(),
9692 C->getMapTypeModifiers(),
9693 C->isImplicit(), Mapper, E);
9702 addImplicitMapForAttachPtrBaseIfMemberOfCapturedVD(
9703 VD, DeclComponentLists, StorageForImplicitlyAddedComponentLists);
9705 llvm::stable_sort(DeclComponentLists, [](
const MapData &LHS,
9706 const MapData &RHS) {
9707 ArrayRef<OpenMPMapModifierKind> MapModifiers = std::get<2>(LHS);
9710 llvm::is_contained(MapModifiers, clang::OMPC_MAP_MODIFIER_present);
9711 bool HasAllocs = MapType == OMPC_MAP_alloc;
9712 MapModifiers = std::get<2>(RHS);
9713 MapType = std::get<1>(LHS);
9715 llvm::is_contained(MapModifiers, clang::OMPC_MAP_MODIFIER_present);
9716 bool HasAllocsR = MapType == OMPC_MAP_alloc;
9717 return (HasPresent && !HasPresentR) || (HasAllocs && !HasAllocsR);
9753 void addImplicitMapForAttachPtrBaseIfMemberOfCapturedVD(
9754 const ValueDecl *CapturedVD, MapDataArrayTy &DeclComponentLists,
9756 SmallVector<OMPClauseMappableExprCommon::MappableComponent, 8>>
9757 &ComponentVectorStorage)
const {
9758 bool IsThisCapture = CapturedVD ==
nullptr;
9760 for (
const auto &ComponentsAndAttachPtr : AttachPtrExprMap) {
9762 ComponentsWithAttachPtr = ComponentsAndAttachPtr.first;
9763 const Expr *AttachPtrExpr = ComponentsAndAttachPtr.second;
9767 const auto *ME = dyn_cast<MemberExpr>(AttachPtrExpr);
9771 const Expr *
Base = ME->getBase()->IgnoreParenImpCasts();
9792 bool FoundExistingMap =
false;
9793 for (
const MapData &ExistingL : DeclComponentLists) {
9795 ExistingComponents = std::get<0>(ExistingL);
9797 if (ExistingComponents.empty())
9801 const auto &FirstComponent = ExistingComponents.front();
9802 const Expr *FirstExpr = FirstComponent.getAssociatedExpression();
9808 if (AttachPtrComparator.areEqual(FirstExpr, AttachPtrExpr)) {
9809 FoundExistingMap =
true;
9814 if (IsThisCapture) {
9815 if (
const auto *OASE = dyn_cast<ArraySectionExpr>(FirstExpr)) {
9817 FoundExistingMap =
true;
9826 if (
const auto *DRE = dyn_cast<DeclRefExpr>(FirstExpr)) {
9827 if (DRE->getDecl() == CapturedVD) {
9828 FoundExistingMap =
true;
9834 if (FoundExistingMap)
9840 ComponentVectorStorage.emplace_back();
9841 auto &AttachPtrComponents = ComponentVectorStorage.back();
9844 bool SeenAttachPtrComponent =
false;
9850 for (
size_t i = 0; i < ComponentsWithAttachPtr.size(); ++i) {
9851 const auto &Component = ComponentsWithAttachPtr[i];
9852 const Expr *ComponentExpr = Component.getAssociatedExpression();
9854 if (!SeenAttachPtrComponent && ComponentExpr != AttachPtrExpr)
9856 SeenAttachPtrComponent =
true;
9858 AttachPtrComponents.emplace_back(Component.getAssociatedExpression(),
9859 Component.getAssociatedDeclaration(),
9860 Component.isNonContiguous());
9862 assert(!AttachPtrComponents.empty() &&
9863 "Could not populate component-lists for mapping attach-ptr");
9865 DeclComponentLists.emplace_back(
9866 AttachPtrComponents, OMPC_MAP_tofrom,
Unknown,
9867 true,
nullptr, AttachPtrExpr);
9874 void generateInfoForCaptureFromClauseInfo(
9875 const MapDataArrayTy &DeclComponentListsFromClauses,
9876 const CapturedStmt::Capture *Cap, llvm::Value *Arg,
9877 MapCombinedInfoTy &CurCaptureVarInfo, llvm::OpenMPIRBuilder &OMPBuilder,
9878 unsigned OffsetForMemberOfFlag)
const {
9880 "Not expecting to generate map info for a variable array type!");
9889 if (LambdasMap.count(VD))
9895 if (VD && (DevPointersMap.count(VD) || HasDevAddrsMap.count(VD))) {
9896 CurCaptureVarInfo.Exprs.push_back(VD);
9897 CurCaptureVarInfo.BasePointers.emplace_back(Arg);
9898 CurCaptureVarInfo.DevicePtrDecls.emplace_back(VD);
9899 CurCaptureVarInfo.DevicePointers.emplace_back(DeviceInfoTy::Pointer);
9900 CurCaptureVarInfo.Pointers.push_back(Arg);
9901 CurCaptureVarInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
9904 CurCaptureVarInfo.Types.push_back(
9905 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL |
9906 OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM);
9907 CurCaptureVarInfo.Mappers.push_back(
nullptr);
9911 auto GenerateInfoForComponentLists =
9912 [&](ArrayRef<MapData> DeclComponentListsFromClauses,
9913 bool IsEligibleForTargetParamFlag) {
9914 MapCombinedInfoTy CurInfoForComponentLists;
9915 StructRangeInfoTy PartialStruct;
9916 AttachInfoTy AttachInfo;
9918 if (DeclComponentListsFromClauses.empty())
9921 generateInfoForCaptureFromComponentLists(
9922 VD, DeclComponentListsFromClauses, CurInfoForComponentLists,
9923 PartialStruct, AttachInfo, IsEligibleForTargetParamFlag);
9928 if (PartialStruct.Base.isValid()) {
9929 CurCaptureVarInfo.append(PartialStruct.PreliminaryMapData);
9931 CurCaptureVarInfo, CurInfoForComponentLists.Types,
9932 PartialStruct, AttachInfo, Cap->
capturesThis(), OMPBuilder,
9933 nullptr, OffsetForMemberOfFlag,
9934 !IsEligibleForTargetParamFlag);
9939 CurCaptureVarInfo.append(CurInfoForComponentLists);
9940 if (AttachInfo.isValid())
9941 emitAttachEntry(CGF, CurCaptureVarInfo, AttachInfo);
9965 SmallVector<std::pair<const Expr *, MapData>, 16> AttachPtrMapDataPairs;
9967 for (
const MapData &L : DeclComponentListsFromClauses) {
9970 const Expr *AttachPtrExpr = getAttachPtrExpr(Components);
9971 AttachPtrMapDataPairs.emplace_back(AttachPtrExpr, L);
9975 llvm::stable_sort(AttachPtrMapDataPairs,
9976 [
this](
const auto &LHS,
const auto &RHS) {
9977 return AttachPtrComparator(LHS.first, RHS.first);
9980 bool NoDefaultMappingDoneForVD = CurCaptureVarInfo.BasePointers.empty();
9981 bool IsFirstGroup =
true;
9985 auto *It = AttachPtrMapDataPairs.begin();
9986 while (It != AttachPtrMapDataPairs.end()) {
9987 const Expr *AttachPtrExpr = It->first;
9989 MapDataArrayTy GroupLists;
9990 while (It != AttachPtrMapDataPairs.end() &&
9991 (It->first == AttachPtrExpr ||
9992 AttachPtrComparator.areEqual(It->first, AttachPtrExpr))) {
9993 GroupLists.push_back(It->second);
9996 assert(!GroupLists.empty() &&
"GroupLists should not be empty");
10001 bool IsEligibleForTargetParamFlag =
10002 IsFirstGroup && NoDefaultMappingDoneForVD;
10004 GenerateInfoForComponentLists(GroupLists, IsEligibleForTargetParamFlag);
10005 IsFirstGroup =
false;
10012 void generateInfoForCaptureFromComponentLists(
10013 const ValueDecl *VD, ArrayRef<MapData> DeclComponentLists,
10014 MapCombinedInfoTy &CurComponentListInfo, StructRangeInfoTy &PartialStruct,
10015 AttachInfoTy &AttachInfo,
bool IsListEligibleForTargetParamFlag)
const {
10017 llvm::SmallDenseMap<
10024 for (
const MapData &L : DeclComponentLists) {
10027 ArrayRef<OpenMPMapModifierKind> MapModifiers;
10029 const ValueDecl *Mapper;
10030 const Expr *VarRef;
10031 std::tie(Components, MapType, MapModifiers, IsImplicit, Mapper, VarRef) =
10034 for (
const MapData &L1 : ArrayRef(DeclComponentLists).slice(Count)) {
10036 std::tie(Components1, MapType, MapModifiers, IsImplicit, Mapper,
10038 auto CI = Components.rbegin();
10039 auto CE = Components.rend();
10040 auto SI = Components1.rbegin();
10041 auto SE = Components1.rend();
10042 for (; CI != CE && SI != SE; ++CI, ++SI) {
10043 if (CI->getAssociatedExpression()->getStmtClass() !=
10044 SI->getAssociatedExpression()->getStmtClass())
10047 if (CI->getAssociatedDeclaration() != SI->getAssociatedDeclaration())
10052 if (CI == CE || SI == SE) {
10054 if (CI == CE && SI == SE)
10056 const auto It = (SI == SE) ? CI : SI;
10063 (std::prev(It)->getAssociatedDeclaration() &&
10065 ->getAssociatedDeclaration()
10067 ->isPointerType()) ||
10068 (It->getAssociatedDeclaration() &&
10069 It->getAssociatedDeclaration()->getType()->isPointerType() &&
10070 std::next(It) != CE && std::next(It) != SE))
10072 const MapData &BaseData = CI == CE ? L : L1;
10074 SI == SE ? Components : Components1;
10075 OverlappedData[&BaseData].push_back(SubData);
10080 llvm::SmallVector<const FieldDecl *, 4> Layout;
10081 if (!OverlappedData.empty()) {
10084 while (BaseType != OrigType) {
10090 getPlainLayout(CRD, Layout,
false);
10096 for (
auto &Pair : OverlappedData) {
10103 auto CI = First.rbegin();
10104 auto CE = First.rend();
10105 auto SI = Second.rbegin();
10106 auto SE = Second.rend();
10107 for (; CI != CE && SI != SE; ++CI, ++SI) {
10108 if (CI->getAssociatedExpression()->getStmtClass() !=
10109 SI->getAssociatedExpression()->getStmtClass())
10112 if (CI->getAssociatedDeclaration() !=
10113 SI->getAssociatedDeclaration())
10118 if (CI == CE && SI == SE)
10122 if (CI == CE || SI == SE)
10127 if (FD1->getParent() == FD2->getParent())
10128 return FD1->getFieldIndex() < FD2->getFieldIndex();
10130 llvm::find_if(Layout, [FD1, FD2](
const FieldDecl *FD) {
10131 return FD == FD1 || FD == FD2;
10139 bool AddTargetParamFlag = IsListEligibleForTargetParamFlag;
10140 MapCombinedInfoTy StructBaseCombinedInfo;
10141 for (
const auto &Pair : OverlappedData) {
10142 const MapData &L = *Pair.getFirst();
10145 ArrayRef<OpenMPMapModifierKind> MapModifiers;
10147 const ValueDecl *Mapper;
10148 const Expr *VarRef;
10149 std::tie(Components, MapType, MapModifiers, IsImplicit, Mapper, VarRef) =
10151 ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef>
10152 OverlappedComponents = Pair.getSecond();
10153 generateInfoForComponentList(
10154 MapType, MapModifiers, {}, Components, CurComponentListInfo,
10155 StructBaseCombinedInfo, PartialStruct, AttachInfo, AddTargetParamFlag,
10156 IsImplicit,
false, Mapper,
10157 false, VD, VarRef, OverlappedComponents);
10158 AddTargetParamFlag =
false;
10161 for (
const MapData &L : DeclComponentLists) {
10164 ArrayRef<OpenMPMapModifierKind> MapModifiers;
10166 const ValueDecl *Mapper;
10167 const Expr *VarRef;
10168 std::tie(Components, MapType, MapModifiers, IsImplicit, Mapper, VarRef) =
10170 auto It = OverlappedData.find(&L);
10171 if (It == OverlappedData.end())
10172 generateInfoForComponentList(
10173 MapType, MapModifiers, {}, Components, CurComponentListInfo,
10174 StructBaseCombinedInfo, PartialStruct, AttachInfo,
10175 AddTargetParamFlag, IsImplicit,
false,
10176 Mapper,
false, VD, VarRef,
10178 AddTargetParamFlag =
false;
10184 bool isEffectivelyFirstprivate(
const VarDecl *VD, QualType
Type)
const {
10186 auto I = FirstPrivateDecls.find(VD);
10187 if (I != FirstPrivateDecls.end() && !I->getSecond())
10191 if (DefaultmapFirstprivateKinds.count(OMPC_DEFAULTMAP_scalar)) {
10192 if (
Type->isScalarType())
10197 if (DefaultmapFirstprivateKinds.count(OMPC_DEFAULTMAP_pointer)) {
10198 if (
Type->isAnyPointerType())
10203 if (DefaultmapFirstprivateKinds.count(OMPC_DEFAULTMAP_aggregate)) {
10204 if (
Type->isAggregateType())
10209 return DefaultmapFirstprivateKinds.count(OMPC_DEFAULTMAP_all);
10214 void generateDefaultMapInfo(
const CapturedStmt::Capture &CI,
10215 const FieldDecl &RI, llvm::Value *CV,
10216 MapCombinedInfoTy &CombinedInfo)
const {
10217 bool IsImplicit =
true;
10220 CombinedInfo.Exprs.push_back(
nullptr);
10221 CombinedInfo.BasePointers.push_back(CV);
10222 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
10223 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
10224 CombinedInfo.Pointers.push_back(CV);
10226 CombinedInfo.Sizes.push_back(
10230 CombinedInfo.Types.push_back(OpenMPOffloadMappingFlags::OMP_MAP_TO |
10231 OpenMPOffloadMappingFlags::OMP_MAP_FROM);
10235 CombinedInfo.BasePointers.push_back(CV);
10236 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
10237 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
10238 CombinedInfo.Pointers.push_back(CV);
10239 bool IsFirstprivate =
10245 CombinedInfo.Types.push_back(
10246 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL);
10247 CombinedInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
10249 }
else if (IsFirstprivate) {
10252 CombinedInfo.Types.push_back(
10253 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL);
10255 CombinedInfo.Sizes.push_back(llvm::Constant::getNullValue(CGF.
Int64Ty));
10259 CombinedInfo.Types.push_back(OpenMPOffloadMappingFlags::OMP_MAP_NONE);
10260 CombinedInfo.Sizes.push_back(llvm::Constant::getNullValue(CGF.
Int64Ty));
10262 auto I = FirstPrivateDecls.find(VD);
10263 if (I != FirstPrivateDecls.end())
10264 IsImplicit = I->getSecond();
10270 bool IsFirstprivate = isEffectivelyFirstprivate(VD, ElementType);
10272 CombinedInfo.BasePointers.push_back(CV);
10273 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
10274 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
10279 CombinedInfo.Pointers.push_back(CV);
10281 CombinedInfo.Sizes.push_back(llvm::Constant::getNullValue(CGF.
Int64Ty));
10282 CombinedInfo.Types.push_back(
10283 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL);
10285 CombinedInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
10290 CombinedInfo.Types.push_back(getMapModifiersForPrivateClauses(CI));
10291 CombinedInfo.Pointers.push_back(CV);
10293 auto I = FirstPrivateDecls.find(VD);
10294 if (I != FirstPrivateDecls.end())
10295 IsImplicit = I->getSecond();
10298 CombinedInfo.Types.back() |=
10299 OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM;
10303 CombinedInfo.Types.back() |= OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT;
10306 CombinedInfo.Mappers.push_back(
nullptr);
10318 dyn_cast<MemberExpr>(OASE->getBase()->IgnoreParenImpCasts()))
10319 return ME->getMemberDecl();
10325static llvm::Constant *
10327 MappableExprsHandler::MappingExprInfo &MapExprs) {
10329 uint32_t SrcLocStrSize;
10330 if (!MapExprs.getMapDecl() && !MapExprs.getMapExpr())
10331 return OMPBuilder.getOrCreateDefaultSrcLocStr(SrcLocStrSize);
10334 if (!MapExprs.getMapDecl() && MapExprs.getMapExpr()) {
10338 Loc = MapExprs.getMapExpr()->getExprLoc();
10340 Loc = MapExprs.getMapDecl()->getLocation();
10343 std::string ExprName;
10344 if (MapExprs.getMapExpr()) {
10346 llvm::raw_string_ostream OS(ExprName);
10347 MapExprs.getMapExpr()->printPretty(OS,
nullptr, P);
10349 ExprName = MapExprs.getMapDecl()->getNameAsString();
10358 return OMPBuilder.getOrCreateSrcLocStr(
FileName, ExprName, PLoc.
getLine(),
10365 CodeGenFunction &CGF, MappableExprsHandler::MapCombinedInfoTy &CombinedInfo,
10367 bool IsNonContiguous =
false,
bool ForEndCall =
false) {
10370 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
10373 InsertPointTy CodeGenIP(CGF.
Builder.GetInsertBlock(),
10374 CGF.
Builder.GetInsertPoint());
10376 auto DeviceAddrCB = [&](
unsigned int I, llvm::Value *NewDecl) {
10377 if (
const ValueDecl *DevVD = CombinedInfo.DevicePtrDecls[I]) {
10382 auto CustomMapperCB = [&](
unsigned int I) {
10383 llvm::Function *MFunc =
nullptr;
10384 if (CombinedInfo.Mappers[I]) {
10385 Info.HasMapper =
true;
10391 cantFail(OMPBuilder.emitOffloadingArraysAndArgs(
10392 AllocaIP, CodeGenIP, Info, Info.RTArgs, CombinedInfo, CustomMapperCB,
10393 IsNonContiguous, ForEndCall, DeviceAddrCB));
10397static const OMPExecutableDirective *
10399 const auto *CS = D.getInnermostCapturedStmt();
10402 const Stmt *ChildStmt =
10405 if (
const auto *NestedDir =
10406 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) {
10408 switch (D.getDirectiveKind()) {
10414 if (DKind == OMPD_teams) {
10415 Body = NestedDir->getInnermostCapturedStmt()->IgnoreContainers(
10420 if (
const auto *NND =
10421 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) {
10422 DKind = NND->getDirectiveKind();
10428 case OMPD_target_teams:
10432 case OMPD_target_parallel:
10433 case OMPD_target_simd:
10434 case OMPD_target_parallel_for:
10435 case OMPD_target_parallel_for_simd:
10437 case OMPD_target_teams_distribute:
10438 case OMPD_target_teams_distribute_simd:
10439 case OMPD_target_teams_distribute_parallel_for:
10440 case OMPD_target_teams_distribute_parallel_for_simd:
10441 case OMPD_parallel:
10443 case OMPD_parallel_for:
10444 case OMPD_parallel_master:
10445 case OMPD_parallel_sections:
10446 case OMPD_for_simd:
10447 case OMPD_parallel_for_simd:
10449 case OMPD_cancellation_point:
10451 case OMPD_threadprivate:
10452 case OMPD_allocate:
10457 case OMPD_sections:
10461 case OMPD_critical:
10462 case OMPD_taskyield:
10464 case OMPD_taskwait:
10465 case OMPD_taskgroup:
10471 case OMPD_target_data:
10472 case OMPD_target_exit_data:
10473 case OMPD_target_enter_data:
10474 case OMPD_distribute:
10475 case OMPD_distribute_simd:
10476 case OMPD_distribute_parallel_for:
10477 case OMPD_distribute_parallel_for_simd:
10478 case OMPD_teams_distribute:
10479 case OMPD_teams_distribute_simd:
10480 case OMPD_teams_distribute_parallel_for:
10481 case OMPD_teams_distribute_parallel_for_simd:
10482 case OMPD_target_update:
10483 case OMPD_declare_simd:
10484 case OMPD_declare_variant:
10485 case OMPD_begin_declare_variant:
10486 case OMPD_end_declare_variant:
10487 case OMPD_declare_target:
10488 case OMPD_end_declare_target:
10489 case OMPD_declare_reduction:
10490 case OMPD_declare_mapper:
10491 case OMPD_taskloop:
10492 case OMPD_taskloop_simd:
10493 case OMPD_master_taskloop:
10494 case OMPD_master_taskloop_simd:
10495 case OMPD_parallel_master_taskloop:
10496 case OMPD_parallel_master_taskloop_simd:
10497 case OMPD_requires:
10498 case OMPD_metadirective:
10501 llvm_unreachable(
"Unexpected directive.");
10540 if (
UDMMap.count(D) > 0)
10544 auto *MapperVarDecl =
10546 CharUnits ElementSize =
C.getTypeSizeInChars(Ty);
10547 llvm::Type *ElemTy =
CGM.getTypes().ConvertTypeForMem(Ty);
10550 MappableExprsHandler::MapCombinedInfoTy CombinedInfo;
10551 auto PrivatizeAndGenMapInfoCB =
10552 [&](llvm::OpenMPIRBuilder::InsertPointTy CodeGenIP, llvm::Value *PtrPHI,
10553 llvm::Value *BeginArg) -> llvm::OpenMPIRBuilder::MapInfosTy & {
10554 MapperCGF.
Builder.restoreIP(CodeGenIP);
10564 Scope.addPrivate(MapperVarDecl, PtrCurrent);
10565 (void)
Scope.Privatize();
10568 MappableExprsHandler MEHandler(*D, MapperCGF);
10569 MEHandler.generateAllInfoForMapper(CombinedInfo,
OMPBuilder);
10571 auto FillInfoMap = [&](MappableExprsHandler::MappingExprInfo &MapExpr) {
10574 if (
CGM.getCodeGenOpts().getDebugInfo() !=
10575 llvm::codegenoptions::NoDebugInfo) {
10576 CombinedInfo.Names.resize(CombinedInfo.Exprs.size());
10577 llvm::transform(CombinedInfo.Exprs, CombinedInfo.Names.begin(),
10581 return CombinedInfo;
10584 auto CustomMapperCB = [&](
unsigned I) {
10585 llvm::Function *MapperFunc =
nullptr;
10586 if (CombinedInfo.Mappers[I]) {
10590 assert(MapperFunc &&
"Expect a valid mapper function is available.");
10596 llvm::raw_svector_ostream Out(TyStr);
10597 CGM.getCXXABI().getMangleContext().mangleCanonicalTypeName(Ty, Out);
10598 std::string Name =
getName({
"omp_mapper", TyStr, D->
getName()});
10600 llvm::Function *NewFn = cantFail(
OMPBuilder.emitUserDefinedMapper(
10601 PrivatizeAndGenMapInfoCB, ElemTy, Name, CustomMapperCB));
10602 UDMMap.try_emplace(D, NewFn);
10609 auto I =
UDMMap.find(D);
10613 return UDMMap.lookup(D);
10626 Kind != OMPD_target_teams_loop)
10629 return llvm::ConstantInt::get(CGF.
Int64Ty, 0);
10632 if (llvm::Value *NumIterations = SizeEmitter(CGF, *LD))
10633 return NumIterations;
10634 return llvm::ConstantInt::get(CGF.
Int64Ty, 0);
10643 if (OffloadingMandatory) {
10644 CGF.
Builder.CreateUnreachable();
10646 if (RequiresOuterTask) {
10647 CapturedVars.clear();
10651 CapturedVars.end());
10652 Args.push_back(llvm::Constant::getNullValue(CGF.
Builder.getPtrTy()));
10659 llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier>
Device,
10662 llvm::Value *DeviceID;
10663 if (
Device.getPointer()) {
10665 Device.getInt() == OMPC_DEVICE_device_num) &&
10666 "Expected device_num modifier.");
10671 DeviceID = CGF.
Builder.getInt64(OMP_DEVICEID_UNDEF);
10676static std::pair<llvm::Value *, OMPDynGroupprivateFallbackType>
10678 llvm::Value *DynGP = CGF.
Builder.getInt32(0);
10679 auto DynGPFallback = OMPDynGroupprivateFallbackType::Abort;
10683 llvm::Value *DynGPVal =
10687 auto FallbackModifier = DynGPClause->getDynGroupprivateFallbackModifier();
10688 switch (FallbackModifier) {
10689 case OMPC_DYN_GROUPPRIVATE_FALLBACK_abort:
10690 DynGPFallback = OMPDynGroupprivateFallbackType::Abort;
10692 case OMPC_DYN_GROUPPRIVATE_FALLBACK_null:
10693 DynGPFallback = OMPDynGroupprivateFallbackType::Null;
10695 case OMPC_DYN_GROUPPRIVATE_FALLBACK_default_mem:
10698 DynGPFallback = OMPDynGroupprivateFallbackType::DefaultMem;
10701 llvm_unreachable(
"Unknown fallback modifier for OpenMP dyn_groupprivate");
10703 }
else if (
auto *OMPXDynCGClause =
10706 llvm::Value *DynCGMemVal = CGF.
EmitScalarExpr(OMPXDynCGClause->getSize(),
10711 return {DynGP, DynGPFallback};
10717 llvm::OpenMPIRBuilder &OMPBuilder,
10719 MappableExprsHandler::MapCombinedInfoTy &CombinedInfo) {
10721 llvm::DenseMap<llvm::Value *, llvm::Value *> LambdaPointers;
10723 auto *CV = CapturedVars.begin();
10726 CI != CE; ++CI, ++RI, ++CV) {
10727 MappableExprsHandler::MapCombinedInfoTy CurInfo;
10732 CurInfo.Exprs.push_back(
nullptr);
10733 CurInfo.BasePointers.push_back(*CV);
10734 CurInfo.DevicePtrDecls.push_back(
nullptr);
10735 CurInfo.DevicePointers.push_back(
10736 MappableExprsHandler::DeviceInfoTy::None);
10737 CurInfo.Pointers.push_back(*CV);
10738 CurInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
10741 CurInfo.Types.push_back(OpenMPOffloadMappingFlags::OMP_MAP_LITERAL |
10742 OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM |
10743 OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT);
10744 CurInfo.Mappers.push_back(
nullptr);
10749 bool HasEntryWithCVAsAttachPtr =
false;
10751 HasEntryWithCVAsAttachPtr =
10752 MEHandler.hasAttachEntryForCapturedVar(CapturedVD);
10755 MappableExprsHandler::MapDataArrayTy DeclComponentLists;
10758 StorageForImplicitlyAddedComponentLists;
10759 MEHandler.populateComponentListsForNonLambdaCaptureFromClauses(
10760 CapturedVD, DeclComponentLists,
10761 StorageForImplicitlyAddedComponentLists);
10772 bool HasEntryWithoutAttachPtr =
10773 llvm::any_of(DeclComponentLists, [&](
const auto &MapData) {
10775 Components = std::get<0>(MapData);
10776 return !MEHandler.getAttachPtrExpr(Components);
10781 if (DeclComponentLists.empty() ||
10782 (!HasEntryWithCVAsAttachPtr && !HasEntryWithoutAttachPtr))
10783 MEHandler.generateDefaultMapInfo(*CI, **RI, *CV, CurInfo);
10787 MEHandler.generateInfoForCaptureFromClauseInfo(
10788 DeclComponentLists, CI, *CV, CurInfo, OMPBuilder,
10789 CombinedInfo.BasePointers.size());
10794 MappedVarSet.insert(
nullptr);
10799 MEHandler.generateInfoForLambdaCaptures(CI->
getCapturedVar(), *CV,
10800 CurInfo, LambdaPointers);
10803 assert(!CurInfo.BasePointers.empty() &&
10804 "Non-existing map pointer for capture!");
10805 assert(CurInfo.BasePointers.size() == CurInfo.Pointers.size() &&
10806 CurInfo.BasePointers.size() == CurInfo.Sizes.size() &&
10807 CurInfo.BasePointers.size() == CurInfo.Types.size() &&
10808 CurInfo.BasePointers.size() == CurInfo.Mappers.size() &&
10809 "Inconsistent map information sizes!");
10812 CombinedInfo.append(CurInfo);
10815 MEHandler.adjustMemberOfForLambdaCaptures(
10816 OMPBuilder, LambdaPointers, CombinedInfo.BasePointers,
10817 CombinedInfo.Pointers, CombinedInfo.Types);
10821 MappableExprsHandler::MapCombinedInfoTy &CombinedInfo,
10822 llvm::OpenMPIRBuilder &OMPBuilder,
10829 MEHandler.generateAllInfo(CombinedInfo, OMPBuilder, SkippedVarSet);
10831 auto FillInfoMap = [&](MappableExprsHandler::MappingExprInfo &MapExpr) {
10835 llvm::codegenoptions::NoDebugInfo) {
10836 CombinedInfo.Names.resize(CombinedInfo.Exprs.size());
10837 llvm::transform(CombinedInfo.Exprs, CombinedInfo.Names.begin(),
10845 llvm::OpenMPIRBuilder &OMPBuilder,
10846 MappableExprsHandler::MapCombinedInfoTy &CombinedInfo) {
10848 MappableExprsHandler MEHandler(D, CGF);
10849 llvm::DenseSet<CanonicalDeclPtr<const Decl>> MappedVarSet;
10852 MappedVarSet, CombinedInfo);
10853 genMapInfo(MEHandler, CGF, CombinedInfo, OMPBuilder, MappedVarSet);
10856template <
typename ClauseTy>
10861 const auto *
C = D.getSingleClause<ClauseTy>();
10862 assert(!
C->varlist_empty() &&
10863 "ompx_bare requires explicit num_teams and thread_limit");
10865 for (
auto *E :
C->varlist()) {
10877 llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier>
Device,
10879 llvm::Value *&MapTypesArray, llvm::Value *&MapNamesArray,
10884 llvm::OpenMPIRBuilder &OMPBuilder = OMPRuntime->
getOMPBuilder();
10887 MappableExprsHandler::MapCombinedInfoTy CombinedInfo;
10889 genMapInfo(D, CGF, CS, CapturedVars, OMPBuilder, CombinedInfo);
10892 using OpenMPOffloadMappingFlags = llvm::omp::OpenMPOffloadMappingFlags;
10893 auto *NullPtr = llvm::Constant::getNullValue(CGF.
Builder.getPtrTy());
10894 CombinedInfo.BasePointers.push_back(NullPtr);
10895 CombinedInfo.Pointers.push_back(NullPtr);
10896 CombinedInfo.DevicePointers.push_back(
10897 llvm::OpenMPIRBuilder::DeviceInfoTy::None);
10898 CombinedInfo.Sizes.push_back(CGF.
Builder.getInt64(0));
10899 CombinedInfo.Types.push_back(OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM |
10900 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL);
10901 if (!CombinedInfo.Names.empty())
10902 CombinedInfo.Names.push_back(NullPtr);
10903 CombinedInfo.Exprs.push_back(
nullptr);
10904 CombinedInfo.Mappers.push_back(
nullptr);
10905 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
10919 MapTypesArray = Info.RTArgs.MapTypesArray;
10920 MapNamesArray = Info.RTArgs.MapNamesArray;
10922 auto &&ThenGen = [&OMPRuntime, OutlinedFn, &D, &CapturedVars,
10923 RequiresOuterTask, &CS, OffloadingMandatory,
Device,
10924 OutlinedFnID, &InputInfo, &MapTypesArray, &MapNamesArray,
10926 bool IsReverseOffloading =
Device.getInt() == OMPC_DEVICE_ancestor;
10928 if (IsReverseOffloading) {
10934 RequiresOuterTask, CS, OffloadingMandatory, CGF);
10938 bool HasNoWait = D.hasClausesOfKind<OMPNowaitClause>();
10939 unsigned NumTargetItems = InputInfo.NumberOfTargetItems;
10941 llvm::Value *BasePointersArray =
10942 InputInfo.BasePointersArray.emitRawPointer(CGF);
10943 llvm::Value *PointersArray = InputInfo.PointersArray.emitRawPointer(CGF);
10944 llvm::Value *SizesArray = InputInfo.SizesArray.emitRawPointer(CGF);
10945 llvm::Value *MappersArray = InputInfo.MappersArray.emitRawPointer(CGF);
10947 auto &&EmitTargetCallFallbackCB =
10948 [&OMPRuntime, OutlinedFn, &D, &CapturedVars, RequiresOuterTask, &CS,
10949 OffloadingMandatory, &CGF](llvm::OpenMPIRBuilder::InsertPointTy IP)
10950 -> llvm::OpenMPIRBuilder::InsertPointTy {
10953 RequiresOuterTask, CS, OffloadingMandatory, CGF);
10966 NumThreads.push_back(
10972 llvm::Value *NumIterations =
10975 llvm::OpenMPIRBuilder::InsertPointTy AllocaIP(
10978 llvm::OpenMPIRBuilder::TargetDataRTArgs RTArgs(
10979 BasePointersArray, PointersArray, SizesArray, MapTypesArray,
10980 nullptr , MappersArray, MapNamesArray);
10982 llvm::OpenMPIRBuilder::TargetKernelArgs Args(
10983 NumTargetItems, RTArgs, NumIterations, NumTeams, NumThreads,
10984 DynCGroupMem, HasNoWait, DynCGroupMemFallback);
10986 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
10988 CGF.
Builder, OutlinedFnID, EmitTargetCallFallbackCB, Args, DeviceID,
10990 CGF.
Builder.restoreIP(AfterIP);
10993 if (RequiresOuterTask)
11008 [&OMPRuntime, OutlinedFn, &D, &CapturedVars, RequiresOuterTask, &CS,
11011 RequiresOuterTask, CS, OffloadingMandatory, CGF);
11014 if (RequiresOuterTask) {
11024 llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID,
const Expr *IfCond,
11025 llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier>
Device,
11032 const bool OffloadingMandatory = !
CGM.getLangOpts().OpenMPIsTargetDevice &&
11033 CGM.getLangOpts().OpenMPOffloadMandatory;
11035 assert((OffloadingMandatory || OutlinedFn) &&
"Invalid outlined function!");
11037 const bool RequiresOuterTask =
11039 D.hasClausesOfKind<OMPNowaitClause>() ||
11040 D.hasClausesOfKind<OMPInReductionClause>() ||
11041 (
CGM.getLangOpts().OpenMP >= 51 &&
11045 const CapturedStmt &CS = *D.getCapturedStmt(OMPD_target);
11053 llvm::Value *MapTypesArray =
nullptr;
11054 llvm::Value *MapNamesArray =
nullptr;
11056 auto &&TargetThenGen = [
this, OutlinedFn, &D, &CapturedVars,
11057 RequiresOuterTask, &CS, OffloadingMandatory,
Device,
11058 OutlinedFnID, &InputInfo, &MapTypesArray,
11062 RequiresOuterTask, CS, OffloadingMandatory,
11063 Device, OutlinedFnID, InputInfo, MapTypesArray,
11064 MapNamesArray, SizeEmitter, CGF,
CGM);
11067 auto &&TargetElseGen =
11068 [
this, OutlinedFn, &D, &CapturedVars, RequiresOuterTask, &CS,
11071 CS, OffloadingMandatory, CGF);
11078 if (OutlinedFnID) {
11080 emitIfClause(CGF, IfCond, TargetThenGen, TargetElseGen);
11092 StringRef ParentName) {
11099 if (
auto *E = dyn_cast<OMPExecutableDirective>(S);
11108 bool RequiresDeviceCodegen =
11113 if (RequiresDeviceCodegen) {
11121 if (!
OMPBuilder.OffloadInfoManager.hasTargetRegionEntryInfo(EntryInfo))
11124 switch (E.getDirectiveKind()) {
11129 case OMPD_target_parallel:
11133 case OMPD_target_teams:
11137 case OMPD_target_teams_distribute:
11141 case OMPD_target_teams_distribute_simd:
11145 case OMPD_target_parallel_for:
11149 case OMPD_target_parallel_for_simd:
11153 case OMPD_target_simd:
11157 case OMPD_target_teams_distribute_parallel_for:
11162 case OMPD_target_teams_distribute_parallel_for_simd:
11168 case OMPD_target_teams_loop:
11172 case OMPD_target_parallel_loop:
11176 case OMPD_parallel:
11178 case OMPD_parallel_for:
11179 case OMPD_parallel_master:
11180 case OMPD_parallel_sections:
11181 case OMPD_for_simd:
11182 case OMPD_parallel_for_simd:
11184 case OMPD_cancellation_point:
11186 case OMPD_threadprivate:
11187 case OMPD_allocate:
11192 case OMPD_sections:
11196 case OMPD_critical:
11197 case OMPD_taskyield:
11199 case OMPD_taskwait:
11200 case OMPD_taskgroup:
11206 case OMPD_target_data:
11207 case OMPD_target_exit_data:
11208 case OMPD_target_enter_data:
11209 case OMPD_distribute:
11210 case OMPD_distribute_simd:
11211 case OMPD_distribute_parallel_for:
11212 case OMPD_distribute_parallel_for_simd:
11213 case OMPD_teams_distribute:
11214 case OMPD_teams_distribute_simd:
11215 case OMPD_teams_distribute_parallel_for:
11216 case OMPD_teams_distribute_parallel_for_simd:
11217 case OMPD_target_update:
11218 case OMPD_declare_simd:
11219 case OMPD_declare_variant:
11220 case OMPD_begin_declare_variant:
11221 case OMPD_end_declare_variant:
11222 case OMPD_declare_target:
11223 case OMPD_end_declare_target:
11224 case OMPD_declare_reduction:
11225 case OMPD_declare_mapper:
11226 case OMPD_taskloop:
11227 case OMPD_taskloop_simd:
11228 case OMPD_master_taskloop:
11229 case OMPD_master_taskloop_simd:
11230 case OMPD_parallel_master_taskloop:
11231 case OMPD_parallel_master_taskloop_simd:
11232 case OMPD_requires:
11233 case OMPD_metadirective:
11236 llvm_unreachable(
"Unknown target directive for OpenMP device codegen.");
11241 if (
const auto *E = dyn_cast<OMPExecutableDirective>(S)) {
11242 if (!E->hasAssociatedStmt() || !E->getAssociatedStmt())
11250 if (
const auto *L = dyn_cast<LambdaExpr>(S))
11259 std::optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
11260 OMPDeclareTargetDeclAttr::getDeviceType(VD);
11264 if (!IsDevice && DevTy == OMPDeclareTargetDeclAttr::DT_NoHost)
11267 if (IsDevice && DevTy == OMPDeclareTargetDeclAttr::DT_Host)
11275 if (!
CGM.getLangOpts().OpenMPIsTargetDevice) {
11276 if (
const auto *FD = dyn_cast<FunctionDecl>(GD.
getDecl()))
11278 CGM.getLangOpts().OpenMPIsTargetDevice))
11285 if (
const auto *FD = dyn_cast<FunctionDecl>(VD)) {
11286 StringRef Name =
CGM.getMangledName(GD);
11289 CGM.getLangOpts().OpenMPIsTargetDevice))
11294 return !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD) &&
11300 CGM.getLangOpts().OpenMPIsTargetDevice))
11303 if (!
CGM.getLangOpts().OpenMPIsTargetDevice)
11312 StringRef ParentName =
11317 StringRef ParentName =
11324 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
11325 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(
11327 if (!Res || *Res == OMPDeclareTargetDeclAttr::MT_Link ||
11328 ((*Res == OMPDeclareTargetDeclAttr::MT_To ||
11329 *Res == OMPDeclareTargetDeclAttr::MT_Enter ||
11330 *Res == OMPDeclareTargetDeclAttr::MT_Local) &&
11339 llvm::Constant *
Addr) {
11340 if (
CGM.getLangOpts().OMPTargetTriples.empty() &&
11341 !
CGM.getLangOpts().OpenMPIsTargetDevice)
11344 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
11345 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
11349 if (Res && *Res != OMPDeclareTargetDeclAttr::MT_Link &&
11354 if (
CGM.getLangOpts().OpenMPIsTargetDevice) {
11357 StringRef VarName =
CGM.getMangledName(VD);
11363 auto AddrOfGlobal = [&VD,
this]() {
return CGM.GetAddrOfGlobal(VD); };
11364 auto LinkageForVariable = [&VD,
this]() {
11365 return CGM.getLLVMLinkageVarDefinition(VD);
11368 std::vector<llvm::GlobalVariable *> GeneratedRefs;
11375 CGM.getMangledName(VD), GeneratedRefs,
CGM.getLangOpts().OpenMPSimd,
11376 CGM.getLangOpts().OMPTargetTriples, AddrOfGlobal, LinkageForVariable,
11377 CGM.getTypes().ConvertTypeForMem(
11378 CGM.getContext().getPointerType(VD->
getType())),
11381 for (
auto *ref : GeneratedRefs)
11382 CGM.addCompilerUsedGlobal(ref);
11395 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
11396 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
11399 if ((*Res == OMPDeclareTargetDeclAttr::MT_To ||
11400 *Res == OMPDeclareTargetDeclAttr::MT_Enter ||
11401 *Res == OMPDeclareTargetDeclAttr::MT_Local) &&
11403 CGM.EmitGlobal(VD);
11405 assert((*Res == OMPDeclareTargetDeclAttr::MT_Link ||
11406 ((*Res == OMPDeclareTargetDeclAttr::MT_To ||
11407 *Res == OMPDeclareTargetDeclAttr::MT_Enter ||
11408 *Res == OMPDeclareTargetDeclAttr::MT_Local) &&
11410 "Expected link clause or to clause with unified memory.");
11411 (void)
CGM.getOpenMPRuntime().getAddrOfDeclareTargetVar(VD);
11419 " Expected target-based directive.");
11424 if (Clause->getClauseKind() == OMPC_unified_shared_memory) {
11426 OMPBuilder.Config.setHasRequiresUnifiedSharedMemory(
true);
11427 }
else if (
const auto *AC =
11428 dyn_cast<OMPAtomicDefaultMemOrderClause>(Clause)) {
11429 switch (AC->getAtomicDefaultMemOrderKind()) {
11430 case OMPC_ATOMIC_DEFAULT_MEM_ORDER_acq_rel:
11433 case OMPC_ATOMIC_DEFAULT_MEM_ORDER_seq_cst:
11436 case OMPC_ATOMIC_DEFAULT_MEM_ORDER_relaxed:
11452 if (!VD || !VD->
hasAttr<OMPAllocateDeclAttr>())
11454 const auto *A = VD->
getAttr<OMPAllocateDeclAttr>();
11455 switch(A->getAllocatorType()) {
11456 case OMPAllocateDeclAttr::OMPNullMemAlloc:
11457 case OMPAllocateDeclAttr::OMPDefaultMemAlloc:
11459 case OMPAllocateDeclAttr::OMPLargeCapMemAlloc:
11460 case OMPAllocateDeclAttr::OMPCGroupMemAlloc:
11461 case OMPAllocateDeclAttr::OMPHighBWMemAlloc:
11462 case OMPAllocateDeclAttr::OMPLowLatMemAlloc:
11463 case OMPAllocateDeclAttr::OMPThreadMemAlloc:
11464 case OMPAllocateDeclAttr::OMPConstMemAlloc:
11465 case OMPAllocateDeclAttr::OMPPTeamMemAlloc:
11468 case OMPAllocateDeclAttr::OMPUserDefinedMemAlloc:
11469 llvm_unreachable(
"Expected predefined allocator for the variables with the "
11470 "static storage.");
11482 if (CGM.getLangOpts().OpenMPIsTargetDevice) {
11483 SavedShouldMarkAsGlobal = CGM.getOpenMPRuntime().ShouldMarkAsGlobal;
11484 CGM.getOpenMPRuntime().ShouldMarkAsGlobal = false;
11489 if (CGM.getLangOpts().OpenMPIsTargetDevice)
11490 CGM.getOpenMPRuntime().ShouldMarkAsGlobal = SavedShouldMarkAsGlobal;
11500 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(D)) {
11502 if (
auto *F = dyn_cast_or_null<llvm::Function>(
11503 CGM.GetGlobalValue(
CGM.getMangledName(GD))))
11504 return !F->isDeclaration();
11516 llvm::Function *OutlinedFn,
11525 llvm::Value *Args[] = {
11527 CGF.
Builder.getInt32(CapturedVars.size()),
11530 RealArgs.append(std::begin(Args), std::end(Args));
11531 RealArgs.append(CapturedVars.begin(), CapturedVars.end());
11533 llvm::FunctionCallee RTLFn =
OMPBuilder.getOrCreateRuntimeFunction(
11534 CGM.getModule(), OMPRTL___kmpc_fork_teams);
11539 const Expr *NumTeams,
11540 const Expr *ThreadLimit,
11547 llvm::Value *NumTeamsVal =
11553 llvm::Value *ThreadLimitVal =
11560 llvm::Value *PushNumTeamsArgs[] = {RTLoc,
getThreadID(CGF, Loc), NumTeamsVal,
11563 CGM.getModule(), OMPRTL___kmpc_push_num_teams),
11568 const Expr *ThreadLimit,
11571 llvm::Value *ThreadLimitVal =
11578 llvm::Value *ThreadLimitArgs[] = {RTLoc,
getThreadID(CGF, Loc),
11581 CGM.getModule(), OMPRTL___kmpc_set_thread_limit),
11596 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
11598 llvm::Value *IfCondVal =
nullptr;
11603 llvm::Value *DeviceID =
nullptr;
11608 DeviceID = CGF.
Builder.getInt64(OMP_DEVICEID_UNDEF);
11612 MappableExprsHandler::MapCombinedInfoTy CombinedInfo;
11613 auto GenMapInfoCB =
11614 [&](InsertPointTy CodeGenIP) -> llvm::OpenMPIRBuilder::MapInfosTy & {
11615 CGF.
Builder.restoreIP(CodeGenIP);
11617 MappableExprsHandler MEHandler(D, CGF);
11618 MEHandler.generateAllInfo(CombinedInfo,
OMPBuilder);
11620 auto FillInfoMap = [&](MappableExprsHandler::MappingExprInfo &MapExpr) {
11623 if (
CGM.getCodeGenOpts().getDebugInfo() !=
11624 llvm::codegenoptions::NoDebugInfo) {
11625 CombinedInfo.Names.resize(CombinedInfo.Exprs.size());
11626 llvm::transform(CombinedInfo.Exprs, CombinedInfo.Names.begin(),
11630 return CombinedInfo;
11632 using BodyGenTy = llvm::OpenMPIRBuilder::BodyGenTy;
11633 auto BodyCB = [&](InsertPointTy CodeGenIP, BodyGenTy BodyGenType) {
11634 CGF.
Builder.restoreIP(CodeGenIP);
11635 switch (BodyGenType) {
11636 case BodyGenTy::Priv:
11640 case BodyGenTy::DupNoPriv:
11642 CodeGen.setAction(NoPrivAction);
11646 case BodyGenTy::NoPriv:
11648 CodeGen.setAction(NoPrivAction);
11653 return InsertPointTy(CGF.
Builder.GetInsertBlock(),
11654 CGF.
Builder.GetInsertPoint());
11657 auto DeviceAddrCB = [&](
unsigned int I, llvm::Value *NewDecl) {
11658 if (
const ValueDecl *DevVD = CombinedInfo.DevicePtrDecls[I]) {
11663 auto CustomMapperCB = [&](
unsigned int I) {
11664 llvm::Function *MFunc =
nullptr;
11665 if (CombinedInfo.Mappers[I]) {
11666 Info.HasMapper =
true;
11678 InsertPointTy CodeGenIP(CGF.
Builder.GetInsertBlock(),
11679 CGF.
Builder.GetInsertPoint());
11680 llvm::OpenMPIRBuilder::LocationDescription OmpLoc(CodeGenIP);
11681 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
11683 OmpLoc, AllocaIP, CodeGenIP, DeviceID, IfCondVal, Info, GenMapInfoCB,
11685 nullptr, BodyCB, DeviceAddrCB, RTLoc));
11686 CGF.
Builder.restoreIP(AfterIP);
11698 "Expecting either target enter, exit data, or update directives.");
11701 llvm::Value *MapTypesArray =
nullptr;
11702 llvm::Value *MapNamesArray =
nullptr;
11704 auto &&ThenGen = [
this, &D,
Device, &InputInfo, &MapTypesArray,
11707 llvm::Value *DeviceID =
nullptr;
11712 DeviceID = CGF.
Builder.getInt64(OMP_DEVICEID_UNDEF);
11716 llvm::Constant *PointerNum =
11723 {RTLoc, DeviceID, PointerNum,
11731 const bool HasNowait = D.hasClausesOfKind<OMPNowaitClause>();
11732 RuntimeFunction RTLFn;
11733 switch (D.getDirectiveKind()) {
11734 case OMPD_target_enter_data:
11735 RTLFn = HasNowait ? OMPRTL___tgt_target_data_begin_nowait_mapper
11736 : OMPRTL___tgt_target_data_begin_mapper;
11738 case OMPD_target_exit_data:
11739 RTLFn = HasNowait ? OMPRTL___tgt_target_data_end_nowait_mapper
11740 : OMPRTL___tgt_target_data_end_mapper;
11742 case OMPD_target_update:
11743 RTLFn = HasNowait ? OMPRTL___tgt_target_data_update_nowait_mapper
11744 : OMPRTL___tgt_target_data_update_mapper;
11746 case OMPD_parallel:
11748 case OMPD_parallel_for:
11749 case OMPD_parallel_master:
11750 case OMPD_parallel_sections:
11751 case OMPD_for_simd:
11752 case OMPD_parallel_for_simd:
11754 case OMPD_cancellation_point:
11756 case OMPD_threadprivate:
11757 case OMPD_allocate:
11762 case OMPD_sections:
11766 case OMPD_critical:
11767 case OMPD_taskyield:
11769 case OMPD_taskwait:
11770 case OMPD_taskgroup:
11776 case OMPD_target_data:
11777 case OMPD_distribute:
11778 case OMPD_distribute_simd:
11779 case OMPD_distribute_parallel_for:
11780 case OMPD_distribute_parallel_for_simd:
11781 case OMPD_teams_distribute:
11782 case OMPD_teams_distribute_simd:
11783 case OMPD_teams_distribute_parallel_for:
11784 case OMPD_teams_distribute_parallel_for_simd:
11785 case OMPD_declare_simd:
11786 case OMPD_declare_variant:
11787 case OMPD_begin_declare_variant:
11788 case OMPD_end_declare_variant:
11789 case OMPD_declare_target:
11790 case OMPD_end_declare_target:
11791 case OMPD_declare_reduction:
11792 case OMPD_declare_mapper:
11793 case OMPD_taskloop:
11794 case OMPD_taskloop_simd:
11795 case OMPD_master_taskloop:
11796 case OMPD_master_taskloop_simd:
11797 case OMPD_parallel_master_taskloop:
11798 case OMPD_parallel_master_taskloop_simd:
11800 case OMPD_target_simd:
11801 case OMPD_target_teams_distribute:
11802 case OMPD_target_teams_distribute_simd:
11803 case OMPD_target_teams_distribute_parallel_for:
11804 case OMPD_target_teams_distribute_parallel_for_simd:
11805 case OMPD_target_teams:
11806 case OMPD_target_parallel:
11807 case OMPD_target_parallel_for:
11808 case OMPD_target_parallel_for_simd:
11809 case OMPD_requires:
11810 case OMPD_metadirective:
11813 llvm_unreachable(
"Unexpected standalone target data directive.");
11817 OffloadingArgs.push_back(llvm::Constant::getNullValue(CGF.
Int32Ty));
11818 OffloadingArgs.push_back(llvm::Constant::getNullValue(CGF.
VoidPtrTy));
11819 OffloadingArgs.push_back(llvm::Constant::getNullValue(CGF.
Int32Ty));
11820 OffloadingArgs.push_back(llvm::Constant::getNullValue(CGF.
VoidPtrTy));
11823 OMPBuilder.getOrCreateRuntimeFunction(
CGM.getModule(), RTLFn),
11827 auto &&TargetThenGen = [
this, &ThenGen, &D, &InputInfo, &MapTypesArray,
11831 MappableExprsHandler::MapCombinedInfoTy CombinedInfo;
11833 MappableExprsHandler MEHandler(D, CGF);
11839 D.hasClausesOfKind<OMPNowaitClause>();
11845 CGM.getPointerAlign());
11850 MapTypesArray = Info.RTArgs.MapTypesArray;
11851 MapNamesArray = Info.RTArgs.MapNamesArray;
11852 if (RequiresOuterTask)
11897 unsigned Offset = 0;
11898 if (
const auto *MD = dyn_cast<CXXMethodDecl>(FD)) {
11899 if (ParamAttrs[Offset].Kind ==
11900 llvm::OpenMPIRBuilder::DeclareSimdKindTy::Vector)
11901 CDT =
C.getPointerType(
C.getCanonicalTagType(MD->
getParent()));
11905 for (
unsigned I = 0, E = FD->
getNumParams(); I < E; ++I) {
11906 if (ParamAttrs[I + Offset].Kind ==
11907 llvm::OpenMPIRBuilder::DeclareSimdKindTy::Vector) {
11919 return C.getTypeSize(CDT);
11930 llvm::OpenMPIRBuilder::DeclareSimdKindTy Kind) {
11936 if (Kind == llvm::OpenMPIRBuilder::DeclareSimdKindTy::Uniform)
11939 if (Kind == llvm::OpenMPIRBuilder::DeclareSimdKindTy::LinearUVal ||
11940 Kind == llvm::OpenMPIRBuilder::DeclareSimdKindTy::LinearRef)
11943 if ((Kind == llvm::OpenMPIRBuilder::DeclareSimdKindTy::Linear ||
11944 Kind == llvm::OpenMPIRBuilder::DeclareSimdKindTy::LinearVal) &&
11954 unsigned Size =
C.getTypeSize(QT);
11957 if (Size != 8 && Size != 16 && Size != 32 && Size != 64 && Size != 128)
11978 llvm::OpenMPIRBuilder::DeclareSimdKindTy Kind,
11983 return C.getTypeSize(PTy);
11986 return C.getTypeSize(QT);
11988 return C.getTypeSize(
C.getUIntPtrType());
11994static std::tuple<unsigned, unsigned, bool>
12001 bool OutputBecomesInput =
false;
12006 RetType, llvm::OpenMPIRBuilder::DeclareSimdKindTy::Vector,
C));
12008 OutputBecomesInput =
true;
12010 for (
unsigned I = 0, E = FD->
getNumParams(); I < E; ++I) {
12015 assert(!Sizes.empty() &&
"Unable to determine NDS and WDS.");
12018 assert(llvm::all_of(Sizes,
12019 [](
unsigned Size) {
12020 return Size == 8 || Size == 16 || Size == 32 ||
12021 Size == 64 || Size == 128;
12025 return std::make_tuple(*llvm::min_element(Sizes), *llvm::max_element(Sizes),
12026 OutputBecomesInput);
12029static llvm::OpenMPIRBuilder::DeclareSimdBranch
12032 case OMPDeclareSimdDeclAttr::BS_Undefined:
12033 return llvm::OpenMPIRBuilder::DeclareSimdBranch::Undefined;
12034 case OMPDeclareSimdDeclAttr::BS_Inbranch:
12035 return llvm::OpenMPIRBuilder::DeclareSimdBranch::Inbranch;
12036 case OMPDeclareSimdDeclAttr::BS_Notinbranch:
12037 return llvm::OpenMPIRBuilder::DeclareSimdBranch::Notinbranch;
12039 llvm_unreachable(
"unexpected declare simd branch state");
12044 unsigned UserVLEN,
unsigned WDS,
char ISA) {
12046 if (UserVLEN == 1) {
12053 if (ISA ==
'n' && UserVLEN && !llvm::isPowerOf2_32(UserVLEN)) {
12059 if (ISA ==
's' && UserVLEN != 0 &&
12060 ((UserVLEN * WDS > 2048) || (UserVLEN * WDS % 128 != 0))) {
12069 llvm::Function *Fn) {
12074 llvm::DenseMap<const Decl *, unsigned> ParamPositions;
12076 ParamPositions.try_emplace(FD, 0);
12077 unsigned ParamPos = ParamPositions.size();
12079 ParamPositions.try_emplace(P->getCanonicalDecl(), ParamPos);
12084 ParamPositions.size());
12086 for (
const Expr *E :
Attr->uniforms()) {
12090 Pos = ParamPositions[FD];
12093 ->getCanonicalDecl();
12094 auto It = ParamPositions.find(PVD);
12095 assert(It != ParamPositions.end() &&
"Function parameter not found");
12098 ParamAttrs[Pos].Kind =
12099 llvm::OpenMPIRBuilder::DeclareSimdKindTy::Uniform;
12102 auto *NI =
Attr->alignments_begin();
12103 for (
const Expr *E :
Attr->aligneds()) {
12108 Pos = ParamPositions[FD];
12112 ->getCanonicalDecl();
12113 auto It = ParamPositions.find(PVD);
12114 assert(It != ParamPositions.end() &&
"Function parameter not found");
12116 ParmTy = PVD->getType();
12118 ParamAttrs[Pos].Alignment =
12120 ? (*NI)->EvaluateKnownConstInt(
C)
12121 : llvm::APSInt::getUnsigned(
12122 C.toCharUnitsFromBits(
C.getOpenMPDefaultSimdAlign(ParmTy))
12127 auto *SI =
Attr->steps_begin();
12128 auto *MI =
Attr->modifiers_begin();
12129 for (
const Expr *E :
Attr->linears()) {
12132 bool IsReferenceType =
false;
12135 unsigned PtrRescalingFactor = 1;
12137 Pos = ParamPositions[FD];
12139 PtrRescalingFactor =
CGM.getContext()
12140 .getTypeSizeInChars(P->getPointeeType())
12144 ->getCanonicalDecl();
12145 auto It = ParamPositions.find(PVD);
12146 assert(It != ParamPositions.end() &&
"Function parameter not found");
12148 if (
auto *P = dyn_cast<PointerType>(PVD->getType()))
12149 PtrRescalingFactor =
CGM.getContext()
12150 .getTypeSizeInChars(P->getPointeeType())
12152 else if (PVD->getType()->isReferenceType()) {
12153 IsReferenceType =
true;
12154 PtrRescalingFactor =
12156 .getTypeSizeInChars(PVD->getType().getNonReferenceType())
12160 llvm::OpenMPIRBuilder::DeclareSimdAttrTy &ParamAttr = ParamAttrs[Pos];
12161 if (*MI == OMPC_LINEAR_ref)
12162 ParamAttr.Kind = llvm::OpenMPIRBuilder::DeclareSimdKindTy::LinearRef;
12163 else if (*MI == OMPC_LINEAR_uval)
12164 ParamAttr.Kind = llvm::OpenMPIRBuilder::DeclareSimdKindTy::LinearUVal;
12165 else if (IsReferenceType)
12166 ParamAttr.Kind = llvm::OpenMPIRBuilder::DeclareSimdKindTy::LinearVal;
12168 ParamAttr.Kind = llvm::OpenMPIRBuilder::DeclareSimdKindTy::Linear;
12170 ParamAttr.StrideOrArg = llvm::APSInt::getUnsigned(1);
12174 if (
const auto *DRE =
12176 if (
const auto *StridePVD =
12177 dyn_cast<ParmVarDecl>(DRE->getDecl())) {
12178 ParamAttr.HasVarStride =
true;
12179 auto It = ParamPositions.find(StridePVD->getCanonicalDecl());
12180 assert(It != ParamPositions.end() &&
12181 "Function parameter not found");
12182 ParamAttr.StrideOrArg = llvm::APSInt::getUnsigned(It->second);
12186 ParamAttr.StrideOrArg =
Result.Val.getInt();
12192 if (!ParamAttr.HasVarStride &&
12194 llvm::OpenMPIRBuilder::DeclareSimdKindTy::Linear ||
12196 llvm::OpenMPIRBuilder::DeclareSimdKindTy::LinearRef))
12197 ParamAttr.StrideOrArg = ParamAttr.StrideOrArg * PtrRescalingFactor;
12201 llvm::APSInt VLENVal;
12203 const Expr *VLENExpr =
Attr->getSimdlen();
12208 llvm::OpenMPIRBuilder::DeclareSimdBranch State =
12210 if (
CGM.getTriple().isX86()) {
12212 assert(NumElts &&
"Non-zero simdlen/cdtsize expected");
12213 OMPBuilder.emitX86DeclareSimdFunction(Fn, NumElts, VLENVal, ParamAttrs,
12215 }
else if (
CGM.getTriple().getArch() == llvm::Triple::aarch64) {
12216 unsigned VLEN = VLENVal.getExtValue();
12219 const unsigned NDS = std::get<0>(
Data);
12220 const unsigned WDS = std::get<1>(
Data);
12221 const bool OutputBecomesInput = std::get<2>(
Data);
12222 if (
CGM.getTarget().hasFeature(
"sve")) {
12225 Fn, VLEN, ParamAttrs, State,
's', NDS, OutputBecomesInput);
12226 }
else if (
CGM.getTarget().hasFeature(
"neon")) {
12229 Fn, VLEN, ParamAttrs, State,
'n', NDS, OutputBecomesInput);
12239class DoacrossCleanupTy final :
public EHScopeStack::Cleanup {
12241 static const int DoacrossFinArgs = 2;
12244 llvm::FunctionCallee RTLFn;
12245 llvm::Value *Args[DoacrossFinArgs];
12248 DoacrossCleanupTy(llvm::FunctionCallee RTLFn,
12251 assert(CallArgs.size() == DoacrossFinArgs);
12252 std::copy(CallArgs.begin(), CallArgs.end(), std::begin(Args));
12269 QualType Int64Ty =
C.getIntTypeForBitwidth(64,
true);
12277 RD =
C.buildImplicitRecord(
"kmp_dim");
12285 RD =
KmpDimTy->castAsRecordDecl();
12287 llvm::APInt Size(32, NumIterations.size());
12293 enum { LowerFD = 0, UpperFD, StrideFD };
12295 for (
unsigned I = 0, E = NumIterations.size(); I < E; ++I) {
12300 DimsLVal, *std::next(RD->
field_begin(), UpperFD));
12302 CGF.
EmitScalarExpr(NumIterations[I]), NumIterations[I]->getType(),
12303 Int64Ty, NumIterations[I]->getExprLoc());
12307 DimsLVal, *std::next(RD->
field_begin(), StrideFD));
12314 llvm::Value *Args[] = {
12317 llvm::ConstantInt::getSigned(
CGM.Int32Ty, NumIterations.size()),
12322 llvm::FunctionCallee RTLFn =
OMPBuilder.getOrCreateRuntimeFunction(
12323 CGM.getModule(), OMPRTL___kmpc_doacross_init);
12325 llvm::Value *FiniArgs[DoacrossCleanupTy::DoacrossFinArgs] = {
12327 llvm::FunctionCallee FiniRTLFn =
OMPBuilder.getOrCreateRuntimeFunction(
12328 CGM.getModule(), OMPRTL___kmpc_doacross_fini);
12333template <
typename T>
12335 const T *
C, llvm::Value *ULoc,
12336 llvm::Value *ThreadID) {
12339 llvm::APInt Size(32,
C->getNumLoops());
12343 for (
unsigned I = 0, E =
C->getNumLoops(); I < E; ++I) {
12344 const Expr *CounterVal =
C->getLoopData(I);
12345 assert(CounterVal);
12352 llvm::Value *Args[] = {
12355 llvm::FunctionCallee RTLFn;
12357 OMPDoacrossKind<T> ODK;
12358 if (ODK.isSource(
C)) {
12360 OMPRTL___kmpc_doacross_post);
12362 assert(ODK.isSink(
C) &&
"Expect sink modifier.");
12364 OMPRTL___kmpc_doacross_wait);
12384 llvm::FunctionCallee Callee,
12386 assert(Loc.
isValid() &&
"Outlined function call location must be valid.");
12389 if (
auto *Fn = dyn_cast<llvm::Function>(Callee.getCallee())) {
12390 if (Fn->doesNotThrow()) {
12401 emitCall(CGF, Loc, OutlinedFn, Args);
12405 if (
const auto *FD = dyn_cast<FunctionDecl>(D))
12406 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(FD))
12412 const VarDecl *TargetParam)
const {
12419 const Expr *Allocator) {
12420 llvm::Value *AllocVal;
12430 AllocVal = llvm::Constant::getNullValue(
12440 if (!AllocateAlignment)
12443 return llvm::ConstantInt::get(
CGM.
SizeTy, AllocateAlignment->getQuantity());
12456 auto I = UntiedData.find(VD);
12457 if (I != UntiedData.end()) {
12458 UntiedAddr = I->second.first;
12459 UntiedRealAddr = I->second.second;
12463 if (CVD->
hasAttr<OMPAllocateDeclAttr>()) {
12472 Size = CGF.
Builder.CreateNUWAdd(
12474 Size = CGF.
Builder.CreateUDiv(Size,
CGM.getSize(Align));
12475 Size = CGF.
Builder.CreateNUWMul(Size,
CGM.getSize(Align));
12481 const auto *AA = CVD->
getAttr<OMPAllocateDeclAttr>();
12482 const Expr *Allocator = AA->getAllocator();
12486 Args.push_back(ThreadID);
12488 Args.push_back(Alignment);
12489 Args.push_back(Size);
12490 Args.push_back(AllocVal);
12491 llvm::omp::RuntimeFunction FnID =
12492 Alignment ? OMPRTL___kmpc_aligned_alloc : OMPRTL___kmpc_alloc;
12494 OMPBuilder.getOrCreateRuntimeFunction(
CGM.getModule(), FnID), Args,
12496 llvm::FunctionCallee FiniRTLFn =
OMPBuilder.getOrCreateRuntimeFunction(
12497 CGM.getModule(), OMPRTL___kmpc_free);
12505 class OMPAllocateCleanupTy final :
public EHScopeStack::Cleanup {
12506 llvm::FunctionCallee RTLFn;
12509 const Expr *AllocExpr;
12512 OMPAllocateCleanupTy(llvm::FunctionCallee RTLFn,
12514 const Expr *AllocExpr)
12515 : RTLFn(RTLFn), LocEncoding(LocEncoding),
Addr(
Addr),
12516 AllocExpr(AllocExpr) {}
12520 llvm::Value *Args[3];
12526 Args[2] = AllocVal;
12534 CGF.
EHStack.pushCleanup<OMPAllocateCleanupTy>(
12536 VDAddr, Allocator);
12537 if (UntiedRealAddr.
isValid())
12540 Region->emitUntiedSwitch(CGF);
12557 assert(CGM.getLangOpts().OpenMP &&
"Not in OpenMP mode.");
12561 CGM.getOpenMPRuntime().NontemporalDeclsStack.emplace_back();
12563 for (
const Stmt *Ref :
C->private_refs()) {
12564 const auto *SimpleRefExpr =
cast<Expr>(Ref)->IgnoreParenImpCasts();
12566 if (
const auto *DRE = dyn_cast<DeclRefExpr>(SimpleRefExpr)) {
12567 VD = DRE->getDecl();
12570 assert((ME->isImplicitCXXThis() ||
12572 "Expected member of current class.");
12573 VD = ME->getMemberDecl();
12583 CGM.getOpenMPRuntime().NontemporalDeclsStack.pop_back();
12589 std::pair<Address, Address>> &LocalVars)
12590 : CGM(CGF.CGM), NeedToPush(!LocalVars.empty()) {
12594 CGF.
CurFn, CGM.getOpenMPRuntime().UntiedLocalVarsStack.size());
12595 CGM.getOpenMPRuntime().UntiedLocalVarsStack.push_back(LocalVars);
12601 CGM.getOpenMPRuntime().UntiedLocalVarsStack.pop_back();
12605 assert(
CGM.getLangOpts().OpenMP &&
"Not in OpenMP mode.");
12607 return llvm::any_of(
12608 CGM.getOpenMPRuntime().NontemporalDeclsStack,
12612void CGOpenMPRuntime::LastprivateConditionalRAII::tryToDisableInnerAnalysis(
12616 llvm::DenseSet<CanonicalDeclPtr<const Decl>> NeedToCheckForLPCs;
12622 const CapturedStmt *CS = S.getCapturedStmt(CaptureRegions.front());
12629 for (
const auto *
C : S.getClausesOfKind<OMPPrivateClause>()) {
12630 for (
const Expr *Ref :
C->varlist()) {
12631 if (!Ref->getType()->isScalarType())
12633 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
12636 NeedToCheckForLPCs.insert(DRE->getDecl());
12639 for (
const auto *
C : S.getClausesOfKind<OMPFirstprivateClause>()) {
12640 for (
const Expr *Ref :
C->varlist()) {
12641 if (!Ref->getType()->isScalarType())
12643 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
12646 NeedToCheckForLPCs.insert(DRE->getDecl());
12649 for (
const auto *
C : S.getClausesOfKind<OMPLastprivateClause>()) {
12650 for (
const Expr *Ref :
C->varlist()) {
12651 if (!Ref->getType()->isScalarType())
12653 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
12656 NeedToCheckForLPCs.insert(DRE->getDecl());
12659 for (
const auto *
C : S.getClausesOfKind<OMPReductionClause>()) {
12660 for (
const Expr *Ref :
C->varlist()) {
12661 if (!Ref->getType()->isScalarType())
12663 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
12666 NeedToCheckForLPCs.insert(DRE->getDecl());
12669 for (
const auto *
C : S.getClausesOfKind<OMPLinearClause>()) {
12670 for (
const Expr *Ref :
C->varlist()) {
12671 if (!Ref->getType()->isScalarType())
12673 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
12676 NeedToCheckForLPCs.insert(DRE->getDecl());
12679 for (
const Decl *VD : NeedToCheckForLPCs) {
12681 llvm::reverse(
CGM.getOpenMPRuntime().LastprivateConditionalStack)) {
12682 if (
Data.DeclToUniqueName.count(VD) > 0) {
12683 if (!
Data.Disabled)
12684 NeedToAddForLPCsAsDisabled.insert(VD);
12691CGOpenMPRuntime::LastprivateConditionalRAII::LastprivateConditionalRAII(
12694 Action((CGM.getLangOpts().OpenMP >= 50 &&
12695 llvm::any_of(S.getClausesOfKind<OMPLastprivateClause>(),
12696 [](const OMPLastprivateClause *
C) {
12697 return C->getKind() ==
12698 OMPC_LASTPRIVATE_conditional;
12700 ? ActionToDo::PushAsLastprivateConditional
12701 : ActionToDo::DoNotPush) {
12702 assert(
CGM.getLangOpts().OpenMP &&
"Not in OpenMP mode.");
12703 if (
CGM.getLangOpts().OpenMP < 50 || Action == ActionToDo::DoNotPush)
12705 assert(Action == ActionToDo::PushAsLastprivateConditional &&
12706 "Expected a push action.");
12708 CGM.getOpenMPRuntime().LastprivateConditionalStack.emplace_back();
12709 for (
const auto *
C : S.getClausesOfKind<OMPLastprivateClause>()) {
12710 if (
C->getKind() != OMPC_LASTPRIVATE_conditional)
12713 for (
const Expr *Ref :
C->varlist()) {
12714 Data.DeclToUniqueName.insert(std::make_pair(
12719 Data.IVLVal = IVLVal;
12723CGOpenMPRuntime::LastprivateConditionalRAII::LastprivateConditionalRAII(
12725 :
CGM(CGF.
CGM), Action(ActionToDo::DoNotPush) {
12729 llvm::DenseSet<CanonicalDeclPtr<const Decl>> NeedToAddForLPCsAsDisabled;
12730 tryToDisableInnerAnalysis(S, NeedToAddForLPCsAsDisabled);
12731 if (!NeedToAddForLPCsAsDisabled.empty()) {
12732 Action = ActionToDo::DisableLastprivateConditional;
12733 LastprivateConditionalData &
Data =
12735 for (
const Decl *VD : NeedToAddForLPCsAsDisabled)
12736 Data.DeclToUniqueName.try_emplace(VD);
12738 Data.Disabled =
true;
12742CGOpenMPRuntime::LastprivateConditionalRAII
12745 return LastprivateConditionalRAII(CGF, S);
12749 if (CGM.getLangOpts().OpenMP < 50)
12751 if (Action == ActionToDo::DisableLastprivateConditional) {
12752 assert(CGM.getOpenMPRuntime().LastprivateConditionalStack.back().Disabled &&
12753 "Expected list of disabled private vars.");
12754 CGM.getOpenMPRuntime().LastprivateConditionalStack.pop_back();
12756 if (Action == ActionToDo::PushAsLastprivateConditional) {
12758 !CGM.getOpenMPRuntime().LastprivateConditionalStack.back().Disabled &&
12759 "Expected list of lastprivate conditional vars.");
12760 CGM.getOpenMPRuntime().LastprivateConditionalStack.pop_back();
12772 auto VI = I->getSecond().find(VD);
12773 if (VI == I->getSecond().end()) {
12774 RecordDecl *RD =
C.buildImplicitRecord(
"lasprivate.conditional");
12779 NewType =
C.getCanonicalTagType(RD);
12782 I->getSecond().try_emplace(VD, NewType, VDField, FiredField, BaseLVal);
12784 NewType = std::get<0>(VI->getSecond());
12785 VDField = std::get<1>(VI->getSecond());
12786 FiredField = std::get<2>(VI->getSecond());
12787 BaseLVal = std::get<3>(VI->getSecond());
12799class LastprivateConditionalRefChecker final
12802 const Expr *FoundE =
nullptr;
12803 const Decl *FoundD =
nullptr;
12804 StringRef UniqueDeclName;
12806 llvm::Function *FoundFn =
nullptr;
12812 llvm::reverse(LPM)) {
12813 auto It = D.DeclToUniqueName.find(E->
getDecl());
12814 if (It == D.DeclToUniqueName.end())
12820 UniqueDeclName = It->second;
12825 return FoundE == E;
12831 llvm::reverse(LPM)) {
12833 if (It == D.DeclToUniqueName.end())
12839 UniqueDeclName = It->second;
12844 return FoundE == E;
12846 bool VisitStmt(
const Stmt *S) {
12847 for (
const Stmt *Child : S->
children()) {
12850 if (
const auto *E = dyn_cast<Expr>(Child))
12858 explicit LastprivateConditionalRefChecker(
12859 ArrayRef<CGOpenMPRuntime::LastprivateConditionalData> LPM)
12861 std::tuple<const Expr *, const Decl *, StringRef, LValue, llvm::Function *>
12862 getFoundData()
const {
12863 return std::make_tuple(FoundE, FoundD, UniqueDeclName, IVLVal, FoundFn);
12870 StringRef UniqueDeclName,
12876 llvm::Constant *LastIV =
OMPBuilder.getOrCreateInternalVariable(
12877 LLIVTy,
getName({UniqueDeclName,
"iv"}));
12885 llvm::GlobalVariable *
Last =
OMPBuilder.getOrCreateInternalVariable(
12901 auto &&
CodeGen = [&LastIVLVal, &IVLVal, IVVal, &LVal, &LastLVal,
12907 llvm::Value *CmpRes;
12909 CmpRes = CGF.
Builder.CreateICmpSLE(LastIVVal, IVVal);
12912 "Loop iteration variable must be integer.");
12913 CmpRes = CGF.
Builder.CreateICmpULE(LastIVVal, IVVal);
12917 CGF.
Builder.CreateCondBr(CmpRes, ThenBB, ExitBB);
12938 "Aggregates are not supported in lastprivate conditional.");
12947 if (
CGM.getLangOpts().OpenMPSimd) {
12961 if (!Checker.Visit(LHS))
12963 const Expr *FoundE;
12964 const Decl *FoundD;
12965 StringRef UniqueDeclName;
12967 llvm::Function *FoundFn;
12968 std::tie(FoundE, FoundD, UniqueDeclName, IVLVal, FoundFn) =
12969 Checker.getFoundData();
12970 if (FoundFn != CGF.
CurFn) {
12975 "Lastprivate conditional is not found in outer region.");
12976 QualType StructTy = std::get<0>(It->getSecond());
12977 const FieldDecl* FiredDecl = std::get<2>(It->getSecond());
12988 FiredLVal, llvm::AtomicOrdering::Unordered,
13006 auto It = llvm::find_if(
13008 if (It == Range.end() || It->Fn != CGF.
CurFn)
13012 "Lastprivates must be registered already.");
13015 const CapturedStmt *CS = D.getCapturedStmt(CaptureRegions.back());
13016 for (
const auto &Pair : It->DeclToUniqueName) {
13017 const auto *VD =
cast<VarDecl>(Pair.first->getCanonicalDecl());
13020 auto I = LPCI->getSecond().find(Pair.first);
13021 assert(I != LPCI->getSecond().end() &&
13022 "Lastprivate must be rehistered already.");
13024 LValue BaseLVal = std::get<3>(I->getSecond());
13028 llvm::Value *
Cmp = CGF.
Builder.CreateIsNotNull(Res);
13032 CGF.
Builder.CreateCondBr(
Cmp, ThenBB, DoneBB);
13057 "Unknown lastprivate conditional variable.");
13058 StringRef UniqueName = It->second;
13059 llvm::GlobalVariable *GV =
CGM.getModule().getNamedGlobal(UniqueName);
13073 llvm_unreachable(
"Not supported in SIMD-only mode");
13080 llvm_unreachable(
"Not supported in SIMD-only mode");
13087 bool Tied,
unsigned &NumberOfParts) {
13088 llvm_unreachable(
"Not supported in SIMD-only mode");
13096 llvm_unreachable(
"Not supported in SIMD-only mode");
13102 const Expr *Hint) {
13103 llvm_unreachable(
"Not supported in SIMD-only mode");
13109 llvm_unreachable(
"Not supported in SIMD-only mode");
13115 const Expr *Filter) {
13116 llvm_unreachable(
"Not supported in SIMD-only mode");
13121 llvm_unreachable(
"Not supported in SIMD-only mode");
13127 llvm_unreachable(
"Not supported in SIMD-only mode");
13135 llvm_unreachable(
"Not supported in SIMD-only mode");
13142 llvm_unreachable(
"Not supported in SIMD-only mode");
13149 bool ForceSimpleCall) {
13150 llvm_unreachable(
"Not supported in SIMD-only mode");
13157 llvm_unreachable(
"Not supported in SIMD-only mode");
13162 llvm_unreachable(
"Not supported in SIMD-only mode");
13168 llvm_unreachable(
"Not supported in SIMD-only mode");
13174 llvm_unreachable(
"Not supported in SIMD-only mode");
13181 llvm_unreachable(
"Not supported in SIMD-only mode");
13187 llvm_unreachable(
"Not supported in SIMD-only mode");
13192 unsigned IVSize,
bool IVSigned,
13195 llvm_unreachable(
"Not supported in SIMD-only mode");
13203 llvm_unreachable(
"Not supported in SIMD-only mode");
13207 ProcBindKind ProcBind,
13209 llvm_unreachable(
"Not supported in SIMD-only mode");
13216 llvm_unreachable(
"Not supported in SIMD-only mode");
13222 llvm_unreachable(
"Not supported in SIMD-only mode");
13227 llvm_unreachable(
"Not supported in SIMD-only mode");
13233 llvm::AtomicOrdering AO) {
13234 llvm_unreachable(
"Not supported in SIMD-only mode");
13239 llvm::Function *TaskFunction,
13241 const Expr *IfCond,
13243 llvm_unreachable(
"Not supported in SIMD-only mode");
13250 llvm_unreachable(
"Not supported in SIMD-only mode");
13257 assert(Options.
SimpleReduction &&
"Only simple reduction is expected.");
13259 ReductionOps, Options);
13265 llvm_unreachable(
"Not supported in SIMD-only mode");
13270 bool IsWorksharingReduction) {
13271 llvm_unreachable(
"Not supported in SIMD-only mode");
13278 llvm_unreachable(
"Not supported in SIMD-only mode");
13283 llvm::Value *ReductionsPtr,
13285 llvm_unreachable(
"Not supported in SIMD-only mode");
13291 llvm_unreachable(
"Not supported in SIMD-only mode");
13297 llvm_unreachable(
"Not supported in SIMD-only mode");
13303 llvm_unreachable(
"Not supported in SIMD-only mode");
13308 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
13310 llvm_unreachable(
"Not supported in SIMD-only mode");
13315 llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID,
const Expr *IfCond,
13316 llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier>
Device,
13320 llvm_unreachable(
"Not supported in SIMD-only mode");
13324 llvm_unreachable(
"Not supported in SIMD-only mode");
13328 llvm_unreachable(
"Not supported in SIMD-only mode");
13338 llvm::Function *OutlinedFn,
13340 llvm_unreachable(
"Not supported in SIMD-only mode");
13344 const Expr *NumTeams,
13345 const Expr *ThreadLimit,
13347 llvm_unreachable(
"Not supported in SIMD-only mode");
13354 llvm_unreachable(
"Not supported in SIMD-only mode");
13360 llvm_unreachable(
"Not supported in SIMD-only mode");
13366 llvm_unreachable(
"Not supported in SIMD-only mode");
13371 llvm_unreachable(
"Not supported in SIMD-only mode");
13376 llvm_unreachable(
"Not supported in SIMD-only mode");
13381 const VarDecl *NativeParam)
const {
13382 llvm_unreachable(
"Not supported in SIMD-only mode");
13388 const VarDecl *TargetParam)
const {
13389 llvm_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 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 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 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 getAArch64MTV(QualType QT, llvm::OpenMPIRBuilder::DeclareSimdKindTy Kind)
Maps To Vector (MTV), as defined in 4.1.1 of the AAVFABI (2021Q1).
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 validateAArch64Simdlen(CodeGenModule &CGM, SourceLocation SLoc, unsigned UserVLEN, unsigned WDS, char ISA)
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 unsigned getAArch64LS(QualType QT, llvm::OpenMPIRBuilder::DeclareSimdKindTy 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 llvm::OpenMPIRBuilder::DeclareSimdBranch convertDeclareSimdBranch(OMPDeclareSimdDeclAttr::BranchStateTy State)
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 std::pair< llvm::Value *, OMPDynGroupprivateFallbackType > emitDynCGroupMem(const OMPExecutableDirective &D, CodeGenFunction &CGF)
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 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 emitReductionCombiner(CodeGenFunction &CGF, const Expr *ReductionOp)
Emit reduction combiner.
static std::tuple< unsigned, unsigned, bool > getNDSWDS(const FunctionDecl *FD, ArrayRef< llvm::OpenMPIRBuilder::DeclareSimdAttrTy > ParamAttrs)
static std::string generateUniqueName(CodeGenModule &CGM, llvm::StringRef Prefix, const Expr *Ref)
static llvm::Function * emitParallelOrTeamsOutlinedFunction(CodeGenModule &CGM, const OMPExecutableDirective &D, const CapturedStmt *CS, const VarDecl *ThreadIDVar, OpenMPDirectiveKind InnermostKind, const StringRef OutlinedHelperName, const RegionCodeGenTy &CodeGen)
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 bool isAssumedToBeNotEmitted(const ValueDecl *VD, bool IsDevice)
static FieldDecl * addFieldToRecordDecl(ASTContext &C, DeclContext *DC, QualType FieldTy)
static unsigned evaluateCDTSize(const FunctionDecl *FD, ArrayRef< llvm::OpenMPIRBuilder::DeclareSimdAttrTy > ParamAttrs)
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)
@ 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)
This represents clause 'affinity' in the 'pragma omp task'-based directives.
ValueDecl * getAssociatedDeclaration() const
Expr * getAssociatedExpression() const
static std::pair< const Expr *, std::optional< size_t > > findAttachPtrExpr(MappableExprComponentListRef Components, OpenMPDirectiveKind CurDirKind)
Find the attach pointer expression from a list of mappable expression components.
static QualType getComponentExprElementType(const Expr *Exp)
Get the type of an element of a ComponentList Expr Exp.
ArrayRef< MappableComponent > MappableExprComponentListRef
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 represents 'dyn_groupprivate' clause in 'pragma omp target ...' and 'pragma omp teams ....
This represents clause 'map' in the 'pragma omp ...' directives.
This represents clause 'nontemporal' in the 'pragma omp ...' directives.
This represents 'num_teams' clause in the 'pragma omp ...' 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.
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,...
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,...
CharUnits getDeclAlign(const Decl *D, bool ForAlignof=false) const
Return a conservative estimate of the alignment of the specified decl D.
int64_t toBits(CharUnits CharSize) const
Convert a size in characters to a size in bits.
const ArrayType * getAsArrayType(QualType T) const
Type Query functions.
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
static bool hasSameType(QualType T1, QualType T2)
Determine whether the given types T1 and T2 are equivalent.
const VariableArrayType * getAsVariableArrayType(QualType T) const
QualType getSizeType() const
Return the unique type for "size_t" (C99 7.17), defined in <stddef.h>.
unsigned getTypeAlign(QualType T) const
Return the ABI-specified alignment of a (complete) type T, in bits.
CharUnits getSize() const
getSize - Get the record size in characters.
uint64_t getFieldOffset(unsigned FieldNo) const
getFieldOffset - Get the offset of the given field index, in bits.
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 base class of a C++ class.
Represents a C++ constructor within a class.
Represents a C++ destructor within a 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.
const Capture * const_capture_iterator
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 ...
std::string SampleProfileFile
Name of the profile file to use with -fprofile-sample-use.
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.
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.
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...
Address CreateAddrSpaceCast(Address Addr, llvm::Type *Ty, llvm::Type *ElementTy, const llvm::Twine &Name="")
CGFunctionInfo - Class to encapsulate the information about a function definition.
DisableAutoDeclareTargetRAII(CodeGenModule &CGM)
~DisableAutoDeclareTargetRAII()
~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::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 emitParallelCall(CodeGenFunction &CGF, SourceLocation Loc, llvm::Function *OutlinedFn, ArrayRef< llvm::Value * > CapturedVars, const Expr *IfCond, llvm::Value *NumThreads, OpenMPNumThreadsClauseModifier NumThreadsModifier=OMPC_NUMTHREADS_unknown, OpenMPSeverityClauseKind Severity=OMPC_SEVERITY_fatal, const Expr *Message=nullptr)
Emits code for parallel or serial call of the OutlinedFn with variables captured in a record which ad...
llvm::SmallDenseSet< CanonicalDeclPtr< const Decl > > NontemporalDeclsSet
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, OpenMPNumThreadsClauseModifier Modifier=OMPC_NUMTHREADS_unknown, OpenMPSeverityClauseKind Severity=OMPC_SEVERITY_fatal, SourceLocation SeverityLoc=SourceLocation(), const Expr *Message=nullptr, SourceLocation MessageLoc=SourceLocation())
Emits call to void __kmpc_push_num_threads(ident_t *loc, kmp_int32global_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.
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::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 ...
void emitPrivateReduction(CodeGenFunction &CGF, SourceLocation Loc, const Expr *Privates, const Expr *LHSExprs, const Expr *RHSExprs, const Expr *ReductionOps)
Emits code for private variable reduction.
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 llvm::Value * emitMessageClause(CodeGenFunction &CGF, const Expr *Message, SourceLocation Loc)
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_int32global_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.
llvm::MapVector< CanonicalDeclPtr< const VarDecl >, std::pair< Address, Address > > UntiedLocalVarsAddressesMap
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_int32global_tid, int proc_bind) to generate...
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_int32global_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...
virtual void registerVTableOffloadEntry(llvm::GlobalVariable *VTable, const VarDecl *VD)
Register VTable to OpenMP offload entry.
virtual llvm::Value * emitSeverityClause(OpenMPSeverityClauseKind Severity, SourceLocation Loc)
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.
virtual bool isStaticNonchunked(OpenMPScheduleClauseKind ScheduleKind, bool Chunked) const
Check if the specified ScheduleKind is static non-chunked.
virtual void emitAndRegisterVTable(CodeGenModule &CGM, CXXRecordDecl *CXXRecord, const VarDecl *VD)
Emit and register VTable for the C++ class in OpenMP offload entry.
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.
virtual void registerVTable(const OMPExecutableDirective &D)
Emit code for registering vtable by scanning through map clause in OpenMP target region.
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.
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 emitParallelCall(CodeGenFunction &CGF, SourceLocation Loc, llvm::Function *OutlinedFn, ArrayRef< llvm::Value * > CapturedVars, const Expr *IfCond, llvm::Value *NumThreads, OpenMPNumThreadsClauseModifier NumThreadsModifier=OMPC_NUMTHREADS_unknown, OpenMPSeverityClauseKind Severity=OMPC_SEVERITY_fatal, const Expr *Message=nullptr) override
Emits code for parallel or serial call of the OutlinedFn with variables captured in a record which ad...
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 emitProcBindClause(CodeGenFunction &CGF, llvm::omp::ProcBindKind ProcBind, SourceLocation Loc) override
Emit call to void __kmpc_push_proc_bind(ident_t *loc, kmp_int32global_tid, int proc_bind) to generate...
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_int32global_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 emitNumThreadsClause(CodeGenFunction &CGF, llvm::Value *NumThreads, SourceLocation Loc, OpenMPNumThreadsClauseModifier Modifier=OMPC_NUMTHREADS_unknown, OpenMPSeverityClauseKind Severity=OMPC_SEVERITY_fatal, SourceLocation SeverityLoc=SourceLocation(), const Expr *Message=nullptr, SourceLocation MessageLoc=SourceLocation()) override
Emits call to void __kmpc_push_num_threads(ident_t *loc, kmp_int32global_tid, kmp_int32 num_threads) ...
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 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.
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.
API for captured statement code generation.
virtual void EmitBody(CodeGenFunction &CGF, const Stmt *S)
Emit the captured statement body.
virtual const FieldDecl * lookup(const VarDecl *VD) const
Lookup the captured field decl for a variable.
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...
LValue EmitLoadOfReferenceLValue(LValue RefLVal)
void EmitBranchOnBoolExpr(const Expr *Cond, llvm::BasicBlock *TrueBlock, llvm::BasicBlock *FalseBlock, uint64_t TrueCount, Stmt::Likelihood LH=Stmt::LH_None, const Expr *ConditionalOp=nullptr, const VarDecl *ConditionalDecl=nullptr)
EmitBranchOnBoolExpr - Emit a branch on a boolean condition (e.g.
void emitDestroy(Address addr, QualType type, Destroyer *destroyer, bool useEHCleanupForArray)
emitDestroy - Immediately perform the destruction of the given object.
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...
static void EmitOMPTargetParallelDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetParallelDirective &S)
void EmitNullInitialization(Address DestPtr, QualType Ty)
EmitNullInitialization - Generate code to set a value of the given type to null, If the type contains...
Address LoadCXXThisAddress()
CGCapturedStmtInfo * CapturedStmtInfo
ComplexPairTy EmitLoadOfComplex(LValue src, SourceLocation loc)
EmitLoadOfComplex - Load a complex number from the specified l-value.
static void EmitOMPTargetDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetDirective &S)
Emit device code for the target directive.
static void EmitOMPTargetTeamsDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsDirective &S)
Emit device code for the target teams directive.
static void EmitOMPTargetTeamsDistributeDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsDistributeDirective &S)
Emit device code for the target teams distribute directive.
llvm::Function * GenerateOpenMPCapturedStmtFunctionAggregate(const CapturedStmt &S, const OMPExecutableDirective &D)
llvm::BasicBlock * createBasicBlock(const Twine &name="", llvm::Function *parent=nullptr, llvm::BasicBlock *before=nullptr)
createBasicBlock - Create an LLVM basic block.
const LangOptions & getLangOpts() const
AutoVarEmission EmitAutoVarAlloca(const VarDecl &var)
EmitAutoVarAlloca - Emit the alloca and debug information for a local variable.
void pushDestroy(QualType::DestructionKind dtorKind, Address addr, QualType type)
pushDestroy - Push the standard destructor for the given type as at least a normal cleanup.
Address EmitLoadOfPointer(Address Ptr, const PointerType *PtrTy, LValueBaseInfo *BaseInfo=nullptr, TBAAAccessInfo *TBAAInfo=nullptr)
Load a pointer with type PtrTy stored at address Ptr.
void EmitBranchThroughCleanup(JumpDest Dest)
EmitBranchThroughCleanup - Emit a branch from the current insert block through the normal cleanup han...
const Decl * CurCodeDecl
CurCodeDecl - This is the inner-most code context, which includes blocks.
Destroyer * getDestroyer(QualType::DestructionKind destructionKind)
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.
JumpDest ReturnBlock
ReturnBlock - Unified return block.
void EmitAggregateCopy(LValue Dest, LValue Src, QualType EltTy, AggValueSlot::Overlap_t MayOverlap, bool isVolatile=false)
EmitAggregateCopy - Emit an aggregate copy.
LValue EmitLValueForField(LValue Base, const FieldDecl *Field, bool IsInBounds=true)
RawAddress CreateDefaultAlignTempAlloca(llvm::Type *Ty, const Twine &Name="tmp")
CreateDefaultAlignedTempAlloca - This creates an alloca with the default ABI alignment of the given L...
void GenerateOpenMPCapturedVars(const CapturedStmt &S, SmallVectorImpl< llvm::Value * > &CapturedVars)
void EmitIgnoredExpr(const Expr *E)
EmitIgnoredExpr - Emit an expression in a context which ignores the result.
RValue EmitLoadOfLValue(LValue V, SourceLocation Loc)
EmitLoadOfLValue - Given an expression that represents a value lvalue, this method emits the address ...
LValue EmitArraySectionExpr(const ArraySectionExpr *E, bool IsLowerBound=true)
LValue EmitOMPSharedLValue(const Expr *E)
Emits the lvalue for the expression with possibly captured variable.
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.
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.
llvm::Value * EvaluateExprAsBool(const Expr *E)
EvaluateExprAsBool - Perform the usual unary conversions on the specified expression and compare the ...
JumpDest getOMPCancelDestination(OpenMPDirectiveKind Kind)
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...
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...
bool HaveInsertPoint() const
HaveInsertPoint - True if an insertion point is defined.
CGDebugInfo * getDebugInfo()
llvm::Value * getTypeSize(QualType Ty)
Returns calculated size of the specified type.
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.
LValue EmitLValueForFieldInitialization(LValue Base, const FieldDecl *Field)
EmitLValueForFieldInitialization - Like EmitLValueForField, except that if the Field is a reference,...
VlaSizePair getVLASize(const VariableArrayType *vla)
Returns an LLVM value that corresponds to the size, in non-variably-sized elements,...
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...
void EmitStoreOfComplex(ComplexPairTy V, LValue dest, bool isInit)
EmitStoreOfComplex - Store a complex number into the specified l-value.
const Decl * CurFuncDecl
CurFuncDecl - Holds the Decl for the current outermost non-closure context.
void EmitAutoVarCleanups(const AutoVarEmission &emission)
void EmitStoreThroughLValue(RValue Src, LValue Dst, bool isInit=false)
EmitStoreThroughLValue - Store the specified rvalue into the specified lvalue, where both are guarant...
LValue EmitLoadOfPointerLValue(Address Ptr, const PointerType *PtrTy)
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...
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="")
llvm::Type * ConvertTypeForMem(QualType T)
static void EmitOMPTargetTeamsDistributeParallelForDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsDistributeParallelForDirective &S)
static void EmitOMPTargetParallelForSimdDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetParallelForSimdDirective &S)
Emit device code for the target parallel for simd directive.
CodeGenTypes & getTypes() const
static TypeEvaluationKind getEvaluationKind(QualType T)
getEvaluationKind - Return the TypeEvaluationKind of QualType T.
void EmitOMPTargetTaskBasedDirective(const OMPExecutableDirective &S, const RegionCodeGenTy &BodyGen, OMPTargetDataInfo &InputInfo)
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...
static void EmitOMPTargetTeamsDistributeParallelForSimdDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsDistributeParallelForSimdDirective &S)
Emit device code for the target teams distribute parallel for simd directive.
void EmitBranch(llvm::BasicBlock *Block)
EmitBranch - Emit a branch to the specified basic block from the current insert block,...
llvm::Function * GenerateOpenMPCapturedStmtFunction(const CapturedStmt &S, const OMPExecutableDirective &D)
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...
void EmitVarDecl(const VarDecl &D)
EmitVarDecl - Emit a local variable declaration.
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...
static void EmitOMPTargetParallelGenericLoopDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetParallelGenericLoopDirective &S)
Emit device code for the target parallel loop directive.
llvm::Value * EmitScalarExpr(const Expr *E, bool IgnoreResultAssign=false)
EmitScalarExpr - Emit the computation of the specified expression of LLVM scalar type,...
static bool IsWrappedCXXThis(const Expr *E)
Check if E is a C++ "this" pointer wrapped in value-preserving casts.
LValue MakeAddrLValue(Address Addr, QualType T, AlignmentSource Source=AlignmentSource::Type)
void FinishFunction(SourceLocation EndLoc=SourceLocation())
FinishFunction - Complete IR generation of the current function.
void EmitAtomicStore(RValue rvalue, LValue lvalue, bool isInit)
static void EmitOMPTargetSimdDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetSimdDirective &S)
Emit device code for the target simd directive.
static void EmitOMPTargetParallelForDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetParallelForDirective &S)
Emit device code for the target parallel for directive.
Address GetAddrOfLocalVar(const VarDecl *VD)
GetAddrOfLocalVar - Return the address of a local variable.
bool ConstantFoldsToSimpleInteger(const Expr *Cond, bool &Result, bool AllowLabels=false)
ConstantFoldsToSimpleInteger - If the specified expression does not fold to a constant,...
static void EmitOMPTargetTeamsGenericLoopDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsGenericLoopDirective &S)
Emit device code for the target teams loop directive.
LValue EmitMemberExpr(const MemberExpr *E)
std::pair< llvm::Value *, llvm::Value * > ComplexPairTy
Address ReturnValue
ReturnValue - The temporary alloca to hold the return value.
LValue EmitLValue(const Expr *E, KnownNonNull_t IsKnownNonNull=NotKnownNonNull)
EmitLValue - Emit code to compute a designator that specifies the location of the expression.
void incrementProfileCounter(const Stmt *S, llvm::Value *StepV=nullptr)
Increment the profiler's counter for the given statement by StepV.
static void EmitOMPTargetTeamsDistributeSimdDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsDistributeSimdDirective &S)
Emit device code for the target teams distribute simd directive.
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...
void EmitVariablyModifiedType(QualType Ty)
EmitVLASize - Capture all the sizes for the VLA expressions in the given variably-modified type and s...
bool isTrivialInitializer(const Expr *Init)
Determine whether the given initializer is trivial in the sense that it requires no code to be genera...
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...
void EmitBlock(llvm::BasicBlock *BB, bool IsFinished=false)
EmitBlock - Emit the given block.
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...
LValue MakeNaturalAlignRawAddrLValue(llvm::Value *V, QualType T)
This class organizes the cross-function state that is used while generating LLVM code.
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
const IntrusiveRefCntPtr< llvm::vfs::FileSystem > & getFileSystem() const
DiagnosticsEngine & getDiags() const
const LangOptions & getLangOpts() const
CharUnits getNaturalTypeAlignment(QualType T, LValueBaseInfo *BaseInfo=nullptr, TBAAAccessInfo *TBAAInfo=nullptr, bool forPointeeType=false)
CodeGenTypes & getTypes()
CGOpenMPRuntime & getOpenMPRuntime()
Return a reference to the configured OpenMP runtime.
TBAAAccessInfo getTBAAInfoForSubobject(LValue Base, QualType AccessType)
getTBAAInfoForSubobject - Get TBAA information for an access with a given base lvalue.
ASTContext & getContext() const
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::Constant * EmitNullConstant(QualType T)
Return the result of value-initializing the given type, i.e.
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::GlobalVariable * GetAddrOfVTable(const CXXRecordDecl *RD)
GetAddrOfVTable - Get the address of the VTable for the given record decl.
A specialization of Address that requires the address to be an LLVM Constant.
static ConstantAddress invalid()
bool requiresLandingPad() const
void pushTerminate()
Push a terminate handler on the stack.
void popTerminate()
Pops a terminate handler off 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
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.
ASTContext & getASTContext() const LLVM_READONLY
virtual Stmt * getBody() const
getBody - If this Decl represents a declaration for a body of code, such as a function or method defi...
llvm::iterator_range< specific_attr_iterator< T > > specific_attrs() const
SourceLocation getLocation() const
DeclContext * getDeclContext()
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.
This represents one expression.
bool isIntegerConstantExpr(const ASTContext &Ctx) const
Expr * IgnoreParenNoopCasts(const ASTContext &Ctx) LLVM_READONLY
Skip past any parentheses and casts which do not change the value (including ptr->int casts of the sa...
@ 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) 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...
std::optional< llvm::APSInt > getIntegerConstantExpr(const ASTContext &Ctx) const
isIntegerConstantExpr - Return the value if this expression is a valid integer constant expression.
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 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...
static bool isSameComparisonOperand(const Expr *E1, const Expr *E2)
Checks that the two Expr's will refer to the same value as a comparison operand.
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.
unsigned getFieldIndex() const
Returns the index of this field within its record, as appropriate for passing to ASTRecordLayout::get...
const RecordDecl * getParent() const
Returns the parent of this field declaration, which is the struct in which this field is defined.
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.
FunctionDecl * getMostRecentDecl()
Returns the most recent (re)declaration of this declaration.
unsigned getNumParams() const
Return the number of parameters this function must have based on its FunctionType.
FunctionDecl * getPreviousDecl()
Return the previous declaration of this declaration or NULL if this is the first declaration.
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'.
An lvalue reference type, per C++11 [dcl.ref].
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
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.
Expr * getMapperVarRef()
Get the variable declared in the mapper.
This represents 'pragma omp declare reduction ...' directive.
Expr * getInitializer()
Get initializer expression (if specified) of the declare reduction construct.
Expr * getInitPriv()
Get Priv variable of the initializer.
Expr * getCombinerOut()
Get Out variable of the combiner.
Expr * getCombinerIn()
Get In variable of the combiner.
Expr * getCombiner()
Get combiner expression of the declare reduction construct.
Expr * getInitOrig()
Get Orig variable of the initializer.
OMPDeclareReductionInitKind getInitializerKind() const
Get initializer kind.
This represents 'if' clause in the 'pragma omp ...' directive.
Expr * getCondition() const
Returns condition.
OMPIteratorHelperData & getHelper(unsigned I)
Fetches helper data for the specified iteration space.
unsigned numOfIterators() const
Returns number of iterator definitions.
This represents 'num_threads' clause in the 'pragma omp ...' directive.
This represents 'pragma omp requires...' directive.
clauselist_range clauselists()
This represents 'threadset' clause in the 'pragma omp task ...' 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
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.
Stmt - This represents one statement.
StmtClass getStmtClass() const
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.
The base class of the type hierarchy.
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,...
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
RecordDecl * getAsRecordDecl() const
Retrieves the RecordDecl this type refers to.
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
bool isAggregateType() const
Determines whether the type is a C++ aggregate type or C aggregate or union type.
RecordDecl * castAsRecordDecl() const
QualType getCanonicalTypeInternal() 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
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.
const Expr * getInit() const
bool hasExternalStorage() const
Returns true if a variable has extern or private_extern storage.
@ 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...
@ Type
The l-value was considered opaque, so the alignment was determined from a type.
@ 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 ...
ComparisonResult
Indicates the result of a tentative comparison.
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.
CanQual< Type > CanQualType
Represents a canonical, potentially-qualified type.
bool needsTaskBasedThreadLimit(OpenMPDirectiveKind DKind)
Checks if the specified target directive, combined or not, needs task based thread_limit.
@ Match
This is not an overload because the signature exactly matches an existing declaration.
@ Ctor_Complete
Complete object ctor.
Privates[]
This class represents the 'transparent' clause in the 'pragma omp task' directive.
bool isa(CodeGen::Address addr)
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.
static bool classof(const OMPClause *T)
@ Conditional
A conditional (?:) operator.
@ 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...
@ 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
nullptr
This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...
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.
@ OMPC_DYN_GROUPPRIVATE_FALLBACK_unknown
@ 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 isOpenMPTargetMapEnteringDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a map-entering target directive.
@ Type
The name was classified as a type.
bool isOpenMPLoopDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a directive with an associated loop construct.
OpenMPSeverityClauseKind
OpenMP attributes for 'severity' clause.
LangAS
Defines the address space values used by the address space qualifier of QualType.
llvm::omp::Directive OpenMPDirectiveKind
OpenMP directives.
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.
for(const auto &A :T->param_types())
void getOpenMPCaptureRegions(llvm::SmallVectorImpl< OpenMPDirectiveKind > &CaptureRegions, OpenMPDirectiveKind DKind)
Return the captured regions of an OpenMP directive.
OpenMPNumThreadsClauseModifier
@ OMPC_ATOMIC_DEFAULT_MEM_ORDER_unknown
U cast(CodeGen::Address addr)
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.
OpenMPThreadsetKind
OpenMP modifiers for 'threadset' clause.
OpenMPMapClauseKind
OpenMP mapping kind for 'map' clause.
Diagnostic wrappers for TextAPI types for error reporting.
Data for list of allocators.
Expr * AllocatorTraits
Allocator traits.
Expr * Allocator
Allocator.
Maps the expression for the lastprivate variable to the global copy used to store new value because o...
llvm::SmallVector< bool, 8 > IsPrivateVarReduction
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::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
CharUnits getPointerAlign() const
OpenMPDependClauseKind DepKind
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.
Expr * CounterUpdate
Updater for the internal counter: ++CounterVD;.
Scheduling data for loop-based OpenMP directives.
OpenMPScheduleClauseModifier M2
OpenMPScheduleClauseModifier M1
OpenMPScheduleClauseKind Schedule
Describes how types, statements, expressions, and declarations should be printed.