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.CreateNUWAdd(
819 Size, llvm::ConstantInt::get(Size->getType(), 1));
820 SizeInChars = CGF.
Builder.CreateNUWMul(Size, ElemSizeOf);
823 CGF.
getTypeSize(OrigAddresses[N].first.getType().getNonReferenceType());
824 Size = CGF.
Builder.CreateExactUDiv(SizeInChars, ElemSizeOf);
826 Sizes.emplace_back(SizeInChars, Size);
839 assert(!Size && !Sizes[N].second &&
840 "Size should be nullptr for non-variably modified reduction "
855 assert(SharedAddresses.size() > N &&
"No variable was generated");
856 const auto *PrivateVD =
862 (void)DefaultInit(CGF);
863 emitAggregateInitialization(CGF, N, PrivateAddr, SharedAddr, DRD);
864 }
else if (DRD && (DRD->
getInitializer() || !PrivateVD->hasInit())) {
865 (void)DefaultInit(CGF);
866 QualType SharedType = SharedAddresses[N].first.getType();
868 PrivateAddr, SharedAddr, SharedType);
869 }
else if (!DefaultInit(CGF) && PrivateVD->hasInit() &&
872 PrivateVD->
getType().getQualifiers(),
890 CGF.
pushDestroy(DTorKind, PrivateAddr, PrivateType);
909 BaseLV.getType(), BaseLV.getBaseInfo(),
943 const VarDecl *OrigVD =
nullptr;
944 if (
const auto *OASE = dyn_cast<ArraySectionExpr>(Ref)) {
945 const Expr *
Base = OASE->getBase()->IgnoreParenImpCasts();
946 while (
const auto *TempOASE = dyn_cast<ArraySectionExpr>(
Base))
947 Base = TempOASE->getBase()->IgnoreParenImpCasts();
948 while (
const auto *TempASE = dyn_cast<ArraySubscriptExpr>(
Base))
949 Base = TempASE->getBase()->IgnoreParenImpCasts();
952 }
else if (
const auto *ASE = dyn_cast<ArraySubscriptExpr>(Ref)) {
953 const Expr *
Base = ASE->getBase()->IgnoreParenImpCasts();
954 while (
const auto *TempASE = dyn_cast<ArraySubscriptExpr>(
Base))
955 Base = TempASE->getBase()->IgnoreParenImpCasts();
966 BaseDecls.emplace_back(OrigVD);
969 loadToBegin(CGF, OrigVD->getType(), SharedAddresses[N].first.getType(),
971 Address SharedAddr = SharedAddresses[N].first.getAddress();
972 llvm::Value *Adjustment = CGF.
Builder.CreatePtrDiff(
975 llvm::Value *PrivatePointer =
981 SharedAddresses[N].first.getType(),
984 BaseDecls.emplace_back(
998 getThreadIDVariable()->
getType()->castAs<PointerType>());
1016LValue CGOpenMPTaskOutlinedRegionInfo::getThreadIDVariableLValue(
1019 getThreadIDVariable()->
getType(),
1037 llvm::OpenMPIRBuilderConfig Config(
1038 CGM.getLangOpts().OpenMPIsTargetDevice,
isGPU(),
1039 CGM.getLangOpts().OpenMPOffloadMandatory,
1042 Config.setDefaultTargetAS(
1044 Config.setRuntimeCC(
CGM.getRuntimeCC());
1049 CGM.getLangOpts().OpenMPIsTargetDevice
1050 ?
CGM.getLangOpts().OMPHostIRFile
1055 if (
CGM.getLangOpts().OpenMPForceUSM) {
1057 OMPBuilder.Config.setHasRequiresUnifiedSharedMemory(
true);
1065 if (!
Data.getValue().pointsToAliveValue())
1067 auto *GV = dyn_cast<llvm::GlobalVariable>(
Data.getValue());
1070 if (!GV->isDeclaration() || GV->getNumUses() > 0)
1072 GV->eraseFromParent();
1077 return OMPBuilder.createPlatformSpecificName(Parts);
1080static llvm::Function *
1082 const Expr *CombinerInitializer,
const VarDecl *In,
1083 const VarDecl *Out,
bool IsCombiner) {
1086 QualType PtrTy =
C.getPointerType(Ty).withRestrict();
1092 Args.push_back(&OmpOutParm);
1093 Args.push_back(&OmpInParm);
1098 {IsCombiner ?
"omp_combiner" :
"omp_initializer",
""});
1099 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
1103 Fn->removeFnAttr(llvm::Attribute::NoInline);
1104 Fn->removeFnAttr(llvm::Attribute::OptimizeNone);
1105 Fn->addFnAttr(llvm::Attribute::AlwaysInline);
1111 Out->getLocation());
1121 (void)
Scope.Privatize();
1122 if (!IsCombiner && Out->hasInit() &&
1125 Out->getType().getQualifiers(),
1128 if (CombinerInitializer)
1130 Scope.ForceCleanup();
1159std::pair<llvm::Function *, llvm::Function *>
1171struct PushAndPopStackRAII {
1172 PushAndPopStackRAII(llvm::OpenMPIRBuilder *OMPBuilder,
CodeGenFunction &CGF,
1173 bool HasCancel, llvm::omp::Directive Kind)
1174 : OMPBuilder(OMPBuilder) {
1190 auto FiniCB = [&CGF](llvm::OpenMPIRBuilder::InsertPointTy IP) {
1191 assert(IP.getBlock()->end() == IP.getPoint() &&
1192 "Clang CG should cause non-terminated block!");
1193 CGBuilderTy::InsertPointGuard IPG(CGF.
Builder);
1198 return llvm::Error::success();
1203 llvm::OpenMPIRBuilder::FinalizationInfo FI({FiniCB, Kind, HasCancel});
1204 OMPBuilder->pushFinalizationCB(std::move(FI));
1206 ~PushAndPopStackRAII() {
1208 OMPBuilder->popFinalizationCB();
1210 llvm::OpenMPIRBuilder *OMPBuilder;
1219 "thread id variable must be of type kmp_int32 *");
1221 bool HasCancel =
false;
1222 if (
const auto *OPD = dyn_cast<OMPParallelDirective>(&D))
1223 HasCancel = OPD->hasCancel();
1224 else if (
const auto *OPD = dyn_cast<OMPTargetParallelDirective>(&D))
1225 HasCancel = OPD->hasCancel();
1226 else if (
const auto *OPSD = dyn_cast<OMPParallelSectionsDirective>(&D))
1227 HasCancel = OPSD->hasCancel();
1228 else if (
const auto *OPFD = dyn_cast<OMPParallelForDirective>(&D))
1229 HasCancel = OPFD->hasCancel();
1230 else if (
const auto *OPFD = dyn_cast<OMPTargetParallelForDirective>(&D))
1231 HasCancel = OPFD->hasCancel();
1232 else if (
const auto *OPFD = dyn_cast<OMPDistributeParallelForDirective>(&D))
1233 HasCancel = OPFD->hasCancel();
1234 else if (
const auto *OPFD =
1235 dyn_cast<OMPTeamsDistributeParallelForDirective>(&D))
1236 HasCancel = OPFD->hasCancel();
1237 else if (
const auto *OPFD =
1238 dyn_cast<OMPTargetTeamsDistributeParallelForDirective>(&D))
1239 HasCancel = OPFD->hasCancel();
1244 PushAndPopStackRAII PSR(&OMPBuilder, CGF, HasCancel, InnermostKind);
1245 CGOpenMPOutlinedRegionInfo CGInfo(*CS, ThreadIDVar,
CodeGen, InnermostKind,
1246 HasCancel, OutlinedHelperName);
1252 std::string Suffix =
getName({
"omp_outlined"});
1253 return (Name + Suffix).str();
1261 std::string Suffix =
getName({
"omp",
"reduction",
"reduction_func"});
1262 return (Name + Suffix).str();
1269 const CapturedStmt *CS = D.getCapturedStmt(OMPD_parallel);
1279 const CapturedStmt *CS = D.getCapturedStmt(OMPD_teams);
1289 bool Tied,
unsigned &NumberOfParts) {
1292 llvm::Value *ThreadID =
getThreadID(CGF, D.getBeginLoc());
1294 llvm::Value *TaskArgs[] = {
1296 CGF.EmitLoadOfPointerLValue(CGF.GetAddrOfLocalVar(TaskTVar),
1299 CGF.EmitRuntimeCall(
OMPBuilder.getOrCreateRuntimeFunction(
1300 CGM.getModule(), OMPRTL___kmpc_omp_task),
1303 CGOpenMPTaskOutlinedRegionInfo::UntiedTaskActionTy Action(Tied, PartIDVar,
1307 "thread id variable must be of type kmp_int32 for tasks");
1312 bool HasCancel =
false;
1313 if (
const auto *TD = dyn_cast<OMPTaskDirective>(&D))
1314 HasCancel = TD->hasCancel();
1315 else if (
const auto *TD = dyn_cast<OMPTaskLoopDirective>(&D))
1316 HasCancel = TD->hasCancel();
1317 else if (
const auto *TD = dyn_cast<OMPMasterTaskLoopDirective>(&D))
1318 HasCancel = TD->hasCancel();
1319 else if (
const auto *TD = dyn_cast<OMPParallelMasterTaskLoopDirective>(&D))
1320 HasCancel = TD->hasCancel();
1323 CGOpenMPTaskOutlinedRegionInfo CGInfo(*CS, ThreadIDVar,
CodeGen,
1324 InnermostKind, HasCancel, Action);
1326 llvm::Function *Res = CGF.GenerateCapturedStmtFunction(*CS);
1328 NumberOfParts = Action.getNumberOfParts();
1333 bool AtCurrentPoint) {
1335 assert(!Elem.ServiceInsertPt &&
"Insert point is set already.");
1337 llvm::Value *Undef = llvm::UndefValue::get(CGF.
Int32Ty);
1338 if (AtCurrentPoint) {
1339 Elem.ServiceInsertPt =
new llvm::BitCastInst(Undef, CGF.
Int32Ty,
"svcpt",
1340 CGF.
Builder.GetInsertBlock());
1342 Elem.ServiceInsertPt =
new llvm::BitCastInst(Undef, CGF.
Int32Ty,
"svcpt");
1343 Elem.ServiceInsertPt->insertAfter(CGF.
AllocaInsertPt->getIterator());
1349 if (Elem.ServiceInsertPt) {
1350 llvm::Instruction *Ptr = Elem.ServiceInsertPt;
1351 Elem.ServiceInsertPt =
nullptr;
1352 Ptr->eraseFromParent();
1359 llvm::raw_svector_ostream OS(Buffer);
1368 if (
const auto *FD = dyn_cast_or_null<FunctionDecl>(CGF.
CurFuncDecl))
1369 OS << FD->getQualifiedNameAsString();
1376 unsigned Flags,
bool EmitLoc) {
1377 uint32_t SrcLocStrSize;
1378 llvm::Constant *SrcLocStr;
1379 if ((!EmitLoc &&
CGM.getCodeGenOpts().getDebugInfo() ==
1380 llvm::codegenoptions::NoDebugInfo) ||
1382 SrcLocStr =
OMPBuilder.getOrCreateDefaultSrcLocStr(SrcLocStrSize);
1384 std::string FunctionName;
1386 if (
const auto *FD = dyn_cast_or_null<FunctionDecl>(CGF.
CurFuncDecl))
1387 FunctionName = FD->getQualifiedNameAsString();
1400 SrcLocStr, SrcLocStrSize, llvm::omp::IdentFlag(Flags), Reserved2Flags);
1405 assert(CGF.
CurFn &&
"No function in current CodeGenFunction.");
1408 if (
CGM.getLangOpts().OpenMPIRBuilder) {
1411 uint32_t SrcLocStrSize;
1412 auto *SrcLocStr =
OMPBuilder.getOrCreateSrcLocStr(
1415 OMPBuilder.getOrCreateIdent(SrcLocStr, SrcLocStrSize));
1418 llvm::Value *ThreadID =
nullptr;
1423 ThreadID = I->second.ThreadID;
1424 if (ThreadID !=
nullptr)
1428 if (
auto *OMPRegionInfo =
1430 if (OMPRegionInfo->getThreadIDVariable()) {
1432 LValue LVal = OMPRegionInfo->getThreadIDVariableLValue(CGF);
1436 CGF.
Builder.GetInsertBlock() == TopBlock ||
1441 CGF.
Builder.GetInsertBlock()) {
1445 if (CGF.
Builder.GetInsertBlock() == TopBlock)
1457 if (!Elem.ServiceInsertPt)
1459 CGBuilderTy::InsertPointGuard IPG(CGF.
Builder);
1460 CGF.
Builder.SetInsertPoint(Elem.ServiceInsertPt);
1464 OMPRTL___kmpc_global_thread_num),
1467 Elem.ThreadID =
Call;
1472 assert(CGF.
CurFn &&
"No function in current CodeGenFunction.");
1478 for (
const auto *D : I->second)
1483 for (
const auto *D : I->second)
1495static llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseKind
1497 std::optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
1498 OMPDeclareTargetDeclAttr::getDeviceType(VD);
1500 return llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseNone;
1502 switch ((
int)*DevTy) {
1503 case OMPDeclareTargetDeclAttr::DT_Host:
1504 return llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseHost;
1506 case OMPDeclareTargetDeclAttr::DT_NoHost:
1507 return llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseNoHost;
1509 case OMPDeclareTargetDeclAttr::DT_Any:
1510 return llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseAny;
1513 return llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseNone;
1518static llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryKind
1520 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> MapType =
1521 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
1523 return llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryNone;
1524 switch ((
int)*MapType) {
1525 case OMPDeclareTargetDeclAttr::MapTypeTy::MT_To:
1526 return llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryTo;
1528 case OMPDeclareTargetDeclAttr::MapTypeTy::MT_Enter:
1529 return llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryEnter;
1531 case OMPDeclareTargetDeclAttr::MapTypeTy::MT_Link:
1532 return llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryLink;
1535 return llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryNone;
1544 auto FileInfoCallBack = [&]() {
1549 PLoc =
SM.getPresumedLoc(BeginLoc,
false);
1554 return OMPBuilder.getTargetEntryUniqueInfo(FileInfoCallBack,
1559 auto AddrOfGlobal = [&VD,
this]() {
return CGM.GetAddrOfGlobal(VD); };
1561 auto LinkageForVariable = [&VD,
this]() {
1562 return CGM.getLLVMLinkageVarDefinition(VD);
1565 std::vector<llvm::GlobalVariable *> GeneratedRefs;
1567 llvm::Type *LlvmPtrTy =
CGM.getTypes().ConvertTypeForMem(
1568 CGM.getContext().getPointerType(VD->
getType()));
1569 llvm::Constant *addr =
OMPBuilder.getAddrOfDeclareTargetVar(
1575 CGM.getMangledName(VD), GeneratedRefs,
CGM.getLangOpts().OpenMPSimd,
1576 CGM.getLangOpts().OMPTargetTriples, LlvmPtrTy, AddrOfGlobal,
1577 LinkageForVariable);
1586 assert(!
CGM.getLangOpts().OpenMPUseTLS ||
1587 !
CGM.getContext().getTargetInfo().isTLSSupported());
1589 std::string Suffix =
getName({
"cache",
""});
1590 return OMPBuilder.getOrCreateInternalVariable(
1591 CGM.Int8PtrPtrTy, Twine(
CGM.getMangledName(VD)).concat(Suffix).str());
1598 if (
CGM.getLangOpts().OpenMPUseTLS &&
1599 CGM.getContext().getTargetInfo().isTLSSupported())
1603 llvm::Value *Args[] = {
1606 CGM.getSize(
CGM.GetTargetTypeStoreSize(VarTy)),
1611 CGM.getModule(), OMPRTL___kmpc_threadprivate_cached),
1623 CGM.getModule(), OMPRTL___kmpc_global_thread_num),
1627 llvm::Value *Args[] = {
1630 Ctor, CopyCtor, Dtor};
1633 CGM.getModule(), OMPRTL___kmpc_threadprivate_register),
1640 if (
CGM.getLangOpts().OpenMPUseTLS &&
1641 CGM.getContext().getTargetInfo().isTLSSupported())
1648 llvm::Value *Ctor =
nullptr, *CopyCtor =
nullptr, *Dtor =
nullptr;
1650 if (
CGM.getLangOpts().CPlusPlus && PerformInit) {
1656 nullptr,
CGM.getContext().VoidPtrTy,
1658 Args.push_back(&Dst);
1660 const auto &FI =
CGM.getTypes().arrangeBuiltinFunctionDeclaration(
1661 CGM.getContext().VoidPtrTy, Args);
1662 llvm::FunctionType *FTy =
CGM.getTypes().GetFunctionType(FI);
1663 std::string Name =
getName({
"__kmpc_global_ctor_",
""});
1664 llvm::Function *Fn =
1665 CGM.CreateGlobalInitOrCleanUpFunction(FTy, Name, FI, Loc);
1688 nullptr,
CGM.getContext().VoidPtrTy,
1690 Args.push_back(&Dst);
1692 const auto &FI =
CGM.getTypes().arrangeBuiltinFunctionDeclaration(
1693 CGM.getContext().VoidTy, Args);
1694 llvm::FunctionType *FTy =
CGM.getTypes().GetFunctionType(FI);
1695 std::string Name =
getName({
"__kmpc_global_dtor_",
""});
1696 llvm::Function *Fn =
1697 CGM.CreateGlobalInitOrCleanUpFunction(FTy, Name, FI, Loc);
1720 CopyCtor = llvm::Constant::getNullValue(
CGM.DefaultPtrTy);
1721 if (Ctor ==
nullptr) {
1722 Ctor = llvm::Constant::getNullValue(
CGM.DefaultPtrTy);
1724 if (Dtor ==
nullptr) {
1725 Dtor = llvm::Constant::getNullValue(
CGM.DefaultPtrTy);
1728 auto *InitFunctionTy =
1729 llvm::FunctionType::get(
CGM.VoidTy,
false);
1730 std::string Name =
getName({
"__omp_threadprivate_init_",
""});
1731 llvm::Function *InitFunction =
CGM.CreateGlobalInitOrCleanUpFunction(
1732 InitFunctionTy, Name,
CGM.getTypes().arrangeNullaryFunction());
1736 CGM.getTypes().arrangeNullaryFunction(), ArgList,
1740 return InitFunction;
1748 llvm::GlobalValue *GV) {
1749 std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr =
1750 OMPDeclareTargetDeclAttr::getActiveAttr(FD);
1753 if (!ActiveAttr || !(*ActiveAttr)->getIndirect())
1760 OMPBuilder.OffloadInfoManager.getTargetRegionEntryFnName(Name, EntryInfo);
1766 llvm::GlobalValue *
Addr = GV;
1767 if (
CGM.getLangOpts().OpenMPIsTargetDevice) {
1768 llvm::PointerType *FnPtrTy = llvm::PointerType::get(
1769 CGM.getLLVMContext(),
1770 CGM.getModule().getDataLayout().getProgramAddressSpace());
1771 Addr =
new llvm::GlobalVariable(
1772 CGM.getModule(), FnPtrTy,
1773 true, llvm::GlobalValue::ExternalLinkage, GV, Name,
1774 nullptr, llvm::GlobalValue::NotThreadLocal,
1775 CGM.getModule().getDataLayout().getDefaultGlobalsAddressSpace());
1776 Addr->setVisibility(llvm::GlobalValue::ProtectedVisibility);
1779 OMPBuilder.OffloadInfoManager.registerDeviceGlobalVarEntryInfo(
1780 Name,
Addr,
CGM.GetTargetTypeStoreSize(
CGM.VoidPtrTy).getQuantity(),
1781 llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryIndirect,
1782 llvm::GlobalValue::WeakODRLinkage);
1788 std::string Suffix =
getName({
"artificial",
""});
1790 llvm::GlobalVariable *GAddr =
OMPBuilder.getOrCreateInternalVariable(
1791 VarLVType, Twine(Name).concat(Suffix).str());
1792 if (
CGM.getLangOpts().OpenMP &&
CGM.getLangOpts().OpenMPUseTLS &&
1793 CGM.getTarget().isTLSSupported()) {
1794 GAddr->setThreadLocal(
true);
1795 return Address(GAddr, GAddr->getValueType(),
1796 CGM.getContext().getTypeAlignInChars(VarType));
1798 std::string CacheSuffix =
getName({
"cache",
""});
1799 llvm::Value *Args[] = {
1807 Twine(Name).concat(Suffix).concat(CacheSuffix).str())};
1812 CGM.getModule(), OMPRTL___kmpc_threadprivate_cached),
1815 VarLVType,
CGM.getContext().getTypeAlignInChars(VarType));
1865 auto &M =
CGM.getModule();
1866 auto &&ThenGen = [&M, OutlinedFn, CapturedVars, RTLoc,
1869 llvm::Value *Args[] = {
1871 CGF.
Builder.getInt32(CapturedVars.size()),
1874 RealArgs.append(std::begin(Args), std::end(Args));
1875 RealArgs.append(CapturedVars.begin(), CapturedVars.end());
1877 llvm::FunctionCallee RTLFn =
1878 OMPBuilder.getOrCreateRuntimeFunction(M, OMPRTL___kmpc_fork_call);
1881 auto &&ElseGen = [&M, OutlinedFn, CapturedVars, RTLoc, Loc,
1887 llvm::Value *Args[] = {RTLoc, ThreadID};
1889 M, OMPRTL___kmpc_serialized_parallel),
1896 ".bound.zero.addr");
1901 OutlinedFnArgs.push_back(ZeroAddrBound.
getPointer());
1902 OutlinedFnArgs.append(CapturedVars.begin(), CapturedVars.end());
1910 OutlinedFn->removeFnAttr(llvm::Attribute::AlwaysInline);
1911 OutlinedFn->addFnAttr(llvm::Attribute::NoInline);
1917 M, OMPRTL___kmpc_end_serialized_parallel),
1936 if (
auto *OMPRegionInfo =
1938 if (OMPRegionInfo->getThreadIDVariable())
1939 return OMPRegionInfo->getThreadIDVariableLValue(CGF).getAddress();
1948 return ThreadIDTemp;
1952 std::string Prefix = Twine(
"gomp_critical_user_", CriticalName).str();
1953 std::string Name =
getName({Prefix,
"var"});
1960 llvm::FunctionCallee EnterCallee;
1962 llvm::FunctionCallee ExitCallee;
1965 llvm::BasicBlock *ContBlock =
nullptr;
1968 CommonActionTy(llvm::FunctionCallee EnterCallee,
1970 llvm::FunctionCallee ExitCallee,
1972 : EnterCallee(EnterCallee), EnterArgs(EnterArgs), ExitCallee(ExitCallee),
1977 llvm::Value *CallBool = CGF.
Builder.CreateIsNotNull(EnterRes);
1981 CGF.
Builder.CreateCondBr(CallBool, ThenBlock, ContBlock);
1985 void Done(CodeGenFunction &CGF) {
1990 void Exit(CodeGenFunction &CGF)
override {
1997 StringRef CriticalName,
2006 llvm::FunctionCallee RuntimeFcn =
OMPBuilder.getOrCreateRuntimeFunction(
2008 Hint ? OMPRTL___kmpc_critical_with_hint : OMPRTL___kmpc_critical);
2010 unsigned LockVarArgIdx = 2;
2012 RuntimeFcn.getFunctionType()
2013 ->getParamType(LockVarArgIdx)
2014 ->getPointerAddressSpace())
2016 LockVar, RuntimeFcn.getFunctionType()->getParamType(LockVarArgIdx));
2022 EnterArgs.push_back(CGF.
Builder.CreateIntCast(
2025 CommonActionTy Action(RuntimeFcn, EnterArgs,
2027 CGM.getModule(), OMPRTL___kmpc_end_critical),
2044 CommonActionTy Action(
OMPBuilder.getOrCreateRuntimeFunction(
2045 CGM.getModule(), OMPRTL___kmpc_master),
2048 CGM.getModule(), OMPRTL___kmpc_end_master),
2066 llvm::Value *FilterVal = Filter
2068 : llvm::ConstantInt::get(
CGM.Int32Ty, 0);
2073 CommonActionTy Action(
OMPBuilder.getOrCreateRuntimeFunction(
2074 CGM.getModule(), OMPRTL___kmpc_masked),
2077 CGM.getModule(), OMPRTL___kmpc_end_masked),
2093 llvm::Value *Args[] = {
2095 llvm::ConstantInt::get(
CGM.IntTy, 0,
true)};
2097 CGM.getModule(), OMPRTL___kmpc_omp_taskyield),
2101 if (
auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.
CapturedStmtInfo))
2102 Region->emitUntiedSwitch(CGF);
2115 CommonActionTy Action(
OMPBuilder.getOrCreateRuntimeFunction(
2116 CGM.getModule(), OMPRTL___kmpc_taskgroup),
2119 CGM.getModule(), OMPRTL___kmpc_end_taskgroup),
2128 unsigned Index,
const VarDecl *Var) {
2149 Args.push_back(&LHSArg);
2150 Args.push_back(&RHSArg);
2156 llvm::GlobalValue::InternalLinkage, Name,
2159 Fn->setDoesNotRecurse();
2176 for (
unsigned I = 0, E = AssignmentOps.size(); I < E; ++I) {
2177 const auto *DestVar =
2181 const auto *SrcVar =
2187 CGF.
EmitOMPCopy(
Type, DestAddr, SrcAddr, DestVar, SrcVar, AssignmentOps[I]);
2202 assert(CopyprivateVars.size() == SrcExprs.size() &&
2203 CopyprivateVars.size() == DstExprs.size() &&
2204 CopyprivateVars.size() == AssignmentOps.size());
2216 if (!CopyprivateVars.empty()) {
2219 C.getIntTypeForBitwidth(32, 1);
2220 DidIt = CGF.
CreateMemTemp(KmpInt32Ty,
".omp.copyprivate.did_it");
2225 CommonActionTy Action(
OMPBuilder.getOrCreateRuntimeFunction(
2226 CGM.getModule(), OMPRTL___kmpc_single),
2229 CGM.getModule(), OMPRTL___kmpc_end_single),
2242 llvm::APInt ArraySize(32, CopyprivateVars.size());
2243 QualType CopyprivateArrayTy =
C.getConstantArrayType(
2248 CGF.
CreateMemTemp(CopyprivateArrayTy,
".omp.copyprivate.cpr_list");
2249 for (
unsigned I = 0, E = CopyprivateVars.size(); I < E; ++I) {
2261 SrcExprs, DstExprs, AssignmentOps, Loc);
2262 llvm::Value *BufSize = CGF.
getTypeSize(CopyprivateArrayTy);
2266 llvm::Value *Args[] = {
2270 CL.emitRawPointer(CGF),
2275 CGM.getModule(), OMPRTL___kmpc_copyprivate),
2291 CommonActionTy Action(
OMPBuilder.getOrCreateRuntimeFunction(
2292 CGM.getModule(), OMPRTL___kmpc_ordered),
2295 CGM.getModule(), OMPRTL___kmpc_end_ordered),
2306 if (Kind == OMPD_for)
2307 Flags = OMP_IDENT_BARRIER_IMPL_FOR;
2308 else if (Kind == OMPD_sections)
2309 Flags = OMP_IDENT_BARRIER_IMPL_SECTIONS;
2310 else if (Kind == OMPD_single)
2311 Flags = OMP_IDENT_BARRIER_IMPL_SINGLE;
2312 else if (Kind == OMPD_barrier)
2313 Flags = OMP_IDENT_BARRIER_EXPL;
2315 Flags = OMP_IDENT_BARRIER_IMPL;
2327 ScheduleKind = OMPC_SCHEDULE_static;
2329 llvm::APInt ChunkSize(32, 1);
2339 bool ForceSimpleCall) {
2341 auto *OMPRegionInfo =
2344 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
2347 CGF.
Builder.restoreIP(AfterIP);
2360 if (OMPRegionInfo) {
2361 if (!ForceSimpleCall && OMPRegionInfo->hasCancel()) {
2364 OMPRTL___kmpc_cancel_barrier),
2373 CGF.
Builder.CreateCondBr(Cmp, ExitBB, ContBB);
2385 CGM.getModule(), OMPRTL___kmpc_barrier),
2390 Expr *ME,
bool IsFatal) {
2392 : llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
2395 llvm::Value *Args[] = {
2397 llvm::ConstantInt::get(
CGM.Int32Ty, IsFatal ? 2 : 1),
2398 CGF.
Builder.CreatePointerCast(MVL,
CGM.Int8PtrTy)};
2400 CGM.getModule(), OMPRTL___kmpc_error),
2406 bool Chunked,
bool Ordered) {
2407 switch (ScheduleKind) {
2408 case OMPC_SCHEDULE_static:
2409 return Chunked ? (Ordered ? OMP_ord_static_chunked : OMP_sch_static_chunked)
2410 : (Ordered ? OMP_ord_static : OMP_sch_static);
2411 case OMPC_SCHEDULE_dynamic:
2412 return Ordered ? OMP_ord_dynamic_chunked : OMP_sch_dynamic_chunked;
2413 case OMPC_SCHEDULE_guided:
2414 return Ordered ? OMP_ord_guided_chunked : OMP_sch_guided_chunked;
2415 case OMPC_SCHEDULE_runtime:
2416 return Ordered ? OMP_ord_runtime : OMP_sch_runtime;
2417 case OMPC_SCHEDULE_auto:
2418 return Ordered ? OMP_ord_auto : OMP_sch_auto;
2420 assert(!Chunked &&
"chunk was specified but schedule kind not known");
2421 return Ordered ? OMP_ord_static : OMP_sch_static;
2423 llvm_unreachable(
"Unexpected runtime schedule");
2427static OpenMPSchedType
2430 return Chunked ? OMP_dist_sch_static_chunked : OMP_dist_sch_static;
2434 bool Chunked)
const {
2435 OpenMPSchedType Schedule =
2437 return Schedule == OMP_sch_static;
2443 return Schedule == OMP_dist_sch_static;
2447 bool Chunked)
const {
2448 OpenMPSchedType Schedule =
2450 return Schedule == OMP_sch_static_chunked;
2456 return Schedule == OMP_dist_sch_static_chunked;
2460 OpenMPSchedType Schedule =
2462 assert(Schedule != OMP_sch_static_chunked &&
"cannot be chunked here");
2463 return Schedule != OMP_sch_static;
2471 case OMPC_SCHEDULE_MODIFIER_monotonic:
2472 Modifier = OMP_sch_modifier_monotonic;
2474 case OMPC_SCHEDULE_MODIFIER_nonmonotonic:
2475 Modifier = OMP_sch_modifier_nonmonotonic;
2477 case OMPC_SCHEDULE_MODIFIER_simd:
2478 if (Schedule == OMP_sch_static_chunked)
2479 Schedule = OMP_sch_static_balanced_chunked;
2486 case OMPC_SCHEDULE_MODIFIER_monotonic:
2487 Modifier = OMP_sch_modifier_monotonic;
2489 case OMPC_SCHEDULE_MODIFIER_nonmonotonic:
2490 Modifier = OMP_sch_modifier_nonmonotonic;
2492 case OMPC_SCHEDULE_MODIFIER_simd:
2493 if (Schedule == OMP_sch_static_chunked)
2494 Schedule = OMP_sch_static_balanced_chunked;
2506 if (CGM.
getLangOpts().OpenMP >= 50 && Modifier == 0) {
2507 if (!(Schedule == OMP_sch_static_chunked || Schedule == OMP_sch_static ||
2508 Schedule == OMP_sch_static_balanced_chunked ||
2509 Schedule == OMP_ord_static_chunked || Schedule == OMP_ord_static ||
2510 Schedule == OMP_dist_sch_static_chunked ||
2511 Schedule == OMP_dist_sch_static))
2512 Modifier = OMP_sch_modifier_nonmonotonic;
2514 return Schedule | Modifier;
2524 ScheduleKind.
Schedule, DispatchValues.
Chunk !=
nullptr, Ordered);
2526 (Schedule != OMP_sch_static && Schedule != OMP_sch_static_chunked &&
2527 Schedule != OMP_ord_static && Schedule != OMP_ord_static_chunked &&
2528 Schedule != OMP_sch_static_balanced_chunked));
2535 llvm::Value *Chunk = DispatchValues.
Chunk ? DispatchValues.
Chunk
2536 : CGF.
Builder.getIntN(IVSize, 1);
2537 llvm::Value *Args[] = {
2541 CGM, Schedule, ScheduleKind.
M1, ScheduleKind.
M2)),
2544 CGF.
Builder.getIntN(IVSize, 1),
2561 CodeGenFunction &CGF, llvm::Value *UpdateLocation, llvm::Value *ThreadId,
2562 llvm::FunctionCallee ForStaticInitFunction, OpenMPSchedType Schedule,
2569 assert(Schedule == OMP_sch_static || Schedule == OMP_sch_static_chunked ||
2570 Schedule == OMP_sch_static_balanced_chunked ||
2571 Schedule == OMP_ord_static || Schedule == OMP_ord_static_chunked ||
2572 Schedule == OMP_dist_sch_static ||
2573 Schedule == OMP_dist_sch_static_chunked);
2580 llvm::Value *Chunk = Values.
Chunk;
2581 if (Chunk ==
nullptr) {
2582 assert((Schedule == OMP_sch_static || Schedule == OMP_ord_static ||
2583 Schedule == OMP_dist_sch_static) &&
2584 "expected static non-chunked schedule");
2588 assert((Schedule == OMP_sch_static_chunked ||
2589 Schedule == OMP_sch_static_balanced_chunked ||
2590 Schedule == OMP_ord_static_chunked ||
2591 Schedule == OMP_dist_sch_static_chunked) &&
2592 "expected static chunked schedule");
2594 llvm::Value *Args[] = {
2617 "Expected loop-based or sections-based directive.");
2620 ? OMP_IDENT_WORK_LOOP
2621 : OMP_IDENT_WORK_SECTIONS);
2623 llvm::FunctionCallee StaticInitFunction =
2628 ScheduleNum, ScheduleKind.
M1, ScheduleKind.
M2, Values);
2635 OpenMPSchedType ScheduleNum =
2637 llvm::Value *UpdatedLocation =
2640 llvm::FunctionCallee StaticInitFunction;
2641 bool isGPUDistribute =
2642 CGM.getLangOpts().OpenMPIsTargetDevice &&
CGM.getTriple().isGPU();
2643 StaticInitFunction =
OMPBuilder.createForStaticInitFunction(
2654 assert((DKind == OMPD_distribute || DKind == OMPD_for ||
2655 DKind == OMPD_sections) &&
2656 "Expected distribute, for, or sections directive kind");
2660 llvm::Value *Args[] = {
2663 (DKind == OMPD_target_teams_loop)
2664 ? OMP_IDENT_WORK_DISTRIBUTE
2666 ? OMP_IDENT_WORK_LOOP
2667 : OMP_IDENT_WORK_SECTIONS),
2671 CGM.getLangOpts().OpenMPIsTargetDevice &&
CGM.getTriple().isGPU())
2674 CGM.getModule(), OMPRTL___kmpc_distribute_static_fini),
2678 CGM.getModule(), OMPRTL___kmpc_for_static_fini),
2703 llvm::Value *Args[] = {
2711 OMPBuilder.createDispatchNextFunction(IVSize, IVSigned), Args);
2718 const Expr *Message,
2721 return llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
2730 return llvm::ConstantInt::get(
CGM.Int32Ty,
2731 Severity == OMPC_SEVERITY_warning ? 1 : 2);
2747 RuntimeFunction FnID = OMPRTL___kmpc_push_num_threads;
2748 if (Modifier == OMPC_NUMTHREADS_strict) {
2749 FnID = OMPRTL___kmpc_push_num_threads_strict;
2754 OMPBuilder.getOrCreateRuntimeFunction(
CGM.getModule(), FnID), Args);
2758 ProcBindKind ProcBind,
2762 assert(ProcBind != OMP_PROC_BIND_unknown &&
"Unsupported proc_bind value.");
2764 llvm::Value *Args[] = {
2766 llvm::ConstantInt::get(
CGM.IntTy,
unsigned(ProcBind),
true)};
2768 CGM.getModule(), OMPRTL___kmpc_push_proc_bind),
2781 CGM.getModule(), OMPRTL___kmpc_flush),
2788enum KmpTaskTFields {
2815 if (
CGM.getLangOpts().OpenMPSimd ||
OMPBuilder.OffloadInfoManager.empty())
2818 llvm::OpenMPIRBuilder::EmitMetadataErrorReportFunctionTy &&ErrorReportFn =
2819 [
this](llvm::OpenMPIRBuilder::EmitMetadataErrorKind Kind,
2820 const llvm::TargetRegionEntryInfo &EntryInfo) ->
void {
2822 if (Kind != llvm::OpenMPIRBuilder::EMIT_MD_GLOBAL_VAR_LINK_ERROR) {
2823 for (
auto I =
CGM.getContext().getSourceManager().fileinfo_begin(),
2824 E =
CGM.getContext().getSourceManager().fileinfo_end();
2826 if (I->getFirst().getUniqueID().getDevice() == EntryInfo.DeviceID &&
2827 I->getFirst().getUniqueID().getFile() == EntryInfo.FileID) {
2828 Loc =
CGM.getContext().getSourceManager().translateFileLineCol(
2829 I->getFirst(), EntryInfo.Line, 1);
2835 case llvm::OpenMPIRBuilder::EMIT_MD_TARGET_REGION_ERROR: {
2836 CGM.getDiags().Report(Loc,
2837 diag::err_target_region_offloading_entry_incorrect)
2838 << EntryInfo.ParentName;
2840 case llvm::OpenMPIRBuilder::EMIT_MD_DECLARE_TARGET_ERROR: {
2841 CGM.getDiags().Report(
2842 Loc, diag::err_target_var_offloading_entry_incorrect_with_parent)
2843 << EntryInfo.ParentName;
2845 case llvm::OpenMPIRBuilder::EMIT_MD_GLOBAL_VAR_LINK_ERROR: {
2846 CGM.getDiags().Report(diag::err_target_var_offloading_entry_incorrect);
2851 OMPBuilder.createOffloadEntriesAndInfoMetadata(ErrorReportFn);
2858 QualType KmpRoutineEntryTyArgs[] = {KmpInt32Ty,
C.VoidPtrTy};
2861 C.getFunctionType(KmpInt32Ty, KmpRoutineEntryTyArgs, EPI));
2867struct PrivateHelpersTy {
2868 PrivateHelpersTy(
const Expr *OriginalRef,
const VarDecl *Original,
2870 : OriginalRef(OriginalRef), Original(Original), PrivateCopy(PrivateCopy),
2871 PrivateElemInit(PrivateElemInit) {}
2872 PrivateHelpersTy(
const VarDecl *Original) : Original(Original) {}
2873 const Expr *OriginalRef =
nullptr;
2874 const VarDecl *Original =
nullptr;
2875 const VarDecl *PrivateCopy =
nullptr;
2876 const VarDecl *PrivateElemInit =
nullptr;
2877 bool isLocalPrivate()
const {
2878 return !OriginalRef && !PrivateCopy && !PrivateElemInit;
2881typedef std::pair<CharUnits , PrivateHelpersTy> PrivateDataTy;
2886 if (!CVD->
hasAttr<OMPAllocateDeclAttr>())
2888 const auto *AA = CVD->
getAttr<OMPAllocateDeclAttr>();
2890 return !(AA->getAllocatorType() == OMPAllocateDeclAttr::OMPDefaultMemAlloc &&
2891 !AA->getAllocator());
2896 if (!Privates.empty()) {
2901 RecordDecl *RD =
C.buildImplicitRecord(
".kmp_privates.t");
2903 for (
const auto &Pair : Privates) {
2904 const VarDecl *VD = Pair.second.Original;
2908 if (Pair.second.isLocalPrivate()) {
2931 QualType KmpRoutineEntryPointerQTy) {
2951 CanQualType KmpCmplrdataTy =
C.getCanonicalTagType(UD);
2952 RecordDecl *RD =
C.buildImplicitRecord(
"kmp_task_t");
2982 RecordDecl *RD =
C.buildImplicitRecord(
"kmp_task_t_with_privates");
3002static llvm::Function *
3005 QualType KmpTaskTWithPrivatesPtrQTy,
3007 QualType SharedsPtrTy, llvm::Function *TaskFunction,
3008 llvm::Value *TaskPrivatesMap) {
3016 Args.push_back(&GtidArg);
3017 Args.push_back(&TaskTypeArg);
3018 const auto &TaskEntryFnInfo =
3020 llvm::FunctionType *TaskEntryTy =
3023 auto *TaskEntry = llvm::Function::Create(
3024 TaskEntryTy, llvm::GlobalValue::InternalLinkage, Name, &CGM.
getModule());
3026 TaskEntry->setDoesNotRecurse();
3041 const auto *KmpTaskTWithPrivatesQTyRD =
3046 auto PartIdFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTPartId);
3048 llvm::Value *PartidParam = PartIdLVal.getPointer(CGF);
3050 auto SharedsFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTShareds);
3056 auto PrivatesFI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin(), 1);
3057 llvm::Value *PrivatesParam;
3058 if (PrivatesFI != KmpTaskTWithPrivatesQTyRD->field_end()) {
3061 PrivatesLVal.getPointer(CGF), CGF.
VoidPtrTy);
3063 PrivatesParam = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
3066 llvm::Value *CommonArgs[] = {
3067 GtidParam, PartidParam, PrivatesParam, TaskPrivatesMap,
3073 std::end(CommonArgs));
3075 auto LBFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound);
3078 auto UBFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound);
3081 auto StFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTStride);
3084 auto LIFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLastIter);
3087 auto RFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTReductions);
3090 CallArgs.push_back(LBParam);
3091 CallArgs.push_back(UBParam);
3092 CallArgs.push_back(StParam);
3093 CallArgs.push_back(LIParam);
3094 CallArgs.push_back(RParam);
3096 CallArgs.push_back(SharedsParam);
3109 QualType KmpTaskTWithPrivatesPtrQTy,
3110 QualType KmpTaskTWithPrivatesQTy) {
3118 Args.push_back(&GtidArg);
3119 Args.push_back(&TaskTypeArg);
3120 const auto &DestructorFnInfo =
3122 llvm::FunctionType *DestructorFnTy =
3126 auto *DestructorFn =
3127 llvm::Function::Create(DestructorFnTy, llvm::GlobalValue::InternalLinkage,
3131 DestructorFn->setDoesNotRecurse();
3139 const auto *KmpTaskTWithPrivatesQTyRD =
3141 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin());
3143 for (
const auto *Field : FI->getType()->castAsRecordDecl()->fields()) {
3145 Field->getType().isDestructedType()) {
3147 CGF.
pushDestroy(DtorKind, FieldLValue.getAddress(), Field->getType());
3151 return DestructorFn;
3171 C,
nullptr, Loc,
nullptr,
3172 C.getPointerType(PrivatesQTy).withConst().withRestrict(),
3174 Args.push_back(&TaskPrivatesArg);
3175 llvm::DenseMap<CanonicalDeclPtr<const VarDecl>,
unsigned> PrivateVarsPos;
3176 unsigned Counter = 1;
3177 for (
const Expr *E :
Data.PrivateVars) {
3179 C,
nullptr, Loc,
nullptr,
3180 C.getPointerType(
C.getPointerType(E->
getType()))
3185 PrivateVarsPos[VD] = Counter;
3188 for (
const Expr *E :
Data.FirstprivateVars) {
3190 C,
nullptr, Loc,
nullptr,
3191 C.getPointerType(
C.getPointerType(E->
getType()))
3196 PrivateVarsPos[VD] = Counter;
3199 for (
const Expr *E :
Data.LastprivateVars) {
3201 C,
nullptr, Loc,
nullptr,
3202 C.getPointerType(
C.getPointerType(E->
getType()))
3207 PrivateVarsPos[VD] = Counter;
3213 Ty =
C.getPointerType(Ty);
3215 Ty =
C.getPointerType(Ty);
3217 C,
nullptr, Loc,
nullptr,
3218 C.getPointerType(
C.getPointerType(Ty)).withConst().withRestrict(),
3220 PrivateVarsPos[VD] = Counter;
3223 const auto &TaskPrivatesMapFnInfo =
3225 llvm::FunctionType *TaskPrivatesMapTy =
3229 auto *TaskPrivatesMap = llvm::Function::Create(
3230 TaskPrivatesMapTy, llvm::GlobalValue::InternalLinkage, Name,
3233 TaskPrivatesMapFnInfo);
3235 TaskPrivatesMap->removeFnAttr(llvm::Attribute::NoInline);
3236 TaskPrivatesMap->removeFnAttr(llvm::Attribute::OptimizeNone);
3237 TaskPrivatesMap->addFnAttr(llvm::Attribute::AlwaysInline);
3241 TaskPrivatesMapFnInfo, Args, Loc, Loc);
3249 for (
const FieldDecl *Field : PrivatesQTyRD->fields()) {
3251 const VarDecl *VD = Args[PrivateVarsPos[Privates[Counter].second.Original]];
3255 RefLVal.getAddress(), RefLVal.getType()->castAs<
PointerType>());
3260 return TaskPrivatesMap;
3266 Address KmpTaskSharedsPtr, LValue TDBase,
3272 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->
field_begin());
3286 if ((!IsTargetTask && !
Data.FirstprivateVars.empty() && ForDup) ||
3287 (IsTargetTask && KmpTaskSharedsPtr.
isValid())) {
3294 FI = FI->getType()->castAsRecordDecl()->field_begin();
3295 for (
const PrivateDataTy &Pair : Privates) {
3297 if (Pair.second.isLocalPrivate()) {
3301 const VarDecl *VD = Pair.second.PrivateCopy;
3306 if (
const VarDecl *Elem = Pair.second.PrivateElemInit) {
3307 const VarDecl *OriginalVD = Pair.second.Original;
3310 LValue SharedRefLValue;
3313 if (IsTargetTask && !SharedField) {
3317 ->getNumParams() == 0 &&
3320 ->getDeclContext()) &&
3321 "Expected artificial target data variable.");
3324 }
else if (ForDup) {
3327 SharedRefLValue.getAddress().withAlignment(
3328 C.getDeclAlign(OriginalVD)),
3330 SharedRefLValue.getTBAAInfo());
3332 Pair.second.Original->getCanonicalDecl()) > 0 ||
3334 SharedRefLValue = CGF.
EmitLValue(Pair.second.OriginalRef);
3337 InlinedOpenMPRegionRAII Region(
3340 SharedRefLValue = CGF.
EmitLValue(Pair.second.OriginalRef);
3351 PrivateLValue.getAddress(), SharedRefLValue.getAddress(),
Type,
3352 [&CGF, Elem,
Init, &CapturesInfo](
Address DestElement,
3355 CodeGenFunction::OMPPrivateScope InitScope(CGF);
3356 InitScope.addPrivate(Elem, SrcElement);
3357 (void)InitScope.Privatize();
3359 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(
3360 CGF, &CapturesInfo);
3361 CGF.EmitAnyExprToMem(Init, DestElement,
3362 Init->getType().getQualifiers(),
3368 InitScope.addPrivate(Elem, SharedRefLValue.getAddress());
3369 (void)InitScope.Privatize();
3385 bool InitRequired =
false;
3386 for (
const PrivateDataTy &Pair : Privates) {
3387 if (Pair.second.isLocalPrivate())
3389 const VarDecl *VD = Pair.second.PrivateCopy;
3391 InitRequired = InitRequired || (isa_and_nonnull<CXXConstructExpr>(
Init) &&
3396 return InitRequired;
3413 QualType KmpTaskTWithPrivatesPtrQTy,
3421 KmpTaskTWithPrivatesPtrQTy,
3424 KmpTaskTWithPrivatesPtrQTy,
3428 Args.push_back(&DstArg);
3429 Args.push_back(&SrcArg);
3430 Args.push_back(&LastprivArg);
3431 const auto &TaskDupFnInfo =
3435 auto *TaskDup = llvm::Function::Create(
3436 TaskDupTy, llvm::GlobalValue::InternalLinkage, Name, &CGM.
getModule());
3438 TaskDup->setDoesNotRecurse();
3448 auto LIFI = std::next(KmpTaskTQTyRD->
field_begin(), KmpTaskTLastIter);
3450 TDBase, *KmpTaskTWithPrivatesQTyRD->
field_begin());
3458 assert(!Privates.empty());
3460 if (!
Data.FirstprivateVars.empty()) {
3465 TDBase, *KmpTaskTWithPrivatesQTyRD->
field_begin());
3473 emitPrivatesInit(CGF, D, KmpTaskSharedsPtr, TDBase, KmpTaskTWithPrivatesQTyRD,
3474 SharedsTy, SharedsPtrTy,
Data, Privates,
true);
3484 for (
const PrivateDataTy &P : Privates) {
3485 if (P.second.isLocalPrivate())
3487 QualType Ty = P.second.Original->getType().getNonReferenceType();
3496class OMPIteratorGeneratorScope final
3498 CodeGenFunction &CGF;
3499 const OMPIteratorExpr *E =
nullptr;
3500 SmallVector<CodeGenFunction::JumpDest, 4> ContDests;
3501 SmallVector<CodeGenFunction::JumpDest, 4> ExitDests;
3502 OMPIteratorGeneratorScope() =
delete;
3503 OMPIteratorGeneratorScope(OMPIteratorGeneratorScope &) =
delete;
3506 OMPIteratorGeneratorScope(CodeGenFunction &CGF,
const OMPIteratorExpr *E)
3507 : CodeGenFunction::OMPPrivateScope(CGF), CGF(CGF), E(E) {
3510 SmallVector<llvm::Value *, 4> Uppers;
3512 Uppers.push_back(CGF.EmitScalarExpr(E->getHelper(I).Upper));
3513 const auto *VD = cast<VarDecl>(E->getIteratorDecl(I));
3514 addPrivate(VD, CGF.CreateMemTemp(VD->getType(), VD->getName()));
3515 const OMPIteratorHelperData &HelperData = E->getHelper(I);
3517 HelperData.CounterVD,
3518 CGF.CreateMemTemp(HelperData.CounterVD->getType(),
"counter.addr"));
3523 const OMPIteratorHelperData &HelperData = E->getHelper(I);
3525 CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(HelperData.CounterVD),
3526 HelperData.CounterVD->getType());
3528 CGF.EmitStoreOfScalar(
3529 llvm::ConstantInt::get(CLVal.getAddress().getElementType(), 0),
3531 CodeGenFunction::JumpDest &ContDest =
3532 ContDests.emplace_back(CGF.getJumpDestInCurrentScope(
"iter.cont"));
3533 CodeGenFunction::JumpDest &ExitDest =
3534 ExitDests.emplace_back(CGF.getJumpDestInCurrentScope(
"iter.exit"));
3536 llvm::Value *N = Uppers[I];
3539 CGF.EmitBlock(ContDest.getBlock());
3541 CGF.EmitLoadOfScalar(CLVal, HelperData.CounterVD->getLocation());
3543 HelperData.CounterVD->getType()->isSignedIntegerOrEnumerationType()
3544 ? CGF.Builder.CreateICmpSLT(CVal, N)
3545 : CGF.Builder.CreateICmpULT(CVal, N);
3546 llvm::BasicBlock *BodyBB = CGF.createBasicBlock(
"iter.body");
3547 CGF.Builder.CreateCondBr(Cmp, BodyBB, ExitDest.getBlock());
3549 CGF.EmitBlock(BodyBB);
3551 CGF.EmitIgnoredExpr(HelperData.Update);
3554 ~OMPIteratorGeneratorScope() {
3559 const OMPIteratorHelperData &HelperData = E->
getHelper(I - 1);
3564 CGF.
EmitBlock(ExitDests[I - 1].getBlock(), I == 1);
3570static std::pair<llvm::Value *, llvm::Value *>
3572 const auto *OASE = dyn_cast<OMPArrayShapingExpr>(E);
3575 const Expr *
Base = OASE->getBase();
3580 llvm::Value *SizeVal;
3583 SizeVal = CGF.
getTypeSize(OASE->getBase()->getType()->getPointeeType());
3584 for (
const Expr *SE : OASE->getDimensions()) {
3588 SizeVal = CGF.
Builder.CreateNUWMul(SizeVal, Sz);
3590 }
else if (
const auto *ASE =
3593 Address UpAddrAddress = UpAddrLVal.getAddress();
3594 llvm::Value *UpAddr = CGF.
Builder.CreateConstGEP1_32(
3598 llvm::Value *UpIntPtr = CGF.
Builder.CreatePtrToInt(UpAddr, CGF.
SizeTy);
3599 SizeVal = CGF.
Builder.CreateNUWSub(UpIntPtr, LowIntPtr);
3603 return std::make_pair(
Addr, SizeVal);
3608 QualType FlagsTy =
C.getIntTypeForBitwidth(32,
false);
3609 if (KmpTaskAffinityInfoTy.
isNull()) {
3611 C.buildImplicitRecord(
"kmp_task_affinity_info_t");
3617 KmpTaskAffinityInfoTy =
C.getCanonicalTagType(KmpAffinityInfoRD);
3624 llvm::Function *TaskFunction,
QualType SharedsTy,
3629 const auto *I =
Data.PrivateCopies.begin();
3630 for (
const Expr *E :
Data.PrivateVars) {
3632 Privates.emplace_back(
3638 I =
Data.FirstprivateCopies.begin();
3639 const auto *IElemInitRef =
Data.FirstprivateInits.begin();
3640 for (
const Expr *E :
Data.FirstprivateVars) {
3642 Privates.emplace_back(
3650 I =
Data.LastprivateCopies.begin();
3651 for (
const Expr *E :
Data.LastprivateVars) {
3653 Privates.emplace_back(
3661 Privates.emplace_back(
CGM.getPointerAlign(), PrivateHelpersTy(VD));
3663 Privates.emplace_back(
C.getDeclAlign(VD), PrivateHelpersTy(VD));
3665 llvm::stable_sort(Privates,
3666 [](
const PrivateDataTy &L,
const PrivateDataTy &R) {
3667 return L.first > R.first;
3669 QualType KmpInt32Ty =
C.getIntTypeForBitwidth(32, 1);
3680 assert((D.getDirectiveKind() == OMPD_task ||
3683 "Expected taskloop, task or target directive");
3690 const auto *KmpTaskTQTyRD =
KmpTaskTQTy->castAsRecordDecl();
3692 const RecordDecl *KmpTaskTWithPrivatesQTyRD =
3695 C.getCanonicalTagType(KmpTaskTWithPrivatesQTyRD);
3696 QualType KmpTaskTWithPrivatesPtrQTy =
3697 C.getPointerType(KmpTaskTWithPrivatesQTy);
3698 llvm::Type *KmpTaskTWithPrivatesPtrTy = CGF.
Builder.getPtrTy(0);
3699 llvm::Value *KmpTaskTWithPrivatesTySize =
3701 QualType SharedsPtrTy =
C.getPointerType(SharedsTy);
3704 llvm::Value *TaskPrivatesMap =
nullptr;
3705 llvm::Type *TaskPrivatesMapTy =
3706 std::next(TaskFunction->arg_begin(), 3)->getType();
3707 if (!Privates.empty()) {
3708 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->
field_begin());
3712 TaskPrivatesMap, TaskPrivatesMapTy);
3714 TaskPrivatesMap = llvm::ConstantPointerNull::get(
3720 CGM, Loc, D.getDirectiveKind(), KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy,
3721 KmpTaskTWithPrivatesQTy,
KmpTaskTQTy, SharedsPtrTy, TaskFunction,
3733 DestructorsFlag = 0x8,
3734 PriorityFlag = 0x20,
3735 DetachableFlag = 0x40,
3736 FreeAgentFlag = 0x80,
3738 unsigned Flags =
Data.Tied ? TiedFlag : 0;
3739 bool NeedsCleanup =
false;
3740 if (!Privates.empty()) {
3744 Flags = Flags | DestructorsFlag;
3748 if (Kind == OMPC_THREADSET_omp_pool)
3749 Flags = Flags | FreeAgentFlag;
3751 if (
Data.Priority.getInt())
3752 Flags = Flags | PriorityFlag;
3754 Flags = Flags | DetachableFlag;
3755 llvm::Value *TaskFlags =
3756 Data.Final.getPointer()
3757 ? CGF.
Builder.CreateSelect(
Data.Final.getPointer(),
3758 CGF.
Builder.getInt32(FinalFlag),
3760 : CGF.
Builder.getInt32(
Data.Final.getInt() ? FinalFlag : 0);
3761 TaskFlags = CGF.
Builder.CreateOr(TaskFlags, CGF.
Builder.getInt32(Flags));
3762 llvm::Value *SharedsSize =
CGM.getSize(
C.getTypeSizeInChars(SharedsTy));
3764 getThreadID(CGF, Loc), TaskFlags, KmpTaskTWithPrivatesTySize,
3767 llvm::Value *NewTask;
3774 llvm::Value *DeviceID;
3779 DeviceID = CGF.
Builder.getInt64(OMP_DEVICEID_UNDEF);
3780 AllocArgs.push_back(DeviceID);
3783 CGM.getModule(), OMPRTL___kmpc_omp_target_task_alloc),
3788 CGM.getModule(), OMPRTL___kmpc_omp_task_alloc),
3801 llvm::Value *Tid =
getThreadID(CGF, DC->getBeginLoc());
3802 Tid = CGF.
Builder.CreateIntCast(Tid, CGF.
IntTy,
false);
3805 CGM.getModule(), OMPRTL___kmpc_task_allow_completion_event),
3806 {Loc, Tid, NewTask});
3817 llvm::Value *NumOfElements =
nullptr;
3818 unsigned NumAffinities = 0;
3820 if (
const Expr *Modifier =
C->getModifier()) {
3822 for (
unsigned I = 0, E = IE->numOfIterators(); I < E; ++I) {
3826 NumOfElements ? CGF.
Builder.CreateNUWMul(NumOfElements, Sz) : Sz;
3829 NumAffinities +=
C->varlist_size();
3834 enum RTLAffinityInfoFieldsTy { BaseAddr, Len, Flags };
3836 QualType KmpTaskAffinityInfoArrayTy;
3837 if (NumOfElements) {
3838 NumOfElements = CGF.
Builder.CreateNUWAdd(
3839 llvm::ConstantInt::get(CGF.
SizeTy, NumAffinities), NumOfElements);
3842 C.getIntTypeForBitwidth(
C.getTypeSize(
C.getSizeType()), 0),
3846 KmpTaskAffinityInfoArrayTy =
C.getVariableArrayType(
3854 NumOfElements = CGF.
Builder.CreateIntCast(NumOfElements, CGF.
Int32Ty,
3857 KmpTaskAffinityInfoArrayTy =
C.getConstantArrayType(
3859 llvm::APInt(
C.getTypeSize(
C.getSizeType()), NumAffinities),
nullptr,
3862 CGF.
CreateMemTemp(KmpTaskAffinityInfoArrayTy,
".affs.arr.addr");
3864 NumOfElements = llvm::ConstantInt::get(
CGM.Int32Ty, NumAffinities,
3871 bool HasIterator =
false;
3873 if (
C->getModifier()) {
3877 for (
const Expr *E :
C->varlist()) {
3886 Base, *std::next(KmpAffinityInfoRD->field_begin(), BaseAddr));
3891 Base, *std::next(KmpAffinityInfoRD->field_begin(), Len));
3905 const Expr *Modifier =
C->getModifier();
3908 OMPIteratorGeneratorScope IteratorScope(
3910 for (
const Expr *E :
C->varlist()) {
3920 Base, *std::next(KmpAffinityInfoRD->field_begin(), BaseAddr));
3925 Base, *std::next(KmpAffinityInfoRD->field_begin(), Len));
3927 Idx = CGF.
Builder.CreateNUWAdd(
3928 Idx, llvm::ConstantInt::get(Idx->getType(), 1));
3943 CGM.getModule(), OMPRTL___kmpc_omp_reg_task_with_affinity),
3944 {LocRef, GTid, NewTask, NumOfElements, AffinListPtr});
3946 llvm::Value *NewTaskNewTaskTTy =
3948 NewTask, KmpTaskTWithPrivatesPtrTy);
3950 KmpTaskTWithPrivatesQTy);
3961 *std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTShareds)),
3963 CGF.
Int8Ty,
CGM.getNaturalTypeAlignment(SharedsTy));
3970 if (!Privates.empty()) {
3972 SharedsTy, SharedsPtrTy,
Data, Privates,
3977 CGM, Loc, D, KmpTaskTWithPrivatesPtrQTy, KmpTaskTWithPrivatesQTyRD,
3978 KmpTaskTQTyRD, SharedsTy, SharedsPtrTy,
Data, Privates,
3979 !
Data.LastprivateVars.empty());
3983 enum { Priority = 0, Destructors = 1 };
3985 auto FI = std::next(KmpTaskTQTyRD->field_begin(), Data1);
3986 const auto *KmpCmplrdataUD = (*FI)->getType()->castAsRecordDecl();
3987 assert(KmpCmplrdataUD->isUnion());
3990 CGM, Loc, KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy,
3991 KmpTaskTWithPrivatesQTy);
3994 Data1LV, *std::next(KmpCmplrdataUD->field_begin(), Destructors));
4000 if (
Data.Priority.getInt()) {
4002 TDBase, *std::next(KmpTaskTQTyRD->field_begin(), Data2));
4004 Data2LV, *std::next(KmpCmplrdataUD->field_begin(), Priority));
4007 Result.NewTask = NewTask;
4008 Result.TaskEntry = TaskEntry;
4009 Result.NewTaskNewTaskTTy = NewTaskNewTaskTTy;
4011 Result.KmpTaskTQTyRD = KmpTaskTQTyRD;
4017 RTLDependenceKindTy DepKind;
4019 case OMPC_DEPEND_in:
4020 DepKind = RTLDependenceKindTy::DepIn;
4023 case OMPC_DEPEND_out:
4024 case OMPC_DEPEND_inout:
4025 DepKind = RTLDependenceKindTy::DepInOut;
4027 case OMPC_DEPEND_mutexinoutset:
4028 DepKind = RTLDependenceKindTy::DepMutexInOutSet;
4030 case OMPC_DEPEND_inoutset:
4031 DepKind = RTLDependenceKindTy::DepInOutSet;
4033 case OMPC_DEPEND_outallmemory:
4034 DepKind = RTLDependenceKindTy::DepOmpAllMem;
4036 case OMPC_DEPEND_source:
4037 case OMPC_DEPEND_sink:
4038 case OMPC_DEPEND_depobj:
4039 case OMPC_DEPEND_inoutallmemory:
4041 llvm_unreachable(
"Unknown task dependence type");
4049 FlagsTy =
C.getIntTypeForBitwidth(
C.getTypeSize(
C.BoolTy),
false);
4050 if (KmpDependInfoTy.
isNull()) {
4051 RecordDecl *KmpDependInfoRD =
C.buildImplicitRecord(
"kmp_depend_info");
4057 KmpDependInfoTy =
C.getCanonicalTagType(KmpDependInfoRD);
4061std::pair<llvm::Value *, LValue>
4074 CGF,
Base.getAddress(),
4075 llvm::ConstantInt::get(CGF.
IntPtrTy, -1,
true));
4081 *std::next(KmpDependInfoRD->field_begin(),
4082 static_cast<unsigned int>(RTLDependInfoFields::BaseAddr)));
4084 return std::make_pair(NumDeps,
Base);
4088 llvm::PointerUnion<unsigned *, LValue *> Pos,
4098 OMPIteratorGeneratorScope IteratorScope(
4099 CGF, cast_or_null<OMPIteratorExpr>(
4100 Data.IteratorExpr ?
Data.IteratorExpr->IgnoreParenImpCasts()
4102 for (
const Expr *E :
Data.DepExprs) {
4112 Size = llvm::ConstantInt::get(CGF.
SizeTy, 0);
4115 if (
unsigned *P = dyn_cast<unsigned *>(Pos)) {
4119 assert(E &&
"Expected a non-null expression");
4128 *std::next(KmpDependInfoRD->field_begin(),
4129 static_cast<unsigned int>(RTLDependInfoFields::BaseAddr)));
4133 Base, *std::next(KmpDependInfoRD->field_begin(),
4134 static_cast<unsigned int>(RTLDependInfoFields::Len)));
4140 *std::next(KmpDependInfoRD->field_begin(),
4141 static_cast<unsigned int>(RTLDependInfoFields::Flags)));
4143 llvm::ConstantInt::get(LLVMFlagsTy,
static_cast<unsigned int>(DepKind)),
4145 if (
unsigned *P = dyn_cast<unsigned *>(Pos)) {
4150 Idx = CGF.
Builder.CreateNUWAdd(Idx,
4151 llvm::ConstantInt::get(Idx->getType(), 1));
4160 assert(
Data.DepKind == OMPC_DEPEND_depobj &&
4161 "Expected depobj dependency kind.");
4166 OMPIteratorGeneratorScope IteratorScope(
4167 CGF, cast_or_null<OMPIteratorExpr>(
4168 Data.IteratorExpr ?
Data.IteratorExpr->IgnoreParenImpCasts()
4170 for (
const Expr *E :
Data.DepExprs) {
4171 llvm::Value *NumDeps;
4174 std::tie(NumDeps,
Base) =
4178 C.getUIntPtrType());
4182 llvm::Value *Add = CGF.
Builder.CreateNUWAdd(PrevVal, NumDeps);
4184 SizeLVals.push_back(NumLVal);
4187 for (
unsigned I = 0, E = SizeLVals.size(); I < E; ++I) {
4190 Sizes.push_back(Size);
4200 assert(
Data.DepKind == OMPC_DEPEND_depobj &&
4201 "Expected depobj dependency kind.");
4204 OMPIteratorGeneratorScope IteratorScope(
4205 CGF, cast_or_null<OMPIteratorExpr>(
4206 Data.IteratorExpr ?
Data.IteratorExpr->IgnoreParenImpCasts()
4208 for (
const Expr *E :
Data.DepExprs) {
4209 llvm::Value *NumDeps;
4212 std::tie(NumDeps,
Base) =
4216 llvm::Value *Size = CGF.
Builder.CreateNUWMul(
4225 llvm::Value *Add = CGF.
Builder.CreateNUWAdd(Pos, NumDeps);
4241 llvm::Value *NumOfElements =
nullptr;
4242 unsigned NumDependencies = std::accumulate(
4243 Dependencies.begin(), Dependencies.end(), 0,
4245 return D.DepKind == OMPC_DEPEND_depobj
4247 : (V + (D.IteratorExpr ? 0 : D.DepExprs.size()));
4251 bool HasDepobjDeps =
false;
4252 bool HasRegularWithIterators =
false;
4253 llvm::Value *NumOfDepobjElements = llvm::ConstantInt::get(CGF.
IntPtrTy, 0);
4254 llvm::Value *NumOfRegularWithIterators =
4255 llvm::ConstantInt::get(CGF.
IntPtrTy, 0);
4259 if (D.
DepKind == OMPC_DEPEND_depobj) {
4262 for (llvm::Value *Size : Sizes) {
4263 NumOfDepobjElements =
4264 CGF.
Builder.CreateNUWAdd(NumOfDepobjElements, Size);
4266 HasDepobjDeps =
true;
4271 if (
const auto *IE = cast_or_null<OMPIteratorExpr>(D.
IteratorExpr)) {
4272 llvm::Value *ClauseIteratorSpace =
4273 llvm::ConstantInt::get(CGF.
IntPtrTy, 1);
4277 ClauseIteratorSpace = CGF.
Builder.CreateNUWMul(Sz, ClauseIteratorSpace);
4279 llvm::Value *NumClauseDeps = CGF.
Builder.CreateNUWMul(
4280 ClauseIteratorSpace,
4282 NumOfRegularWithIterators =
4283 CGF.
Builder.CreateNUWAdd(NumOfRegularWithIterators, NumClauseDeps);
4284 HasRegularWithIterators =
true;
4290 if (HasDepobjDeps || HasRegularWithIterators) {
4291 NumOfElements = llvm::ConstantInt::get(
CGM.IntPtrTy, NumDependencies,
4293 if (HasDepobjDeps) {
4295 CGF.
Builder.CreateNUWAdd(NumOfDepobjElements, NumOfElements);
4297 if (HasRegularWithIterators) {
4299 CGF.
Builder.CreateNUWAdd(NumOfRegularWithIterators, NumOfElements);
4302 Loc,
C.getIntTypeForBitwidth(64, 0),
4306 KmpDependInfoArrayTy =
4315 NumOfElements = CGF.
Builder.CreateIntCast(NumOfElements, CGF.
Int32Ty,
4318 KmpDependInfoArrayTy =
C.getConstantArrayType(
4324 NumOfElements = llvm::ConstantInt::get(
CGM.Int32Ty, NumDependencies,
4329 if (Dep.DepKind == OMPC_DEPEND_depobj || Dep.IteratorExpr)
4335 CGF.
CreateMemTemp(
C.getSizeType(),
"dep.counter.addr"),
C.getSizeType());
4338 if (Dep.DepKind == OMPC_DEPEND_depobj || !Dep.IteratorExpr)
4343 if (HasDepobjDeps) {
4345 if (Dep.DepKind != OMPC_DEPEND_depobj)
4352 return std::make_pair(NumOfElements, DependenciesArray);
4363 unsigned NumDependencies = Dependencies.
DepExprs.size();
4373 llvm::Value *NumDepsVal;
4375 if (
const auto *IE =
4376 cast_or_null<OMPIteratorExpr>(Dependencies.
IteratorExpr)) {
4377 NumDepsVal = llvm::ConstantInt::get(CGF.
SizeTy, 1);
4381 NumDepsVal = CGF.
Builder.CreateNUWMul(NumDepsVal, Sz);
4383 Size = CGF.
Builder.CreateNUWAdd(llvm::ConstantInt::get(CGF.
SizeTy, 1),
4387 llvm::Value *RecSize =
CGM.getSize(SizeInBytes);
4388 Size = CGF.
Builder.CreateNUWMul(Size, RecSize);
4392 QualType KmpDependInfoArrayTy =
C.getConstantArrayType(
4395 CharUnits Sz =
C.getTypeSizeInChars(KmpDependInfoArrayTy);
4397 NumDepsVal = llvm::ConstantInt::get(CGF.
IntPtrTy, NumDependencies);
4402 llvm::Value *Allocator = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
4403 llvm::Value *Args[] = {ThreadID, Size, Allocator};
4407 CGM.getModule(), OMPRTL___kmpc_alloc),
4408 Args,
".dep.arr.addr");
4412 DependenciesArray =
Address(
Addr, KmpDependInfoLlvmTy, Align);
4418 *std::next(KmpDependInfoRD->field_begin(),
4419 static_cast<unsigned int>(RTLDependInfoFields::BaseAddr)));
4421 llvm::PointerUnion<unsigned *, LValue *> Pos;
4438 return DependenciesArray;
4453 Addr.getElementType(),
Addr.emitRawPointer(CGF),
4454 llvm::ConstantInt::get(CGF.
IntPtrTy, -1,
true));
4459 llvm::Value *Allocator = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
4460 llvm::Value *Args[] = {ThreadID, DepObjAddr, Allocator};
4464 CGM.getModule(), OMPRTL___kmpc_free),
4476 llvm::Value *NumDeps;
4487 llvm::BasicBlock *EntryBB = CGF.
Builder.GetInsertBlock();
4489 llvm::PHINode *ElementPHI =
4494 Base.getTBAAInfo());
4498 Base, *std::next(KmpDependInfoRD->field_begin(),
4499 static_cast<unsigned int>(RTLDependInfoFields::Flags)));
4501 llvm::ConstantInt::get(LLVMFlagsTy,
static_cast<unsigned int>(DepKind)),
4505 llvm::Value *ElementNext =
4508 ElementPHI->addIncoming(ElementNext, CGF.
Builder.GetInsertBlock());
4509 llvm::Value *IsEmpty =
4510 CGF.
Builder.CreateICmpEQ(ElementNext, End,
"omp.isempty");
4511 CGF.
Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
4518 llvm::Function *TaskFunction,
4527 llvm::Value *NewTask =
Result.NewTask;
4528 llvm::Function *TaskEntry =
Result.TaskEntry;
4529 llvm::Value *NewTaskNewTaskTTy =
Result.NewTaskNewTaskTTy;
4534 llvm::Value *NumOfElements;
4535 std::tie(NumOfElements, DependenciesArray) =
4546 llvm::Value *TaskArgs[] = { UpLoc, ThreadID, NewTask };
4547 llvm::Value *DepTaskArgs[7];
4548 if (!
Data.Dependences.empty()) {
4549 DepTaskArgs[0] = UpLoc;
4550 DepTaskArgs[1] = ThreadID;
4551 DepTaskArgs[2] = NewTask;
4552 DepTaskArgs[3] = NumOfElements;
4554 DepTaskArgs[5] = CGF.
Builder.getInt32(0);
4555 DepTaskArgs[6] = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
4557 auto &&ThenCodeGen = [
this, &
Data, TDBase, KmpTaskTQTyRD, &TaskArgs,
4560 auto PartIdFI = std::next(KmpTaskTQTyRD->
field_begin(), KmpTaskTPartId);
4564 if (!
Data.Dependences.empty()) {
4567 CGM.getModule(), OMPRTL___kmpc_omp_task_with_deps),
4571 CGM.getModule(), OMPRTL___kmpc_omp_task),
4577 Region->emitUntiedSwitch(CGF);
4580 llvm::Value *DepWaitTaskArgs[7];
4581 if (!
Data.Dependences.empty()) {
4582 DepWaitTaskArgs[0] = UpLoc;
4583 DepWaitTaskArgs[1] = ThreadID;
4584 DepWaitTaskArgs[2] = NumOfElements;
4586 DepWaitTaskArgs[4] = CGF.
Builder.getInt32(0);
4587 DepWaitTaskArgs[5] = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
4588 DepWaitTaskArgs[6] =
4589 llvm::ConstantInt::get(CGF.
Int32Ty,
Data.HasNowaitClause);
4591 auto &M =
CGM.getModule();
4592 auto &&ElseCodeGen = [
this, &M, &TaskArgs, ThreadID, NewTaskNewTaskTTy,
4593 TaskEntry, &
Data, &DepWaitTaskArgs,
4600 if (!
Data.Dependences.empty())
4602 M, OMPRTL___kmpc_omp_taskwait_deps_51),
4605 auto &&
CodeGen = [TaskEntry, ThreadID, NewTaskNewTaskTTy,
4608 llvm::Value *OutlinedFnArgs[] = {ThreadID, NewTaskNewTaskTTy};
4609 CGF.CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, Loc, TaskEntry,
4618 CommonActionTy Action(
OMPBuilder.getOrCreateRuntimeFunction(
4619 M, OMPRTL___kmpc_omp_task_begin_if0),
4622 M, OMPRTL___kmpc_omp_task_complete_if0),
4638 llvm::Function *TaskFunction,
4658 IfVal = llvm::ConstantInt::getSigned(CGF.
IntTy, 1);
4663 *std::next(
Result.KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound));
4670 *std::next(
Result.KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound));
4677 *std::next(
Result.KmpTaskTQTyRD->field_begin(), KmpTaskTStride));
4685 *std::next(
Result.KmpTaskTQTyRD->field_begin(), KmpTaskTReductions));
4686 if (
Data.Reductions) {
4692 enum { NoSchedule = 0, Grainsize = 1, NumTasks = 2 };
4701 llvm::ConstantInt::getSigned(
4703 llvm::ConstantInt::getSigned(
4705 ?
Data.Schedule.getInt() ? NumTasks : Grainsize
4707 Data.Schedule.getPointer()
4710 : llvm::ConstantInt::get(CGF.
Int64Ty, 0)};
4711 if (
Data.HasModifier)
4712 TaskArgs.push_back(llvm::ConstantInt::get(CGF.
Int32Ty, 1));
4714 TaskArgs.push_back(
Result.TaskDupFn
4717 : llvm::ConstantPointerNull::get(CGF.
VoidPtrTy));
4719 CGM.getModule(),
Data.HasModifier
4720 ? OMPRTL___kmpc_taskloop_5
4721 : OMPRTL___kmpc_taskloop),
4738 const Expr *,
const Expr *)> &RedOpGen,
4739 const Expr *XExpr =
nullptr,
const Expr *EExpr =
nullptr,
4740 const Expr *UpExpr =
nullptr) {
4748 llvm::Value *NumElements = CGF.
emitArrayLength(ArrayTy, ElementTy, LHSAddr);
4753 llvm::Value *LHSEnd =
4758 llvm::Value *IsEmpty =
4759 CGF.
Builder.CreateICmpEQ(LHSBegin, LHSEnd,
"omp.arraycpy.isempty");
4760 CGF.
Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
4763 llvm::BasicBlock *EntryBB = CGF.
Builder.GetInsertBlock();
4768 llvm::PHINode *RHSElementPHI = CGF.
Builder.CreatePHI(
4769 RHSBegin->getType(), 2,
"omp.arraycpy.srcElementPast");
4770 RHSElementPHI->addIncoming(RHSBegin, EntryBB);
4775 llvm::PHINode *LHSElementPHI = CGF.
Builder.CreatePHI(
4776 LHSBegin->getType(), 2,
"omp.arraycpy.destElementPast");
4777 LHSElementPHI->addIncoming(LHSBegin, EntryBB);
4784 Scope.addPrivate(LHSVar, LHSElementCurrent);
4785 Scope.addPrivate(RHSVar, RHSElementCurrent);
4787 RedOpGen(CGF, XExpr, EExpr, UpExpr);
4788 Scope.ForceCleanup();
4791 llvm::Value *LHSElementNext = CGF.
Builder.CreateConstGEP1_32(
4793 "omp.arraycpy.dest.element");
4794 llvm::Value *RHSElementNext = CGF.
Builder.CreateConstGEP1_32(
4796 "omp.arraycpy.src.element");
4799 CGF.
Builder.CreateICmpEQ(LHSElementNext, LHSEnd,
"omp.arraycpy.done");
4800 CGF.
Builder.CreateCondBr(Done, DoneBB, BodyBB);
4801 LHSElementPHI->addIncoming(LHSElementNext, CGF.
Builder.GetInsertBlock());
4802 RHSElementPHI->addIncoming(RHSElementNext, CGF.
Builder.GetInsertBlock());
4812 const Expr *ReductionOp) {
4813 if (
const auto *CE = dyn_cast<CallExpr>(ReductionOp))
4814 if (
const auto *OVE = dyn_cast<OpaqueValueExpr>(CE->getCallee()))
4815 if (
const auto *DRE =
4816 dyn_cast<DeclRefExpr>(OVE->getSourceExpr()->IgnoreImpCasts()))
4817 if (
const auto *DRD =
4818 dyn_cast<OMPDeclareReductionDecl>(DRE->getDecl())) {
4819 std::pair<llvm::Function *, llvm::Function *>
Reduction =
4830 StringRef ReducerName,
SourceLocation Loc, llvm::Type *ArgsElemType,
4841 Args.push_back(&LHSArg);
4842 Args.push_back(&RHSArg);
4844 CGM.getTypes().arrangeBuiltinFunctionDeclaration(
C.VoidTy, Args);
4846 auto *Fn = llvm::Function::Create(
CGM.getTypes().GetFunctionType(CGFI),
4847 llvm::GlobalValue::InternalLinkage, Name,
4850 Fn->setDoesNotRecurse();
4869 const auto *IPriv = Privates.begin();
4871 for (
unsigned I = 0, E = ReductionOps.size(); I < E; ++I, ++IPriv, ++Idx) {
4872 const auto *RHSVar =
4875 const auto *LHSVar =
4878 QualType PrivTy = (*IPriv)->getType();
4893 IPriv = Privates.begin();
4894 const auto *ILHS = LHSExprs.begin();
4895 const auto *IRHS = RHSExprs.begin();
4896 for (
const Expr *E : ReductionOps) {
4897 if ((*IPriv)->getType()->isArrayType()) {
4902 CGF, (*IPriv)->getType(), LHSVar, RHSVar,
4904 emitReductionCombiner(CGF, E);
4914 Scope.ForceCleanup();
4920 const Expr *ReductionOp,
4921 const Expr *PrivateRef,
4929 CGF, PrivateRef->
getType(), LHSVar, RHSVar,
4931 emitReductionCombiner(CGF, ReductionOp);
4940 llvm::StringRef Prefix,
const Expr *Ref);
4944 const Expr *LHSExprs,
const Expr *RHSExprs,
const Expr *ReductionOps) {
4971 std::string ReductionVarNameStr;
4973 ReductionVarNameStr =
4976 ReductionVarNameStr =
"unnamed_priv_var";
4979 std::string SharedName =
4980 CGM.getOpenMPRuntime().getName({
"internal_pivate_", ReductionVarNameStr});
4981 llvm::GlobalVariable *SharedVar =
OMPBuilder.getOrCreateInternalVariable(
4982 LLVMType,
".omp.reduction." + SharedName);
4984 SharedVar->setAlignment(
4992 llvm::Value *BarrierArgs[] = {BarrierLoc, ThreadId};
4997 llvm::Value *IsWorker = CGF.
Builder.CreateICmpEQ(
4998 ThreadId, llvm::ConstantInt::get(ThreadId->getType(), 0));
4999 CGF.
Builder.CreateCondBr(IsWorker, InitBB, InitEndBB);
5003 auto EmitSharedInit = [&]() {
5006 std::pair<llvm::Function *, llvm::Function *> FnPair =
5008 llvm::Function *InitializerFn = FnPair.second;
5009 if (InitializerFn) {
5010 if (
const auto *CE =
5011 dyn_cast<CallExpr>(UDRInitExpr->IgnoreParenImpCasts())) {
5018 LocalScope.addPrivate(OutVD, SharedResult);
5020 (void)LocalScope.Privatize();
5021 if (
const auto *OVE = dyn_cast<OpaqueValueExpr>(
5022 CE->getCallee()->IgnoreParenImpCasts())) {
5048 if (
const auto *DRE = dyn_cast<DeclRefExpr>(Privates)) {
5049 if (
const auto *VD = dyn_cast<VarDecl>(DRE->getDecl())) {
5060 CGF.
Builder.CreateBr(InitEndBB);
5064 CGM.getModule(), OMPRTL___kmpc_barrier),
5067 const Expr *ReductionOp = ReductionOps;
5072 auto EmitCriticalReduction = [&](
auto ReductionGen) {
5073 std::string CriticalName =
getName({
"reduction_critical"});
5081 std::pair<llvm::Function *, llvm::Function *> FnPair =
5084 if (
const auto *CE = dyn_cast<CallExpr>(ReductionOp)) {
5096 (void)LocalScope.Privatize();
5101 EmitCriticalReduction(ReductionGen);
5106 if (
const auto *Cleanup = dyn_cast<ExprWithCleanups>(ReductionClauseExpr))
5109 const Expr *AssignRHS =
nullptr;
5110 if (
const auto *BinOp = dyn_cast<BinaryOperator>(ReductionClauseExpr)) {
5111 if (BinOp->getOpcode() == BO_Assign)
5112 AssignRHS = BinOp->getRHS();
5113 }
else if (
const auto *OpCall =
5114 dyn_cast<CXXOperatorCallExpr>(ReductionClauseExpr)) {
5115 if (OpCall->getOperator() == OO_Equal)
5116 AssignRHS = OpCall->getArg(1);
5120 "Private Variable Reduction : Invalid ReductionOp expression");
5125 const auto *OmpOutDRE =
5127 const auto *OmpInDRE =
5130 OmpOutDRE && OmpInDRE &&
5131 "Private Variable Reduction : LHSExpr/RHSExpr must be DeclRefExprs");
5135 LocalScope.addPrivate(OmpOutVD, SharedLV.
getAddress());
5136 LocalScope.addPrivate(OmpInVD, LHSLV.
getAddress());
5137 (void)LocalScope.Privatize();
5141 EmitCriticalReduction(ReductionGen);
5145 CGM.getModule(), OMPRTL___kmpc_barrier),
5151 llvm::Value *FinalResultVal =
nullptr;
5155 FinalResultAddr = SharedResult;
5169 CGM.getModule(), OMPRTL___kmpc_barrier),
5180 EmitCriticalReduction(OriginalListCombiner);
5232 if (SimpleReduction) {
5234 const auto *IPriv = OrgPrivates.begin();
5235 const auto *ILHS = OrgLHSExprs.begin();
5236 const auto *IRHS = OrgRHSExprs.begin();
5237 for (
const Expr *E : OrgReductionOps) {
5250 FilteredRHSExprs, FilteredReductionOps;
5251 for (
unsigned I : llvm::seq<unsigned>(
5252 std::min(OrgReductionOps.size(), OrgLHSExprs.size()))) {
5254 FilteredPrivates.emplace_back(OrgPrivates[I]);
5255 FilteredLHSExprs.emplace_back(OrgLHSExprs[I]);
5256 FilteredRHSExprs.emplace_back(OrgRHSExprs[I]);
5257 FilteredReductionOps.emplace_back(OrgReductionOps[I]);
5269 auto Size = RHSExprs.size();
5270 for (
const Expr *E : Privates) {
5275 llvm::APInt ArraySize(32, Size);
5276 QualType ReductionArrayTy =
C.getConstantArrayType(
5280 CGF.
CreateMemTemp(ReductionArrayTy,
".omp.reduction.red_list");
5281 const auto *IPriv = Privates.begin();
5283 for (
unsigned I = 0, E = RHSExprs.size(); I < E; ++I, ++IPriv, ++Idx) {
5289 if ((*IPriv)->getType()->isVariablyModifiedType()) {
5293 llvm::Value *Size = CGF.
Builder.CreateIntCast(
5306 Privates, LHSExprs, RHSExprs, ReductionOps);
5309 std::string Name =
getName({
"reduction"});
5316 llvm::Value *ReductionArrayTySize = CGF.
getTypeSize(ReductionArrayTy);
5319 llvm::Value *Args[] = {
5322 CGF.
Builder.getInt32(RHSExprs.size()),
5323 ReductionArrayTySize,
5331 WithNowait ? OMPRTL___kmpc_reduce_nowait : OMPRTL___kmpc_reduce),
5335 llvm::BasicBlock *DefaultBB = CGF.
createBasicBlock(
".omp.reduction.default");
5336 llvm::SwitchInst *SwInst =
5337 CGF.
Builder.CreateSwitch(Res, DefaultBB, 2);
5346 SwInst->addCase(CGF.
Builder.getInt32(1), Case1BB);
5350 llvm::Value *EndArgs[] = {
5355 auto &&
CodeGen = [Privates, LHSExprs, RHSExprs, ReductionOps](
5358 const auto *IPriv = Privates.begin();
5359 const auto *ILHS = LHSExprs.begin();
5360 const auto *IRHS = RHSExprs.begin();
5361 for (
const Expr *E : ReductionOps) {
5370 CommonActionTy Action(
5373 CGM.getModule(), WithNowait ? OMPRTL___kmpc_end_reduce_nowait
5374 : OMPRTL___kmpc_end_reduce),
5387 SwInst->addCase(CGF.
Builder.getInt32(2), Case2BB);
5390 auto &&AtomicCodeGen = [Loc, Privates, LHSExprs, RHSExprs, ReductionOps](
5392 const auto *ILHS = LHSExprs.begin();
5393 const auto *IRHS = RHSExprs.begin();
5394 const auto *IPriv = Privates.begin();
5395 for (
const Expr *E : ReductionOps) {
5396 const Expr *XExpr =
nullptr;
5397 const Expr *EExpr =
nullptr;
5398 const Expr *UpExpr =
nullptr;
5400 if (
const auto *BO = dyn_cast<BinaryOperator>(E)) {
5401 if (BO->getOpcode() == BO_Assign) {
5402 XExpr = BO->getLHS();
5403 UpExpr = BO->getRHS();
5407 const Expr *RHSExpr = UpExpr;
5410 if (
const auto *ACO = dyn_cast<AbstractConditionalOperator>(
5414 RHSExpr = ACO->getCond();
5416 if (
const auto *BORHS =
5418 EExpr = BORHS->getRHS();
5419 BO = BORHS->getOpcode();
5424 auto &&AtomicRedGen = [BO, VD,
5426 const Expr *EExpr,
const Expr *UpExpr) {
5427 LValue X = CGF.EmitLValue(XExpr);
5430 E = CGF.EmitAnyExpr(EExpr);
5431 CGF.EmitOMPAtomicSimpleUpdateExpr(
5433 llvm::AtomicOrdering::Monotonic, Loc,
5434 [&CGF, UpExpr, VD, Loc](
RValue XRValue) {
5436 Address LHSTemp = CGF.CreateMemTemp(VD->getType());
5437 CGF.emitOMPSimpleStore(
5438 CGF.MakeAddrLValue(LHSTemp, VD->
getType()), XRValue,
5439 VD->getType().getNonReferenceType(), Loc);
5442 return CGF.EmitAnyExpr(UpExpr);
5445 if ((*IPriv)->getType()->isArrayType()) {
5447 const auto *RHSVar =
5450 AtomicRedGen, XExpr, EExpr, UpExpr);
5453 AtomicRedGen(CGF, XExpr, EExpr, UpExpr);
5460 std::string Name = RT.
getName({
"atomic_reduction"});
5469 if ((*IPriv)->getType()->isArrayType()) {
5470 const auto *LHSVar =
5472 const auto *RHSVar =
5477 CritRedGen(CGF,
nullptr,
nullptr,
nullptr);
5488 llvm::Value *EndArgs[] = {
5493 CommonActionTy Action(
nullptr, {},
5495 CGM.getModule(), OMPRTL___kmpc_end_reduce),
5505 assert(OrgLHSExprs.size() == OrgPrivates.size() &&
5506 "PrivateVarReduction: Privates size mismatch");
5507 assert(OrgLHSExprs.size() == OrgReductionOps.size() &&
5508 "PrivateVarReduction: ReductionOps size mismatch");
5509 for (
unsigned I : llvm::seq<unsigned>(
5510 std::min(OrgReductionOps.size(), OrgLHSExprs.size()))) {
5513 OrgRHSExprs[I], OrgReductionOps[I]);
5522 llvm::raw_svector_ostream Out(Buffer);
5530 Out << Prefix << Name <<
"_"
5532 return std::string(Out.str());
5554 Args.emplace_back(&Param);
5555 Args.emplace_back(&ParamOrig);
5556 const auto &FnInfo =
5560 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
5563 Fn->setDoesNotRecurse();
5570 llvm::Value *Size =
nullptr;
5613 const Expr *ReductionOp,
5615 const Expr *PrivateRef) {
5624 Args.emplace_back(&ParamInOut);
5625 Args.emplace_back(&ParamIn);
5626 const auto &FnInfo =
5630 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
5633 Fn->setDoesNotRecurse();
5636 llvm::Value *Size =
nullptr;
5657 C.getPointerType(LHSVD->getType())->castAs<
PointerType>()));
5664 C.getPointerType(RHSVD->getType())->castAs<
PointerType>()));
5693 Args.emplace_back(&Param);
5694 const auto &FnInfo =
5698 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
5701 Fn->setDoesNotRecurse();
5706 llvm::Value *Size =
nullptr;
5741 RecordDecl *RD =
C.buildImplicitRecord(
"kmp_taskred_input_t");
5750 C, RD,
C.getIntTypeForBitwidth(32,
false));
5753 unsigned Size =
Data.ReductionVars.size();
5754 llvm::APInt ArraySize(64, Size);
5756 C.getConstantArrayType(RDType, ArraySize,
nullptr,
5761 Data.ReductionCopies,
Data.ReductionOps);
5762 for (
unsigned Cnt = 0; Cnt < Size; ++Cnt) {
5764 llvm::Value *Idxs[] = {llvm::ConstantInt::get(
CGM.SizeTy, 0),
5765 llvm::ConstantInt::get(
CGM.SizeTy, Cnt)};
5781 llvm::Value *SizeValInChars;
5782 llvm::Value *SizeVal;
5783 std::tie(SizeValInChars, SizeVal) = RCG.
getSizes(Cnt);
5789 bool DelayedCreation = !!SizeVal;
5790 SizeValInChars = CGF.
Builder.CreateIntCast(SizeValInChars,
CGM.SizeTy,
5801 llvm::Value *FiniAddr =
5802 Fini ? Fini : llvm::ConstantPointerNull::get(
CGM.VoidPtrTy);
5807 CGM, Loc, RCG, Cnt,
Data.ReductionOps[Cnt], LHSExprs[Cnt],
5808 RHSExprs[Cnt],
Data.ReductionCopies[Cnt]);
5812 if (DelayedCreation) {
5814 llvm::ConstantInt::get(
CGM.Int32Ty, 1,
true),
5819 if (
Data.IsReductionWithTaskMod) {
5825 llvm::Value *Args[] = {
5827 llvm::ConstantInt::get(
CGM.IntTy,
Data.IsWorksharingReduction ? 1 : 0,
5829 llvm::ConstantInt::get(
CGM.IntTy, Size,
true),
5834 CGM.getModule(), OMPRTL___kmpc_taskred_modifier_init),
5838 llvm::Value *Args[] = {
5841 llvm::ConstantInt::get(
CGM.IntTy, Size,
true),
5845 CGM.getModule(), OMPRTL___kmpc_taskred_init),
5851 bool IsWorksharingReduction) {
5857 llvm::Value *Args[] = {IdentTLoc, GTid,
5858 llvm::ConstantInt::get(
CGM.IntTy,
5859 IsWorksharingReduction ? 1 : 0,
5863 CGM.getModule(), OMPRTL___kmpc_task_reduction_modifier_fini),
5875 llvm::Value *SizeVal = CGF.
Builder.CreateIntCast(Sizes.second,
CGM.SizeTy,
5878 CGF,
CGM.getContext().getSizeType(),
5886 llvm::Value *ReductionsPtr,
5899 CGM.getModule(), OMPRTL___kmpc_task_reduction_get_th_data),
5915 auto &M =
CGM.getModule();
5917 llvm::Value *NumOfElements;
5918 std::tie(NumOfElements, DependenciesArray) =
5920 if (!
Data.Dependences.empty()) {
5921 llvm::Value *DepWaitTaskArgs[7];
5922 DepWaitTaskArgs[0] = UpLoc;
5923 DepWaitTaskArgs[1] = ThreadID;
5924 DepWaitTaskArgs[2] = NumOfElements;
5926 DepWaitTaskArgs[4] = CGF.
Builder.getInt32(0);
5927 DepWaitTaskArgs[5] = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
5928 DepWaitTaskArgs[6] =
5929 llvm::ConstantInt::get(CGF.
Int32Ty,
Data.HasNowaitClause);
5938 M, OMPRTL___kmpc_omp_taskwait_deps_51),
5945 llvm::Value *Args[] = {UpLoc, ThreadID};
5948 OMPBuilder.getOrCreateRuntimeFunction(M, OMPRTL___kmpc_omp_taskwait),
5953 if (
auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.
CapturedStmtInfo))
5954 Region->emitUntiedSwitch(CGF);
5963 InlinedOpenMPRegionRAII Region(CGF,
CodeGen, InnerKind, HasCancel,
5964 InnerKind != OMPD_critical &&
5965 InnerKind != OMPD_master &&
5966 InnerKind != OMPD_masked);
5981 RTCancelKind CancelKind = CancelNoreq;
5982 if (CancelRegion == OMPD_parallel)
5983 CancelKind = CancelParallel;
5984 else if (CancelRegion == OMPD_for)
5985 CancelKind = CancelLoop;
5986 else if (CancelRegion == OMPD_sections)
5987 CancelKind = CancelSections;
5989 assert(CancelRegion == OMPD_taskgroup);
5990 CancelKind = CancelTaskgroup;
6002 if (
auto *OMPRegionInfo =
6006 if (CancelRegion == OMPD_taskgroup || OMPRegionInfo->hasCancel()) {
6007 llvm::Value *Args[] = {
6013 CGM.getModule(), OMPRTL___kmpc_cancellationpoint),
6022 CGF.
Builder.CreateCondBr(Cmp, ExitBB, ContBB);
6024 if (CancelRegion == OMPD_parallel)
6042 auto &M =
CGM.getModule();
6043 if (
auto *OMPRegionInfo =
6045 auto &&ThenGen = [
this, &M, Loc, CancelRegion,
6048 llvm::Value *Args[] = {
6052 llvm::Value *
Result = CGF.EmitRuntimeCall(
6053 OMPBuilder.getOrCreateRuntimeFunction(M, OMPRTL___kmpc_cancel), Args);
6058 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(
".cancel.exit");
6059 llvm::BasicBlock *ContBB = CGF.createBasicBlock(
".cancel.continue");
6060 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(
Result);
6061 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB);
6062 CGF.EmitBlock(ExitBB);
6063 if (CancelRegion == OMPD_parallel)
6067 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind());
6068 CGF.EmitBranchThroughCleanup(CancelDest);
6069 CGF.EmitBlock(ContBB,
true);
6087 OMPUsesAllocatorsActionTy(
6088 ArrayRef<std::pair<const Expr *, const Expr *>> Allocators)
6089 : Allocators(Allocators) {}
6093 for (
const auto &AllocatorData : Allocators) {
6095 CGF, AllocatorData.first, AllocatorData.second);
6098 void Exit(CodeGenFunction &CGF)
override {
6101 for (
const auto &AllocatorData : Allocators) {
6103 AllocatorData.first);
6111 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
6113 assert(!ParentName.empty() &&
"Invalid target entry parent name!");
6117 for (
unsigned I = 0, E =
C->getNumberOfAllocators(); I < E; ++I) {
6124 OMPUsesAllocatorsActionTy UsesAllocatorAction(Allocators);
6125 CodeGen.setAction(UsesAllocatorAction);
6131 const Expr *Allocator,
6132 const Expr *AllocatorTraits) {
6134 ThreadId = CGF.
Builder.CreateIntCast(ThreadId, CGF.
IntTy,
true);
6136 llvm::Value *MemSpaceHandle = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
6137 llvm::Value *NumTraits = llvm::ConstantInt::get(
6141 .getLimitedValue());
6148 llvm::Value *Traits =
Addr.emitRawPointer(CGF);
6150 llvm::Value *AllocatorVal =
6152 CGM.getModule(), OMPRTL___kmpc_init_allocator),
6153 {ThreadId, MemSpaceHandle, NumTraits, Traits});
6165 const Expr *Allocator) {
6167 ThreadId = CGF.
Builder.CreateIntCast(ThreadId, CGF.
IntTy,
true);
6169 llvm::Value *AllocatorVal =
6176 OMPRTL___kmpc_destroy_allocator),
6177 {ThreadId, AllocatorVal});
6182 llvm::OpenMPIRBuilder::TargetKernelDefaultAttrs &Attrs) {
6183 assert(Attrs.MaxTeams.size() == 1 && Attrs.MaxThreads.size() == 1 &&
6184 "invalid default attrs structure");
6185 int32_t &MaxTeamsVal = Attrs.MaxTeams.front();
6186 int32_t &MaxThreadsVal = Attrs.MaxThreads.front();
6193 for (
auto *A :
C->getAttrs()) {
6194 int32_t AttrMinThreadsVal = 1, AttrMaxThreadsVal = -1;
6195 int32_t AttrMinBlocksVal = 1, AttrMaxBlocksVal = -1;
6196 if (
auto *
Attr = dyn_cast<CUDALaunchBoundsAttr>(A))
6197 CGM.handleCUDALaunchBoundsAttr(
nullptr,
Attr, &AttrMaxThreadsVal,
6198 &AttrMinBlocksVal, &AttrMaxBlocksVal);
6199 else if (
auto *
Attr = dyn_cast<AMDGPUFlatWorkGroupSizeAttr>(A))
6200 CGM.handleAMDGPUFlatWorkGroupSizeAttr(
6201 nullptr,
Attr,
nullptr, &AttrMinThreadsVal,
6202 &AttrMaxThreadsVal);
6206 Attrs.MinThreads = std::max(Attrs.MinThreads, AttrMinThreadsVal);
6207 if (AttrMaxThreadsVal > 0)
6208 MaxThreadsVal = MaxThreadsVal > 0
6209 ? std::min(MaxThreadsVal, AttrMaxThreadsVal)
6210 : AttrMaxThreadsVal;
6211 Attrs.MinTeams = std::max(Attrs.MinTeams, AttrMinBlocksVal);
6212 if (AttrMaxBlocksVal > 0)
6213 MaxTeamsVal = MaxTeamsVal > 0 ? std::min(MaxTeamsVal, AttrMaxBlocksVal)
6221 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
6224 llvm::TargetRegionEntryInfo EntryInfo =
6228 llvm::OpenMPIRBuilder::FunctionGenCallback &&GenerateOutlinedFunction =
6229 [&CGF, &D, &
CodeGen](StringRef EntryFnName) {
6230 const CapturedStmt &CS = *D.getCapturedStmt(OMPD_target);
6232 CGOpenMPTargetRegionInfo CGInfo(CS,
CodeGen, EntryFnName);
6237 cantFail(
OMPBuilder.emitTargetRegionFunction(
6238 EntryInfo, GenerateOutlinedFunction, IsOffloadEntry, OutlinedFn,
6244 CGM.getTargetCodeGenInfo().setTargetAttributes(
nullptr, OutlinedFn,
CGM);
6247 for (
auto *A :
C->getAttrs()) {
6248 if (
auto *
Attr = dyn_cast<AMDGPUWavesPerEUAttr>(A))
6249 CGM.handleAMDGPUWavesPerEUAttr(OutlinedFn,
Attr);
6267 while (
const auto *
C = dyn_cast_or_null<CompoundStmt>(Child)) {
6269 for (
const Stmt *S :
C->body()) {
6270 if (
const auto *E = dyn_cast<Expr>(S)) {
6279 if (
const auto *DS = dyn_cast<DeclStmt>(S)) {
6280 if (llvm::all_of(DS->decls(), [](
const Decl *D) {
6281 if (isa<EmptyDecl>(D) || isa<DeclContext>(D) ||
6282 isa<TypeDecl>(D) || isa<PragmaCommentDecl>(D) ||
6283 isa<PragmaDetectMismatchDecl>(D) || isa<UsingDecl>(D) ||
6284 isa<UsingDirectiveDecl>(D) ||
6285 isa<OMPDeclareReductionDecl>(D) ||
6286 isa<OMPThreadPrivateDecl>(D) || isa<OMPAllocateDecl>(D))
6288 const auto *VD = dyn_cast<VarDecl>(D);
6291 return VD->hasGlobalStorage() || !VD->isUsed();
6301 Child = Child->IgnoreContainers();
6308 int32_t &MaxTeamsVal) {
6312 "Expected target-based executable directive.");
6313 switch (DirectiveKind) {
6315 const auto *CS = D.getInnermostCapturedStmt();
6318 const Stmt *ChildStmt =
6320 if (
const auto *NestedDir =
6321 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) {
6330 MinTeamsVal = MaxTeamsVal = Constant->getExtValue();
6333 MinTeamsVal = MaxTeamsVal = 0;
6336 MinTeamsVal = MaxTeamsVal = 1;
6340 MinTeamsVal = MaxTeamsVal = -1;
6343 case OMPD_target_teams_loop:
6344 case OMPD_target_teams:
6345 case OMPD_target_teams_distribute:
6346 case OMPD_target_teams_distribute_simd:
6347 case OMPD_target_teams_distribute_parallel_for:
6348 case OMPD_target_teams_distribute_parallel_for_simd: {
6350 const Expr *NumTeams =
6354 MinTeamsVal = MaxTeamsVal = Constant->getExtValue();
6357 MinTeamsVal = MaxTeamsVal = 0;
6360 case OMPD_target_parallel:
6361 case OMPD_target_parallel_for:
6362 case OMPD_target_parallel_for_simd:
6363 case OMPD_target_parallel_loop:
6364 case OMPD_target_simd:
6365 MinTeamsVal = MaxTeamsVal = 1;
6369 case OMPD_parallel_for:
6370 case OMPD_parallel_loop:
6371 case OMPD_parallel_master:
6372 case OMPD_parallel_sections:
6374 case OMPD_parallel_for_simd:
6376 case OMPD_cancellation_point:
6378 case OMPD_threadprivate:
6389 case OMPD_taskyield:
6392 case OMPD_taskgroup:
6398 case OMPD_target_data:
6399 case OMPD_target_exit_data:
6400 case OMPD_target_enter_data:
6401 case OMPD_distribute:
6402 case OMPD_distribute_simd:
6403 case OMPD_distribute_parallel_for:
6404 case OMPD_distribute_parallel_for_simd:
6405 case OMPD_teams_distribute:
6406 case OMPD_teams_distribute_simd:
6407 case OMPD_teams_distribute_parallel_for:
6408 case OMPD_teams_distribute_parallel_for_simd:
6409 case OMPD_target_update:
6410 case OMPD_declare_simd:
6411 case OMPD_declare_variant:
6412 case OMPD_begin_declare_variant:
6413 case OMPD_end_declare_variant:
6414 case OMPD_declare_target:
6415 case OMPD_end_declare_target:
6416 case OMPD_declare_reduction:
6417 case OMPD_declare_mapper:
6419 case OMPD_taskloop_simd:
6420 case OMPD_master_taskloop:
6421 case OMPD_master_taskloop_simd:
6422 case OMPD_parallel_master_taskloop:
6423 case OMPD_parallel_master_taskloop_simd:
6425 case OMPD_metadirective:
6431 llvm_unreachable(
"Unexpected directive kind.");
6437 "Clauses associated with the teams directive expected to be emitted "
6438 "only for the host!");
6440 int32_t MinNT = -1, MaxNT = -1;
6441 const Expr *NumTeams =
6443 if (NumTeams !=
nullptr) {
6446 switch (DirectiveKind) {
6448 const auto *CS = D.getInnermostCapturedStmt();
6449 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6453 return Bld.CreateIntCast(NumTeamsVal, CGF.
Int32Ty,
6456 case OMPD_target_teams:
6457 case OMPD_target_teams_distribute:
6458 case OMPD_target_teams_distribute_simd:
6459 case OMPD_target_teams_distribute_parallel_for:
6460 case OMPD_target_teams_distribute_parallel_for_simd: {
6464 return Bld.CreateIntCast(NumTeamsVal, CGF.
Int32Ty,
6472 assert(MinNT == MaxNT &&
"Num threads ranges require handling here.");
6473 return llvm::ConstantInt::getSigned(CGF.
Int32Ty, MinNT);
6481 const Expr **E, int32_t &UpperBound,
6482 bool UpperBoundOnly, llvm::Value **CondVal) {
6485 const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child);
6492 if (CondVal && Dir->hasClausesOfKind<
OMPIfClause>()) {
6493 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6496 for (
const auto *
C : Dir->getClausesOfKind<
OMPIfClause>()) {
6497 if (
C->getNameModifier() == OMPD_unknown ||
6498 C->getNameModifier() == OMPD_parallel) {
6513 if (
const auto *PreInit =
6515 for (
const auto *I : PreInit->decls()) {
6516 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
6532 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6534 const auto *NumThreadsClause =
6536 const Expr *NTExpr = NumThreadsClause->getNumThreads();
6537 if (NTExpr->isIntegerConstantExpr(CGF.
getContext()))
6538 if (
auto Constant = NTExpr->getIntegerConstantExpr(CGF.
getContext()))
6541 ? Constant->getZExtValue()
6542 : std::min(UpperBound,
6543 static_cast<int32_t
>(Constant->getZExtValue()));
6546 if (UpperBound == -1)
6551 if (
const auto *PreInit =
6552 cast_or_null<DeclStmt>(NumThreadsClause->getPreInitStmt())) {
6553 for (
const auto *I : PreInit->decls()) {
6554 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
6573 bool UpperBoundOnly, llvm::Value **CondVal,
const Expr **ThreadLimitExpr) {
6574 assert((!CGF.
getLangOpts().OpenMPIsTargetDevice || UpperBoundOnly) &&
6575 "Clauses associated with the teams directive expected to be emitted "
6576 "only for the host!");
6579 "Expected target-based executable directive.");
6581 const Expr *NT =
nullptr;
6582 const Expr **NTPtr = UpperBoundOnly ?
nullptr : &NT;
6584 auto CheckForConstExpr = [&](
const Expr *E,
const Expr **EPtr) {
6587 UpperBound = UpperBound ? Constant->getZExtValue()
6588 : std::min(UpperBound,
6589 int32_t(Constant->getZExtValue()));
6593 if (UpperBound == -1)
6599 auto ReturnSequential = [&]() {
6604 switch (DirectiveKind) {
6607 getNumThreads(CGF, CS, NTPtr, UpperBound, UpperBoundOnly, CondVal);
6613 if (
const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) {
6615 ThreadLimitClause = TLC;
6616 if (ThreadLimitExpr) {
6617 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6621 ThreadLimitClause->getThreadLimit().front()->getSourceRange());
6622 if (
const auto *PreInit =
6623 cast_or_null<DeclStmt>(ThreadLimitClause->getPreInitStmt())) {
6624 for (
const auto *I : PreInit->decls()) {
6625 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
6637 if (ThreadLimitClause)
6638 CheckForConstExpr(ThreadLimitClause->getThreadLimit().front(),
6640 if (
const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) {
6643 CS = Dir->getInnermostCapturedStmt();
6646 Dir = dyn_cast_or_null<OMPExecutableDirective>(Child);
6649 CS = Dir->getInnermostCapturedStmt();
6650 getNumThreads(CGF, CS, NTPtr, UpperBound, UpperBoundOnly, CondVal);
6652 return ReturnSequential();
6656 case OMPD_target_teams: {
6660 CheckForConstExpr(ThreadLimitClause->getThreadLimit().front(),
6664 getNumThreads(CGF, CS, NTPtr, UpperBound, UpperBoundOnly, CondVal);
6667 if (
const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) {
6668 if (Dir->getDirectiveKind() == OMPD_distribute) {
6669 CS = Dir->getInnermostCapturedStmt();
6670 getNumThreads(CGF, CS, NTPtr, UpperBound, UpperBoundOnly, CondVal);
6675 case OMPD_target_teams_distribute:
6679 CheckForConstExpr(ThreadLimitClause->getThreadLimit().front(),
6682 getNumThreads(CGF, D.getInnermostCapturedStmt(), NTPtr, UpperBound,
6683 UpperBoundOnly, CondVal);
6685 case OMPD_target_teams_loop:
6686 case OMPD_target_parallel_loop:
6687 case OMPD_target_parallel:
6688 case OMPD_target_parallel_for:
6689 case OMPD_target_parallel_for_simd:
6690 case OMPD_target_teams_distribute_parallel_for:
6691 case OMPD_target_teams_distribute_parallel_for_simd: {
6692 if (CondVal && D.hasClausesOfKind<
OMPIfClause>()) {
6694 for (
const auto *
C : D.getClausesOfKind<
OMPIfClause>()) {
6695 if (
C->getNameModifier() == OMPD_unknown ||
6696 C->getNameModifier() == OMPD_parallel) {
6706 return ReturnSequential();
6716 CheckForConstExpr(ThreadLimitClause->getThreadLimit().front(),
6722 CheckForConstExpr(NumThreadsClause->getNumThreads(),
nullptr);
6723 return NumThreadsClause->getNumThreads();
6727 case OMPD_target_teams_distribute_simd:
6728 case OMPD_target_simd:
6729 return ReturnSequential();
6733 llvm_unreachable(
"Unsupported directive kind.");
6738 llvm::Value *NumThreadsVal =
nullptr;
6739 llvm::Value *CondVal =
nullptr;
6740 llvm::Value *ThreadLimitVal =
nullptr;
6741 const Expr *ThreadLimitExpr =
nullptr;
6742 int32_t UpperBound = -1;
6745 CGF, D, UpperBound,
false, &CondVal,
6749 if (ThreadLimitExpr) {
6752 ThreadLimitVal = CGF.
Builder.CreateIntCast(ThreadLimitVal, CGF.
Int32Ty,
6757 if (UpperBound == 1) {
6758 NumThreadsVal = CGF.
Builder.getInt32(UpperBound);
6761 NumThreadsVal = CGF.
Builder.CreateIntCast(NumThreadsVal, CGF.
Int32Ty,
6763 }
else if (ThreadLimitVal) {
6766 NumThreadsVal = ThreadLimitVal;
6767 ThreadLimitVal =
nullptr;
6770 assert(!ThreadLimitVal &&
"Default not applicable with thread limit value");
6771 NumThreadsVal = CGF.
Builder.getInt32(0);
6778 NumThreadsVal = CGF.
Builder.CreateSelect(CondVal, NumThreadsVal,
6784 if (ThreadLimitVal) {
6785 NumThreadsVal = CGF.
Builder.CreateSelect(
6786 CGF.
Builder.CreateICmpULT(ThreadLimitVal, NumThreadsVal),
6787 ThreadLimitVal, NumThreadsVal);
6790 return NumThreadsVal;
6800class MappableExprsHandler {
6806 struct AttachPtrExprComparator {
6807 const MappableExprsHandler &Handler;
6809 mutable llvm::DenseMap<std::pair<const Expr *, const Expr *>,
bool>
6810 CachedEqualityComparisons;
6812 AttachPtrExprComparator(
const MappableExprsHandler &H) : Handler(H) {}
6813 AttachPtrExprComparator() =
delete;
6816 bool operator()(
const Expr *LHS,
const Expr *RHS)
const {
6821 const auto ItLHS = Handler.AttachPtrComponentDepthMap.find(LHS);
6822 const auto ItRHS = Handler.AttachPtrComponentDepthMap.find(RHS);
6824 std::optional<size_t> DepthLHS =
6825 (ItLHS != Handler.AttachPtrComponentDepthMap.end()) ? ItLHS->second
6827 std::optional<size_t> DepthRHS =
6828 (ItRHS != Handler.AttachPtrComponentDepthMap.end()) ? ItRHS->second
6832 if (!DepthLHS.has_value() && !DepthRHS.has_value()) {
6834 if (areEqual(LHS, RHS))
6837 return wasComputedBefore(LHS, RHS);
6839 if (!DepthLHS.has_value())
6841 if (!DepthRHS.has_value())
6845 if (DepthLHS.value() != DepthRHS.value())
6846 return DepthLHS.value() < DepthRHS.value();
6849 if (areEqual(LHS, RHS))
6852 return wasComputedBefore(LHS, RHS);
6858 bool areEqual(
const Expr *LHS,
const Expr *RHS)
const {
6860 const auto CachedResultIt = CachedEqualityComparisons.find({LHS, RHS});
6861 if (CachedResultIt != CachedEqualityComparisons.end())
6862 return CachedResultIt->second;
6876 bool wasComputedBefore(
const Expr *LHS,
const Expr *RHS)
const {
6877 const size_t &OrderLHS = Handler.AttachPtrComputationOrderMap.at(LHS);
6878 const size_t &OrderRHS = Handler.AttachPtrComputationOrderMap.at(RHS);
6880 return OrderLHS < OrderRHS;
6889 bool areSemanticallyEqual(
const Expr *LHS,
const Expr *RHS)
const {
6911 if (
const auto *LD = dyn_cast<DeclRefExpr>(LHS)) {
6912 const auto *RD = dyn_cast<DeclRefExpr>(RHS);
6915 return LD->getDecl()->getCanonicalDecl() ==
6916 RD->getDecl()->getCanonicalDecl();
6920 if (
const auto *LA = dyn_cast<ArraySubscriptExpr>(LHS)) {
6921 const auto *RA = dyn_cast<ArraySubscriptExpr>(RHS);
6924 return areSemanticallyEqual(LA->getBase(), RA->getBase()) &&
6925 areSemanticallyEqual(LA->getIdx(), RA->getIdx());
6929 if (
const auto *LM = dyn_cast<MemberExpr>(LHS)) {
6930 const auto *RM = dyn_cast<MemberExpr>(RHS);
6933 if (LM->getMemberDecl()->getCanonicalDecl() !=
6934 RM->getMemberDecl()->getCanonicalDecl())
6936 return areSemanticallyEqual(LM->getBase(), RM->getBase());
6940 if (
const auto *LU = dyn_cast<UnaryOperator>(LHS)) {
6941 const auto *RU = dyn_cast<UnaryOperator>(RHS);
6944 if (LU->getOpcode() != RU->getOpcode())
6946 return areSemanticallyEqual(LU->getSubExpr(), RU->getSubExpr());
6950 if (
const auto *LB = dyn_cast<BinaryOperator>(LHS)) {
6951 const auto *RB = dyn_cast<BinaryOperator>(RHS);
6954 if (LB->getOpcode() != RB->getOpcode())
6956 return areSemanticallyEqual(LB->getLHS(), RB->getLHS()) &&
6957 areSemanticallyEqual(LB->getRHS(), RB->getRHS());
6963 if (
const auto *LAS = dyn_cast<ArraySectionExpr>(LHS)) {
6964 const auto *RAS = dyn_cast<ArraySectionExpr>(RHS);
6967 return areSemanticallyEqual(LAS->getBase(), RAS->getBase()) &&
6968 areSemanticallyEqual(LAS->getLowerBound(),
6969 RAS->getLowerBound()) &&
6970 areSemanticallyEqual(LAS->getLength(), RAS->getLength());
6974 if (
const auto *LC = dyn_cast<CastExpr>(LHS)) {
6975 const auto *RC = dyn_cast<CastExpr>(RHS);
6978 if (LC->getCastKind() != RC->getCastKind())
6980 return areSemanticallyEqual(LC->getSubExpr(), RC->getSubExpr());
6988 if (
const auto *LI = dyn_cast<IntegerLiteral>(LHS)) {
6989 const auto *RI = dyn_cast<IntegerLiteral>(RHS);
6992 return LI->getValue() == RI->getValue();
6996 if (
const auto *LC = dyn_cast<CharacterLiteral>(LHS)) {
6997 const auto *RC = dyn_cast<CharacterLiteral>(RHS);
7000 return LC->getValue() == RC->getValue();
7004 if (
const auto *LF = dyn_cast<FloatingLiteral>(LHS)) {
7005 const auto *RF = dyn_cast<FloatingLiteral>(RHS);
7009 return LF->getValue().bitwiseIsEqual(RF->getValue());
7013 if (
const auto *LS = dyn_cast<StringLiteral>(LHS)) {
7014 const auto *RS = dyn_cast<StringLiteral>(RHS);
7017 return LS->getString() == RS->getString();
7025 if (
const auto *LB = dyn_cast<CXXBoolLiteralExpr>(LHS)) {
7026 const auto *RB = dyn_cast<CXXBoolLiteralExpr>(RHS);
7029 return LB->getValue() == RB->getValue();
7038 static unsigned getFlagMemberOffset() {
7039 unsigned Offset = 0;
7040 for (uint64_t Remain =
7041 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
7042 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF);
7043 !(Remain & 1); Remain = Remain >> 1)
7050 class MappingExprInfo {
7052 const ValueDecl *MapDecl =
nullptr;
7055 const Expr *MapExpr =
nullptr;
7058 MappingExprInfo(
const ValueDecl *MapDecl,
const Expr *MapExpr =
nullptr)
7059 : MapDecl(MapDecl), MapExpr(MapExpr) {}
7061 const ValueDecl *getMapDecl()
const {
return MapDecl; }
7062 const Expr *getMapExpr()
const {
return MapExpr; }
7065 using DeviceInfoTy = llvm::OpenMPIRBuilder::DeviceInfoTy;
7066 using MapBaseValuesArrayTy = llvm::OpenMPIRBuilder::MapValuesArrayTy;
7067 using MapValuesArrayTy = llvm::OpenMPIRBuilder::MapValuesArrayTy;
7068 using MapFlagsArrayTy = llvm::OpenMPIRBuilder::MapFlagsArrayTy;
7069 using MapDimArrayTy = llvm::OpenMPIRBuilder::MapDimArrayTy;
7070 using MapNonContiguousArrayTy =
7071 llvm::OpenMPIRBuilder::MapNonContiguousArrayTy;
7072 using MapExprsArrayTy = SmallVector<MappingExprInfo, 4>;
7073 using MapValueDeclsArrayTy = SmallVector<const ValueDecl *, 4>;
7077 bool ,
const ValueDecl *,
const Expr *>;
7078 using MapDataArrayTy = SmallVector<MapData, 4>;
7083 struct MapCombinedInfoTy : llvm::OpenMPIRBuilder::MapInfosTy {
7084 MapExprsArrayTy Exprs;
7085 MapValueDeclsArrayTy Mappers;
7086 MapValueDeclsArrayTy DevicePtrDecls;
7089 void append(MapCombinedInfoTy &CurInfo) {
7090 Exprs.append(CurInfo.Exprs.begin(), CurInfo.Exprs.end());
7091 DevicePtrDecls.append(CurInfo.DevicePtrDecls.begin(),
7092 CurInfo.DevicePtrDecls.end());
7093 Mappers.append(CurInfo.Mappers.begin(), CurInfo.Mappers.end());
7094 llvm::OpenMPIRBuilder::MapInfosTy::append(CurInfo);
7102 struct StructRangeInfoTy {
7103 MapCombinedInfoTy PreliminaryMapData;
7104 std::pair<
unsigned , Address > LowestElem = {
7106 std::pair<
unsigned , Address > HighestElem = {
7110 bool IsArraySection =
false;
7111 bool HasCompleteRecord =
false;
7116 struct AttachInfoTy {
7119 const ValueDecl *AttachPtrDecl =
nullptr;
7120 const Expr *AttachMapExpr =
nullptr;
7122 bool isValid()
const {
7129 bool hasAttachEntryForCapturedVar(
const ValueDecl *VD)
const {
7130 for (
const auto &AttachEntry : AttachPtrExprMap) {
7131 if (AttachEntry.second) {
7134 if (
const auto *DRE = dyn_cast<DeclRefExpr>(AttachEntry.second))
7135 if (DRE->getDecl() == VD)
7143 const Expr *getAttachPtrExpr(
7146 const auto It = AttachPtrExprMap.find(Components);
7147 if (It != AttachPtrExprMap.end())
7158 ArrayRef<OpenMPMapModifierKind> MapModifiers;
7159 ArrayRef<OpenMPMotionModifierKind> MotionModifiers;
7160 bool ReturnDevicePointer =
false;
7161 bool IsImplicit =
false;
7162 const ValueDecl *Mapper =
nullptr;
7163 const Expr *VarRef =
nullptr;
7164 bool ForDeviceAddr =
false;
7166 MapInfo() =
default;
7170 ArrayRef<OpenMPMapModifierKind> MapModifiers,
7171 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
7172 bool ReturnDevicePointer,
bool IsImplicit,
7173 const ValueDecl *Mapper =
nullptr,
const Expr *VarRef =
nullptr,
7174 bool ForDeviceAddr =
false)
7175 : Components(Components), MapType(MapType), MapModifiers(MapModifiers),
7176 MotionModifiers(MotionModifiers),
7177 ReturnDevicePointer(ReturnDevicePointer), IsImplicit(IsImplicit),
7178 Mapper(Mapper), VarRef(VarRef), ForDeviceAddr(ForDeviceAddr) {}
7183 llvm::PointerUnion<
const OMPExecutableDirective *,
7184 const OMPDeclareMapperDecl *>
7188 CodeGenFunction &CGF;
7193 llvm::DenseMap<CanonicalDeclPtr<const VarDecl>,
bool> FirstPrivateDecls;
7196 llvm::SmallSet<OpenMPDefaultmapClauseKind, 4> DefaultmapFirstprivateKinds;
7202 SmallVector<OMPClauseMappableExprCommon::MappableExprComponentListRef, 4>>
7209 SmallVector<OMPClauseMappableExprCommon::MappableExprComponentListRef, 4>>
7213 llvm::DenseMap<const ValueDecl *, const OMPMapClause *> LambdasMap;
7228 llvm::DenseMap<const Expr *, std::optional<size_t>>
7229 AttachPtrComponentDepthMap = {{
nullptr, std::nullopt}};
7233 llvm::DenseMap<const Expr *, size_t> AttachPtrComputationOrderMap = {
7238 AttachPtrExprComparator AttachPtrComparator;
7240 llvm::Value *getExprTypeSize(
const Expr *E)
const {
7244 if (
const auto *OAE = dyn_cast<OMPArrayShapingExpr>(E)) {
7246 CGF.
getTypeSize(OAE->getBase()->getType()->getPointeeType());
7247 for (
const Expr *SE : OAE->getDimensions()) {
7258 if (
const auto *RefTy = ExprTy->
getAs<ReferenceType>())
7264 if (
const auto *OAE = dyn_cast<ArraySectionExpr>(E)) {
7266 OAE->getBase()->IgnoreParenImpCasts())
7272 if (!OAE->getLength() && OAE->getColonLocFirst().isValid() &&
7273 !OAE->getLowerBound())
7276 llvm::Value *ElemSize;
7277 if (
const auto *PTy = BaseTy->
getAs<PointerType>()) {
7278 ElemSize = CGF.
getTypeSize(PTy->getPointeeType().getCanonicalType());
7281 assert(ATy &&
"Expecting array type if not a pointer type.");
7282 ElemSize = CGF.
getTypeSize(ATy->getElementType().getCanonicalType());
7287 if (!OAE->getLength() && OAE->getColonLocFirst().isInvalid())
7290 if (
const Expr *LenExpr = OAE->getLength()) {
7294 LenExpr->getExprLoc());
7295 return CGF.
Builder.CreateNUWMul(LengthVal, ElemSize);
7297 assert(!OAE->getLength() && OAE->getColonLocFirst().isValid() &&
7298 OAE->getLowerBound() &&
"expected array_section[lb:].");
7304 OAE->getLowerBound()->getExprLoc());
7305 LBVal = CGF.
Builder.CreateNUWMul(LBVal, ElemSize);
7306 llvm::Value *Cmp = CGF.
Builder.CreateICmpUGT(LengthVal, LBVal);
7307 llvm::Value *TrueVal = CGF.
Builder.CreateNUWSub(LengthVal, LBVal);
7308 LengthVal = CGF.
Builder.CreateSelect(
7309 Cmp, TrueVal, llvm::ConstantInt::get(CGF.
SizeTy, 0));
7319 OpenMPOffloadMappingFlags getMapTypeBits(
7321 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
bool IsImplicit,
7322 bool AddPtrFlag,
bool AddIsTargetParamFlag,
bool IsNonContiguous)
const {
7323 OpenMPOffloadMappingFlags Bits =
7324 IsImplicit ? OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT
7325 : OpenMPOffloadMappingFlags::OMP_MAP_NONE;
7327 case OMPC_MAP_alloc:
7328 case OMPC_MAP_release:
7335 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_TO;
7338 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_FROM;
7340 case OMPC_MAP_tofrom:
7341 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_TO |
7342 OpenMPOffloadMappingFlags::OMP_MAP_FROM;
7344 case OMPC_MAP_delete:
7345 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_DELETE;
7348 llvm_unreachable(
"Unexpected map type!");
7351 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ;
7352 if (AddIsTargetParamFlag)
7353 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM;
7354 if (llvm::is_contained(MapModifiers, OMPC_MAP_MODIFIER_always))
7355 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_ALWAYS;
7356 if (llvm::is_contained(MapModifiers, OMPC_MAP_MODIFIER_close))
7357 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_CLOSE;
7358 if (llvm::is_contained(MapModifiers, OMPC_MAP_MODIFIER_present) ||
7359 llvm::is_contained(MotionModifiers, OMPC_MOTION_MODIFIER_present))
7360 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_PRESENT;
7361 if (llvm::is_contained(MapModifiers, OMPC_MAP_MODIFIER_ompx_hold))
7362 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_OMPX_HOLD;
7363 if (IsNonContiguous)
7364 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_NON_CONTIG;
7370 bool isFinalArraySectionExpression(
const Expr *E)
const {
7371 const auto *OASE = dyn_cast<ArraySectionExpr>(E);
7378 if (OASE->getColonLocFirst().isInvalid())
7381 const Expr *Length = OASE->getLength();
7388 OASE->getBase()->IgnoreParenImpCasts())
7390 if (
const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.
getTypePtr()))
7391 return ATy->getSExtSize() != 1;
7403 llvm::APSInt ConstLength =
Result.Val.getInt();
7404 return ConstLength.getSExtValue() != 1;
7411 void emitAttachEntry(CodeGenFunction &CGF, MapCombinedInfoTy &CombinedInfo,
7412 const AttachInfoTy &AttachInfo)
const {
7413 assert(AttachInfo.isValid() &&
7414 "Expected valid attach pointer/pointee information!");
7418 llvm::Value *PointerSize = CGF.
Builder.CreateIntCast(
7419 llvm::ConstantInt::get(
7425 CombinedInfo.Exprs.emplace_back(AttachInfo.AttachPtrDecl,
7426 AttachInfo.AttachMapExpr);
7427 CombinedInfo.BasePointers.push_back(
7428 AttachInfo.AttachPtrAddr.emitRawPointer(CGF));
7429 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
7430 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
7431 CombinedInfo.Pointers.push_back(
7432 AttachInfo.AttachPteeAddr.emitRawPointer(CGF));
7433 CombinedInfo.Sizes.push_back(PointerSize);
7434 CombinedInfo.Types.push_back(OpenMPOffloadMappingFlags::OMP_MAP_ATTACH);
7435 CombinedInfo.Mappers.push_back(
nullptr);
7436 CombinedInfo.NonContigInfo.Dims.push_back(1);
7443 class CopyOverlappedEntryGaps {
7444 CodeGenFunction &CGF;
7445 MapCombinedInfoTy &CombinedInfo;
7446 OpenMPOffloadMappingFlags Flags = OpenMPOffloadMappingFlags::OMP_MAP_NONE;
7447 const ValueDecl *MapDecl =
nullptr;
7448 const Expr *MapExpr =
nullptr;
7450 bool IsNonContiguous =
false;
7454 const RecordDecl *LastParent =
nullptr;
7456 unsigned LastIndex = -1u;
7460 CopyOverlappedEntryGaps(CodeGenFunction &CGF,
7461 MapCombinedInfoTy &CombinedInfo,
7462 OpenMPOffloadMappingFlags Flags,
7463 const ValueDecl *MapDecl,
const Expr *MapExpr,
7464 Address BP, Address LB,
bool IsNonContiguous,
7466 : CGF(CGF), CombinedInfo(CombinedInfo), Flags(Flags), MapDecl(MapDecl),
7467 MapExpr(MapExpr), BP(BP), IsNonContiguous(IsNonContiguous),
7468 DimSize(DimSize), LB(LB) {}
7471 const OMPClauseMappableExprCommon::MappableComponent &MC,
7472 const FieldDecl *FD,
7473 llvm::function_ref<LValue(CodeGenFunction &,
const MemberExpr *)>
7474 EmitMemberExprBase) {
7484 LValue BaseLVal = EmitMemberExprBase(CGF, ME);
7496 copyUntilField(FD, ComponentLB);
7499 if (((int64_t)FieldOffset - (int64_t)Cursor) > 0)
7500 copyUntilField(FD, ComponentLB);
7502 Cursor = FieldOffset + FieldSize;
7507 void copyUntilField(
const FieldDecl *FD, Address ComponentLB) {
7511 CGF.
Builder.CreatePtrDiff(CGF.
Int8Ty, ComponentLBPtr, LBPtr);
7512 copySizedChunk(LBPtr, Size);
7515 void copyUntilEnd(Address HB) {
7517 const ASTRecordLayout &RL =
7526 copySizedChunk(LBPtr, Size);
7529 void copySizedChunk(llvm::Value *Base, llvm::Value *Size) {
7530 CombinedInfo.Exprs.emplace_back(MapDecl, MapExpr);
7532 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
7533 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
7534 CombinedInfo.Pointers.push_back(Base);
7535 CombinedInfo.Sizes.push_back(
7537 CombinedInfo.Types.push_back(Flags);
7538 CombinedInfo.Mappers.push_back(
nullptr);
7539 CombinedInfo.NonContigInfo.Dims.push_back(IsNonContiguous ? DimSize : 1);
7548 void generateInfoForComponentList(
7550 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
7552 MapCombinedInfoTy &CombinedInfo,
7553 MapCombinedInfoTy &StructBaseCombinedInfo,
7554 StructRangeInfoTy &PartialStruct, AttachInfoTy &AttachInfo,
7555 bool IsFirstComponentList,
bool IsImplicit,
7556 bool GenerateAllInfoForClauses,
const ValueDecl *Mapper =
nullptr,
7557 bool ForDeviceAddr =
false,
const ValueDecl *BaseDecl =
nullptr,
7558 const Expr *MapExpr =
nullptr,
7559 ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef>
7560 OverlappedElements = {})
const {
7778 bool IsCaptureFirstInfo = IsFirstComponentList;
7782 bool RequiresReference =
false;
7785 auto CI = Components.rbegin();
7786 auto CE = Components.rend();
7791 bool IsExpressionFirstInfo =
true;
7792 bool FirstPointerInComplexData =
false;
7795 const Expr *AssocExpr = I->getAssociatedExpression();
7796 const auto *AE = dyn_cast<ArraySubscriptExpr>(AssocExpr);
7797 const auto *OASE = dyn_cast<ArraySectionExpr>(AssocExpr);
7798 const auto *OAShE = dyn_cast<OMPArrayShapingExpr>(AssocExpr);
7801 const Expr *AttachPtrExpr = getAttachPtrExpr(Components);
7802 auto [AttachPtrAddr, AttachPteeBaseAddr] =
7803 getAttachPtrAddrAndPteeBaseAddr(AttachPtrExpr, CGF);
7805 bool HasAttachPtr = AttachPtrExpr !=
nullptr;
7806 bool FirstComponentIsForAttachPtr = AssocExpr == AttachPtrExpr;
7807 bool SeenAttachPtr = FirstComponentIsForAttachPtr;
7809 if (FirstComponentIsForAttachPtr) {
7817 }
else if ((AE &&
isa<CXXThisExpr>(AE->getBase()->IgnoreParenImpCasts())) ||
7831 if (
const auto *VD =
7832 dyn_cast_or_null<VarDecl>(I->getAssociatedDeclaration())) {
7833 if (std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
7834 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD)) {
7835 if ((*Res == OMPDeclareTargetDeclAttr::MT_Link) ||
7836 ((*Res == OMPDeclareTargetDeclAttr::MT_To ||
7837 *Res == OMPDeclareTargetDeclAttr::MT_Enter) &&
7839 RequiresReference =
true;
7849 I->getAssociatedDeclaration()->
getType().getNonReferenceType();
7854 const auto *VD = dyn_cast<VarDecl>(I->getAssociatedDeclaration());
7856 !VD || VD->hasLocalStorage() || HasAttachPtr)
7859 FirstPointerInComplexData =
true;
7878 bool ShouldBeMemberOf =
false;
7887 const MemberExpr *EncounteredME =
nullptr;
7899 bool IsNonContiguous =
7900 CombinedInfo.NonContigInfo.IsNonContiguous ||
7901 any_of(Components, [&](
const auto &Component) {
7903 dyn_cast<ArraySectionExpr>(Component.getAssociatedExpression());
7907 const Expr *StrideExpr = OASE->getStride();
7911 const auto Constant =
7916 return !Constant->isOne();
7919 bool IsPrevMemberReference =
false;
7921 bool IsPartialMapped =
7922 !PartialStruct.PreliminaryMapData.BasePointers.empty();
7929 bool IsMappingWholeStruct =
true;
7930 if (!GenerateAllInfoForClauses) {
7931 IsMappingWholeStruct =
false;
7933 for (
auto TempI = I; TempI != CE; ++TempI) {
7934 const MemberExpr *PossibleME =
7935 dyn_cast<MemberExpr>(TempI->getAssociatedExpression());
7937 IsMappingWholeStruct =
false;
7943 bool SeenFirstNonBinOpExprAfterAttachPtr =
false;
7944 for (; I != CE; ++I) {
7947 if (HasAttachPtr && !SeenAttachPtr) {
7948 SeenAttachPtr = I->getAssociatedExpression() == AttachPtrExpr;
7955 if (HasAttachPtr && !SeenFirstNonBinOpExprAfterAttachPtr) {
7956 const auto *BO = dyn_cast<BinaryOperator>(I->getAssociatedExpression());
7961 SeenFirstNonBinOpExprAfterAttachPtr =
true;
7962 BP = AttachPteeBaseAddr;
7966 if (!EncounteredME) {
7967 EncounteredME = dyn_cast<MemberExpr>(I->getAssociatedExpression());
7970 if (EncounteredME) {
7971 ShouldBeMemberOf =
true;
7974 if (FirstPointerInComplexData) {
7975 QualType Ty = std::prev(I)
7976 ->getAssociatedDeclaration()
7978 .getNonReferenceType();
7980 FirstPointerInComplexData =
false;
7985 auto Next = std::next(I);
7995 bool IsFinalArraySection =
7997 isFinalArraySectionExpression(I->getAssociatedExpression());
8001 const ValueDecl *MapDecl = (I->getAssociatedDeclaration())
8002 ? I->getAssociatedDeclaration()
8004 MapExpr = (I->getAssociatedExpression()) ? I->getAssociatedExpression()
8011 dyn_cast<ArraySectionExpr>(I->getAssociatedExpression());
8013 dyn_cast<OMPArrayShapingExpr>(I->getAssociatedExpression());
8014 const auto *UO = dyn_cast<UnaryOperator>(I->getAssociatedExpression());
8015 const auto *BO = dyn_cast<BinaryOperator>(I->getAssociatedExpression());
8021 I->getAssociatedExpression()->getType()->isAnyPointerType();
8022 bool IsMemberReference =
isa<MemberExpr>(I->getAssociatedExpression()) &&
8025 bool IsNonDerefPointer = IsPointer &&
8026 !(UO && UO->getOpcode() != UO_Deref) && !BO &&
8032 if (
Next == CE || IsMemberReference || IsNonDerefPointer ||
8033 IsFinalArraySection) {
8036 assert((
Next == CE ||
8043 "Unexpected expression");
8047 auto &&EmitMemberExprBase = [](CodeGenFunction &CGF,
8048 const MemberExpr *E) {
8049 const Expr *BaseExpr = E->getBase();
8054 LValueBaseInfo BaseInfo;
8055 TBAAAccessInfo TBAAInfo;
8069 OAShE->getBase()->getType()->getPointeeType()),
8071 OAShE->getBase()->getType()));
8072 }
else if (IsMemberReference) {
8074 LValue BaseLVal = EmitMemberExprBase(CGF, ME);
8089 FinalLowestElem = LowestElem;
8094 bool IsMemberPointerOrAddr =
8096 (((IsPointer || ForDeviceAddr) &&
8097 I->getAssociatedExpression() == EncounteredME) ||
8098 (IsPrevMemberReference && !IsPointer) ||
8099 (IsMemberReference &&
Next != CE &&
8100 !
Next->getAssociatedExpression()->getType()->isPointerType()));
8101 if (!OverlappedElements.empty() &&
Next == CE) {
8103 assert(!PartialStruct.Base.isValid() &&
"The base element is set.");
8104 assert(!IsPointer &&
8105 "Unexpected base element with the pointer type.");
8108 PartialStruct.LowestElem = {0, LowestElem};
8110 I->getAssociatedExpression()->getType());
8115 PartialStruct.HighestElem = {
8116 std::numeric_limits<
decltype(
8117 PartialStruct.HighestElem.first)>
::max(),
8119 PartialStruct.Base = BP;
8120 PartialStruct.LB = LB;
8122 PartialStruct.PreliminaryMapData.BasePointers.empty() &&
8123 "Overlapped elements must be used only once for the variable.");
8124 std::swap(PartialStruct.PreliminaryMapData, CombinedInfo);
8126 OpenMPOffloadMappingFlags Flags =
8127 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF |
8128 getMapTypeBits(MapType, MapModifiers, MotionModifiers, IsImplicit,
8130 false, IsNonContiguous);
8131 CopyOverlappedEntryGaps CopyGaps(CGF, CombinedInfo, Flags, MapDecl,
8132 MapExpr, BP, LB, IsNonContiguous,
8136 Component : OverlappedElements) {
8137 for (
const OMPClauseMappableExprCommon::MappableComponent &MC :
8140 if (
const auto *FD = dyn_cast<FieldDecl>(VD)) {
8141 CopyGaps.processField(MC, FD, EmitMemberExprBase);
8146 CopyGaps.copyUntilEnd(HB);
8149 llvm::Value *
Size = getExprTypeSize(I->getAssociatedExpression());
8156 if ((!IsMemberPointerOrAddr && !IsPartialMapped) ||
8158 if (!IsMappingWholeStruct) {
8159 CombinedInfo.Exprs.emplace_back(MapDecl, MapExpr);
8161 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
8162 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
8164 CombinedInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
8166 CombinedInfo.NonContigInfo.Dims.push_back(IsNonContiguous ? DimSize
8169 StructBaseCombinedInfo.Exprs.emplace_back(MapDecl, MapExpr);
8170 StructBaseCombinedInfo.BasePointers.push_back(
8172 StructBaseCombinedInfo.DevicePtrDecls.push_back(
nullptr);
8173 StructBaseCombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
8174 StructBaseCombinedInfo.Pointers.push_back(LB.
emitRawPointer(CGF));
8175 StructBaseCombinedInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
8177 StructBaseCombinedInfo.NonContigInfo.Dims.push_back(
8178 IsNonContiguous ? DimSize : 1);
8182 bool HasMapper = Mapper &&
Next == CE;
8183 if (!IsMappingWholeStruct)
8184 CombinedInfo.Mappers.push_back(HasMapper ? Mapper :
nullptr);
8186 StructBaseCombinedInfo.Mappers.push_back(HasMapper ? Mapper
8193 OpenMPOffloadMappingFlags Flags = getMapTypeBits(
8194 MapType, MapModifiers, MotionModifiers, IsImplicit,
8195 !IsExpressionFirstInfo || RequiresReference ||
8196 FirstPointerInComplexData || IsMemberReference,
8197 IsCaptureFirstInfo && !RequiresReference, IsNonContiguous);
8199 if (!IsExpressionFirstInfo || IsMemberReference) {
8202 if (IsPointer || (IsMemberReference &&
Next != CE))
8203 Flags &= ~(OpenMPOffloadMappingFlags::OMP_MAP_TO |
8204 OpenMPOffloadMappingFlags::OMP_MAP_FROM |
8205 OpenMPOffloadMappingFlags::OMP_MAP_ALWAYS |
8206 OpenMPOffloadMappingFlags::OMP_MAP_DELETE |
8207 OpenMPOffloadMappingFlags::OMP_MAP_CLOSE);
8209 if (ShouldBeMemberOf) {
8212 Flags |= OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF;
8215 ShouldBeMemberOf =
false;
8219 if (!IsMappingWholeStruct)
8220 CombinedInfo.Types.push_back(Flags);
8222 StructBaseCombinedInfo.Types.push_back(Flags);
8228 if (EncounteredME) {
8233 if (!PartialStruct.Base.isValid()) {
8234 PartialStruct.LowestElem = {FieldIndex, LowestElem};
8235 if (IsFinalArraySection && OASE) {
8239 PartialStruct.HighestElem = {FieldIndex, HB};
8241 PartialStruct.HighestElem = {FieldIndex, LowestElem};
8243 PartialStruct.Base = BP;
8244 PartialStruct.LB = BP;
8245 }
else if (FieldIndex < PartialStruct.LowestElem.first) {
8246 PartialStruct.LowestElem = {FieldIndex, LowestElem};
8247 }
else if (FieldIndex > PartialStruct.HighestElem.first) {
8248 if (IsFinalArraySection && OASE) {
8252 PartialStruct.HighestElem = {FieldIndex, HB};
8254 PartialStruct.HighestElem = {FieldIndex, LowestElem};
8260 if (IsFinalArraySection || IsNonContiguous)
8261 PartialStruct.IsArraySection =
true;
8264 if (IsFinalArraySection)
8269 BP = IsMemberReference ? LowestElem : LB;
8270 if (!IsPartialMapped)
8271 IsExpressionFirstInfo =
false;
8272 IsCaptureFirstInfo =
false;
8273 FirstPointerInComplexData =
false;
8274 IsPrevMemberReference = IsMemberReference;
8275 }
else if (FirstPointerInComplexData) {
8276 QualType Ty = Components.rbegin()
8277 ->getAssociatedDeclaration()
8279 .getNonReferenceType();
8281 FirstPointerInComplexData =
false;
8287 PartialStruct.HasCompleteRecord =
true;
8290 if (shouldEmitAttachEntry(AttachPtrExpr, BaseDecl, CGF, CurDir)) {
8291 AttachInfo.AttachPtrAddr = AttachPtrAddr;
8292 AttachInfo.AttachPteeAddr = FinalLowestElem;
8293 AttachInfo.AttachPtrDecl = BaseDecl;
8294 AttachInfo.AttachMapExpr = MapExpr;
8297 if (!IsNonContiguous)
8300 const ASTContext &Context = CGF.
getContext();
8304 MapValuesArrayTy CurOffsets = {llvm::ConstantInt::get(CGF.
CGM.
Int64Ty, 0)};
8305 MapValuesArrayTy CurCounts = {llvm::ConstantInt::get(CGF.
CGM.
Int64Ty, 1)};
8306 MapValuesArrayTy CurStrides;
8307 MapValuesArrayTy DimSizes{llvm::ConstantInt::get(CGF.
CGM.
Int64Ty, 1)};
8313 for (
const OMPClauseMappableExprCommon::MappableComponent &Component :
8315 const Expr *AssocExpr = Component.getAssociatedExpression();
8316 const auto *OASE = dyn_cast<ArraySectionExpr>(AssocExpr);
8326 assert((VAT || CAT || &Component == &*Components.begin()) &&
8327 "Should be either ConstantArray or VariableArray if not the "
8331 if (CurStrides.empty()) {
8332 const Type *ElementType =
nullptr;
8334 ElementType = CAT->getElementType().getTypePtr();
8336 ElementType = VAT->getElementType().getTypePtr();
8337 else if (&Component == &*Components.begin()) {
8344 if (
const auto *PtrType = Ty->
getAs<PointerType>())
8351 "Non-first components should not be raw pointers");
8359 if (&Component != &*Components.begin())
8363 CurStrides.push_back(
8364 llvm::ConstantInt::get(CGF.
Int64Ty, ElementTypeSize));
8369 if (DimSizes.size() < Components.size() - 1) {
8372 llvm::ConstantInt::get(CGF.
Int64Ty, CAT->getZExtSize()));
8374 DimSizes.push_back(CGF.
Builder.CreateIntCast(
8381 auto *DI = DimSizes.begin() + 1;
8383 llvm::Value *DimProd =
8384 llvm::ConstantInt::get(CGF.
CGM.
Int64Ty, ElementTypeSize);
8393 for (
const OMPClauseMappableExprCommon::MappableComponent &Component :
8395 const Expr *AssocExpr = Component.getAssociatedExpression();
8397 if (
const auto *AE = dyn_cast<ArraySubscriptExpr>(AssocExpr)) {
8398 llvm::Value *Offset = CGF.
Builder.CreateIntCast(
8401 CurOffsets.push_back(Offset);
8402 CurCounts.push_back(llvm::ConstantInt::get(CGF.
Int64Ty, 1));
8403 CurStrides.push_back(CurStrides.back());
8407 const auto *OASE = dyn_cast<ArraySectionExpr>(AssocExpr);
8413 const Expr *OffsetExpr = OASE->getLowerBound();
8414 llvm::Value *Offset =
nullptr;
8417 Offset = llvm::ConstantInt::get(CGF.
Int64Ty, 0);
8423 CurOffsets.push_back(Offset);
8426 const Expr *CountExpr = OASE->getLength();
8427 llvm::Value *Count =
nullptr;
8433 if (!OASE->getColonLocFirst().isValid() &&
8434 !OASE->getColonLocSecond().isValid()) {
8435 Count = llvm::ConstantInt::get(CGF.
Int64Ty, 1);
8441 const Expr *StrideExpr = OASE->getStride();
8442 llvm::Value *Stride =
8448 Count = CGF.
Builder.CreateUDiv(
8449 CGF.
Builder.CreateNUWSub(*DI, Offset), Stride);
8451 Count = CGF.
Builder.CreateNUWSub(*DI, Offset);
8457 CurCounts.push_back(Count);
8466 const Expr *StrideExpr = OASE->getStride();
8467 llvm::Value *Stride =
8472 DimProd = CGF.
Builder.CreateNUWMul(DimProd, *(DI - 1));
8474 CurStrides.push_back(CGF.
Builder.CreateNUWMul(DimProd, Stride));
8476 CurStrides.push_back(DimProd);
8477 if (DI != DimSizes.end())
8481 CombinedInfo.NonContigInfo.Offsets.push_back(CurOffsets);
8482 CombinedInfo.NonContigInfo.Counts.push_back(CurCounts);
8483 CombinedInfo.NonContigInfo.Strides.push_back(CurStrides);
8489 OpenMPOffloadMappingFlags
8490 getMapModifiersForPrivateClauses(
const CapturedStmt::Capture &Cap)
const {
8498 return OpenMPOffloadMappingFlags::OMP_MAP_TO |
8499 OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ;
8500 return OpenMPOffloadMappingFlags::OMP_MAP_PRIVATE |
8501 OpenMPOffloadMappingFlags::OMP_MAP_TO;
8504 if (I != LambdasMap.end())
8506 return getMapTypeBits(
8507 I->getSecond()->getMapType(), I->getSecond()->getMapTypeModifiers(),
8508 {}, I->getSecond()->isImplicit(),
8512 return OpenMPOffloadMappingFlags::OMP_MAP_TO |
8513 OpenMPOffloadMappingFlags::OMP_MAP_FROM;
8516 void getPlainLayout(
const CXXRecordDecl *RD,
8517 llvm::SmallVectorImpl<const FieldDecl *> &Layout,
8518 bool AsBase)
const {
8521 llvm::StructType *St =
8524 unsigned NumElements = St->getNumElements();
8526 llvm::PointerUnion<const CXXRecordDecl *, const FieldDecl *>, 4>
8527 RecordLayout(NumElements);
8530 for (
const auto &I : RD->
bases()) {
8534 QualType BaseTy = I.getType();
8545 RecordLayout[FieldIndex] =
Base;
8548 for (
const auto &I : RD->
vbases()) {
8549 QualType BaseTy = I.getType();
8556 if (RecordLayout[FieldIndex])
8558 RecordLayout[FieldIndex] =
Base;
8561 assert(!RD->
isUnion() &&
"Unexpected union.");
8562 for (
const auto *Field : RD->
fields()) {
8565 if (!
Field->isBitField() &&
8568 RecordLayout[FieldIndex] =
Field;
8571 for (
const llvm::PointerUnion<const CXXRecordDecl *, const FieldDecl *>
8572 &
Data : RecordLayout) {
8575 if (
const auto *Base = dyn_cast<const CXXRecordDecl *>(
Data))
8576 getPlainLayout(Base, Layout,
true);
8583 static Address getAttachPtrAddr(
const Expr *PointerExpr,
8584 CodeGenFunction &CGF) {
8585 assert(PointerExpr &&
"Cannot get addr from null attach-ptr expr");
8588 if (
auto *DRE = dyn_cast<DeclRefExpr>(PointerExpr)) {
8591 }
else if (
auto *OASE = dyn_cast<ArraySectionExpr>(PointerExpr)) {
8594 }
else if (
auto *ASE = dyn_cast<ArraySubscriptExpr>(PointerExpr)) {
8596 }
else if (
auto *ME = dyn_cast<MemberExpr>(PointerExpr)) {
8598 }
else if (
auto *UO = dyn_cast<UnaryOperator>(PointerExpr)) {
8599 assert(UO->getOpcode() == UO_Deref &&
8600 "Unexpected unary-operator on attach-ptr-expr");
8603 assert(AttachPtrAddr.
isValid() &&
8604 "Failed to get address for attach pointer expression");
8605 return AttachPtrAddr;
8612 static std::pair<Address, Address>
8613 getAttachPtrAddrAndPteeBaseAddr(
const Expr *AttachPtrExpr,
8614 CodeGenFunction &CGF) {
8619 Address AttachPtrAddr = getAttachPtrAddr(AttachPtrExpr, CGF);
8620 assert(AttachPtrAddr.
isValid() &&
"Invalid attach pointer addr");
8622 QualType AttachPtrType =
8627 AttachPtrAddr, AttachPtrType->
castAs<PointerType>());
8628 assert(AttachPteeBaseAddr.
isValid() &&
"Invalid attach pointee base addr");
8630 return {AttachPtrAddr, AttachPteeBaseAddr};
8636 shouldEmitAttachEntry(
const Expr *PointerExpr,
const ValueDecl *MapBaseDecl,
8637 CodeGenFunction &CGF,
8638 llvm::PointerUnion<
const OMPExecutableDirective *,
8639 const OMPDeclareMapperDecl *>
8649 ->getDirectiveKind());
8658 void collectAttachPtrExprInfo(
8660 llvm::PointerUnion<
const OMPExecutableDirective *,
8661 const OMPDeclareMapperDecl *>
8666 ? OMPD_declare_mapper
8669 const auto &[AttachPtrExpr, Depth] =
8673 AttachPtrComputationOrderMap.try_emplace(
8674 AttachPtrExpr, AttachPtrComputationOrderMap.size());
8675 AttachPtrComponentDepthMap.try_emplace(AttachPtrExpr, Depth);
8676 AttachPtrExprMap.try_emplace(Components, AttachPtrExpr);
8684 void generateAllInfoForClauses(
8685 ArrayRef<const OMPClause *> Clauses, MapCombinedInfoTy &CombinedInfo,
8686 llvm::OpenMPIRBuilder &OMPBuilder,
8687 const llvm::DenseSet<CanonicalDeclPtr<const Decl>> &SkipVarSet =
8688 llvm::DenseSet<CanonicalDeclPtr<const Decl>>())
const {
8693 llvm::MapVector<CanonicalDeclPtr<const Decl>,
8694 SmallVector<SmallVector<MapInfo, 8>, 4>>
8700 [&Info, &SkipVarSet](
8701 const ValueDecl *D, MapKind
Kind,
8704 ArrayRef<OpenMPMapModifierKind> MapModifiers,
8705 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
8706 bool ReturnDevicePointer,
bool IsImplicit,
const ValueDecl *Mapper,
8707 const Expr *VarRef =
nullptr,
bool ForDeviceAddr =
false) {
8708 if (SkipVarSet.contains(D))
8710 auto It = Info.try_emplace(D, Total).first;
8711 It->second[
Kind].emplace_back(
8712 L, MapType, MapModifiers, MotionModifiers, ReturnDevicePointer,
8713 IsImplicit, Mapper, VarRef, ForDeviceAddr);
8716 for (
const auto *
Cl : Clauses) {
8717 const auto *
C = dyn_cast<OMPMapClause>(
Cl);
8721 if (llvm::is_contained(
C->getMapTypeModifiers(),
8722 OMPC_MAP_MODIFIER_present))
8724 else if (
C->getMapType() == OMPC_MAP_alloc)
8726 const auto *EI =
C->getVarRefs().begin();
8727 for (
const auto L :
C->component_lists()) {
8728 const Expr *E = (
C->getMapLoc().isValid()) ? *EI :
nullptr;
8729 InfoGen(std::get<0>(L), Kind, std::get<1>(L),
C->getMapType(),
8730 C->getMapTypeModifiers(), {},
8731 false,
C->isImplicit(), std::get<2>(L),
8736 for (
const auto *
Cl : Clauses) {
8737 const auto *
C = dyn_cast<OMPToClause>(
Cl);
8741 if (llvm::is_contained(
C->getMotionModifiers(),
8742 OMPC_MOTION_MODIFIER_present))
8744 if (llvm::is_contained(
C->getMotionModifiers(),
8745 OMPC_MOTION_MODIFIER_iterator)) {
8746 if (
auto *IteratorExpr = dyn_cast<OMPIteratorExpr>(
8747 C->getIteratorModifier()->IgnoreParenImpCasts())) {
8748 const auto *VD =
cast<VarDecl>(IteratorExpr->getIteratorDecl(0));
8753 const auto *EI =
C->getVarRefs().begin();
8754 for (
const auto L :
C->component_lists()) {
8755 InfoGen(std::get<0>(L), Kind, std::get<1>(L), OMPC_MAP_to, {},
8756 C->getMotionModifiers(),
false,
8757 C->isImplicit(), std::get<2>(L), *EI);
8761 for (
const auto *
Cl : Clauses) {
8762 const auto *
C = dyn_cast<OMPFromClause>(
Cl);
8766 if (llvm::is_contained(
C->getMotionModifiers(),
8767 OMPC_MOTION_MODIFIER_present))
8769 if (llvm::is_contained(
C->getMotionModifiers(),
8770 OMPC_MOTION_MODIFIER_iterator)) {
8771 if (
auto *IteratorExpr = dyn_cast<OMPIteratorExpr>(
8772 C->getIteratorModifier()->IgnoreParenImpCasts())) {
8773 const auto *VD =
cast<VarDecl>(IteratorExpr->getIteratorDecl(0));
8778 const auto *EI =
C->getVarRefs().begin();
8779 for (
const auto L :
C->component_lists()) {
8780 InfoGen(std::get<0>(L), Kind, std::get<1>(L), OMPC_MAP_from, {},
8781 C->getMotionModifiers(),
8782 false,
C->isImplicit(), std::get<2>(L),
8795 MapCombinedInfoTy UseDeviceDataCombinedInfo;
8797 auto &&UseDeviceDataCombinedInfoGen =
8798 [&UseDeviceDataCombinedInfo](
const ValueDecl *VD, llvm::Value *Ptr,
8799 CodeGenFunction &CGF,
bool IsDevAddr) {
8800 UseDeviceDataCombinedInfo.Exprs.push_back(VD);
8801 UseDeviceDataCombinedInfo.BasePointers.emplace_back(Ptr);
8802 UseDeviceDataCombinedInfo.DevicePtrDecls.emplace_back(VD);
8803 UseDeviceDataCombinedInfo.DevicePointers.emplace_back(
8804 IsDevAddr ? DeviceInfoTy::Address : DeviceInfoTy::Pointer);
8810 UseDeviceDataCombinedInfo.Pointers.push_back(Ptr);
8811 UseDeviceDataCombinedInfo.Sizes.push_back(
8812 llvm::Constant::getNullValue(CGF.Int64Ty));
8813 UseDeviceDataCombinedInfo.Types.push_back(
8814 OpenMPOffloadMappingFlags::OMP_MAP_RETURN_PARAM);
8815 UseDeviceDataCombinedInfo.Mappers.push_back(
nullptr);
8819 [&UseDeviceDataCombinedInfoGen](
8820 CodeGenFunction &CGF,
const Expr *IE,
const ValueDecl *VD,
8823 bool IsDevAddr,
bool IEIsAttachPtrForDevAddr =
false) {
8827 if (IsDevAddr && !IEIsAttachPtrForDevAddr) {
8828 if (IE->isGLValue())
8835 bool TreatDevAddrAsDevPtr = IEIsAttachPtrForDevAddr;
8842 UseDeviceDataCombinedInfoGen(VD, Ptr, CGF, IsDevAddr &&
8843 !TreatDevAddrAsDevPtr);
8846 auto &&IsMapInfoExist = [&Info,
this](CodeGenFunction &CGF,
8847 const ValueDecl *VD,
const Expr *IE,
8848 const Expr *DesiredAttachPtrExpr,
8849 bool IsDevAddr) ->
bool {
8857 if (It != Info.end()) {
8859 for (
auto &
Data : It->second) {
8860 MapInfo *CI =
nullptr;
8864 auto *It = llvm::find_if(
Data, [&](
const MapInfo &MI) {
8865 if (MI.Components.back().getAssociatedDeclaration() != VD)
8868 const Expr *MapAttachPtr = getAttachPtrExpr(MI.Components);
8869 bool Match = AttachPtrComparator.areEqual(MapAttachPtr,
8870 DesiredAttachPtrExpr);
8874 if (It !=
Data.end())
8879 CI->ForDeviceAddr =
true;
8880 CI->ReturnDevicePointer =
true;
8884 auto PrevCI = std::next(CI->Components.rbegin());
8885 const auto *VarD = dyn_cast<VarDecl>(VD);
8886 const Expr *AttachPtrExpr = getAttachPtrExpr(CI->Components);
8887 if (CGF.CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory() ||
8889 !VD->getType().getNonReferenceType()->isPointerType() ||
8890 PrevCI == CI->Components.rend() ||
8892 VarD->hasLocalStorage() ||
8893 (isa_and_nonnull<DeclRefExpr>(AttachPtrExpr) &&
8895 CI->ForDeviceAddr = IsDevAddr;
8896 CI->ReturnDevicePointer =
true;
8914 for (
const auto *
Cl : Clauses) {
8915 const auto *
C = dyn_cast<OMPUseDevicePtrClause>(
Cl);
8918 for (
const auto L :
C->component_lists()) {
8921 assert(!Components.empty() &&
8922 "Not expecting empty list of components!");
8923 const ValueDecl *VD = Components.back().getAssociatedDeclaration();
8925 const Expr *IE = Components.back().getAssociatedExpression();
8933 const Expr *UDPOperandExpr =
8934 Components.front().getAssociatedExpression();
8935 if (IsMapInfoExist(CGF, VD, IE,
8939 MapInfoGen(CGF, IE, VD, Components,
false);
8943 llvm::SmallDenseSet<CanonicalDeclPtr<const Decl>, 4> Processed;
8944 for (
const auto *
Cl : Clauses) {
8945 const auto *
C = dyn_cast<OMPUseDeviceAddrClause>(
Cl);
8948 for (
const auto L :
C->component_lists()) {
8951 assert(!std::get<1>(L).empty() &&
8952 "Not expecting empty list of components!");
8953 const ValueDecl *VD = std::get<1>(L).back().getAssociatedDeclaration();
8954 if (!Processed.insert(VD).second)
8975 const Expr *UDAAttachPtrExpr = getAttachPtrExpr(Components);
8976 const Expr *IE = std::get<1>(L).back().getAssociatedExpression();
8977 assert((!UDAAttachPtrExpr || UDAAttachPtrExpr == IE) &&
8978 "use_device_addr operand has an attach-ptr, but does not match "
8979 "last component's expr.");
8980 if (IsMapInfoExist(CGF, VD, IE,
8984 MapInfoGen(CGF, IE, VD, Components,
8986 UDAAttachPtrExpr !=
nullptr);
8990 for (
const auto &
Data : Info) {
8991 MapCombinedInfoTy CurInfo;
8993 const ValueDecl *VD = cast_or_null<ValueDecl>(D);
9000 SmallVector<std::pair<const Expr *, MapInfo>, 16> AttachPtrMapInfoPairs;
9003 for (
const auto &M :
Data.second) {
9004 for (
const MapInfo &L : M) {
9005 assert(!L.Components.empty() &&
9006 "Not expecting declaration with no component lists.");
9008 const Expr *AttachPtrExpr = getAttachPtrExpr(L.Components);
9009 AttachPtrMapInfoPairs.emplace_back(AttachPtrExpr, L);
9014 llvm::stable_sort(AttachPtrMapInfoPairs,
9015 [
this](
const auto &LHS,
const auto &RHS) {
9016 return AttachPtrComparator(LHS.first, RHS.first);
9021 auto *It = AttachPtrMapInfoPairs.begin();
9022 while (It != AttachPtrMapInfoPairs.end()) {
9023 const Expr *AttachPtrExpr = It->first;
9025 SmallVector<MapInfo, 8> GroupLists;
9026 while (It != AttachPtrMapInfoPairs.end() &&
9027 (It->first == AttachPtrExpr ||
9028 AttachPtrComparator.areEqual(It->first, AttachPtrExpr))) {
9029 GroupLists.push_back(It->second);
9032 assert(!GroupLists.empty() &&
"GroupLists should not be empty");
9034 StructRangeInfoTy PartialStruct;
9035 AttachInfoTy AttachInfo;
9036 MapCombinedInfoTy GroupCurInfo;
9038 MapCombinedInfoTy GroupStructBaseCurInfo;
9039 for (
const MapInfo &L : GroupLists) {
9041 unsigned CurrentBasePointersIdx = GroupCurInfo.BasePointers.size();
9042 unsigned StructBasePointersIdx =
9043 GroupStructBaseCurInfo.BasePointers.size();
9045 GroupCurInfo.NonContigInfo.IsNonContiguous =
9046 L.Components.back().isNonContiguous();
9047 generateInfoForComponentList(
9048 L.MapType, L.MapModifiers, L.MotionModifiers, L.Components,
9049 GroupCurInfo, GroupStructBaseCurInfo, PartialStruct, AttachInfo,
9050 false, L.IsImplicit,
9051 true, L.Mapper, L.ForDeviceAddr, VD,
9056 if (L.ReturnDevicePointer) {
9060 assert((CurrentBasePointersIdx < GroupCurInfo.BasePointers.size() ||
9061 StructBasePointersIdx <
9062 GroupStructBaseCurInfo.BasePointers.size()) &&
9063 "Unexpected number of mapped base pointers.");
9066 const ValueDecl *RelevantVD =
9067 L.Components.back().getAssociatedDeclaration();
9068 assert(RelevantVD &&
9069 "No relevant declaration related with device pointer??");
9076 if (StructBasePointersIdx <
9077 GroupStructBaseCurInfo.BasePointers.size()) {
9078 GroupStructBaseCurInfo.DevicePtrDecls[StructBasePointersIdx] =
9080 GroupStructBaseCurInfo.DevicePointers[StructBasePointersIdx] =
9081 L.ForDeviceAddr ? DeviceInfoTy::Address
9082 : DeviceInfoTy::Pointer;
9083 GroupStructBaseCurInfo.Types[StructBasePointersIdx] |=
9084 OpenMPOffloadMappingFlags::OMP_MAP_RETURN_PARAM;
9086 GroupCurInfo.DevicePtrDecls[CurrentBasePointersIdx] = RelevantVD;
9087 GroupCurInfo.DevicePointers[CurrentBasePointersIdx] =
9088 L.ForDeviceAddr ? DeviceInfoTy::Address
9089 : DeviceInfoTy::Pointer;
9090 GroupCurInfo.Types[CurrentBasePointersIdx] |=
9091 OpenMPOffloadMappingFlags::OMP_MAP_RETURN_PARAM;
9098 MapCombinedInfoTy GroupUnionCurInfo;
9099 GroupUnionCurInfo.append(GroupStructBaseCurInfo);
9100 GroupUnionCurInfo.append(GroupCurInfo);
9104 if (PartialStruct.Base.isValid()) {
9112 GroupUnionCurInfo.NonContigInfo.Dims.insert(
9113 GroupUnionCurInfo.NonContigInfo.Dims.begin(), 1);
9115 CurInfo, GroupUnionCurInfo.Types, PartialStruct, AttachInfo,
9116 !VD, OMPBuilder, VD,
9117 CombinedInfo.BasePointers.size(),
9123 CurInfo.append(GroupUnionCurInfo);
9124 if (AttachInfo.isValid())
9125 emitAttachEntry(CGF, CurInfo, AttachInfo);
9129 CombinedInfo.append(CurInfo);
9132 CombinedInfo.append(UseDeviceDataCombinedInfo);
9136 MappableExprsHandler(
const OMPExecutableDirective &Dir, CodeGenFunction &CGF)
9137 : CurDir(&Dir), CGF(CGF), AttachPtrComparator(*this) {
9139 for (
const auto *
C : Dir.getClausesOfKind<OMPFirstprivateClause>())
9140 for (
const auto *D :
C->varlist())
9141 FirstPrivateDecls.try_emplace(
9144 for (
const auto *
C : Dir.getClausesOfKind<OMPUsesAllocatorsClause>()) {
9145 for (unsigned I = 0, E = C->getNumberOfAllocators(); I < E; ++I) {
9146 OMPUsesAllocatorsClause::Data D = C->getAllocatorData(I);
9147 if (const auto *DRE = dyn_cast_or_null<DeclRefExpr>(D.AllocatorTraits))
9148 FirstPrivateDecls.try_emplace(cast<VarDecl>(DRE->getDecl()),
9150 else if (const auto *VD = dyn_cast<VarDecl>(
9151 cast<DeclRefExpr>(D.Allocator->IgnoreParenImpCasts())
9153 FirstPrivateDecls.try_emplace(VD, true);
9157 for (
const auto *
C : Dir.getClausesOfKind<OMPDefaultmapClause>())
9158 if (
C->getDefaultmapModifier() == OMPC_DEFAULTMAP_MODIFIER_firstprivate)
9159 DefaultmapFirstprivateKinds.insert(
C->getDefaultmapKind());
9161 for (
const auto *
C : Dir.getClausesOfKind<OMPIsDevicePtrClause>())
9162 for (
auto L :
C->component_lists())
9163 DevPointersMap[std::get<0>(L)].push_back(std::get<1>(L));
9165 for (
const auto *
C : Dir.getClausesOfKind<OMPHasDeviceAddrClause>())
9166 for (
auto L :
C->component_lists())
9167 HasDevAddrsMap[std::get<0>(L)].push_back(std::get<1>(L));
9169 for (
const auto *
C : Dir.getClausesOfKind<OMPMapClause>()) {
9170 if (C->getMapType() != OMPC_MAP_to)
9172 for (auto L : C->component_lists()) {
9173 const ValueDecl *VD = std::get<0>(L);
9174 const auto *RD = VD ? VD->getType()
9176 .getNonReferenceType()
9177 ->getAsCXXRecordDecl()
9179 if (RD && RD->isLambda())
9180 LambdasMap.try_emplace(std::get<0>(L), C);
9184 auto CollectAttachPtrExprsForClauseComponents = [
this](
const auto *
C) {
9185 for (
auto L :
C->component_lists()) {
9188 if (!Components.empty())
9189 collectAttachPtrExprInfo(Components, CurDir);
9195 for (
const auto *
C : Dir.getClausesOfKind<OMPMapClause>())
9196 CollectAttachPtrExprsForClauseComponents(
C);
9197 for (
const auto *
C : Dir.getClausesOfKind<OMPToClause>())
9198 CollectAttachPtrExprsForClauseComponents(
C);
9199 for (
const auto *
C : Dir.getClausesOfKind<OMPFromClause>())
9200 CollectAttachPtrExprsForClauseComponents(
C);
9201 for (
const auto *
C : Dir.getClausesOfKind<OMPUseDevicePtrClause>())
9202 CollectAttachPtrExprsForClauseComponents(
C);
9203 for (
const auto *
C : Dir.getClausesOfKind<OMPUseDeviceAddrClause>())
9204 CollectAttachPtrExprsForClauseComponents(
C);
9205 for (
const auto *
C : Dir.getClausesOfKind<OMPIsDevicePtrClause>())
9206 CollectAttachPtrExprsForClauseComponents(
C);
9207 for (
const auto *
C : Dir.getClausesOfKind<OMPHasDeviceAddrClause>())
9208 CollectAttachPtrExprsForClauseComponents(
C);
9212 MappableExprsHandler(
const OMPDeclareMapperDecl &Dir,
CodeGenFunction &CGF)
9213 : CurDir(&Dir), CGF(CGF), AttachPtrComparator(*this) {}
9223 void emitCombinedEntry(MapCombinedInfoTy &CombinedInfo,
9224 MapFlagsArrayTy &CurTypes,
9225 const StructRangeInfoTy &PartialStruct,
9226 AttachInfoTy &AttachInfo,
bool IsMapThis,
9227 llvm::OpenMPIRBuilder &OMPBuilder,
const ValueDecl *VD,
9228 unsigned OffsetForMemberOfFlag,
9229 bool NotTargetParams)
const {
9230 if (CurTypes.size() == 1 &&
9231 ((CurTypes.back() & OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF) !=
9232 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF) &&
9233 !PartialStruct.IsArraySection)
9235 Address LBAddr = PartialStruct.LowestElem.second;
9236 Address HBAddr = PartialStruct.HighestElem.second;
9237 if (PartialStruct.HasCompleteRecord) {
9238 LBAddr = PartialStruct.LB;
9239 HBAddr = PartialStruct.LB;
9241 CombinedInfo.Exprs.push_back(VD);
9243 CombinedInfo.BasePointers.push_back(PartialStruct.Base.emitRawPointer(CGF));
9244 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
9245 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
9248 const CXXMethodDecl *MD =
9250 const CXXRecordDecl *RD = MD ? MD->
getParent() :
nullptr;
9251 bool HasBaseClass = RD && IsMapThis ? RD->
getNumBases() > 0 :
false;
9261 CombinedInfo.Pointers.push_back(PartialStruct.Base.emitRawPointer(CGF));
9266 CombinedInfo.Sizes.push_back(Size);
9268 CombinedInfo.Pointers.push_back(LB);
9271 llvm::Value *HAddr = CGF.
Builder.CreateConstGEP1_32(
9275 llvm::Value *Diff = CGF.
Builder.CreatePtrDiff(CGF.
Int8Ty, CHAddr, CLAddr);
9278 CombinedInfo.Sizes.push_back(Size);
9280 CombinedInfo.Mappers.push_back(
nullptr);
9282 CombinedInfo.Types.push_back(
9283 NotTargetParams ? OpenMPOffloadMappingFlags::OMP_MAP_NONE
9284 : !PartialStruct.PreliminaryMapData.BasePointers.empty()
9285 ? OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ
9286 : OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM);
9289 if (CurTypes.end() !=
9290 llvm::find_if(CurTypes, [](OpenMPOffloadMappingFlags
Type) {
9291 return static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>>(
9292 Type & OpenMPOffloadMappingFlags::OMP_MAP_PRESENT);
9294 CombinedInfo.Types.back() |= OpenMPOffloadMappingFlags::OMP_MAP_PRESENT;
9296 (*CurTypes.begin()) &= ~OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM;
9303 if (CurTypes.end() !=
9304 llvm::find_if(CurTypes, [](OpenMPOffloadMappingFlags
Type) {
9305 return static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>>(
9306 Type & OpenMPOffloadMappingFlags::OMP_MAP_OMPX_HOLD);
9308 CombinedInfo.Types.back() |= OpenMPOffloadMappingFlags::OMP_MAP_OMPX_HOLD;
9309 for (
auto &M : CurTypes)
9310 M |= OpenMPOffloadMappingFlags::OMP_MAP_OMPX_HOLD;
9317 OpenMPOffloadMappingFlags MemberOfFlag = OMPBuilder.getMemberOfFlag(
9318 OffsetForMemberOfFlag + CombinedInfo.BasePointers.size() - 1);
9319 for (
auto &M : CurTypes)
9320 OMPBuilder.setCorrectMemberOfFlag(M, MemberOfFlag);
9337 if (AttachInfo.isValid())
9338 AttachInfo.AttachPteeAddr = LBAddr;
9346 void generateAllInfo(
9347 MapCombinedInfoTy &CombinedInfo, llvm::OpenMPIRBuilder &OMPBuilder,
9348 const llvm::DenseSet<CanonicalDeclPtr<const Decl>> &SkipVarSet =
9349 llvm::DenseSet<CanonicalDeclPtr<const Decl>>())
const {
9351 "Expect a executable directive");
9353 generateAllInfoForClauses(CurExecDir->clauses(), CombinedInfo, OMPBuilder,
9360 void generateAllInfoForMapper(MapCombinedInfoTy &CombinedInfo,
9361 llvm::OpenMPIRBuilder &OMPBuilder)
const {
9363 "Expect a declare mapper directive");
9365 generateAllInfoForClauses(CurMapperDir->clauses(), CombinedInfo,
9370 void generateInfoForLambdaCaptures(
9371 const ValueDecl *VD, llvm::Value *Arg, MapCombinedInfoTy &CombinedInfo,
9372 llvm::DenseMap<llvm::Value *, llvm::Value *> &LambdaPointers)
const {
9380 llvm::DenseMap<const ValueDecl *, FieldDecl *> Captures;
9381 FieldDecl *ThisCapture =
nullptr;
9387 LambdaPointers.try_emplace(ThisLVal.getPointer(CGF),
9388 VDLVal.getPointer(CGF));
9389 CombinedInfo.Exprs.push_back(VD);
9390 CombinedInfo.BasePointers.push_back(ThisLVal.getPointer(CGF));
9391 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
9392 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
9393 CombinedInfo.Pointers.push_back(ThisLValVal.getPointer(CGF));
9394 CombinedInfo.Sizes.push_back(
9397 CombinedInfo.Types.push_back(
9398 OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ |
9399 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL |
9400 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF |
9401 OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT);
9402 CombinedInfo.Mappers.push_back(
nullptr);
9404 for (
const LambdaCapture &LC : RD->
captures()) {
9405 if (!LC.capturesVariable())
9410 auto It = Captures.find(VD);
9411 assert(It != Captures.end() &&
"Found lambda capture without field.");
9415 LambdaPointers.try_emplace(VarLVal.getPointer(CGF),
9416 VDLVal.getPointer(CGF));
9417 CombinedInfo.Exprs.push_back(VD);
9418 CombinedInfo.BasePointers.push_back(VarLVal.getPointer(CGF));
9419 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
9420 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
9421 CombinedInfo.Pointers.push_back(VarLValVal.getPointer(CGF));
9422 CombinedInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
9428 LambdaPointers.try_emplace(VarLVal.getPointer(CGF),
9429 VDLVal.getPointer(CGF));
9430 CombinedInfo.Exprs.push_back(VD);
9431 CombinedInfo.BasePointers.push_back(VarLVal.getPointer(CGF));
9432 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
9433 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
9434 CombinedInfo.Pointers.push_back(VarRVal.
getScalarVal());
9435 CombinedInfo.Sizes.push_back(llvm::ConstantInt::get(CGF.
Int64Ty, 0));
9437 CombinedInfo.Types.push_back(
9438 OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ |
9439 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL |
9440 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF |
9441 OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT);
9442 CombinedInfo.Mappers.push_back(
nullptr);
9447 void adjustMemberOfForLambdaCaptures(
9448 llvm::OpenMPIRBuilder &OMPBuilder,
9449 const llvm::DenseMap<llvm::Value *, llvm::Value *> &LambdaPointers,
9450 MapBaseValuesArrayTy &BasePointers, MapValuesArrayTy &Pointers,
9451 MapFlagsArrayTy &Types)
const {
9452 for (
unsigned I = 0, E = Types.size(); I < E; ++I) {
9454 if (Types[I] != (OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ |
9455 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL |
9456 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF |
9457 OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT))
9459 llvm::Value *BasePtr = LambdaPointers.lookup(BasePointers[I]);
9460 assert(BasePtr &&
"Unable to find base lambda address.");
9462 for (
unsigned J = I; J > 0; --J) {
9463 unsigned Idx = J - 1;
9464 if (Pointers[Idx] != BasePtr)
9469 assert(TgtIdx != -1 &&
"Unable to find parent lambda.");
9473 OpenMPOffloadMappingFlags MemberOfFlag =
9474 OMPBuilder.getMemberOfFlag(TgtIdx);
9475 OMPBuilder.setCorrectMemberOfFlag(Types[I], MemberOfFlag);
9481 void populateComponentListsForNonLambdaCaptureFromClauses(
9482 const ValueDecl *VD, MapDataArrayTy &DeclComponentLists,
9484 SmallVector<OMPClauseMappableExprCommon::MappableComponent, 8>>
9485 &StorageForImplicitlyAddedComponentLists)
const {
9486 if (VD && LambdasMap.count(VD))
9492 auto It = DevPointersMap.find(VD);
9493 if (It != DevPointersMap.end())
9494 for (
const auto &MCL : It->second)
9495 DeclComponentLists.emplace_back(MCL, OMPC_MAP_to,
Unknown,
9498 auto I = HasDevAddrsMap.find(VD);
9499 if (I != HasDevAddrsMap.end())
9500 for (
const auto &MCL : I->second)
9501 DeclComponentLists.emplace_back(MCL, OMPC_MAP_tofrom,
Unknown,
9505 "Expect a executable directive");
9507 for (
const auto *
C : CurExecDir->getClausesOfKind<OMPMapClause>()) {
9508 const auto *EI =
C->getVarRefs().begin();
9509 for (
const auto L :
C->decl_component_lists(VD)) {
9510 const ValueDecl *VDecl, *Mapper;
9512 const Expr *E = (
C->getMapLoc().isValid()) ? *EI :
nullptr;
9514 std::tie(VDecl, Components, Mapper) = L;
9515 assert(VDecl == VD &&
"We got information for the wrong declaration??");
9516 assert(!Components.empty() &&
9517 "Not expecting declaration with no component lists.");
9518 DeclComponentLists.emplace_back(Components,
C->getMapType(),
9519 C->getMapTypeModifiers(),
9520 C->isImplicit(), Mapper, E);
9529 addImplicitMapForAttachPtrBaseIfMemberOfCapturedVD(
9530 VD, DeclComponentLists, StorageForImplicitlyAddedComponentLists);
9532 llvm::stable_sort(DeclComponentLists, [](
const MapData &LHS,
9533 const MapData &RHS) {
9534 ArrayRef<OpenMPMapModifierKind> MapModifiers = std::get<2>(LHS);
9537 llvm::is_contained(MapModifiers, clang::OMPC_MAP_MODIFIER_present);
9538 bool HasAllocs = MapType == OMPC_MAP_alloc;
9539 MapModifiers = std::get<2>(RHS);
9540 MapType = std::get<1>(LHS);
9542 llvm::is_contained(MapModifiers, clang::OMPC_MAP_MODIFIER_present);
9543 bool HasAllocsR = MapType == OMPC_MAP_alloc;
9544 return (HasPresent && !HasPresentR) || (HasAllocs && !HasAllocsR);
9580 void addImplicitMapForAttachPtrBaseIfMemberOfCapturedVD(
9581 const ValueDecl *CapturedVD, MapDataArrayTy &DeclComponentLists,
9583 SmallVector<OMPClauseMappableExprCommon::MappableComponent, 8>>
9584 &ComponentVectorStorage)
const {
9585 bool IsThisCapture = CapturedVD ==
nullptr;
9587 for (
const auto &ComponentsAndAttachPtr : AttachPtrExprMap) {
9589 ComponentsWithAttachPtr = ComponentsAndAttachPtr.first;
9590 const Expr *AttachPtrExpr = ComponentsAndAttachPtr.second;
9594 const auto *ME = dyn_cast<MemberExpr>(AttachPtrExpr);
9598 const Expr *
Base = ME->getBase()->IgnoreParenImpCasts();
9619 bool FoundExistingMap =
false;
9620 for (
const MapData &ExistingL : DeclComponentLists) {
9622 ExistingComponents = std::get<0>(ExistingL);
9624 if (ExistingComponents.empty())
9628 const auto &FirstComponent = ExistingComponents.front();
9629 const Expr *FirstExpr = FirstComponent.getAssociatedExpression();
9635 if (AttachPtrComparator.areEqual(FirstExpr, AttachPtrExpr)) {
9636 FoundExistingMap =
true;
9641 if (IsThisCapture) {
9642 if (
const auto *OASE = dyn_cast<ArraySectionExpr>(FirstExpr)) {
9644 FoundExistingMap =
true;
9653 if (
const auto *DRE = dyn_cast<DeclRefExpr>(FirstExpr)) {
9654 if (DRE->getDecl() == CapturedVD) {
9655 FoundExistingMap =
true;
9661 if (FoundExistingMap)
9667 ComponentVectorStorage.emplace_back();
9668 auto &AttachPtrComponents = ComponentVectorStorage.back();
9671 bool SeenAttachPtrComponent =
false;
9677 for (
size_t i = 0; i < ComponentsWithAttachPtr.size(); ++i) {
9678 const auto &Component = ComponentsWithAttachPtr[i];
9679 const Expr *ComponentExpr = Component.getAssociatedExpression();
9681 if (!SeenAttachPtrComponent && ComponentExpr != AttachPtrExpr)
9683 SeenAttachPtrComponent =
true;
9685 AttachPtrComponents.emplace_back(Component.getAssociatedExpression(),
9686 Component.getAssociatedDeclaration(),
9687 Component.isNonContiguous());
9689 assert(!AttachPtrComponents.empty() &&
9690 "Could not populate component-lists for mapping attach-ptr");
9692 DeclComponentLists.emplace_back(
9693 AttachPtrComponents, OMPC_MAP_tofrom,
Unknown,
9694 true,
nullptr, AttachPtrExpr);
9701 void generateInfoForCaptureFromClauseInfo(
9702 const MapDataArrayTy &DeclComponentListsFromClauses,
9703 const CapturedStmt::Capture *Cap, llvm::Value *Arg,
9704 MapCombinedInfoTy &CurCaptureVarInfo, llvm::OpenMPIRBuilder &OMPBuilder,
9705 unsigned OffsetForMemberOfFlag)
const {
9707 "Not expecting to generate map info for a variable array type!");
9716 if (LambdasMap.count(VD))
9722 if (VD && (DevPointersMap.count(VD) || HasDevAddrsMap.count(VD))) {
9723 CurCaptureVarInfo.Exprs.push_back(VD);
9724 CurCaptureVarInfo.BasePointers.emplace_back(Arg);
9725 CurCaptureVarInfo.DevicePtrDecls.emplace_back(VD);
9726 CurCaptureVarInfo.DevicePointers.emplace_back(DeviceInfoTy::Pointer);
9727 CurCaptureVarInfo.Pointers.push_back(Arg);
9728 CurCaptureVarInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
9731 CurCaptureVarInfo.Types.push_back(
9732 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL |
9733 OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM);
9734 CurCaptureVarInfo.Mappers.push_back(
nullptr);
9738 auto GenerateInfoForComponentLists =
9739 [&](ArrayRef<MapData> DeclComponentListsFromClauses,
9740 bool IsEligibleForTargetParamFlag) {
9741 MapCombinedInfoTy CurInfoForComponentLists;
9742 StructRangeInfoTy PartialStruct;
9743 AttachInfoTy AttachInfo;
9745 if (DeclComponentListsFromClauses.empty())
9748 generateInfoForCaptureFromComponentLists(
9749 VD, DeclComponentListsFromClauses, CurInfoForComponentLists,
9750 PartialStruct, AttachInfo, IsEligibleForTargetParamFlag);
9755 if (PartialStruct.Base.isValid()) {
9756 CurCaptureVarInfo.append(PartialStruct.PreliminaryMapData);
9758 CurCaptureVarInfo, CurInfoForComponentLists.Types,
9759 PartialStruct, AttachInfo, Cap->
capturesThis(), OMPBuilder,
9760 nullptr, OffsetForMemberOfFlag,
9761 !IsEligibleForTargetParamFlag);
9766 CurCaptureVarInfo.append(CurInfoForComponentLists);
9767 if (AttachInfo.isValid())
9768 emitAttachEntry(CGF, CurCaptureVarInfo, AttachInfo);
9792 SmallVector<std::pair<const Expr *, MapData>, 16> AttachPtrMapDataPairs;
9794 for (
const MapData &L : DeclComponentListsFromClauses) {
9797 const Expr *AttachPtrExpr = getAttachPtrExpr(Components);
9798 AttachPtrMapDataPairs.emplace_back(AttachPtrExpr, L);
9802 llvm::stable_sort(AttachPtrMapDataPairs,
9803 [
this](
const auto &LHS,
const auto &RHS) {
9804 return AttachPtrComparator(LHS.first, RHS.first);
9807 bool NoDefaultMappingDoneForVD = CurCaptureVarInfo.BasePointers.empty();
9808 bool IsFirstGroup =
true;
9812 auto *It = AttachPtrMapDataPairs.begin();
9813 while (It != AttachPtrMapDataPairs.end()) {
9814 const Expr *AttachPtrExpr = It->first;
9816 MapDataArrayTy GroupLists;
9817 while (It != AttachPtrMapDataPairs.end() &&
9818 (It->first == AttachPtrExpr ||
9819 AttachPtrComparator.areEqual(It->first, AttachPtrExpr))) {
9820 GroupLists.push_back(It->second);
9823 assert(!GroupLists.empty() &&
"GroupLists should not be empty");
9828 bool IsEligibleForTargetParamFlag =
9829 IsFirstGroup && NoDefaultMappingDoneForVD;
9831 GenerateInfoForComponentLists(GroupLists, IsEligibleForTargetParamFlag);
9832 IsFirstGroup =
false;
9839 void generateInfoForCaptureFromComponentLists(
9840 const ValueDecl *VD, ArrayRef<MapData> DeclComponentLists,
9841 MapCombinedInfoTy &CurComponentListInfo, StructRangeInfoTy &PartialStruct,
9842 AttachInfoTy &AttachInfo,
bool IsListEligibleForTargetParamFlag)
const {
9844 llvm::SmallDenseMap<
9851 for (
const MapData &L : DeclComponentLists) {
9854 ArrayRef<OpenMPMapModifierKind> MapModifiers;
9856 const ValueDecl *Mapper;
9858 std::tie(Components, MapType, MapModifiers, IsImplicit, Mapper, VarRef) =
9861 for (
const MapData &L1 : ArrayRef(DeclComponentLists).slice(Count)) {
9863 std::tie(Components1, MapType, MapModifiers, IsImplicit, Mapper,
9865 auto CI = Components.rbegin();
9866 auto CE = Components.rend();
9867 auto SI = Components1.rbegin();
9868 auto SE = Components1.rend();
9869 for (; CI != CE && SI != SE; ++CI, ++SI) {
9870 if (CI->getAssociatedExpression()->getStmtClass() !=
9871 SI->getAssociatedExpression()->getStmtClass())
9874 if (CI->getAssociatedDeclaration() != SI->getAssociatedDeclaration())
9879 if (CI == CE || SI == SE) {
9881 if (CI == CE && SI == SE)
9883 const auto It = (SI == SE) ? CI : SI;
9890 (std::prev(It)->getAssociatedDeclaration() &&
9892 ->getAssociatedDeclaration()
9894 ->isPointerType()) ||
9895 (It->getAssociatedDeclaration() &&
9896 It->getAssociatedDeclaration()->getType()->isPointerType() &&
9897 std::next(It) != CE && std::next(It) != SE))
9899 const MapData &BaseData = CI == CE ? L : L1;
9901 SI == SE ? Components : Components1;
9902 OverlappedData[&BaseData].push_back(SubData);
9907 llvm::SmallVector<const FieldDecl *, 4> Layout;
9908 if (!OverlappedData.empty()) {
9911 while (BaseType != OrigType) {
9917 getPlainLayout(CRD, Layout,
false);
9923 for (
auto &Pair : OverlappedData) {
9930 auto CI = First.rbegin();
9931 auto CE = First.rend();
9932 auto SI = Second.rbegin();
9933 auto SE = Second.rend();
9934 for (; CI != CE && SI != SE; ++CI, ++SI) {
9935 if (CI->getAssociatedExpression()->getStmtClass() !=
9936 SI->getAssociatedExpression()->getStmtClass())
9939 if (CI->getAssociatedDeclaration() !=
9940 SI->getAssociatedDeclaration())
9945 if (CI == CE && SI == SE)
9949 if (CI == CE || SI == SE)
9954 if (FD1->getParent() == FD2->getParent())
9955 return FD1->getFieldIndex() < FD2->getFieldIndex();
9957 llvm::find_if(Layout, [FD1, FD2](
const FieldDecl *FD) {
9958 return FD == FD1 || FD == FD2;
9966 bool AddTargetParamFlag = IsListEligibleForTargetParamFlag;
9967 MapCombinedInfoTy StructBaseCombinedInfo;
9968 for (
const auto &Pair : OverlappedData) {
9969 const MapData &L = *Pair.getFirst();
9972 ArrayRef<OpenMPMapModifierKind> MapModifiers;
9974 const ValueDecl *Mapper;
9976 std::tie(Components, MapType, MapModifiers, IsImplicit, Mapper, VarRef) =
9978 ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef>
9979 OverlappedComponents = Pair.getSecond();
9980 generateInfoForComponentList(
9981 MapType, MapModifiers, {}, Components, CurComponentListInfo,
9982 StructBaseCombinedInfo, PartialStruct, AttachInfo, AddTargetParamFlag,
9983 IsImplicit,
false, Mapper,
9984 false, VD, VarRef, OverlappedComponents);
9985 AddTargetParamFlag =
false;
9988 for (
const MapData &L : DeclComponentLists) {
9991 ArrayRef<OpenMPMapModifierKind> MapModifiers;
9993 const ValueDecl *Mapper;
9995 std::tie(Components, MapType, MapModifiers, IsImplicit, Mapper, VarRef) =
9997 auto It = OverlappedData.find(&L);
9998 if (It == OverlappedData.end())
9999 generateInfoForComponentList(
10000 MapType, MapModifiers, {}, Components, CurComponentListInfo,
10001 StructBaseCombinedInfo, PartialStruct, AttachInfo,
10002 AddTargetParamFlag, IsImplicit,
false,
10003 Mapper,
false, VD, VarRef,
10005 AddTargetParamFlag =
false;
10011 bool isEffectivelyFirstprivate(
const VarDecl *VD, QualType
Type)
const {
10013 auto I = FirstPrivateDecls.find(VD);
10014 if (I != FirstPrivateDecls.end() && !I->getSecond())
10018 if (DefaultmapFirstprivateKinds.count(OMPC_DEFAULTMAP_scalar)) {
10019 if (
Type->isScalarType())
10024 if (DefaultmapFirstprivateKinds.count(OMPC_DEFAULTMAP_pointer)) {
10025 if (
Type->isAnyPointerType())
10030 if (DefaultmapFirstprivateKinds.count(OMPC_DEFAULTMAP_aggregate)) {
10031 if (
Type->isAggregateType())
10036 return DefaultmapFirstprivateKinds.count(OMPC_DEFAULTMAP_all);
10041 void generateDefaultMapInfo(
const CapturedStmt::Capture &CI,
10042 const FieldDecl &RI, llvm::Value *CV,
10043 MapCombinedInfoTy &CombinedInfo)
const {
10044 bool IsImplicit =
true;
10047 CombinedInfo.Exprs.push_back(
nullptr);
10048 CombinedInfo.BasePointers.push_back(CV);
10049 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
10050 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
10051 CombinedInfo.Pointers.push_back(CV);
10053 CombinedInfo.Sizes.push_back(
10057 CombinedInfo.Types.push_back(OpenMPOffloadMappingFlags::OMP_MAP_TO |
10058 OpenMPOffloadMappingFlags::OMP_MAP_FROM);
10062 CombinedInfo.BasePointers.push_back(CV);
10063 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
10064 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
10065 CombinedInfo.Pointers.push_back(CV);
10066 bool IsFirstprivate =
10072 CombinedInfo.Types.push_back(
10073 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL);
10074 CombinedInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
10076 }
else if (IsFirstprivate) {
10079 CombinedInfo.Types.push_back(
10080 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL);
10082 CombinedInfo.Sizes.push_back(llvm::Constant::getNullValue(CGF.
Int64Ty));
10086 CombinedInfo.Types.push_back(OpenMPOffloadMappingFlags::OMP_MAP_NONE);
10087 CombinedInfo.Sizes.push_back(llvm::Constant::getNullValue(CGF.
Int64Ty));
10089 auto I = FirstPrivateDecls.find(VD);
10090 if (I != FirstPrivateDecls.end())
10091 IsImplicit = I->getSecond();
10097 bool IsFirstprivate = isEffectivelyFirstprivate(VD, ElementType);
10099 CombinedInfo.BasePointers.push_back(CV);
10100 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
10101 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
10106 CombinedInfo.Pointers.push_back(CV);
10108 CombinedInfo.Sizes.push_back(llvm::Constant::getNullValue(CGF.
Int64Ty));
10109 CombinedInfo.Types.push_back(
10110 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL);
10112 CombinedInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
10117 CombinedInfo.Types.push_back(getMapModifiersForPrivateClauses(CI));
10118 CombinedInfo.Pointers.push_back(CV);
10120 auto I = FirstPrivateDecls.find(VD);
10121 if (I != FirstPrivateDecls.end())
10122 IsImplicit = I->getSecond();
10125 CombinedInfo.Types.back() |=
10126 OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM;
10130 CombinedInfo.Types.back() |= OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT;
10133 CombinedInfo.Mappers.push_back(
nullptr);
10145 dyn_cast<MemberExpr>(OASE->getBase()->IgnoreParenImpCasts()))
10146 return ME->getMemberDecl();
10152static llvm::Constant *
10154 MappableExprsHandler::MappingExprInfo &MapExprs) {
10156 uint32_t SrcLocStrSize;
10157 if (!MapExprs.getMapDecl() && !MapExprs.getMapExpr())
10158 return OMPBuilder.getOrCreateDefaultSrcLocStr(SrcLocStrSize);
10161 if (!MapExprs.getMapDecl() && MapExprs.getMapExpr()) {
10165 Loc = MapExprs.getMapExpr()->getExprLoc();
10167 Loc = MapExprs.getMapDecl()->getLocation();
10170 std::string ExprName;
10171 if (MapExprs.getMapExpr()) {
10173 llvm::raw_string_ostream OS(ExprName);
10174 MapExprs.getMapExpr()->printPretty(OS,
nullptr, P);
10176 ExprName = MapExprs.getMapDecl()->getNameAsString();
10185 return OMPBuilder.getOrCreateSrcLocStr(
FileName, ExprName, PLoc.
getLine(),
10192 CodeGenFunction &CGF, MappableExprsHandler::MapCombinedInfoTy &CombinedInfo,
10194 bool IsNonContiguous =
false,
bool ForEndCall =
false) {
10197 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
10200 InsertPointTy CodeGenIP(CGF.
Builder.GetInsertBlock(),
10201 CGF.
Builder.GetInsertPoint());
10203 auto DeviceAddrCB = [&](
unsigned int I, llvm::Value *NewDecl) {
10204 if (
const ValueDecl *DevVD = CombinedInfo.DevicePtrDecls[I]) {
10209 auto CustomMapperCB = [&](
unsigned int I) {
10210 llvm::Function *MFunc =
nullptr;
10211 if (CombinedInfo.Mappers[I]) {
10212 Info.HasMapper =
true;
10218 cantFail(OMPBuilder.emitOffloadingArraysAndArgs(
10219 AllocaIP, CodeGenIP, Info, Info.RTArgs, CombinedInfo, CustomMapperCB,
10220 IsNonContiguous, ForEndCall, DeviceAddrCB));
10224static const OMPExecutableDirective *
10226 const auto *CS = D.getInnermostCapturedStmt();
10229 const Stmt *ChildStmt =
10232 if (
const auto *NestedDir =
10233 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) {
10235 switch (D.getDirectiveKind()) {
10241 if (DKind == OMPD_teams) {
10242 Body = NestedDir->getInnermostCapturedStmt()->IgnoreContainers(
10247 if (
const auto *NND =
10248 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) {
10249 DKind = NND->getDirectiveKind();
10255 case OMPD_target_teams:
10259 case OMPD_target_parallel:
10260 case OMPD_target_simd:
10261 case OMPD_target_parallel_for:
10262 case OMPD_target_parallel_for_simd:
10264 case OMPD_target_teams_distribute:
10265 case OMPD_target_teams_distribute_simd:
10266 case OMPD_target_teams_distribute_parallel_for:
10267 case OMPD_target_teams_distribute_parallel_for_simd:
10268 case OMPD_parallel:
10270 case OMPD_parallel_for:
10271 case OMPD_parallel_master:
10272 case OMPD_parallel_sections:
10273 case OMPD_for_simd:
10274 case OMPD_parallel_for_simd:
10276 case OMPD_cancellation_point:
10278 case OMPD_threadprivate:
10279 case OMPD_allocate:
10284 case OMPD_sections:
10288 case OMPD_critical:
10289 case OMPD_taskyield:
10291 case OMPD_taskwait:
10292 case OMPD_taskgroup:
10298 case OMPD_target_data:
10299 case OMPD_target_exit_data:
10300 case OMPD_target_enter_data:
10301 case OMPD_distribute:
10302 case OMPD_distribute_simd:
10303 case OMPD_distribute_parallel_for:
10304 case OMPD_distribute_parallel_for_simd:
10305 case OMPD_teams_distribute:
10306 case OMPD_teams_distribute_simd:
10307 case OMPD_teams_distribute_parallel_for:
10308 case OMPD_teams_distribute_parallel_for_simd:
10309 case OMPD_target_update:
10310 case OMPD_declare_simd:
10311 case OMPD_declare_variant:
10312 case OMPD_begin_declare_variant:
10313 case OMPD_end_declare_variant:
10314 case OMPD_declare_target:
10315 case OMPD_end_declare_target:
10316 case OMPD_declare_reduction:
10317 case OMPD_declare_mapper:
10318 case OMPD_taskloop:
10319 case OMPD_taskloop_simd:
10320 case OMPD_master_taskloop:
10321 case OMPD_master_taskloop_simd:
10322 case OMPD_parallel_master_taskloop:
10323 case OMPD_parallel_master_taskloop_simd:
10324 case OMPD_requires:
10325 case OMPD_metadirective:
10328 llvm_unreachable(
"Unexpected directive.");
10369 if (
UDMMap.count(D) > 0)
10373 auto *MapperVarDecl =
10375 CharUnits ElementSize =
C.getTypeSizeInChars(Ty);
10376 llvm::Type *ElemTy =
CGM.getTypes().ConvertTypeForMem(Ty);
10379 MappableExprsHandler::MapCombinedInfoTy CombinedInfo;
10380 auto PrivatizeAndGenMapInfoCB =
10381 [&](llvm::OpenMPIRBuilder::InsertPointTy CodeGenIP, llvm::Value *PtrPHI,
10382 llvm::Value *BeginArg) -> llvm::OpenMPIRBuilder::MapInfosTy & {
10383 MapperCGF.
Builder.restoreIP(CodeGenIP);
10393 Scope.addPrivate(MapperVarDecl, PtrCurrent);
10394 (void)
Scope.Privatize();
10397 MappableExprsHandler MEHandler(*D, MapperCGF);
10398 MEHandler.generateAllInfoForMapper(CombinedInfo,
OMPBuilder);
10400 auto FillInfoMap = [&](MappableExprsHandler::MappingExprInfo &MapExpr) {
10403 if (
CGM.getCodeGenOpts().getDebugInfo() !=
10404 llvm::codegenoptions::NoDebugInfo) {
10405 CombinedInfo.Names.resize(CombinedInfo.Exprs.size());
10406 llvm::transform(CombinedInfo.Exprs, CombinedInfo.Names.begin(),
10410 return CombinedInfo;
10413 auto CustomMapperCB = [&](
unsigned I) {
10414 llvm::Function *MapperFunc =
nullptr;
10415 if (CombinedInfo.Mappers[I]) {
10419 assert(MapperFunc &&
"Expect a valid mapper function is available.");
10425 llvm::raw_svector_ostream Out(TyStr);
10426 CGM.getCXXABI().getMangleContext().mangleCanonicalTypeName(Ty, Out);
10427 std::string Name =
getName({
"omp_mapper", TyStr, D->
getName()});
10429 llvm::Function *NewFn = cantFail(
OMPBuilder.emitUserDefinedMapper(
10430 PrivatizeAndGenMapInfoCB, ElemTy, Name, CustomMapperCB));
10431 UDMMap.try_emplace(D, NewFn);
10438 auto I =
UDMMap.find(D);
10442 return UDMMap.lookup(D);
10455 Kind != OMPD_target_teams_loop)
10458 return llvm::ConstantInt::get(CGF.
Int64Ty, 0);
10461 if (llvm::Value *NumIterations = SizeEmitter(CGF, *LD))
10462 return NumIterations;
10463 return llvm::ConstantInt::get(CGF.
Int64Ty, 0);
10472 if (OffloadingMandatory) {
10473 CGF.
Builder.CreateUnreachable();
10475 if (RequiresOuterTask) {
10476 CapturedVars.clear();
10485 llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier>
Device,
10488 llvm::Value *DeviceID;
10489 if (
Device.getPointer()) {
10491 Device.getInt() == OMPC_DEVICE_device_num) &&
10492 "Expected device_num modifier.");
10497 DeviceID = CGF.
Builder.getInt64(OMP_DEVICEID_UNDEF);
10502static std::pair<llvm::Value *, OMPDynGroupprivateFallbackType>
10504 llvm::Value *DynGP = CGF.
Builder.getInt32(0);
10505 auto DynGPFallback = OMPDynGroupprivateFallbackType::Abort;
10509 llvm::Value *DynGPVal =
10513 auto FallbackModifier = DynGPClause->getDynGroupprivateFallbackModifier();
10514 switch (FallbackModifier) {
10515 case OMPC_DYN_GROUPPRIVATE_FALLBACK_abort:
10516 DynGPFallback = OMPDynGroupprivateFallbackType::Abort;
10518 case OMPC_DYN_GROUPPRIVATE_FALLBACK_null:
10519 DynGPFallback = OMPDynGroupprivateFallbackType::Null;
10521 case OMPC_DYN_GROUPPRIVATE_FALLBACK_default_mem:
10524 DynGPFallback = OMPDynGroupprivateFallbackType::DefaultMem;
10527 llvm_unreachable(
"Unknown fallback modifier for OpenMP dyn_groupprivate");
10529 }
else if (
auto *OMPXDynCGClause =
10532 llvm::Value *DynCGMemVal = CGF.
EmitScalarExpr(OMPXDynCGClause->getSize(),
10537 return {DynGP, DynGPFallback};
10543 llvm::OpenMPIRBuilder &OMPBuilder,
10545 MappableExprsHandler::MapCombinedInfoTy &CombinedInfo) {
10547 llvm::DenseMap<llvm::Value *, llvm::Value *> LambdaPointers;
10549 auto *CV = CapturedVars.begin();
10552 CI != CE; ++CI, ++RI, ++CV) {
10553 MappableExprsHandler::MapCombinedInfoTy CurInfo;
10558 CurInfo.Exprs.push_back(
nullptr);
10559 CurInfo.BasePointers.push_back(*CV);
10560 CurInfo.DevicePtrDecls.push_back(
nullptr);
10561 CurInfo.DevicePointers.push_back(
10562 MappableExprsHandler::DeviceInfoTy::None);
10563 CurInfo.Pointers.push_back(*CV);
10564 CurInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
10567 CurInfo.Types.push_back(OpenMPOffloadMappingFlags::OMP_MAP_LITERAL |
10568 OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM |
10569 OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT);
10570 CurInfo.Mappers.push_back(
nullptr);
10575 bool HasEntryWithCVAsAttachPtr =
false;
10577 HasEntryWithCVAsAttachPtr =
10578 MEHandler.hasAttachEntryForCapturedVar(CapturedVD);
10581 MappableExprsHandler::MapDataArrayTy DeclComponentLists;
10584 StorageForImplicitlyAddedComponentLists;
10585 MEHandler.populateComponentListsForNonLambdaCaptureFromClauses(
10586 CapturedVD, DeclComponentLists,
10587 StorageForImplicitlyAddedComponentLists);
10598 bool HasEntryWithoutAttachPtr =
10599 llvm::any_of(DeclComponentLists, [&](
const auto &MapData) {
10601 Components = std::get<0>(MapData);
10602 return !MEHandler.getAttachPtrExpr(Components);
10607 if (DeclComponentLists.empty() ||
10608 (!HasEntryWithCVAsAttachPtr && !HasEntryWithoutAttachPtr))
10609 MEHandler.generateDefaultMapInfo(*CI, **RI, *CV, CurInfo);
10613 MEHandler.generateInfoForCaptureFromClauseInfo(
10614 DeclComponentLists, CI, *CV, CurInfo, OMPBuilder,
10615 CombinedInfo.BasePointers.size());
10620 MappedVarSet.insert(
nullptr);
10625 MEHandler.generateInfoForLambdaCaptures(CI->
getCapturedVar(), *CV,
10626 CurInfo, LambdaPointers);
10629 assert(!CurInfo.BasePointers.empty() &&
10630 "Non-existing map pointer for capture!");
10631 assert(CurInfo.BasePointers.size() == CurInfo.Pointers.size() &&
10632 CurInfo.BasePointers.size() == CurInfo.Sizes.size() &&
10633 CurInfo.BasePointers.size() == CurInfo.Types.size() &&
10634 CurInfo.BasePointers.size() == CurInfo.Mappers.size() &&
10635 "Inconsistent map information sizes!");
10638 CombinedInfo.append(CurInfo);
10641 MEHandler.adjustMemberOfForLambdaCaptures(
10642 OMPBuilder, LambdaPointers, CombinedInfo.BasePointers,
10643 CombinedInfo.Pointers, CombinedInfo.Types);
10647 MappableExprsHandler::MapCombinedInfoTy &CombinedInfo,
10648 llvm::OpenMPIRBuilder &OMPBuilder,
10655 MEHandler.generateAllInfo(CombinedInfo, OMPBuilder, SkippedVarSet);
10657 auto FillInfoMap = [&](MappableExprsHandler::MappingExprInfo &MapExpr) {
10661 llvm::codegenoptions::NoDebugInfo) {
10662 CombinedInfo.Names.resize(CombinedInfo.Exprs.size());
10663 llvm::transform(CombinedInfo.Exprs, CombinedInfo.Names.begin(),
10671 llvm::OpenMPIRBuilder &OMPBuilder,
10672 MappableExprsHandler::MapCombinedInfoTy &CombinedInfo) {
10674 MappableExprsHandler MEHandler(D, CGF);
10675 llvm::DenseSet<CanonicalDeclPtr<const Decl>> MappedVarSet;
10678 MappedVarSet, CombinedInfo);
10679 genMapInfo(MEHandler, CGF, CombinedInfo, OMPBuilder, MappedVarSet);
10682template <
typename ClauseTy>
10687 const auto *
C = D.getSingleClause<ClauseTy>();
10688 assert(!
C->varlist_empty() &&
10689 "ompx_bare requires explicit num_teams and thread_limit");
10691 for (
auto *E :
C->varlist()) {
10703 llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier>
Device,
10705 llvm::Value *&MapTypesArray, llvm::Value *&MapNamesArray,
10710 llvm::OpenMPIRBuilder &OMPBuilder = OMPRuntime->
getOMPBuilder();
10713 MappableExprsHandler::MapCombinedInfoTy CombinedInfo;
10715 genMapInfo(D, CGF, CS, CapturedVars, OMPBuilder, CombinedInfo);
10729 MapTypesArray = Info.RTArgs.MapTypesArray;
10730 MapNamesArray = Info.RTArgs.MapNamesArray;
10732 auto &&ThenGen = [&OMPRuntime, OutlinedFn, &D, &CapturedVars,
10733 RequiresOuterTask, &CS, OffloadingMandatory,
Device,
10734 OutlinedFnID, &InputInfo, &MapTypesArray, &MapNamesArray,
10736 bool IsReverseOffloading =
Device.getInt() == OMPC_DEVICE_ancestor;
10738 if (IsReverseOffloading) {
10744 RequiresOuterTask, CS, OffloadingMandatory, CGF);
10749 unsigned NumTargetItems = InputInfo.NumberOfTargetItems;
10751 llvm::Value *BasePointersArray =
10752 InputInfo.BasePointersArray.emitRawPointer(CGF);
10753 llvm::Value *PointersArray = InputInfo.PointersArray.emitRawPointer(CGF);
10754 llvm::Value *SizesArray = InputInfo.SizesArray.emitRawPointer(CGF);
10755 llvm::Value *MappersArray = InputInfo.MappersArray.emitRawPointer(CGF);
10757 auto &&EmitTargetCallFallbackCB =
10758 [&OMPRuntime, OutlinedFn, &D, &CapturedVars, RequiresOuterTask, &CS,
10759 OffloadingMandatory, &CGF](llvm::OpenMPIRBuilder::InsertPointTy IP)
10760 -> llvm::OpenMPIRBuilder::InsertPointTy {
10763 RequiresOuterTask, CS, OffloadingMandatory, CGF);
10776 NumThreads.push_back(
10782 llvm::Value *NumIterations =
10785 llvm::OpenMPIRBuilder::InsertPointTy AllocaIP(
10788 llvm::OpenMPIRBuilder::TargetDataRTArgs RTArgs(
10789 BasePointersArray, PointersArray, SizesArray, MapTypesArray,
10790 nullptr , MappersArray, MapNamesArray);
10792 llvm::OpenMPIRBuilder::TargetKernelArgs Args(
10793 NumTargetItems, RTArgs, NumIterations, NumTeams, NumThreads,
10794 DynCGroupMem, HasNoWait, DynCGroupMemFallback);
10796 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
10798 CGF.
Builder, OutlinedFnID, EmitTargetCallFallbackCB, Args, DeviceID,
10800 CGF.
Builder.restoreIP(AfterIP);
10803 if (RequiresOuterTask)
10818 [&OMPRuntime, OutlinedFn, &D, &CapturedVars, RequiresOuterTask, &CS,
10821 RequiresOuterTask, CS, OffloadingMandatory, CGF);
10824 if (RequiresOuterTask) {
10834 llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID,
const Expr *IfCond,
10835 llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier>
Device,
10842 const bool OffloadingMandatory = !
CGM.getLangOpts().OpenMPIsTargetDevice &&
10843 CGM.getLangOpts().OpenMPOffloadMandatory;
10845 assert((OffloadingMandatory || OutlinedFn) &&
"Invalid outlined function!");
10847 const bool RequiresOuterTask =
10851 (
CGM.getLangOpts().OpenMP >= 51 &&
10855 const CapturedStmt &CS = *D.getCapturedStmt(OMPD_target);
10863 llvm::Value *MapTypesArray =
nullptr;
10864 llvm::Value *MapNamesArray =
nullptr;
10866 auto &&TargetThenGen = [
this, OutlinedFn, &D, &CapturedVars,
10867 RequiresOuterTask, &CS, OffloadingMandatory,
Device,
10868 OutlinedFnID, &InputInfo, &MapTypesArray,
10872 RequiresOuterTask, CS, OffloadingMandatory,
10873 Device, OutlinedFnID, InputInfo, MapTypesArray,
10874 MapNamesArray, SizeEmitter, CGF,
CGM);
10877 auto &&TargetElseGen =
10878 [
this, OutlinedFn, &D, &CapturedVars, RequiresOuterTask, &CS,
10881 CS, OffloadingMandatory, CGF);
10888 if (OutlinedFnID) {
10890 emitIfClause(CGF, IfCond, TargetThenGen, TargetElseGen);
10902 StringRef ParentName) {
10907 bool RequiresDeviceCodegen =
10912 if (RequiresDeviceCodegen) {
10920 if (!
OMPBuilder.OffloadInfoManager.hasTargetRegionEntryInfo(EntryInfo))
10923 switch (E.getDirectiveKind()) {
10928 case OMPD_target_parallel:
10932 case OMPD_target_teams:
10936 case OMPD_target_teams_distribute:
10940 case OMPD_target_teams_distribute_simd:
10944 case OMPD_target_parallel_for:
10948 case OMPD_target_parallel_for_simd:
10952 case OMPD_target_simd:
10956 case OMPD_target_teams_distribute_parallel_for:
10961 case OMPD_target_teams_distribute_parallel_for_simd:
10967 case OMPD_target_teams_loop:
10971 case OMPD_target_parallel_loop:
10975 case OMPD_parallel:
10977 case OMPD_parallel_for:
10978 case OMPD_parallel_master:
10979 case OMPD_parallel_sections:
10980 case OMPD_for_simd:
10981 case OMPD_parallel_for_simd:
10983 case OMPD_cancellation_point:
10985 case OMPD_threadprivate:
10986 case OMPD_allocate:
10991 case OMPD_sections:
10995 case OMPD_critical:
10996 case OMPD_taskyield:
10998 case OMPD_taskwait:
10999 case OMPD_taskgroup:
11005 case OMPD_target_data:
11006 case OMPD_target_exit_data:
11007 case OMPD_target_enter_data:
11008 case OMPD_distribute:
11009 case OMPD_distribute_simd:
11010 case OMPD_distribute_parallel_for:
11011 case OMPD_distribute_parallel_for_simd:
11012 case OMPD_teams_distribute:
11013 case OMPD_teams_distribute_simd:
11014 case OMPD_teams_distribute_parallel_for:
11015 case OMPD_teams_distribute_parallel_for_simd:
11016 case OMPD_target_update:
11017 case OMPD_declare_simd:
11018 case OMPD_declare_variant:
11019 case OMPD_begin_declare_variant:
11020 case OMPD_end_declare_variant:
11021 case OMPD_declare_target:
11022 case OMPD_end_declare_target:
11023 case OMPD_declare_reduction:
11024 case OMPD_declare_mapper:
11025 case OMPD_taskloop:
11026 case OMPD_taskloop_simd:
11027 case OMPD_master_taskloop:
11028 case OMPD_master_taskloop_simd:
11029 case OMPD_parallel_master_taskloop:
11030 case OMPD_parallel_master_taskloop_simd:
11031 case OMPD_requires:
11032 case OMPD_metadirective:
11035 llvm_unreachable(
"Unknown target directive for OpenMP device codegen.");
11040 if (
const auto *E = dyn_cast<OMPExecutableDirective>(S)) {
11041 if (!E->hasAssociatedStmt() || !E->getAssociatedStmt())
11049 if (
const auto *L = dyn_cast<LambdaExpr>(S))
11058 std::optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
11059 OMPDeclareTargetDeclAttr::getDeviceType(VD);
11063 if (!IsDevice && DevTy == OMPDeclareTargetDeclAttr::DT_NoHost)
11066 if (IsDevice && DevTy == OMPDeclareTargetDeclAttr::DT_Host)
11074 if (!
CGM.getLangOpts().OpenMPIsTargetDevice) {
11075 if (
const auto *FD = dyn_cast<FunctionDecl>(GD.
getDecl()))
11077 CGM.getLangOpts().OpenMPIsTargetDevice))
11084 if (
const auto *FD = dyn_cast<FunctionDecl>(VD)) {
11085 StringRef Name =
CGM.getMangledName(GD);
11088 CGM.getLangOpts().OpenMPIsTargetDevice))
11093 return !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD) &&
11099 CGM.getLangOpts().OpenMPIsTargetDevice))
11102 if (!
CGM.getLangOpts().OpenMPIsTargetDevice)
11111 StringRef ParentName =
11116 StringRef ParentName =
11123 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
11124 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(
11126 if (!Res || *Res == OMPDeclareTargetDeclAttr::MT_Link ||
11127 ((*Res == OMPDeclareTargetDeclAttr::MT_To ||
11128 *Res == OMPDeclareTargetDeclAttr::MT_Enter) &&
11137 llvm::Constant *
Addr) {
11138 if (
CGM.getLangOpts().OMPTargetTriples.empty() &&
11139 !
CGM.getLangOpts().OpenMPIsTargetDevice)
11142 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
11143 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
11147 if (Res && *Res != OMPDeclareTargetDeclAttr::MT_Link &&
11152 if (
CGM.getLangOpts().OpenMPIsTargetDevice) {
11155 StringRef VarName =
CGM.getMangledName(VD);
11161 auto AddrOfGlobal = [&VD,
this]() {
return CGM.GetAddrOfGlobal(VD); };
11162 auto LinkageForVariable = [&VD,
this]() {
11163 return CGM.getLLVMLinkageVarDefinition(VD);
11166 std::vector<llvm::GlobalVariable *> GeneratedRefs;
11173 CGM.getMangledName(VD), GeneratedRefs,
CGM.getLangOpts().OpenMPSimd,
11174 CGM.getLangOpts().OMPTargetTriples, AddrOfGlobal, LinkageForVariable,
11175 CGM.getTypes().ConvertTypeForMem(
11176 CGM.getContext().getPointerType(VD->
getType())),
11179 for (
auto *ref : GeneratedRefs)
11180 CGM.addCompilerUsedGlobal(ref);
11193 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
11194 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
11197 if ((*Res == OMPDeclareTargetDeclAttr::MT_To ||
11198 *Res == OMPDeclareTargetDeclAttr::MT_Enter) &&
11200 CGM.EmitGlobal(VD);
11202 assert((*Res == OMPDeclareTargetDeclAttr::MT_Link ||
11203 ((*Res == OMPDeclareTargetDeclAttr::MT_To ||
11204 *Res == OMPDeclareTargetDeclAttr::MT_Enter) &&
11206 "Expected link clause or to clause with unified memory.");
11207 (void)
CGM.getOpenMPRuntime().getAddrOfDeclareTargetVar(VD);
11215 " Expected target-based directive.");
11220 if (Clause->getClauseKind() == OMPC_unified_shared_memory) {
11222 OMPBuilder.Config.setHasRequiresUnifiedSharedMemory(
true);
11223 }
else if (
const auto *AC =
11224 dyn_cast<OMPAtomicDefaultMemOrderClause>(Clause)) {
11225 switch (AC->getAtomicDefaultMemOrderKind()) {
11226 case OMPC_ATOMIC_DEFAULT_MEM_ORDER_acq_rel:
11229 case OMPC_ATOMIC_DEFAULT_MEM_ORDER_seq_cst:
11232 case OMPC_ATOMIC_DEFAULT_MEM_ORDER_relaxed:
11248 if (!VD || !VD->
hasAttr<OMPAllocateDeclAttr>())
11250 const auto *A = VD->
getAttr<OMPAllocateDeclAttr>();
11251 switch(A->getAllocatorType()) {
11252 case OMPAllocateDeclAttr::OMPNullMemAlloc:
11253 case OMPAllocateDeclAttr::OMPDefaultMemAlloc:
11255 case OMPAllocateDeclAttr::OMPLargeCapMemAlloc:
11256 case OMPAllocateDeclAttr::OMPCGroupMemAlloc:
11257 case OMPAllocateDeclAttr::OMPHighBWMemAlloc:
11258 case OMPAllocateDeclAttr::OMPLowLatMemAlloc:
11259 case OMPAllocateDeclAttr::OMPThreadMemAlloc:
11260 case OMPAllocateDeclAttr::OMPConstMemAlloc:
11261 case OMPAllocateDeclAttr::OMPPTeamMemAlloc:
11264 case OMPAllocateDeclAttr::OMPUserDefinedMemAlloc:
11265 llvm_unreachable(
"Expected predefined allocator for the variables with the "
11266 "static storage.");
11278 if (CGM.getLangOpts().OpenMPIsTargetDevice) {
11279 SavedShouldMarkAsGlobal = CGM.getOpenMPRuntime().ShouldMarkAsGlobal;
11280 CGM.getOpenMPRuntime().ShouldMarkAsGlobal = false;
11285 if (CGM.getLangOpts().OpenMPIsTargetDevice)
11286 CGM.getOpenMPRuntime().ShouldMarkAsGlobal = SavedShouldMarkAsGlobal;
11296 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(D)) {
11298 if (
auto *F = dyn_cast_or_null<llvm::Function>(
11299 CGM.GetGlobalValue(
CGM.getMangledName(GD))))
11300 return !F->isDeclaration();
11312 llvm::Function *OutlinedFn,
11321 llvm::Value *Args[] = {
11323 CGF.
Builder.getInt32(CapturedVars.size()),
11326 RealArgs.append(std::begin(Args), std::end(Args));
11327 RealArgs.append(CapturedVars.begin(), CapturedVars.end());
11329 llvm::FunctionCallee RTLFn =
OMPBuilder.getOrCreateRuntimeFunction(
11330 CGM.getModule(), OMPRTL___kmpc_fork_teams);
11335 const Expr *NumTeams,
11336 const Expr *ThreadLimit,
11343 llvm::Value *NumTeamsVal =
11349 llvm::Value *ThreadLimitVal =
11356 llvm::Value *PushNumTeamsArgs[] = {RTLoc,
getThreadID(CGF, Loc), NumTeamsVal,
11359 CGM.getModule(), OMPRTL___kmpc_push_num_teams),
11364 const Expr *ThreadLimit,
11367 llvm::Value *ThreadLimitVal =
11374 llvm::Value *ThreadLimitArgs[] = {RTLoc,
getThreadID(CGF, Loc),
11377 CGM.getModule(), OMPRTL___kmpc_set_thread_limit),
11392 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
11394 llvm::Value *IfCondVal =
nullptr;
11399 llvm::Value *DeviceID =
nullptr;
11404 DeviceID = CGF.
Builder.getInt64(OMP_DEVICEID_UNDEF);
11408 MappableExprsHandler::MapCombinedInfoTy CombinedInfo;
11409 auto GenMapInfoCB =
11410 [&](InsertPointTy CodeGenIP) -> llvm::OpenMPIRBuilder::MapInfosTy & {
11411 CGF.
Builder.restoreIP(CodeGenIP);
11413 MappableExprsHandler MEHandler(D, CGF);
11414 MEHandler.generateAllInfo(CombinedInfo,
OMPBuilder);
11416 auto FillInfoMap = [&](MappableExprsHandler::MappingExprInfo &MapExpr) {
11419 if (
CGM.getCodeGenOpts().getDebugInfo() !=
11420 llvm::codegenoptions::NoDebugInfo) {
11421 CombinedInfo.Names.resize(CombinedInfo.Exprs.size());
11422 llvm::transform(CombinedInfo.Exprs, CombinedInfo.Names.begin(),
11426 return CombinedInfo;
11428 using BodyGenTy = llvm::OpenMPIRBuilder::BodyGenTy;
11429 auto BodyCB = [&](InsertPointTy CodeGenIP, BodyGenTy BodyGenType) {
11430 CGF.
Builder.restoreIP(CodeGenIP);
11431 switch (BodyGenType) {
11432 case BodyGenTy::Priv:
11436 case BodyGenTy::DupNoPriv:
11438 CodeGen.setAction(NoPrivAction);
11442 case BodyGenTy::NoPriv:
11444 CodeGen.setAction(NoPrivAction);
11449 return InsertPointTy(CGF.
Builder.GetInsertBlock(),
11450 CGF.
Builder.GetInsertPoint());
11453 auto DeviceAddrCB = [&](
unsigned int I, llvm::Value *NewDecl) {
11454 if (
const ValueDecl *DevVD = CombinedInfo.DevicePtrDecls[I]) {
11459 auto CustomMapperCB = [&](
unsigned int I) {
11460 llvm::Function *MFunc =
nullptr;
11461 if (CombinedInfo.Mappers[I]) {
11462 Info.HasMapper =
true;
11474 InsertPointTy CodeGenIP(CGF.
Builder.GetInsertBlock(),
11475 CGF.
Builder.GetInsertPoint());
11476 llvm::OpenMPIRBuilder::LocationDescription OmpLoc(CodeGenIP);
11477 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
11479 OmpLoc, AllocaIP, CodeGenIP, DeviceID, IfCondVal, Info, GenMapInfoCB,
11481 nullptr, BodyCB, DeviceAddrCB, RTLoc));
11482 CGF.
Builder.restoreIP(AfterIP);
11494 "Expecting either target enter, exit data, or update directives.");
11497 llvm::Value *MapTypesArray =
nullptr;
11498 llvm::Value *MapNamesArray =
nullptr;
11500 auto &&ThenGen = [
this, &D,
Device, &InputInfo, &MapTypesArray,
11503 llvm::Value *DeviceID =
nullptr;
11508 DeviceID = CGF.
Builder.getInt64(OMP_DEVICEID_UNDEF);
11512 llvm::Constant *PointerNum =
11519 {RTLoc, DeviceID, PointerNum,
11528 RuntimeFunction RTLFn;
11529 switch (D.getDirectiveKind()) {
11530 case OMPD_target_enter_data:
11531 RTLFn = HasNowait ? OMPRTL___tgt_target_data_begin_nowait_mapper
11532 : OMPRTL___tgt_target_data_begin_mapper;
11534 case OMPD_target_exit_data:
11535 RTLFn = HasNowait ? OMPRTL___tgt_target_data_end_nowait_mapper
11536 : OMPRTL___tgt_target_data_end_mapper;
11538 case OMPD_target_update:
11539 RTLFn = HasNowait ? OMPRTL___tgt_target_data_update_nowait_mapper
11540 : OMPRTL___tgt_target_data_update_mapper;
11542 case OMPD_parallel:
11544 case OMPD_parallel_for:
11545 case OMPD_parallel_master:
11546 case OMPD_parallel_sections:
11547 case OMPD_for_simd:
11548 case OMPD_parallel_for_simd:
11550 case OMPD_cancellation_point:
11552 case OMPD_threadprivate:
11553 case OMPD_allocate:
11558 case OMPD_sections:
11562 case OMPD_critical:
11563 case OMPD_taskyield:
11565 case OMPD_taskwait:
11566 case OMPD_taskgroup:
11572 case OMPD_target_data:
11573 case OMPD_distribute:
11574 case OMPD_distribute_simd:
11575 case OMPD_distribute_parallel_for:
11576 case OMPD_distribute_parallel_for_simd:
11577 case OMPD_teams_distribute:
11578 case OMPD_teams_distribute_simd:
11579 case OMPD_teams_distribute_parallel_for:
11580 case OMPD_teams_distribute_parallel_for_simd:
11581 case OMPD_declare_simd:
11582 case OMPD_declare_variant:
11583 case OMPD_begin_declare_variant:
11584 case OMPD_end_declare_variant:
11585 case OMPD_declare_target:
11586 case OMPD_end_declare_target:
11587 case OMPD_declare_reduction:
11588 case OMPD_declare_mapper:
11589 case OMPD_taskloop:
11590 case OMPD_taskloop_simd:
11591 case OMPD_master_taskloop:
11592 case OMPD_master_taskloop_simd:
11593 case OMPD_parallel_master_taskloop:
11594 case OMPD_parallel_master_taskloop_simd:
11596 case OMPD_target_simd:
11597 case OMPD_target_teams_distribute:
11598 case OMPD_target_teams_distribute_simd:
11599 case OMPD_target_teams_distribute_parallel_for:
11600 case OMPD_target_teams_distribute_parallel_for_simd:
11601 case OMPD_target_teams:
11602 case OMPD_target_parallel:
11603 case OMPD_target_parallel_for:
11604 case OMPD_target_parallel_for_simd:
11605 case OMPD_requires:
11606 case OMPD_metadirective:
11609 llvm_unreachable(
"Unexpected standalone target data directive.");
11613 OffloadingArgs.push_back(llvm::Constant::getNullValue(CGF.
Int32Ty));
11614 OffloadingArgs.push_back(llvm::Constant::getNullValue(CGF.
VoidPtrTy));
11615 OffloadingArgs.push_back(llvm::Constant::getNullValue(CGF.
Int32Ty));
11616 OffloadingArgs.push_back(llvm::Constant::getNullValue(CGF.
VoidPtrTy));
11619 OMPBuilder.getOrCreateRuntimeFunction(
CGM.getModule(), RTLFn),
11623 auto &&TargetThenGen = [
this, &ThenGen, &D, &InputInfo, &MapTypesArray,
11627 MappableExprsHandler::MapCombinedInfoTy CombinedInfo;
11629 MappableExprsHandler MEHandler(D, CGF);
11641 CGM.getPointerAlign());
11646 MapTypesArray = Info.RTArgs.MapTypesArray;
11647 MapNamesArray = Info.RTArgs.MapNamesArray;
11648 if (RequiresOuterTask)
11674struct ParamAttrTy {
11675 ParamKindTy Kind =
Vector;
11676 llvm::APSInt StrideOrArg;
11677 llvm::APSInt Alignment;
11678 bool HasVarStride =
false;
11711 unsigned Offset = 0;
11712 if (
const auto *MD = dyn_cast<CXXMethodDecl>(FD)) {
11713 if (ParamAttrs[Offset].Kind ==
Vector)
11714 CDT =
C.getPointerType(
C.getCanonicalTagType(MD->
getParent()));
11718 for (
unsigned I = 0, E = FD->
getNumParams(); I < E; ++I) {
11719 if (ParamAttrs[I + Offset].Kind ==
Vector) {
11731 return C.getTypeSize(CDT);
11739 llvm::raw_svector_ostream Out(Buffer);
11740 for (
const auto &ParamAttr : ParamAttrs) {
11741 switch (ParamAttr.Kind) {
11761 if (ParamAttr.HasVarStride)
11762 Out <<
"s" << ParamAttr.StrideOrArg;
11763 else if (ParamAttr.Kind == Linear || ParamAttr.Kind == LinearRef ||
11764 ParamAttr.Kind == LinearUVal || ParamAttr.Kind == LinearVal) {
11767 if (ParamAttr.StrideOrArg < 0)
11768 Out <<
'n' << -ParamAttr.StrideOrArg;
11769 else if (ParamAttr.StrideOrArg != 1)
11770 Out << ParamAttr.StrideOrArg;
11773 if (!!ParamAttr.Alignment)
11774 Out <<
'a' << ParamAttr.Alignment;
11777 return std::string(Out.str());
11782 const llvm::APSInt &VLENVal,
11784 OMPDeclareSimdDeclAttr::BranchStateTy State) {
11787 unsigned VecRegSize;
11789 ISADataTy ISAData[] = {
11805 case OMPDeclareSimdDeclAttr::BS_Undefined:
11806 Masked.push_back(
'N');
11807 Masked.push_back(
'M');
11809 case OMPDeclareSimdDeclAttr::BS_Notinbranch:
11810 Masked.push_back(
'N');
11812 case OMPDeclareSimdDeclAttr::BS_Inbranch:
11813 Masked.push_back(
'M');
11816 for (
char Mask : Masked) {
11817 for (
const ISADataTy &
Data : ISAData) {
11819 llvm::raw_svector_ostream Out(Buffer);
11820 Out <<
"_ZGV" <<
Data.ISA << Mask;
11823 assert(NumElts &&
"Non-zero simdlen/cdtsize expected");
11824 Out << llvm::APSInt::getUnsigned(
Data.VecRegSize / NumElts);
11829 Out <<
'_' << Fn->getName();
11830 Fn->addFnAttr(Out.str());
11848 if (Kind == ParamKindTy::Uniform)
11851 if (Kind == ParamKindTy::LinearUVal || Kind == ParamKindTy::LinearRef)
11854 if ((Kind == ParamKindTy::Linear || Kind == ParamKindTy::LinearVal) &&
11864 unsigned Size =
C.getTypeSize(QT);
11867 if (Size != 8 && Size != 16 && Size != 32 && Size != 64 && Size != 128)
11891 return C.getTypeSize(PTy);
11894 return C.getTypeSize(QT);
11896 return C.getTypeSize(
C.getUIntPtrType());
11902static std::tuple<unsigned, unsigned, bool>
11908 bool OutputBecomesInput =
false;
11912 Sizes.push_back(
getAArch64LS(RetType, ParamKindTy::Vector,
C));
11914 OutputBecomesInput =
true;
11916 for (
unsigned I = 0, E = FD->
getNumParams(); I < E; ++I) {
11921 assert(!Sizes.empty() &&
"Unable to determine NDS and WDS.");
11924 assert(llvm::all_of(Sizes,
11925 [](
unsigned Size) {
11926 return Size == 8 || Size == 16 || Size == 32 ||
11927 Size == 64 || Size == 128;
11931 return std::make_tuple(*llvm::min_element(Sizes), *llvm::max_element(Sizes),
11932 OutputBecomesInput);
11938template <
typename T>
11940 char ISA, StringRef ParSeq,
11941 StringRef MangledName,
bool OutputBecomesInput,
11942 llvm::Function *Fn) {
11944 llvm::raw_svector_ostream Out(Buffer);
11945 Out << Prefix << ISA << LMask << VLEN;
11946 if (OutputBecomesInput)
11948 Out << ParSeq <<
"_" << MangledName;
11949 Fn->addFnAttr(Out.str());
11955 StringRef Prefix,
char ISA,
11956 StringRef ParSeq, StringRef MangledName,
11957 bool OutputBecomesInput,
11958 llvm::Function *Fn) {
11962 OutputBecomesInput, Fn);
11964 OutputBecomesInput, Fn);
11968 OutputBecomesInput, Fn);
11970 OutputBecomesInput, Fn);
11974 OutputBecomesInput, Fn);
11976 OutputBecomesInput, Fn);
11981 OutputBecomesInput, Fn);
11984 llvm_unreachable(
"Scalar type is too wide.");
11992 OMPDeclareSimdDeclAttr::BranchStateTy State, StringRef MangledName,
11993 char ISA,
unsigned VecRegSize, llvm::Function *Fn,
SourceLocation SLoc) {
11997 const unsigned NDS = std::get<0>(
Data);
11998 const unsigned WDS = std::get<1>(
Data);
11999 const bool OutputBecomesInput = std::get<2>(
Data);
12003 if (UserVLEN == 1) {
12010 if (ISA ==
'n' && UserVLEN && !llvm::isPowerOf2_32(UserVLEN)) {
12017 if (ISA ==
's' && UserVLEN != 0) {
12018 if ((UserVLEN * WDS > 2048) || (UserVLEN * WDS % 128 != 0)) {
12026 StringRef Prefix =
"_ZGV";
12032 OutputBecomesInput, Fn);
12034 assert(ISA ==
'n' &&
"Expected ISA either 's' or 'n'.");
12038 case OMPDeclareSimdDeclAttr::BS_Undefined:
12040 OutputBecomesInput, Fn);
12042 OutputBecomesInput, Fn);
12044 case OMPDeclareSimdDeclAttr::BS_Notinbranch:
12046 OutputBecomesInput, Fn);
12048 case OMPDeclareSimdDeclAttr::BS_Inbranch:
12050 OutputBecomesInput, Fn);
12060 OutputBecomesInput, Fn);
12062 assert(ISA ==
'n' &&
"Expected ISA either 's' or 'n'.");
12067 case OMPDeclareSimdDeclAttr::BS_Undefined:
12069 OutputBecomesInput, Fn);
12071 OutputBecomesInput, Fn);
12073 case OMPDeclareSimdDeclAttr::BS_Notinbranch:
12075 OutputBecomesInput, Fn);
12077 case OMPDeclareSimdDeclAttr::BS_Inbranch:
12079 OutputBecomesInput, Fn);
12087 llvm::Function *Fn) {
12092 llvm::DenseMap<const Decl *, unsigned> ParamPositions;
12094 ParamPositions.try_emplace(FD, 0);
12095 unsigned ParamPos = ParamPositions.size();
12097 ParamPositions.try_emplace(P->getCanonicalDecl(), ParamPos);
12103 for (
const Expr *E :
Attr->uniforms()) {
12107 Pos = ParamPositions[FD];
12110 ->getCanonicalDecl();
12111 auto It = ParamPositions.find(PVD);
12112 assert(It != ParamPositions.end() &&
"Function parameter not found");
12115 ParamAttrs[Pos].Kind = Uniform;
12118 auto *NI =
Attr->alignments_begin();
12119 for (
const Expr *E :
Attr->aligneds()) {
12124 Pos = ParamPositions[FD];
12128 ->getCanonicalDecl();
12129 auto It = ParamPositions.find(PVD);
12130 assert(It != ParamPositions.end() &&
"Function parameter not found");
12132 ParmTy = PVD->getType();
12134 ParamAttrs[Pos].Alignment =
12136 ? (*NI)->EvaluateKnownConstInt(
C)
12137 : llvm::APSInt::getUnsigned(
12138 C.toCharUnitsFromBits(
C.getOpenMPDefaultSimdAlign(ParmTy))
12143 auto *SI =
Attr->steps_begin();
12144 auto *MI =
Attr->modifiers_begin();
12145 for (
const Expr *E :
Attr->linears()) {
12148 bool IsReferenceType =
false;
12151 unsigned PtrRescalingFactor = 1;
12153 Pos = ParamPositions[FD];
12155 PtrRescalingFactor =
CGM.getContext()
12156 .getTypeSizeInChars(P->getPointeeType())
12160 ->getCanonicalDecl();
12161 auto It = ParamPositions.find(PVD);
12162 assert(It != ParamPositions.end() &&
"Function parameter not found");
12164 if (
auto *P = dyn_cast<PointerType>(PVD->getType()))
12165 PtrRescalingFactor =
CGM.getContext()
12166 .getTypeSizeInChars(P->getPointeeType())
12168 else if (PVD->getType()->isReferenceType()) {
12169 IsReferenceType =
true;
12170 PtrRescalingFactor =
12172 .getTypeSizeInChars(PVD->getType().getNonReferenceType())
12176 ParamAttrTy &ParamAttr = ParamAttrs[Pos];
12177 if (*MI == OMPC_LINEAR_ref)
12178 ParamAttr.Kind = LinearRef;
12179 else if (*MI == OMPC_LINEAR_uval)
12180 ParamAttr.Kind = LinearUVal;
12181 else if (IsReferenceType)
12182 ParamAttr.Kind = LinearVal;
12184 ParamAttr.Kind = Linear;
12186 ParamAttr.StrideOrArg = llvm::APSInt::getUnsigned(1);
12190 if (
const auto *DRE =
12192 if (
const auto *StridePVD =
12193 dyn_cast<ParmVarDecl>(DRE->getDecl())) {
12194 ParamAttr.HasVarStride =
true;
12195 auto It = ParamPositions.find(StridePVD->getCanonicalDecl());
12196 assert(It != ParamPositions.end() &&
12197 "Function parameter not found");
12198 ParamAttr.StrideOrArg = llvm::APSInt::getUnsigned(It->second);
12202 ParamAttr.StrideOrArg =
Result.Val.getInt();
12208 if (!ParamAttr.HasVarStride &&
12209 (ParamAttr.Kind == Linear || ParamAttr.Kind == LinearRef))
12210 ParamAttr.StrideOrArg = ParamAttr.StrideOrArg * PtrRescalingFactor;
12214 llvm::APSInt VLENVal;
12216 const Expr *VLENExpr =
Attr->getSimdlen();
12221 OMPDeclareSimdDeclAttr::BranchStateTy State =
Attr->getBranchState();
12222 if (
CGM.getTriple().isX86()) {
12224 }
else if (
CGM.getTriple().getArch() == llvm::Triple::aarch64) {
12225 unsigned VLEN = VLENVal.getExtValue();
12226 StringRef MangledName = Fn->getName();
12227 if (
CGM.getTarget().hasFeature(
"sve"))
12229 MangledName,
's', 128, Fn, ExprLoc);
12230 else if (
CGM.getTarget().hasFeature(
"neon"))
12232 MangledName,
'n', 128, Fn, ExprLoc);
12241class DoacrossCleanupTy final :
public EHScopeStack::Cleanup {
12243 static const int DoacrossFinArgs = 2;
12246 llvm::FunctionCallee RTLFn;
12247 llvm::Value *Args[DoacrossFinArgs];
12250 DoacrossCleanupTy(llvm::FunctionCallee RTLFn,
12253 assert(CallArgs.size() == DoacrossFinArgs);
12254 std::copy(CallArgs.begin(), CallArgs.end(), std::begin(Args));
12271 QualType Int64Ty =
C.getIntTypeForBitwidth(64,
true);
12279 RD =
C.buildImplicitRecord(
"kmp_dim");
12287 RD =
KmpDimTy->castAsRecordDecl();
12289 llvm::APInt Size(32, NumIterations.size());
12295 enum { LowerFD = 0, UpperFD, StrideFD };
12297 for (
unsigned I = 0, E = NumIterations.size(); I < E; ++I) {
12302 DimsLVal, *std::next(RD->
field_begin(), UpperFD));
12304 CGF.
EmitScalarExpr(NumIterations[I]), NumIterations[I]->getType(),
12305 Int64Ty, NumIterations[I]->getExprLoc());
12309 DimsLVal, *std::next(RD->
field_begin(), StrideFD));
12316 llvm::Value *Args[] = {
12319 llvm::ConstantInt::getSigned(
CGM.Int32Ty, NumIterations.size()),
12324 llvm::FunctionCallee RTLFn =
OMPBuilder.getOrCreateRuntimeFunction(
12325 CGM.getModule(), OMPRTL___kmpc_doacross_init);
12327 llvm::Value *FiniArgs[DoacrossCleanupTy::DoacrossFinArgs] = {
12329 llvm::FunctionCallee FiniRTLFn =
OMPBuilder.getOrCreateRuntimeFunction(
12330 CGM.getModule(), OMPRTL___kmpc_doacross_fini);
12335template <
typename T>
12337 const T *
C, llvm::Value *ULoc,
12338 llvm::Value *ThreadID) {
12341 llvm::APInt Size(32,
C->getNumLoops());
12345 for (
unsigned I = 0, E =
C->getNumLoops(); I < E; ++I) {
12346 const Expr *CounterVal =
C->getLoopData(I);
12347 assert(CounterVal);
12354 llvm::Value *Args[] = {
12357 llvm::FunctionCallee RTLFn;
12359 OMPDoacrossKind<T> ODK;
12360 if (ODK.isSource(
C)) {
12362 OMPRTL___kmpc_doacross_post);
12364 assert(ODK.isSink(
C) &&
"Expect sink modifier.");
12366 OMPRTL___kmpc_doacross_wait);
12386 llvm::FunctionCallee Callee,
12388 assert(Loc.
isValid() &&
"Outlined function call location must be valid.");
12391 if (
auto *Fn = dyn_cast<llvm::Function>(Callee.getCallee())) {
12392 if (Fn->doesNotThrow()) {
12403 emitCall(CGF, Loc, OutlinedFn, Args);
12407 if (
const auto *FD = dyn_cast<FunctionDecl>(D))
12408 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(FD))
12414 const VarDecl *TargetParam)
const {
12421 const Expr *Allocator) {
12422 llvm::Value *AllocVal;
12432 AllocVal = llvm::Constant::getNullValue(
12442 if (!AllocateAlignment)
12445 return llvm::ConstantInt::get(
CGM.
SizeTy, AllocateAlignment->getQuantity());
12458 auto I = UntiedData.find(VD);
12459 if (I != UntiedData.end()) {
12460 UntiedAddr = I->second.first;
12461 UntiedRealAddr = I->second.second;
12465 if (CVD->
hasAttr<OMPAllocateDeclAttr>()) {
12474 Size = CGF.
Builder.CreateNUWAdd(
12476 Size = CGF.
Builder.CreateUDiv(Size,
CGM.getSize(Align));
12477 Size = CGF.
Builder.CreateNUWMul(Size,
CGM.getSize(Align));
12483 const auto *AA = CVD->
getAttr<OMPAllocateDeclAttr>();
12484 const Expr *Allocator = AA->getAllocator();
12488 Args.push_back(ThreadID);
12490 Args.push_back(Alignment);
12491 Args.push_back(Size);
12492 Args.push_back(AllocVal);
12493 llvm::omp::RuntimeFunction FnID =
12494 Alignment ? OMPRTL___kmpc_aligned_alloc : OMPRTL___kmpc_alloc;
12496 OMPBuilder.getOrCreateRuntimeFunction(
CGM.getModule(), FnID), Args,
12498 llvm::FunctionCallee FiniRTLFn =
OMPBuilder.getOrCreateRuntimeFunction(
12499 CGM.getModule(), OMPRTL___kmpc_free);
12507 class OMPAllocateCleanupTy final :
public EHScopeStack::Cleanup {
12508 llvm::FunctionCallee RTLFn;
12511 const Expr *AllocExpr;
12514 OMPAllocateCleanupTy(llvm::FunctionCallee RTLFn,
12516 const Expr *AllocExpr)
12517 : RTLFn(RTLFn), LocEncoding(LocEncoding),
Addr(
Addr),
12518 AllocExpr(AllocExpr) {}
12522 llvm::Value *Args[3];
12528 Args[2] = AllocVal;
12536 CGF.
EHStack.pushCleanup<OMPAllocateCleanupTy>(
12538 VDAddr, Allocator);
12539 if (UntiedRealAddr.
isValid())
12542 Region->emitUntiedSwitch(CGF);
12559 assert(CGM.getLangOpts().OpenMP &&
"Not in OpenMP mode.");
12563 CGM.getOpenMPRuntime().NontemporalDeclsStack.emplace_back();
12565 for (
const Stmt *Ref :
C->private_refs()) {
12566 const auto *SimpleRefExpr =
cast<Expr>(Ref)->IgnoreParenImpCasts();
12568 if (
const auto *DRE = dyn_cast<DeclRefExpr>(SimpleRefExpr)) {
12569 VD = DRE->getDecl();
12572 assert((ME->isImplicitCXXThis() ||
12574 "Expected member of current class.");
12575 VD = ME->getMemberDecl();
12585 CGM.getOpenMPRuntime().NontemporalDeclsStack.pop_back();
12591 std::pair<Address, Address>> &LocalVars)
12592 : CGM(CGF.CGM), NeedToPush(!LocalVars.empty()) {
12596 CGF.
CurFn, CGM.getOpenMPRuntime().UntiedLocalVarsStack.size());
12597 CGM.getOpenMPRuntime().UntiedLocalVarsStack.push_back(LocalVars);
12603 CGM.getOpenMPRuntime().UntiedLocalVarsStack.pop_back();
12607 assert(
CGM.getLangOpts().OpenMP &&
"Not in OpenMP mode.");
12609 return llvm::any_of(
12610 CGM.getOpenMPRuntime().NontemporalDeclsStack,
12614void CGOpenMPRuntime::LastprivateConditionalRAII::tryToDisableInnerAnalysis(
12618 llvm::DenseSet<CanonicalDeclPtr<const Decl>> NeedToCheckForLPCs;
12624 const CapturedStmt *CS = S.getCapturedStmt(CaptureRegions.front());
12632 for (
const Expr *Ref :
C->varlist()) {
12633 if (!Ref->getType()->isScalarType())
12635 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
12638 NeedToCheckForLPCs.insert(DRE->getDecl());
12641 for (
const auto *
C : S.getClausesOfKind<OMPFirstprivateClause>()) {
12642 for (
const Expr *Ref :
C->varlist()) {
12643 if (!Ref->getType()->isScalarType())
12645 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
12648 NeedToCheckForLPCs.insert(DRE->getDecl());
12651 for (
const auto *
C : S.getClausesOfKind<OMPLastprivateClause>()) {
12652 for (
const Expr *Ref :
C->varlist()) {
12653 if (!Ref->getType()->isScalarType())
12655 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
12658 NeedToCheckForLPCs.insert(DRE->getDecl());
12661 for (
const auto *
C : S.getClausesOfKind<OMPReductionClause>()) {
12662 for (
const Expr *Ref :
C->varlist()) {
12663 if (!Ref->getType()->isScalarType())
12665 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
12668 NeedToCheckForLPCs.insert(DRE->getDecl());
12671 for (
const auto *
C : S.getClausesOfKind<OMPLinearClause>()) {
12672 for (
const Expr *Ref :
C->varlist()) {
12673 if (!Ref->getType()->isScalarType())
12675 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
12678 NeedToCheckForLPCs.insert(DRE->getDecl());
12681 for (
const Decl *VD : NeedToCheckForLPCs) {
12683 llvm::reverse(
CGM.getOpenMPRuntime().LastprivateConditionalStack)) {
12684 if (
Data.DeclToUniqueName.count(VD) > 0) {
12685 if (!
Data.Disabled)
12686 NeedToAddForLPCsAsDisabled.insert(VD);
12693CGOpenMPRuntime::LastprivateConditionalRAII::LastprivateConditionalRAII(
12696 Action((CGM.getLangOpts().OpenMP >= 50 &&
12699 return C->getKind() ==
12700 OMPC_LASTPRIVATE_conditional;
12702 ? ActionToDo::PushAsLastprivateConditional
12703 : ActionToDo::DoNotPush) {
12704 assert(
CGM.getLangOpts().OpenMP &&
"Not in OpenMP mode.");
12705 if (
CGM.getLangOpts().OpenMP < 50 || Action == ActionToDo::DoNotPush)
12707 assert(Action == ActionToDo::PushAsLastprivateConditional &&
12708 "Expected a push action.");
12710 CGM.getOpenMPRuntime().LastprivateConditionalStack.emplace_back();
12712 if (
C->getKind() != OMPC_LASTPRIVATE_conditional)
12715 for (
const Expr *Ref :
C->varlist()) {
12716 Data.DeclToUniqueName.insert(std::make_pair(
12721 Data.IVLVal = IVLVal;
12725CGOpenMPRuntime::LastprivateConditionalRAII::LastprivateConditionalRAII(
12727 :
CGM(CGF.
CGM), Action(ActionToDo::DoNotPush) {
12731 llvm::DenseSet<CanonicalDeclPtr<const Decl>> NeedToAddForLPCsAsDisabled;
12732 tryToDisableInnerAnalysis(S, NeedToAddForLPCsAsDisabled);
12733 if (!NeedToAddForLPCsAsDisabled.empty()) {
12734 Action = ActionToDo::DisableLastprivateConditional;
12735 LastprivateConditionalData &
Data =
12737 for (
const Decl *VD : NeedToAddForLPCsAsDisabled)
12738 Data.DeclToUniqueName.try_emplace(VD);
12740 Data.Disabled =
true;
12744CGOpenMPRuntime::LastprivateConditionalRAII
12747 return LastprivateConditionalRAII(CGF, S);
12751 if (CGM.getLangOpts().OpenMP < 50)
12753 if (Action == ActionToDo::DisableLastprivateConditional) {
12754 assert(CGM.getOpenMPRuntime().LastprivateConditionalStack.back().Disabled &&
12755 "Expected list of disabled private vars.");
12756 CGM.getOpenMPRuntime().LastprivateConditionalStack.pop_back();
12758 if (Action == ActionToDo::PushAsLastprivateConditional) {
12760 !CGM.getOpenMPRuntime().LastprivateConditionalStack.back().Disabled &&
12761 "Expected list of lastprivate conditional vars.");
12762 CGM.getOpenMPRuntime().LastprivateConditionalStack.pop_back();
12774 auto VI = I->getSecond().find(VD);
12775 if (VI == I->getSecond().end()) {
12776 RecordDecl *RD =
C.buildImplicitRecord(
"lasprivate.conditional");
12781 NewType =
C.getCanonicalTagType(RD);
12784 I->getSecond().try_emplace(VD, NewType, VDField, FiredField, BaseLVal);
12786 NewType = std::get<0>(VI->getSecond());
12787 VDField = std::get<1>(VI->getSecond());
12788 FiredField = std::get<2>(VI->getSecond());
12789 BaseLVal = std::get<3>(VI->getSecond());
12801class LastprivateConditionalRefChecker final
12804 const Expr *FoundE =
nullptr;
12805 const Decl *FoundD =
nullptr;
12806 StringRef UniqueDeclName;
12808 llvm::Function *FoundFn =
nullptr;
12814 llvm::reverse(LPM)) {
12815 auto It = D.DeclToUniqueName.find(E->
getDecl());
12816 if (It == D.DeclToUniqueName.end())
12822 UniqueDeclName = It->second;
12827 return FoundE == E;
12833 llvm::reverse(LPM)) {
12835 if (It == D.DeclToUniqueName.end())
12841 UniqueDeclName = It->second;
12846 return FoundE == E;
12848 bool VisitStmt(
const Stmt *S) {
12849 for (
const Stmt *Child : S->
children()) {
12852 if (
const auto *E = dyn_cast<Expr>(Child))
12860 explicit LastprivateConditionalRefChecker(
12861 ArrayRef<CGOpenMPRuntime::LastprivateConditionalData> LPM)
12863 std::tuple<const Expr *, const Decl *, StringRef, LValue, llvm::Function *>
12864 getFoundData()
const {
12865 return std::make_tuple(FoundE, FoundD, UniqueDeclName, IVLVal, FoundFn);
12872 StringRef UniqueDeclName,
12878 llvm::Constant *LastIV =
OMPBuilder.getOrCreateInternalVariable(
12879 LLIVTy,
getName({UniqueDeclName,
"iv"}));
12887 llvm::GlobalVariable *
Last =
OMPBuilder.getOrCreateInternalVariable(
12903 auto &&
CodeGen = [&LastIVLVal, &IVLVal, IVVal, &LVal, &LastLVal,
12909 llvm::Value *CmpRes;
12911 CmpRes = CGF.
Builder.CreateICmpSLE(LastIVVal, IVVal);
12914 "Loop iteration variable must be integer.");
12915 CmpRes = CGF.
Builder.CreateICmpULE(LastIVVal, IVVal);
12919 CGF.
Builder.CreateCondBr(CmpRes, ThenBB, ExitBB);
12940 "Aggregates are not supported in lastprivate conditional.");
12949 if (
CGM.getLangOpts().OpenMPSimd) {
12963 if (!Checker.Visit(LHS))
12965 const Expr *FoundE;
12966 const Decl *FoundD;
12967 StringRef UniqueDeclName;
12969 llvm::Function *FoundFn;
12970 std::tie(FoundE, FoundD, UniqueDeclName, IVLVal, FoundFn) =
12971 Checker.getFoundData();
12972 if (FoundFn != CGF.
CurFn) {
12977 "Lastprivate conditional is not found in outer region.");
12978 QualType StructTy = std::get<0>(It->getSecond());
12979 const FieldDecl* FiredDecl = std::get<2>(It->getSecond());
12990 FiredLVal, llvm::AtomicOrdering::Unordered,
13008 auto It = llvm::find_if(
13010 if (It == Range.end() || It->Fn != CGF.
CurFn)
13014 "Lastprivates must be registered already.");
13017 const CapturedStmt *CS = D.getCapturedStmt(CaptureRegions.back());
13018 for (
const auto &Pair : It->DeclToUniqueName) {
13019 const auto *VD =
cast<VarDecl>(Pair.first->getCanonicalDecl());
13022 auto I = LPCI->getSecond().find(Pair.first);
13023 assert(I != LPCI->getSecond().end() &&
13024 "Lastprivate must be rehistered already.");
13026 LValue BaseLVal = std::get<3>(I->getSecond());
13030 llvm::Value *Cmp = CGF.
Builder.CreateIsNotNull(Res);
13034 CGF.
Builder.CreateCondBr(Cmp, ThenBB, DoneBB);
13059 "Unknown lastprivate conditional variable.");
13060 StringRef UniqueName = It->second;
13061 llvm::GlobalVariable *GV =
CGM.getModule().getNamedGlobal(UniqueName);
13075 llvm_unreachable(
"Not supported in SIMD-only mode");
13082 llvm_unreachable(
"Not supported in SIMD-only mode");
13089 bool Tied,
unsigned &NumberOfParts) {
13090 llvm_unreachable(
"Not supported in SIMD-only mode");
13098 llvm_unreachable(
"Not supported in SIMD-only mode");
13104 const Expr *Hint) {
13105 llvm_unreachable(
"Not supported in SIMD-only mode");
13111 llvm_unreachable(
"Not supported in SIMD-only mode");
13117 const Expr *Filter) {
13118 llvm_unreachable(
"Not supported in SIMD-only mode");
13123 llvm_unreachable(
"Not supported in SIMD-only mode");
13129 llvm_unreachable(
"Not supported in SIMD-only mode");
13137 llvm_unreachable(
"Not supported in SIMD-only mode");
13144 llvm_unreachable(
"Not supported in SIMD-only mode");
13151 bool ForceSimpleCall) {
13152 llvm_unreachable(
"Not supported in SIMD-only mode");
13159 llvm_unreachable(
"Not supported in SIMD-only mode");
13164 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");
13183 llvm_unreachable(
"Not supported in SIMD-only mode");
13189 llvm_unreachable(
"Not supported in SIMD-only mode");
13194 unsigned IVSize,
bool IVSigned,
13197 llvm_unreachable(
"Not supported in SIMD-only mode");
13205 llvm_unreachable(
"Not supported in SIMD-only mode");
13209 ProcBindKind ProcBind,
13211 llvm_unreachable(
"Not supported in SIMD-only mode");
13218 llvm_unreachable(
"Not supported in SIMD-only mode");
13224 llvm_unreachable(
"Not supported in SIMD-only mode");
13229 llvm_unreachable(
"Not supported in SIMD-only mode");
13235 llvm::AtomicOrdering AO) {
13236 llvm_unreachable(
"Not supported in SIMD-only mode");
13241 llvm::Function *TaskFunction,
13243 const Expr *IfCond,
13245 llvm_unreachable(
"Not supported in SIMD-only mode");
13252 llvm_unreachable(
"Not supported in SIMD-only mode");
13259 assert(Options.
SimpleReduction &&
"Only simple reduction is expected.");
13261 ReductionOps, Options);
13267 llvm_unreachable(
"Not supported in SIMD-only mode");
13272 bool IsWorksharingReduction) {
13273 llvm_unreachable(
"Not supported in SIMD-only mode");
13280 llvm_unreachable(
"Not supported in SIMD-only mode");
13285 llvm::Value *ReductionsPtr,
13287 llvm_unreachable(
"Not supported in SIMD-only mode");
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");
13310 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
13312 llvm_unreachable(
"Not supported in SIMD-only mode");
13317 llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID,
const Expr *IfCond,
13318 llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier>
Device,
13322 llvm_unreachable(
"Not supported in SIMD-only mode");
13326 llvm_unreachable(
"Not supported in SIMD-only mode");
13330 llvm_unreachable(
"Not supported in SIMD-only mode");
13340 llvm::Function *OutlinedFn,
13342 llvm_unreachable(
"Not supported in SIMD-only mode");
13346 const Expr *NumTeams,
13347 const Expr *ThreadLimit,
13349 llvm_unreachable(
"Not supported in SIMD-only mode");
13356 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");
13373 llvm_unreachable(
"Not supported in SIMD-only mode");
13378 llvm_unreachable(
"Not supported in SIMD-only mode");
13383 const VarDecl *NativeParam)
const {
13384 llvm_unreachable(
"Not supported in SIMD-only mode");
13390 const VarDecl *TargetParam)
const {
13391 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 unsigned evaluateCDTSize(const FunctionDecl *FD, ArrayRef< ParamAttrTy > ParamAttrs)
static void EmitOMPAggregateReduction(CodeGenFunction &CGF, QualType Type, const VarDecl *LHSVar, const VarDecl *RHSVar, const llvm::function_ref< void(CodeGenFunction &CGF, const Expr *, const Expr *, const Expr *)> &RedOpGen, const Expr *XExpr=nullptr, const Expr *EExpr=nullptr, const Expr *UpExpr=nullptr)
Emit reduction operation for each element of array (required for array sections) LHS op = RHS.
static void emitTargetCallFallback(CGOpenMPRuntime *OMPRuntime, llvm::Function *OutlinedFn, const OMPExecutableDirective &D, llvm::SmallVectorImpl< llvm::Value * > &CapturedVars, bool RequiresOuterTask, const CapturedStmt &CS, bool OffloadingMandatory, CodeGenFunction &CGF)
static llvm::Value * emitReduceInitFunction(CodeGenModule &CGM, SourceLocation Loc, ReductionCodeGen &RCG, unsigned N)
Emits reduction initializer function:
static RTCancelKind getCancellationKind(OpenMPDirectiveKind CancelRegion)
static void emitDependData(CodeGenFunction &CGF, QualType &KmpDependInfoTy, llvm::PointerUnion< unsigned *, LValue * > Pos, const OMPTaskDataTy::DependData &Data, Address DependenciesArray)
static llvm::Value * emitTaskPrivateMappingFunction(CodeGenModule &CGM, SourceLocation Loc, const OMPTaskDataTy &Data, QualType PrivatesQTy, ArrayRef< PrivateDataTy > Privates)
Emit a privates mapping function for correct handling of private and firstprivate variables.
static llvm::Value * emitReduceCombFunction(CodeGenModule &CGM, SourceLocation Loc, ReductionCodeGen &RCG, unsigned N, const Expr *ReductionOp, const Expr *LHS, const Expr *RHS, const Expr *PrivateRef)
Emits reduction combiner function:
static RecordDecl * createPrivatesRecordDecl(CodeGenModule &CGM, ArrayRef< PrivateDataTy > Privates)
static llvm::Value * getAllocatorVal(CodeGenFunction &CGF, const Expr *Allocator)
Return allocator value from expression, or return a null allocator (default when no allocator specifi...
static llvm::Function * emitProxyTaskFunction(CodeGenModule &CGM, SourceLocation Loc, OpenMPDirectiveKind Kind, QualType KmpInt32Ty, QualType KmpTaskTWithPrivatesPtrQTy, QualType KmpTaskTWithPrivatesQTy, QualType KmpTaskTQTy, QualType SharedsPtrTy, llvm::Function *TaskFunction, llvm::Value *TaskPrivatesMap)
Emit a proxy function which accepts kmp_task_t as the second argument.
static void addAArch64VectorName(T VLEN, StringRef LMask, StringRef Prefix, char ISA, StringRef ParSeq, StringRef MangledName, bool OutputBecomesInput, llvm::Function *Fn)
static bool isAllocatableDecl(const VarDecl *VD)
static llvm::Value * getAlignmentValue(CodeGenModule &CGM, const VarDecl *VD)
Return the alignment from an allocate directive if present.
static void emitTargetCallKernelLaunch(CGOpenMPRuntime *OMPRuntime, llvm::Function *OutlinedFn, const OMPExecutableDirective &D, llvm::SmallVectorImpl< llvm::Value * > &CapturedVars, bool RequiresOuterTask, const CapturedStmt &CS, bool OffloadingMandatory, llvm::PointerIntPair< const Expr *, 2, OpenMPDeviceClauseModifier > Device, llvm::Value *OutlinedFnID, CodeGenFunction::OMPTargetDataInfo &InputInfo, llvm::Value *&MapTypesArray, llvm::Value *&MapNamesArray, llvm::function_ref< llvm::Value *(CodeGenFunction &CGF, const OMPLoopDirective &D)> SizeEmitter, CodeGenFunction &CGF, CodeGenModule &CGM)
static llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryKind convertCaptureClause(const VarDecl *VD)
static std::tuple< unsigned, unsigned, bool > getNDSWDS(const FunctionDecl *FD, ArrayRef< ParamAttrTy > ParamAttrs)
static const OMPExecutableDirective * getNestedDistributeDirective(ASTContext &Ctx, const OMPExecutableDirective &D)
Check for inner distribute directive.
static std::pair< llvm::Value *, llvm::Value * > getPointerAndSize(CodeGenFunction &CGF, const Expr *E)
static const VarDecl * getBaseDecl(const Expr *Ref, const DeclRefExpr *&DE)
static bool isTrivial(ASTContext &Ctx, const Expr *E)
Checks if the expression is constant or does not have non-trivial function calls.
static OpenMPSchedType getRuntimeSchedule(OpenMPScheduleClauseKind ScheduleKind, bool Chunked, bool Ordered)
Map the OpenMP loop schedule to the runtime enumeration.
static void getNumThreads(CodeGenFunction &CGF, const CapturedStmt *CS, const Expr **E, int32_t &UpperBound, bool UpperBoundOnly, llvm::Value **CondVal)
Check for a num threads constant value (stored in DefaultVal), or expression (stored in E).
static llvm::Value * emitDeviceID(llvm::PointerIntPair< const Expr *, 2, OpenMPDeviceClauseModifier > Device, CodeGenFunction &CGF)
static const OMPDeclareReductionDecl * getReductionInit(const Expr *ReductionOp)
Check if the combiner is a call to UDR combiner and if it is so return the UDR decl used for reductio...
static bool checkInitIsRequired(CodeGenFunction &CGF, ArrayRef< PrivateDataTy > Privates)
Check if duplication function is required for taskloops.
static bool checkDestructorsRequired(const RecordDecl *KmpTaskTWithPrivatesQTyRD, ArrayRef< PrivateDataTy > Privates)
Checks if destructor function is required to be generated.
static llvm::TargetRegionEntryInfo getEntryInfoFromPresumedLoc(CodeGenModule &CGM, llvm::OpenMPIRBuilder &OMPBuilder, SourceLocation BeginLoc, llvm::StringRef ParentName="")
static void genMapInfo(MappableExprsHandler &MEHandler, CodeGenFunction &CGF, MappableExprsHandler::MapCombinedInfoTy &CombinedInfo, llvm::OpenMPIRBuilder &OMPBuilder, const llvm::DenseSet< CanonicalDeclPtr< const Decl > > &SkippedVarSet=llvm::DenseSet< CanonicalDeclPtr< const Decl > >())
static 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 unsigned getAArch64LS(QualType QT, ParamKindTy Kind, ASTContext &C)
Computes the lane size (LS) of a return type or of an input parameter, as defined by LS(P) in 3....
static void EmitDoacrossOrdered(CodeGenFunction &CGF, CodeGenModule &CGM, const T *C, llvm::Value *ULoc, llvm::Value *ThreadID)
static RTLDependenceKindTy translateDependencyKind(OpenMPDependClauseKind K)
Translates internal dependency kind into the runtime kind.
static void emitTargetCallElse(CGOpenMPRuntime *OMPRuntime, llvm::Function *OutlinedFn, const OMPExecutableDirective &D, llvm::SmallVectorImpl< llvm::Value * > &CapturedVars, bool RequiresOuterTask, const CapturedStmt &CS, bool OffloadingMandatory, CodeGenFunction &CGF)
static llvm::Function * emitCombinerOrInitializer(CodeGenModule &CGM, QualType Ty, const Expr *CombinerInitializer, const VarDecl *In, const VarDecl *Out, bool IsCombiner)
static void emitX86DeclareSimdFunction(const FunctionDecl *FD, llvm::Function *Fn, const llvm::APSInt &VLENVal, ArrayRef< ParamAttrTy > ParamAttrs, OMPDeclareSimdDeclAttr::BranchStateTy State)
static void emitReductionCombiner(CodeGenFunction &CGF, const Expr *ReductionOp)
Emit reduction combiner.
static std::string mangleVectorParameters(ArrayRef< ParamAttrTy > ParamAttrs)
Mangle the parameter part of the vector function name according to their OpenMP classification.
static 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 void emitAArch64DeclareSimdFunction(CodeGenModule &CGM, const FunctionDecl *FD, unsigned UserVLEN, ArrayRef< ParamAttrTy > ParamAttrs, OMPDeclareSimdDeclAttr::BranchStateTy State, StringRef MangledName, char ISA, unsigned VecRegSize, llvm::Function *Fn, SourceLocation SLoc)
Emit vector function attributes for AArch64, as defined in the AAVFABI.
static Address emitAddrOfVarFromArray(CodeGenFunction &CGF, Address Array, unsigned Index, const VarDecl *Var)
Given an array of pointers to variables, project the address of a given variable.
static bool isAssumedToBeNotEmitted(const ValueDecl *VD, bool IsDevice)
static void addAArch64AdvSIMDNDSNames(unsigned NDS, StringRef Mask, StringRef Prefix, char ISA, StringRef ParSeq, StringRef MangledName, bool OutputBecomesInput, llvm::Function *Fn)
static FieldDecl * addFieldToRecordDecl(ASTContext &C, DeclContext *DC, QualType FieldTy)
static ValueDecl * getDeclFromThisExpr(const Expr *E)
static void genMapInfoForCaptures(MappableExprsHandler &MEHandler, CodeGenFunction &CGF, const CapturedStmt &CS, llvm::SmallVectorImpl< llvm::Value * > &CapturedVars, llvm::OpenMPIRBuilder &OMPBuilder, llvm::DenseSet< CanonicalDeclPtr< const Decl > > &MappedVarSet, MappableExprsHandler::MapCombinedInfoTy &CombinedInfo)
static RecordDecl * createKmpTaskTRecordDecl(CodeGenModule &CGM, OpenMPDirectiveKind Kind, QualType KmpInt32Ty, QualType KmpRoutineEntryPointerQTy)
static int addMonoNonMonoModifier(CodeGenModule &CGM, OpenMPSchedType Schedule, OpenMPScheduleClauseModifier M1, OpenMPScheduleClauseModifier M2)
static bool getAArch64MTV(QualType QT, ParamKindTy Kind)
Maps To Vector (MTV), as defined in 4.1.1 of the AAVFABI (2021Q1).
@ LLVM_MARK_AS_BITMASK_ENUM
This file defines OpenMP AST classes for clauses.
Defines some OpenMP-specific enums and functions.
Defines the SourceManager interface.
This file defines OpenMP AST classes for executable directives and clauses.
__DEVICE__ int max(int __a, int __b)
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
SourceManager & getSourceManager()
const ConstantArrayType * getAsConstantArrayType(QualType T) const
CharUnits getTypeAlignInChars(QualType T) const
Return the ABI-specified alignment of a (complete) type T, in characters.
const ASTRecordLayout & getASTRecordLayout(const RecordDecl *D) const
Get or compute information about the layout of the specified record (struct/union/class) D,...
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 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
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 ...
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 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.
llvm::Value * getCriticalRegionLock(StringRef CriticalName)
Returns corresponding lock object for the specified critical region name.
virtual void emitCancelCall(CodeGenFunction &CGF, SourceLocation Loc, const Expr *IfCond, OpenMPDirectiveKind CancelRegion)
Emit code for 'cancel' construct.
QualType SavedKmpTaskTQTy
Saved kmp_task_t for task directive.
virtual void emitMasterRegion(CodeGenFunction &CGF, const RegionCodeGenTy &MasterOpGen, SourceLocation Loc)
Emits a master region.
virtual llvm::Function * emitTaskOutlinedFunction(const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, const VarDecl *PartIDVar, const VarDecl *TaskTVar, OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen, bool Tied, unsigned &NumberOfParts)
Emits outlined function for the OpenMP task directive D.
llvm::DenseMap< llvm::Function *, unsigned > FunctionToUntiedTaskStackMap
Maps function to the position of the untied task locals stack.
void emitDestroyClause(CodeGenFunction &CGF, LValue DepobjLVal, SourceLocation Loc)
Emits the code to destroy the dependency object provided in depobj directive.
virtual void emitTaskReductionFixups(CodeGenFunction &CGF, SourceLocation Loc, ReductionCodeGen &RCG, unsigned N)
Required to resolve existing problems in the runtime.
llvm::ArrayType * KmpCriticalNameTy
Type kmp_critical_name, originally defined as typedef kmp_int32 kmp_critical_name[8];.
virtual void emitDoacrossOrdered(CodeGenFunction &CGF, const OMPDependClause *C)
Emit code for doacross ordered directive with 'depend' clause.
llvm::DenseMap< const OMPDeclareMapperDecl *, llvm::Function * > UDMMap
Map from the user-defined mapper declaration to its corresponding functions.
virtual void checkAndEmitLastprivateConditional(CodeGenFunction &CGF, const Expr *LHS)
Checks if the provided LVal is lastprivate conditional and emits the code to update the value of the ...
std::pair< llvm::Value *, LValue > getDepobjElements(CodeGenFunction &CGF, LValue DepobjLVal, SourceLocation Loc)
Returns the number of the elements and the address of the depobj dependency array.
llvm::SmallDenseSet< const VarDecl * > DeferredGlobalVariables
List of variables that can become declare target implicitly and, thus, must be emitted.
void emitUsesAllocatorsInit(CodeGenFunction &CGF, const Expr *Allocator, const Expr *AllocatorTraits)
Initializes user defined allocators specified in the uses_allocators clauses.
llvm::Type * KmpRoutineEntryPtrTy
Type typedef kmp_int32 (* kmp_routine_entry_t)(kmp_int32, void *);.
llvm::Type * getIdentTyPointerTy()
Returns pointer to ident_t type.
void emitSingleReductionCombiner(CodeGenFunction &CGF, const Expr *ReductionOp, const Expr *PrivateRef, const DeclRefExpr *LHS, const DeclRefExpr *RHS)
Emits single reduction combiner.
llvm::OpenMPIRBuilder & getOMPBuilder()
virtual void emitTargetOutlinedFunction(const OMPExecutableDirective &D, StringRef ParentName, llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID, bool IsOffloadEntry, const RegionCodeGenTy &CodeGen)
Emit outilined function for 'target' directive.
virtual void emitCriticalRegion(CodeGenFunction &CGF, StringRef CriticalName, const RegionCodeGenTy &CriticalOpGen, SourceLocation Loc, const Expr *Hint=nullptr)
Emits a critical region.
virtual void emitForOrderedIterationEnd(CodeGenFunction &CGF, SourceLocation Loc, unsigned IVSize, bool IVSigned)
Call the appropriate runtime routine to notify that we finished iteration of the ordered loop with th...
virtual void emitOutlinedFunctionCall(CodeGenFunction &CGF, SourceLocation Loc, llvm::FunctionCallee OutlinedFn, ArrayRef< llvm::Value * > Args={}) const
Emits call of the outlined function with the provided arguments, translating these arguments to corre...
llvm::Value * emitNumThreadsForTargetDirective(CodeGenFunction &CGF, const OMPExecutableDirective &D)
Emit an expression that denotes the number of threads a target region shall use.
void emitThreadPrivateVarInit(CodeGenFunction &CGF, Address VDAddr, llvm::Value *Ctor, llvm::Value *CopyCtor, llvm::Value *Dtor, SourceLocation Loc)
Emits initialization code for the threadprivate variables.
virtual void emitUserDefinedReduction(CodeGenFunction *CGF, const OMPDeclareReductionDecl *D)
Emit code for the specified user defined reduction construct.
virtual void checkAndEmitSharedLastprivateConditional(CodeGenFunction &CGF, const OMPExecutableDirective &D, const llvm::DenseSet< CanonicalDeclPtr< const VarDecl > > &IgnoredDecls)
Checks if the lastprivate conditional was updated in inner region and writes the value.
QualType KmpDimTy
struct kmp_dim { // loop bounds info casted to kmp_int64 kmp_int64 lo; // lower kmp_int64 up; // uppe...
virtual void emitInlinedDirective(CodeGenFunction &CGF, OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen, bool HasCancel=false)
Emit code for the directive that does not require outlining.
virtual void registerTargetGlobalVariable(const VarDecl *VD, llvm::Constant *Addr)
Checks if the provided global decl GD is a declare target variable and registers it when emitting cod...
virtual void emitFunctionProlog(CodeGenFunction &CGF, const Decl *D)
Emits OpenMP-specific function prolog.
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::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,...
void incrementProfileCounter(const Stmt *S, llvm::Value *StepV=nullptr)
Increment the profiler's counter for the given statement by StepV.
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.
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.
A specialization of Address that requires the address to be an LLVM Constant.
static ConstantAddress invalid()
bool requiresLandingPad() const
void pushTerminate()
Push a terminate handler on the stack.
void popTerminate()
Pops a terminate handler off the stack.
FunctionArgList - Type for representing both the decl and type of parameters to a function.
LValue - This represents an lvalue references.
CharUnits getAlignment() const
llvm::Value * getPointer(CodeGenFunction &CGF) const
const Qualifiers & getQuals() const
Address getAddress() const
LValueBaseInfo getBaseInfo() const
TBAAAccessInfo getTBAAInfo() const
A basic class for pre|post-action for advanced codegen sequence for OpenMP region.
virtual void Enter(CodeGenFunction &CGF)
RValue - This trivial value class is used to represent the result of an expression that is evaluated.
static RValue get(llvm::Value *V)
static RValue getComplex(llvm::Value *V1, llvm::Value *V2)
llvm::Value * getScalarVal() const
getScalarVal() - Return the Value* of this scalar value.
An abstract representation of an aligned address.
llvm::Type * getElementType() const
Return the type of the values stored in this address.
llvm::Value * getPointer() const
static RawAddress invalid()
Class intended to support codegen of all kind of the reduction clauses.
LValue getSharedLValue(unsigned N) const
Returns LValue for the reduction item.
const Expr * getRefExpr(unsigned N) const
Returns the base declaration of the reduction item.
LValue getOrigLValue(unsigned N) const
Returns LValue for the original reduction item.
bool needCleanups(unsigned N)
Returns true if the private copy requires cleanups.
void emitAggregateType(CodeGenFunction &CGF, unsigned N)
Emits the code for the variable-modified type, if required.
const VarDecl * getBaseDecl(unsigned N) const
Returns the base declaration of the reduction item.
QualType getPrivateType(unsigned N) const
Return the type of the private item.
bool usesReductionInitializer(unsigned N) const
Returns true if the initialization of the reduction item uses initializer from declare reduction cons...
void emitSharedOrigLValue(CodeGenFunction &CGF, unsigned N)
Emits lvalue for the shared and original reduction item.
void emitInitialization(CodeGenFunction &CGF, unsigned N, Address PrivateAddr, Address SharedAddr, llvm::function_ref< bool(CodeGenFunction &)> DefaultInit)
Performs initialization of the private copy for the reduction item.
std::pair< llvm::Value *, llvm::Value * > getSizes(unsigned N) const
Returns the size of the reduction item (in chars and total number of elements in the item),...
ReductionCodeGen(ArrayRef< const Expr * > Shareds, ArrayRef< const Expr * > Origs, ArrayRef< const Expr * > Privates, ArrayRef< const Expr * > ReductionOps)
void emitCleanups(CodeGenFunction &CGF, unsigned N, Address PrivateAddr)
Emits cleanup code for the reduction item.
Address adjustPrivateAddress(CodeGenFunction &CGF, unsigned N, Address PrivateAddr)
Adjusts PrivatedAddr for using instead of the original variable address in normal operations.
Class provides a way to call simple version of codegen for OpenMP region, or an advanced with possibl...
void operator()(CodeGenFunction &CGF) const
void setAction(PrePostActionTy &Action) const
ConstStmtVisitor - This class implements a simple visitor for Stmt subclasses.
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
void addDecl(Decl *D)
Add the declaration D into this context.
A reference to a declared variable, function, enum, etc.
Decl - This represents one declaration (or definition), e.g.
ASTContext & getASTContext() const LLVM_READONLY
virtual Stmt * getBody() const
getBody - If this Decl represents a declaration for a body of code, such as a function or method defi...
llvm::iterator_range< specific_attr_iterator< T > > specific_attrs() const
SourceLocation getLocation() const
DeclContext * getDeclContext()
virtual Decl * getCanonicalDecl()
Retrieves the "canonical" declaration of the given declaration.
SourceLocation getBeginLoc() const LLVM_READONLY
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
This represents one expression.
bool isIntegerConstantExpr(const ASTContext &Ctx) const
Expr * IgnoreParenNoopCasts(const ASTContext &Ctx) LLVM_READONLY
Skip past any parentheses and casts which do not change the value (including ptr->int casts of the sa...
@ SE_AllowSideEffects
Allow any unmodeled side effect.
@ SE_AllowUndefinedBehavior
Allow UB that we can give a value, but not arbitrary unmodeled side effects.
Expr * IgnoreParenCasts() LLVM_READONLY
Skip past any parentheses and casts which might surround this expression until reaching a fixed point...
llvm::APSInt EvaluateKnownConstInt(const ASTContext &Ctx) const
EvaluateKnownConstInt - Call EvaluateAsRValue and return the folded integer.
Expr * IgnoreParenImpCasts() LLVM_READONLY
Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...
bool isEvaluatable(const ASTContext &Ctx, SideEffectsKind AllowSideEffects=SE_NoSideEffects) const
isEvaluatable - Call EvaluateAsRValue to see if this expression can be constant folded without side-e...
std::optional< llvm::APSInt > getIntegerConstantExpr(const ASTContext &Ctx) const
isIntegerConstantExpr - Return the value if this expression is a valid integer constant expression.
bool HasSideEffects(const ASTContext &Ctx, bool IncludePossibleEffects=true) const
HasSideEffects - This routine returns true for all those expressions which have any effect other than...
bool EvaluateAsBooleanCondition(bool &Result, const ASTContext &Ctx, bool InConstantContext=false) const
EvaluateAsBooleanCondition - Return true if this is a constant which we can fold and convert to a boo...
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
static bool isSameComparisonOperand(const Expr *E1, const Expr *E2)
Checks that the two Expr's will refer to the same value as a comparison operand.
bool hasNonTrivialCall(const ASTContext &Ctx) const
Determine whether this expression involves a call to any function that is not trivial.
Represents a member of a struct/union/class.
unsigned getFieldIndex() const
Returns the index of this field within its record, as appropriate for passing to ASTRecordLayout::get...
const RecordDecl * getParent() const
Returns the parent of this field declaration, which is the struct in which this field is defined.
static FieldDecl * Create(const ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, const IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, Expr *BW, bool Mutable, InClassInitStyle InitStyle)
Represents a function declaration or definition.
const ParmVarDecl * getParamDecl(unsigned i) const
QualType getReturnType() const
ArrayRef< ParmVarDecl * > parameters() const
FunctionDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
FunctionDecl * getMostRecentDecl()
Returns the most recent (re)declaration of this declaration.
unsigned getNumParams() const
Return the number of parameters this function must have based on its FunctionType.
FunctionDecl * getPreviousDecl()
Return the previous declaration of this declaration or NULL if this is the first declaration.
GlobalDecl - represents a global declaration.
const Decl * getDecl() const
static ImplicitParamDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation IdLoc, IdentifierInfo *Id, QualType T, ImplicitParamKind ParamKind)
Create implicit parameter.
static IntegerLiteral * Create(const ASTContext &C, const llvm::APInt &V, QualType type, SourceLocation l)
Returns a new integer literal with value 'V' and type 'type'.
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
ValueDecl * getMemberDecl() const
Retrieve the member declaration to which this expression refers.
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
bool isExternallyVisible() const
This represents clause 'affinity' in the 'pragma omp task'-based directives.
Expr * getAssociatedExpression() const
ValueDecl * getAssociatedDeclaration() const
ArrayRef< MappableComponent > MappableExprComponentListRef
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.
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 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 'if' clause in the 'pragma omp ...' directive.
Expr * getCondition() const
Returns condition.
This represents clause 'in_reduction' in the 'pragma omp task' directives.
OMPIteratorHelperData & getHelper(unsigned I)
Fetches helper data for the specified iteration space.
unsigned numOfIterators() const
Returns number of iterator definitions.
This represents clause 'lastprivate' in the 'pragma omp ...' directives.
This represents clause 'nontemporal' in the 'pragma omp ...' directives.
This represents 'nowait' clause in the 'pragma omp ...' directive.
This represents 'num_teams' clause in the 'pragma omp ...' directive.
This represents 'num_threads' clause in the 'pragma omp ...' directive.
This represents 'ordered' clause in the 'pragma omp ...' directive.
This represents clause 'private' in the 'pragma omp ...' directives.
This represents 'pragma omp requires...' directive.
clauselist_range clauselists()
This represents 'thread_limit' clause in the 'pragma omp ...' directive.
This represents 'threadset' clause in the 'pragma omp task ...' directive.
This represents clause 'uses_allocators' in the 'pragma omp target'-based directives.
This represents 'ompx_attribute' clause in a directive that might generate an outlined function.
This represents 'ompx_bare' clause in the 'pragma omp target teams ...' directive.
This represents 'ompx_dyn_cgroup_mem' clause in the 'pragma omp target ...' directive.
OpaqueValueExpr - An expression referring to an opaque object of a fixed type and value class.
Represents a parameter to a function.
PointerType - C99 6.7.5.1 - Pointer Declarators.
Represents an unpacked "presumed" location which can be presented to the user.
unsigned getColumn() const
Return the presumed column number of this location.
const char * getFilename() const
Return the presumed filename of this location.
unsigned getLine() const
Return the presumed line number of this location.
A (possibly-)qualified type.
void addRestrict()
Add the restrict qualifier to this QualType.
QualType withRestrict() const
bool isNull() const
Return true if this QualType doesn't point to a type yet.
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
Qualifiers getQualifiers() const
Retrieve the set of qualifiers applied to this type.
QualType getNonReferenceType() const
If Type is a reference type (e.g., const int&), returns the type that the reference refers to ("const...
QualType getCanonicalType() const
DestructionKind isDestructedType() const
Returns a nonzero value if objects of this type require non-trivial work to clean up after.
Represents a struct/union/class.
field_iterator field_end() const
field_range fields() const
virtual void completeDefinition()
Note that the definition of this type is now complete.
field_iterator field_begin() const
Scope - A scope is a transient data structure that is used while parsing the program.
Encodes a location in the source.
static SourceLocation getFromRawEncoding(UIntTy Encoding)
Turn a raw encoding of a SourceLocation object into a real SourceLocation.
bool isValid() const
Return true if this is a valid SourceLocation object.
UIntTy getRawEncoding() const
When a SourceLocation itself cannot be used, this returns an (opaque) 32-bit integer encoding for it.
This class handles loading and caching of source files into memory.
PresumedLoc getPresumedLoc(SourceLocation Loc, bool UseLineDirectives=true) const
Returns the "presumed" location of a SourceLocation specifies.
Stmt - This represents one statement.
StmtClass getStmtClass() const
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Stmt * IgnoreContainers(bool IgnoreCaptured=false)
Skip no-op (attributed, compound) container stmts and skip captured stmt at the top,...
SourceLocation getBeginLoc() const LLVM_READONLY
void startDefinition()
Starts the definition of this tag declaration.
The base class of the type hierarchy.
const Type * getPointeeOrArrayElementType() const
If this is a pointer type, return the pointee type.
bool isSignedIntegerType() const
Return true if this is an integer type that is signed, according to C99 6.2.5p4 [char,...
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
RecordDecl * getAsRecordDecl() const
Retrieves the RecordDecl this type refers to.
bool isPointerType() const
CanQualType getCanonicalTypeUnqualified() const
bool isIntegerType() const
isIntegerType() does not include complex integers (a GCC extension).
const T * castAs() const
Member-template castAs<specific type>.
bool isReferenceType() const
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
bool isLValueReferenceType() const
bool isAggregateType() const
Determines whether the type is a C++ aggregate type or C aggregate or union type.
RecordDecl * castAsRecordDecl() const
QualType getCanonicalTypeInternal() const
const Type * getBaseElementTypeUnsafe() const
Get the base element type of this type, potentially discarding type qualifiers.
bool isVariablyModifiedType() const
Whether this type is a variably-modified type (C99 6.7.5).
const ArrayType * getAsArrayTypeUnsafe() const
A variant of getAs<> for array types which silently discards qualifiers from the outermost type.
bool isFloatingType() const
bool isUnsignedIntegerType() const
Return true if this is an integer type that is unsigned, according to C99 6.2.5p6 [which returns true...
bool isAnyPointerType() const
const T * getAs() const
Member-template getAs<specific type>'.
bool isRecordType() const
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Represents a variable declaration or definition.
VarDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
VarDecl * getDefinition(ASTContext &)
Get the real (not just tentative) definition for this declaration.
const Expr * getInit() const
bool hasExternalStorage() const
Returns true if a variable has extern or private_extern storage.
@ DeclarationOnly
This declaration is only a declaration.
DefinitionKind hasDefinition(ASTContext &) const
Check whether this variable is defined in this translation unit.
bool isLocalVarDeclOrParm() const
Similar to isLocalVarDecl but also includes parameters.
const Expr * getAnyInitializer() const
Get the initializer for this variable, no matter which declaration it is attached to.
Represents a C array with a specified size that is not an integer-constant-expression.
Expr * getSizeExpr() const
specific_attr_iterator - Iterates over a subrange of an AttrVec, only providing attributes that are o...
bool isEmptyRecordForLayout(const ASTContext &Context, QualType T)
isEmptyRecordForLayout - Return true iff a structure contains only empty base classes (per isEmptyRec...
@ Type
The l-value was considered opaque, so the alignment was determined from a type.
@ Decl
The l-value was an access to a declared entity or something equivalently strong, like the address of ...
bool isEmptyFieldForLayout(const ASTContext &Context, const FieldDecl *FD)
isEmptyFieldForLayout - Return true iff the field is "empty", that is, either a zero-width bit-field ...
ComparisonResult
Indicates the result of a tentative comparison.
The JSON file list parser is used to communicate input to InstallAPI.
bool isOpenMPWorksharingDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a worksharing directive.
CanQual< Type > CanQualType
Represents a canonical, potentially-qualified type.
bool needsTaskBasedThreadLimit(OpenMPDirectiveKind DKind)
Checks if the specified target directive, combined or not, needs task based thread_limit.
@ Match
This is not an overload because the signature exactly matches an existing declaration.
@ Ctor_Complete
Complete object ctor.
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.
@ 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...
@ Vector
'vector' clause, allowed on 'loop', Combined, and 'routine' directives.
@ Reduction
'reduction' clause, allowed on Parallel, Serial, Loop, and the combined constructs.
@ Present
'present' clause, allowed on Compute and Combined constructs, plus 'data' and 'declare'.
OpenMPScheduleClauseModifier
OpenMP modifiers for 'schedule' clause.
@ OMPC_SCHEDULE_MODIFIER_last
@ OMPC_SCHEDULE_MODIFIER_unknown
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.
static bool classof(const Stmt *T)
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.
const FunctionProtoType * T
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.
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;.
Data for list of allocators.
Expr * AllocatorTraits
Allocator traits.
Expr * Allocator
Allocator.
Scheduling data for loop-based OpenMP directives.
OpenMPScheduleClauseModifier M2
OpenMPScheduleClauseModifier M1
OpenMPScheduleClauseKind Schedule
Describes how types, statements, expressions, and declarations should be printed.