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();
1089 C,
nullptr, Out->getLocation(),
1092 C,
nullptr, In->getLocation(),
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 return llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryEnter;
1533 case OMPDeclareTargetDeclAttr::MapTypeTy::MT_Link:
1534 return llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryLink;
1536 case OMPDeclareTargetDeclAttr::MapTypeTy::MT_Local:
1538 llvm_unreachable(
"MT_Local should not reach convertCaptureClause");
1541 return llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryNone;
1550 auto FileInfoCallBack = [&]() {
1555 PLoc =
SM.getPresumedLoc(BeginLoc,
false);
1560 return OMPBuilder.getTargetEntryUniqueInfo(FileInfoCallBack,
1565 auto AddrOfGlobal = [&VD,
this]() {
return CGM.GetAddrOfGlobal(VD); };
1567 auto LinkageForVariable = [&VD,
this]() {
1568 return CGM.getLLVMLinkageVarDefinition(VD);
1571 std::vector<llvm::GlobalVariable *> GeneratedRefs;
1573 llvm::Type *LlvmPtrTy =
CGM.getTypes().ConvertTypeForMem(
1574 CGM.getContext().getPointerType(VD->
getType()));
1575 llvm::Constant *addr =
OMPBuilder.getAddrOfDeclareTargetVar(
1581 CGM.getMangledName(VD), GeneratedRefs,
CGM.getLangOpts().OpenMPSimd,
1582 CGM.getLangOpts().OMPTargetTriples, LlvmPtrTy, AddrOfGlobal,
1583 LinkageForVariable);
1592 assert(!
CGM.getLangOpts().OpenMPUseTLS ||
1593 !
CGM.getContext().getTargetInfo().isTLSSupported());
1595 std::string Suffix =
getName({
"cache",
""});
1596 return OMPBuilder.getOrCreateInternalVariable(
1597 CGM.Int8PtrPtrTy, Twine(
CGM.getMangledName(VD)).concat(Suffix).str());
1604 if (
CGM.getLangOpts().OpenMPUseTLS &&
1605 CGM.getContext().getTargetInfo().isTLSSupported())
1609 llvm::Value *Args[] = {
1612 CGM.getSize(
CGM.GetTargetTypeStoreSize(VarTy)),
1617 CGM.getModule(), OMPRTL___kmpc_threadprivate_cached),
1629 CGM.getModule(), OMPRTL___kmpc_global_thread_num),
1633 llvm::Value *Args[] = {
1636 Ctor, CopyCtor, Dtor};
1639 CGM.getModule(), OMPRTL___kmpc_threadprivate_register),
1646 if (
CGM.getLangOpts().OpenMPUseTLS &&
1647 CGM.getContext().getTargetInfo().isTLSSupported())
1654 llvm::Value *Ctor =
nullptr, *CopyCtor =
nullptr, *Dtor =
nullptr;
1656 if (
CGM.getLangOpts().CPlusPlus && PerformInit) {
1661 CGM.getContext(),
nullptr, Loc,
1665 const auto &FI =
CGM.getTypes().arrangeBuiltinFunctionDeclaration(
1666 CGM.getContext().VoidPtrTy, Args);
1667 llvm::FunctionType *FTy =
CGM.getTypes().GetFunctionType(FI);
1668 std::string Name =
getName({
"__kmpc_global_ctor_",
""});
1669 llvm::Function *Fn =
1670 CGM.CreateGlobalInitOrCleanUpFunction(FTy, Name, FI, Loc);
1675 CGM.getContext().VoidPtrTy, Dst->getLocation());
1682 CGM.getContext().VoidPtrTy, Dst->getLocation());
1692 CGM.getContext(),
nullptr, Loc,
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);
1709 false,
CGM.getContext().VoidPtrTy, Dst->getLocation());
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();
2067 return ThreadIDTemp;
2071 std::string Prefix = Twine(
"gomp_critical_user_", CriticalName).str();
2072 std::string Name =
getName({Prefix,
"var"});
2079 llvm::FunctionCallee EnterCallee;
2081 llvm::FunctionCallee ExitCallee;
2084 llvm::BasicBlock *ContBlock =
nullptr;
2087 CommonActionTy(llvm::FunctionCallee EnterCallee,
2089 llvm::FunctionCallee ExitCallee,
2091 : EnterCallee(EnterCallee), EnterArgs(EnterArgs), ExitCallee(ExitCallee),
2096 llvm::Value *CallBool = CGF.
Builder.CreateIsNotNull(EnterRes);
2100 CGF.
Builder.CreateCondBr(CallBool, ThenBlock, ContBlock);
2104 void Done(CodeGenFunction &CGF) {
2109 void Exit(CodeGenFunction &CGF)
override {
2116 StringRef CriticalName,
2125 llvm::FunctionCallee RuntimeFcn =
OMPBuilder.getOrCreateRuntimeFunction(
2127 Hint ? OMPRTL___kmpc_critical_with_hint : OMPRTL___kmpc_critical);
2129 unsigned LockVarArgIdx = 2;
2131 RuntimeFcn.getFunctionType()
2132 ->getParamType(LockVarArgIdx)
2133 ->getPointerAddressSpace())
2135 LockVar, RuntimeFcn.getFunctionType()->getParamType(LockVarArgIdx));
2141 EnterArgs.push_back(CGF.
Builder.CreateIntCast(
2144 CommonActionTy Action(RuntimeFcn, EnterArgs,
2146 CGM.getModule(), OMPRTL___kmpc_end_critical),
2163 CommonActionTy Action(
OMPBuilder.getOrCreateRuntimeFunction(
2164 CGM.getModule(), OMPRTL___kmpc_master),
2167 CGM.getModule(), OMPRTL___kmpc_end_master),
2185 llvm::Value *FilterVal = Filter
2187 : llvm::ConstantInt::get(
CGM.Int32Ty, 0);
2192 CommonActionTy Action(
OMPBuilder.getOrCreateRuntimeFunction(
2193 CGM.getModule(), OMPRTL___kmpc_masked),
2196 CGM.getModule(), OMPRTL___kmpc_end_masked),
2212 llvm::Value *Args[] = {
2214 llvm::ConstantInt::get(
CGM.IntTy, 0,
true)};
2216 CGM.getModule(), OMPRTL___kmpc_omp_taskyield),
2220 if (
auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.
CapturedStmtInfo))
2221 Region->emitUntiedSwitch(CGF);
2234 CommonActionTy Action(
OMPBuilder.getOrCreateRuntimeFunction(
2235 CGM.getModule(), OMPRTL___kmpc_taskgroup),
2238 CGM.getModule(), OMPRTL___kmpc_end_taskgroup),
2247 unsigned Index,
const VarDecl *Var) {
2276 llvm::GlobalValue::InternalLinkage, Name,
2280 Fn->addFnAttr(
"sample-profile-suffix-elision-policy",
"selected");
2281 Fn->setDoesNotRecurse();
2298 for (
unsigned I = 0, E = AssignmentOps.size(); I < E; ++I) {
2299 const auto *DestVar =
2303 const auto *SrcVar =
2309 CGF.
EmitOMPCopy(
Type, DestAddr, SrcAddr, DestVar, SrcVar, AssignmentOps[I]);
2324 assert(CopyprivateVars.size() == SrcExprs.size() &&
2325 CopyprivateVars.size() == DstExprs.size() &&
2326 CopyprivateVars.size() == AssignmentOps.size());
2338 if (!CopyprivateVars.empty()) {
2341 C.getIntTypeForBitwidth(32, 1);
2347 CommonActionTy Action(
OMPBuilder.getOrCreateRuntimeFunction(
2348 CGM.getModule(), OMPRTL___kmpc_single),
2351 CGM.getModule(), OMPRTL___kmpc_end_single),
2364 llvm::APInt ArraySize(32, CopyprivateVars.size());
2365 QualType CopyprivateArrayTy =
C.getConstantArrayType(
2370 CopyprivateArrayTy,
".omp.copyprivate.cpr_list");
2371 for (
unsigned I = 0, E = CopyprivateVars.size(); I < E; ++I) {
2383 SrcExprs, DstExprs, AssignmentOps, Loc);
2384 llvm::Value *BufSize = CGF.
getTypeSize(CopyprivateArrayTy);
2388 llvm::Value *Args[] = {
2392 CL.emitRawPointer(CGF),
2397 CGM.getModule(), OMPRTL___kmpc_copyprivate),
2413 CommonActionTy Action(
OMPBuilder.getOrCreateRuntimeFunction(
2414 CGM.getModule(), OMPRTL___kmpc_ordered),
2417 CGM.getModule(), OMPRTL___kmpc_end_ordered),
2428 if (Kind == OMPD_for)
2429 Flags = OMP_IDENT_BARRIER_IMPL_FOR;
2430 else if (Kind == OMPD_sections)
2431 Flags = OMP_IDENT_BARRIER_IMPL_SECTIONS;
2432 else if (Kind == OMPD_single)
2433 Flags = OMP_IDENT_BARRIER_IMPL_SINGLE;
2434 else if (Kind == OMPD_barrier)
2435 Flags = OMP_IDENT_BARRIER_EXPL;
2437 Flags = OMP_IDENT_BARRIER_IMPL;
2447 S.getClausesOfKind<OMPOrderedClause>(),
2448 [](
const OMPOrderedClause *
C) { return C->getNumForLoops(); })) {
2449 ScheduleKind = OMPC_SCHEDULE_static;
2451 llvm::APInt ChunkSize(32, 1);
2461 bool ForceSimpleCall) {
2463 auto *OMPRegionInfo =
2466 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
2469 CGF.
Builder.restoreIP(AfterIP);
2482 if (OMPRegionInfo) {
2483 if (!ForceSimpleCall && OMPRegionInfo->hasCancel()) {
2486 OMPRTL___kmpc_cancel_barrier),
2495 CGF.
Builder.CreateCondBr(
Cmp, ExitBB, ContBB);
2507 CGM.getModule(), OMPRTL___kmpc_barrier),
2512 Expr *ME,
bool IsFatal) {
2514 : llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
2517 llvm::Value *Args[] = {
2519 llvm::ConstantInt::get(
CGM.Int32Ty, IsFatal ? 2 : 1),
2520 CGF.
Builder.CreatePointerCast(MVL,
CGM.Int8PtrTy)};
2522 CGM.getModule(), OMPRTL___kmpc_error),
2528 bool Chunked,
bool Ordered) {
2529 switch (ScheduleKind) {
2530 case OMPC_SCHEDULE_static:
2531 return Chunked ? (Ordered ? OMP_ord_static_chunked : OMP_sch_static_chunked)
2532 : (Ordered ? OMP_ord_static : OMP_sch_static);
2533 case OMPC_SCHEDULE_dynamic:
2534 return Ordered ? OMP_ord_dynamic_chunked : OMP_sch_dynamic_chunked;
2535 case OMPC_SCHEDULE_guided:
2536 return Ordered ? OMP_ord_guided_chunked : OMP_sch_guided_chunked;
2537 case OMPC_SCHEDULE_runtime:
2538 return Ordered ? OMP_ord_runtime : OMP_sch_runtime;
2539 case OMPC_SCHEDULE_auto:
2540 return Ordered ? OMP_ord_auto : OMP_sch_auto;
2542 assert(!Chunked &&
"chunk was specified but schedule kind not known");
2543 return Ordered ? OMP_ord_static : OMP_sch_static;
2545 llvm_unreachable(
"Unexpected runtime schedule");
2549static OpenMPSchedType
2552 return Chunked ? OMP_dist_sch_static_chunked : OMP_dist_sch_static;
2556 bool Chunked)
const {
2557 OpenMPSchedType Schedule =
2559 return Schedule == OMP_sch_static;
2565 return Schedule == OMP_dist_sch_static;
2569 bool Chunked)
const {
2570 OpenMPSchedType Schedule =
2572 return Schedule == OMP_sch_static_chunked;
2578 return Schedule == OMP_dist_sch_static_chunked;
2582 OpenMPSchedType Schedule =
2584 assert(Schedule != OMP_sch_static_chunked &&
"cannot be chunked here");
2585 return Schedule != OMP_sch_static;
2593 case OMPC_SCHEDULE_MODIFIER_monotonic:
2594 Modifier = OMP_sch_modifier_monotonic;
2596 case OMPC_SCHEDULE_MODIFIER_nonmonotonic:
2597 Modifier = OMP_sch_modifier_nonmonotonic;
2599 case OMPC_SCHEDULE_MODIFIER_simd:
2600 if (Schedule == OMP_sch_static_chunked)
2601 Schedule = OMP_sch_static_balanced_chunked;
2608 case OMPC_SCHEDULE_MODIFIER_monotonic:
2609 Modifier = OMP_sch_modifier_monotonic;
2611 case OMPC_SCHEDULE_MODIFIER_nonmonotonic:
2612 Modifier = OMP_sch_modifier_nonmonotonic;
2614 case OMPC_SCHEDULE_MODIFIER_simd:
2615 if (Schedule == OMP_sch_static_chunked)
2616 Schedule = OMP_sch_static_balanced_chunked;
2628 if (CGM.
getLangOpts().OpenMP >= 50 && Modifier == 0) {
2629 if (!(Schedule == OMP_sch_static_chunked || Schedule == OMP_sch_static ||
2630 Schedule == OMP_sch_static_balanced_chunked ||
2631 Schedule == OMP_ord_static_chunked || Schedule == OMP_ord_static ||
2632 Schedule == OMP_dist_sch_static_chunked ||
2633 Schedule == OMP_dist_sch_static))
2634 Modifier = OMP_sch_modifier_nonmonotonic;
2636 return Schedule | Modifier;
2646 ScheduleKind.
Schedule, DispatchValues.
Chunk !=
nullptr, Ordered);
2648 (Schedule != OMP_sch_static && Schedule != OMP_sch_static_chunked &&
2649 Schedule != OMP_ord_static && Schedule != OMP_ord_static_chunked &&
2650 Schedule != OMP_sch_static_balanced_chunked));
2657 llvm::Value *Chunk = DispatchValues.
Chunk ? DispatchValues.
Chunk
2658 : CGF.
Builder.getIntN(IVSize, 1);
2659 llvm::Value *Args[] = {
2663 CGM, Schedule, ScheduleKind.
M1, ScheduleKind.
M2)),
2666 CGF.
Builder.getIntN(IVSize, 1),
2683 CodeGenFunction &CGF, llvm::Value *UpdateLocation, llvm::Value *ThreadId,
2684 llvm::FunctionCallee ForStaticInitFunction, OpenMPSchedType Schedule,
2691 assert(Schedule == OMP_sch_static || Schedule == OMP_sch_static_chunked ||
2692 Schedule == OMP_sch_static_balanced_chunked ||
2693 Schedule == OMP_ord_static || Schedule == OMP_ord_static_chunked ||
2694 Schedule == OMP_dist_sch_static ||
2695 Schedule == OMP_dist_sch_static_chunked);
2702 llvm::Value *Chunk = Values.
Chunk;
2703 if (Chunk ==
nullptr) {
2704 assert((Schedule == OMP_sch_static || Schedule == OMP_ord_static ||
2705 Schedule == OMP_dist_sch_static) &&
2706 "expected static non-chunked schedule");
2710 assert((Schedule == OMP_sch_static_chunked ||
2711 Schedule == OMP_sch_static_balanced_chunked ||
2712 Schedule == OMP_ord_static_chunked ||
2713 Schedule == OMP_dist_sch_static_chunked) &&
2714 "expected static chunked schedule");
2716 llvm::Value *Args[] = {
2739 "Expected loop-based or sections-based directive.");
2742 ? OMP_IDENT_WORK_LOOP
2743 : OMP_IDENT_WORK_SECTIONS);
2745 llvm::FunctionCallee StaticInitFunction =
2750 ScheduleNum, ScheduleKind.
M1, ScheduleKind.
M2, Values);
2757 OpenMPSchedType ScheduleNum =
2759 llvm::Value *UpdatedLocation =
2762 llvm::FunctionCallee StaticInitFunction;
2763 bool isGPUDistribute =
2764 CGM.getLangOpts().OpenMPIsTargetDevice &&
CGM.getTriple().isGPU();
2765 StaticInitFunction =
OMPBuilder.createForStaticInitFunction(
2776 assert((DKind == OMPD_distribute || DKind == OMPD_for ||
2777 DKind == OMPD_sections) &&
2778 "Expected distribute, for, or sections directive kind");
2782 llvm::Value *Args[] = {
2785 (DKind == OMPD_target_teams_loop)
2786 ? OMP_IDENT_WORK_DISTRIBUTE
2788 ? OMP_IDENT_WORK_LOOP
2789 : OMP_IDENT_WORK_SECTIONS),
2793 CGM.getLangOpts().OpenMPIsTargetDevice &&
CGM.getTriple().isGPU())
2796 CGM.getModule(), OMPRTL___kmpc_distribute_static_fini),
2800 CGM.getModule(), OMPRTL___kmpc_for_static_fini),
2825 llvm::Value *Args[] = {
2833 OMPBuilder.createDispatchNextFunction(IVSize, IVSigned), Args);
2840 const Expr *Message,
2843 return llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
2852 return llvm::ConstantInt::get(
CGM.Int32Ty,
2853 Severity == OMPC_SEVERITY_warning ? 1 : 2);
2869 RuntimeFunction FnID = OMPRTL___kmpc_push_num_threads;
2870 if (Modifier == OMPC_NUMTHREADS_strict) {
2871 FnID = OMPRTL___kmpc_push_num_threads_strict;
2876 OMPBuilder.getOrCreateRuntimeFunction(
CGM.getModule(), FnID), Args);
2880 ProcBindKind ProcBind,
2884 assert(ProcBind != OMP_PROC_BIND_unknown &&
"Unsupported proc_bind value.");
2886 llvm::Value *Args[] = {
2888 llvm::ConstantInt::get(
CGM.IntTy,
unsigned(ProcBind),
true)};
2890 CGM.getModule(), OMPRTL___kmpc_push_proc_bind),
2903 CGM.getModule(), OMPRTL___kmpc_flush),
2910enum KmpTaskTFields {
2937 if (
CGM.getLangOpts().OpenMPSimd ||
OMPBuilder.OffloadInfoManager.empty())
2940 llvm::OpenMPIRBuilder::EmitMetadataErrorReportFunctionTy &&ErrorReportFn =
2941 [
this](llvm::OpenMPIRBuilder::EmitMetadataErrorKind Kind,
2942 const llvm::TargetRegionEntryInfo &EntryInfo) ->
void {
2944 if (Kind != llvm::OpenMPIRBuilder::EMIT_MD_GLOBAL_VAR_LINK_ERROR) {
2945 for (
auto I =
CGM.getContext().getSourceManager().fileinfo_begin(),
2946 E =
CGM.getContext().getSourceManager().fileinfo_end();
2948 if (I->getFirst().getUniqueID().getDevice() == EntryInfo.DeviceID &&
2949 I->getFirst().getUniqueID().getFile() == EntryInfo.FileID) {
2950 Loc =
CGM.getContext().getSourceManager().translateFileLineCol(
2951 I->getFirst(), EntryInfo.Line, 1);
2957 case llvm::OpenMPIRBuilder::EMIT_MD_TARGET_REGION_ERROR: {
2958 CGM.getDiags().Report(Loc,
2959 diag::err_target_region_offloading_entry_incorrect)
2960 << EntryInfo.ParentName;
2962 case llvm::OpenMPIRBuilder::EMIT_MD_DECLARE_TARGET_ERROR: {
2963 CGM.getDiags().Report(
2964 Loc, diag::err_target_var_offloading_entry_incorrect_with_parent)
2965 << EntryInfo.ParentName;
2967 case llvm::OpenMPIRBuilder::EMIT_MD_GLOBAL_VAR_LINK_ERROR: {
2968 CGM.getDiags().Report(diag::err_target_var_offloading_entry_incorrect);
2970 case llvm::OpenMPIRBuilder::EMIT_MD_GLOBAL_VAR_INDIRECT_ERROR: {
2971 unsigned DiagID =
CGM.getDiags().getCustomDiagID(
2973 "target variable is incorrect: the "
2974 "address is invalid.");
2975 CGM.getDiags().Report(DiagID);
2980 OMPBuilder.createOffloadEntriesAndInfoMetadata(ErrorReportFn);
2987 QualType KmpRoutineEntryTyArgs[] = {KmpInt32Ty,
C.VoidPtrTy};
2990 C.getFunctionType(KmpInt32Ty, KmpRoutineEntryTyArgs, EPI));
2996struct PrivateHelpersTy {
2997 PrivateHelpersTy(
const Expr *OriginalRef,
const VarDecl *Original,
2999 : OriginalRef(OriginalRef), Original(Original), PrivateCopy(PrivateCopy),
3000 PrivateElemInit(PrivateElemInit) {}
3001 PrivateHelpersTy(
const VarDecl *Original) : Original(Original) {}
3002 const Expr *OriginalRef =
nullptr;
3003 const VarDecl *Original =
nullptr;
3004 const VarDecl *PrivateCopy =
nullptr;
3005 const VarDecl *PrivateElemInit =
nullptr;
3006 bool isLocalPrivate()
const {
3007 return !OriginalRef && !PrivateCopy && !PrivateElemInit;
3010typedef std::pair<CharUnits , PrivateHelpersTy> PrivateDataTy;
3015 if (!CVD->
hasAttr<OMPAllocateDeclAttr>())
3017 const auto *AA = CVD->
getAttr<OMPAllocateDeclAttr>();
3019 return !(AA->getAllocatorType() == OMPAllocateDeclAttr::OMPDefaultMemAlloc &&
3020 !AA->getAllocator());
3030 RecordDecl *RD =
C.buildImplicitRecord(
".kmp_privates.t");
3032 for (
const auto &Pair :
Privates) {
3033 const VarDecl *VD = Pair.second.Original;
3037 if (Pair.second.isLocalPrivate()) {
3060 QualType KmpRoutineEntryPointerQTy) {
3080 CanQualType KmpCmplrdataTy =
C.getCanonicalTagType(UD);
3081 RecordDecl *RD =
C.buildImplicitRecord(
"kmp_task_t");
3111 RecordDecl *RD =
C.buildImplicitRecord(
"kmp_task_t_with_privates");
3131static llvm::Function *
3134 QualType KmpTaskTWithPrivatesPtrQTy,
3136 QualType SharedsPtrTy, llvm::Function *TaskFunction,
3137 llvm::Value *TaskPrivatesMap) {
3143 C,
nullptr, Loc,
nullptr,
3146 const auto &TaskEntryFnInfo =
3148 llvm::FunctionType *TaskEntryTy =
3151 auto *TaskEntry = llvm::Function::Create(
3152 TaskEntryTy, llvm::GlobalValue::InternalLinkage, Name, &CGM.
getModule());
3155 TaskEntry->addFnAttr(
"sample-profile-suffix-elision-policy",
"selected");
3156 TaskEntry->setDoesNotRecurse();
3171 const auto *KmpTaskTWithPrivatesQTyRD =
3176 auto PartIdFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTPartId);
3178 llvm::Value *PartidParam = PartIdLVal.getPointer(CGF);
3180 auto SharedsFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTShareds);
3186 auto PrivatesFI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin(), 1);
3187 llvm::Value *PrivatesParam;
3188 if (PrivatesFI != KmpTaskTWithPrivatesQTyRD->field_end()) {
3191 PrivatesLVal.getPointer(CGF), CGF.
VoidPtrTy);
3193 PrivatesParam = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
3196 llvm::Value *CommonArgs[] = {
3197 GtidParam, PartidParam, PrivatesParam, TaskPrivatesMap,
3203 std::end(CommonArgs));
3205 auto LBFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound);
3208 auto UBFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound);
3211 auto StFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTStride);
3214 auto LIFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLastIter);
3217 auto RFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTReductions);
3220 CallArgs.push_back(LBParam);
3221 CallArgs.push_back(UBParam);
3222 CallArgs.push_back(StParam);
3223 CallArgs.push_back(LIParam);
3224 CallArgs.push_back(RParam);
3226 CallArgs.push_back(SharedsParam);
3239 QualType KmpTaskTWithPrivatesPtrQTy,
3240 QualType KmpTaskTWithPrivatesQTy) {
3246 C,
nullptr, Loc,
nullptr,
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,
3554 C,
nullptr, Loc,
nullptr, KmpTaskTWithPrivatesPtrQTy,
3557 C,
nullptr, Loc,
nullptr, KmpTaskTWithPrivatesPtrQTy,
3563 const auto &TaskDupFnInfo =
3567 auto *TaskDup = llvm::Function::Create(
3568 TaskDupTy, llvm::GlobalValue::InternalLinkage, Name, &CGM.
getModule());
3571 TaskDup->addFnAttr(
"sample-profile-suffix-elision-policy",
"selected");
3572 TaskDup->setDoesNotRecurse();
3582 auto LIFI = std::next(KmpTaskTQTyRD->
field_begin(), KmpTaskTLastIter);
3584 TDBase, *KmpTaskTWithPrivatesQTyRD->
field_begin());
3594 if (!
Data.FirstprivateVars.empty()) {
3599 TDBase, *KmpTaskTWithPrivatesQTyRD->
field_begin());
3607 emitPrivatesInit(CGF, D, KmpTaskSharedsPtr, TDBase, KmpTaskTWithPrivatesQTyRD,
3618 for (
const PrivateDataTy &P :
Privates) {
3619 if (P.second.isLocalPrivate())
3621 QualType Ty = P.second.Original->getType().getNonReferenceType();
3630class OMPIteratorGeneratorScope final
3632 CodeGenFunction &CGF;
3633 const OMPIteratorExpr *E =
nullptr;
3634 SmallVector<CodeGenFunction::JumpDest, 4> ContDests;
3635 SmallVector<CodeGenFunction::JumpDest, 4> ExitDests;
3636 OMPIteratorGeneratorScope() =
delete;
3637 OMPIteratorGeneratorScope(OMPIteratorGeneratorScope &) =
delete;
3640 OMPIteratorGeneratorScope(CodeGenFunction &CGF,
const OMPIteratorExpr *E)
3641 : CodeGenFunction::OMPPrivateScope(CGF), CGF(CGF), E(E) {
3644 SmallVector<llvm::Value *, 4> Uppers;
3646 Uppers.push_back(CGF.EmitScalarExpr(E->getHelper(I).Upper));
3647 const auto *VD = cast<VarDecl>(E->getIteratorDecl(I));
3648 addPrivate(VD, CGF.CreateMemTemp(VD->getType(), VD->getName()));
3649 const OMPIteratorHelperData &HelperData = E->getHelper(I);
3651 HelperData.CounterVD,
3652 CGF.CreateMemTemp(HelperData.CounterVD->getType(),
"counter.addr"));
3657 const OMPIteratorHelperData &HelperData = E->getHelper(I);
3659 CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(HelperData.CounterVD),
3660 HelperData.CounterVD->getType());
3662 CGF.EmitStoreOfScalar(
3663 llvm::ConstantInt::get(CLVal.getAddress().getElementType(), 0),
3665 CodeGenFunction::JumpDest &ContDest =
3666 ContDests.emplace_back(CGF.getJumpDestInCurrentScope(
"iter.cont"));
3667 CodeGenFunction::JumpDest &ExitDest =
3668 ExitDests.emplace_back(CGF.getJumpDestInCurrentScope(
"iter.exit"));
3670 llvm::Value *N = Uppers[I];
3673 CGF.EmitBlock(ContDest.getBlock());
3675 CGF.EmitLoadOfScalar(CLVal, HelperData.CounterVD->getLocation());
3677 HelperData.CounterVD->getType()->isSignedIntegerOrEnumerationType()
3678 ? CGF.Builder.CreateICmpSLT(CVal, N)
3679 : CGF.Builder.CreateICmpULT(CVal, N);
3680 llvm::BasicBlock *BodyBB = CGF.createBasicBlock(
"iter.body");
3681 CGF.Builder.CreateCondBr(Cmp, BodyBB, ExitDest.getBlock());
3683 CGF.EmitBlock(BodyBB);
3685 CGF.EmitIgnoredExpr(HelperData.Update);
3688 ~OMPIteratorGeneratorScope() {
3693 const OMPIteratorHelperData &HelperData = E->
getHelper(I - 1);
3698 CGF.
EmitBlock(ExitDests[I - 1].getBlock(), I == 1);
3704static std::pair<llvm::Value *, llvm::Value *>
3706 const auto *OASE = dyn_cast<OMPArrayShapingExpr>(E);
3709 const Expr *
Base = OASE->getBase();
3714 llvm::Value *SizeVal;
3717 SizeVal = CGF.
getTypeSize(OASE->getBase()->getType()->getPointeeType());
3718 for (
const Expr *SE : OASE->getDimensions()) {
3722 SizeVal = CGF.
Builder.CreateNUWMul(SizeVal, Sz);
3724 }
else if (
const auto *ASE =
3727 Address UpAddrAddress = UpAddrLVal.getAddress();
3728 llvm::Value *UpAddr = CGF.
Builder.CreateConstGEP1_32(
3731 SizeVal = CGF.
Builder.CreatePtrDiff(UpAddr,
Addr,
"",
true);
3735 return std::make_pair(
Addr, SizeVal);
3740 QualType FlagsTy =
C.getIntTypeForBitwidth(32,
false);
3741 if (KmpTaskAffinityInfoTy.
isNull()) {
3743 C.buildImplicitRecord(
"kmp_task_affinity_info_t");
3749 KmpTaskAffinityInfoTy =
C.getCanonicalTagType(KmpAffinityInfoRD);
3756 llvm::Function *TaskFunction,
QualType SharedsTy,
3761 const auto *I =
Data.PrivateCopies.begin();
3762 for (
const Expr *E :
Data.PrivateVars) {
3770 I =
Data.FirstprivateCopies.begin();
3771 const auto *IElemInitRef =
Data.FirstprivateInits.begin();
3772 for (
const Expr *E :
Data.FirstprivateVars) {
3782 I =
Data.LastprivateCopies.begin();
3783 for (
const Expr *E :
Data.LastprivateVars) {
3793 Privates.emplace_back(
CGM.getPointerAlign(), PrivateHelpersTy(VD));
3795 Privates.emplace_back(
C.getDeclAlign(VD), PrivateHelpersTy(VD));
3798 [](
const PrivateDataTy &L,
const PrivateDataTy &R) {
3799 return L.first > R.first;
3801 QualType KmpInt32Ty =
C.getIntTypeForBitwidth(32, 1);
3812 assert((D.getDirectiveKind() == OMPD_task ||
3815 "Expected taskloop, task or target directive");
3822 const auto *KmpTaskTQTyRD =
KmpTaskTQTy->castAsRecordDecl();
3824 const RecordDecl *KmpTaskTWithPrivatesQTyRD =
3827 C.getCanonicalTagType(KmpTaskTWithPrivatesQTyRD);
3828 QualType KmpTaskTWithPrivatesPtrQTy =
3829 C.getPointerType(KmpTaskTWithPrivatesQTy);
3830 llvm::Type *KmpTaskTWithPrivatesPtrTy = CGF.
Builder.getPtrTy(0);
3831 llvm::Value *KmpTaskTWithPrivatesTySize =
3833 QualType SharedsPtrTy =
C.getPointerType(SharedsTy);
3836 llvm::Value *TaskPrivatesMap =
nullptr;
3837 llvm::Type *TaskPrivatesMapTy =
3838 std::next(TaskFunction->arg_begin(), 3)->getType();
3840 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->
field_begin());
3844 TaskPrivatesMap, TaskPrivatesMapTy);
3846 TaskPrivatesMap = llvm::ConstantPointerNull::get(
3852 CGM, Loc, D.getDirectiveKind(), KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy,
3853 KmpTaskTWithPrivatesQTy,
KmpTaskTQTy, SharedsPtrTy, TaskFunction,
3865 DestructorsFlag = 0x8,
3866 PriorityFlag = 0x20,
3867 DetachableFlag = 0x40,
3868 FreeAgentFlag = 0x80,
3869 TransparentFlag = 0x100,
3871 unsigned Flags =
Data.Tied ? TiedFlag : 0;
3872 bool NeedsCleanup =
false;
3877 Flags = Flags | DestructorsFlag;
3881 if (Kind == OMPC_THREADSET_omp_pool)
3882 Flags = Flags | FreeAgentFlag;
3884 if (D.getSingleClause<OMPTransparentClause>())
3885 Flags |= TransparentFlag;
3887 if (
Data.Priority.getInt())
3888 Flags = Flags | PriorityFlag;
3890 Flags = Flags | DetachableFlag;
3891 llvm::Value *TaskFlags =
3892 Data.Final.getPointer()
3893 ? CGF.
Builder.CreateSelect(
Data.Final.getPointer(),
3894 CGF.
Builder.getInt32(FinalFlag),
3896 : CGF.
Builder.getInt32(
Data.Final.getInt() ? FinalFlag : 0);
3897 TaskFlags = CGF.
Builder.CreateOr(TaskFlags, CGF.
Builder.getInt32(Flags));
3898 llvm::Value *SharedsSize =
CGM.getSize(
C.getTypeSizeInChars(SharedsTy));
3900 getThreadID(CGF, Loc), TaskFlags, KmpTaskTWithPrivatesTySize,
3903 llvm::Value *NewTask;
3904 if (D.hasClausesOfKind<OMPNowaitClause>()) {
3910 llvm::Value *DeviceID;
3915 DeviceID = CGF.
Builder.getInt64(OMP_DEVICEID_UNDEF);
3916 AllocArgs.push_back(DeviceID);
3919 CGM.getModule(), OMPRTL___kmpc_omp_target_task_alloc),
3924 CGM.getModule(), OMPRTL___kmpc_omp_task_alloc),
3937 llvm::Value *Tid =
getThreadID(CGF, DC->getBeginLoc());
3938 Tid = CGF.
Builder.CreateIntCast(Tid, CGF.
IntTy,
false);
3941 CGM.getModule(), OMPRTL___kmpc_task_allow_completion_event),
3942 {Loc, Tid, NewTask});
3953 llvm::Value *NumOfElements =
nullptr;
3954 unsigned NumAffinities = 0;
3956 if (
const Expr *Modifier =
C->getModifier()) {
3958 for (
unsigned I = 0, E = IE->numOfIterators(); I < E; ++I) {
3962 NumOfElements ? CGF.
Builder.CreateNUWMul(NumOfElements, Sz) : Sz;
3965 NumAffinities +=
C->varlist_size();
3970 enum RTLAffinityInfoFieldsTy { BaseAddr, Len, Flags };
3972 QualType KmpTaskAffinityInfoArrayTy;
3973 if (NumOfElements) {
3974 NumOfElements = CGF.
Builder.CreateNUWAdd(
3975 llvm::ConstantInt::get(CGF.
SizeTy, NumAffinities), NumOfElements);
3978 C.getIntTypeForBitwidth(
C.getTypeSize(
C.getSizeType()), 0),
3982 KmpTaskAffinityInfoArrayTy =
C.getVariableArrayType(
3990 NumOfElements = CGF.
Builder.CreateIntCast(NumOfElements, CGF.
Int32Ty,
3993 KmpTaskAffinityInfoArrayTy =
C.getConstantArrayType(
3995 llvm::APInt(
C.getTypeSize(
C.getSizeType()), NumAffinities),
nullptr,
4000 NumOfElements = llvm::ConstantInt::get(
CGM.Int32Ty, NumAffinities,
4007 bool HasIterator =
false;
4009 if (
C->getModifier()) {
4013 for (
const Expr *E :
C->varlist()) {
4022 Base, *std::next(KmpAffinityInfoRD->field_begin(), BaseAddr));
4027 Base, *std::next(KmpAffinityInfoRD->field_begin(), Len));
4041 const Expr *Modifier =
C->getModifier();
4044 OMPIteratorGeneratorScope IteratorScope(
4046 for (
const Expr *E :
C->varlist()) {
4056 Base, *std::next(KmpAffinityInfoRD->field_begin(), BaseAddr));
4061 Base, *std::next(KmpAffinityInfoRD->field_begin(), Len));
4063 Idx = CGF.
Builder.CreateNUWAdd(
4064 Idx, llvm::ConstantInt::get(Idx->getType(), 1));
4079 CGM.getModule(), OMPRTL___kmpc_omp_reg_task_with_affinity),
4080 {LocRef, GTid, NewTask, NumOfElements, AffinListPtr});
4082 llvm::Value *NewTaskNewTaskTTy =
4084 NewTask, KmpTaskTWithPrivatesPtrTy);
4086 KmpTaskTWithPrivatesQTy);
4097 *std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTShareds)),
4099 CGF.
Int8Ty,
CGM.getNaturalTypeAlignment(SharedsTy));
4113 CGM, Loc, D, KmpTaskTWithPrivatesPtrQTy, KmpTaskTWithPrivatesQTyRD,
4114 KmpTaskTQTyRD, SharedsTy, SharedsPtrTy,
Data,
Privates,
4115 !
Data.LastprivateVars.empty());
4119 enum { Priority = 0, Destructors = 1 };
4121 auto FI = std::next(KmpTaskTQTyRD->field_begin(), Data1);
4122 const auto *KmpCmplrdataUD = (*FI)->getType()->castAsRecordDecl();
4123 assert(KmpCmplrdataUD->isUnion());
4126 CGM, Loc, KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy,
4127 KmpTaskTWithPrivatesQTy);
4130 Data1LV, *std::next(KmpCmplrdataUD->field_begin(), Destructors));
4136 if (
Data.Priority.getInt()) {
4138 TDBase, *std::next(KmpTaskTQTyRD->field_begin(), Data2));
4140 Data2LV, *std::next(KmpCmplrdataUD->field_begin(), Priority));
4143 Result.NewTask = NewTask;
4144 Result.TaskEntry = TaskEntry;
4145 Result.NewTaskNewTaskTTy = NewTaskNewTaskTTy;
4147 Result.KmpTaskTQTyRD = KmpTaskTQTyRD;
4153 RTLDependenceKindTy DepKind;
4155 case OMPC_DEPEND_in:
4156 DepKind = RTLDependenceKindTy::DepIn;
4159 case OMPC_DEPEND_out:
4160 case OMPC_DEPEND_inout:
4161 DepKind = RTLDependenceKindTy::DepInOut;
4163 case OMPC_DEPEND_mutexinoutset:
4164 DepKind = RTLDependenceKindTy::DepMutexInOutSet;
4166 case OMPC_DEPEND_inoutset:
4167 DepKind = RTLDependenceKindTy::DepInOutSet;
4169 case OMPC_DEPEND_outallmemory:
4170 DepKind = RTLDependenceKindTy::DepOmpAllMem;
4172 case OMPC_DEPEND_source:
4173 case OMPC_DEPEND_sink:
4174 case OMPC_DEPEND_depobj:
4175 case OMPC_DEPEND_inoutallmemory:
4177 llvm_unreachable(
"Unknown task dependence type");
4185 FlagsTy =
C.getIntTypeForBitwidth(
C.getTypeSize(
C.BoolTy),
false);
4186 if (KmpDependInfoTy.
isNull()) {
4187 RecordDecl *KmpDependInfoRD =
C.buildImplicitRecord(
"kmp_depend_info");
4193 KmpDependInfoTy =
C.getCanonicalTagType(KmpDependInfoRD);
4197std::pair<llvm::Value *, LValue>
4210 CGF,
Base.getAddress(),
4211 llvm::ConstantInt::get(CGF.
IntPtrTy, -1,
true));
4217 *std::next(KmpDependInfoRD->field_begin(),
4218 static_cast<unsigned int>(RTLDependInfoFields::BaseAddr)));
4220 return std::make_pair(NumDeps,
Base);
4224 llvm::PointerUnion<unsigned *, LValue *> Pos,
4234 OMPIteratorGeneratorScope IteratorScope(
4235 CGF, cast_or_null<OMPIteratorExpr>(
4236 Data.IteratorExpr ?
Data.IteratorExpr->IgnoreParenImpCasts()
4238 for (
const Expr *E :
Data.DepExprs) {
4248 Size = llvm::ConstantInt::get(CGF.
SizeTy, 0);
4251 if (
unsigned *P = dyn_cast<unsigned *>(Pos)) {
4255 assert(E &&
"Expected a non-null expression");
4264 *std::next(KmpDependInfoRD->field_begin(),
4265 static_cast<unsigned int>(RTLDependInfoFields::BaseAddr)));
4269 Base, *std::next(KmpDependInfoRD->field_begin(),
4270 static_cast<unsigned int>(RTLDependInfoFields::Len)));
4276 *std::next(KmpDependInfoRD->field_begin(),
4277 static_cast<unsigned int>(RTLDependInfoFields::Flags)));
4279 llvm::ConstantInt::get(LLVMFlagsTy,
static_cast<unsigned int>(DepKind)),
4281 if (
unsigned *P = dyn_cast<unsigned *>(Pos)) {
4286 Idx = CGF.
Builder.CreateNUWAdd(Idx,
4287 llvm::ConstantInt::get(Idx->getType(), 1));
4296 assert(
Data.DepKind == OMPC_DEPEND_depobj &&
4297 "Expected depobj dependency kind.");
4302 OMPIteratorGeneratorScope IteratorScope(
4303 CGF, cast_or_null<OMPIteratorExpr>(
4304 Data.IteratorExpr ?
Data.IteratorExpr->IgnoreParenImpCasts()
4306 for (
const Expr *E :
Data.DepExprs) {
4307 llvm::Value *NumDeps;
4310 std::tie(NumDeps,
Base) =
4314 C.getUIntPtrType());
4318 llvm::Value *Add = CGF.
Builder.CreateNUWAdd(PrevVal, NumDeps);
4320 SizeLVals.push_back(NumLVal);
4323 for (
unsigned I = 0, E = SizeLVals.size(); I < E; ++I) {
4326 Sizes.push_back(Size);
4336 assert(
Data.DepKind == OMPC_DEPEND_depobj &&
4337 "Expected depobj dependency kind.");
4340 OMPIteratorGeneratorScope IteratorScope(
4341 CGF, cast_or_null<OMPIteratorExpr>(
4342 Data.IteratorExpr ?
Data.IteratorExpr->IgnoreParenImpCasts()
4344 for (
const Expr *E :
Data.DepExprs) {
4345 llvm::Value *NumDeps;
4348 std::tie(NumDeps,
Base) =
4352 llvm::Value *Size = CGF.
Builder.CreateNUWMul(
4361 llvm::Value *Add = CGF.
Builder.CreateNUWAdd(Pos, NumDeps);
4377 llvm::Value *NumOfElements =
nullptr;
4378 unsigned NumDependencies = std::accumulate(
4379 Dependencies.begin(), Dependencies.end(), 0,
4381 return D.DepKind == OMPC_DEPEND_depobj
4383 : (V + (D.IteratorExpr ? 0 : D.DepExprs.size()));
4387 bool HasDepobjDeps =
false;
4388 bool HasRegularWithIterators =
false;
4389 llvm::Value *NumOfDepobjElements = llvm::ConstantInt::get(CGF.
IntPtrTy, 0);
4390 llvm::Value *NumOfRegularWithIterators =
4391 llvm::ConstantInt::get(CGF.
IntPtrTy, 0);
4395 if (D.
DepKind == OMPC_DEPEND_depobj) {
4398 for (llvm::Value *Size : Sizes) {
4399 NumOfDepobjElements =
4400 CGF.
Builder.CreateNUWAdd(NumOfDepobjElements, Size);
4402 HasDepobjDeps =
true;
4407 if (
const auto *IE = cast_or_null<OMPIteratorExpr>(D.
IteratorExpr)) {
4408 llvm::Value *ClauseIteratorSpace =
4409 llvm::ConstantInt::get(CGF.
IntPtrTy, 1);
4413 ClauseIteratorSpace = CGF.
Builder.CreateNUWMul(Sz, ClauseIteratorSpace);
4415 llvm::Value *NumClauseDeps = CGF.
Builder.CreateNUWMul(
4416 ClauseIteratorSpace,
4418 NumOfRegularWithIterators =
4419 CGF.
Builder.CreateNUWAdd(NumOfRegularWithIterators, NumClauseDeps);
4420 HasRegularWithIterators =
true;
4426 if (HasDepobjDeps || HasRegularWithIterators) {
4427 NumOfElements = llvm::ConstantInt::get(
CGM.IntPtrTy, NumDependencies,
4429 if (HasDepobjDeps) {
4431 CGF.
Builder.CreateNUWAdd(NumOfDepobjElements, NumOfElements);
4433 if (HasRegularWithIterators) {
4435 CGF.
Builder.CreateNUWAdd(NumOfRegularWithIterators, NumOfElements);
4438 Loc,
C.getIntTypeForBitwidth(64, 0),
4442 KmpDependInfoArrayTy =
4451 NumOfElements = CGF.
Builder.CreateIntCast(NumOfElements, CGF.
Int32Ty,
4454 KmpDependInfoArrayTy =
C.getConstantArrayType(
4460 NumOfElements = llvm::ConstantInt::get(
CGM.Int32Ty, NumDependencies,
4465 if (Dep.DepKind == OMPC_DEPEND_depobj || Dep.IteratorExpr)
4475 if (Dep.DepKind == OMPC_DEPEND_depobj || !Dep.IteratorExpr)
4480 if (HasDepobjDeps) {
4482 if (Dep.DepKind != OMPC_DEPEND_depobj)
4489 return std::make_pair(NumOfElements, DependenciesArray);
4500 unsigned NumDependencies = Dependencies.
DepExprs.size();
4510 llvm::Value *NumDepsVal;
4512 if (
const auto *IE =
4513 cast_or_null<OMPIteratorExpr>(Dependencies.
IteratorExpr)) {
4514 NumDepsVal = llvm::ConstantInt::get(CGF.
SizeTy, 1);
4518 NumDepsVal = CGF.
Builder.CreateNUWMul(NumDepsVal, Sz);
4520 Size = CGF.
Builder.CreateNUWAdd(llvm::ConstantInt::get(CGF.
SizeTy, 1),
4524 llvm::Value *RecSize =
CGM.getSize(SizeInBytes);
4525 Size = CGF.
Builder.CreateNUWMul(Size, RecSize);
4529 QualType KmpDependInfoArrayTy =
C.getConstantArrayType(
4532 CharUnits Sz =
C.getTypeSizeInChars(KmpDependInfoArrayTy);
4534 NumDepsVal = llvm::ConstantInt::get(CGF.
IntPtrTy, NumDependencies);
4539 llvm::Value *Allocator = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
4540 llvm::Value *Args[] = {ThreadID, Size, Allocator};
4544 CGM.getModule(), OMPRTL___kmpc_alloc),
4545 Args,
".dep.arr.addr");
4549 DependenciesArray =
Address(
Addr, KmpDependInfoLlvmTy, Align);
4555 *std::next(KmpDependInfoRD->field_begin(),
4556 static_cast<unsigned int>(RTLDependInfoFields::BaseAddr)));
4558 llvm::PointerUnion<unsigned *, LValue *> Pos;
4575 return DependenciesArray;
4590 Addr.getElementType(),
Addr.emitRawPointer(CGF),
4591 llvm::ConstantInt::get(CGF.
IntPtrTy, -1,
true));
4596 llvm::Value *Allocator = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
4597 llvm::Value *Args[] = {ThreadID, DepObjAddr, Allocator};
4601 CGM.getModule(), OMPRTL___kmpc_free),
4613 llvm::Value *NumDeps;
4624 llvm::BasicBlock *EntryBB = CGF.
Builder.GetInsertBlock();
4626 llvm::PHINode *ElementPHI =
4631 Base.getTBAAInfo());
4635 Base, *std::next(KmpDependInfoRD->field_begin(),
4636 static_cast<unsigned int>(RTLDependInfoFields::Flags)));
4638 llvm::ConstantInt::get(LLVMFlagsTy,
static_cast<unsigned int>(DepKind)),
4642 llvm::Value *ElementNext =
4645 ElementPHI->addIncoming(ElementNext, CGF.
Builder.GetInsertBlock());
4646 llvm::Value *IsEmpty =
4647 CGF.
Builder.CreateICmpEQ(ElementNext, End,
"omp.isempty");
4648 CGF.
Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
4655 llvm::Function *TaskFunction,
4664 llvm::Value *NewTask =
Result.NewTask;
4665 llvm::Function *TaskEntry =
Result.TaskEntry;
4666 llvm::Value *NewTaskNewTaskTTy =
Result.NewTaskNewTaskTTy;
4671 llvm::Value *NumOfElements;
4672 std::tie(NumOfElements, DependenciesArray) =
4683 llvm::Value *TaskArgs[] = { UpLoc, ThreadID, NewTask };
4684 llvm::Value *DepTaskArgs[7];
4685 if (!
Data.Dependences.empty()) {
4686 DepTaskArgs[0] = UpLoc;
4687 DepTaskArgs[1] = ThreadID;
4688 DepTaskArgs[2] = NewTask;
4689 DepTaskArgs[3] = NumOfElements;
4691 DepTaskArgs[5] = CGF.
Builder.getInt32(0);
4692 DepTaskArgs[6] = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
4694 auto &&ThenCodeGen = [
this, &
Data, TDBase, KmpTaskTQTyRD, &TaskArgs,
4697 auto PartIdFI = std::next(KmpTaskTQTyRD->
field_begin(), KmpTaskTPartId);
4701 if (!
Data.Dependences.empty()) {
4704 CGM.getModule(), OMPRTL___kmpc_omp_task_with_deps),
4708 CGM.getModule(), OMPRTL___kmpc_omp_task),
4714 Region->emitUntiedSwitch(CGF);
4717 llvm::Value *DepWaitTaskArgs[7];
4718 if (!
Data.Dependences.empty()) {
4719 DepWaitTaskArgs[0] = UpLoc;
4720 DepWaitTaskArgs[1] = ThreadID;
4721 DepWaitTaskArgs[2] = NumOfElements;
4723 DepWaitTaskArgs[4] = CGF.
Builder.getInt32(0);
4724 DepWaitTaskArgs[5] = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
4725 DepWaitTaskArgs[6] =
4726 llvm::ConstantInt::get(CGF.
Int32Ty,
Data.HasNowaitClause);
4728 auto &M =
CGM.getModule();
4729 auto &&ElseCodeGen = [
this, &M, &TaskArgs, ThreadID, NewTaskNewTaskTTy,
4730 TaskEntry, &
Data, &DepWaitTaskArgs,
4737 if (!
Data.Dependences.empty())
4739 M, OMPRTL___kmpc_omp_taskwait_deps_51),
4742 auto &&
CodeGen = [TaskEntry, ThreadID, NewTaskNewTaskTTy,
4745 llvm::Value *OutlinedFnArgs[] = {ThreadID, NewTaskNewTaskTTy};
4746 CGF.CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, Loc, TaskEntry,
4755 CommonActionTy Action(
OMPBuilder.getOrCreateRuntimeFunction(
4756 M, OMPRTL___kmpc_omp_task_begin_if0),
4759 M, OMPRTL___kmpc_omp_task_complete_if0),
4775 llvm::Function *TaskFunction,
4795 IfVal = llvm::ConstantInt::getSigned(CGF.
IntTy, 1);
4800 *std::next(
Result.KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound));
4807 *std::next(
Result.KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound));
4814 *std::next(
Result.KmpTaskTQTyRD->field_begin(), KmpTaskTStride));
4822 *std::next(
Result.KmpTaskTQTyRD->field_begin(), KmpTaskTReductions));
4823 if (
Data.Reductions) {
4829 enum { NoSchedule = 0, Grainsize = 1, NumTasks = 2 };
4838 llvm::ConstantInt::getSigned(
4840 llvm::ConstantInt::getSigned(
4842 ?
Data.Schedule.getInt() ? NumTasks : Grainsize
4844 Data.Schedule.getPointer()
4847 : llvm::ConstantInt::get(CGF.
Int64Ty, 0)};
4848 if (
Data.HasModifier)
4849 TaskArgs.push_back(llvm::ConstantInt::get(CGF.
Int32Ty, 1));
4851 TaskArgs.push_back(
Result.TaskDupFn
4854 : llvm::ConstantPointerNull::get(CGF.
VoidPtrTy));
4856 CGM.getModule(),
Data.HasModifier
4857 ? OMPRTL___kmpc_taskloop_5
4858 : OMPRTL___kmpc_taskloop),
4875 const Expr *,
const Expr *)> &RedOpGen,
4876 const Expr *XExpr =
nullptr,
const Expr *EExpr =
nullptr,
4877 const Expr *UpExpr =
nullptr) {
4885 llvm::Value *NumElements = CGF.
emitArrayLength(ArrayTy, ElementTy, LHSAddr);
4890 llvm::Value *LHSEnd =
4895 llvm::Value *IsEmpty =
4896 CGF.
Builder.CreateICmpEQ(LHSBegin, LHSEnd,
"omp.arraycpy.isempty");
4897 CGF.
Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
4900 llvm::BasicBlock *EntryBB = CGF.
Builder.GetInsertBlock();
4905 llvm::PHINode *RHSElementPHI = CGF.
Builder.CreatePHI(
4906 RHSBegin->getType(), 2,
"omp.arraycpy.srcElementPast");
4907 RHSElementPHI->addIncoming(RHSBegin, EntryBB);
4912 llvm::PHINode *LHSElementPHI = CGF.
Builder.CreatePHI(
4913 LHSBegin->getType(), 2,
"omp.arraycpy.destElementPast");
4914 LHSElementPHI->addIncoming(LHSBegin, EntryBB);
4921 Scope.addPrivate(LHSVar, LHSElementCurrent);
4922 Scope.addPrivate(RHSVar, RHSElementCurrent);
4924 RedOpGen(CGF, XExpr, EExpr, UpExpr);
4925 Scope.ForceCleanup();
4928 llvm::Value *LHSElementNext = CGF.
Builder.CreateConstGEP1_32(
4930 "omp.arraycpy.dest.element");
4931 llvm::Value *RHSElementNext = CGF.
Builder.CreateConstGEP1_32(
4933 "omp.arraycpy.src.element");
4936 CGF.
Builder.CreateICmpEQ(LHSElementNext, LHSEnd,
"omp.arraycpy.done");
4937 CGF.
Builder.CreateCondBr(Done, DoneBB, BodyBB);
4938 LHSElementPHI->addIncoming(LHSElementNext, CGF.
Builder.GetInsertBlock());
4939 RHSElementPHI->addIncoming(RHSElementNext, CGF.
Builder.GetInsertBlock());
4949 const Expr *ReductionOp) {
4950 if (
const auto *CE = dyn_cast<CallExpr>(ReductionOp))
4951 if (
const auto *OVE = dyn_cast<OpaqueValueExpr>(CE->getCallee()))
4952 if (
const auto *DRE =
4953 dyn_cast<DeclRefExpr>(OVE->getSourceExpr()->IgnoreImpCasts()))
4954 if (
const auto *DRD =
4955 dyn_cast<OMPDeclareReductionDecl>(DRE->getDecl())) {
4956 std::pair<llvm::Function *, llvm::Function *>
Reduction =
4967 StringRef ReducerName,
SourceLocation Loc, llvm::Type *ArgsElemType,
4981 CGM.getTypes().arrangeBuiltinFunctionDeclaration(
C.VoidTy, Args);
4983 auto *Fn = llvm::Function::Create(
CGM.getTypes().GetFunctionType(CGFI),
4984 llvm::GlobalValue::InternalLinkage, Name,
4987 if (!
CGM.getCodeGenOpts().SampleProfileFile.empty())
4988 Fn->addFnAttr(
"sample-profile-suffix-elision-policy",
"selected");
4989 Fn->setDoesNotRecurse();
5008 const auto *IPriv =
Privates.begin();
5010 for (
unsigned I = 0, E = ReductionOps.size(); I < E; ++I, ++IPriv, ++Idx) {
5011 const auto *RHSVar =
5014 const auto *LHSVar =
5017 QualType PrivTy = (*IPriv)->getType();
5033 const auto *ILHS = LHSExprs.begin();
5034 const auto *IRHS = RHSExprs.begin();
5035 for (
const Expr *E : ReductionOps) {
5036 if ((*IPriv)->getType()->isArrayType()) {
5041 CGF, (*IPriv)->getType(), LHSVar, RHSVar,
5043 emitReductionCombiner(CGF, E);
5053 Scope.ForceCleanup();
5059 const Expr *ReductionOp,
5060 const Expr *PrivateRef,
5068 CGF, PrivateRef->
getType(), LHSVar, RHSVar,
5070 emitReductionCombiner(CGF, ReductionOp);
5079 llvm::StringRef Prefix,
const Expr *Ref);
5083 const Expr *LHSExprs,
const Expr *RHSExprs,
const Expr *ReductionOps) {
5110 std::string ReductionVarNameStr;
5111 if (
const auto *DRE = dyn_cast<DeclRefExpr>(
Privates->IgnoreParenCasts()))
5112 ReductionVarNameStr =
5115 ReductionVarNameStr =
"unnamed_priv_var";
5118 std::string SharedName =
5119 CGM.getOpenMPRuntime().getName({
"internal_pivate_", ReductionVarNameStr});
5120 llvm::GlobalVariable *SharedVar =
OMPBuilder.getOrCreateInternalVariable(
5121 LLVMType,
".omp.reduction." + SharedName);
5123 SharedVar->setAlignment(
5131 llvm::Value *BarrierArgs[] = {BarrierLoc, ThreadId};
5136 llvm::Value *IsWorker = CGF.
Builder.CreateICmpEQ(
5137 ThreadId, llvm::ConstantInt::get(ThreadId->getType(), 0));
5138 CGF.
Builder.CreateCondBr(IsWorker, InitBB, InitEndBB);
5142 auto EmitSharedInit = [&]() {
5145 std::pair<llvm::Function *, llvm::Function *> FnPair =
5147 llvm::Function *InitializerFn = FnPair.second;
5148 if (InitializerFn) {
5149 if (
const auto *CE =
5150 dyn_cast<CallExpr>(UDRInitExpr->IgnoreParenImpCasts())) {
5157 LocalScope.addPrivate(OutVD, SharedResult);
5159 (void)LocalScope.Privatize();
5160 if (
const auto *OVE = dyn_cast<OpaqueValueExpr>(
5161 CE->getCallee()->IgnoreParenImpCasts())) {
5187 if (
const auto *DRE = dyn_cast<DeclRefExpr>(
Privates)) {
5188 if (
const auto *VD = dyn_cast<VarDecl>(DRE->getDecl())) {
5199 CGF.
Builder.CreateBr(InitEndBB);
5203 CGM.getModule(), OMPRTL___kmpc_barrier),
5206 const Expr *ReductionOp = ReductionOps;
5211 auto EmitCriticalReduction = [&](
auto ReductionGen) {
5212 std::string CriticalName =
getName({
"reduction_critical"});
5220 std::pair<llvm::Function *, llvm::Function *> FnPair =
5223 if (
const auto *CE = dyn_cast<CallExpr>(ReductionOp)) {
5235 (void)LocalScope.Privatize();
5240 EmitCriticalReduction(ReductionGen);
5245 if (
const auto *Cleanup = dyn_cast<ExprWithCleanups>(ReductionClauseExpr))
5248 const Expr *AssignRHS =
nullptr;
5249 if (
const auto *BinOp = dyn_cast<BinaryOperator>(ReductionClauseExpr)) {
5250 if (BinOp->getOpcode() == BO_Assign)
5251 AssignRHS = BinOp->getRHS();
5252 }
else if (
const auto *OpCall =
5253 dyn_cast<CXXOperatorCallExpr>(ReductionClauseExpr)) {
5254 if (OpCall->getOperator() == OO_Equal)
5255 AssignRHS = OpCall->getArg(1);
5259 "Private Variable Reduction : Invalid ReductionOp expression");
5264 const auto *OmpOutDRE =
5266 const auto *OmpInDRE =
5269 OmpOutDRE && OmpInDRE &&
5270 "Private Variable Reduction : LHSExpr/RHSExpr must be DeclRefExprs");
5274 LocalScope.addPrivate(OmpOutVD, SharedLV.
getAddress());
5275 LocalScope.addPrivate(OmpInVD, LHSLV.
getAddress());
5276 (void)LocalScope.Privatize();
5280 EmitCriticalReduction(ReductionGen);
5284 CGM.getModule(), OMPRTL___kmpc_barrier),
5290 llvm::Value *FinalResultVal =
nullptr;
5294 FinalResultAddr = SharedResult;
5308 CGM.getModule(), OMPRTL___kmpc_barrier),
5319 EmitCriticalReduction(OriginalListCombiner);
5371 if (SimpleReduction) {
5373 const auto *IPriv = OrgPrivates.begin();
5374 const auto *ILHS = OrgLHSExprs.begin();
5375 const auto *IRHS = OrgRHSExprs.begin();
5376 for (
const Expr *E : OrgReductionOps) {
5389 FilteredRHSExprs, FilteredReductionOps;
5390 for (
unsigned I : llvm::seq<unsigned>(
5391 std::min(OrgReductionOps.size(), OrgLHSExprs.size()))) {
5393 FilteredPrivates.emplace_back(OrgPrivates[I]);
5394 FilteredLHSExprs.emplace_back(OrgLHSExprs[I]);
5395 FilteredRHSExprs.emplace_back(OrgRHSExprs[I]);
5396 FilteredReductionOps.emplace_back(OrgReductionOps[I]);
5408 auto Size = RHSExprs.size();
5414 llvm::APInt ArraySize(32, Size);
5415 QualType ReductionArrayTy =
C.getConstantArrayType(
5419 CGF.
CreateMemTemp(ReductionArrayTy,
".omp.reduction.red_list");
5420 const auto *IPriv =
Privates.begin();
5422 for (
unsigned I = 0, E = RHSExprs.size(); I < E; ++I, ++IPriv, ++Idx) {
5428 if ((*IPriv)->getType()->isVariablyModifiedType()) {
5432 llvm::Value *Size = CGF.
Builder.CreateIntCast(
5445 Privates, LHSExprs, RHSExprs, ReductionOps);
5448 std::string Name =
getName({
"reduction"});
5455 llvm::Value *ReductionArrayTySize = CGF.
getTypeSize(ReductionArrayTy);
5458 llvm::Value *Args[] = {
5461 CGF.
Builder.getInt32(RHSExprs.size()),
5462 ReductionArrayTySize,
5470 WithNowait ? OMPRTL___kmpc_reduce_nowait : OMPRTL___kmpc_reduce),
5474 llvm::BasicBlock *DefaultBB = CGF.
createBasicBlock(
".omp.reduction.default");
5475 llvm::SwitchInst *SwInst =
5476 CGF.
Builder.CreateSwitch(Res, DefaultBB, 2);
5485 SwInst->addCase(CGF.
Builder.getInt32(1), Case1BB);
5489 llvm::Value *EndArgs[] = {
5497 const auto *IPriv =
Privates.begin();
5498 const auto *ILHS = LHSExprs.begin();
5499 const auto *IRHS = RHSExprs.begin();
5500 for (
const Expr *E : ReductionOps) {
5509 CommonActionTy Action(
5512 CGM.getModule(), WithNowait ? OMPRTL___kmpc_end_reduce_nowait
5513 : OMPRTL___kmpc_end_reduce),
5526 SwInst->addCase(CGF.
Builder.getInt32(2), Case2BB);
5529 auto &&AtomicCodeGen = [Loc,
Privates, LHSExprs, RHSExprs, ReductionOps](
5531 const auto *ILHS = LHSExprs.begin();
5532 const auto *IRHS = RHSExprs.begin();
5533 const auto *IPriv =
Privates.begin();
5534 for (
const Expr *E : ReductionOps) {
5535 const Expr *XExpr =
nullptr;
5536 const Expr *EExpr =
nullptr;
5537 const Expr *UpExpr =
nullptr;
5539 if (
const auto *BO = dyn_cast<BinaryOperator>(E)) {
5540 if (BO->getOpcode() == BO_Assign) {
5541 XExpr = BO->getLHS();
5542 UpExpr = BO->getRHS();
5546 const Expr *RHSExpr = UpExpr;
5549 if (
const auto *ACO = dyn_cast<AbstractConditionalOperator>(
5553 RHSExpr = ACO->getCond();
5555 if (
const auto *BORHS =
5557 EExpr = BORHS->getRHS();
5558 BO = BORHS->getOpcode();
5563 auto &&AtomicRedGen = [BO, VD,
5565 const Expr *EExpr,
const Expr *UpExpr) {
5566 LValue X = CGF.EmitLValue(XExpr);
5569 E = CGF.EmitAnyExpr(EExpr);
5570 CGF.EmitOMPAtomicSimpleUpdateExpr(
5572 llvm::AtomicOrdering::Monotonic, Loc,
5573 [&CGF, UpExpr, VD, Loc](
RValue XRValue) {
5575 Address LHSTemp = CGF.CreateMemTemp(VD->getType());
5576 CGF.emitOMPSimpleStore(
5577 CGF.MakeAddrLValue(LHSTemp, VD->
getType()), XRValue,
5578 VD->getType().getNonReferenceType(), Loc);
5581 return CGF.EmitAnyExpr(UpExpr);
5584 if ((*IPriv)->getType()->isArrayType()) {
5586 const auto *RHSVar =
5589 AtomicRedGen, XExpr, EExpr, UpExpr);
5592 AtomicRedGen(CGF, XExpr, EExpr, UpExpr);
5599 std::string Name = RT.
getName({
"atomic_reduction"});
5608 if ((*IPriv)->getType()->isArrayType()) {
5609 const auto *LHSVar =
5611 const auto *RHSVar =
5616 CritRedGen(CGF,
nullptr,
nullptr,
nullptr);
5627 llvm::Value *EndArgs[] = {
5632 CommonActionTy Action(
nullptr, {},
5634 CGM.getModule(), OMPRTL___kmpc_end_reduce),
5644 assert(OrgLHSExprs.size() == OrgPrivates.size() &&
5645 "PrivateVarReduction: Privates size mismatch");
5646 assert(OrgLHSExprs.size() == OrgReductionOps.size() &&
5647 "PrivateVarReduction: ReductionOps size mismatch");
5648 for (
unsigned I : llvm::seq<unsigned>(
5649 std::min(OrgReductionOps.size(), OrgLHSExprs.size()))) {
5652 OrgRHSExprs[I], OrgReductionOps[I]);
5661 llvm::raw_svector_ostream Out(Buffer);
5669 Out << Prefix << Name <<
"_"
5671 return std::string(Out.str());
5695 Args.emplace_back(Param);
5696 Args.emplace_back(ParamOrig);
5697 const auto &FnInfo =
5701 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
5705 Fn->addFnAttr(
"sample-profile-suffix-elision-policy",
"selected");
5706 Fn->setDoesNotRecurse();
5713 llvm::Value *Size =
nullptr;
5756 const Expr *ReductionOp,
5758 const Expr *PrivateRef) {
5769 Args.emplace_back(ParamInOut);
5770 Args.emplace_back(ParamIn);
5771 const auto &FnInfo =
5775 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
5779 Fn->addFnAttr(
"sample-profile-suffix-elision-policy",
"selected");
5780 Fn->setDoesNotRecurse();
5783 llvm::Value *Size =
nullptr;
5804 C.getPointerType(LHSVD->getType())->castAs<
PointerType>()));
5811 C.getPointerType(RHSVD->getType())->castAs<
PointerType>()));
5841 Args.emplace_back(Param);
5842 const auto &FnInfo =
5846 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
5850 Fn->addFnAttr(
"sample-profile-suffix-elision-policy",
"selected");
5851 Fn->setDoesNotRecurse();
5856 llvm::Value *Size =
nullptr;
5891 RecordDecl *RD =
C.buildImplicitRecord(
"kmp_taskred_input_t");
5900 C, RD,
C.getIntTypeForBitwidth(32,
false));
5903 unsigned Size =
Data.ReductionVars.size();
5904 llvm::APInt ArraySize(64, Size);
5906 C.getConstantArrayType(RDType, ArraySize,
nullptr,
5911 Data.ReductionCopies,
Data.ReductionOps);
5912 for (
unsigned Cnt = 0; Cnt < Size; ++Cnt) {
5914 llvm::Value *Idxs[] = {llvm::ConstantInt::get(
CGM.SizeTy, 0),
5915 llvm::ConstantInt::get(
CGM.SizeTy, Cnt)};
5931 llvm::Value *SizeValInChars;
5932 llvm::Value *SizeVal;
5933 std::tie(SizeValInChars, SizeVal) = RCG.
getSizes(Cnt);
5939 bool DelayedCreation = !!SizeVal;
5940 SizeValInChars = CGF.
Builder.CreateIntCast(SizeValInChars,
CGM.SizeTy,
5951 llvm::Value *FiniAddr =
5952 Fini ? Fini : llvm::ConstantPointerNull::get(
CGM.VoidPtrTy);
5957 CGM, Loc, RCG, Cnt,
Data.ReductionOps[Cnt], LHSExprs[Cnt],
5958 RHSExprs[Cnt],
Data.ReductionCopies[Cnt]);
5962 if (DelayedCreation) {
5964 llvm::ConstantInt::get(
CGM.Int32Ty, 1,
true),
5969 if (
Data.IsReductionWithTaskMod) {
5975 llvm::Value *Args[] = {
5977 llvm::ConstantInt::get(
CGM.IntTy,
Data.IsWorksharingReduction ? 1 : 0,
5979 llvm::ConstantInt::get(
CGM.IntTy, Size,
true),
5984 CGM.getModule(), OMPRTL___kmpc_taskred_modifier_init),
5988 llvm::Value *Args[] = {
5991 llvm::ConstantInt::get(
CGM.IntTy, Size,
true),
5995 CGM.getModule(), OMPRTL___kmpc_taskred_init),
6001 bool IsWorksharingReduction) {
6007 llvm::Value *Args[] = {IdentTLoc, GTid,
6008 llvm::ConstantInt::get(
CGM.IntTy,
6009 IsWorksharingReduction ? 1 : 0,
6013 CGM.getModule(), OMPRTL___kmpc_task_reduction_modifier_fini),
6025 llvm::Value *SizeVal = CGF.
Builder.CreateIntCast(Sizes.second,
CGM.SizeTy,
6028 CGF,
CGM.getContext().getSizeType(),
6036 llvm::Value *ReductionsPtr,
6049 CGM.getModule(), OMPRTL___kmpc_task_reduction_get_th_data),
6065 auto &M =
CGM.getModule();
6067 llvm::Value *NumOfElements;
6068 std::tie(NumOfElements, DependenciesArray) =
6070 if (!
Data.Dependences.empty()) {
6071 llvm::Value *DepWaitTaskArgs[7];
6072 DepWaitTaskArgs[0] = UpLoc;
6073 DepWaitTaskArgs[1] = ThreadID;
6074 DepWaitTaskArgs[2] = NumOfElements;
6076 DepWaitTaskArgs[4] = CGF.
Builder.getInt32(0);
6077 DepWaitTaskArgs[5] = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
6078 DepWaitTaskArgs[6] =
6079 llvm::ConstantInt::get(CGF.
Int32Ty,
Data.HasNowaitClause);
6088 M, OMPRTL___kmpc_omp_taskwait_deps_51),
6095 llvm::Value *Args[] = {UpLoc, ThreadID};
6098 OMPBuilder.getOrCreateRuntimeFunction(M, OMPRTL___kmpc_omp_taskwait),
6103 if (
auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.
CapturedStmtInfo))
6104 Region->emitUntiedSwitch(CGF);
6113 InlinedOpenMPRegionRAII Region(CGF,
CodeGen, InnerKind, HasCancel,
6114 InnerKind != OMPD_critical &&
6115 InnerKind != OMPD_master &&
6116 InnerKind != OMPD_masked);
6131 RTCancelKind CancelKind = CancelNoreq;
6132 if (CancelRegion == OMPD_parallel)
6133 CancelKind = CancelParallel;
6134 else if (CancelRegion == OMPD_for)
6135 CancelKind = CancelLoop;
6136 else if (CancelRegion == OMPD_sections)
6137 CancelKind = CancelSections;
6139 assert(CancelRegion == OMPD_taskgroup);
6140 CancelKind = CancelTaskgroup;
6152 if (
auto *OMPRegionInfo =
6156 if (CancelRegion == OMPD_taskgroup || OMPRegionInfo->hasCancel()) {
6157 llvm::Value *Args[] = {
6163 CGM.getModule(), OMPRTL___kmpc_cancellationpoint),
6172 CGF.
Builder.CreateCondBr(
Cmp, ExitBB, ContBB);
6174 if (CancelRegion == OMPD_parallel)
6192 auto &M =
CGM.getModule();
6193 if (
auto *OMPRegionInfo =
6195 auto &&ThenGen = [
this, &M, Loc, CancelRegion,
6198 llvm::Value *Args[] = {
6202 llvm::Value *
Result = CGF.EmitRuntimeCall(
6203 OMPBuilder.getOrCreateRuntimeFunction(M, OMPRTL___kmpc_cancel), Args);
6208 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(
".cancel.exit");
6209 llvm::BasicBlock *ContBB = CGF.createBasicBlock(
".cancel.continue");
6210 llvm::Value *
Cmp = CGF.Builder.CreateIsNotNull(
Result);
6211 CGF.Builder.CreateCondBr(
Cmp, ExitBB, ContBB);
6212 CGF.EmitBlock(ExitBB);
6213 if (CancelRegion == OMPD_parallel)
6217 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind());
6218 CGF.EmitBranchThroughCleanup(CancelDest);
6219 CGF.EmitBlock(ContBB,
true);
6237 OMPUsesAllocatorsActionTy(
6238 ArrayRef<std::pair<const Expr *, const Expr *>> Allocators)
6239 : Allocators(Allocators) {}
6243 for (
const auto &AllocatorData : Allocators) {
6245 CGF, AllocatorData.first, AllocatorData.second);
6248 void Exit(CodeGenFunction &CGF)
override {
6251 for (
const auto &AllocatorData : Allocators) {
6253 AllocatorData.first);
6261 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
6263 assert(!ParentName.empty() &&
"Invalid target entry parent name!");
6267 for (
unsigned I = 0, E =
C->getNumberOfAllocators(); I < E; ++I) {
6274 OMPUsesAllocatorsActionTy UsesAllocatorAction(Allocators);
6275 CodeGen.setAction(UsesAllocatorAction);
6281 const Expr *Allocator,
6282 const Expr *AllocatorTraits) {
6284 ThreadId = CGF.
Builder.CreateIntCast(ThreadId, CGF.
IntTy,
true);
6286 llvm::Value *MemSpaceHandle = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
6287 llvm::Value *NumTraits = llvm::ConstantInt::get(
6291 .getLimitedValue());
6298 llvm::Value *Traits =
Addr.emitRawPointer(CGF);
6300 llvm::Value *AllocatorVal =
6302 CGM.getModule(), OMPRTL___kmpc_init_allocator),
6303 {ThreadId, MemSpaceHandle, NumTraits, Traits});
6315 const Expr *Allocator) {
6317 ThreadId = CGF.
Builder.CreateIntCast(ThreadId, CGF.
IntTy,
true);
6319 llvm::Value *AllocatorVal =
6326 OMPRTL___kmpc_destroy_allocator),
6327 {ThreadId, AllocatorVal});
6332 llvm::OpenMPIRBuilder::TargetKernelDefaultAttrs &Attrs) {
6333 assert(Attrs.MaxTeams.size() == 1 && Attrs.MaxThreads.size() == 1 &&
6334 "invalid default attrs structure");
6335 int32_t &MaxTeamsVal = Attrs.MaxTeams.front();
6336 int32_t &MaxThreadsVal = Attrs.MaxThreads.front();
6343 for (
auto *A :
C->getAttrs()) {
6344 int32_t AttrMinThreadsVal = 1, AttrMaxThreadsVal = -1;
6345 int32_t AttrMinBlocksVal = 1, AttrMaxBlocksVal = -1;
6346 if (
auto *
Attr = dyn_cast<CUDALaunchBoundsAttr>(A))
6347 CGM.handleCUDALaunchBoundsAttr(
nullptr,
Attr, &AttrMaxThreadsVal,
6348 &AttrMinBlocksVal, &AttrMaxBlocksVal);
6349 else if (
auto *
Attr = dyn_cast<AMDGPUFlatWorkGroupSizeAttr>(A))
6350 CGM.handleAMDGPUFlatWorkGroupSizeAttr(
6351 nullptr,
Attr,
nullptr, &AttrMinThreadsVal,
6352 &AttrMaxThreadsVal);
6356 Attrs.MinThreads = std::max(Attrs.MinThreads, AttrMinThreadsVal);
6357 if (AttrMaxThreadsVal > 0)
6358 MaxThreadsVal = MaxThreadsVal > 0
6359 ? std::min(MaxThreadsVal, AttrMaxThreadsVal)
6360 : AttrMaxThreadsVal;
6361 Attrs.MinTeams = std::max(Attrs.MinTeams, AttrMinBlocksVal);
6362 if (AttrMaxBlocksVal > 0)
6363 MaxTeamsVal = MaxTeamsVal > 0 ? std::min(MaxTeamsVal, AttrMaxBlocksVal)
6371 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
6374 llvm::TargetRegionEntryInfo EntryInfo =
6378 llvm::OpenMPIRBuilder::FunctionGenCallback &&GenerateOutlinedFunction =
6379 [&CGF, &D, &
CodeGen,
this](StringRef EntryFnName) {
6380 const CapturedStmt &CS = *D.getCapturedStmt(OMPD_target);
6382 CGOpenMPTargetRegionInfo CGInfo(CS,
CodeGen, EntryFnName);
6384 if (
CGM.getLangOpts().OpenMPIsTargetDevice && !
isGPU())
6389 cantFail(
OMPBuilder.emitTargetRegionFunction(
6390 EntryInfo, GenerateOutlinedFunction, IsOffloadEntry, OutlinedFn,
6396 CGM.getTargetCodeGenInfo().setTargetAttributes(
nullptr, OutlinedFn,
CGM);
6399 for (
auto *A :
C->getAttrs()) {
6400 if (
auto *
Attr = dyn_cast<AMDGPUWavesPerEUAttr>(A))
6401 CGM.handleAMDGPUWavesPerEUAttr(OutlinedFn,
Attr);
6420 while (
const auto *
C = dyn_cast_or_null<CompoundStmt>(Child)) {
6422 for (
const Stmt *S :
C->body()) {
6423 if (
const auto *E = dyn_cast<Expr>(S)) {
6432 if (
const auto *DS = dyn_cast<DeclStmt>(S)) {
6433 if (llvm::all_of(DS->decls(), [](
const Decl *D) {
6434 if (isa<EmptyDecl>(D) || isa<DeclContext>(D) ||
6435 isa<TypeDecl>(D) || isa<PragmaCommentDecl>(D) ||
6436 isa<PragmaDetectMismatchDecl>(D) || isa<UsingDecl>(D) ||
6437 isa<UsingDirectiveDecl>(D) ||
6438 isa<OMPDeclareReductionDecl>(D) ||
6439 isa<OMPThreadPrivateDecl>(D) || isa<OMPAllocateDecl>(D))
6441 const auto *VD = dyn_cast<VarDecl>(D);
6444 return VD->hasGlobalStorage() || !VD->isUsed();
6454 Child = Child->IgnoreContainers();
6461 int32_t &MaxTeamsVal) {
6465 "Expected target-based executable directive.");
6466 switch (DirectiveKind) {
6468 const auto *CS = D.getInnermostCapturedStmt();
6471 const Stmt *ChildStmt =
6473 if (
const auto *NestedDir =
6474 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) {
6483 MinTeamsVal = MaxTeamsVal =
Constant->getExtValue();
6486 MinTeamsVal = MaxTeamsVal = 0;
6489 MinTeamsVal = MaxTeamsVal = 1;
6493 MinTeamsVal = MaxTeamsVal = -1;
6496 case OMPD_target_teams_loop:
6497 case OMPD_target_teams:
6498 case OMPD_target_teams_distribute:
6499 case OMPD_target_teams_distribute_simd:
6500 case OMPD_target_teams_distribute_parallel_for:
6501 case OMPD_target_teams_distribute_parallel_for_simd: {
6503 const Expr *NumTeams =
6507 MinTeamsVal = MaxTeamsVal =
Constant->getExtValue();
6510 MinTeamsVal = MaxTeamsVal = 0;
6513 case OMPD_target_parallel:
6514 case OMPD_target_parallel_for:
6515 case OMPD_target_parallel_for_simd:
6516 case OMPD_target_parallel_loop:
6517 case OMPD_target_simd:
6518 MinTeamsVal = MaxTeamsVal = 1;
6522 case OMPD_parallel_for:
6523 case OMPD_parallel_loop:
6524 case OMPD_parallel_master:
6525 case OMPD_parallel_sections:
6527 case OMPD_parallel_for_simd:
6529 case OMPD_cancellation_point:
6531 case OMPD_threadprivate:
6542 case OMPD_taskyield:
6545 case OMPD_taskgroup:
6551 case OMPD_target_data:
6552 case OMPD_target_exit_data:
6553 case OMPD_target_enter_data:
6554 case OMPD_distribute:
6555 case OMPD_distribute_simd:
6556 case OMPD_distribute_parallel_for:
6557 case OMPD_distribute_parallel_for_simd:
6558 case OMPD_teams_distribute:
6559 case OMPD_teams_distribute_simd:
6560 case OMPD_teams_distribute_parallel_for:
6561 case OMPD_teams_distribute_parallel_for_simd:
6562 case OMPD_target_update:
6563 case OMPD_declare_simd:
6564 case OMPD_declare_variant:
6565 case OMPD_begin_declare_variant:
6566 case OMPD_end_declare_variant:
6567 case OMPD_declare_target:
6568 case OMPD_end_declare_target:
6569 case OMPD_declare_reduction:
6570 case OMPD_declare_mapper:
6572 case OMPD_taskloop_simd:
6573 case OMPD_master_taskloop:
6574 case OMPD_master_taskloop_simd:
6575 case OMPD_parallel_master_taskloop:
6576 case OMPD_parallel_master_taskloop_simd:
6578 case OMPD_metadirective:
6584 llvm_unreachable(
"Unexpected directive kind.");
6590 "Clauses associated with the teams directive expected to be emitted "
6591 "only for the host!");
6593 int32_t MinNT = -1, MaxNT = -1;
6594 const Expr *NumTeams =
6596 if (NumTeams !=
nullptr) {
6599 switch (DirectiveKind) {
6601 const auto *CS = D.getInnermostCapturedStmt();
6602 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6606 return Bld.CreateIntCast(NumTeamsVal, CGF.
Int32Ty,
6609 case OMPD_target_teams:
6610 case OMPD_target_teams_distribute:
6611 case OMPD_target_teams_distribute_simd:
6612 case OMPD_target_teams_distribute_parallel_for:
6613 case OMPD_target_teams_distribute_parallel_for_simd: {
6617 return Bld.CreateIntCast(NumTeamsVal, CGF.
Int32Ty,
6625 assert(MinNT == MaxNT &&
"Num threads ranges require handling here.");
6626 return llvm::ConstantInt::getSigned(CGF.
Int32Ty, MinNT);
6634 const Expr **E, int32_t &UpperBound,
6635 bool UpperBoundOnly, llvm::Value **CondVal) {
6638 const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child);
6645 if (CondVal && Dir->hasClausesOfKind<
OMPIfClause>()) {
6646 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6649 for (
const auto *
C : Dir->getClausesOfKind<
OMPIfClause>()) {
6650 if (
C->getNameModifier() == OMPD_unknown ||
6651 C->getNameModifier() == OMPD_parallel) {
6666 if (
const auto *PreInit =
6668 for (
const auto *I : PreInit->decls()) {
6669 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
6685 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6687 const auto *NumThreadsClause =
6689 const Expr *NTExpr = NumThreadsClause->getNumThreads();
6690 if (NTExpr->isIntegerConstantExpr(CGF.
getContext()))
6695 : std::min(UpperBound,
6696 static_cast<int32_t
>(
Constant->getZExtValue()));
6699 if (UpperBound == -1)
6704 if (
const auto *PreInit =
6705 cast_or_null<DeclStmt>(NumThreadsClause->getPreInitStmt())) {
6706 for (
const auto *I : PreInit->decls()) {
6707 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
6726 bool UpperBoundOnly, llvm::Value **CondVal,
const Expr **ThreadLimitExpr) {
6727 assert((!CGF.
getLangOpts().OpenMPIsTargetDevice || UpperBoundOnly) &&
6728 "Clauses associated with the teams directive expected to be emitted "
6729 "only for the host!");
6732 "Expected target-based executable directive.");
6734 const Expr *NT =
nullptr;
6735 const Expr **NTPtr = UpperBoundOnly ?
nullptr : &NT;
6737 auto CheckForConstExpr = [&](
const Expr *E,
const Expr **EPtr) {
6740 UpperBound = UpperBound ?
Constant->getZExtValue()
6741 : std::min(UpperBound,
6742 int32_t(
Constant->getZExtValue()));
6746 if (UpperBound == -1)
6752 auto ReturnSequential = [&]() {
6757 switch (DirectiveKind) {
6760 getNumThreads(CGF, CS, NTPtr, UpperBound, UpperBoundOnly, CondVal);
6766 if (
const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) {
6768 ThreadLimitClause = TLC;
6769 if (ThreadLimitExpr) {
6770 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6774 ThreadLimitClause->getThreadLimit().front()->getSourceRange());
6775 if (
const auto *PreInit =
6776 cast_or_null<DeclStmt>(ThreadLimitClause->getPreInitStmt())) {
6777 for (
const auto *I : PreInit->decls()) {
6778 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
6790 if (ThreadLimitClause)
6791 CheckForConstExpr(ThreadLimitClause->getThreadLimit().front(),
6793 if (
const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) {
6796 CS = Dir->getInnermostCapturedStmt();
6799 Dir = dyn_cast_or_null<OMPExecutableDirective>(Child);
6802 CS = Dir->getInnermostCapturedStmt();
6803 getNumThreads(CGF, CS, NTPtr, UpperBound, UpperBoundOnly, CondVal);
6805 return ReturnSequential();
6809 case OMPD_target_teams: {
6813 CheckForConstExpr(ThreadLimitClause->getThreadLimit().front(),
6817 getNumThreads(CGF, CS, NTPtr, UpperBound, UpperBoundOnly, CondVal);
6820 if (
const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) {
6821 if (Dir->getDirectiveKind() == OMPD_distribute) {
6822 CS = Dir->getInnermostCapturedStmt();
6823 getNumThreads(CGF, CS, NTPtr, UpperBound, UpperBoundOnly, CondVal);
6828 case OMPD_target_teams_distribute:
6832 CheckForConstExpr(ThreadLimitClause->getThreadLimit().front(),
6835 getNumThreads(CGF, D.getInnermostCapturedStmt(), NTPtr, UpperBound,
6836 UpperBoundOnly, CondVal);
6838 case OMPD_target_teams_loop:
6839 case OMPD_target_parallel_loop:
6840 case OMPD_target_parallel:
6841 case OMPD_target_parallel_for:
6842 case OMPD_target_parallel_for_simd:
6843 case OMPD_target_teams_distribute_parallel_for:
6844 case OMPD_target_teams_distribute_parallel_for_simd: {
6845 if (CondVal && D.hasClausesOfKind<
OMPIfClause>()) {
6847 for (
const auto *
C : D.getClausesOfKind<
OMPIfClause>()) {
6848 if (
C->getNameModifier() == OMPD_unknown ||
6849 C->getNameModifier() == OMPD_parallel) {
6859 return ReturnSequential();
6869 CheckForConstExpr(ThreadLimitClause->getThreadLimit().front(),
6875 CheckForConstExpr(NumThreadsClause->getNumThreads(),
nullptr);
6876 return NumThreadsClause->getNumThreads();
6880 case OMPD_target_teams_distribute_simd:
6881 case OMPD_target_simd:
6882 return ReturnSequential();
6886 llvm_unreachable(
"Unsupported directive kind.");
6891 llvm::Value *NumThreadsVal =
nullptr;
6892 llvm::Value *CondVal =
nullptr;
6893 llvm::Value *ThreadLimitVal =
nullptr;
6894 const Expr *ThreadLimitExpr =
nullptr;
6895 int32_t UpperBound = -1;
6898 CGF, D, UpperBound,
false, &CondVal,
6902 if (ThreadLimitExpr) {
6905 ThreadLimitVal = CGF.
Builder.CreateIntCast(ThreadLimitVal, CGF.
Int32Ty,
6910 if (UpperBound == 1) {
6911 NumThreadsVal = CGF.
Builder.getInt32(UpperBound);
6914 NumThreadsVal = CGF.
Builder.CreateIntCast(NumThreadsVal, CGF.
Int32Ty,
6916 }
else if (ThreadLimitVal) {
6919 NumThreadsVal = ThreadLimitVal;
6920 ThreadLimitVal =
nullptr;
6923 assert(!ThreadLimitVal &&
"Default not applicable with thread limit value");
6924 NumThreadsVal = CGF.
Builder.getInt32(0);
6931 NumThreadsVal = CGF.
Builder.CreateSelect(CondVal, NumThreadsVal,
6937 if (ThreadLimitVal) {
6938 NumThreadsVal = CGF.
Builder.CreateSelect(
6939 CGF.
Builder.CreateICmpULT(ThreadLimitVal, NumThreadsVal),
6940 ThreadLimitVal, NumThreadsVal);
6943 return NumThreadsVal;
6953class MappableExprsHandler {
6959 struct AttachPtrExprComparator {
6960 const MappableExprsHandler &Handler;
6962 mutable llvm::DenseMap<std::pair<const Expr *, const Expr *>,
bool>
6963 CachedEqualityComparisons;
6965 AttachPtrExprComparator(
const MappableExprsHandler &H) : Handler(H) {}
6966 AttachPtrExprComparator() =
delete;
6969 bool operator()(
const Expr *LHS,
const Expr *RHS)
const {
6974 const auto ItLHS = Handler.AttachPtrComponentDepthMap.find(LHS);
6975 const auto ItRHS = Handler.AttachPtrComponentDepthMap.find(RHS);
6977 std::optional<size_t> DepthLHS =
6978 (ItLHS != Handler.AttachPtrComponentDepthMap.end()) ? ItLHS->second
6980 std::optional<size_t> DepthRHS =
6981 (ItRHS != Handler.AttachPtrComponentDepthMap.end()) ? ItRHS->second
6985 if (!DepthLHS.has_value() && !DepthRHS.has_value()) {
6987 if (areEqual(LHS, RHS))
6990 return wasComputedBefore(LHS, RHS);
6992 if (!DepthLHS.has_value())
6994 if (!DepthRHS.has_value())
6998 if (DepthLHS.value() != DepthRHS.value())
6999 return DepthLHS.value() < DepthRHS.value();
7002 if (areEqual(LHS, RHS))
7005 return wasComputedBefore(LHS, RHS);
7011 bool areEqual(
const Expr *LHS,
const Expr *RHS)
const {
7013 const auto CachedResultIt = CachedEqualityComparisons.find({LHS, RHS});
7014 if (CachedResultIt != CachedEqualityComparisons.end())
7015 return CachedResultIt->second;
7029 bool wasComputedBefore(
const Expr *LHS,
const Expr *RHS)
const {
7030 const size_t &OrderLHS = Handler.AttachPtrComputationOrderMap.at(LHS);
7031 const size_t &OrderRHS = Handler.AttachPtrComputationOrderMap.at(RHS);
7033 return OrderLHS < OrderRHS;
7042 bool areSemanticallyEqual(
const Expr *LHS,
const Expr *RHS)
const {
7064 if (
const auto *LD = dyn_cast<DeclRefExpr>(LHS)) {
7065 const auto *RD = dyn_cast<DeclRefExpr>(RHS);
7068 return LD->getDecl()->getCanonicalDecl() ==
7069 RD->getDecl()->getCanonicalDecl();
7073 if (
const auto *LA = dyn_cast<ArraySubscriptExpr>(LHS)) {
7074 const auto *RA = dyn_cast<ArraySubscriptExpr>(RHS);
7077 return areSemanticallyEqual(LA->getBase(), RA->getBase()) &&
7078 areSemanticallyEqual(LA->getIdx(), RA->getIdx());
7082 if (
const auto *LM = dyn_cast<MemberExpr>(LHS)) {
7083 const auto *RM = dyn_cast<MemberExpr>(RHS);
7086 if (LM->getMemberDecl()->getCanonicalDecl() !=
7087 RM->getMemberDecl()->getCanonicalDecl())
7089 return areSemanticallyEqual(LM->getBase(), RM->getBase());
7093 if (
const auto *LU = dyn_cast<UnaryOperator>(LHS)) {
7094 const auto *RU = dyn_cast<UnaryOperator>(RHS);
7097 if (LU->getOpcode() != RU->getOpcode())
7099 return areSemanticallyEqual(LU->getSubExpr(), RU->getSubExpr());
7103 if (
const auto *LB = dyn_cast<BinaryOperator>(LHS)) {
7104 const auto *RB = dyn_cast<BinaryOperator>(RHS);
7107 if (LB->getOpcode() != RB->getOpcode())
7109 return areSemanticallyEqual(LB->getLHS(), RB->getLHS()) &&
7110 areSemanticallyEqual(LB->getRHS(), RB->getRHS());
7116 if (
const auto *LAS = dyn_cast<ArraySectionExpr>(LHS)) {
7117 const auto *RAS = dyn_cast<ArraySectionExpr>(RHS);
7120 return areSemanticallyEqual(LAS->getBase(), RAS->getBase()) &&
7121 areSemanticallyEqual(LAS->getLowerBound(),
7122 RAS->getLowerBound()) &&
7123 areSemanticallyEqual(LAS->getLength(), RAS->getLength());
7127 if (
const auto *LC = dyn_cast<CastExpr>(LHS)) {
7128 const auto *RC = dyn_cast<CastExpr>(RHS);
7131 if (LC->getCastKind() != RC->getCastKind())
7133 return areSemanticallyEqual(LC->getSubExpr(), RC->getSubExpr());
7141 if (
const auto *LI = dyn_cast<IntegerLiteral>(LHS)) {
7142 const auto *RI = dyn_cast<IntegerLiteral>(RHS);
7145 return LI->getValue() == RI->getValue();
7149 if (
const auto *LC = dyn_cast<CharacterLiteral>(LHS)) {
7150 const auto *RC = dyn_cast<CharacterLiteral>(RHS);
7153 return LC->getValue() == RC->getValue();
7157 if (
const auto *LF = dyn_cast<FloatingLiteral>(LHS)) {
7158 const auto *RF = dyn_cast<FloatingLiteral>(RHS);
7162 return LF->getValue().bitwiseIsEqual(RF->getValue());
7166 if (
const auto *LS = dyn_cast<StringLiteral>(LHS)) {
7167 const auto *RS = dyn_cast<StringLiteral>(RHS);
7170 return LS->getString() == RS->getString();
7178 if (
const auto *LB = dyn_cast<CXXBoolLiteralExpr>(LHS)) {
7179 const auto *RB = dyn_cast<CXXBoolLiteralExpr>(RHS);
7182 return LB->getValue() == RB->getValue();
7191 static unsigned getFlagMemberOffset() {
7192 unsigned Offset = 0;
7193 for (uint64_t Remain =
7194 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
7195 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF);
7196 !(Remain & 1); Remain = Remain >> 1)
7203 class MappingExprInfo {
7205 const ValueDecl *MapDecl =
nullptr;
7208 const Expr *MapExpr =
nullptr;
7211 MappingExprInfo(
const ValueDecl *MapDecl,
const Expr *MapExpr =
nullptr)
7212 : MapDecl(MapDecl), MapExpr(MapExpr) {}
7214 const ValueDecl *getMapDecl()
const {
return MapDecl; }
7215 const Expr *getMapExpr()
const {
return MapExpr; }
7218 using DeviceInfoTy = llvm::OpenMPIRBuilder::DeviceInfoTy;
7219 using MapBaseValuesArrayTy = llvm::OpenMPIRBuilder::MapValuesArrayTy;
7220 using MapValuesArrayTy = llvm::OpenMPIRBuilder::MapValuesArrayTy;
7221 using MapFlagsArrayTy = llvm::OpenMPIRBuilder::MapFlagsArrayTy;
7222 using MapDimArrayTy = llvm::OpenMPIRBuilder::MapDimArrayTy;
7223 using MapNonContiguousArrayTy =
7224 llvm::OpenMPIRBuilder::MapNonContiguousArrayTy;
7225 using MapExprsArrayTy = SmallVector<MappingExprInfo, 4>;
7226 using MapValueDeclsArrayTy = SmallVector<const ValueDecl *, 4>;
7230 bool ,
const ValueDecl *,
const Expr *>;
7231 using MapDataArrayTy = SmallVector<MapData, 4>;
7236 struct MapCombinedInfoTy : llvm::OpenMPIRBuilder::MapInfosTy {
7237 MapExprsArrayTy Exprs;
7238 MapValueDeclsArrayTy Mappers;
7239 MapValueDeclsArrayTy DevicePtrDecls;
7242 void append(MapCombinedInfoTy &CurInfo) {
7243 Exprs.append(CurInfo.Exprs.begin(), CurInfo.Exprs.end());
7244 DevicePtrDecls.append(CurInfo.DevicePtrDecls.begin(),
7245 CurInfo.DevicePtrDecls.end());
7246 Mappers.append(CurInfo.Mappers.begin(), CurInfo.Mappers.end());
7247 llvm::OpenMPIRBuilder::MapInfosTy::append(CurInfo);
7255 struct StructRangeInfoTy {
7256 MapCombinedInfoTy PreliminaryMapData;
7257 std::pair<
unsigned ,
Address > LowestElem = {
7259 std::pair<
unsigned ,
Address > HighestElem = {
7263 bool IsArraySection =
false;
7264 bool HasCompleteRecord =
false;
7269 struct AttachInfoTy {
7272 const ValueDecl *AttachPtrDecl =
nullptr;
7273 const Expr *AttachMapExpr =
nullptr;
7275 bool isValid()
const {
7282 bool hasAttachEntryForCapturedVar(
const ValueDecl *VD)
const {
7283 for (
const auto &AttachEntry : AttachPtrExprMap) {
7284 if (AttachEntry.second) {
7287 if (
const auto *DRE = dyn_cast<DeclRefExpr>(AttachEntry.second))
7288 if (DRE->getDecl() == VD)
7296 const Expr *getAttachPtrExpr(
7299 const auto It = AttachPtrExprMap.find(Components);
7300 if (It != AttachPtrExprMap.end())
7311 ArrayRef<OpenMPMapModifierKind> MapModifiers;
7312 ArrayRef<OpenMPMotionModifierKind> MotionModifiers;
7313 bool ReturnDevicePointer =
false;
7314 bool IsImplicit =
false;
7315 const ValueDecl *Mapper =
nullptr;
7316 const Expr *VarRef =
nullptr;
7317 bool ForDeviceAddr =
false;
7318 bool HasUdpFbNullify =
false;
7320 MapInfo() =
default;
7324 ArrayRef<OpenMPMapModifierKind> MapModifiers,
7325 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
7326 bool ReturnDevicePointer,
bool IsImplicit,
7327 const ValueDecl *Mapper =
nullptr,
const Expr *VarRef =
nullptr,
7328 bool ForDeviceAddr =
false,
bool HasUdpFbNullify =
false)
7329 : Components(Components), MapType(MapType), MapModifiers(MapModifiers),
7330 MotionModifiers(MotionModifiers),
7331 ReturnDevicePointer(ReturnDevicePointer), IsImplicit(IsImplicit),
7332 Mapper(Mapper), VarRef(VarRef), ForDeviceAddr(ForDeviceAddr),
7333 HasUdpFbNullify(HasUdpFbNullify) {}
7338 llvm::PointerUnion<
const OMPExecutableDirective *,
7339 const OMPDeclareMapperDecl *>
7343 CodeGenFunction &CGF;
7348 llvm::DenseMap<CanonicalDeclPtr<const VarDecl>,
bool> FirstPrivateDecls;
7351 llvm::SmallSet<OpenMPDefaultmapClauseKind, 4> DefaultmapFirstprivateKinds;
7357 SmallVector<OMPClauseMappableExprCommon::MappableExprComponentListRef, 4>>
7364 SmallVector<OMPClauseMappableExprCommon::MappableExprComponentListRef, 4>>
7368 llvm::DenseMap<const ValueDecl *, const OMPMapClause *> LambdasMap;
7383 llvm::DenseMap<const Expr *, std::optional<size_t>>
7384 AttachPtrComponentDepthMap = {{
nullptr, std::nullopt}};
7388 llvm::DenseMap<const Expr *, size_t> AttachPtrComputationOrderMap = {
7393 AttachPtrExprComparator AttachPtrComparator;
7395 llvm::Value *getExprTypeSize(
const Expr *E)
const {
7399 if (
const auto *OAE = dyn_cast<OMPArrayShapingExpr>(E)) {
7401 CGF.
getTypeSize(OAE->getBase()->getType()->getPointeeType());
7402 for (
const Expr *SE : OAE->getDimensions()) {
7413 if (
const auto *RefTy = ExprTy->
getAs<ReferenceType>())
7419 if (
const auto *OAE = dyn_cast<ArraySectionExpr>(E)) {
7421 OAE->getBase()->IgnoreParenImpCasts())
7427 if (!OAE->getLength() && OAE->getColonLocFirst().isValid() &&
7428 !OAE->getLowerBound())
7431 llvm::Value *ElemSize;
7432 if (
const auto *PTy = BaseTy->
getAs<PointerType>()) {
7433 ElemSize = CGF.
getTypeSize(PTy->getPointeeType().getCanonicalType());
7436 assert(ATy &&
"Expecting array type if not a pointer type.");
7437 ElemSize = CGF.
getTypeSize(ATy->getElementType().getCanonicalType());
7442 if (!OAE->getLength() && OAE->getColonLocFirst().isInvalid())
7445 if (
const Expr *LenExpr = OAE->getLength()) {
7449 LenExpr->getExprLoc());
7450 return CGF.
Builder.CreateNUWMul(LengthVal, ElemSize);
7452 assert(!OAE->getLength() && OAE->getColonLocFirst().isValid() &&
7453 OAE->getLowerBound() &&
"expected array_section[lb:].");
7459 OAE->getLowerBound()->getExprLoc());
7460 LBVal = CGF.
Builder.CreateNUWMul(LBVal, ElemSize);
7461 llvm::Value *
Cmp = CGF.
Builder.CreateICmpUGT(LengthVal, LBVal);
7462 llvm::Value *TrueVal = CGF.
Builder.CreateNUWSub(LengthVal, LBVal);
7463 LengthVal = CGF.
Builder.CreateSelect(
7464 Cmp, TrueVal, llvm::ConstantInt::get(CGF.
SizeTy, 0));
7474 OpenMPOffloadMappingFlags getMapTypeBits(
7476 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
bool IsImplicit,
7477 bool AddPtrFlag,
bool AddIsTargetParamFlag,
bool IsNonContiguous)
const {
7478 OpenMPOffloadMappingFlags Bits =
7479 IsImplicit ? OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT
7480 : OpenMPOffloadMappingFlags::OMP_MAP_NONE;
7482 case OMPC_MAP_alloc:
7483 case OMPC_MAP_release:
7490 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_TO;
7493 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_FROM;
7495 case OMPC_MAP_tofrom:
7496 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_TO |
7497 OpenMPOffloadMappingFlags::OMP_MAP_FROM;
7499 case OMPC_MAP_delete:
7500 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_DELETE;
7503 llvm_unreachable(
"Unexpected map type!");
7506 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ;
7507 if (AddIsTargetParamFlag)
7508 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM;
7509 if (llvm::is_contained(MapModifiers, OMPC_MAP_MODIFIER_always))
7510 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_ALWAYS;
7511 if (llvm::is_contained(MapModifiers, OMPC_MAP_MODIFIER_close))
7512 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_CLOSE;
7513 if (llvm::is_contained(MapModifiers, OMPC_MAP_MODIFIER_present) ||
7514 llvm::is_contained(MotionModifiers, OMPC_MOTION_MODIFIER_present))
7515 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_PRESENT;
7516 if (llvm::is_contained(MapModifiers, OMPC_MAP_MODIFIER_ompx_hold))
7517 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_OMPX_HOLD;
7518 if (IsNonContiguous)
7519 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_NON_CONTIG;
7525 bool isFinalArraySectionExpression(
const Expr *E)
const {
7526 const auto *OASE = dyn_cast<ArraySectionExpr>(E);
7533 if (OASE->getColonLocFirst().isInvalid())
7536 const Expr *Length = OASE->getLength();
7543 OASE->getBase()->IgnoreParenImpCasts())
7545 if (
const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.
getTypePtr()))
7546 return ATy->getSExtSize() != 1;
7558 llvm::APSInt ConstLength =
Result.Val.getInt();
7559 return ConstLength.getSExtValue() != 1;
7566 void emitAttachEntry(CodeGenFunction &CGF, MapCombinedInfoTy &CombinedInfo,
7567 const AttachInfoTy &AttachInfo)
const {
7568 assert(AttachInfo.isValid() &&
7569 "Expected valid attach pointer/pointee information!");
7573 llvm::Value *PointerSize = CGF.
Builder.CreateIntCast(
7574 llvm::ConstantInt::get(
7580 CombinedInfo.Exprs.emplace_back(AttachInfo.AttachPtrDecl,
7581 AttachInfo.AttachMapExpr);
7582 CombinedInfo.BasePointers.push_back(
7583 AttachInfo.AttachPtrAddr.emitRawPointer(CGF));
7584 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
7585 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
7586 CombinedInfo.Pointers.push_back(
7587 AttachInfo.AttachPteeAddr.emitRawPointer(CGF));
7588 CombinedInfo.Sizes.push_back(PointerSize);
7589 CombinedInfo.Types.push_back(OpenMPOffloadMappingFlags::OMP_MAP_ATTACH);
7590 CombinedInfo.Mappers.push_back(
nullptr);
7591 CombinedInfo.NonContigInfo.Dims.push_back(1);
7598 class CopyOverlappedEntryGaps {
7599 CodeGenFunction &CGF;
7600 MapCombinedInfoTy &CombinedInfo;
7601 OpenMPOffloadMappingFlags Flags = OpenMPOffloadMappingFlags::OMP_MAP_NONE;
7602 const ValueDecl *MapDecl =
nullptr;
7603 const Expr *MapExpr =
nullptr;
7605 bool IsNonContiguous =
false;
7609 const RecordDecl *LastParent =
nullptr;
7611 unsigned LastIndex = -1u;
7615 CopyOverlappedEntryGaps(CodeGenFunction &CGF,
7616 MapCombinedInfoTy &CombinedInfo,
7617 OpenMPOffloadMappingFlags Flags,
7618 const ValueDecl *MapDecl,
const Expr *MapExpr,
7619 Address BP, Address LB,
bool IsNonContiguous,
7621 : CGF(CGF), CombinedInfo(CombinedInfo), Flags(Flags), MapDecl(MapDecl),
7622 MapExpr(MapExpr), BP(BP), IsNonContiguous(IsNonContiguous),
7623 DimSize(DimSize), LB(LB) {}
7626 const OMPClauseMappableExprCommon::MappableComponent &MC,
7627 const FieldDecl *FD,
7628 llvm::function_ref<LValue(CodeGenFunction &,
const MemberExpr *)>
7629 EmitMemberExprBase) {
7639 LValue BaseLVal = EmitMemberExprBase(CGF, ME);
7651 copyUntilField(FD, ComponentLB);
7654 if (((int64_t)FieldOffset - (int64_t)Cursor) > 0)
7655 copyUntilField(FD, ComponentLB);
7657 Cursor = FieldOffset + FieldSize;
7662 void copyUntilField(
const FieldDecl *FD, Address ComponentLB) {
7665 llvm::Value *
Size = CGF.
Builder.CreatePtrDiff(ComponentLBPtr, LBPtr);
7666 copySizedChunk(LBPtr, Size);
7669 void copyUntilEnd(Address HB) {
7671 const ASTRecordLayout &RL =
7679 copySizedChunk(LBPtr, Size);
7682 void copySizedChunk(llvm::Value *Base, llvm::Value *Size) {
7683 CombinedInfo.Exprs.emplace_back(MapDecl, MapExpr);
7685 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
7686 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
7687 CombinedInfo.Pointers.push_back(Base);
7688 CombinedInfo.Sizes.push_back(
7690 CombinedInfo.Types.push_back(Flags);
7691 CombinedInfo.Mappers.push_back(
nullptr);
7692 CombinedInfo.NonContigInfo.Dims.push_back(IsNonContiguous ? DimSize : 1);
7701 void generateInfoForComponentList(
7703 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
7705 MapCombinedInfoTy &CombinedInfo,
7706 MapCombinedInfoTy &StructBaseCombinedInfo,
7707 StructRangeInfoTy &PartialStruct, AttachInfoTy &AttachInfo,
7708 bool IsFirstComponentList,
bool IsImplicit,
7709 bool GenerateAllInfoForClauses,
const ValueDecl *Mapper =
nullptr,
7710 bool ForDeviceAddr =
false,
const ValueDecl *BaseDecl =
nullptr,
7711 const Expr *MapExpr =
nullptr,
7712 ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef>
7713 OverlappedElements = {})
const {
7931 bool IsCaptureFirstInfo = IsFirstComponentList;
7935 bool RequiresReference =
false;
7938 auto CI = Components.rbegin();
7939 auto CE = Components.rend();
7944 bool IsExpressionFirstInfo =
true;
7945 bool FirstPointerInComplexData =
false;
7948 const Expr *AssocExpr = I->getAssociatedExpression();
7949 const auto *AE = dyn_cast<ArraySubscriptExpr>(AssocExpr);
7950 const auto *OASE = dyn_cast<ArraySectionExpr>(AssocExpr);
7951 const auto *OAShE = dyn_cast<OMPArrayShapingExpr>(AssocExpr);
7954 const Expr *AttachPtrExpr = getAttachPtrExpr(Components);
7955 auto [AttachPtrAddr, AttachPteeBaseAddr] =
7956 getAttachPtrAddrAndPteeBaseAddr(AttachPtrExpr, CGF);
7958 bool HasAttachPtr = AttachPtrExpr !=
nullptr;
7959 bool FirstComponentIsForAttachPtr = AssocExpr == AttachPtrExpr;
7960 bool SeenAttachPtr = FirstComponentIsForAttachPtr;
7962 if (FirstComponentIsForAttachPtr) {
7970 }
else if ((AE &&
isa<CXXThisExpr>(AE->getBase()->IgnoreParenImpCasts())) ||
7984 if (
const auto *VD =
7985 dyn_cast_or_null<VarDecl>(I->getAssociatedDeclaration())) {
7986 if (std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
7987 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD)) {
7988 if ((*Res == OMPDeclareTargetDeclAttr::MT_Link) ||
7989 ((*Res == OMPDeclareTargetDeclAttr::MT_To ||
7990 *Res == OMPDeclareTargetDeclAttr::MT_Enter) &&
7992 RequiresReference =
true;
8002 I->getAssociatedDeclaration()->
getType().getNonReferenceType();
8007 const auto *VD = dyn_cast<VarDecl>(I->getAssociatedDeclaration());
8009 !VD || VD->hasLocalStorage() || HasAttachPtr)
8012 FirstPointerInComplexData =
true;
8031 bool ShouldBeMemberOf =
false;
8040 const MemberExpr *EncounteredME =
nullptr;
8052 bool IsNonContiguous =
8053 CombinedInfo.NonContigInfo.IsNonContiguous ||
8054 any_of(Components, [&](
const auto &Component) {
8056 dyn_cast<ArraySectionExpr>(Component.getAssociatedExpression());
8060 const Expr *StrideExpr = OASE->getStride();
8065 "Stride expression must be of integer type");
8078 bool IsPrevMemberReference =
false;
8080 bool IsPartialMapped =
8081 !PartialStruct.PreliminaryMapData.BasePointers.empty();
8088 bool IsMappingWholeStruct =
true;
8089 if (!GenerateAllInfoForClauses) {
8090 IsMappingWholeStruct =
false;
8092 for (
auto TempI = I; TempI != CE; ++TempI) {
8093 const MemberExpr *PossibleME =
8094 dyn_cast<MemberExpr>(TempI->getAssociatedExpression());
8096 IsMappingWholeStruct =
false;
8102 bool SeenFirstNonBinOpExprAfterAttachPtr =
false;
8103 for (; I != CE; ++I) {
8106 if (HasAttachPtr && !SeenAttachPtr) {
8107 SeenAttachPtr = I->getAssociatedExpression() == AttachPtrExpr;
8114 if (HasAttachPtr && !SeenFirstNonBinOpExprAfterAttachPtr) {
8115 const auto *BO = dyn_cast<BinaryOperator>(I->getAssociatedExpression());
8120 SeenFirstNonBinOpExprAfterAttachPtr =
true;
8121 BP = AttachPteeBaseAddr;
8125 if (!EncounteredME) {
8126 EncounteredME = dyn_cast<MemberExpr>(I->getAssociatedExpression());
8129 if (EncounteredME) {
8130 ShouldBeMemberOf =
true;
8133 if (FirstPointerInComplexData) {
8134 QualType Ty = std::prev(I)
8135 ->getAssociatedDeclaration()
8137 .getNonReferenceType();
8139 FirstPointerInComplexData =
false;
8144 auto Next = std::next(I);
8154 bool IsFinalArraySection =
8156 isFinalArraySectionExpression(I->getAssociatedExpression());
8160 const ValueDecl *MapDecl = (I->getAssociatedDeclaration())
8161 ? I->getAssociatedDeclaration()
8163 MapExpr = (I->getAssociatedExpression()) ? I->getAssociatedExpression()
8170 dyn_cast<ArraySectionExpr>(I->getAssociatedExpression());
8172 dyn_cast<OMPArrayShapingExpr>(I->getAssociatedExpression());
8173 const auto *UO = dyn_cast<UnaryOperator>(I->getAssociatedExpression());
8174 const auto *BO = dyn_cast<BinaryOperator>(I->getAssociatedExpression());
8180 I->getAssociatedExpression()->getType()->isAnyPointerType();
8181 bool IsMemberReference =
isa<MemberExpr>(I->getAssociatedExpression()) &&
8184 bool IsNonDerefPointer = IsPointer &&
8185 !(UO && UO->getOpcode() != UO_Deref) && !BO &&
8191 if (
Next == CE || IsMemberReference || IsNonDerefPointer ||
8192 IsFinalArraySection) {
8195 assert((
Next == CE ||
8202 "Unexpected expression");
8206 auto &&EmitMemberExprBase = [](CodeGenFunction &CGF,
8207 const MemberExpr *E) {
8208 const Expr *BaseExpr = E->getBase();
8213 LValueBaseInfo BaseInfo;
8214 TBAAAccessInfo TBAAInfo;
8228 OAShE->getBase()->getType()->getPointeeType()),
8230 OAShE->getBase()->getType()));
8231 }
else if (IsMemberReference) {
8233 LValue BaseLVal = EmitMemberExprBase(CGF, ME);
8248 FinalLowestElem = LowestElem;
8253 bool IsMemberPointerOrAddr =
8255 (((IsPointer || ForDeviceAddr) &&
8256 I->getAssociatedExpression() == EncounteredME) ||
8257 (IsPrevMemberReference && !IsPointer) ||
8258 (IsMemberReference &&
Next != CE &&
8259 !
Next->getAssociatedExpression()->getType()->isPointerType()));
8260 if (!OverlappedElements.empty() &&
Next == CE) {
8262 assert(!PartialStruct.Base.isValid() &&
"The base element is set.");
8263 assert(!IsPointer &&
8264 "Unexpected base element with the pointer type.");
8267 PartialStruct.LowestElem = {0, LowestElem};
8269 I->getAssociatedExpression()->getType());
8274 PartialStruct.HighestElem = {
8275 std::numeric_limits<
decltype(
8276 PartialStruct.HighestElem.first)>
::max(),
8278 PartialStruct.Base = BP;
8279 PartialStruct.LB = LB;
8281 PartialStruct.PreliminaryMapData.BasePointers.empty() &&
8282 "Overlapped elements must be used only once for the variable.");
8283 std::swap(PartialStruct.PreliminaryMapData, CombinedInfo);
8285 OpenMPOffloadMappingFlags Flags =
8286 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF |
8287 getMapTypeBits(MapType, MapModifiers, MotionModifiers, IsImplicit,
8289 false, IsNonContiguous);
8290 CopyOverlappedEntryGaps CopyGaps(CGF, CombinedInfo, Flags, MapDecl,
8291 MapExpr, BP, LB, IsNonContiguous,
8295 Component : OverlappedElements) {
8296 for (
const OMPClauseMappableExprCommon::MappableComponent &MC :
8299 if (
const auto *FD = dyn_cast<FieldDecl>(VD)) {
8300 CopyGaps.processField(MC, FD, EmitMemberExprBase);
8305 CopyGaps.copyUntilEnd(HB);
8308 llvm::Value *
Size = getExprTypeSize(I->getAssociatedExpression());
8315 if ((!IsMemberPointerOrAddr && !IsPartialMapped) ||
8317 if (!IsMappingWholeStruct) {
8318 CombinedInfo.Exprs.emplace_back(MapDecl, MapExpr);
8320 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
8321 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
8323 CombinedInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
8325 CombinedInfo.NonContigInfo.Dims.push_back(IsNonContiguous ? DimSize
8328 StructBaseCombinedInfo.Exprs.emplace_back(MapDecl, MapExpr);
8329 StructBaseCombinedInfo.BasePointers.push_back(
8331 StructBaseCombinedInfo.DevicePtrDecls.push_back(
nullptr);
8332 StructBaseCombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
8333 StructBaseCombinedInfo.Pointers.push_back(LB.
emitRawPointer(CGF));
8334 StructBaseCombinedInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
8336 StructBaseCombinedInfo.NonContigInfo.Dims.push_back(
8337 IsNonContiguous ? DimSize : 1);
8341 bool HasMapper = Mapper &&
Next == CE;
8342 if (!IsMappingWholeStruct)
8343 CombinedInfo.Mappers.push_back(HasMapper ? Mapper :
nullptr);
8345 StructBaseCombinedInfo.Mappers.push_back(HasMapper ? Mapper
8352 OpenMPOffloadMappingFlags Flags = getMapTypeBits(
8353 MapType, MapModifiers, MotionModifiers, IsImplicit,
8354 !IsExpressionFirstInfo || RequiresReference ||
8355 FirstPointerInComplexData || IsMemberReference,
8356 IsCaptureFirstInfo && !RequiresReference, IsNonContiguous);
8358 if (!IsExpressionFirstInfo || IsMemberReference) {
8361 if (IsPointer || (IsMemberReference &&
Next != CE))
8362 Flags &= ~(OpenMPOffloadMappingFlags::OMP_MAP_TO |
8363 OpenMPOffloadMappingFlags::OMP_MAP_FROM |
8364 OpenMPOffloadMappingFlags::OMP_MAP_ALWAYS |
8365 OpenMPOffloadMappingFlags::OMP_MAP_DELETE |
8366 OpenMPOffloadMappingFlags::OMP_MAP_CLOSE);
8368 if (ShouldBeMemberOf) {
8371 Flags |= OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF;
8374 ShouldBeMemberOf =
false;
8378 if (!IsMappingWholeStruct)
8379 CombinedInfo.Types.push_back(Flags);
8381 StructBaseCombinedInfo.Types.push_back(Flags);
8387 if (EncounteredME) {
8392 if (!PartialStruct.Base.isValid()) {
8393 PartialStruct.LowestElem = {FieldIndex, LowestElem};
8394 if (IsFinalArraySection && OASE) {
8398 PartialStruct.HighestElem = {FieldIndex, HB};
8400 PartialStruct.HighestElem = {FieldIndex, LowestElem};
8402 PartialStruct.Base = BP;
8403 PartialStruct.LB = BP;
8404 }
else if (FieldIndex < PartialStruct.LowestElem.first) {
8405 PartialStruct.LowestElem = {FieldIndex, LowestElem};
8406 }
else if (FieldIndex > PartialStruct.HighestElem.first) {
8407 if (IsFinalArraySection && OASE) {
8411 PartialStruct.HighestElem = {FieldIndex, HB};
8413 PartialStruct.HighestElem = {FieldIndex, LowestElem};
8419 if (IsFinalArraySection || IsNonContiguous)
8420 PartialStruct.IsArraySection =
true;
8423 if (IsFinalArraySection)
8428 BP = IsMemberReference ? LowestElem : LB;
8429 if (!IsPartialMapped)
8430 IsExpressionFirstInfo =
false;
8431 IsCaptureFirstInfo =
false;
8432 FirstPointerInComplexData =
false;
8433 IsPrevMemberReference = IsMemberReference;
8434 }
else if (FirstPointerInComplexData) {
8435 QualType Ty = Components.rbegin()
8436 ->getAssociatedDeclaration()
8438 .getNonReferenceType();
8440 FirstPointerInComplexData =
false;
8446 PartialStruct.HasCompleteRecord =
true;
8449 if (shouldEmitAttachEntry(AttachPtrExpr, BaseDecl, CGF, CurDir)) {
8450 AttachInfo.AttachPtrAddr = AttachPtrAddr;
8451 AttachInfo.AttachPteeAddr = FinalLowestElem;
8452 AttachInfo.AttachPtrDecl = BaseDecl;
8453 AttachInfo.AttachMapExpr = MapExpr;
8456 if (!IsNonContiguous)
8459 const ASTContext &Context = CGF.
getContext();
8463 MapValuesArrayTy CurOffsets = {llvm::ConstantInt::get(CGF.
CGM.
Int64Ty, 0)};
8464 MapValuesArrayTy CurCounts;
8465 MapValuesArrayTy CurStrides = {llvm::ConstantInt::get(CGF.
CGM.
Int64Ty, 1)};
8466 MapValuesArrayTy DimSizes{llvm::ConstantInt::get(CGF.
CGM.
Int64Ty, 1)};
8472 for (
const OMPClauseMappableExprCommon::MappableComponent &Component :
8474 const Expr *AssocExpr = Component.getAssociatedExpression();
8475 const auto *OASE = dyn_cast<ArraySectionExpr>(AssocExpr);
8485 assert((VAT || CAT || &Component == &*Components.begin()) &&
8486 "Should be either ConstantArray or VariableArray if not the "
8490 if (CurCounts.empty()) {
8491 const Type *ElementType =
nullptr;
8493 ElementType = CAT->getElementType().getTypePtr();
8495 ElementType = VAT->getElementType().getTypePtr();
8496 else if (&Component == &*Components.begin()) {
8503 if (
const auto *PtrType = Ty->
getAs<PointerType>())
8510 "Non-first components should not be raw pointers");
8518 if (&Component != &*Components.begin())
8522 CurCounts.push_back(
8523 llvm::ConstantInt::get(CGF.
Int64Ty, ElementTypeSize));
8528 if (DimSizes.size() < Components.size() - 1) {
8531 llvm::ConstantInt::get(CGF.
Int64Ty, CAT->getZExtSize()));
8533 DimSizes.push_back(CGF.
Builder.CreateIntCast(
8540 auto *DI = DimSizes.begin() + 1;
8542 llvm::Value *DimProd =
8543 llvm::ConstantInt::get(CGF.
CGM.
Int64Ty, ElementTypeSize);
8552 for (
const OMPClauseMappableExprCommon::MappableComponent &Component :
8554 const Expr *AssocExpr = Component.getAssociatedExpression();
8556 if (
const auto *AE = dyn_cast<ArraySubscriptExpr>(AssocExpr)) {
8557 llvm::Value *Offset = CGF.
Builder.CreateIntCast(
8560 CurOffsets.push_back(Offset);
8561 CurCounts.push_back(llvm::ConstantInt::get(CGF.
Int64Ty, 1));
8562 CurStrides.push_back(CurStrides.back());
8566 const auto *OASE = dyn_cast<ArraySectionExpr>(AssocExpr);
8572 const Expr *OffsetExpr = OASE->getLowerBound();
8573 llvm::Value *Offset =
nullptr;
8576 Offset = llvm::ConstantInt::get(CGF.
Int64Ty, 0);
8584 const Expr *CountExpr = OASE->getLength();
8585 llvm::Value *Count =
nullptr;
8591 if (!OASE->getColonLocFirst().isValid() &&
8592 !OASE->getColonLocSecond().isValid()) {
8593 Count = llvm::ConstantInt::get(CGF.
Int64Ty, 1);
8599 const Expr *StrideExpr = OASE->getStride();
8600 llvm::Value *Stride =
8606 Count = CGF.
Builder.CreateUDiv(
8607 CGF.
Builder.CreateNUWSub(*DI, Offset), Stride);
8609 Count = CGF.
Builder.CreateNUWSub(*DI, Offset);
8615 CurCounts.push_back(Count);
8625 const Expr *StrideExpr = OASE->getStride();
8626 llvm::Value *Stride =
8631 DimProd = CGF.
Builder.CreateNUWMul(DimProd, *(DI - 1));
8633 CurStrides.push_back(CGF.
Builder.CreateNUWMul(DimProd, Stride));
8635 CurStrides.push_back(DimProd);
8637 Offset = CGF.
Builder.CreateNUWMul(DimProd, Offset);
8638 CurOffsets.push_back(Offset);
8640 if (DI != DimSizes.end())
8644 CombinedInfo.NonContigInfo.Offsets.push_back(CurOffsets);
8645 CombinedInfo.NonContigInfo.Counts.push_back(CurCounts);
8646 CombinedInfo.NonContigInfo.Strides.push_back(CurStrides);
8652 OpenMPOffloadMappingFlags
8653 getMapModifiersForPrivateClauses(
const CapturedStmt::Capture &Cap)
const {
8661 return OpenMPOffloadMappingFlags::OMP_MAP_TO |
8662 OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ;
8663 return OpenMPOffloadMappingFlags::OMP_MAP_PRIVATE |
8664 OpenMPOffloadMappingFlags::OMP_MAP_TO;
8667 if (I != LambdasMap.end())
8669 return getMapTypeBits(
8670 I->getSecond()->getMapType(), I->getSecond()->getMapTypeModifiers(),
8671 {}, I->getSecond()->isImplicit(),
8675 return OpenMPOffloadMappingFlags::OMP_MAP_TO |
8676 OpenMPOffloadMappingFlags::OMP_MAP_FROM;
8679 void getPlainLayout(
const CXXRecordDecl *RD,
8680 llvm::SmallVectorImpl<const FieldDecl *> &Layout,
8681 bool AsBase)
const {
8684 llvm::StructType *St =
8687 unsigned NumElements = St->getNumElements();
8689 llvm::PointerUnion<const CXXRecordDecl *, const FieldDecl *>, 4>
8690 RecordLayout(NumElements);
8693 for (
const auto &I : RD->
bases()) {
8697 QualType BaseTy = I.getType();
8708 RecordLayout[FieldIndex] =
Base;
8711 for (
const auto &I : RD->
vbases()) {
8712 QualType BaseTy = I.getType();
8719 if (RecordLayout[FieldIndex])
8721 RecordLayout[FieldIndex] =
Base;
8724 assert(!RD->
isUnion() &&
"Unexpected union.");
8725 for (
const auto *Field : RD->
fields()) {
8728 if (!
Field->isBitField() &&
8731 RecordLayout[FieldIndex] =
Field;
8734 for (
const llvm::PointerUnion<const CXXRecordDecl *, const FieldDecl *>
8735 &
Data : RecordLayout) {
8738 if (
const auto *Base = dyn_cast<const CXXRecordDecl *>(
Data))
8739 getPlainLayout(Base, Layout,
true);
8746 static Address getAttachPtrAddr(
const Expr *PointerExpr,
8747 CodeGenFunction &CGF) {
8748 assert(PointerExpr &&
"Cannot get addr from null attach-ptr expr");
8751 if (
auto *DRE = dyn_cast<DeclRefExpr>(PointerExpr)) {
8754 }
else if (
auto *OASE = dyn_cast<ArraySectionExpr>(PointerExpr)) {
8757 }
else if (
auto *ASE = dyn_cast<ArraySubscriptExpr>(PointerExpr)) {
8759 }
else if (
auto *ME = dyn_cast<MemberExpr>(PointerExpr)) {
8761 }
else if (
auto *UO = dyn_cast<UnaryOperator>(PointerExpr)) {
8762 assert(UO->getOpcode() == UO_Deref &&
8763 "Unexpected unary-operator on attach-ptr-expr");
8766 assert(AttachPtrAddr.
isValid() &&
8767 "Failed to get address for attach pointer expression");
8768 return AttachPtrAddr;
8775 static std::pair<Address, Address>
8776 getAttachPtrAddrAndPteeBaseAddr(
const Expr *AttachPtrExpr,
8777 CodeGenFunction &CGF) {
8782 Address AttachPtrAddr = getAttachPtrAddr(AttachPtrExpr, CGF);
8783 assert(AttachPtrAddr.
isValid() &&
"Invalid attach pointer addr");
8785 QualType AttachPtrType =
8790 AttachPtrAddr, AttachPtrType->
castAs<PointerType>());
8791 assert(AttachPteeBaseAddr.
isValid() &&
"Invalid attach pointee base addr");
8793 return {AttachPtrAddr, AttachPteeBaseAddr};
8799 shouldEmitAttachEntry(
const Expr *PointerExpr,
const ValueDecl *MapBaseDecl,
8800 CodeGenFunction &CGF,
8801 llvm::PointerUnion<
const OMPExecutableDirective *,
8802 const OMPDeclareMapperDecl *>
8812 ->getDirectiveKind());
8821 void collectAttachPtrExprInfo(
8823 llvm::PointerUnion<
const OMPExecutableDirective *,
8824 const OMPDeclareMapperDecl *>
8829 ? OMPD_declare_mapper
8832 const auto &[AttachPtrExpr, Depth] =
8836 AttachPtrComputationOrderMap.try_emplace(
8837 AttachPtrExpr, AttachPtrComputationOrderMap.size());
8838 AttachPtrComponentDepthMap.try_emplace(AttachPtrExpr, Depth);
8839 AttachPtrExprMap.try_emplace(Components, AttachPtrExpr);
8847 void generateAllInfoForClauses(
8848 ArrayRef<const OMPClause *> Clauses, MapCombinedInfoTy &CombinedInfo,
8849 llvm::OpenMPIRBuilder &OMPBuilder,
8850 const llvm::DenseSet<CanonicalDeclPtr<const Decl>> &SkipVarSet =
8851 llvm::DenseSet<CanonicalDeclPtr<const Decl>>())
const {
8856 llvm::MapVector<CanonicalDeclPtr<const Decl>,
8857 SmallVector<SmallVector<MapInfo, 8>, 4>>
8863 [&Info, &SkipVarSet](
8864 const ValueDecl *D, MapKind
Kind,
8867 ArrayRef<OpenMPMapModifierKind> MapModifiers,
8868 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
8869 bool ReturnDevicePointer,
bool IsImplicit,
const ValueDecl *Mapper,
8870 const Expr *VarRef =
nullptr,
bool ForDeviceAddr =
false) {
8871 if (SkipVarSet.contains(D))
8873 auto It = Info.try_emplace(D, Total).first;
8874 It->second[
Kind].emplace_back(
8875 L, MapType, MapModifiers, MotionModifiers, ReturnDevicePointer,
8876 IsImplicit, Mapper, VarRef, ForDeviceAddr);
8879 for (
const auto *
Cl : Clauses) {
8880 const auto *
C = dyn_cast<OMPMapClause>(
Cl);
8884 if (llvm::is_contained(
C->getMapTypeModifiers(),
8885 OMPC_MAP_MODIFIER_present))
8887 else if (
C->getMapType() == OMPC_MAP_alloc)
8889 const auto *EI =
C->getVarRefs().begin();
8890 for (
const auto L :
C->component_lists()) {
8891 const Expr *E = (
C->getMapLoc().isValid()) ? *EI :
nullptr;
8892 InfoGen(std::get<0>(L), Kind, std::get<1>(L),
C->getMapType(),
8893 C->getMapTypeModifiers(), {},
8894 false,
C->isImplicit(), std::get<2>(L),
8899 for (
const auto *
Cl : Clauses) {
8900 const auto *
C = dyn_cast<OMPToClause>(
Cl);
8904 if (llvm::is_contained(
C->getMotionModifiers(),
8905 OMPC_MOTION_MODIFIER_present))
8907 if (llvm::is_contained(
C->getMotionModifiers(),
8908 OMPC_MOTION_MODIFIER_iterator)) {
8909 if (
auto *IteratorExpr = dyn_cast<OMPIteratorExpr>(
8910 C->getIteratorModifier()->IgnoreParenImpCasts())) {
8911 const auto *VD =
cast<VarDecl>(IteratorExpr->getIteratorDecl(0));
8916 const auto *EI =
C->getVarRefs().begin();
8917 for (
const auto L :
C->component_lists()) {
8918 InfoGen(std::get<0>(L), Kind, std::get<1>(L), OMPC_MAP_to, {},
8919 C->getMotionModifiers(),
false,
8920 C->isImplicit(), std::get<2>(L), *EI);
8924 for (
const auto *
Cl : Clauses) {
8925 const auto *
C = dyn_cast<OMPFromClause>(
Cl);
8929 if (llvm::is_contained(
C->getMotionModifiers(),
8930 OMPC_MOTION_MODIFIER_present))
8932 if (llvm::is_contained(
C->getMotionModifiers(),
8933 OMPC_MOTION_MODIFIER_iterator)) {
8934 if (
auto *IteratorExpr = dyn_cast<OMPIteratorExpr>(
8935 C->getIteratorModifier()->IgnoreParenImpCasts())) {
8936 const auto *VD =
cast<VarDecl>(IteratorExpr->getIteratorDecl(0));
8941 const auto *EI =
C->getVarRefs().begin();
8942 for (
const auto L :
C->component_lists()) {
8943 InfoGen(std::get<0>(L), Kind, std::get<1>(L), OMPC_MAP_from, {},
8944 C->getMotionModifiers(),
8945 false,
C->isImplicit(), std::get<2>(L),
8958 MapCombinedInfoTy UseDeviceDataCombinedInfo;
8960 auto &&UseDeviceDataCombinedInfoGen =
8961 [&UseDeviceDataCombinedInfo](
const ValueDecl *VD, llvm::Value *Ptr,
8962 CodeGenFunction &CGF,
bool IsDevAddr,
8963 bool HasUdpFbNullify =
false) {
8964 UseDeviceDataCombinedInfo.Exprs.push_back(VD);
8965 UseDeviceDataCombinedInfo.BasePointers.emplace_back(Ptr);
8966 UseDeviceDataCombinedInfo.DevicePtrDecls.emplace_back(VD);
8967 UseDeviceDataCombinedInfo.DevicePointers.emplace_back(
8968 IsDevAddr ? DeviceInfoTy::Address : DeviceInfoTy::Pointer);
8974 UseDeviceDataCombinedInfo.Pointers.push_back(Ptr);
8975 UseDeviceDataCombinedInfo.Sizes.push_back(
8976 llvm::Constant::getNullValue(CGF.Int64Ty));
8977 OpenMPOffloadMappingFlags Flags =
8978 OpenMPOffloadMappingFlags::OMP_MAP_RETURN_PARAM;
8979 if (HasUdpFbNullify)
8980 Flags |= OpenMPOffloadMappingFlags::OMP_MAP_FB_NULLIFY;
8981 UseDeviceDataCombinedInfo.Types.push_back(Flags);
8982 UseDeviceDataCombinedInfo.Mappers.push_back(
nullptr);
8986 [&UseDeviceDataCombinedInfoGen](
8987 CodeGenFunction &CGF,
const Expr *IE,
const ValueDecl *VD,
8990 bool IsDevAddr,
bool IEIsAttachPtrForDevAddr =
false,
8991 bool HasUdpFbNullify =
false) {
8995 if (IsDevAddr && !IEIsAttachPtrForDevAddr) {
8996 if (IE->isGLValue())
9003 bool TreatDevAddrAsDevPtr = IEIsAttachPtrForDevAddr;
9010 UseDeviceDataCombinedInfoGen(VD, Ptr, CGF, IsDevAddr &&
9011 !TreatDevAddrAsDevPtr,
9015 auto &&IsMapInfoExist =
9016 [&Info,
this](CodeGenFunction &CGF,
const ValueDecl *VD,
const Expr *IE,
9017 const Expr *DesiredAttachPtrExpr,
bool IsDevAddr,
9018 bool HasUdpFbNullify =
false) ->
bool {
9026 if (It != Info.end()) {
9028 for (
auto &
Data : It->second) {
9029 MapInfo *CI =
nullptr;
9033 auto *It = llvm::find_if(
Data, [&](
const MapInfo &MI) {
9034 if (MI.Components.back().getAssociatedDeclaration() != VD)
9037 const Expr *MapAttachPtr = getAttachPtrExpr(MI.Components);
9038 bool Match = AttachPtrComparator.areEqual(MapAttachPtr,
9039 DesiredAttachPtrExpr);
9043 if (It !=
Data.end())
9048 CI->ForDeviceAddr =
true;
9049 CI->ReturnDevicePointer =
true;
9050 CI->HasUdpFbNullify = HasUdpFbNullify;
9054 auto PrevCI = std::next(CI->Components.rbegin());
9055 const auto *VarD = dyn_cast<VarDecl>(VD);
9056 const Expr *AttachPtrExpr = getAttachPtrExpr(CI->Components);
9057 if (CGF.CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory() ||
9059 !VD->getType().getNonReferenceType()->isPointerType() ||
9060 PrevCI == CI->Components.rend() ||
9062 VarD->hasLocalStorage() ||
9063 (isa_and_nonnull<DeclRefExpr>(AttachPtrExpr) &&
9065 CI->ForDeviceAddr = IsDevAddr;
9066 CI->ReturnDevicePointer =
true;
9067 CI->HasUdpFbNullify = HasUdpFbNullify;
9085 for (
const auto *
Cl : Clauses) {
9086 const auto *
C = dyn_cast<OMPUseDevicePtrClause>(
Cl);
9089 bool HasUdpFbNullify =
9090 C->getFallbackModifier() == OMPC_USE_DEVICE_PTR_FALLBACK_fb_nullify;
9091 for (
const auto L :
C->component_lists()) {
9094 assert(!Components.empty() &&
9095 "Not expecting empty list of components!");
9096 const ValueDecl *VD = Components.back().getAssociatedDeclaration();
9098 const Expr *IE = Components.back().getAssociatedExpression();
9106 const Expr *UDPOperandExpr =
9107 Components.front().getAssociatedExpression();
9108 if (IsMapInfoExist(CGF, VD, IE,
9110 false, HasUdpFbNullify))
9112 MapInfoGen(CGF, IE, VD, Components,
false,
9113 false, HasUdpFbNullify);
9117 llvm::SmallDenseSet<CanonicalDeclPtr<const Decl>, 4> Processed;
9118 for (
const auto *
Cl : Clauses) {
9119 const auto *
C = dyn_cast<OMPUseDeviceAddrClause>(
Cl);
9122 for (
const auto L :
C->component_lists()) {
9125 assert(!std::get<1>(L).empty() &&
9126 "Not expecting empty list of components!");
9127 const ValueDecl *VD = std::get<1>(L).back().getAssociatedDeclaration();
9128 if (!Processed.insert(VD).second)
9149 const Expr *UDAAttachPtrExpr = getAttachPtrExpr(Components);
9150 const Expr *IE = std::get<1>(L).back().getAssociatedExpression();
9151 assert((!UDAAttachPtrExpr || UDAAttachPtrExpr == IE) &&
9152 "use_device_addr operand has an attach-ptr, but does not match "
9153 "last component's expr.");
9154 if (IsMapInfoExist(CGF, VD, IE,
9158 MapInfoGen(CGF, IE, VD, Components,
9160 UDAAttachPtrExpr !=
nullptr);
9164 for (
const auto &
Data : Info) {
9165 MapCombinedInfoTy CurInfo;
9167 const ValueDecl *VD = cast_or_null<ValueDecl>(D);
9174 SmallVector<std::pair<const Expr *, MapInfo>, 16> AttachPtrMapInfoPairs;
9177 for (
const auto &M :
Data.second) {
9178 for (
const MapInfo &L : M) {
9179 assert(!L.Components.empty() &&
9180 "Not expecting declaration with no component lists.");
9182 const Expr *AttachPtrExpr = getAttachPtrExpr(L.Components);
9183 AttachPtrMapInfoPairs.emplace_back(AttachPtrExpr, L);
9188 llvm::stable_sort(AttachPtrMapInfoPairs,
9189 [
this](
const auto &LHS,
const auto &RHS) {
9190 return AttachPtrComparator(LHS.first, RHS.first);
9195 auto *It = AttachPtrMapInfoPairs.begin();
9196 while (It != AttachPtrMapInfoPairs.end()) {
9197 const Expr *AttachPtrExpr = It->first;
9199 SmallVector<MapInfo, 8> GroupLists;
9200 while (It != AttachPtrMapInfoPairs.end() &&
9201 (It->first == AttachPtrExpr ||
9202 AttachPtrComparator.areEqual(It->first, AttachPtrExpr))) {
9203 GroupLists.push_back(It->second);
9206 assert(!GroupLists.empty() &&
"GroupLists should not be empty");
9208 StructRangeInfoTy PartialStruct;
9209 AttachInfoTy AttachInfo;
9210 MapCombinedInfoTy GroupCurInfo;
9212 MapCombinedInfoTy GroupStructBaseCurInfo;
9213 for (
const MapInfo &L : GroupLists) {
9215 unsigned CurrentBasePointersIdx = GroupCurInfo.BasePointers.size();
9216 unsigned StructBasePointersIdx =
9217 GroupStructBaseCurInfo.BasePointers.size();
9219 GroupCurInfo.NonContigInfo.IsNonContiguous =
9220 L.Components.back().isNonContiguous();
9221 generateInfoForComponentList(
9222 L.MapType, L.MapModifiers, L.MotionModifiers, L.Components,
9223 GroupCurInfo, GroupStructBaseCurInfo, PartialStruct, AttachInfo,
9224 false, L.IsImplicit,
9225 true, L.Mapper, L.ForDeviceAddr, VD,
9230 if (L.ReturnDevicePointer) {
9234 assert((CurrentBasePointersIdx < GroupCurInfo.BasePointers.size() ||
9235 StructBasePointersIdx <
9236 GroupStructBaseCurInfo.BasePointers.size()) &&
9237 "Unexpected number of mapped base pointers.");
9240 const ValueDecl *RelevantVD =
9241 L.Components.back().getAssociatedDeclaration();
9242 assert(RelevantVD &&
9243 "No relevant declaration related with device pointer??");
9250 auto SetDevicePointerInfo = [&](MapCombinedInfoTy &Info,
9252 Info.DevicePtrDecls[Idx] = RelevantVD;
9253 Info.DevicePointers[Idx] = L.ForDeviceAddr
9254 ? DeviceInfoTy::Address
9255 : DeviceInfoTy::Pointer;
9257 OpenMPOffloadMappingFlags::OMP_MAP_RETURN_PARAM;
9258 if (L.HasUdpFbNullify)
9260 OpenMPOffloadMappingFlags::OMP_MAP_FB_NULLIFY;
9263 if (StructBasePointersIdx <
9264 GroupStructBaseCurInfo.BasePointers.size())
9265 SetDevicePointerInfo(GroupStructBaseCurInfo,
9266 StructBasePointersIdx);
9268 SetDevicePointerInfo(GroupCurInfo, CurrentBasePointersIdx);
9274 MapCombinedInfoTy GroupUnionCurInfo;
9275 GroupUnionCurInfo.append(GroupStructBaseCurInfo);
9276 GroupUnionCurInfo.append(GroupCurInfo);
9280 if (PartialStruct.Base.isValid()) {
9288 GroupUnionCurInfo.NonContigInfo.Dims.insert(
9289 GroupUnionCurInfo.NonContigInfo.Dims.begin(), 1);
9291 CurInfo, GroupUnionCurInfo.Types, PartialStruct, AttachInfo,
9292 !VD, OMPBuilder, VD,
9293 CombinedInfo.BasePointers.size(),
9299 CurInfo.append(GroupUnionCurInfo);
9300 if (AttachInfo.isValid())
9301 emitAttachEntry(CGF, CurInfo, AttachInfo);
9305 CombinedInfo.append(CurInfo);
9308 CombinedInfo.append(UseDeviceDataCombinedInfo);
9312 MappableExprsHandler(
const OMPExecutableDirective &Dir, CodeGenFunction &CGF)
9313 : CurDir(&Dir), CGF(CGF), AttachPtrComparator(*this) {
9315 for (
const auto *
C : Dir.getClausesOfKind<OMPFirstprivateClause>())
9316 for (
const auto *D :
C->varlist())
9317 FirstPrivateDecls.try_emplace(
9320 for (
const auto *
C : Dir.getClausesOfKind<OMPUsesAllocatorsClause>()) {
9321 for (unsigned I = 0, E = C->getNumberOfAllocators(); I < E; ++I) {
9322 OMPUsesAllocatorsClause::Data D = C->getAllocatorData(I);
9323 if (const auto *DRE = dyn_cast_or_null<DeclRefExpr>(D.AllocatorTraits))
9324 FirstPrivateDecls.try_emplace(cast<VarDecl>(DRE->getDecl()),
9326 else if (const auto *VD = dyn_cast<VarDecl>(
9327 cast<DeclRefExpr>(D.Allocator->IgnoreParenImpCasts())
9329 FirstPrivateDecls.try_emplace(VD, true);
9333 for (
const auto *
C : Dir.getClausesOfKind<OMPDefaultmapClause>())
9334 if (
C->getDefaultmapModifier() == OMPC_DEFAULTMAP_MODIFIER_firstprivate)
9335 DefaultmapFirstprivateKinds.insert(
C->getDefaultmapKind());
9337 for (
const auto *
C : Dir.getClausesOfKind<OMPIsDevicePtrClause>())
9338 for (
auto L :
C->component_lists())
9339 DevPointersMap[std::get<0>(L)].push_back(std::get<1>(L));
9341 for (
const auto *
C : Dir.getClausesOfKind<OMPHasDeviceAddrClause>())
9342 for (
auto L :
C->component_lists())
9343 HasDevAddrsMap[std::get<0>(L)].push_back(std::get<1>(L));
9345 for (
const auto *
C : Dir.getClausesOfKind<OMPMapClause>()) {
9346 if (C->getMapType() != OMPC_MAP_to)
9348 for (auto L : C->component_lists()) {
9349 const ValueDecl *VD = std::get<0>(L);
9350 const auto *RD = VD ? VD->getType()
9352 .getNonReferenceType()
9353 ->getAsCXXRecordDecl()
9355 if (RD && RD->isLambda())
9356 LambdasMap.try_emplace(std::get<0>(L), C);
9360 auto CollectAttachPtrExprsForClauseComponents = [
this](
const auto *
C) {
9361 for (
auto L :
C->component_lists()) {
9364 if (!Components.empty())
9365 collectAttachPtrExprInfo(Components, CurDir);
9371 for (
const auto *
C : Dir.getClausesOfKind<OMPMapClause>())
9372 CollectAttachPtrExprsForClauseComponents(
C);
9373 for (
const auto *
C : Dir.getClausesOfKind<OMPToClause>())
9374 CollectAttachPtrExprsForClauseComponents(
C);
9375 for (
const auto *
C : Dir.getClausesOfKind<OMPFromClause>())
9376 CollectAttachPtrExprsForClauseComponents(
C);
9377 for (
const auto *
C : Dir.getClausesOfKind<OMPUseDevicePtrClause>())
9378 CollectAttachPtrExprsForClauseComponents(
C);
9379 for (
const auto *
C : Dir.getClausesOfKind<OMPUseDeviceAddrClause>())
9380 CollectAttachPtrExprsForClauseComponents(
C);
9381 for (
const auto *
C : Dir.getClausesOfKind<OMPIsDevicePtrClause>())
9382 CollectAttachPtrExprsForClauseComponents(
C);
9383 for (
const auto *
C : Dir.getClausesOfKind<OMPHasDeviceAddrClause>())
9384 CollectAttachPtrExprsForClauseComponents(
C);
9388 MappableExprsHandler(
const OMPDeclareMapperDecl &Dir,
CodeGenFunction &CGF)
9389 : CurDir(&Dir), CGF(CGF), AttachPtrComparator(*this) {}
9399 void emitCombinedEntry(MapCombinedInfoTy &CombinedInfo,
9400 MapFlagsArrayTy &CurTypes,
9401 const StructRangeInfoTy &PartialStruct,
9402 AttachInfoTy &AttachInfo,
bool IsMapThis,
9403 llvm::OpenMPIRBuilder &OMPBuilder,
const ValueDecl *VD,
9404 unsigned OffsetForMemberOfFlag,
9405 bool NotTargetParams)
const {
9406 if (CurTypes.size() == 1 &&
9407 ((CurTypes.back() & OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF) !=
9408 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF) &&
9409 !PartialStruct.IsArraySection)
9411 Address LBAddr = PartialStruct.LowestElem.second;
9412 Address HBAddr = PartialStruct.HighestElem.second;
9413 if (PartialStruct.HasCompleteRecord) {
9414 LBAddr = PartialStruct.LB;
9415 HBAddr = PartialStruct.LB;
9417 CombinedInfo.Exprs.push_back(VD);
9419 CombinedInfo.BasePointers.push_back(PartialStruct.Base.emitRawPointer(CGF));
9420 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
9421 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
9424 const CXXMethodDecl *MD =
9426 const CXXRecordDecl *RD = MD ? MD->
getParent() :
nullptr;
9427 bool HasBaseClass = RD && IsMapThis ? RD->
getNumBases() > 0 :
false;
9437 CombinedInfo.Pointers.push_back(PartialStruct.Base.emitRawPointer(CGF));
9442 CombinedInfo.Sizes.push_back(Size);
9444 CombinedInfo.Pointers.push_back(LB);
9447 llvm::Value *HAddr = CGF.
Builder.CreateConstGEP1_32(
9451 llvm::Value *Diff = CGF.
Builder.CreatePtrDiff(CHAddr, CLAddr);
9454 CombinedInfo.Sizes.push_back(Size);
9456 CombinedInfo.Mappers.push_back(
nullptr);
9458 CombinedInfo.Types.push_back(
9459 NotTargetParams ? OpenMPOffloadMappingFlags::OMP_MAP_NONE
9460 : !PartialStruct.PreliminaryMapData.BasePointers.empty()
9461 ? OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ
9462 : OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM);
9465 if (CurTypes.end() !=
9466 llvm::find_if(CurTypes, [](OpenMPOffloadMappingFlags
Type) {
9467 return static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>>(
9468 Type & OpenMPOffloadMappingFlags::OMP_MAP_PRESENT);
9470 CombinedInfo.Types.back() |= OpenMPOffloadMappingFlags::OMP_MAP_PRESENT;
9472 (*CurTypes.begin()) &= ~OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM;
9479 if (CurTypes.end() !=
9480 llvm::find_if(CurTypes, [](OpenMPOffloadMappingFlags
Type) {
9481 return static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>>(
9482 Type & OpenMPOffloadMappingFlags::OMP_MAP_OMPX_HOLD);
9484 CombinedInfo.Types.back() |= OpenMPOffloadMappingFlags::OMP_MAP_OMPX_HOLD;
9485 for (
auto &M : CurTypes)
9486 M |= OpenMPOffloadMappingFlags::OMP_MAP_OMPX_HOLD;
9493 OpenMPOffloadMappingFlags MemberOfFlag = OMPBuilder.getMemberOfFlag(
9494 OffsetForMemberOfFlag + CombinedInfo.BasePointers.size() - 1);
9495 for (
auto &M : CurTypes)
9496 OMPBuilder.setCorrectMemberOfFlag(M, MemberOfFlag);
9513 if (AttachInfo.isValid())
9514 AttachInfo.AttachPteeAddr = LBAddr;
9522 void generateAllInfo(
9523 MapCombinedInfoTy &CombinedInfo, llvm::OpenMPIRBuilder &OMPBuilder,
9524 const llvm::DenseSet<CanonicalDeclPtr<const Decl>> &SkipVarSet =
9525 llvm::DenseSet<CanonicalDeclPtr<const Decl>>())
const {
9527 "Expect a executable directive");
9529 generateAllInfoForClauses(CurExecDir->clauses(), CombinedInfo, OMPBuilder,
9536 void generateAllInfoForMapper(MapCombinedInfoTy &CombinedInfo,
9537 llvm::OpenMPIRBuilder &OMPBuilder)
const {
9539 "Expect a declare mapper directive");
9541 generateAllInfoForClauses(CurMapperDir->clauses(), CombinedInfo,
9546 void generateInfoForLambdaCaptures(
9547 const ValueDecl *VD, llvm::Value *Arg, MapCombinedInfoTy &CombinedInfo,
9548 llvm::DenseMap<llvm::Value *, llvm::Value *> &LambdaPointers)
const {
9556 llvm::DenseMap<const ValueDecl *, FieldDecl *> Captures;
9557 FieldDecl *ThisCapture =
nullptr;
9563 LambdaPointers.try_emplace(ThisLVal.getPointer(CGF),
9564 VDLVal.getPointer(CGF));
9565 CombinedInfo.Exprs.push_back(VD);
9566 CombinedInfo.BasePointers.push_back(ThisLVal.getPointer(CGF));
9567 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
9568 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
9569 CombinedInfo.Pointers.push_back(ThisLValVal.getPointer(CGF));
9570 CombinedInfo.Sizes.push_back(
9573 CombinedInfo.Types.push_back(
9574 OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ |
9575 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL |
9576 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF |
9577 OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT);
9578 CombinedInfo.Mappers.push_back(
nullptr);
9580 for (
const LambdaCapture &LC : RD->
captures()) {
9581 if (!LC.capturesVariable())
9586 auto It = Captures.find(VD);
9587 assert(It != Captures.end() &&
"Found lambda capture without field.");
9591 LambdaPointers.try_emplace(VarLVal.getPointer(CGF),
9592 VDLVal.getPointer(CGF));
9593 CombinedInfo.Exprs.push_back(VD);
9594 CombinedInfo.BasePointers.push_back(VarLVal.getPointer(CGF));
9595 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
9596 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
9597 CombinedInfo.Pointers.push_back(VarLValVal.getPointer(CGF));
9598 CombinedInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
9604 LambdaPointers.try_emplace(VarLVal.getPointer(CGF),
9605 VDLVal.getPointer(CGF));
9606 CombinedInfo.Exprs.push_back(VD);
9607 CombinedInfo.BasePointers.push_back(VarLVal.getPointer(CGF));
9608 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
9609 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
9610 CombinedInfo.Pointers.push_back(VarRVal.
getScalarVal());
9611 CombinedInfo.Sizes.push_back(llvm::ConstantInt::get(CGF.
Int64Ty, 0));
9613 CombinedInfo.Types.push_back(
9614 OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ |
9615 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL |
9616 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF |
9617 OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT);
9618 CombinedInfo.Mappers.push_back(
nullptr);
9623 void adjustMemberOfForLambdaCaptures(
9624 llvm::OpenMPIRBuilder &OMPBuilder,
9625 const llvm::DenseMap<llvm::Value *, llvm::Value *> &LambdaPointers,
9626 MapBaseValuesArrayTy &BasePointers, MapValuesArrayTy &Pointers,
9627 MapFlagsArrayTy &Types)
const {
9628 for (
unsigned I = 0, E = Types.size(); I < E; ++I) {
9630 if (Types[I] != (OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ |
9631 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL |
9632 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF |
9633 OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT))
9635 llvm::Value *BasePtr = LambdaPointers.lookup(BasePointers[I]);
9636 assert(BasePtr &&
"Unable to find base lambda address.");
9638 for (
unsigned J = I; J > 0; --J) {
9639 unsigned Idx = J - 1;
9640 if (Pointers[Idx] != BasePtr)
9645 assert(TgtIdx != -1 &&
"Unable to find parent lambda.");
9649 OpenMPOffloadMappingFlags MemberOfFlag =
9650 OMPBuilder.getMemberOfFlag(TgtIdx);
9651 OMPBuilder.setCorrectMemberOfFlag(Types[I], MemberOfFlag);
9657 void populateComponentListsForNonLambdaCaptureFromClauses(
9658 const ValueDecl *VD, MapDataArrayTy &DeclComponentLists,
9660 SmallVector<OMPClauseMappableExprCommon::MappableComponent, 8>>
9661 &StorageForImplicitlyAddedComponentLists)
const {
9662 if (VD && LambdasMap.count(VD))
9668 auto It = DevPointersMap.find(VD);
9669 if (It != DevPointersMap.end())
9670 for (
const auto &MCL : It->second)
9671 DeclComponentLists.emplace_back(MCL, OMPC_MAP_to,
Unknown,
9674 auto I = HasDevAddrsMap.find(VD);
9675 if (I != HasDevAddrsMap.end())
9676 for (
const auto &MCL : I->second)
9677 DeclComponentLists.emplace_back(MCL, OMPC_MAP_tofrom,
Unknown,
9681 "Expect a executable directive");
9683 for (
const auto *
C : CurExecDir->getClausesOfKind<OMPMapClause>()) {
9684 const auto *EI =
C->getVarRefs().begin();
9685 for (
const auto L :
C->decl_component_lists(VD)) {
9686 const ValueDecl *VDecl, *Mapper;
9688 const Expr *E = (
C->getMapLoc().isValid()) ? *EI :
nullptr;
9690 std::tie(VDecl, Components, Mapper) = L;
9691 assert(VDecl == VD &&
"We got information for the wrong declaration??");
9692 assert(!Components.empty() &&
9693 "Not expecting declaration with no component lists.");
9694 DeclComponentLists.emplace_back(Components,
C->getMapType(),
9695 C->getMapTypeModifiers(),
9696 C->isImplicit(), Mapper, E);
9705 addImplicitMapForAttachPtrBaseIfMemberOfCapturedVD(
9706 VD, DeclComponentLists, StorageForImplicitlyAddedComponentLists);
9708 llvm::stable_sort(DeclComponentLists, [](
const MapData &LHS,
9709 const MapData &RHS) {
9710 ArrayRef<OpenMPMapModifierKind> MapModifiers = std::get<2>(LHS);
9713 llvm::is_contained(MapModifiers, clang::OMPC_MAP_MODIFIER_present);
9714 bool HasAllocs = MapType == OMPC_MAP_alloc;
9715 MapModifiers = std::get<2>(RHS);
9716 MapType = std::get<1>(LHS);
9718 llvm::is_contained(MapModifiers, clang::OMPC_MAP_MODIFIER_present);
9719 bool HasAllocsR = MapType == OMPC_MAP_alloc;
9720 return (HasPresent && !HasPresentR) || (HasAllocs && !HasAllocsR);
9756 void addImplicitMapForAttachPtrBaseIfMemberOfCapturedVD(
9757 const ValueDecl *CapturedVD, MapDataArrayTy &DeclComponentLists,
9759 SmallVector<OMPClauseMappableExprCommon::MappableComponent, 8>>
9760 &ComponentVectorStorage)
const {
9761 bool IsThisCapture = CapturedVD ==
nullptr;
9763 for (
const auto &ComponentsAndAttachPtr : AttachPtrExprMap) {
9765 ComponentsWithAttachPtr = ComponentsAndAttachPtr.first;
9766 const Expr *AttachPtrExpr = ComponentsAndAttachPtr.second;
9770 const auto *ME = dyn_cast<MemberExpr>(AttachPtrExpr);
9774 const Expr *
Base = ME->getBase()->IgnoreParenImpCasts();
9795 bool FoundExistingMap =
false;
9796 for (
const MapData &ExistingL : DeclComponentLists) {
9798 ExistingComponents = std::get<0>(ExistingL);
9800 if (ExistingComponents.empty())
9804 const auto &FirstComponent = ExistingComponents.front();
9805 const Expr *FirstExpr = FirstComponent.getAssociatedExpression();
9811 if (AttachPtrComparator.areEqual(FirstExpr, AttachPtrExpr)) {
9812 FoundExistingMap =
true;
9817 if (IsThisCapture) {
9818 if (
const auto *OASE = dyn_cast<ArraySectionExpr>(FirstExpr)) {
9820 FoundExistingMap =
true;
9829 if (
const auto *DRE = dyn_cast<DeclRefExpr>(FirstExpr)) {
9830 if (DRE->getDecl() == CapturedVD) {
9831 FoundExistingMap =
true;
9837 if (FoundExistingMap)
9843 ComponentVectorStorage.emplace_back();
9844 auto &AttachPtrComponents = ComponentVectorStorage.back();
9847 bool SeenAttachPtrComponent =
false;
9853 for (
size_t i = 0; i < ComponentsWithAttachPtr.size(); ++i) {
9854 const auto &Component = ComponentsWithAttachPtr[i];
9855 const Expr *ComponentExpr = Component.getAssociatedExpression();
9857 if (!SeenAttachPtrComponent && ComponentExpr != AttachPtrExpr)
9859 SeenAttachPtrComponent =
true;
9861 AttachPtrComponents.emplace_back(Component.getAssociatedExpression(),
9862 Component.getAssociatedDeclaration(),
9863 Component.isNonContiguous());
9865 assert(!AttachPtrComponents.empty() &&
9866 "Could not populate component-lists for mapping attach-ptr");
9868 DeclComponentLists.emplace_back(
9869 AttachPtrComponents, OMPC_MAP_tofrom,
Unknown,
9870 true,
nullptr, AttachPtrExpr);
9877 void generateInfoForCaptureFromClauseInfo(
9878 const MapDataArrayTy &DeclComponentListsFromClauses,
9879 const CapturedStmt::Capture *Cap, llvm::Value *Arg,
9880 MapCombinedInfoTy &CurCaptureVarInfo, llvm::OpenMPIRBuilder &OMPBuilder,
9881 unsigned OffsetForMemberOfFlag)
const {
9883 "Not expecting to generate map info for a variable array type!");
9892 if (LambdasMap.count(VD))
9898 if (VD && (DevPointersMap.count(VD) || HasDevAddrsMap.count(VD))) {
9899 CurCaptureVarInfo.Exprs.push_back(VD);
9900 CurCaptureVarInfo.BasePointers.emplace_back(Arg);
9901 CurCaptureVarInfo.DevicePtrDecls.emplace_back(VD);
9902 CurCaptureVarInfo.DevicePointers.emplace_back(DeviceInfoTy::Pointer);
9903 CurCaptureVarInfo.Pointers.push_back(Arg);
9904 CurCaptureVarInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
9907 CurCaptureVarInfo.Types.push_back(
9908 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL |
9909 OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM);
9910 CurCaptureVarInfo.Mappers.push_back(
nullptr);
9914 auto GenerateInfoForComponentLists =
9915 [&](ArrayRef<MapData> DeclComponentListsFromClauses,
9916 bool IsEligibleForTargetParamFlag) {
9917 MapCombinedInfoTy CurInfoForComponentLists;
9918 StructRangeInfoTy PartialStruct;
9919 AttachInfoTy AttachInfo;
9921 if (DeclComponentListsFromClauses.empty())
9924 generateInfoForCaptureFromComponentLists(
9925 VD, DeclComponentListsFromClauses, CurInfoForComponentLists,
9926 PartialStruct, AttachInfo, IsEligibleForTargetParamFlag);
9931 if (PartialStruct.Base.isValid()) {
9932 CurCaptureVarInfo.append(PartialStruct.PreliminaryMapData);
9934 CurCaptureVarInfo, CurInfoForComponentLists.Types,
9935 PartialStruct, AttachInfo, Cap->
capturesThis(), OMPBuilder,
9936 nullptr, OffsetForMemberOfFlag,
9937 !IsEligibleForTargetParamFlag);
9942 CurCaptureVarInfo.append(CurInfoForComponentLists);
9943 if (AttachInfo.isValid())
9944 emitAttachEntry(CGF, CurCaptureVarInfo, AttachInfo);
9968 SmallVector<std::pair<const Expr *, MapData>, 16> AttachPtrMapDataPairs;
9970 for (
const MapData &L : DeclComponentListsFromClauses) {
9973 const Expr *AttachPtrExpr = getAttachPtrExpr(Components);
9974 AttachPtrMapDataPairs.emplace_back(AttachPtrExpr, L);
9978 llvm::stable_sort(AttachPtrMapDataPairs,
9979 [
this](
const auto &LHS,
const auto &RHS) {
9980 return AttachPtrComparator(LHS.first, RHS.first);
9983 bool NoDefaultMappingDoneForVD = CurCaptureVarInfo.BasePointers.empty();
9984 bool IsFirstGroup =
true;
9988 auto *It = AttachPtrMapDataPairs.begin();
9989 while (It != AttachPtrMapDataPairs.end()) {
9990 const Expr *AttachPtrExpr = It->first;
9992 MapDataArrayTy GroupLists;
9993 while (It != AttachPtrMapDataPairs.end() &&
9994 (It->first == AttachPtrExpr ||
9995 AttachPtrComparator.areEqual(It->first, AttachPtrExpr))) {
9996 GroupLists.push_back(It->second);
9999 assert(!GroupLists.empty() &&
"GroupLists should not be empty");
10004 bool IsEligibleForTargetParamFlag =
10005 IsFirstGroup && NoDefaultMappingDoneForVD;
10007 GenerateInfoForComponentLists(GroupLists, IsEligibleForTargetParamFlag);
10008 IsFirstGroup =
false;
10015 void generateInfoForCaptureFromComponentLists(
10016 const ValueDecl *VD, ArrayRef<MapData> DeclComponentLists,
10017 MapCombinedInfoTy &CurComponentListInfo, StructRangeInfoTy &PartialStruct,
10018 AttachInfoTy &AttachInfo,
bool IsListEligibleForTargetParamFlag)
const {
10020 llvm::SmallDenseMap<
10027 for (
const MapData &L : DeclComponentLists) {
10030 ArrayRef<OpenMPMapModifierKind> MapModifiers;
10032 const ValueDecl *Mapper;
10033 const Expr *VarRef;
10034 std::tie(Components, MapType, MapModifiers, IsImplicit, Mapper, VarRef) =
10037 for (
const MapData &L1 : ArrayRef(DeclComponentLists).slice(Count)) {
10039 std::tie(Components1, MapType, MapModifiers, IsImplicit, Mapper,
10041 auto CI = Components.rbegin();
10042 auto CE = Components.rend();
10043 auto SI = Components1.rbegin();
10044 auto SE = Components1.rend();
10045 for (; CI != CE && SI != SE; ++CI, ++SI) {
10046 if (CI->getAssociatedExpression()->getStmtClass() !=
10047 SI->getAssociatedExpression()->getStmtClass())
10050 if (CI->getAssociatedDeclaration() != SI->getAssociatedDeclaration())
10055 if (CI == CE || SI == SE) {
10057 if (CI == CE && SI == SE)
10059 const auto It = (SI == SE) ? CI : SI;
10066 (std::prev(It)->getAssociatedDeclaration() &&
10068 ->getAssociatedDeclaration()
10070 ->isPointerType()) ||
10071 (It->getAssociatedDeclaration() &&
10072 It->getAssociatedDeclaration()->getType()->isPointerType() &&
10073 std::next(It) != CE && std::next(It) != SE))
10075 const MapData &BaseData = CI == CE ? L : L1;
10077 SI == SE ? Components : Components1;
10078 OverlappedData[&BaseData].push_back(SubData);
10083 llvm::SmallVector<const FieldDecl *, 4> Layout;
10084 if (!OverlappedData.empty()) {
10087 while (BaseType != OrigType) {
10093 getPlainLayout(CRD, Layout,
false);
10099 for (
auto &Pair : OverlappedData) {
10106 auto CI = First.rbegin();
10107 auto CE = First.rend();
10108 auto SI = Second.rbegin();
10109 auto SE = Second.rend();
10110 for (; CI != CE && SI != SE; ++CI, ++SI) {
10111 if (CI->getAssociatedExpression()->getStmtClass() !=
10112 SI->getAssociatedExpression()->getStmtClass())
10115 if (CI->getAssociatedDeclaration() !=
10116 SI->getAssociatedDeclaration())
10121 if (CI == CE && SI == SE)
10125 if (CI == CE || SI == SE)
10130 if (FD1->getParent() == FD2->getParent())
10131 return FD1->getFieldIndex() < FD2->getFieldIndex();
10133 llvm::find_if(Layout, [FD1, FD2](
const FieldDecl *FD) {
10134 return FD == FD1 || FD == FD2;
10142 bool AddTargetParamFlag = IsListEligibleForTargetParamFlag;
10143 MapCombinedInfoTy StructBaseCombinedInfo;
10144 for (
const auto &Pair : OverlappedData) {
10145 const MapData &L = *Pair.getFirst();
10148 ArrayRef<OpenMPMapModifierKind> MapModifiers;
10150 const ValueDecl *Mapper;
10151 const Expr *VarRef;
10152 std::tie(Components, MapType, MapModifiers, IsImplicit, Mapper, VarRef) =
10154 ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef>
10155 OverlappedComponents = Pair.getSecond();
10156 generateInfoForComponentList(
10157 MapType, MapModifiers, {}, Components, CurComponentListInfo,
10158 StructBaseCombinedInfo, PartialStruct, AttachInfo, AddTargetParamFlag,
10159 IsImplicit,
false, Mapper,
10160 false, VD, VarRef, OverlappedComponents);
10161 AddTargetParamFlag =
false;
10164 for (
const MapData &L : DeclComponentLists) {
10167 ArrayRef<OpenMPMapModifierKind> MapModifiers;
10169 const ValueDecl *Mapper;
10170 const Expr *VarRef;
10171 std::tie(Components, MapType, MapModifiers, IsImplicit, Mapper, VarRef) =
10173 auto It = OverlappedData.find(&L);
10174 if (It == OverlappedData.end())
10175 generateInfoForComponentList(
10176 MapType, MapModifiers, {}, Components, CurComponentListInfo,
10177 StructBaseCombinedInfo, PartialStruct, AttachInfo,
10178 AddTargetParamFlag, IsImplicit,
false,
10179 Mapper,
false, VD, VarRef,
10181 AddTargetParamFlag =
false;
10187 bool isEffectivelyFirstprivate(
const VarDecl *VD, QualType
Type)
const {
10189 auto I = FirstPrivateDecls.find(VD);
10190 if (I != FirstPrivateDecls.end() && !I->getSecond())
10194 if (DefaultmapFirstprivateKinds.count(OMPC_DEFAULTMAP_scalar)) {
10195 if (
Type->isScalarType())
10200 if (DefaultmapFirstprivateKinds.count(OMPC_DEFAULTMAP_pointer)) {
10201 if (
Type->isAnyPointerType())
10206 if (DefaultmapFirstprivateKinds.count(OMPC_DEFAULTMAP_aggregate)) {
10207 if (
Type->isAggregateType())
10212 return DefaultmapFirstprivateKinds.count(OMPC_DEFAULTMAP_all);
10217 void generateDefaultMapInfo(
const CapturedStmt::Capture &CI,
10218 const FieldDecl &RI, llvm::Value *CV,
10219 MapCombinedInfoTy &CombinedInfo)
const {
10220 bool IsImplicit =
true;
10223 CombinedInfo.Exprs.push_back(
nullptr);
10224 CombinedInfo.BasePointers.push_back(CV);
10225 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
10226 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
10227 CombinedInfo.Pointers.push_back(CV);
10229 CombinedInfo.Sizes.push_back(
10233 CombinedInfo.Types.push_back(OpenMPOffloadMappingFlags::OMP_MAP_TO |
10234 OpenMPOffloadMappingFlags::OMP_MAP_FROM);
10238 CombinedInfo.BasePointers.push_back(CV);
10239 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
10240 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
10241 CombinedInfo.Pointers.push_back(CV);
10242 bool IsFirstprivate =
10248 CombinedInfo.Types.push_back(
10249 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL);
10250 CombinedInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
10252 }
else if (IsFirstprivate) {
10255 CombinedInfo.Types.push_back(
10256 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL);
10258 CombinedInfo.Sizes.push_back(llvm::Constant::getNullValue(CGF.
Int64Ty));
10262 CombinedInfo.Types.push_back(OpenMPOffloadMappingFlags::OMP_MAP_NONE);
10263 CombinedInfo.Sizes.push_back(llvm::Constant::getNullValue(CGF.
Int64Ty));
10265 auto I = FirstPrivateDecls.find(VD);
10266 if (I != FirstPrivateDecls.end())
10267 IsImplicit = I->getSecond();
10273 bool IsFirstprivate = isEffectivelyFirstprivate(VD, ElementType);
10275 CombinedInfo.BasePointers.push_back(CV);
10276 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
10277 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
10282 CombinedInfo.Pointers.push_back(CV);
10284 CombinedInfo.Sizes.push_back(llvm::Constant::getNullValue(CGF.
Int64Ty));
10285 CombinedInfo.Types.push_back(
10286 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL);
10288 CombinedInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
10293 CombinedInfo.Types.push_back(getMapModifiersForPrivateClauses(CI));
10294 CombinedInfo.Pointers.push_back(CV);
10296 auto I = FirstPrivateDecls.find(VD);
10297 if (I != FirstPrivateDecls.end())
10298 IsImplicit = I->getSecond();
10301 CombinedInfo.Types.back() |=
10302 OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM;
10306 CombinedInfo.Types.back() |= OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT;
10309 CombinedInfo.Mappers.push_back(
nullptr);
10321 dyn_cast<MemberExpr>(OASE->getBase()->IgnoreParenImpCasts()))
10322 return ME->getMemberDecl();
10328static llvm::Constant *
10330 MappableExprsHandler::MappingExprInfo &MapExprs) {
10332 uint32_t SrcLocStrSize;
10333 if (!MapExprs.getMapDecl() && !MapExprs.getMapExpr())
10334 return OMPBuilder.getOrCreateDefaultSrcLocStr(SrcLocStrSize);
10337 if (!MapExprs.getMapDecl() && MapExprs.getMapExpr()) {
10341 Loc = MapExprs.getMapExpr()->getExprLoc();
10343 Loc = MapExprs.getMapDecl()->getLocation();
10346 std::string ExprName;
10347 if (MapExprs.getMapExpr()) {
10349 llvm::raw_string_ostream OS(ExprName);
10350 MapExprs.getMapExpr()->printPretty(OS,
nullptr, P);
10352 ExprName = MapExprs.getMapDecl()->getNameAsString();
10361 return OMPBuilder.getOrCreateSrcLocStr(
FileName, ExprName, PLoc.
getLine(),
10368 CodeGenFunction &CGF, MappableExprsHandler::MapCombinedInfoTy &CombinedInfo,
10370 bool IsNonContiguous =
false,
bool ForEndCall =
false) {
10373 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
10376 InsertPointTy CodeGenIP(CGF.
Builder.GetInsertBlock(),
10377 CGF.
Builder.GetInsertPoint());
10379 auto DeviceAddrCB = [&](
unsigned int I, llvm::Value *NewDecl) {
10380 if (
const ValueDecl *DevVD = CombinedInfo.DevicePtrDecls[I]) {
10385 auto CustomMapperCB = [&](
unsigned int I) {
10386 llvm::Function *MFunc =
nullptr;
10387 if (CombinedInfo.Mappers[I]) {
10388 Info.HasMapper =
true;
10394 cantFail(OMPBuilder.emitOffloadingArraysAndArgs(
10395 AllocaIP, CodeGenIP, Info, Info.RTArgs, CombinedInfo, CustomMapperCB,
10396 IsNonContiguous, ForEndCall, DeviceAddrCB));
10400static const OMPExecutableDirective *
10402 const auto *CS = D.getInnermostCapturedStmt();
10405 const Stmt *ChildStmt =
10408 if (
const auto *NestedDir =
10409 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) {
10411 switch (D.getDirectiveKind()) {
10417 if (DKind == OMPD_teams) {
10418 Body = NestedDir->getInnermostCapturedStmt()->IgnoreContainers(
10423 if (
const auto *NND =
10424 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) {
10425 DKind = NND->getDirectiveKind();
10431 case OMPD_target_teams:
10435 case OMPD_target_parallel:
10436 case OMPD_target_simd:
10437 case OMPD_target_parallel_for:
10438 case OMPD_target_parallel_for_simd:
10440 case OMPD_target_teams_distribute:
10441 case OMPD_target_teams_distribute_simd:
10442 case OMPD_target_teams_distribute_parallel_for:
10443 case OMPD_target_teams_distribute_parallel_for_simd:
10444 case OMPD_parallel:
10446 case OMPD_parallel_for:
10447 case OMPD_parallel_master:
10448 case OMPD_parallel_sections:
10449 case OMPD_for_simd:
10450 case OMPD_parallel_for_simd:
10452 case OMPD_cancellation_point:
10454 case OMPD_threadprivate:
10455 case OMPD_allocate:
10460 case OMPD_sections:
10464 case OMPD_critical:
10465 case OMPD_taskyield:
10467 case OMPD_taskwait:
10468 case OMPD_taskgroup:
10474 case OMPD_target_data:
10475 case OMPD_target_exit_data:
10476 case OMPD_target_enter_data:
10477 case OMPD_distribute:
10478 case OMPD_distribute_simd:
10479 case OMPD_distribute_parallel_for:
10480 case OMPD_distribute_parallel_for_simd:
10481 case OMPD_teams_distribute:
10482 case OMPD_teams_distribute_simd:
10483 case OMPD_teams_distribute_parallel_for:
10484 case OMPD_teams_distribute_parallel_for_simd:
10485 case OMPD_target_update:
10486 case OMPD_declare_simd:
10487 case OMPD_declare_variant:
10488 case OMPD_begin_declare_variant:
10489 case OMPD_end_declare_variant:
10490 case OMPD_declare_target:
10491 case OMPD_end_declare_target:
10492 case OMPD_declare_reduction:
10493 case OMPD_declare_mapper:
10494 case OMPD_taskloop:
10495 case OMPD_taskloop_simd:
10496 case OMPD_master_taskloop:
10497 case OMPD_master_taskloop_simd:
10498 case OMPD_parallel_master_taskloop:
10499 case OMPD_parallel_master_taskloop_simd:
10500 case OMPD_requires:
10501 case OMPD_metadirective:
10504 llvm_unreachable(
"Unexpected directive.");
10543 if (
UDMMap.count(D) > 0)
10547 auto *MapperVarDecl =
10549 CharUnits ElementSize =
C.getTypeSizeInChars(Ty);
10550 llvm::Type *ElemTy =
CGM.getTypes().ConvertTypeForMem(Ty);
10553 MappableExprsHandler::MapCombinedInfoTy CombinedInfo;
10554 auto PrivatizeAndGenMapInfoCB =
10555 [&](llvm::OpenMPIRBuilder::InsertPointTy CodeGenIP, llvm::Value *PtrPHI,
10556 llvm::Value *BeginArg) -> llvm::OpenMPIRBuilder::MapInfosTy & {
10557 MapperCGF.
Builder.restoreIP(CodeGenIP);
10567 Scope.addPrivate(MapperVarDecl, PtrCurrent);
10568 (void)
Scope.Privatize();
10571 MappableExprsHandler MEHandler(*D, MapperCGF);
10572 MEHandler.generateAllInfoForMapper(CombinedInfo,
OMPBuilder);
10574 auto FillInfoMap = [&](MappableExprsHandler::MappingExprInfo &MapExpr) {
10577 if (
CGM.getCodeGenOpts().getDebugInfo() !=
10578 llvm::codegenoptions::NoDebugInfo) {
10579 CombinedInfo.Names.resize(CombinedInfo.Exprs.size());
10580 llvm::transform(CombinedInfo.Exprs, CombinedInfo.Names.begin(),
10584 return CombinedInfo;
10587 auto CustomMapperCB = [&](
unsigned I) {
10588 llvm::Function *MapperFunc =
nullptr;
10589 if (CombinedInfo.Mappers[I]) {
10593 assert(MapperFunc &&
"Expect a valid mapper function is available.");
10599 llvm::raw_svector_ostream Out(TyStr);
10600 CGM.getCXXABI().getMangleContext().mangleCanonicalTypeName(Ty, Out);
10601 std::string Name =
getName({
"omp_mapper", TyStr, D->
getName()});
10603 llvm::Function *NewFn = cantFail(
OMPBuilder.emitUserDefinedMapper(
10604 PrivatizeAndGenMapInfoCB, ElemTy, Name, CustomMapperCB));
10605 UDMMap.try_emplace(D, NewFn);
10612 auto I =
UDMMap.find(D);
10616 return UDMMap.lookup(D);
10629 Kind != OMPD_target_teams_loop)
10632 return llvm::ConstantInt::get(CGF.
Int64Ty, 0);
10635 if (llvm::Value *NumIterations = SizeEmitter(CGF, *LD))
10636 return NumIterations;
10637 return llvm::ConstantInt::get(CGF.
Int64Ty, 0);
10646 if (OffloadingMandatory) {
10647 CGF.
Builder.CreateUnreachable();
10649 if (RequiresOuterTask) {
10650 CapturedVars.clear();
10654 CapturedVars.end());
10655 Args.push_back(llvm::Constant::getNullValue(CGF.
Builder.getPtrTy()));
10662 llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier>
Device,
10665 llvm::Value *DeviceID;
10666 if (
Device.getPointer()) {
10668 Device.getInt() == OMPC_DEVICE_device_num) &&
10669 "Expected device_num modifier.");
10674 DeviceID = CGF.
Builder.getInt64(OMP_DEVICEID_UNDEF);
10679static std::pair<llvm::Value *, OMPDynGroupprivateFallbackType>
10681 llvm::Value *DynGP = CGF.
Builder.getInt32(0);
10682 auto DynGPFallback = OMPDynGroupprivateFallbackType::Abort;
10686 llvm::Value *DynGPVal =
10690 auto FallbackModifier = DynGPClause->getDynGroupprivateFallbackModifier();
10691 switch (FallbackModifier) {
10692 case OMPC_DYN_GROUPPRIVATE_FALLBACK_abort:
10693 DynGPFallback = OMPDynGroupprivateFallbackType::Abort;
10695 case OMPC_DYN_GROUPPRIVATE_FALLBACK_null:
10696 DynGPFallback = OMPDynGroupprivateFallbackType::Null;
10698 case OMPC_DYN_GROUPPRIVATE_FALLBACK_default_mem:
10701 DynGPFallback = OMPDynGroupprivateFallbackType::DefaultMem;
10704 llvm_unreachable(
"Unknown fallback modifier for OpenMP dyn_groupprivate");
10706 }
else if (
auto *OMPXDynCGClause =
10709 llvm::Value *DynCGMemVal = CGF.
EmitScalarExpr(OMPXDynCGClause->getSize(),
10714 return {DynGP, DynGPFallback};
10720 llvm::OpenMPIRBuilder &OMPBuilder,
10722 MappableExprsHandler::MapCombinedInfoTy &CombinedInfo) {
10724 llvm::DenseMap<llvm::Value *, llvm::Value *> LambdaPointers;
10726 auto *CV = CapturedVars.begin();
10729 CI != CE; ++CI, ++RI, ++CV) {
10730 MappableExprsHandler::MapCombinedInfoTy CurInfo;
10735 CurInfo.Exprs.push_back(
nullptr);
10736 CurInfo.BasePointers.push_back(*CV);
10737 CurInfo.DevicePtrDecls.push_back(
nullptr);
10738 CurInfo.DevicePointers.push_back(
10739 MappableExprsHandler::DeviceInfoTy::None);
10740 CurInfo.Pointers.push_back(*CV);
10741 CurInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
10744 CurInfo.Types.push_back(OpenMPOffloadMappingFlags::OMP_MAP_LITERAL |
10745 OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM |
10746 OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT);
10747 CurInfo.Mappers.push_back(
nullptr);
10752 bool HasEntryWithCVAsAttachPtr =
false;
10754 HasEntryWithCVAsAttachPtr =
10755 MEHandler.hasAttachEntryForCapturedVar(CapturedVD);
10758 MappableExprsHandler::MapDataArrayTy DeclComponentLists;
10761 StorageForImplicitlyAddedComponentLists;
10762 MEHandler.populateComponentListsForNonLambdaCaptureFromClauses(
10763 CapturedVD, DeclComponentLists,
10764 StorageForImplicitlyAddedComponentLists);
10775 bool HasEntryWithoutAttachPtr =
10776 llvm::any_of(DeclComponentLists, [&](
const auto &MapData) {
10778 Components = std::get<0>(MapData);
10779 return !MEHandler.getAttachPtrExpr(Components);
10784 if (DeclComponentLists.empty() ||
10785 (!HasEntryWithCVAsAttachPtr && !HasEntryWithoutAttachPtr))
10786 MEHandler.generateDefaultMapInfo(*CI, **RI, *CV, CurInfo);
10790 MEHandler.generateInfoForCaptureFromClauseInfo(
10791 DeclComponentLists, CI, *CV, CurInfo, OMPBuilder,
10792 CombinedInfo.BasePointers.size());
10797 MappedVarSet.insert(
nullptr);
10802 MEHandler.generateInfoForLambdaCaptures(CI->
getCapturedVar(), *CV,
10803 CurInfo, LambdaPointers);
10806 assert(!CurInfo.BasePointers.empty() &&
10807 "Non-existing map pointer for capture!");
10808 assert(CurInfo.BasePointers.size() == CurInfo.Pointers.size() &&
10809 CurInfo.BasePointers.size() == CurInfo.Sizes.size() &&
10810 CurInfo.BasePointers.size() == CurInfo.Types.size() &&
10811 CurInfo.BasePointers.size() == CurInfo.Mappers.size() &&
10812 "Inconsistent map information sizes!");
10815 CombinedInfo.append(CurInfo);
10818 MEHandler.adjustMemberOfForLambdaCaptures(
10819 OMPBuilder, LambdaPointers, CombinedInfo.BasePointers,
10820 CombinedInfo.Pointers, CombinedInfo.Types);
10824 MappableExprsHandler::MapCombinedInfoTy &CombinedInfo,
10825 llvm::OpenMPIRBuilder &OMPBuilder,
10832 MEHandler.generateAllInfo(CombinedInfo, OMPBuilder, SkippedVarSet);
10834 auto FillInfoMap = [&](MappableExprsHandler::MappingExprInfo &MapExpr) {
10838 llvm::codegenoptions::NoDebugInfo) {
10839 CombinedInfo.Names.resize(CombinedInfo.Exprs.size());
10840 llvm::transform(CombinedInfo.Exprs, CombinedInfo.Names.begin(),
10848 llvm::OpenMPIRBuilder &OMPBuilder,
10849 MappableExprsHandler::MapCombinedInfoTy &CombinedInfo) {
10851 MappableExprsHandler MEHandler(D, CGF);
10852 llvm::DenseSet<CanonicalDeclPtr<const Decl>> MappedVarSet;
10855 MappedVarSet, CombinedInfo);
10856 genMapInfo(MEHandler, CGF, CombinedInfo, OMPBuilder, MappedVarSet);
10859template <
typename ClauseTy>
10864 const auto *
C = D.getSingleClause<ClauseTy>();
10865 assert(!
C->varlist_empty() &&
10866 "ompx_bare requires explicit num_teams and thread_limit");
10868 for (
auto *E :
C->varlist()) {
10880 llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier>
Device,
10882 llvm::Value *&MapTypesArray, llvm::Value *&MapNamesArray,
10887 llvm::OpenMPIRBuilder &OMPBuilder = OMPRuntime->
getOMPBuilder();
10890 MappableExprsHandler::MapCombinedInfoTy CombinedInfo;
10892 genMapInfo(D, CGF, CS, CapturedVars, OMPBuilder, CombinedInfo);
10895 using OpenMPOffloadMappingFlags = llvm::omp::OpenMPOffloadMappingFlags;
10896 auto *NullPtr = llvm::Constant::getNullValue(CGF.
Builder.getPtrTy());
10897 CombinedInfo.BasePointers.push_back(NullPtr);
10898 CombinedInfo.Pointers.push_back(NullPtr);
10899 CombinedInfo.DevicePointers.push_back(
10900 llvm::OpenMPIRBuilder::DeviceInfoTy::None);
10901 CombinedInfo.Sizes.push_back(CGF.
Builder.getInt64(0));
10902 CombinedInfo.Types.push_back(OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM |
10903 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL);
10904 if (!CombinedInfo.Names.empty())
10905 CombinedInfo.Names.push_back(NullPtr);
10906 CombinedInfo.Exprs.push_back(
nullptr);
10907 CombinedInfo.Mappers.push_back(
nullptr);
10908 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
10922 MapTypesArray = Info.RTArgs.MapTypesArray;
10923 MapNamesArray = Info.RTArgs.MapNamesArray;
10925 auto &&ThenGen = [&OMPRuntime, OutlinedFn, &D, &CapturedVars,
10926 RequiresOuterTask, &CS, OffloadingMandatory,
Device,
10927 OutlinedFnID, &InputInfo, &MapTypesArray, &MapNamesArray,
10929 bool IsReverseOffloading =
Device.getInt() == OMPC_DEVICE_ancestor;
10931 if (IsReverseOffloading) {
10937 RequiresOuterTask, CS, OffloadingMandatory, CGF);
10941 bool HasNoWait = D.hasClausesOfKind<OMPNowaitClause>();
10942 unsigned NumTargetItems = InputInfo.NumberOfTargetItems;
10944 llvm::Value *BasePointersArray =
10945 InputInfo.BasePointersArray.emitRawPointer(CGF);
10946 llvm::Value *PointersArray = InputInfo.PointersArray.emitRawPointer(CGF);
10947 llvm::Value *SizesArray = InputInfo.SizesArray.emitRawPointer(CGF);
10948 llvm::Value *MappersArray = InputInfo.MappersArray.emitRawPointer(CGF);
10950 auto &&EmitTargetCallFallbackCB =
10951 [&OMPRuntime, OutlinedFn, &D, &CapturedVars, RequiresOuterTask, &CS,
10952 OffloadingMandatory, &CGF](llvm::OpenMPIRBuilder::InsertPointTy IP)
10953 -> llvm::OpenMPIRBuilder::InsertPointTy {
10956 RequiresOuterTask, CS, OffloadingMandatory, CGF);
10969 NumThreads.push_back(
10975 llvm::Value *NumIterations =
10978 llvm::OpenMPIRBuilder::InsertPointTy AllocaIP(
10981 llvm::OpenMPIRBuilder::TargetDataRTArgs RTArgs(
10982 BasePointersArray, PointersArray, SizesArray, MapTypesArray,
10983 nullptr , MappersArray, MapNamesArray);
10985 llvm::OpenMPIRBuilder::TargetKernelArgs Args(
10986 NumTargetItems, RTArgs, NumIterations, NumTeams, NumThreads,
10987 DynCGroupMem, HasNoWait, DynCGroupMemFallback);
10989 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
10991 CGF.
Builder, OutlinedFnID, EmitTargetCallFallbackCB, Args, DeviceID,
10993 CGF.
Builder.restoreIP(AfterIP);
10996 if (RequiresOuterTask)
11011 [&OMPRuntime, OutlinedFn, &D, &CapturedVars, RequiresOuterTask, &CS,
11014 RequiresOuterTask, CS, OffloadingMandatory, CGF);
11017 if (RequiresOuterTask) {
11027 llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID,
const Expr *IfCond,
11028 llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier>
Device,
11035 const bool OffloadingMandatory = !
CGM.getLangOpts().OpenMPIsTargetDevice &&
11036 CGM.getLangOpts().OpenMPOffloadMandatory;
11038 assert((OffloadingMandatory || OutlinedFn) &&
"Invalid outlined function!");
11040 const bool RequiresOuterTask =
11042 D.hasClausesOfKind<OMPNowaitClause>() ||
11043 D.hasClausesOfKind<OMPInReductionClause>() ||
11044 (
CGM.getLangOpts().OpenMP >= 51 &&
11048 const CapturedStmt &CS = *D.getCapturedStmt(OMPD_target);
11056 llvm::Value *MapTypesArray =
nullptr;
11057 llvm::Value *MapNamesArray =
nullptr;
11059 auto &&TargetThenGen = [
this, OutlinedFn, &D, &CapturedVars,
11060 RequiresOuterTask, &CS, OffloadingMandatory,
Device,
11061 OutlinedFnID, &InputInfo, &MapTypesArray,
11065 RequiresOuterTask, CS, OffloadingMandatory,
11066 Device, OutlinedFnID, InputInfo, MapTypesArray,
11067 MapNamesArray, SizeEmitter, CGF,
CGM);
11070 auto &&TargetElseGen =
11071 [
this, OutlinedFn, &D, &CapturedVars, RequiresOuterTask, &CS,
11074 CS, OffloadingMandatory, CGF);
11081 if (OutlinedFnID) {
11083 emitIfClause(CGF, IfCond, TargetThenGen, TargetElseGen);
11095 StringRef ParentName) {
11102 if (
auto *E = dyn_cast<OMPExecutableDirective>(S);
11111 bool RequiresDeviceCodegen =
11116 if (RequiresDeviceCodegen) {
11124 if (!
OMPBuilder.OffloadInfoManager.hasTargetRegionEntryInfo(EntryInfo))
11127 switch (E.getDirectiveKind()) {
11132 case OMPD_target_parallel:
11136 case OMPD_target_teams:
11140 case OMPD_target_teams_distribute:
11144 case OMPD_target_teams_distribute_simd:
11148 case OMPD_target_parallel_for:
11152 case OMPD_target_parallel_for_simd:
11156 case OMPD_target_simd:
11160 case OMPD_target_teams_distribute_parallel_for:
11165 case OMPD_target_teams_distribute_parallel_for_simd:
11171 case OMPD_target_teams_loop:
11175 case OMPD_target_parallel_loop:
11179 case OMPD_parallel:
11181 case OMPD_parallel_for:
11182 case OMPD_parallel_master:
11183 case OMPD_parallel_sections:
11184 case OMPD_for_simd:
11185 case OMPD_parallel_for_simd:
11187 case OMPD_cancellation_point:
11189 case OMPD_threadprivate:
11190 case OMPD_allocate:
11195 case OMPD_sections:
11199 case OMPD_critical:
11200 case OMPD_taskyield:
11202 case OMPD_taskwait:
11203 case OMPD_taskgroup:
11209 case OMPD_target_data:
11210 case OMPD_target_exit_data:
11211 case OMPD_target_enter_data:
11212 case OMPD_distribute:
11213 case OMPD_distribute_simd:
11214 case OMPD_distribute_parallel_for:
11215 case OMPD_distribute_parallel_for_simd:
11216 case OMPD_teams_distribute:
11217 case OMPD_teams_distribute_simd:
11218 case OMPD_teams_distribute_parallel_for:
11219 case OMPD_teams_distribute_parallel_for_simd:
11220 case OMPD_target_update:
11221 case OMPD_declare_simd:
11222 case OMPD_declare_variant:
11223 case OMPD_begin_declare_variant:
11224 case OMPD_end_declare_variant:
11225 case OMPD_declare_target:
11226 case OMPD_end_declare_target:
11227 case OMPD_declare_reduction:
11228 case OMPD_declare_mapper:
11229 case OMPD_taskloop:
11230 case OMPD_taskloop_simd:
11231 case OMPD_master_taskloop:
11232 case OMPD_master_taskloop_simd:
11233 case OMPD_parallel_master_taskloop:
11234 case OMPD_parallel_master_taskloop_simd:
11235 case OMPD_requires:
11236 case OMPD_metadirective:
11239 llvm_unreachable(
"Unknown target directive for OpenMP device codegen.");
11244 if (
const auto *E = dyn_cast<OMPExecutableDirective>(S)) {
11245 if (!E->hasAssociatedStmt() || !E->getAssociatedStmt())
11253 if (
const auto *L = dyn_cast<LambdaExpr>(S))
11262 std::optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
11263 OMPDeclareTargetDeclAttr::getDeviceType(VD);
11267 if (!IsDevice && DevTy == OMPDeclareTargetDeclAttr::DT_NoHost)
11270 if (IsDevice && DevTy == OMPDeclareTargetDeclAttr::DT_Host)
11278 if (!
CGM.getLangOpts().OpenMPIsTargetDevice) {
11279 if (
const auto *FD = dyn_cast<FunctionDecl>(GD.
getDecl()))
11281 CGM.getLangOpts().OpenMPIsTargetDevice))
11288 if (
const auto *FD = dyn_cast<FunctionDecl>(VD)) {
11289 StringRef Name =
CGM.getMangledName(GD);
11292 CGM.getLangOpts().OpenMPIsTargetDevice))
11297 return !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD) &&
11303 CGM.getLangOpts().OpenMPIsTargetDevice))
11306 if (!
CGM.getLangOpts().OpenMPIsTargetDevice)
11315 StringRef ParentName =
11320 StringRef ParentName =
11327 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
11328 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(
11330 if (!Res || *Res == OMPDeclareTargetDeclAttr::MT_Link ||
11331 ((*Res == OMPDeclareTargetDeclAttr::MT_To ||
11332 *Res == OMPDeclareTargetDeclAttr::MT_Enter) &&
11341 llvm::Constant *
Addr) {
11342 if (
CGM.getLangOpts().OMPTargetTriples.empty() &&
11343 !
CGM.getLangOpts().OpenMPIsTargetDevice)
11346 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
11347 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
11351 if (Res && *Res != OMPDeclareTargetDeclAttr::MT_Link &&
11357 if (Res && *Res == OMPDeclareTargetDeclAttr::MT_Local)
11361 if (
CGM.getLangOpts().OpenMPIsTargetDevice) {
11364 StringRef VarName =
CGM.getMangledName(VD);
11370 auto AddrOfGlobal = [&VD,
this]() {
return CGM.GetAddrOfGlobal(VD); };
11371 auto LinkageForVariable = [&VD,
this]() {
11372 return CGM.getLLVMLinkageVarDefinition(VD);
11375 std::vector<llvm::GlobalVariable *> GeneratedRefs;
11382 CGM.getMangledName(VD), GeneratedRefs,
CGM.getLangOpts().OpenMPSimd,
11383 CGM.getLangOpts().OMPTargetTriples, AddrOfGlobal, LinkageForVariable,
11384 CGM.getTypes().ConvertTypeForMem(
11385 CGM.getContext().getPointerType(VD->
getType())),
11388 for (
auto *ref : GeneratedRefs)
11389 CGM.addCompilerUsedGlobal(ref);
11402 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
11403 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
11407 if (*Res == OMPDeclareTargetDeclAttr::MT_Local ||
11408 ((*Res == OMPDeclareTargetDeclAttr::MT_To ||
11409 *Res == OMPDeclareTargetDeclAttr::MT_Enter) &&
11411 CGM.EmitGlobal(VD);
11413 assert((*Res == OMPDeclareTargetDeclAttr::MT_Link ||
11414 ((*Res == OMPDeclareTargetDeclAttr::MT_To ||
11415 *Res == OMPDeclareTargetDeclAttr::MT_Enter ||
11416 *Res == OMPDeclareTargetDeclAttr::MT_Local) &&
11418 "Expected link clause or to clause with unified memory.");
11419 (void)
CGM.getOpenMPRuntime().getAddrOfDeclareTargetVar(VD);
11427 " Expected target-based directive.");
11432 if (Clause->getClauseKind() == OMPC_unified_shared_memory) {
11434 OMPBuilder.Config.setHasRequiresUnifiedSharedMemory(
true);
11435 }
else if (
const auto *AC =
11436 dyn_cast<OMPAtomicDefaultMemOrderClause>(Clause)) {
11437 switch (AC->getAtomicDefaultMemOrderKind()) {
11438 case OMPC_ATOMIC_DEFAULT_MEM_ORDER_acq_rel:
11441 case OMPC_ATOMIC_DEFAULT_MEM_ORDER_seq_cst:
11444 case OMPC_ATOMIC_DEFAULT_MEM_ORDER_relaxed:
11460 if (!VD || !VD->
hasAttr<OMPAllocateDeclAttr>())
11462 const auto *A = VD->
getAttr<OMPAllocateDeclAttr>();
11463 switch(A->getAllocatorType()) {
11464 case OMPAllocateDeclAttr::OMPNullMemAlloc:
11465 case OMPAllocateDeclAttr::OMPDefaultMemAlloc:
11467 case OMPAllocateDeclAttr::OMPLargeCapMemAlloc:
11468 case OMPAllocateDeclAttr::OMPCGroupMemAlloc:
11469 case OMPAllocateDeclAttr::OMPHighBWMemAlloc:
11470 case OMPAllocateDeclAttr::OMPLowLatMemAlloc:
11471 case OMPAllocateDeclAttr::OMPThreadMemAlloc:
11472 case OMPAllocateDeclAttr::OMPConstMemAlloc:
11473 case OMPAllocateDeclAttr::OMPPTeamMemAlloc:
11476 case OMPAllocateDeclAttr::OMPUserDefinedMemAlloc:
11477 llvm_unreachable(
"Expected predefined allocator for the variables with the "
11478 "static storage.");
11490 if (CGM.getLangOpts().OpenMPIsTargetDevice) {
11491 SavedShouldMarkAsGlobal = CGM.getOpenMPRuntime().ShouldMarkAsGlobal;
11492 CGM.getOpenMPRuntime().ShouldMarkAsGlobal = false;
11497 if (CGM.getLangOpts().OpenMPIsTargetDevice)
11498 CGM.getOpenMPRuntime().ShouldMarkAsGlobal = SavedShouldMarkAsGlobal;
11508 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(D)) {
11510 if (
auto *F = dyn_cast_or_null<llvm::Function>(
11511 CGM.GetGlobalValue(
CGM.getMangledName(GD))))
11512 return !F->isDeclaration();
11524 llvm::Function *OutlinedFn,
11533 llvm::Value *Args[] = {
11535 CGF.
Builder.getInt32(CapturedVars.size()),
11538 RealArgs.append(std::begin(Args), std::end(Args));
11539 RealArgs.append(CapturedVars.begin(), CapturedVars.end());
11541 llvm::FunctionCallee RTLFn =
OMPBuilder.getOrCreateRuntimeFunction(
11542 CGM.getModule(), OMPRTL___kmpc_fork_teams);
11547 const Expr *NumTeams,
11548 const Expr *ThreadLimit,
11555 llvm::Value *NumTeamsVal =
11561 llvm::Value *ThreadLimitVal =
11568 llvm::Value *PushNumTeamsArgs[] = {RTLoc,
getThreadID(CGF, Loc), NumTeamsVal,
11571 CGM.getModule(), OMPRTL___kmpc_push_num_teams),
11576 const Expr *ThreadLimit,
11579 llvm::Value *ThreadLimitVal =
11586 llvm::Value *ThreadLimitArgs[] = {RTLoc,
getThreadID(CGF, Loc),
11589 CGM.getModule(), OMPRTL___kmpc_set_thread_limit),
11604 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
11606 llvm::Value *IfCondVal =
nullptr;
11611 llvm::Value *DeviceID =
nullptr;
11616 DeviceID = CGF.
Builder.getInt64(OMP_DEVICEID_UNDEF);
11620 MappableExprsHandler::MapCombinedInfoTy CombinedInfo;
11621 auto GenMapInfoCB =
11622 [&](InsertPointTy CodeGenIP) -> llvm::OpenMPIRBuilder::MapInfosTy & {
11623 CGF.
Builder.restoreIP(CodeGenIP);
11625 MappableExprsHandler MEHandler(D, CGF);
11626 MEHandler.generateAllInfo(CombinedInfo,
OMPBuilder);
11628 auto FillInfoMap = [&](MappableExprsHandler::MappingExprInfo &MapExpr) {
11631 if (
CGM.getCodeGenOpts().getDebugInfo() !=
11632 llvm::codegenoptions::NoDebugInfo) {
11633 CombinedInfo.Names.resize(CombinedInfo.Exprs.size());
11634 llvm::transform(CombinedInfo.Exprs, CombinedInfo.Names.begin(),
11638 return CombinedInfo;
11640 using BodyGenTy = llvm::OpenMPIRBuilder::BodyGenTy;
11641 auto BodyCB = [&](InsertPointTy CodeGenIP, BodyGenTy BodyGenType) {
11642 CGF.
Builder.restoreIP(CodeGenIP);
11643 switch (BodyGenType) {
11644 case BodyGenTy::Priv:
11648 case BodyGenTy::DupNoPriv:
11650 CodeGen.setAction(NoPrivAction);
11654 case BodyGenTy::NoPriv:
11656 CodeGen.setAction(NoPrivAction);
11661 return InsertPointTy(CGF.
Builder.GetInsertBlock(),
11662 CGF.
Builder.GetInsertPoint());
11665 auto DeviceAddrCB = [&](
unsigned int I, llvm::Value *NewDecl) {
11666 if (
const ValueDecl *DevVD = CombinedInfo.DevicePtrDecls[I]) {
11671 auto CustomMapperCB = [&](
unsigned int I) {
11672 llvm::Function *MFunc =
nullptr;
11673 if (CombinedInfo.Mappers[I]) {
11674 Info.HasMapper =
true;
11686 InsertPointTy CodeGenIP(CGF.
Builder.GetInsertBlock(),
11687 CGF.
Builder.GetInsertPoint());
11688 llvm::OpenMPIRBuilder::LocationDescription OmpLoc(CodeGenIP);
11689 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
11691 OmpLoc, AllocaIP, CodeGenIP, {}, DeviceID,
11692 IfCondVal, Info, GenMapInfoCB, CustomMapperCB,
11693 nullptr, BodyCB, DeviceAddrCB, RTLoc));
11694 CGF.
Builder.restoreIP(AfterIP);
11706 "Expecting either target enter, exit data, or update directives.");
11709 llvm::Value *MapTypesArray =
nullptr;
11710 llvm::Value *MapNamesArray =
nullptr;
11712 auto &&ThenGen = [
this, &D,
Device, &InputInfo, &MapTypesArray,
11715 llvm::Value *DeviceID =
nullptr;
11720 DeviceID = CGF.
Builder.getInt64(OMP_DEVICEID_UNDEF);
11724 llvm::Constant *PointerNum =
11731 {RTLoc, DeviceID, PointerNum,
11739 const bool HasNowait = D.hasClausesOfKind<OMPNowaitClause>();
11740 RuntimeFunction RTLFn;
11741 switch (D.getDirectiveKind()) {
11742 case OMPD_target_enter_data:
11743 RTLFn = HasNowait ? OMPRTL___tgt_target_data_begin_nowait_mapper
11744 : OMPRTL___tgt_target_data_begin_mapper;
11746 case OMPD_target_exit_data:
11747 RTLFn = HasNowait ? OMPRTL___tgt_target_data_end_nowait_mapper
11748 : OMPRTL___tgt_target_data_end_mapper;
11750 case OMPD_target_update:
11751 RTLFn = HasNowait ? OMPRTL___tgt_target_data_update_nowait_mapper
11752 : OMPRTL___tgt_target_data_update_mapper;
11754 case OMPD_parallel:
11756 case OMPD_parallel_for:
11757 case OMPD_parallel_master:
11758 case OMPD_parallel_sections:
11759 case OMPD_for_simd:
11760 case OMPD_parallel_for_simd:
11762 case OMPD_cancellation_point:
11764 case OMPD_threadprivate:
11765 case OMPD_allocate:
11770 case OMPD_sections:
11774 case OMPD_critical:
11775 case OMPD_taskyield:
11777 case OMPD_taskwait:
11778 case OMPD_taskgroup:
11784 case OMPD_target_data:
11785 case OMPD_distribute:
11786 case OMPD_distribute_simd:
11787 case OMPD_distribute_parallel_for:
11788 case OMPD_distribute_parallel_for_simd:
11789 case OMPD_teams_distribute:
11790 case OMPD_teams_distribute_simd:
11791 case OMPD_teams_distribute_parallel_for:
11792 case OMPD_teams_distribute_parallel_for_simd:
11793 case OMPD_declare_simd:
11794 case OMPD_declare_variant:
11795 case OMPD_begin_declare_variant:
11796 case OMPD_end_declare_variant:
11797 case OMPD_declare_target:
11798 case OMPD_end_declare_target:
11799 case OMPD_declare_reduction:
11800 case OMPD_declare_mapper:
11801 case OMPD_taskloop:
11802 case OMPD_taskloop_simd:
11803 case OMPD_master_taskloop:
11804 case OMPD_master_taskloop_simd:
11805 case OMPD_parallel_master_taskloop:
11806 case OMPD_parallel_master_taskloop_simd:
11808 case OMPD_target_simd:
11809 case OMPD_target_teams_distribute:
11810 case OMPD_target_teams_distribute_simd:
11811 case OMPD_target_teams_distribute_parallel_for:
11812 case OMPD_target_teams_distribute_parallel_for_simd:
11813 case OMPD_target_teams:
11814 case OMPD_target_parallel:
11815 case OMPD_target_parallel_for:
11816 case OMPD_target_parallel_for_simd:
11817 case OMPD_requires:
11818 case OMPD_metadirective:
11821 llvm_unreachable(
"Unexpected standalone target data directive.");
11825 OffloadingArgs.push_back(llvm::Constant::getNullValue(CGF.
Int32Ty));
11826 OffloadingArgs.push_back(llvm::Constant::getNullValue(CGF.
VoidPtrTy));
11827 OffloadingArgs.push_back(llvm::Constant::getNullValue(CGF.
Int32Ty));
11828 OffloadingArgs.push_back(llvm::Constant::getNullValue(CGF.
VoidPtrTy));
11831 OMPBuilder.getOrCreateRuntimeFunction(
CGM.getModule(), RTLFn),
11835 auto &&TargetThenGen = [
this, &ThenGen, &D, &InputInfo, &MapTypesArray,
11839 MappableExprsHandler::MapCombinedInfoTy CombinedInfo;
11841 MappableExprsHandler MEHandler(D, CGF);
11847 D.hasClausesOfKind<OMPNowaitClause>();
11853 CGM.getPointerAlign());
11858 MapTypesArray = Info.RTArgs.MapTypesArray;
11859 MapNamesArray = Info.RTArgs.MapNamesArray;
11860 if (RequiresOuterTask)
11905 unsigned Offset = 0;
11906 if (
const auto *MD = dyn_cast<CXXMethodDecl>(FD)) {
11907 if (ParamAttrs[Offset].Kind ==
11908 llvm::OpenMPIRBuilder::DeclareSimdKindTy::Vector)
11909 CDT =
C.getPointerType(
C.getCanonicalTagType(MD->
getParent()));
11913 for (
unsigned I = 0, E = FD->
getNumParams(); I < E; ++I) {
11914 if (ParamAttrs[I + Offset].Kind ==
11915 llvm::OpenMPIRBuilder::DeclareSimdKindTy::Vector) {
11927 return C.getTypeSize(CDT);
11938 llvm::OpenMPIRBuilder::DeclareSimdKindTy Kind) {
11944 if (Kind == llvm::OpenMPIRBuilder::DeclareSimdKindTy::Uniform)
11947 if (Kind == llvm::OpenMPIRBuilder::DeclareSimdKindTy::LinearUVal ||
11948 Kind == llvm::OpenMPIRBuilder::DeclareSimdKindTy::LinearRef)
11951 if ((Kind == llvm::OpenMPIRBuilder::DeclareSimdKindTy::Linear ||
11952 Kind == llvm::OpenMPIRBuilder::DeclareSimdKindTy::LinearVal) &&
11962 unsigned Size =
C.getTypeSize(QT);
11965 if (Size != 8 && Size != 16 && Size != 32 && Size != 64 && Size != 128)
11986 llvm::OpenMPIRBuilder::DeclareSimdKindTy Kind,
11991 return C.getTypeSize(PTy);
11994 return C.getTypeSize(QT);
11996 return C.getTypeSize(
C.getUIntPtrType());
12002static std::tuple<unsigned, unsigned, bool>
12009 bool OutputBecomesInput =
false;
12014 RetType, llvm::OpenMPIRBuilder::DeclareSimdKindTy::Vector,
C));
12016 OutputBecomesInput =
true;
12018 for (
unsigned I = 0, E = FD->
getNumParams(); I < E; ++I) {
12023 assert(!Sizes.empty() &&
"Unable to determine NDS and WDS.");
12026 assert(llvm::all_of(Sizes,
12027 [](
unsigned Size) {
12028 return Size == 8 || Size == 16 || Size == 32 ||
12029 Size == 64 || Size == 128;
12033 return std::make_tuple(*llvm::min_element(Sizes), *llvm::max_element(Sizes),
12034 OutputBecomesInput);
12037static llvm::OpenMPIRBuilder::DeclareSimdBranch
12040 case OMPDeclareSimdDeclAttr::BS_Undefined:
12041 return llvm::OpenMPIRBuilder::DeclareSimdBranch::Undefined;
12042 case OMPDeclareSimdDeclAttr::BS_Inbranch:
12043 return llvm::OpenMPIRBuilder::DeclareSimdBranch::Inbranch;
12044 case OMPDeclareSimdDeclAttr::BS_Notinbranch:
12045 return llvm::OpenMPIRBuilder::DeclareSimdBranch::Notinbranch;
12047 llvm_unreachable(
"unexpected declare simd branch state");
12052 unsigned UserVLEN,
unsigned WDS,
char ISA) {
12054 if (UserVLEN == 1) {
12061 if (ISA ==
'n' && UserVLEN && !llvm::isPowerOf2_32(UserVLEN)) {
12067 if (ISA ==
's' && UserVLEN != 0 &&
12068 ((UserVLEN * WDS > 2048) || (UserVLEN * WDS % 128 != 0))) {
12077 llvm::Function *Fn) {
12082 llvm::DenseMap<const Decl *, unsigned> ParamPositions;
12084 ParamPositions.try_emplace(FD, 0);
12085 unsigned ParamPos = ParamPositions.size();
12087 ParamPositions.try_emplace(P->getCanonicalDecl(), ParamPos);
12092 ParamPositions.size());
12094 for (
const Expr *E :
Attr->uniforms()) {
12098 Pos = ParamPositions[FD];
12101 ->getCanonicalDecl();
12102 auto It = ParamPositions.find(PVD);
12103 assert(It != ParamPositions.end() &&
"Function parameter not found");
12106 ParamAttrs[Pos].Kind =
12107 llvm::OpenMPIRBuilder::DeclareSimdKindTy::Uniform;
12110 auto *NI =
Attr->alignments_begin();
12111 for (
const Expr *E :
Attr->aligneds()) {
12116 Pos = ParamPositions[FD];
12120 ->getCanonicalDecl();
12121 auto It = ParamPositions.find(PVD);
12122 assert(It != ParamPositions.end() &&
"Function parameter not found");
12124 ParmTy = PVD->getType();
12126 ParamAttrs[Pos].Alignment =
12128 ? (*NI)->EvaluateKnownConstInt(
C)
12129 : llvm::APSInt::getUnsigned(
12130 C.toCharUnitsFromBits(
C.getOpenMPDefaultSimdAlign(ParmTy))
12135 auto *SI =
Attr->steps_begin();
12136 auto *MI =
Attr->modifiers_begin();
12137 for (
const Expr *E :
Attr->linears()) {
12140 bool IsReferenceType =
false;
12143 unsigned PtrRescalingFactor = 1;
12145 Pos = ParamPositions[FD];
12147 PtrRescalingFactor =
CGM.getContext()
12148 .getTypeSizeInChars(P->getPointeeType())
12152 ->getCanonicalDecl();
12153 auto It = ParamPositions.find(PVD);
12154 assert(It != ParamPositions.end() &&
"Function parameter not found");
12156 if (
auto *P = dyn_cast<PointerType>(PVD->getType()))
12157 PtrRescalingFactor =
CGM.getContext()
12158 .getTypeSizeInChars(P->getPointeeType())
12160 else if (PVD->getType()->isReferenceType()) {
12161 IsReferenceType =
true;
12162 PtrRescalingFactor =
12164 .getTypeSizeInChars(PVD->getType().getNonReferenceType())
12168 llvm::OpenMPIRBuilder::DeclareSimdAttrTy &ParamAttr = ParamAttrs[Pos];
12169 if (*MI == OMPC_LINEAR_ref)
12170 ParamAttr.Kind = llvm::OpenMPIRBuilder::DeclareSimdKindTy::LinearRef;
12171 else if (*MI == OMPC_LINEAR_uval)
12172 ParamAttr.Kind = llvm::OpenMPIRBuilder::DeclareSimdKindTy::LinearUVal;
12173 else if (IsReferenceType)
12174 ParamAttr.Kind = llvm::OpenMPIRBuilder::DeclareSimdKindTy::LinearVal;
12176 ParamAttr.Kind = llvm::OpenMPIRBuilder::DeclareSimdKindTy::Linear;
12178 ParamAttr.StrideOrArg = llvm::APSInt::getUnsigned(1);
12182 if (
const auto *DRE =
12184 if (
const auto *StridePVD =
12185 dyn_cast<ParmVarDecl>(DRE->getDecl())) {
12186 ParamAttr.HasVarStride =
true;
12187 auto It = ParamPositions.find(StridePVD->getCanonicalDecl());
12188 assert(It != ParamPositions.end() &&
12189 "Function parameter not found");
12190 ParamAttr.StrideOrArg = llvm::APSInt::getUnsigned(It->second);
12194 ParamAttr.StrideOrArg =
Result.Val.getInt();
12200 if (!ParamAttr.HasVarStride &&
12202 llvm::OpenMPIRBuilder::DeclareSimdKindTy::Linear ||
12204 llvm::OpenMPIRBuilder::DeclareSimdKindTy::LinearRef))
12205 ParamAttr.StrideOrArg = ParamAttr.StrideOrArg * PtrRescalingFactor;
12209 llvm::APSInt VLENVal;
12211 const Expr *VLENExpr =
Attr->getSimdlen();
12216 llvm::OpenMPIRBuilder::DeclareSimdBranch State =
12218 if (
CGM.getTriple().isX86()) {
12220 assert(NumElts &&
"Non-zero simdlen/cdtsize expected");
12221 OMPBuilder.emitX86DeclareSimdFunction(Fn, NumElts, VLENVal, ParamAttrs,
12223 }
else if (
CGM.getTriple().getArch() == llvm::Triple::aarch64) {
12224 unsigned VLEN = VLENVal.getExtValue();
12227 const unsigned NDS = std::get<0>(
Data);
12228 const unsigned WDS = std::get<1>(
Data);
12229 const bool OutputBecomesInput = std::get<2>(
Data);
12230 if (
CGM.getTarget().hasFeature(
"sve")) {
12233 Fn, VLEN, ParamAttrs, State,
's', NDS, OutputBecomesInput);
12234 }
else if (
CGM.getTarget().hasFeature(
"neon")) {
12237 Fn, VLEN, ParamAttrs, State,
'n', NDS, OutputBecomesInput);
12247class DoacrossCleanupTy final :
public EHScopeStack::Cleanup {
12249 static const int DoacrossFinArgs = 2;
12252 llvm::FunctionCallee RTLFn;
12253 llvm::Value *Args[DoacrossFinArgs];
12256 DoacrossCleanupTy(llvm::FunctionCallee RTLFn,
12259 assert(CallArgs.size() == DoacrossFinArgs);
12260 std::copy(CallArgs.begin(), CallArgs.end(), std::begin(Args));
12277 QualType Int64Ty =
C.getIntTypeForBitwidth(64,
true);
12285 RD =
C.buildImplicitRecord(
"kmp_dim");
12293 RD =
KmpDimTy->castAsRecordDecl();
12295 llvm::APInt Size(32, NumIterations.size());
12301 enum { LowerFD = 0, UpperFD, StrideFD };
12303 for (
unsigned I = 0, E = NumIterations.size(); I < E; ++I) {
12308 DimsLVal, *std::next(RD->
field_begin(), UpperFD));
12310 CGF.
EmitScalarExpr(NumIterations[I]), NumIterations[I]->getType(),
12311 Int64Ty, NumIterations[I]->getExprLoc());
12315 DimsLVal, *std::next(RD->
field_begin(), StrideFD));
12322 llvm::Value *Args[] = {
12325 llvm::ConstantInt::getSigned(
CGM.Int32Ty, NumIterations.size()),
12330 llvm::FunctionCallee RTLFn =
OMPBuilder.getOrCreateRuntimeFunction(
12331 CGM.getModule(), OMPRTL___kmpc_doacross_init);
12333 llvm::Value *FiniArgs[DoacrossCleanupTy::DoacrossFinArgs] = {
12335 llvm::FunctionCallee FiniRTLFn =
OMPBuilder.getOrCreateRuntimeFunction(
12336 CGM.getModule(), OMPRTL___kmpc_doacross_fini);
12341template <
typename T>
12343 const T *
C, llvm::Value *ULoc,
12344 llvm::Value *ThreadID) {
12347 llvm::APInt Size(32,
C->getNumLoops());
12351 for (
unsigned I = 0, E =
C->getNumLoops(); I < E; ++I) {
12352 const Expr *CounterVal =
C->getLoopData(I);
12353 assert(CounterVal);
12360 llvm::Value *Args[] = {
12363 llvm::FunctionCallee RTLFn;
12365 OMPDoacrossKind<T> ODK;
12366 if (ODK.isSource(
C)) {
12368 OMPRTL___kmpc_doacross_post);
12370 assert(ODK.isSink(
C) &&
"Expect sink modifier.");
12372 OMPRTL___kmpc_doacross_wait);
12392 llvm::FunctionCallee Callee,
12394 assert(Loc.
isValid() &&
"Outlined function call location must be valid.");
12397 if (
auto *Fn = dyn_cast<llvm::Function>(Callee.getCallee())) {
12398 if (Fn->doesNotThrow()) {
12409 emitCall(CGF, Loc, OutlinedFn, Args);
12413 if (
const auto *FD = dyn_cast<FunctionDecl>(D))
12414 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(FD))
12420 const VarDecl *TargetParam)
const {
12427 const Expr *Allocator) {
12428 llvm::Value *AllocVal;
12438 AllocVal = llvm::Constant::getNullValue(
12448 if (!AllocateAlignment)
12451 return llvm::ConstantInt::get(
CGM.
SizeTy, AllocateAlignment->getQuantity());
12464 auto I = UntiedData.find(VD);
12465 if (I != UntiedData.end()) {
12466 UntiedAddr = I->second.first;
12467 UntiedRealAddr = I->second.second;
12471 if (CVD->
hasAttr<OMPAllocateDeclAttr>()) {
12480 Size = CGF.
Builder.CreateNUWAdd(
12482 Size = CGF.
Builder.CreateUDiv(Size,
CGM.getSize(Align));
12483 Size = CGF.
Builder.CreateNUWMul(Size,
CGM.getSize(Align));
12489 const auto *AA = CVD->
getAttr<OMPAllocateDeclAttr>();
12490 const Expr *Allocator = AA->getAllocator();
12494 Args.push_back(ThreadID);
12496 Args.push_back(Alignment);
12497 Args.push_back(Size);
12498 Args.push_back(AllocVal);
12499 llvm::omp::RuntimeFunction FnID =
12500 Alignment ? OMPRTL___kmpc_aligned_alloc : OMPRTL___kmpc_alloc;
12502 OMPBuilder.getOrCreateRuntimeFunction(
CGM.getModule(), FnID), Args,
12504 llvm::FunctionCallee FiniRTLFn =
OMPBuilder.getOrCreateRuntimeFunction(
12505 CGM.getModule(), OMPRTL___kmpc_free);
12513 class OMPAllocateCleanupTy final :
public EHScopeStack::Cleanup {
12514 llvm::FunctionCallee RTLFn;
12517 const Expr *AllocExpr;
12520 OMPAllocateCleanupTy(llvm::FunctionCallee RTLFn,
12522 const Expr *AllocExpr)
12523 : RTLFn(RTLFn), LocEncoding(LocEncoding),
Addr(
Addr),
12524 AllocExpr(AllocExpr) {}
12528 llvm::Value *Args[3];
12534 Args[2] = AllocVal;
12542 CGF.
EHStack.pushCleanup<OMPAllocateCleanupTy>(
12544 VDAddr, Allocator);
12545 if (UntiedRealAddr.
isValid())
12548 Region->emitUntiedSwitch(CGF);
12565 assert(CGM.getLangOpts().OpenMP &&
"Not in OpenMP mode.");
12569 CGM.getOpenMPRuntime().NontemporalDeclsStack.emplace_back();
12571 for (
const Stmt *Ref :
C->private_refs()) {
12572 const auto *SimpleRefExpr =
cast<Expr>(Ref)->IgnoreParenImpCasts();
12574 if (
const auto *DRE = dyn_cast<DeclRefExpr>(SimpleRefExpr)) {
12575 VD = DRE->getDecl();
12578 assert((ME->isImplicitCXXThis() ||
12580 "Expected member of current class.");
12581 VD = ME->getMemberDecl();
12591 CGM.getOpenMPRuntime().NontemporalDeclsStack.pop_back();
12597 std::pair<Address, Address>> &LocalVars)
12598 : CGM(CGF.CGM), NeedToPush(!LocalVars.empty()) {
12602 CGF.
CurFn, CGM.getOpenMPRuntime().UntiedLocalVarsStack.size());
12603 CGM.getOpenMPRuntime().UntiedLocalVarsStack.push_back(LocalVars);
12609 CGM.getOpenMPRuntime().UntiedLocalVarsStack.pop_back();
12613 assert(
CGM.getLangOpts().OpenMP &&
"Not in OpenMP mode.");
12615 return llvm::any_of(
12616 CGM.getOpenMPRuntime().NontemporalDeclsStack,
12620void CGOpenMPRuntime::LastprivateConditionalRAII::tryToDisableInnerAnalysis(
12624 llvm::DenseSet<CanonicalDeclPtr<const Decl>> NeedToCheckForLPCs;
12630 const CapturedStmt *CS = S.getCapturedStmt(CaptureRegions.front());
12637 for (
const auto *
C : S.getClausesOfKind<OMPPrivateClause>()) {
12638 for (
const Expr *Ref :
C->varlist()) {
12639 if (!Ref->getType()->isScalarType())
12641 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
12644 NeedToCheckForLPCs.insert(DRE->getDecl());
12647 for (
const auto *
C : S.getClausesOfKind<OMPFirstprivateClause>()) {
12648 for (
const Expr *Ref :
C->varlist()) {
12649 if (!Ref->getType()->isScalarType())
12651 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
12654 NeedToCheckForLPCs.insert(DRE->getDecl());
12657 for (
const auto *
C : S.getClausesOfKind<OMPLastprivateClause>()) {
12658 for (
const Expr *Ref :
C->varlist()) {
12659 if (!Ref->getType()->isScalarType())
12661 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
12664 NeedToCheckForLPCs.insert(DRE->getDecl());
12667 for (
const auto *
C : S.getClausesOfKind<OMPReductionClause>()) {
12668 for (
const Expr *Ref :
C->varlist()) {
12669 if (!Ref->getType()->isScalarType())
12671 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
12674 NeedToCheckForLPCs.insert(DRE->getDecl());
12677 for (
const auto *
C : S.getClausesOfKind<OMPLinearClause>()) {
12678 for (
const Expr *Ref :
C->varlist()) {
12679 if (!Ref->getType()->isScalarType())
12681 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
12684 NeedToCheckForLPCs.insert(DRE->getDecl());
12687 for (
const Decl *VD : NeedToCheckForLPCs) {
12689 llvm::reverse(
CGM.getOpenMPRuntime().LastprivateConditionalStack)) {
12690 if (
Data.DeclToUniqueName.count(VD) > 0) {
12691 if (!
Data.Disabled)
12692 NeedToAddForLPCsAsDisabled.insert(VD);
12699CGOpenMPRuntime::LastprivateConditionalRAII::LastprivateConditionalRAII(
12702 Action((CGM.getLangOpts().OpenMP >= 50 &&
12703 llvm::any_of(S.getClausesOfKind<OMPLastprivateClause>(),
12704 [](const OMPLastprivateClause *
C) {
12705 return C->getKind() ==
12706 OMPC_LASTPRIVATE_conditional;
12708 ? ActionToDo::PushAsLastprivateConditional
12709 : ActionToDo::DoNotPush) {
12710 assert(
CGM.getLangOpts().OpenMP &&
"Not in OpenMP mode.");
12711 if (
CGM.getLangOpts().OpenMP < 50 || Action == ActionToDo::DoNotPush)
12713 assert(Action == ActionToDo::PushAsLastprivateConditional &&
12714 "Expected a push action.");
12716 CGM.getOpenMPRuntime().LastprivateConditionalStack.emplace_back();
12717 for (
const auto *
C : S.getClausesOfKind<OMPLastprivateClause>()) {
12718 if (
C->getKind() != OMPC_LASTPRIVATE_conditional)
12721 for (
const Expr *Ref :
C->varlist()) {
12722 Data.DeclToUniqueName.insert(std::make_pair(
12727 Data.IVLVal = IVLVal;
12731CGOpenMPRuntime::LastprivateConditionalRAII::LastprivateConditionalRAII(
12733 :
CGM(CGF.
CGM), Action(ActionToDo::DoNotPush) {
12737 llvm::DenseSet<CanonicalDeclPtr<const Decl>> NeedToAddForLPCsAsDisabled;
12738 tryToDisableInnerAnalysis(S, NeedToAddForLPCsAsDisabled);
12739 if (!NeedToAddForLPCsAsDisabled.empty()) {
12740 Action = ActionToDo::DisableLastprivateConditional;
12741 LastprivateConditionalData &
Data =
12743 for (
const Decl *VD : NeedToAddForLPCsAsDisabled)
12744 Data.DeclToUniqueName.try_emplace(VD);
12746 Data.Disabled =
true;
12750CGOpenMPRuntime::LastprivateConditionalRAII
12753 return LastprivateConditionalRAII(CGF, S);
12757 if (CGM.getLangOpts().OpenMP < 50)
12759 if (Action == ActionToDo::DisableLastprivateConditional) {
12760 assert(CGM.getOpenMPRuntime().LastprivateConditionalStack.back().Disabled &&
12761 "Expected list of disabled private vars.");
12762 CGM.getOpenMPRuntime().LastprivateConditionalStack.pop_back();
12764 if (Action == ActionToDo::PushAsLastprivateConditional) {
12766 !CGM.getOpenMPRuntime().LastprivateConditionalStack.back().Disabled &&
12767 "Expected list of lastprivate conditional vars.");
12768 CGM.getOpenMPRuntime().LastprivateConditionalStack.pop_back();
12780 auto VI = I->getSecond().find(VD);
12781 if (VI == I->getSecond().end()) {
12782 RecordDecl *RD =
C.buildImplicitRecord(
"lasprivate.conditional");
12787 NewType =
C.getCanonicalTagType(RD);
12790 I->getSecond().try_emplace(VD, NewType, VDField, FiredField, BaseLVal);
12792 NewType = std::get<0>(VI->getSecond());
12793 VDField = std::get<1>(VI->getSecond());
12794 FiredField = std::get<2>(VI->getSecond());
12795 BaseLVal = std::get<3>(VI->getSecond());
12807class LastprivateConditionalRefChecker final
12810 const Expr *FoundE =
nullptr;
12811 const Decl *FoundD =
nullptr;
12812 StringRef UniqueDeclName;
12814 llvm::Function *FoundFn =
nullptr;
12820 llvm::reverse(LPM)) {
12821 auto It = D.DeclToUniqueName.find(E->
getDecl());
12822 if (It == D.DeclToUniqueName.end())
12828 UniqueDeclName = It->second;
12833 return FoundE == E;
12839 llvm::reverse(LPM)) {
12841 if (It == D.DeclToUniqueName.end())
12847 UniqueDeclName = It->second;
12852 return FoundE == E;
12854 bool VisitStmt(
const Stmt *S) {
12855 for (
const Stmt *Child : S->
children()) {
12858 if (
const auto *E = dyn_cast<Expr>(Child))
12866 explicit LastprivateConditionalRefChecker(
12867 ArrayRef<CGOpenMPRuntime::LastprivateConditionalData> LPM)
12869 std::tuple<const Expr *, const Decl *, StringRef, LValue, llvm::Function *>
12870 getFoundData()
const {
12871 return std::make_tuple(FoundE, FoundD, UniqueDeclName, IVLVal, FoundFn);
12878 StringRef UniqueDeclName,
12884 llvm::Constant *LastIV =
OMPBuilder.getOrCreateInternalVariable(
12885 LLIVTy,
getName({UniqueDeclName,
"iv"}));
12893 llvm::GlobalVariable *
Last =
OMPBuilder.getOrCreateInternalVariable(
12909 auto &&
CodeGen = [&LastIVLVal, &IVLVal, IVVal, &LVal, &LastLVal,
12915 llvm::Value *CmpRes;
12917 CmpRes = CGF.
Builder.CreateICmpSLE(LastIVVal, IVVal);
12920 "Loop iteration variable must be integer.");
12921 CmpRes = CGF.
Builder.CreateICmpULE(LastIVVal, IVVal);
12925 CGF.
Builder.CreateCondBr(CmpRes, ThenBB, ExitBB);
12946 "Aggregates are not supported in lastprivate conditional.");
12955 if (
CGM.getLangOpts().OpenMPSimd) {
12969 if (!Checker.Visit(LHS))
12971 const Expr *FoundE;
12972 const Decl *FoundD;
12973 StringRef UniqueDeclName;
12975 llvm::Function *FoundFn;
12976 std::tie(FoundE, FoundD, UniqueDeclName, IVLVal, FoundFn) =
12977 Checker.getFoundData();
12978 if (FoundFn != CGF.
CurFn) {
12983 "Lastprivate conditional is not found in outer region.");
12984 QualType StructTy = std::get<0>(It->getSecond());
12985 const FieldDecl* FiredDecl = std::get<2>(It->getSecond());
12996 FiredLVal, llvm::AtomicOrdering::Unordered,
13014 auto It = llvm::find_if(
13016 if (It == Range.end() || It->Fn != CGF.
CurFn)
13020 "Lastprivates must be registered already.");
13023 const CapturedStmt *CS = D.getCapturedStmt(CaptureRegions.back());
13024 for (
const auto &Pair : It->DeclToUniqueName) {
13025 const auto *VD =
cast<VarDecl>(Pair.first->getCanonicalDecl());
13028 auto I = LPCI->getSecond().find(Pair.first);
13029 assert(I != LPCI->getSecond().end() &&
13030 "Lastprivate must be rehistered already.");
13032 LValue BaseLVal = std::get<3>(I->getSecond());
13036 llvm::Value *
Cmp = CGF.
Builder.CreateIsNotNull(Res);
13040 CGF.
Builder.CreateCondBr(
Cmp, ThenBB, DoneBB);
13065 "Unknown lastprivate conditional variable.");
13066 StringRef UniqueName = It->second;
13067 llvm::GlobalVariable *GV =
CGM.getModule().getNamedGlobal(UniqueName);
13081 llvm_unreachable(
"Not supported in SIMD-only mode");
13088 llvm_unreachable(
"Not supported in SIMD-only mode");
13095 bool Tied,
unsigned &NumberOfParts) {
13096 llvm_unreachable(
"Not supported in SIMD-only mode");
13104 llvm_unreachable(
"Not supported in SIMD-only mode");
13110 const Expr *Hint) {
13111 llvm_unreachable(
"Not supported in SIMD-only mode");
13117 llvm_unreachable(
"Not supported in SIMD-only mode");
13123 const Expr *Filter) {
13124 llvm_unreachable(
"Not supported in SIMD-only mode");
13129 llvm_unreachable(
"Not supported in SIMD-only mode");
13135 llvm_unreachable(
"Not supported in SIMD-only mode");
13143 llvm_unreachable(
"Not supported in SIMD-only mode");
13150 llvm_unreachable(
"Not supported in SIMD-only mode");
13157 bool ForceSimpleCall) {
13158 llvm_unreachable(
"Not supported in SIMD-only mode");
13165 llvm_unreachable(
"Not supported in SIMD-only mode");
13170 llvm_unreachable(
"Not supported in SIMD-only mode");
13176 llvm_unreachable(
"Not supported in SIMD-only mode");
13182 llvm_unreachable(
"Not supported in SIMD-only mode");
13189 llvm_unreachable(
"Not supported in SIMD-only mode");
13195 llvm_unreachable(
"Not supported in SIMD-only mode");
13200 unsigned IVSize,
bool IVSigned,
13203 llvm_unreachable(
"Not supported in SIMD-only mode");
13211 llvm_unreachable(
"Not supported in SIMD-only mode");
13215 ProcBindKind ProcBind,
13217 llvm_unreachable(
"Not supported in SIMD-only mode");
13224 llvm_unreachable(
"Not supported in SIMD-only mode");
13230 llvm_unreachable(
"Not supported in SIMD-only mode");
13235 llvm_unreachable(
"Not supported in SIMD-only mode");
13241 llvm::AtomicOrdering AO) {
13242 llvm_unreachable(
"Not supported in SIMD-only mode");
13247 llvm::Function *TaskFunction,
13249 const Expr *IfCond,
13251 llvm_unreachable(
"Not supported in SIMD-only mode");
13258 llvm_unreachable(
"Not supported in SIMD-only mode");
13265 assert(Options.
SimpleReduction &&
"Only simple reduction is expected.");
13267 ReductionOps, Options);
13273 llvm_unreachable(
"Not supported in SIMD-only mode");
13278 bool IsWorksharingReduction) {
13279 llvm_unreachable(
"Not supported in SIMD-only mode");
13286 llvm_unreachable(
"Not supported in SIMD-only mode");
13291 llvm::Value *ReductionsPtr,
13293 llvm_unreachable(
"Not supported in SIMD-only mode");
13299 llvm_unreachable(
"Not supported in SIMD-only mode");
13305 llvm_unreachable(
"Not supported in SIMD-only mode");
13311 llvm_unreachable(
"Not supported in SIMD-only mode");
13316 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
13318 llvm_unreachable(
"Not supported in SIMD-only mode");
13323 llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID,
const Expr *IfCond,
13324 llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier>
Device,
13328 llvm_unreachable(
"Not supported in SIMD-only mode");
13332 llvm_unreachable(
"Not supported in SIMD-only mode");
13336 llvm_unreachable(
"Not supported in SIMD-only mode");
13346 llvm::Function *OutlinedFn,
13348 llvm_unreachable(
"Not supported in SIMD-only mode");
13352 const Expr *NumTeams,
13353 const Expr *ThreadLimit,
13355 llvm_unreachable(
"Not supported in SIMD-only mode");
13362 llvm_unreachable(
"Not supported in SIMD-only mode");
13368 llvm_unreachable(
"Not supported in SIMD-only mode");
13374 llvm_unreachable(
"Not supported in SIMD-only mode");
13379 llvm_unreachable(
"Not supported in SIMD-only mode");
13384 llvm_unreachable(
"Not supported in SIMD-only mode");
13389 const VarDecl *NativeParam)
const {
13390 llvm_unreachable(
"Not supported in SIMD-only mode");
13396 const VarDecl *TargetParam)
const {
13397 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 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 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)
static mlir::omp::DeclareTargetCaptureClause convertCaptureClause(OMPDeclareTargetDeclAttr::MapTypeTy mapTy)
static bool isAssumedToBeNotEmitted(const ValueDecl *vd, bool isDevice)
Returns true if the declaration should be skipped based on its device_type attribute and the current ...
@ LLVM_MARK_AS_BITMASK_ENUM
Result
Implement __builtin_bit_cast and related operations.
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,...
RawAddress CreateMemTempWithoutCast(QualType T, const Twine &Name="tmp")
CreateMemTemp - Create a temporary memory object of the given type, with appropriate alignmen without...
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, const 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.
@ Address
A pointer to a ValueDecl.
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.