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);
1783 OMPBuilder.OffloadInfoManager.registerDeviceGlobalVarEntryInfo(
1784 Name,
Addr,
CGM.GetTargetTypeStoreSize(
CGM.VoidPtrTy).getQuantity(),
1785 llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryIndirect,
1786 llvm::GlobalValue::WeakODRLinkage);
1799 llvm::OpenMPIRBuilder &
OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
1815 llvm::GlobalVariable *
Addr = VTable;
1817 OMPBuilder.OffloadInfoManager.getTargetRegionEntryFnName(AddrName, EntryInfo);
1818 AddrName.append(
"addr");
1820 if (
CGM.getLangOpts().OpenMPIsTargetDevice) {
1821 Addr =
new llvm::GlobalVariable(
1822 CGM.getModule(), VTable->getType(),
1823 true, llvm::GlobalValue::ExternalLinkage, VTable,
1825 nullptr, llvm::GlobalValue::NotThreadLocal,
1826 CGM.getModule().getDataLayout().getDefaultGlobalsAddressSpace());
1827 Addr->setVisibility(llvm::GlobalValue::ProtectedVisibility);
1829 OMPBuilder.OffloadInfoManager.registerDeviceGlobalVarEntryInfo(
1831 CGM.getDataLayout().getTypeAllocSize(VTable->getInitializer()->getType()),
1832 llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryIndirectVTable,
1833 llvm::GlobalValue::WeakODRLinkage);
1842 !
CGM.getOpenMPRuntime().VTableDeclMap.contains(
CXXRecord)) {
1843 auto Res =
CGM.getOpenMPRuntime().VTableDeclMap.try_emplace(
CXXRecord, VD);
1848 assert(VTablesAddr &&
"Expected non-null VTable address");
1849 CGM.getOpenMPRuntime().registerVTableOffloadEntry(VTablesAddr, VD);
1867 auto GetVTableDecl = [](
const Expr *E) {
1878 if (
auto *DRE = dyn_cast<DeclRefExpr>(E)) {
1880 }
else if (
auto *MRE = dyn_cast<MemberExpr>(E)) {
1881 if (
auto *BaseDRE = dyn_cast<DeclRefExpr>(MRE->getBase())) {
1882 if (
auto *BaseVD = dyn_cast<VarDecl>(BaseDRE->getDecl()))
1886 return std::pair<CXXRecordDecl *, const VarDecl *>(
CXXRecord, VD);
1890 for (
const auto *E :
C->varlist()) {
1891 auto DeclPair = GetVTableDecl(E);
1893 if (DeclPair.second)
1902 std::string Suffix =
getName({
"artificial",
""});
1904 llvm::GlobalVariable *GAddr =
OMPBuilder.getOrCreateInternalVariable(
1905 VarLVType, Twine(Name).concat(Suffix).str());
1906 if (
CGM.getLangOpts().OpenMP &&
CGM.getLangOpts().OpenMPUseTLS &&
1907 CGM.getTarget().isTLSSupported()) {
1908 GAddr->setThreadLocal(
true);
1909 return Address(GAddr, GAddr->getValueType(),
1910 CGM.getContext().getTypeAlignInChars(VarType));
1912 std::string CacheSuffix =
getName({
"cache",
""});
1913 llvm::Value *Args[] = {
1921 Twine(Name).concat(Suffix).concat(CacheSuffix).str())};
1926 CGM.getModule(), OMPRTL___kmpc_threadprivate_cached),
1929 VarLVType,
CGM.getContext().getTypeAlignInChars(VarType));
1979 auto &M =
CGM.getModule();
1980 auto &&ThenGen = [&M, OutlinedFn, CapturedVars, RTLoc,
1983 llvm::Value *Args[] = {
1985 CGF.
Builder.getInt32(CapturedVars.size()),
1988 RealArgs.append(std::begin(Args), std::end(Args));
1989 RealArgs.append(CapturedVars.begin(), CapturedVars.end());
1991 llvm::FunctionCallee RTLFn =
1992 OMPBuilder.getOrCreateRuntimeFunction(M, OMPRTL___kmpc_fork_call);
1995 auto &&ElseGen = [&M, OutlinedFn, CapturedVars, RTLoc, Loc,
2001 llvm::Value *Args[] = {RTLoc, ThreadID};
2003 M, OMPRTL___kmpc_serialized_parallel),
2010 ".bound.zero.addr");
2015 OutlinedFnArgs.push_back(ZeroAddrBound.
getPointer());
2016 OutlinedFnArgs.append(CapturedVars.begin(), CapturedVars.end());
2024 OutlinedFn->removeFnAttr(llvm::Attribute::AlwaysInline);
2025 OutlinedFn->addFnAttr(llvm::Attribute::NoInline);
2031 M, OMPRTL___kmpc_end_serialized_parallel),
2050 if (
auto *OMPRegionInfo =
2052 if (OMPRegionInfo->getThreadIDVariable())
2053 return OMPRegionInfo->getThreadIDVariableLValue(CGF).getAddress();
2062 return ThreadIDTemp;
2066 std::string Prefix = Twine(
"gomp_critical_user_", CriticalName).str();
2067 std::string Name =
getName({Prefix,
"var"});
2074 llvm::FunctionCallee EnterCallee;
2076 llvm::FunctionCallee ExitCallee;
2079 llvm::BasicBlock *ContBlock =
nullptr;
2082 CommonActionTy(llvm::FunctionCallee EnterCallee,
2084 llvm::FunctionCallee ExitCallee,
2086 : EnterCallee(EnterCallee), EnterArgs(EnterArgs), ExitCallee(ExitCallee),
2091 llvm::Value *CallBool = CGF.
Builder.CreateIsNotNull(EnterRes);
2095 CGF.
Builder.CreateCondBr(CallBool, ThenBlock, ContBlock);
2099 void Done(CodeGenFunction &CGF) {
2104 void Exit(CodeGenFunction &CGF)
override {
2111 StringRef CriticalName,
2120 llvm::FunctionCallee RuntimeFcn =
OMPBuilder.getOrCreateRuntimeFunction(
2122 Hint ? OMPRTL___kmpc_critical_with_hint : OMPRTL___kmpc_critical);
2124 unsigned LockVarArgIdx = 2;
2126 RuntimeFcn.getFunctionType()
2127 ->getParamType(LockVarArgIdx)
2128 ->getPointerAddressSpace())
2130 LockVar, RuntimeFcn.getFunctionType()->getParamType(LockVarArgIdx));
2136 EnterArgs.push_back(CGF.
Builder.CreateIntCast(
2139 CommonActionTy Action(RuntimeFcn, EnterArgs,
2141 CGM.getModule(), OMPRTL___kmpc_end_critical),
2158 CommonActionTy Action(
OMPBuilder.getOrCreateRuntimeFunction(
2159 CGM.getModule(), OMPRTL___kmpc_master),
2162 CGM.getModule(), OMPRTL___kmpc_end_master),
2180 llvm::Value *FilterVal = Filter
2182 : llvm::ConstantInt::get(
CGM.Int32Ty, 0);
2187 CommonActionTy Action(
OMPBuilder.getOrCreateRuntimeFunction(
2188 CGM.getModule(), OMPRTL___kmpc_masked),
2191 CGM.getModule(), OMPRTL___kmpc_end_masked),
2207 llvm::Value *Args[] = {
2209 llvm::ConstantInt::get(
CGM.IntTy, 0,
true)};
2211 CGM.getModule(), OMPRTL___kmpc_omp_taskyield),
2215 if (
auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.
CapturedStmtInfo))
2216 Region->emitUntiedSwitch(CGF);
2229 CommonActionTy Action(
OMPBuilder.getOrCreateRuntimeFunction(
2230 CGM.getModule(), OMPRTL___kmpc_taskgroup),
2233 CGM.getModule(), OMPRTL___kmpc_end_taskgroup),
2242 unsigned Index,
const VarDecl *Var) {
2263 Args.push_back(&LHSArg);
2264 Args.push_back(&RHSArg);
2270 llvm::GlobalValue::InternalLinkage, Name,
2273 Fn->setDoesNotRecurse();
2290 for (
unsigned I = 0, E = AssignmentOps.size(); I < E; ++I) {
2291 const auto *DestVar =
2295 const auto *SrcVar =
2301 CGF.
EmitOMPCopy(
Type, DestAddr, SrcAddr, DestVar, SrcVar, AssignmentOps[I]);
2316 assert(CopyprivateVars.size() == SrcExprs.size() &&
2317 CopyprivateVars.size() == DstExprs.size() &&
2318 CopyprivateVars.size() == AssignmentOps.size());
2330 if (!CopyprivateVars.empty()) {
2333 C.getIntTypeForBitwidth(32, 1);
2334 DidIt = CGF.
CreateMemTemp(KmpInt32Ty,
".omp.copyprivate.did_it");
2339 CommonActionTy Action(
OMPBuilder.getOrCreateRuntimeFunction(
2340 CGM.getModule(), OMPRTL___kmpc_single),
2343 CGM.getModule(), OMPRTL___kmpc_end_single),
2356 llvm::APInt ArraySize(32, CopyprivateVars.size());
2357 QualType CopyprivateArrayTy =
C.getConstantArrayType(
2362 CGF.
CreateMemTemp(CopyprivateArrayTy,
".omp.copyprivate.cpr_list");
2363 for (
unsigned I = 0, E = CopyprivateVars.size(); I < E; ++I) {
2375 SrcExprs, DstExprs, AssignmentOps, Loc);
2376 llvm::Value *BufSize = CGF.
getTypeSize(CopyprivateArrayTy);
2380 llvm::Value *Args[] = {
2384 CL.emitRawPointer(CGF),
2389 CGM.getModule(), OMPRTL___kmpc_copyprivate),
2405 CommonActionTy Action(
OMPBuilder.getOrCreateRuntimeFunction(
2406 CGM.getModule(), OMPRTL___kmpc_ordered),
2409 CGM.getModule(), OMPRTL___kmpc_end_ordered),
2420 if (Kind == OMPD_for)
2421 Flags = OMP_IDENT_BARRIER_IMPL_FOR;
2422 else if (Kind == OMPD_sections)
2423 Flags = OMP_IDENT_BARRIER_IMPL_SECTIONS;
2424 else if (Kind == OMPD_single)
2425 Flags = OMP_IDENT_BARRIER_IMPL_SINGLE;
2426 else if (Kind == OMPD_barrier)
2427 Flags = OMP_IDENT_BARRIER_EXPL;
2429 Flags = OMP_IDENT_BARRIER_IMPL;
2439 S.getClausesOfKind<OMPOrderedClause>(),
2440 [](
const OMPOrderedClause *
C) { return C->getNumForLoops(); })) {
2441 ScheduleKind = OMPC_SCHEDULE_static;
2443 llvm::APInt ChunkSize(32, 1);
2453 bool ForceSimpleCall) {
2455 auto *OMPRegionInfo =
2458 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
2461 CGF.
Builder.restoreIP(AfterIP);
2474 if (OMPRegionInfo) {
2475 if (!ForceSimpleCall && OMPRegionInfo->hasCancel()) {
2478 OMPRTL___kmpc_cancel_barrier),
2487 CGF.
Builder.CreateCondBr(Cmp, ExitBB, ContBB);
2499 CGM.getModule(), OMPRTL___kmpc_barrier),
2504 Expr *ME,
bool IsFatal) {
2506 : llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
2509 llvm::Value *Args[] = {
2511 llvm::ConstantInt::get(
CGM.Int32Ty, IsFatal ? 2 : 1),
2512 CGF.
Builder.CreatePointerCast(MVL,
CGM.Int8PtrTy)};
2514 CGM.getModule(), OMPRTL___kmpc_error),
2520 bool Chunked,
bool Ordered) {
2521 switch (ScheduleKind) {
2522 case OMPC_SCHEDULE_static:
2523 return Chunked ? (Ordered ? OMP_ord_static_chunked : OMP_sch_static_chunked)
2524 : (Ordered ? OMP_ord_static : OMP_sch_static);
2525 case OMPC_SCHEDULE_dynamic:
2526 return Ordered ? OMP_ord_dynamic_chunked : OMP_sch_dynamic_chunked;
2527 case OMPC_SCHEDULE_guided:
2528 return Ordered ? OMP_ord_guided_chunked : OMP_sch_guided_chunked;
2529 case OMPC_SCHEDULE_runtime:
2530 return Ordered ? OMP_ord_runtime : OMP_sch_runtime;
2531 case OMPC_SCHEDULE_auto:
2532 return Ordered ? OMP_ord_auto : OMP_sch_auto;
2534 assert(!Chunked &&
"chunk was specified but schedule kind not known");
2535 return Ordered ? OMP_ord_static : OMP_sch_static;
2537 llvm_unreachable(
"Unexpected runtime schedule");
2541static OpenMPSchedType
2544 return Chunked ? OMP_dist_sch_static_chunked : OMP_dist_sch_static;
2548 bool Chunked)
const {
2549 OpenMPSchedType Schedule =
2551 return Schedule == OMP_sch_static;
2557 return Schedule == OMP_dist_sch_static;
2561 bool Chunked)
const {
2562 OpenMPSchedType Schedule =
2564 return Schedule == OMP_sch_static_chunked;
2570 return Schedule == OMP_dist_sch_static_chunked;
2574 OpenMPSchedType Schedule =
2576 assert(Schedule != OMP_sch_static_chunked &&
"cannot be chunked here");
2577 return Schedule != OMP_sch_static;
2585 case OMPC_SCHEDULE_MODIFIER_monotonic:
2586 Modifier = OMP_sch_modifier_monotonic;
2588 case OMPC_SCHEDULE_MODIFIER_nonmonotonic:
2589 Modifier = OMP_sch_modifier_nonmonotonic;
2591 case OMPC_SCHEDULE_MODIFIER_simd:
2592 if (Schedule == OMP_sch_static_chunked)
2593 Schedule = OMP_sch_static_balanced_chunked;
2600 case OMPC_SCHEDULE_MODIFIER_monotonic:
2601 Modifier = OMP_sch_modifier_monotonic;
2603 case OMPC_SCHEDULE_MODIFIER_nonmonotonic:
2604 Modifier = OMP_sch_modifier_nonmonotonic;
2606 case OMPC_SCHEDULE_MODIFIER_simd:
2607 if (Schedule == OMP_sch_static_chunked)
2608 Schedule = OMP_sch_static_balanced_chunked;
2620 if (CGM.
getLangOpts().OpenMP >= 50 && Modifier == 0) {
2621 if (!(Schedule == OMP_sch_static_chunked || Schedule == OMP_sch_static ||
2622 Schedule == OMP_sch_static_balanced_chunked ||
2623 Schedule == OMP_ord_static_chunked || Schedule == OMP_ord_static ||
2624 Schedule == OMP_dist_sch_static_chunked ||
2625 Schedule == OMP_dist_sch_static))
2626 Modifier = OMP_sch_modifier_nonmonotonic;
2628 return Schedule | Modifier;
2638 ScheduleKind.
Schedule, DispatchValues.
Chunk !=
nullptr, Ordered);
2640 (Schedule != OMP_sch_static && Schedule != OMP_sch_static_chunked &&
2641 Schedule != OMP_ord_static && Schedule != OMP_ord_static_chunked &&
2642 Schedule != OMP_sch_static_balanced_chunked));
2649 llvm::Value *Chunk = DispatchValues.
Chunk ? DispatchValues.
Chunk
2650 : CGF.
Builder.getIntN(IVSize, 1);
2651 llvm::Value *Args[] = {
2655 CGM, Schedule, ScheduleKind.
M1, ScheduleKind.
M2)),
2658 CGF.
Builder.getIntN(IVSize, 1),
2675 CodeGenFunction &CGF, llvm::Value *UpdateLocation, llvm::Value *ThreadId,
2676 llvm::FunctionCallee ForStaticInitFunction, OpenMPSchedType Schedule,
2683 assert(Schedule == OMP_sch_static || Schedule == OMP_sch_static_chunked ||
2684 Schedule == OMP_sch_static_balanced_chunked ||
2685 Schedule == OMP_ord_static || Schedule == OMP_ord_static_chunked ||
2686 Schedule == OMP_dist_sch_static ||
2687 Schedule == OMP_dist_sch_static_chunked);
2694 llvm::Value *Chunk = Values.
Chunk;
2695 if (Chunk ==
nullptr) {
2696 assert((Schedule == OMP_sch_static || Schedule == OMP_ord_static ||
2697 Schedule == OMP_dist_sch_static) &&
2698 "expected static non-chunked schedule");
2702 assert((Schedule == OMP_sch_static_chunked ||
2703 Schedule == OMP_sch_static_balanced_chunked ||
2704 Schedule == OMP_ord_static_chunked ||
2705 Schedule == OMP_dist_sch_static_chunked) &&
2706 "expected static chunked schedule");
2708 llvm::Value *Args[] = {
2731 "Expected loop-based or sections-based directive.");
2734 ? OMP_IDENT_WORK_LOOP
2735 : OMP_IDENT_WORK_SECTIONS);
2737 llvm::FunctionCallee StaticInitFunction =
2742 ScheduleNum, ScheduleKind.
M1, ScheduleKind.
M2, Values);
2749 OpenMPSchedType ScheduleNum =
2751 llvm::Value *UpdatedLocation =
2754 llvm::FunctionCallee StaticInitFunction;
2755 bool isGPUDistribute =
2756 CGM.getLangOpts().OpenMPIsTargetDevice &&
CGM.getTriple().isGPU();
2757 StaticInitFunction =
OMPBuilder.createForStaticInitFunction(
2768 assert((DKind == OMPD_distribute || DKind == OMPD_for ||
2769 DKind == OMPD_sections) &&
2770 "Expected distribute, for, or sections directive kind");
2774 llvm::Value *Args[] = {
2777 (DKind == OMPD_target_teams_loop)
2778 ? OMP_IDENT_WORK_DISTRIBUTE
2780 ? OMP_IDENT_WORK_LOOP
2781 : OMP_IDENT_WORK_SECTIONS),
2785 CGM.getLangOpts().OpenMPIsTargetDevice &&
CGM.getTriple().isGPU())
2788 CGM.getModule(), OMPRTL___kmpc_distribute_static_fini),
2792 CGM.getModule(), OMPRTL___kmpc_for_static_fini),
2817 llvm::Value *Args[] = {
2825 OMPBuilder.createDispatchNextFunction(IVSize, IVSigned), Args);
2832 const Expr *Message,
2835 return llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
2844 return llvm::ConstantInt::get(
CGM.Int32Ty,
2845 Severity == OMPC_SEVERITY_warning ? 1 : 2);
2861 RuntimeFunction FnID = OMPRTL___kmpc_push_num_threads;
2862 if (Modifier == OMPC_NUMTHREADS_strict) {
2863 FnID = OMPRTL___kmpc_push_num_threads_strict;
2868 OMPBuilder.getOrCreateRuntimeFunction(
CGM.getModule(), FnID), Args);
2872 ProcBindKind ProcBind,
2876 assert(ProcBind != OMP_PROC_BIND_unknown &&
"Unsupported proc_bind value.");
2878 llvm::Value *Args[] = {
2880 llvm::ConstantInt::get(
CGM.IntTy,
unsigned(ProcBind),
true)};
2882 CGM.getModule(), OMPRTL___kmpc_push_proc_bind),
2895 CGM.getModule(), OMPRTL___kmpc_flush),
2902enum KmpTaskTFields {
2929 if (
CGM.getLangOpts().OpenMPSimd ||
OMPBuilder.OffloadInfoManager.empty())
2932 llvm::OpenMPIRBuilder::EmitMetadataErrorReportFunctionTy &&ErrorReportFn =
2933 [
this](llvm::OpenMPIRBuilder::EmitMetadataErrorKind Kind,
2934 const llvm::TargetRegionEntryInfo &EntryInfo) ->
void {
2936 if (Kind != llvm::OpenMPIRBuilder::EMIT_MD_GLOBAL_VAR_LINK_ERROR) {
2937 for (
auto I =
CGM.getContext().getSourceManager().fileinfo_begin(),
2938 E =
CGM.getContext().getSourceManager().fileinfo_end();
2940 if (I->getFirst().getUniqueID().getDevice() == EntryInfo.DeviceID &&
2941 I->getFirst().getUniqueID().getFile() == EntryInfo.FileID) {
2942 Loc =
CGM.getContext().getSourceManager().translateFileLineCol(
2943 I->getFirst(), EntryInfo.Line, 1);
2949 case llvm::OpenMPIRBuilder::EMIT_MD_TARGET_REGION_ERROR: {
2950 CGM.getDiags().Report(Loc,
2951 diag::err_target_region_offloading_entry_incorrect)
2952 << EntryInfo.ParentName;
2954 case llvm::OpenMPIRBuilder::EMIT_MD_DECLARE_TARGET_ERROR: {
2955 CGM.getDiags().Report(
2956 Loc, diag::err_target_var_offloading_entry_incorrect_with_parent)
2957 << EntryInfo.ParentName;
2959 case llvm::OpenMPIRBuilder::EMIT_MD_GLOBAL_VAR_LINK_ERROR: {
2960 CGM.getDiags().Report(diag::err_target_var_offloading_entry_incorrect);
2962 case llvm::OpenMPIRBuilder::EMIT_MD_GLOBAL_VAR_INDIRECT_ERROR: {
2963 unsigned DiagID =
CGM.getDiags().getCustomDiagID(
2965 "target variable is incorrect: the "
2966 "address is invalid.");
2967 CGM.getDiags().Report(DiagID);
2972 OMPBuilder.createOffloadEntriesAndInfoMetadata(ErrorReportFn);
2979 QualType KmpRoutineEntryTyArgs[] = {KmpInt32Ty,
C.VoidPtrTy};
2982 C.getFunctionType(KmpInt32Ty, KmpRoutineEntryTyArgs, EPI));
2988struct PrivateHelpersTy {
2989 PrivateHelpersTy(
const Expr *OriginalRef,
const VarDecl *Original,
2991 : OriginalRef(OriginalRef), Original(Original), PrivateCopy(PrivateCopy),
2992 PrivateElemInit(PrivateElemInit) {}
2993 PrivateHelpersTy(
const VarDecl *Original) : Original(Original) {}
2994 const Expr *OriginalRef =
nullptr;
2995 const VarDecl *Original =
nullptr;
2996 const VarDecl *PrivateCopy =
nullptr;
2997 const VarDecl *PrivateElemInit =
nullptr;
2998 bool isLocalPrivate()
const {
2999 return !OriginalRef && !PrivateCopy && !PrivateElemInit;
3002typedef std::pair<CharUnits , PrivateHelpersTy> PrivateDataTy;
3007 if (!CVD->
hasAttr<OMPAllocateDeclAttr>())
3009 const auto *AA = CVD->
getAttr<OMPAllocateDeclAttr>();
3011 return !(AA->getAllocatorType() == OMPAllocateDeclAttr::OMPDefaultMemAlloc &&
3012 !AA->getAllocator());
3022 RecordDecl *RD =
C.buildImplicitRecord(
".kmp_privates.t");
3024 for (
const auto &Pair :
Privates) {
3025 const VarDecl *VD = Pair.second.Original;
3029 if (Pair.second.isLocalPrivate()) {
3052 QualType KmpRoutineEntryPointerQTy) {
3072 CanQualType KmpCmplrdataTy =
C.getCanonicalTagType(UD);
3073 RecordDecl *RD =
C.buildImplicitRecord(
"kmp_task_t");
3103 RecordDecl *RD =
C.buildImplicitRecord(
"kmp_task_t_with_privates");
3123static llvm::Function *
3126 QualType KmpTaskTWithPrivatesPtrQTy,
3128 QualType SharedsPtrTy, llvm::Function *TaskFunction,
3129 llvm::Value *TaskPrivatesMap) {
3137 Args.push_back(&GtidArg);
3138 Args.push_back(&TaskTypeArg);
3139 const auto &TaskEntryFnInfo =
3141 llvm::FunctionType *TaskEntryTy =
3144 auto *TaskEntry = llvm::Function::Create(
3145 TaskEntryTy, llvm::GlobalValue::InternalLinkage, Name, &CGM.
getModule());
3147 TaskEntry->setDoesNotRecurse();
3162 const auto *KmpTaskTWithPrivatesQTyRD =
3167 auto PartIdFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTPartId);
3169 llvm::Value *PartidParam = PartIdLVal.getPointer(CGF);
3171 auto SharedsFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTShareds);
3177 auto PrivatesFI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin(), 1);
3178 llvm::Value *PrivatesParam;
3179 if (PrivatesFI != KmpTaskTWithPrivatesQTyRD->field_end()) {
3182 PrivatesLVal.getPointer(CGF), CGF.
VoidPtrTy);
3184 PrivatesParam = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
3187 llvm::Value *CommonArgs[] = {
3188 GtidParam, PartidParam, PrivatesParam, TaskPrivatesMap,
3194 std::end(CommonArgs));
3196 auto LBFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound);
3199 auto UBFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound);
3202 auto StFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTStride);
3205 auto LIFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLastIter);
3208 auto RFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTReductions);
3211 CallArgs.push_back(LBParam);
3212 CallArgs.push_back(UBParam);
3213 CallArgs.push_back(StParam);
3214 CallArgs.push_back(LIParam);
3215 CallArgs.push_back(RParam);
3217 CallArgs.push_back(SharedsParam);
3230 QualType KmpTaskTWithPrivatesPtrQTy,
3231 QualType KmpTaskTWithPrivatesQTy) {
3239 Args.push_back(&GtidArg);
3240 Args.push_back(&TaskTypeArg);
3241 const auto &DestructorFnInfo =
3243 llvm::FunctionType *DestructorFnTy =
3247 auto *DestructorFn =
3248 llvm::Function::Create(DestructorFnTy, llvm::GlobalValue::InternalLinkage,
3252 DestructorFn->setDoesNotRecurse();
3260 const auto *KmpTaskTWithPrivatesQTyRD =
3262 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin());
3264 for (
const auto *Field : FI->getType()->castAsRecordDecl()->fields()) {
3266 Field->getType().isDestructedType()) {
3268 CGF.
pushDestroy(DtorKind, FieldLValue.getAddress(), Field->getType());
3272 return DestructorFn;
3292 C,
nullptr, Loc,
nullptr,
3293 C.getPointerType(PrivatesQTy).withConst().withRestrict(),
3295 Args.push_back(&TaskPrivatesArg);
3296 llvm::DenseMap<CanonicalDeclPtr<const VarDecl>,
unsigned> PrivateVarsPos;
3297 unsigned Counter = 1;
3298 for (
const Expr *E :
Data.PrivateVars) {
3300 C,
nullptr, Loc,
nullptr,
3301 C.getPointerType(
C.getPointerType(E->
getType()))
3306 PrivateVarsPos[VD] = Counter;
3309 for (
const Expr *E :
Data.FirstprivateVars) {
3311 C,
nullptr, Loc,
nullptr,
3312 C.getPointerType(
C.getPointerType(E->
getType()))
3317 PrivateVarsPos[VD] = Counter;
3320 for (
const Expr *E :
Data.LastprivateVars) {
3322 C,
nullptr, Loc,
nullptr,
3323 C.getPointerType(
C.getPointerType(E->
getType()))
3328 PrivateVarsPos[VD] = Counter;
3334 Ty =
C.getPointerType(Ty);
3336 Ty =
C.getPointerType(Ty);
3338 C,
nullptr, Loc,
nullptr,
3339 C.getPointerType(
C.getPointerType(Ty)).withConst().withRestrict(),
3341 PrivateVarsPos[VD] = Counter;
3344 const auto &TaskPrivatesMapFnInfo =
3346 llvm::FunctionType *TaskPrivatesMapTy =
3350 auto *TaskPrivatesMap = llvm::Function::Create(
3351 TaskPrivatesMapTy, llvm::GlobalValue::InternalLinkage, Name,
3354 TaskPrivatesMapFnInfo);
3356 TaskPrivatesMap->removeFnAttr(llvm::Attribute::NoInline);
3357 TaskPrivatesMap->removeFnAttr(llvm::Attribute::OptimizeNone);
3358 TaskPrivatesMap->addFnAttr(llvm::Attribute::AlwaysInline);
3362 TaskPrivatesMapFnInfo, Args, Loc, Loc);
3370 for (
const FieldDecl *Field : PrivatesQTyRD->fields()) {
3372 const VarDecl *VD = Args[PrivateVarsPos[
Privates[Counter].second.Original]];
3376 RefLVal.getAddress(), RefLVal.getType()->castAs<
PointerType>());
3381 return TaskPrivatesMap;
3387 Address KmpTaskSharedsPtr, LValue TDBase,
3393 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->
field_begin());
3407 if ((!IsTargetTask && !
Data.FirstprivateVars.empty() && ForDup) ||
3408 (IsTargetTask && KmpTaskSharedsPtr.
isValid())) {
3415 FI = FI->getType()->castAsRecordDecl()->field_begin();
3416 for (
const PrivateDataTy &Pair :
Privates) {
3418 if (Pair.second.isLocalPrivate()) {
3422 const VarDecl *VD = Pair.second.PrivateCopy;
3427 if (
const VarDecl *Elem = Pair.second.PrivateElemInit) {
3428 const VarDecl *OriginalVD = Pair.second.Original;
3431 LValue SharedRefLValue;
3434 if (IsTargetTask && !SharedField) {
3438 ->getNumParams() == 0 &&
3441 ->getDeclContext()) &&
3442 "Expected artificial target data variable.");
3445 }
else if (ForDup) {
3448 SharedRefLValue.getAddress().withAlignment(
3449 C.getDeclAlign(OriginalVD)),
3451 SharedRefLValue.getTBAAInfo());
3453 Pair.second.Original->getCanonicalDecl()) > 0 ||
3455 SharedRefLValue = CGF.
EmitLValue(Pair.second.OriginalRef);
3458 InlinedOpenMPRegionRAII Region(
3461 SharedRefLValue = CGF.
EmitLValue(Pair.second.OriginalRef);
3472 PrivateLValue.getAddress(), SharedRefLValue.getAddress(),
Type,
3473 [&CGF, Elem,
Init, &CapturesInfo](
Address DestElement,
3476 CodeGenFunction::OMPPrivateScope InitScope(CGF);
3477 InitScope.addPrivate(Elem, SrcElement);
3478 (void)InitScope.Privatize();
3480 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(
3481 CGF, &CapturesInfo);
3482 CGF.EmitAnyExprToMem(Init, DestElement,
3483 Init->getType().getQualifiers(),
3489 InitScope.addPrivate(Elem, SharedRefLValue.getAddress());
3490 (void)InitScope.Privatize();
3506 bool InitRequired =
false;
3507 for (
const PrivateDataTy &Pair :
Privates) {
3508 if (Pair.second.isLocalPrivate())
3510 const VarDecl *VD = Pair.second.PrivateCopy;
3512 InitRequired = InitRequired || (isa_and_nonnull<CXXConstructExpr>(
Init) &&
3517 return InitRequired;
3534 QualType KmpTaskTWithPrivatesPtrQTy,
3542 KmpTaskTWithPrivatesPtrQTy,
3545 KmpTaskTWithPrivatesPtrQTy,
3549 Args.push_back(&DstArg);
3550 Args.push_back(&SrcArg);
3551 Args.push_back(&LastprivArg);
3552 const auto &TaskDupFnInfo =
3556 auto *TaskDup = llvm::Function::Create(
3557 TaskDupTy, llvm::GlobalValue::InternalLinkage, Name, &CGM.
getModule());
3559 TaskDup->setDoesNotRecurse();
3569 auto LIFI = std::next(KmpTaskTQTyRD->
field_begin(), KmpTaskTLastIter);
3571 TDBase, *KmpTaskTWithPrivatesQTyRD->
field_begin());
3581 if (!
Data.FirstprivateVars.empty()) {
3586 TDBase, *KmpTaskTWithPrivatesQTyRD->
field_begin());
3594 emitPrivatesInit(CGF, D, KmpTaskSharedsPtr, TDBase, KmpTaskTWithPrivatesQTyRD,
3605 for (
const PrivateDataTy &P :
Privates) {
3606 if (P.second.isLocalPrivate())
3608 QualType Ty = P.second.Original->getType().getNonReferenceType();
3617class OMPIteratorGeneratorScope final
3619 CodeGenFunction &CGF;
3620 const OMPIteratorExpr *E =
nullptr;
3621 SmallVector<CodeGenFunction::JumpDest, 4> ContDests;
3622 SmallVector<CodeGenFunction::JumpDest, 4> ExitDests;
3623 OMPIteratorGeneratorScope() =
delete;
3624 OMPIteratorGeneratorScope(OMPIteratorGeneratorScope &) =
delete;
3627 OMPIteratorGeneratorScope(CodeGenFunction &CGF,
const OMPIteratorExpr *E)
3628 : CodeGenFunction::OMPPrivateScope(CGF), CGF(CGF), E(E) {
3631 SmallVector<llvm::Value *, 4> Uppers;
3633 Uppers.push_back(CGF.EmitScalarExpr(E->getHelper(I).Upper));
3634 const auto *VD = cast<VarDecl>(E->getIteratorDecl(I));
3635 addPrivate(VD, CGF.CreateMemTemp(VD->getType(), VD->getName()));
3636 const OMPIteratorHelperData &HelperData = E->getHelper(I);
3638 HelperData.CounterVD,
3639 CGF.CreateMemTemp(HelperData.CounterVD->getType(),
"counter.addr"));
3644 const OMPIteratorHelperData &HelperData = E->getHelper(I);
3646 CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(HelperData.CounterVD),
3647 HelperData.CounterVD->getType());
3649 CGF.EmitStoreOfScalar(
3650 llvm::ConstantInt::get(CLVal.getAddress().getElementType(), 0),
3652 CodeGenFunction::JumpDest &ContDest =
3653 ContDests.emplace_back(CGF.getJumpDestInCurrentScope(
"iter.cont"));
3654 CodeGenFunction::JumpDest &ExitDest =
3655 ExitDests.emplace_back(CGF.getJumpDestInCurrentScope(
"iter.exit"));
3657 llvm::Value *N = Uppers[I];
3660 CGF.EmitBlock(ContDest.getBlock());
3662 CGF.EmitLoadOfScalar(CLVal, HelperData.CounterVD->getLocation());
3664 HelperData.CounterVD->getType()->isSignedIntegerOrEnumerationType()
3665 ? CGF.Builder.CreateICmpSLT(CVal, N)
3666 : CGF.Builder.CreateICmpULT(CVal, N);
3667 llvm::BasicBlock *BodyBB = CGF.createBasicBlock(
"iter.body");
3668 CGF.Builder.CreateCondBr(Cmp, BodyBB, ExitDest.getBlock());
3670 CGF.EmitBlock(BodyBB);
3672 CGF.EmitIgnoredExpr(HelperData.Update);
3675 ~OMPIteratorGeneratorScope() {
3680 const OMPIteratorHelperData &HelperData = E->
getHelper(I - 1);
3685 CGF.
EmitBlock(ExitDests[I - 1].getBlock(), I == 1);
3691static std::pair<llvm::Value *, llvm::Value *>
3693 const auto *OASE = dyn_cast<OMPArrayShapingExpr>(E);
3696 const Expr *
Base = OASE->getBase();
3701 llvm::Value *SizeVal;
3704 SizeVal = CGF.
getTypeSize(OASE->getBase()->getType()->getPointeeType());
3705 for (
const Expr *SE : OASE->getDimensions()) {
3709 SizeVal = CGF.
Builder.CreateNUWMul(SizeVal, Sz);
3711 }
else if (
const auto *ASE =
3714 Address UpAddrAddress = UpAddrLVal.getAddress();
3715 llvm::Value *UpAddr = CGF.
Builder.CreateConstGEP1_32(
3719 llvm::Value *UpIntPtr = CGF.
Builder.CreatePtrToInt(UpAddr, CGF.
SizeTy);
3720 SizeVal = CGF.
Builder.CreateNUWSub(UpIntPtr, LowIntPtr);
3724 return std::make_pair(
Addr, SizeVal);
3729 QualType FlagsTy =
C.getIntTypeForBitwidth(32,
false);
3730 if (KmpTaskAffinityInfoTy.
isNull()) {
3732 C.buildImplicitRecord(
"kmp_task_affinity_info_t");
3738 KmpTaskAffinityInfoTy =
C.getCanonicalTagType(KmpAffinityInfoRD);
3745 llvm::Function *TaskFunction,
QualType SharedsTy,
3750 const auto *I =
Data.PrivateCopies.begin();
3751 for (
const Expr *E :
Data.PrivateVars) {
3759 I =
Data.FirstprivateCopies.begin();
3760 const auto *IElemInitRef =
Data.FirstprivateInits.begin();
3761 for (
const Expr *E :
Data.FirstprivateVars) {
3771 I =
Data.LastprivateCopies.begin();
3772 for (
const Expr *E :
Data.LastprivateVars) {
3782 Privates.emplace_back(
CGM.getPointerAlign(), PrivateHelpersTy(VD));
3784 Privates.emplace_back(
C.getDeclAlign(VD), PrivateHelpersTy(VD));
3787 [](
const PrivateDataTy &L,
const PrivateDataTy &R) {
3788 return L.first > R.first;
3790 QualType KmpInt32Ty =
C.getIntTypeForBitwidth(32, 1);
3801 assert((D.getDirectiveKind() == OMPD_task ||
3804 "Expected taskloop, task or target directive");
3811 const auto *KmpTaskTQTyRD =
KmpTaskTQTy->castAsRecordDecl();
3813 const RecordDecl *KmpTaskTWithPrivatesQTyRD =
3816 C.getCanonicalTagType(KmpTaskTWithPrivatesQTyRD);
3817 QualType KmpTaskTWithPrivatesPtrQTy =
3818 C.getPointerType(KmpTaskTWithPrivatesQTy);
3819 llvm::Type *KmpTaskTWithPrivatesPtrTy = CGF.
Builder.getPtrTy(0);
3820 llvm::Value *KmpTaskTWithPrivatesTySize =
3822 QualType SharedsPtrTy =
C.getPointerType(SharedsTy);
3825 llvm::Value *TaskPrivatesMap =
nullptr;
3826 llvm::Type *TaskPrivatesMapTy =
3827 std::next(TaskFunction->arg_begin(), 3)->getType();
3829 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->
field_begin());
3833 TaskPrivatesMap, TaskPrivatesMapTy);
3835 TaskPrivatesMap = llvm::ConstantPointerNull::get(
3841 CGM, Loc, D.getDirectiveKind(), KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy,
3842 KmpTaskTWithPrivatesQTy,
KmpTaskTQTy, SharedsPtrTy, TaskFunction,
3854 DestructorsFlag = 0x8,
3855 PriorityFlag = 0x20,
3856 DetachableFlag = 0x40,
3857 FreeAgentFlag = 0x80,
3858 TransparentFlag = 0x100,
3860 unsigned Flags =
Data.Tied ? TiedFlag : 0;
3861 bool NeedsCleanup =
false;
3866 Flags = Flags | DestructorsFlag;
3870 if (Kind == OMPC_THREADSET_omp_pool)
3871 Flags = Flags | FreeAgentFlag;
3873 if (D.getSingleClause<OMPTransparentClause>())
3874 Flags |= TransparentFlag;
3876 if (
Data.Priority.getInt())
3877 Flags = Flags | PriorityFlag;
3879 Flags = Flags | DetachableFlag;
3880 llvm::Value *TaskFlags =
3881 Data.Final.getPointer()
3882 ? CGF.
Builder.CreateSelect(
Data.Final.getPointer(),
3883 CGF.
Builder.getInt32(FinalFlag),
3885 : CGF.
Builder.getInt32(
Data.Final.getInt() ? FinalFlag : 0);
3886 TaskFlags = CGF.
Builder.CreateOr(TaskFlags, CGF.
Builder.getInt32(Flags));
3887 llvm::Value *SharedsSize =
CGM.getSize(
C.getTypeSizeInChars(SharedsTy));
3889 getThreadID(CGF, Loc), TaskFlags, KmpTaskTWithPrivatesTySize,
3892 llvm::Value *NewTask;
3893 if (D.hasClausesOfKind<OMPNowaitClause>()) {
3899 llvm::Value *DeviceID;
3904 DeviceID = CGF.
Builder.getInt64(OMP_DEVICEID_UNDEF);
3905 AllocArgs.push_back(DeviceID);
3908 CGM.getModule(), OMPRTL___kmpc_omp_target_task_alloc),
3913 CGM.getModule(), OMPRTL___kmpc_omp_task_alloc),
3926 llvm::Value *Tid =
getThreadID(CGF, DC->getBeginLoc());
3927 Tid = CGF.
Builder.CreateIntCast(Tid, CGF.
IntTy,
false);
3930 CGM.getModule(), OMPRTL___kmpc_task_allow_completion_event),
3931 {Loc, Tid, NewTask});
3942 llvm::Value *NumOfElements =
nullptr;
3943 unsigned NumAffinities = 0;
3945 if (
const Expr *Modifier =
C->getModifier()) {
3947 for (
unsigned I = 0, E = IE->numOfIterators(); I < E; ++I) {
3951 NumOfElements ? CGF.
Builder.CreateNUWMul(NumOfElements, Sz) : Sz;
3954 NumAffinities +=
C->varlist_size();
3959 enum RTLAffinityInfoFieldsTy { BaseAddr, Len, Flags };
3961 QualType KmpTaskAffinityInfoArrayTy;
3962 if (NumOfElements) {
3963 NumOfElements = CGF.
Builder.CreateNUWAdd(
3964 llvm::ConstantInt::get(CGF.
SizeTy, NumAffinities), NumOfElements);
3967 C.getIntTypeForBitwidth(
C.getTypeSize(
C.getSizeType()), 0),
3971 KmpTaskAffinityInfoArrayTy =
C.getVariableArrayType(
3979 NumOfElements = CGF.
Builder.CreateIntCast(NumOfElements, CGF.
Int32Ty,
3982 KmpTaskAffinityInfoArrayTy =
C.getConstantArrayType(
3984 llvm::APInt(
C.getTypeSize(
C.getSizeType()), NumAffinities),
nullptr,
3987 CGF.
CreateMemTemp(KmpTaskAffinityInfoArrayTy,
".affs.arr.addr");
3989 NumOfElements = llvm::ConstantInt::get(
CGM.Int32Ty, NumAffinities,
3996 bool HasIterator =
false;
3998 if (
C->getModifier()) {
4002 for (
const Expr *E :
C->varlist()) {
4011 Base, *std::next(KmpAffinityInfoRD->field_begin(), BaseAddr));
4016 Base, *std::next(KmpAffinityInfoRD->field_begin(), Len));
4030 const Expr *Modifier =
C->getModifier();
4033 OMPIteratorGeneratorScope IteratorScope(
4035 for (
const Expr *E :
C->varlist()) {
4045 Base, *std::next(KmpAffinityInfoRD->field_begin(), BaseAddr));
4050 Base, *std::next(KmpAffinityInfoRD->field_begin(), Len));
4052 Idx = CGF.
Builder.CreateNUWAdd(
4053 Idx, llvm::ConstantInt::get(Idx->getType(), 1));
4068 CGM.getModule(), OMPRTL___kmpc_omp_reg_task_with_affinity),
4069 {LocRef, GTid, NewTask, NumOfElements, AffinListPtr});
4071 llvm::Value *NewTaskNewTaskTTy =
4073 NewTask, KmpTaskTWithPrivatesPtrTy);
4075 KmpTaskTWithPrivatesQTy);
4086 *std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTShareds)),
4088 CGF.
Int8Ty,
CGM.getNaturalTypeAlignment(SharedsTy));
4102 CGM, Loc, D, KmpTaskTWithPrivatesPtrQTy, KmpTaskTWithPrivatesQTyRD,
4103 KmpTaskTQTyRD, SharedsTy, SharedsPtrTy,
Data,
Privates,
4104 !
Data.LastprivateVars.empty());
4108 enum { Priority = 0, Destructors = 1 };
4110 auto FI = std::next(KmpTaskTQTyRD->field_begin(), Data1);
4111 const auto *KmpCmplrdataUD = (*FI)->getType()->castAsRecordDecl();
4112 assert(KmpCmplrdataUD->isUnion());
4115 CGM, Loc, KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy,
4116 KmpTaskTWithPrivatesQTy);
4119 Data1LV, *std::next(KmpCmplrdataUD->field_begin(), Destructors));
4125 if (
Data.Priority.getInt()) {
4127 TDBase, *std::next(KmpTaskTQTyRD->field_begin(), Data2));
4129 Data2LV, *std::next(KmpCmplrdataUD->field_begin(), Priority));
4132 Result.NewTask = NewTask;
4133 Result.TaskEntry = TaskEntry;
4134 Result.NewTaskNewTaskTTy = NewTaskNewTaskTTy;
4136 Result.KmpTaskTQTyRD = KmpTaskTQTyRD;
4142 RTLDependenceKindTy DepKind;
4144 case OMPC_DEPEND_in:
4145 DepKind = RTLDependenceKindTy::DepIn;
4148 case OMPC_DEPEND_out:
4149 case OMPC_DEPEND_inout:
4150 DepKind = RTLDependenceKindTy::DepInOut;
4152 case OMPC_DEPEND_mutexinoutset:
4153 DepKind = RTLDependenceKindTy::DepMutexInOutSet;
4155 case OMPC_DEPEND_inoutset:
4156 DepKind = RTLDependenceKindTy::DepInOutSet;
4158 case OMPC_DEPEND_outallmemory:
4159 DepKind = RTLDependenceKindTy::DepOmpAllMem;
4161 case OMPC_DEPEND_source:
4162 case OMPC_DEPEND_sink:
4163 case OMPC_DEPEND_depobj:
4164 case OMPC_DEPEND_inoutallmemory:
4166 llvm_unreachable(
"Unknown task dependence type");
4174 FlagsTy =
C.getIntTypeForBitwidth(
C.getTypeSize(
C.BoolTy),
false);
4175 if (KmpDependInfoTy.
isNull()) {
4176 RecordDecl *KmpDependInfoRD =
C.buildImplicitRecord(
"kmp_depend_info");
4182 KmpDependInfoTy =
C.getCanonicalTagType(KmpDependInfoRD);
4186std::pair<llvm::Value *, LValue>
4199 CGF,
Base.getAddress(),
4200 llvm::ConstantInt::get(CGF.
IntPtrTy, -1,
true));
4206 *std::next(KmpDependInfoRD->field_begin(),
4207 static_cast<unsigned int>(RTLDependInfoFields::BaseAddr)));
4209 return std::make_pair(NumDeps,
Base);
4213 llvm::PointerUnion<unsigned *, LValue *> Pos,
4223 OMPIteratorGeneratorScope IteratorScope(
4224 CGF, cast_or_null<OMPIteratorExpr>(
4225 Data.IteratorExpr ?
Data.IteratorExpr->IgnoreParenImpCasts()
4227 for (
const Expr *E :
Data.DepExprs) {
4237 Size = llvm::ConstantInt::get(CGF.
SizeTy, 0);
4240 if (
unsigned *P = dyn_cast<unsigned *>(Pos)) {
4244 assert(E &&
"Expected a non-null expression");
4253 *std::next(KmpDependInfoRD->field_begin(),
4254 static_cast<unsigned int>(RTLDependInfoFields::BaseAddr)));
4258 Base, *std::next(KmpDependInfoRD->field_begin(),
4259 static_cast<unsigned int>(RTLDependInfoFields::Len)));
4265 *std::next(KmpDependInfoRD->field_begin(),
4266 static_cast<unsigned int>(RTLDependInfoFields::Flags)));
4268 llvm::ConstantInt::get(LLVMFlagsTy,
static_cast<unsigned int>(DepKind)),
4270 if (
unsigned *P = dyn_cast<unsigned *>(Pos)) {
4275 Idx = CGF.
Builder.CreateNUWAdd(Idx,
4276 llvm::ConstantInt::get(Idx->getType(), 1));
4285 assert(
Data.DepKind == OMPC_DEPEND_depobj &&
4286 "Expected depobj dependency kind.");
4291 OMPIteratorGeneratorScope IteratorScope(
4292 CGF, cast_or_null<OMPIteratorExpr>(
4293 Data.IteratorExpr ?
Data.IteratorExpr->IgnoreParenImpCasts()
4295 for (
const Expr *E :
Data.DepExprs) {
4296 llvm::Value *NumDeps;
4299 std::tie(NumDeps,
Base) =
4303 C.getUIntPtrType());
4307 llvm::Value *Add = CGF.
Builder.CreateNUWAdd(PrevVal, NumDeps);
4309 SizeLVals.push_back(NumLVal);
4312 for (
unsigned I = 0, E = SizeLVals.size(); I < E; ++I) {
4315 Sizes.push_back(Size);
4325 assert(
Data.DepKind == OMPC_DEPEND_depobj &&
4326 "Expected depobj dependency kind.");
4329 OMPIteratorGeneratorScope IteratorScope(
4330 CGF, cast_or_null<OMPIteratorExpr>(
4331 Data.IteratorExpr ?
Data.IteratorExpr->IgnoreParenImpCasts()
4333 for (
const Expr *E :
Data.DepExprs) {
4334 llvm::Value *NumDeps;
4337 std::tie(NumDeps,
Base) =
4341 llvm::Value *Size = CGF.
Builder.CreateNUWMul(
4350 llvm::Value *Add = CGF.
Builder.CreateNUWAdd(Pos, NumDeps);
4366 llvm::Value *NumOfElements =
nullptr;
4367 unsigned NumDependencies = std::accumulate(
4368 Dependencies.begin(), Dependencies.end(), 0,
4370 return D.DepKind == OMPC_DEPEND_depobj
4372 : (V + (D.IteratorExpr ? 0 : D.DepExprs.size()));
4376 bool HasDepobjDeps =
false;
4377 bool HasRegularWithIterators =
false;
4378 llvm::Value *NumOfDepobjElements = llvm::ConstantInt::get(CGF.
IntPtrTy, 0);
4379 llvm::Value *NumOfRegularWithIterators =
4380 llvm::ConstantInt::get(CGF.
IntPtrTy, 0);
4384 if (D.
DepKind == OMPC_DEPEND_depobj) {
4387 for (llvm::Value *Size : Sizes) {
4388 NumOfDepobjElements =
4389 CGF.
Builder.CreateNUWAdd(NumOfDepobjElements, Size);
4391 HasDepobjDeps =
true;
4396 if (
const auto *IE = cast_or_null<OMPIteratorExpr>(D.
IteratorExpr)) {
4397 llvm::Value *ClauseIteratorSpace =
4398 llvm::ConstantInt::get(CGF.
IntPtrTy, 1);
4402 ClauseIteratorSpace = CGF.
Builder.CreateNUWMul(Sz, ClauseIteratorSpace);
4404 llvm::Value *NumClauseDeps = CGF.
Builder.CreateNUWMul(
4405 ClauseIteratorSpace,
4407 NumOfRegularWithIterators =
4408 CGF.
Builder.CreateNUWAdd(NumOfRegularWithIterators, NumClauseDeps);
4409 HasRegularWithIterators =
true;
4415 if (HasDepobjDeps || HasRegularWithIterators) {
4416 NumOfElements = llvm::ConstantInt::get(
CGM.IntPtrTy, NumDependencies,
4418 if (HasDepobjDeps) {
4420 CGF.
Builder.CreateNUWAdd(NumOfDepobjElements, NumOfElements);
4422 if (HasRegularWithIterators) {
4424 CGF.
Builder.CreateNUWAdd(NumOfRegularWithIterators, NumOfElements);
4427 Loc,
C.getIntTypeForBitwidth(64, 0),
4431 KmpDependInfoArrayTy =
4440 NumOfElements = CGF.
Builder.CreateIntCast(NumOfElements, CGF.
Int32Ty,
4443 KmpDependInfoArrayTy =
C.getConstantArrayType(
4449 NumOfElements = llvm::ConstantInt::get(
CGM.Int32Ty, NumDependencies,
4454 if (Dep.DepKind == OMPC_DEPEND_depobj || Dep.IteratorExpr)
4460 CGF.
CreateMemTemp(
C.getSizeType(),
"dep.counter.addr"),
C.getSizeType());
4463 if (Dep.DepKind == OMPC_DEPEND_depobj || !Dep.IteratorExpr)
4468 if (HasDepobjDeps) {
4470 if (Dep.DepKind != OMPC_DEPEND_depobj)
4477 return std::make_pair(NumOfElements, DependenciesArray);
4488 unsigned NumDependencies = Dependencies.
DepExprs.size();
4498 llvm::Value *NumDepsVal;
4500 if (
const auto *IE =
4501 cast_or_null<OMPIteratorExpr>(Dependencies.
IteratorExpr)) {
4502 NumDepsVal = llvm::ConstantInt::get(CGF.
SizeTy, 1);
4506 NumDepsVal = CGF.
Builder.CreateNUWMul(NumDepsVal, Sz);
4508 Size = CGF.
Builder.CreateNUWAdd(llvm::ConstantInt::get(CGF.
SizeTy, 1),
4512 llvm::Value *RecSize =
CGM.getSize(SizeInBytes);
4513 Size = CGF.
Builder.CreateNUWMul(Size, RecSize);
4517 QualType KmpDependInfoArrayTy =
C.getConstantArrayType(
4520 CharUnits Sz =
C.getTypeSizeInChars(KmpDependInfoArrayTy);
4522 NumDepsVal = llvm::ConstantInt::get(CGF.
IntPtrTy, NumDependencies);
4527 llvm::Value *Allocator = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
4528 llvm::Value *Args[] = {ThreadID, Size, Allocator};
4532 CGM.getModule(), OMPRTL___kmpc_alloc),
4533 Args,
".dep.arr.addr");
4537 DependenciesArray =
Address(
Addr, KmpDependInfoLlvmTy, Align);
4543 *std::next(KmpDependInfoRD->field_begin(),
4544 static_cast<unsigned int>(RTLDependInfoFields::BaseAddr)));
4546 llvm::PointerUnion<unsigned *, LValue *> Pos;
4563 return DependenciesArray;
4578 Addr.getElementType(),
Addr.emitRawPointer(CGF),
4579 llvm::ConstantInt::get(CGF.
IntPtrTy, -1,
true));
4584 llvm::Value *Allocator = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
4585 llvm::Value *Args[] = {ThreadID, DepObjAddr, Allocator};
4589 CGM.getModule(), OMPRTL___kmpc_free),
4601 llvm::Value *NumDeps;
4612 llvm::BasicBlock *EntryBB = CGF.
Builder.GetInsertBlock();
4614 llvm::PHINode *ElementPHI =
4619 Base.getTBAAInfo());
4623 Base, *std::next(KmpDependInfoRD->field_begin(),
4624 static_cast<unsigned int>(RTLDependInfoFields::Flags)));
4626 llvm::ConstantInt::get(LLVMFlagsTy,
static_cast<unsigned int>(DepKind)),
4630 llvm::Value *ElementNext =
4633 ElementPHI->addIncoming(ElementNext, CGF.
Builder.GetInsertBlock());
4634 llvm::Value *IsEmpty =
4635 CGF.
Builder.CreateICmpEQ(ElementNext, End,
"omp.isempty");
4636 CGF.
Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
4643 llvm::Function *TaskFunction,
4652 llvm::Value *NewTask =
Result.NewTask;
4653 llvm::Function *TaskEntry =
Result.TaskEntry;
4654 llvm::Value *NewTaskNewTaskTTy =
Result.NewTaskNewTaskTTy;
4659 llvm::Value *NumOfElements;
4660 std::tie(NumOfElements, DependenciesArray) =
4671 llvm::Value *TaskArgs[] = { UpLoc, ThreadID, NewTask };
4672 llvm::Value *DepTaskArgs[7];
4673 if (!
Data.Dependences.empty()) {
4674 DepTaskArgs[0] = UpLoc;
4675 DepTaskArgs[1] = ThreadID;
4676 DepTaskArgs[2] = NewTask;
4677 DepTaskArgs[3] = NumOfElements;
4679 DepTaskArgs[5] = CGF.
Builder.getInt32(0);
4680 DepTaskArgs[6] = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
4682 auto &&ThenCodeGen = [
this, &
Data, TDBase, KmpTaskTQTyRD, &TaskArgs,
4685 auto PartIdFI = std::next(KmpTaskTQTyRD->
field_begin(), KmpTaskTPartId);
4689 if (!
Data.Dependences.empty()) {
4692 CGM.getModule(), OMPRTL___kmpc_omp_task_with_deps),
4696 CGM.getModule(), OMPRTL___kmpc_omp_task),
4702 Region->emitUntiedSwitch(CGF);
4705 llvm::Value *DepWaitTaskArgs[7];
4706 if (!
Data.Dependences.empty()) {
4707 DepWaitTaskArgs[0] = UpLoc;
4708 DepWaitTaskArgs[1] = ThreadID;
4709 DepWaitTaskArgs[2] = NumOfElements;
4711 DepWaitTaskArgs[4] = CGF.
Builder.getInt32(0);
4712 DepWaitTaskArgs[5] = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
4713 DepWaitTaskArgs[6] =
4714 llvm::ConstantInt::get(CGF.
Int32Ty,
Data.HasNowaitClause);
4716 auto &M =
CGM.getModule();
4717 auto &&ElseCodeGen = [
this, &M, &TaskArgs, ThreadID, NewTaskNewTaskTTy,
4718 TaskEntry, &
Data, &DepWaitTaskArgs,
4725 if (!
Data.Dependences.empty())
4727 M, OMPRTL___kmpc_omp_taskwait_deps_51),
4730 auto &&
CodeGen = [TaskEntry, ThreadID, NewTaskNewTaskTTy,
4733 llvm::Value *OutlinedFnArgs[] = {ThreadID, NewTaskNewTaskTTy};
4734 CGF.CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, Loc, TaskEntry,
4743 CommonActionTy Action(
OMPBuilder.getOrCreateRuntimeFunction(
4744 M, OMPRTL___kmpc_omp_task_begin_if0),
4747 M, OMPRTL___kmpc_omp_task_complete_if0),
4763 llvm::Function *TaskFunction,
4783 IfVal = llvm::ConstantInt::getSigned(CGF.
IntTy, 1);
4788 *std::next(
Result.KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound));
4795 *std::next(
Result.KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound));
4802 *std::next(
Result.KmpTaskTQTyRD->field_begin(), KmpTaskTStride));
4810 *std::next(
Result.KmpTaskTQTyRD->field_begin(), KmpTaskTReductions));
4811 if (
Data.Reductions) {
4817 enum { NoSchedule = 0, Grainsize = 1, NumTasks = 2 };
4826 llvm::ConstantInt::getSigned(
4828 llvm::ConstantInt::getSigned(
4830 ?
Data.Schedule.getInt() ? NumTasks : Grainsize
4832 Data.Schedule.getPointer()
4835 : llvm::ConstantInt::get(CGF.
Int64Ty, 0)};
4836 if (
Data.HasModifier)
4837 TaskArgs.push_back(llvm::ConstantInt::get(CGF.
Int32Ty, 1));
4839 TaskArgs.push_back(
Result.TaskDupFn
4842 : llvm::ConstantPointerNull::get(CGF.
VoidPtrTy));
4844 CGM.getModule(),
Data.HasModifier
4845 ? OMPRTL___kmpc_taskloop_5
4846 : OMPRTL___kmpc_taskloop),
4863 const Expr *,
const Expr *)> &RedOpGen,
4864 const Expr *XExpr =
nullptr,
const Expr *EExpr =
nullptr,
4865 const Expr *UpExpr =
nullptr) {
4873 llvm::Value *NumElements = CGF.
emitArrayLength(ArrayTy, ElementTy, LHSAddr);
4878 llvm::Value *LHSEnd =
4883 llvm::Value *IsEmpty =
4884 CGF.
Builder.CreateICmpEQ(LHSBegin, LHSEnd,
"omp.arraycpy.isempty");
4885 CGF.
Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
4888 llvm::BasicBlock *EntryBB = CGF.
Builder.GetInsertBlock();
4893 llvm::PHINode *RHSElementPHI = CGF.
Builder.CreatePHI(
4894 RHSBegin->getType(), 2,
"omp.arraycpy.srcElementPast");
4895 RHSElementPHI->addIncoming(RHSBegin, EntryBB);
4900 llvm::PHINode *LHSElementPHI = CGF.
Builder.CreatePHI(
4901 LHSBegin->getType(), 2,
"omp.arraycpy.destElementPast");
4902 LHSElementPHI->addIncoming(LHSBegin, EntryBB);
4909 Scope.addPrivate(LHSVar, LHSElementCurrent);
4910 Scope.addPrivate(RHSVar, RHSElementCurrent);
4912 RedOpGen(CGF, XExpr, EExpr, UpExpr);
4913 Scope.ForceCleanup();
4916 llvm::Value *LHSElementNext = CGF.
Builder.CreateConstGEP1_32(
4918 "omp.arraycpy.dest.element");
4919 llvm::Value *RHSElementNext = CGF.
Builder.CreateConstGEP1_32(
4921 "omp.arraycpy.src.element");
4924 CGF.
Builder.CreateICmpEQ(LHSElementNext, LHSEnd,
"omp.arraycpy.done");
4925 CGF.
Builder.CreateCondBr(Done, DoneBB, BodyBB);
4926 LHSElementPHI->addIncoming(LHSElementNext, CGF.
Builder.GetInsertBlock());
4927 RHSElementPHI->addIncoming(RHSElementNext, CGF.
Builder.GetInsertBlock());
4937 const Expr *ReductionOp) {
4938 if (
const auto *CE = dyn_cast<CallExpr>(ReductionOp))
4939 if (
const auto *OVE = dyn_cast<OpaqueValueExpr>(CE->getCallee()))
4940 if (
const auto *DRE =
4941 dyn_cast<DeclRefExpr>(OVE->getSourceExpr()->IgnoreImpCasts()))
4942 if (
const auto *DRD =
4943 dyn_cast<OMPDeclareReductionDecl>(DRE->getDecl())) {
4944 std::pair<llvm::Function *, llvm::Function *>
Reduction =
4955 StringRef ReducerName,
SourceLocation Loc, llvm::Type *ArgsElemType,
4966 Args.push_back(&LHSArg);
4967 Args.push_back(&RHSArg);
4969 CGM.getTypes().arrangeBuiltinFunctionDeclaration(
C.VoidTy, Args);
4971 auto *Fn = llvm::Function::Create(
CGM.getTypes().GetFunctionType(CGFI),
4972 llvm::GlobalValue::InternalLinkage, Name,
4975 Fn->setDoesNotRecurse();
4994 const auto *IPriv =
Privates.begin();
4996 for (
unsigned I = 0, E = ReductionOps.size(); I < E; ++I, ++IPriv, ++Idx) {
4997 const auto *RHSVar =
5000 const auto *LHSVar =
5003 QualType PrivTy = (*IPriv)->getType();
5019 const auto *ILHS = LHSExprs.begin();
5020 const auto *IRHS = RHSExprs.begin();
5021 for (
const Expr *E : ReductionOps) {
5022 if ((*IPriv)->getType()->isArrayType()) {
5027 CGF, (*IPriv)->getType(), LHSVar, RHSVar,
5029 emitReductionCombiner(CGF, E);
5039 Scope.ForceCleanup();
5045 const Expr *ReductionOp,
5046 const Expr *PrivateRef,
5054 CGF, PrivateRef->
getType(), LHSVar, RHSVar,
5056 emitReductionCombiner(CGF, ReductionOp);
5065 llvm::StringRef Prefix,
const Expr *Ref);
5069 const Expr *LHSExprs,
const Expr *RHSExprs,
const Expr *ReductionOps) {
5096 std::string ReductionVarNameStr;
5097 if (
const auto *DRE = dyn_cast<DeclRefExpr>(
Privates->IgnoreParenCasts()))
5098 ReductionVarNameStr =
5101 ReductionVarNameStr =
"unnamed_priv_var";
5104 std::string SharedName =
5105 CGM.getOpenMPRuntime().getName({
"internal_pivate_", ReductionVarNameStr});
5106 llvm::GlobalVariable *SharedVar =
OMPBuilder.getOrCreateInternalVariable(
5107 LLVMType,
".omp.reduction." + SharedName);
5109 SharedVar->setAlignment(
5117 llvm::Value *BarrierArgs[] = {BarrierLoc, ThreadId};
5122 llvm::Value *IsWorker = CGF.
Builder.CreateICmpEQ(
5123 ThreadId, llvm::ConstantInt::get(ThreadId->getType(), 0));
5124 CGF.
Builder.CreateCondBr(IsWorker, InitBB, InitEndBB);
5128 auto EmitSharedInit = [&]() {
5131 std::pair<llvm::Function *, llvm::Function *> FnPair =
5133 llvm::Function *InitializerFn = FnPair.second;
5134 if (InitializerFn) {
5135 if (
const auto *CE =
5136 dyn_cast<CallExpr>(UDRInitExpr->IgnoreParenImpCasts())) {
5143 LocalScope.addPrivate(OutVD, SharedResult);
5145 (void)LocalScope.Privatize();
5146 if (
const auto *OVE = dyn_cast<OpaqueValueExpr>(
5147 CE->getCallee()->IgnoreParenImpCasts())) {
5173 if (
const auto *DRE = dyn_cast<DeclRefExpr>(
Privates)) {
5174 if (
const auto *VD = dyn_cast<VarDecl>(DRE->getDecl())) {
5185 CGF.
Builder.CreateBr(InitEndBB);
5189 CGM.getModule(), OMPRTL___kmpc_barrier),
5192 const Expr *ReductionOp = ReductionOps;
5197 auto EmitCriticalReduction = [&](
auto ReductionGen) {
5198 std::string CriticalName =
getName({
"reduction_critical"});
5206 std::pair<llvm::Function *, llvm::Function *> FnPair =
5209 if (
const auto *CE = dyn_cast<CallExpr>(ReductionOp)) {
5221 (void)LocalScope.Privatize();
5226 EmitCriticalReduction(ReductionGen);
5231 if (
const auto *Cleanup = dyn_cast<ExprWithCleanups>(ReductionClauseExpr))
5234 const Expr *AssignRHS =
nullptr;
5235 if (
const auto *BinOp = dyn_cast<BinaryOperator>(ReductionClauseExpr)) {
5236 if (BinOp->getOpcode() == BO_Assign)
5237 AssignRHS = BinOp->getRHS();
5238 }
else if (
const auto *OpCall =
5239 dyn_cast<CXXOperatorCallExpr>(ReductionClauseExpr)) {
5240 if (OpCall->getOperator() == OO_Equal)
5241 AssignRHS = OpCall->getArg(1);
5245 "Private Variable Reduction : Invalid ReductionOp expression");
5250 const auto *OmpOutDRE =
5252 const auto *OmpInDRE =
5255 OmpOutDRE && OmpInDRE &&
5256 "Private Variable Reduction : LHSExpr/RHSExpr must be DeclRefExprs");
5260 LocalScope.addPrivate(OmpOutVD, SharedLV.
getAddress());
5261 LocalScope.addPrivate(OmpInVD, LHSLV.
getAddress());
5262 (void)LocalScope.Privatize();
5266 EmitCriticalReduction(ReductionGen);
5270 CGM.getModule(), OMPRTL___kmpc_barrier),
5276 llvm::Value *FinalResultVal =
nullptr;
5280 FinalResultAddr = SharedResult;
5294 CGM.getModule(), OMPRTL___kmpc_barrier),
5305 EmitCriticalReduction(OriginalListCombiner);
5357 if (SimpleReduction) {
5359 const auto *IPriv = OrgPrivates.begin();
5360 const auto *ILHS = OrgLHSExprs.begin();
5361 const auto *IRHS = OrgRHSExprs.begin();
5362 for (
const Expr *E : OrgReductionOps) {
5375 FilteredRHSExprs, FilteredReductionOps;
5376 for (
unsigned I : llvm::seq<unsigned>(
5377 std::min(OrgReductionOps.size(), OrgLHSExprs.size()))) {
5379 FilteredPrivates.emplace_back(OrgPrivates[I]);
5380 FilteredLHSExprs.emplace_back(OrgLHSExprs[I]);
5381 FilteredRHSExprs.emplace_back(OrgRHSExprs[I]);
5382 FilteredReductionOps.emplace_back(OrgReductionOps[I]);
5394 auto Size = RHSExprs.size();
5400 llvm::APInt ArraySize(32, Size);
5401 QualType ReductionArrayTy =
C.getConstantArrayType(
5405 CGF.
CreateMemTemp(ReductionArrayTy,
".omp.reduction.red_list");
5406 const auto *IPriv =
Privates.begin();
5408 for (
unsigned I = 0, E = RHSExprs.size(); I < E; ++I, ++IPriv, ++Idx) {
5414 if ((*IPriv)->getType()->isVariablyModifiedType()) {
5418 llvm::Value *Size = CGF.
Builder.CreateIntCast(
5431 Privates, LHSExprs, RHSExprs, ReductionOps);
5434 std::string Name =
getName({
"reduction"});
5441 llvm::Value *ReductionArrayTySize = CGF.
getTypeSize(ReductionArrayTy);
5444 llvm::Value *Args[] = {
5447 CGF.
Builder.getInt32(RHSExprs.size()),
5448 ReductionArrayTySize,
5456 WithNowait ? OMPRTL___kmpc_reduce_nowait : OMPRTL___kmpc_reduce),
5460 llvm::BasicBlock *DefaultBB = CGF.
createBasicBlock(
".omp.reduction.default");
5461 llvm::SwitchInst *SwInst =
5462 CGF.
Builder.CreateSwitch(Res, DefaultBB, 2);
5471 SwInst->addCase(CGF.
Builder.getInt32(1), Case1BB);
5475 llvm::Value *EndArgs[] = {
5483 const auto *IPriv =
Privates.begin();
5484 const auto *ILHS = LHSExprs.begin();
5485 const auto *IRHS = RHSExprs.begin();
5486 for (
const Expr *E : ReductionOps) {
5495 CommonActionTy Action(
5498 CGM.getModule(), WithNowait ? OMPRTL___kmpc_end_reduce_nowait
5499 : OMPRTL___kmpc_end_reduce),
5512 SwInst->addCase(CGF.
Builder.getInt32(2), Case2BB);
5515 auto &&AtomicCodeGen = [Loc,
Privates, LHSExprs, RHSExprs, ReductionOps](
5517 const auto *ILHS = LHSExprs.begin();
5518 const auto *IRHS = RHSExprs.begin();
5519 const auto *IPriv =
Privates.begin();
5520 for (
const Expr *E : ReductionOps) {
5521 const Expr *XExpr =
nullptr;
5522 const Expr *EExpr =
nullptr;
5523 const Expr *UpExpr =
nullptr;
5525 if (
const auto *BO = dyn_cast<BinaryOperator>(E)) {
5526 if (BO->getOpcode() == BO_Assign) {
5527 XExpr = BO->getLHS();
5528 UpExpr = BO->getRHS();
5532 const Expr *RHSExpr = UpExpr;
5535 if (
const auto *ACO = dyn_cast<AbstractConditionalOperator>(
5539 RHSExpr = ACO->getCond();
5541 if (
const auto *BORHS =
5543 EExpr = BORHS->getRHS();
5544 BO = BORHS->getOpcode();
5549 auto &&AtomicRedGen = [BO, VD,
5551 const Expr *EExpr,
const Expr *UpExpr) {
5552 LValue X = CGF.EmitLValue(XExpr);
5555 E = CGF.EmitAnyExpr(EExpr);
5556 CGF.EmitOMPAtomicSimpleUpdateExpr(
5558 llvm::AtomicOrdering::Monotonic, Loc,
5559 [&CGF, UpExpr, VD, Loc](
RValue XRValue) {
5561 Address LHSTemp = CGF.CreateMemTemp(VD->getType());
5562 CGF.emitOMPSimpleStore(
5563 CGF.MakeAddrLValue(LHSTemp, VD->
getType()), XRValue,
5564 VD->getType().getNonReferenceType(), Loc);
5567 return CGF.EmitAnyExpr(UpExpr);
5570 if ((*IPriv)->getType()->isArrayType()) {
5572 const auto *RHSVar =
5575 AtomicRedGen, XExpr, EExpr, UpExpr);
5578 AtomicRedGen(CGF, XExpr, EExpr, UpExpr);
5585 std::string Name = RT.
getName({
"atomic_reduction"});
5594 if ((*IPriv)->getType()->isArrayType()) {
5595 const auto *LHSVar =
5597 const auto *RHSVar =
5602 CritRedGen(CGF,
nullptr,
nullptr,
nullptr);
5613 llvm::Value *EndArgs[] = {
5618 CommonActionTy Action(
nullptr, {},
5620 CGM.getModule(), OMPRTL___kmpc_end_reduce),
5630 assert(OrgLHSExprs.size() == OrgPrivates.size() &&
5631 "PrivateVarReduction: Privates size mismatch");
5632 assert(OrgLHSExprs.size() == OrgReductionOps.size() &&
5633 "PrivateVarReduction: ReductionOps size mismatch");
5634 for (
unsigned I : llvm::seq<unsigned>(
5635 std::min(OrgReductionOps.size(), OrgLHSExprs.size()))) {
5638 OrgRHSExprs[I], OrgReductionOps[I]);
5647 llvm::raw_svector_ostream Out(Buffer);
5655 Out << Prefix << Name <<
"_"
5657 return std::string(Out.str());
5679 Args.emplace_back(&Param);
5680 Args.emplace_back(&ParamOrig);
5681 const auto &FnInfo =
5685 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
5688 Fn->setDoesNotRecurse();
5695 llvm::Value *Size =
nullptr;
5738 const Expr *ReductionOp,
5740 const Expr *PrivateRef) {
5749 Args.emplace_back(&ParamInOut);
5750 Args.emplace_back(&ParamIn);
5751 const auto &FnInfo =
5755 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
5758 Fn->setDoesNotRecurse();
5761 llvm::Value *Size =
nullptr;
5782 C.getPointerType(LHSVD->getType())->castAs<
PointerType>()));
5789 C.getPointerType(RHSVD->getType())->castAs<
PointerType>()));
5818 Args.emplace_back(&Param);
5819 const auto &FnInfo =
5823 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
5826 Fn->setDoesNotRecurse();
5831 llvm::Value *Size =
nullptr;
5866 RecordDecl *RD =
C.buildImplicitRecord(
"kmp_taskred_input_t");
5875 C, RD,
C.getIntTypeForBitwidth(32,
false));
5878 unsigned Size =
Data.ReductionVars.size();
5879 llvm::APInt ArraySize(64, Size);
5881 C.getConstantArrayType(RDType, ArraySize,
nullptr,
5886 Data.ReductionCopies,
Data.ReductionOps);
5887 for (
unsigned Cnt = 0; Cnt < Size; ++Cnt) {
5889 llvm::Value *Idxs[] = {llvm::ConstantInt::get(
CGM.SizeTy, 0),
5890 llvm::ConstantInt::get(
CGM.SizeTy, Cnt)};
5906 llvm::Value *SizeValInChars;
5907 llvm::Value *SizeVal;
5908 std::tie(SizeValInChars, SizeVal) = RCG.
getSizes(Cnt);
5914 bool DelayedCreation = !!SizeVal;
5915 SizeValInChars = CGF.
Builder.CreateIntCast(SizeValInChars,
CGM.SizeTy,
5926 llvm::Value *FiniAddr =
5927 Fini ? Fini : llvm::ConstantPointerNull::get(
CGM.VoidPtrTy);
5932 CGM, Loc, RCG, Cnt,
Data.ReductionOps[Cnt], LHSExprs[Cnt],
5933 RHSExprs[Cnt],
Data.ReductionCopies[Cnt]);
5937 if (DelayedCreation) {
5939 llvm::ConstantInt::get(
CGM.Int32Ty, 1,
true),
5944 if (
Data.IsReductionWithTaskMod) {
5950 llvm::Value *Args[] = {
5952 llvm::ConstantInt::get(
CGM.IntTy,
Data.IsWorksharingReduction ? 1 : 0,
5954 llvm::ConstantInt::get(
CGM.IntTy, Size,
true),
5959 CGM.getModule(), OMPRTL___kmpc_taskred_modifier_init),
5963 llvm::Value *Args[] = {
5966 llvm::ConstantInt::get(
CGM.IntTy, Size,
true),
5970 CGM.getModule(), OMPRTL___kmpc_taskred_init),
5976 bool IsWorksharingReduction) {
5982 llvm::Value *Args[] = {IdentTLoc, GTid,
5983 llvm::ConstantInt::get(
CGM.IntTy,
5984 IsWorksharingReduction ? 1 : 0,
5988 CGM.getModule(), OMPRTL___kmpc_task_reduction_modifier_fini),
6000 llvm::Value *SizeVal = CGF.
Builder.CreateIntCast(Sizes.second,
CGM.SizeTy,
6003 CGF,
CGM.getContext().getSizeType(),
6011 llvm::Value *ReductionsPtr,
6024 CGM.getModule(), OMPRTL___kmpc_task_reduction_get_th_data),
6040 auto &M =
CGM.getModule();
6042 llvm::Value *NumOfElements;
6043 std::tie(NumOfElements, DependenciesArray) =
6045 if (!
Data.Dependences.empty()) {
6046 llvm::Value *DepWaitTaskArgs[7];
6047 DepWaitTaskArgs[0] = UpLoc;
6048 DepWaitTaskArgs[1] = ThreadID;
6049 DepWaitTaskArgs[2] = NumOfElements;
6051 DepWaitTaskArgs[4] = CGF.
Builder.getInt32(0);
6052 DepWaitTaskArgs[5] = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
6053 DepWaitTaskArgs[6] =
6054 llvm::ConstantInt::get(CGF.
Int32Ty,
Data.HasNowaitClause);
6063 M, OMPRTL___kmpc_omp_taskwait_deps_51),
6070 llvm::Value *Args[] = {UpLoc, ThreadID};
6073 OMPBuilder.getOrCreateRuntimeFunction(M, OMPRTL___kmpc_omp_taskwait),
6078 if (
auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.
CapturedStmtInfo))
6079 Region->emitUntiedSwitch(CGF);
6088 InlinedOpenMPRegionRAII Region(CGF,
CodeGen, InnerKind, HasCancel,
6089 InnerKind != OMPD_critical &&
6090 InnerKind != OMPD_master &&
6091 InnerKind != OMPD_masked);
6106 RTCancelKind CancelKind = CancelNoreq;
6107 if (CancelRegion == OMPD_parallel)
6108 CancelKind = CancelParallel;
6109 else if (CancelRegion == OMPD_for)
6110 CancelKind = CancelLoop;
6111 else if (CancelRegion == OMPD_sections)
6112 CancelKind = CancelSections;
6114 assert(CancelRegion == OMPD_taskgroup);
6115 CancelKind = CancelTaskgroup;
6127 if (
auto *OMPRegionInfo =
6131 if (CancelRegion == OMPD_taskgroup || OMPRegionInfo->hasCancel()) {
6132 llvm::Value *Args[] = {
6138 CGM.getModule(), OMPRTL___kmpc_cancellationpoint),
6147 CGF.
Builder.CreateCondBr(Cmp, ExitBB, ContBB);
6149 if (CancelRegion == OMPD_parallel)
6167 auto &M =
CGM.getModule();
6168 if (
auto *OMPRegionInfo =
6170 auto &&ThenGen = [
this, &M, Loc, CancelRegion,
6173 llvm::Value *Args[] = {
6177 llvm::Value *
Result = CGF.EmitRuntimeCall(
6178 OMPBuilder.getOrCreateRuntimeFunction(M, OMPRTL___kmpc_cancel), Args);
6183 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(
".cancel.exit");
6184 llvm::BasicBlock *ContBB = CGF.createBasicBlock(
".cancel.continue");
6185 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(
Result);
6186 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB);
6187 CGF.EmitBlock(ExitBB);
6188 if (CancelRegion == OMPD_parallel)
6192 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind());
6193 CGF.EmitBranchThroughCleanup(CancelDest);
6194 CGF.EmitBlock(ContBB,
true);
6212 OMPUsesAllocatorsActionTy(
6213 ArrayRef<std::pair<const Expr *, const Expr *>> Allocators)
6214 : Allocators(Allocators) {}
6218 for (
const auto &AllocatorData : Allocators) {
6220 CGF, AllocatorData.first, AllocatorData.second);
6223 void Exit(CodeGenFunction &CGF)
override {
6226 for (
const auto &AllocatorData : Allocators) {
6228 AllocatorData.first);
6236 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
6238 assert(!ParentName.empty() &&
"Invalid target entry parent name!");
6242 for (
unsigned I = 0, E =
C->getNumberOfAllocators(); I < E; ++I) {
6249 OMPUsesAllocatorsActionTy UsesAllocatorAction(Allocators);
6250 CodeGen.setAction(UsesAllocatorAction);
6256 const Expr *Allocator,
6257 const Expr *AllocatorTraits) {
6259 ThreadId = CGF.
Builder.CreateIntCast(ThreadId, CGF.
IntTy,
true);
6261 llvm::Value *MemSpaceHandle = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
6262 llvm::Value *NumTraits = llvm::ConstantInt::get(
6266 .getLimitedValue());
6273 llvm::Value *Traits =
Addr.emitRawPointer(CGF);
6275 llvm::Value *AllocatorVal =
6277 CGM.getModule(), OMPRTL___kmpc_init_allocator),
6278 {ThreadId, MemSpaceHandle, NumTraits, Traits});
6290 const Expr *Allocator) {
6292 ThreadId = CGF.
Builder.CreateIntCast(ThreadId, CGF.
IntTy,
true);
6294 llvm::Value *AllocatorVal =
6301 OMPRTL___kmpc_destroy_allocator),
6302 {ThreadId, AllocatorVal});
6307 llvm::OpenMPIRBuilder::TargetKernelDefaultAttrs &Attrs) {
6308 assert(Attrs.MaxTeams.size() == 1 && Attrs.MaxThreads.size() == 1 &&
6309 "invalid default attrs structure");
6310 int32_t &MaxTeamsVal = Attrs.MaxTeams.front();
6311 int32_t &MaxThreadsVal = Attrs.MaxThreads.front();
6318 for (
auto *A :
C->getAttrs()) {
6319 int32_t AttrMinThreadsVal = 1, AttrMaxThreadsVal = -1;
6320 int32_t AttrMinBlocksVal = 1, AttrMaxBlocksVal = -1;
6321 if (
auto *
Attr = dyn_cast<CUDALaunchBoundsAttr>(A))
6322 CGM.handleCUDALaunchBoundsAttr(
nullptr,
Attr, &AttrMaxThreadsVal,
6323 &AttrMinBlocksVal, &AttrMaxBlocksVal);
6324 else if (
auto *
Attr = dyn_cast<AMDGPUFlatWorkGroupSizeAttr>(A))
6325 CGM.handleAMDGPUFlatWorkGroupSizeAttr(
6326 nullptr,
Attr,
nullptr, &AttrMinThreadsVal,
6327 &AttrMaxThreadsVal);
6331 Attrs.MinThreads = std::max(Attrs.MinThreads, AttrMinThreadsVal);
6332 if (AttrMaxThreadsVal > 0)
6333 MaxThreadsVal = MaxThreadsVal > 0
6334 ? std::min(MaxThreadsVal, AttrMaxThreadsVal)
6335 : AttrMaxThreadsVal;
6336 Attrs.MinTeams = std::max(Attrs.MinTeams, AttrMinBlocksVal);
6337 if (AttrMaxBlocksVal > 0)
6338 MaxTeamsVal = MaxTeamsVal > 0 ? std::min(MaxTeamsVal, AttrMaxBlocksVal)
6346 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
6349 llvm::TargetRegionEntryInfo EntryInfo =
6353 llvm::OpenMPIRBuilder::FunctionGenCallback &&GenerateOutlinedFunction =
6354 [&CGF, &D, &
CodeGen](StringRef EntryFnName) {
6355 const CapturedStmt &CS = *D.getCapturedStmt(OMPD_target);
6357 CGOpenMPTargetRegionInfo CGInfo(CS,
CodeGen, EntryFnName);
6362 cantFail(
OMPBuilder.emitTargetRegionFunction(
6363 EntryInfo, GenerateOutlinedFunction, IsOffloadEntry, OutlinedFn,
6369 CGM.getTargetCodeGenInfo().setTargetAttributes(
nullptr, OutlinedFn,
CGM);
6372 for (
auto *A :
C->getAttrs()) {
6373 if (
auto *
Attr = dyn_cast<AMDGPUWavesPerEUAttr>(A))
6374 CGM.handleAMDGPUWavesPerEUAttr(OutlinedFn,
Attr);
6393 while (
const auto *
C = dyn_cast_or_null<CompoundStmt>(Child)) {
6395 for (
const Stmt *S :
C->body()) {
6396 if (
const auto *E = dyn_cast<Expr>(S)) {
6405 if (
const auto *DS = dyn_cast<DeclStmt>(S)) {
6406 if (llvm::all_of(DS->decls(), [](
const Decl *D) {
6407 if (isa<EmptyDecl>(D) || isa<DeclContext>(D) ||
6408 isa<TypeDecl>(D) || isa<PragmaCommentDecl>(D) ||
6409 isa<PragmaDetectMismatchDecl>(D) || isa<UsingDecl>(D) ||
6410 isa<UsingDirectiveDecl>(D) ||
6411 isa<OMPDeclareReductionDecl>(D) ||
6412 isa<OMPThreadPrivateDecl>(D) || isa<OMPAllocateDecl>(D))
6414 const auto *VD = dyn_cast<VarDecl>(D);
6417 return VD->hasGlobalStorage() || !VD->isUsed();
6427 Child = Child->IgnoreContainers();
6434 int32_t &MaxTeamsVal) {
6438 "Expected target-based executable directive.");
6439 switch (DirectiveKind) {
6441 const auto *CS = D.getInnermostCapturedStmt();
6444 const Stmt *ChildStmt =
6446 if (
const auto *NestedDir =
6447 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) {
6456 MinTeamsVal = MaxTeamsVal = Constant->getExtValue();
6459 MinTeamsVal = MaxTeamsVal = 0;
6462 MinTeamsVal = MaxTeamsVal = 1;
6466 MinTeamsVal = MaxTeamsVal = -1;
6469 case OMPD_target_teams_loop:
6470 case OMPD_target_teams:
6471 case OMPD_target_teams_distribute:
6472 case OMPD_target_teams_distribute_simd:
6473 case OMPD_target_teams_distribute_parallel_for:
6474 case OMPD_target_teams_distribute_parallel_for_simd: {
6476 const Expr *NumTeams =
6480 MinTeamsVal = MaxTeamsVal = Constant->getExtValue();
6483 MinTeamsVal = MaxTeamsVal = 0;
6486 case OMPD_target_parallel:
6487 case OMPD_target_parallel_for:
6488 case OMPD_target_parallel_for_simd:
6489 case OMPD_target_parallel_loop:
6490 case OMPD_target_simd:
6491 MinTeamsVal = MaxTeamsVal = 1;
6495 case OMPD_parallel_for:
6496 case OMPD_parallel_loop:
6497 case OMPD_parallel_master:
6498 case OMPD_parallel_sections:
6500 case OMPD_parallel_for_simd:
6502 case OMPD_cancellation_point:
6504 case OMPD_threadprivate:
6515 case OMPD_taskyield:
6518 case OMPD_taskgroup:
6524 case OMPD_target_data:
6525 case OMPD_target_exit_data:
6526 case OMPD_target_enter_data:
6527 case OMPD_distribute:
6528 case OMPD_distribute_simd:
6529 case OMPD_distribute_parallel_for:
6530 case OMPD_distribute_parallel_for_simd:
6531 case OMPD_teams_distribute:
6532 case OMPD_teams_distribute_simd:
6533 case OMPD_teams_distribute_parallel_for:
6534 case OMPD_teams_distribute_parallel_for_simd:
6535 case OMPD_target_update:
6536 case OMPD_declare_simd:
6537 case OMPD_declare_variant:
6538 case OMPD_begin_declare_variant:
6539 case OMPD_end_declare_variant:
6540 case OMPD_declare_target:
6541 case OMPD_end_declare_target:
6542 case OMPD_declare_reduction:
6543 case OMPD_declare_mapper:
6545 case OMPD_taskloop_simd:
6546 case OMPD_master_taskloop:
6547 case OMPD_master_taskloop_simd:
6548 case OMPD_parallel_master_taskloop:
6549 case OMPD_parallel_master_taskloop_simd:
6551 case OMPD_metadirective:
6557 llvm_unreachable(
"Unexpected directive kind.");
6563 "Clauses associated with the teams directive expected to be emitted "
6564 "only for the host!");
6566 int32_t MinNT = -1, MaxNT = -1;
6567 const Expr *NumTeams =
6569 if (NumTeams !=
nullptr) {
6572 switch (DirectiveKind) {
6574 const auto *CS = D.getInnermostCapturedStmt();
6575 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6579 return Bld.CreateIntCast(NumTeamsVal, CGF.
Int32Ty,
6582 case OMPD_target_teams:
6583 case OMPD_target_teams_distribute:
6584 case OMPD_target_teams_distribute_simd:
6585 case OMPD_target_teams_distribute_parallel_for:
6586 case OMPD_target_teams_distribute_parallel_for_simd: {
6590 return Bld.CreateIntCast(NumTeamsVal, CGF.
Int32Ty,
6598 assert(MinNT == MaxNT &&
"Num threads ranges require handling here.");
6599 return llvm::ConstantInt::getSigned(CGF.
Int32Ty, MinNT);
6607 const Expr **E, int32_t &UpperBound,
6608 bool UpperBoundOnly, llvm::Value **CondVal) {
6611 const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child);
6618 if (CondVal && Dir->hasClausesOfKind<
OMPIfClause>()) {
6619 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6622 for (
const auto *
C : Dir->getClausesOfKind<
OMPIfClause>()) {
6623 if (
C->getNameModifier() == OMPD_unknown ||
6624 C->getNameModifier() == OMPD_parallel) {
6639 if (
const auto *PreInit =
6641 for (
const auto *I : PreInit->decls()) {
6642 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
6658 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6660 const auto *NumThreadsClause =
6662 const Expr *NTExpr = NumThreadsClause->getNumThreads();
6663 if (NTExpr->isIntegerConstantExpr(CGF.
getContext()))
6664 if (
auto Constant = NTExpr->getIntegerConstantExpr(CGF.
getContext()))
6667 ? Constant->getZExtValue()
6668 : std::min(UpperBound,
6669 static_cast<int32_t
>(Constant->getZExtValue()));
6672 if (UpperBound == -1)
6677 if (
const auto *PreInit =
6678 cast_or_null<DeclStmt>(NumThreadsClause->getPreInitStmt())) {
6679 for (
const auto *I : PreInit->decls()) {
6680 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
6699 bool UpperBoundOnly, llvm::Value **CondVal,
const Expr **ThreadLimitExpr) {
6700 assert((!CGF.
getLangOpts().OpenMPIsTargetDevice || UpperBoundOnly) &&
6701 "Clauses associated with the teams directive expected to be emitted "
6702 "only for the host!");
6705 "Expected target-based executable directive.");
6707 const Expr *NT =
nullptr;
6708 const Expr **NTPtr = UpperBoundOnly ?
nullptr : &NT;
6710 auto CheckForConstExpr = [&](
const Expr *E,
const Expr **EPtr) {
6713 UpperBound = UpperBound ? Constant->getZExtValue()
6714 : std::min(UpperBound,
6715 int32_t(Constant->getZExtValue()));
6719 if (UpperBound == -1)
6725 auto ReturnSequential = [&]() {
6730 switch (DirectiveKind) {
6733 getNumThreads(CGF, CS, NTPtr, UpperBound, UpperBoundOnly, CondVal);
6739 if (
const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) {
6741 ThreadLimitClause = TLC;
6742 if (ThreadLimitExpr) {
6743 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6747 ThreadLimitClause->getThreadLimit().front()->getSourceRange());
6748 if (
const auto *PreInit =
6749 cast_or_null<DeclStmt>(ThreadLimitClause->getPreInitStmt())) {
6750 for (
const auto *I : PreInit->decls()) {
6751 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
6763 if (ThreadLimitClause)
6764 CheckForConstExpr(ThreadLimitClause->getThreadLimit().front(),
6766 if (
const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) {
6769 CS = Dir->getInnermostCapturedStmt();
6772 Dir = dyn_cast_or_null<OMPExecutableDirective>(Child);
6775 CS = Dir->getInnermostCapturedStmt();
6776 getNumThreads(CGF, CS, NTPtr, UpperBound, UpperBoundOnly, CondVal);
6778 return ReturnSequential();
6782 case OMPD_target_teams: {
6786 CheckForConstExpr(ThreadLimitClause->getThreadLimit().front(),
6790 getNumThreads(CGF, CS, NTPtr, UpperBound, UpperBoundOnly, CondVal);
6793 if (
const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) {
6794 if (Dir->getDirectiveKind() == OMPD_distribute) {
6795 CS = Dir->getInnermostCapturedStmt();
6796 getNumThreads(CGF, CS, NTPtr, UpperBound, UpperBoundOnly, CondVal);
6801 case OMPD_target_teams_distribute:
6805 CheckForConstExpr(ThreadLimitClause->getThreadLimit().front(),
6808 getNumThreads(CGF, D.getInnermostCapturedStmt(), NTPtr, UpperBound,
6809 UpperBoundOnly, CondVal);
6811 case OMPD_target_teams_loop:
6812 case OMPD_target_parallel_loop:
6813 case OMPD_target_parallel:
6814 case OMPD_target_parallel_for:
6815 case OMPD_target_parallel_for_simd:
6816 case OMPD_target_teams_distribute_parallel_for:
6817 case OMPD_target_teams_distribute_parallel_for_simd: {
6818 if (CondVal && D.hasClausesOfKind<
OMPIfClause>()) {
6820 for (
const auto *
C : D.getClausesOfKind<
OMPIfClause>()) {
6821 if (
C->getNameModifier() == OMPD_unknown ||
6822 C->getNameModifier() == OMPD_parallel) {
6832 return ReturnSequential();
6842 CheckForConstExpr(ThreadLimitClause->getThreadLimit().front(),
6848 CheckForConstExpr(NumThreadsClause->getNumThreads(),
nullptr);
6849 return NumThreadsClause->getNumThreads();
6853 case OMPD_target_teams_distribute_simd:
6854 case OMPD_target_simd:
6855 return ReturnSequential();
6859 llvm_unreachable(
"Unsupported directive kind.");
6864 llvm::Value *NumThreadsVal =
nullptr;
6865 llvm::Value *CondVal =
nullptr;
6866 llvm::Value *ThreadLimitVal =
nullptr;
6867 const Expr *ThreadLimitExpr =
nullptr;
6868 int32_t UpperBound = -1;
6871 CGF, D, UpperBound,
false, &CondVal,
6875 if (ThreadLimitExpr) {
6878 ThreadLimitVal = CGF.
Builder.CreateIntCast(ThreadLimitVal, CGF.
Int32Ty,
6883 if (UpperBound == 1) {
6884 NumThreadsVal = CGF.
Builder.getInt32(UpperBound);
6887 NumThreadsVal = CGF.
Builder.CreateIntCast(NumThreadsVal, CGF.
Int32Ty,
6889 }
else if (ThreadLimitVal) {
6892 NumThreadsVal = ThreadLimitVal;
6893 ThreadLimitVal =
nullptr;
6896 assert(!ThreadLimitVal &&
"Default not applicable with thread limit value");
6897 NumThreadsVal = CGF.
Builder.getInt32(0);
6904 NumThreadsVal = CGF.
Builder.CreateSelect(CondVal, NumThreadsVal,
6910 if (ThreadLimitVal) {
6911 NumThreadsVal = CGF.
Builder.CreateSelect(
6912 CGF.
Builder.CreateICmpULT(ThreadLimitVal, NumThreadsVal),
6913 ThreadLimitVal, NumThreadsVal);
6916 return NumThreadsVal;
6926class MappableExprsHandler {
6932 struct AttachPtrExprComparator {
6933 const MappableExprsHandler &Handler;
6935 mutable llvm::DenseMap<std::pair<const Expr *, const Expr *>,
bool>
6936 CachedEqualityComparisons;
6938 AttachPtrExprComparator(
const MappableExprsHandler &H) : Handler(H) {}
6939 AttachPtrExprComparator() =
delete;
6942 bool operator()(
const Expr *LHS,
const Expr *RHS)
const {
6947 const auto ItLHS = Handler.AttachPtrComponentDepthMap.find(LHS);
6948 const auto ItRHS = Handler.AttachPtrComponentDepthMap.find(RHS);
6950 std::optional<size_t> DepthLHS =
6951 (ItLHS != Handler.AttachPtrComponentDepthMap.end()) ? ItLHS->second
6953 std::optional<size_t> DepthRHS =
6954 (ItRHS != Handler.AttachPtrComponentDepthMap.end()) ? ItRHS->second
6958 if (!DepthLHS.has_value() && !DepthRHS.has_value()) {
6960 if (areEqual(LHS, RHS))
6963 return wasComputedBefore(LHS, RHS);
6965 if (!DepthLHS.has_value())
6967 if (!DepthRHS.has_value())
6971 if (DepthLHS.value() != DepthRHS.value())
6972 return DepthLHS.value() < DepthRHS.value();
6975 if (areEqual(LHS, RHS))
6978 return wasComputedBefore(LHS, RHS);
6984 bool areEqual(
const Expr *LHS,
const Expr *RHS)
const {
6986 const auto CachedResultIt = CachedEqualityComparisons.find({LHS, RHS});
6987 if (CachedResultIt != CachedEqualityComparisons.end())
6988 return CachedResultIt->second;
7002 bool wasComputedBefore(
const Expr *LHS,
const Expr *RHS)
const {
7003 const size_t &OrderLHS = Handler.AttachPtrComputationOrderMap.at(LHS);
7004 const size_t &OrderRHS = Handler.AttachPtrComputationOrderMap.at(RHS);
7006 return OrderLHS < OrderRHS;
7015 bool areSemanticallyEqual(
const Expr *LHS,
const Expr *RHS)
const {
7037 if (
const auto *LD = dyn_cast<DeclRefExpr>(LHS)) {
7038 const auto *RD = dyn_cast<DeclRefExpr>(RHS);
7041 return LD->getDecl()->getCanonicalDecl() ==
7042 RD->getDecl()->getCanonicalDecl();
7046 if (
const auto *LA = dyn_cast<ArraySubscriptExpr>(LHS)) {
7047 const auto *RA = dyn_cast<ArraySubscriptExpr>(RHS);
7050 return areSemanticallyEqual(LA->getBase(), RA->getBase()) &&
7051 areSemanticallyEqual(LA->getIdx(), RA->getIdx());
7055 if (
const auto *LM = dyn_cast<MemberExpr>(LHS)) {
7056 const auto *RM = dyn_cast<MemberExpr>(RHS);
7059 if (LM->getMemberDecl()->getCanonicalDecl() !=
7060 RM->getMemberDecl()->getCanonicalDecl())
7062 return areSemanticallyEqual(LM->getBase(), RM->getBase());
7066 if (
const auto *LU = dyn_cast<UnaryOperator>(LHS)) {
7067 const auto *RU = dyn_cast<UnaryOperator>(RHS);
7070 if (LU->getOpcode() != RU->getOpcode())
7072 return areSemanticallyEqual(LU->getSubExpr(), RU->getSubExpr());
7076 if (
const auto *LB = dyn_cast<BinaryOperator>(LHS)) {
7077 const auto *RB = dyn_cast<BinaryOperator>(RHS);
7080 if (LB->getOpcode() != RB->getOpcode())
7082 return areSemanticallyEqual(LB->getLHS(), RB->getLHS()) &&
7083 areSemanticallyEqual(LB->getRHS(), RB->getRHS());
7089 if (
const auto *LAS = dyn_cast<ArraySectionExpr>(LHS)) {
7090 const auto *RAS = dyn_cast<ArraySectionExpr>(RHS);
7093 return areSemanticallyEqual(LAS->getBase(), RAS->getBase()) &&
7094 areSemanticallyEqual(LAS->getLowerBound(),
7095 RAS->getLowerBound()) &&
7096 areSemanticallyEqual(LAS->getLength(), RAS->getLength());
7100 if (
const auto *LC = dyn_cast<CastExpr>(LHS)) {
7101 const auto *RC = dyn_cast<CastExpr>(RHS);
7104 if (LC->getCastKind() != RC->getCastKind())
7106 return areSemanticallyEqual(LC->getSubExpr(), RC->getSubExpr());
7114 if (
const auto *LI = dyn_cast<IntegerLiteral>(LHS)) {
7115 const auto *RI = dyn_cast<IntegerLiteral>(RHS);
7118 return LI->getValue() == RI->getValue();
7122 if (
const auto *LC = dyn_cast<CharacterLiteral>(LHS)) {
7123 const auto *RC = dyn_cast<CharacterLiteral>(RHS);
7126 return LC->getValue() == RC->getValue();
7130 if (
const auto *LF = dyn_cast<FloatingLiteral>(LHS)) {
7131 const auto *RF = dyn_cast<FloatingLiteral>(RHS);
7135 return LF->getValue().bitwiseIsEqual(RF->getValue());
7139 if (
const auto *LS = dyn_cast<StringLiteral>(LHS)) {
7140 const auto *RS = dyn_cast<StringLiteral>(RHS);
7143 return LS->getString() == RS->getString();
7151 if (
const auto *LB = dyn_cast<CXXBoolLiteralExpr>(LHS)) {
7152 const auto *RB = dyn_cast<CXXBoolLiteralExpr>(RHS);
7155 return LB->getValue() == RB->getValue();
7164 static unsigned getFlagMemberOffset() {
7165 unsigned Offset = 0;
7166 for (uint64_t Remain =
7167 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
7168 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF);
7169 !(Remain & 1); Remain = Remain >> 1)
7176 class MappingExprInfo {
7178 const ValueDecl *MapDecl =
nullptr;
7181 const Expr *MapExpr =
nullptr;
7184 MappingExprInfo(
const ValueDecl *MapDecl,
const Expr *MapExpr =
nullptr)
7185 : MapDecl(MapDecl), MapExpr(MapExpr) {}
7187 const ValueDecl *getMapDecl()
const {
return MapDecl; }
7188 const Expr *getMapExpr()
const {
return MapExpr; }
7191 using DeviceInfoTy = llvm::OpenMPIRBuilder::DeviceInfoTy;
7192 using MapBaseValuesArrayTy = llvm::OpenMPIRBuilder::MapValuesArrayTy;
7193 using MapValuesArrayTy = llvm::OpenMPIRBuilder::MapValuesArrayTy;
7194 using MapFlagsArrayTy = llvm::OpenMPIRBuilder::MapFlagsArrayTy;
7195 using MapDimArrayTy = llvm::OpenMPIRBuilder::MapDimArrayTy;
7196 using MapNonContiguousArrayTy =
7197 llvm::OpenMPIRBuilder::MapNonContiguousArrayTy;
7198 using MapExprsArrayTy = SmallVector<MappingExprInfo, 4>;
7199 using MapValueDeclsArrayTy = SmallVector<const ValueDecl *, 4>;
7203 bool ,
const ValueDecl *,
const Expr *>;
7204 using MapDataArrayTy = SmallVector<MapData, 4>;
7209 struct MapCombinedInfoTy : llvm::OpenMPIRBuilder::MapInfosTy {
7210 MapExprsArrayTy Exprs;
7211 MapValueDeclsArrayTy Mappers;
7212 MapValueDeclsArrayTy DevicePtrDecls;
7215 void append(MapCombinedInfoTy &CurInfo) {
7216 Exprs.append(CurInfo.Exprs.begin(), CurInfo.Exprs.end());
7217 DevicePtrDecls.append(CurInfo.DevicePtrDecls.begin(),
7218 CurInfo.DevicePtrDecls.end());
7219 Mappers.append(CurInfo.Mappers.begin(), CurInfo.Mappers.end());
7220 llvm::OpenMPIRBuilder::MapInfosTy::append(CurInfo);
7228 struct StructRangeInfoTy {
7229 MapCombinedInfoTy PreliminaryMapData;
7230 std::pair<
unsigned , Address > LowestElem = {
7232 std::pair<
unsigned , Address > HighestElem = {
7236 bool IsArraySection =
false;
7237 bool HasCompleteRecord =
false;
7242 struct AttachInfoTy {
7245 const ValueDecl *AttachPtrDecl =
nullptr;
7246 const Expr *AttachMapExpr =
nullptr;
7248 bool isValid()
const {
7255 bool hasAttachEntryForCapturedVar(
const ValueDecl *VD)
const {
7256 for (
const auto &AttachEntry : AttachPtrExprMap) {
7257 if (AttachEntry.second) {
7260 if (
const auto *DRE = dyn_cast<DeclRefExpr>(AttachEntry.second))
7261 if (DRE->getDecl() == VD)
7269 const Expr *getAttachPtrExpr(
7272 const auto It = AttachPtrExprMap.find(Components);
7273 if (It != AttachPtrExprMap.end())
7284 ArrayRef<OpenMPMapModifierKind> MapModifiers;
7285 ArrayRef<OpenMPMotionModifierKind> MotionModifiers;
7286 bool ReturnDevicePointer =
false;
7287 bool IsImplicit =
false;
7288 const ValueDecl *Mapper =
nullptr;
7289 const Expr *VarRef =
nullptr;
7290 bool ForDeviceAddr =
false;
7292 MapInfo() =
default;
7296 ArrayRef<OpenMPMapModifierKind> MapModifiers,
7297 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
7298 bool ReturnDevicePointer,
bool IsImplicit,
7299 const ValueDecl *Mapper =
nullptr,
const Expr *VarRef =
nullptr,
7300 bool ForDeviceAddr =
false)
7301 : Components(Components), MapType(MapType), MapModifiers(MapModifiers),
7302 MotionModifiers(MotionModifiers),
7303 ReturnDevicePointer(ReturnDevicePointer), IsImplicit(IsImplicit),
7304 Mapper(Mapper), VarRef(VarRef), ForDeviceAddr(ForDeviceAddr) {}
7309 llvm::PointerUnion<
const OMPExecutableDirective *,
7310 const OMPDeclareMapperDecl *>
7314 CodeGenFunction &CGF;
7319 llvm::DenseMap<CanonicalDeclPtr<const VarDecl>,
bool> FirstPrivateDecls;
7322 llvm::SmallSet<OpenMPDefaultmapClauseKind, 4> DefaultmapFirstprivateKinds;
7328 SmallVector<OMPClauseMappableExprCommon::MappableExprComponentListRef, 4>>
7335 SmallVector<OMPClauseMappableExprCommon::MappableExprComponentListRef, 4>>
7339 llvm::DenseMap<const ValueDecl *, const OMPMapClause *> LambdasMap;
7354 llvm::DenseMap<const Expr *, std::optional<size_t>>
7355 AttachPtrComponentDepthMap = {{
nullptr, std::nullopt}};
7359 llvm::DenseMap<const Expr *, size_t> AttachPtrComputationOrderMap = {
7364 AttachPtrExprComparator AttachPtrComparator;
7366 llvm::Value *getExprTypeSize(
const Expr *E)
const {
7370 if (
const auto *OAE = dyn_cast<OMPArrayShapingExpr>(E)) {
7372 CGF.
getTypeSize(OAE->getBase()->getType()->getPointeeType());
7373 for (
const Expr *SE : OAE->getDimensions()) {
7384 if (
const auto *RefTy = ExprTy->
getAs<ReferenceType>())
7390 if (
const auto *OAE = dyn_cast<ArraySectionExpr>(E)) {
7392 OAE->getBase()->IgnoreParenImpCasts())
7398 if (!OAE->getLength() && OAE->getColonLocFirst().isValid() &&
7399 !OAE->getLowerBound())
7402 llvm::Value *ElemSize;
7403 if (
const auto *PTy = BaseTy->
getAs<PointerType>()) {
7404 ElemSize = CGF.
getTypeSize(PTy->getPointeeType().getCanonicalType());
7407 assert(ATy &&
"Expecting array type if not a pointer type.");
7408 ElemSize = CGF.
getTypeSize(ATy->getElementType().getCanonicalType());
7413 if (!OAE->getLength() && OAE->getColonLocFirst().isInvalid())
7416 if (
const Expr *LenExpr = OAE->getLength()) {
7420 LenExpr->getExprLoc());
7421 return CGF.
Builder.CreateNUWMul(LengthVal, ElemSize);
7423 assert(!OAE->getLength() && OAE->getColonLocFirst().isValid() &&
7424 OAE->getLowerBound() &&
"expected array_section[lb:].");
7430 OAE->getLowerBound()->getExprLoc());
7431 LBVal = CGF.
Builder.CreateNUWMul(LBVal, ElemSize);
7432 llvm::Value *Cmp = CGF.
Builder.CreateICmpUGT(LengthVal, LBVal);
7433 llvm::Value *TrueVal = CGF.
Builder.CreateNUWSub(LengthVal, LBVal);
7434 LengthVal = CGF.
Builder.CreateSelect(
7435 Cmp, TrueVal, llvm::ConstantInt::get(CGF.
SizeTy, 0));
7445 OpenMPOffloadMappingFlags getMapTypeBits(
7447 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
bool IsImplicit,
7448 bool AddPtrFlag,
bool AddIsTargetParamFlag,
bool IsNonContiguous)
const {
7449 OpenMPOffloadMappingFlags Bits =
7450 IsImplicit ? OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT
7451 : OpenMPOffloadMappingFlags::OMP_MAP_NONE;
7453 case OMPC_MAP_alloc:
7454 case OMPC_MAP_release:
7461 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_TO;
7464 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_FROM;
7466 case OMPC_MAP_tofrom:
7467 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_TO |
7468 OpenMPOffloadMappingFlags::OMP_MAP_FROM;
7470 case OMPC_MAP_delete:
7471 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_DELETE;
7474 llvm_unreachable(
"Unexpected map type!");
7477 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ;
7478 if (AddIsTargetParamFlag)
7479 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM;
7480 if (llvm::is_contained(MapModifiers, OMPC_MAP_MODIFIER_always))
7481 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_ALWAYS;
7482 if (llvm::is_contained(MapModifiers, OMPC_MAP_MODIFIER_close))
7483 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_CLOSE;
7484 if (llvm::is_contained(MapModifiers, OMPC_MAP_MODIFIER_present) ||
7485 llvm::is_contained(MotionModifiers, OMPC_MOTION_MODIFIER_present))
7486 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_PRESENT;
7487 if (llvm::is_contained(MapModifiers, OMPC_MAP_MODIFIER_ompx_hold))
7488 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_OMPX_HOLD;
7489 if (IsNonContiguous)
7490 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_NON_CONTIG;
7496 bool isFinalArraySectionExpression(
const Expr *E)
const {
7497 const auto *OASE = dyn_cast<ArraySectionExpr>(E);
7504 if (OASE->getColonLocFirst().isInvalid())
7507 const Expr *Length = OASE->getLength();
7514 OASE->getBase()->IgnoreParenImpCasts())
7516 if (
const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.
getTypePtr()))
7517 return ATy->getSExtSize() != 1;
7529 llvm::APSInt ConstLength =
Result.Val.getInt();
7530 return ConstLength.getSExtValue() != 1;
7537 void emitAttachEntry(CodeGenFunction &CGF, MapCombinedInfoTy &CombinedInfo,
7538 const AttachInfoTy &AttachInfo)
const {
7539 assert(AttachInfo.isValid() &&
7540 "Expected valid attach pointer/pointee information!");
7544 llvm::Value *PointerSize = CGF.
Builder.CreateIntCast(
7545 llvm::ConstantInt::get(
7551 CombinedInfo.Exprs.emplace_back(AttachInfo.AttachPtrDecl,
7552 AttachInfo.AttachMapExpr);
7553 CombinedInfo.BasePointers.push_back(
7554 AttachInfo.AttachPtrAddr.emitRawPointer(CGF));
7555 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
7556 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
7557 CombinedInfo.Pointers.push_back(
7558 AttachInfo.AttachPteeAddr.emitRawPointer(CGF));
7559 CombinedInfo.Sizes.push_back(PointerSize);
7560 CombinedInfo.Types.push_back(OpenMPOffloadMappingFlags::OMP_MAP_ATTACH);
7561 CombinedInfo.Mappers.push_back(
nullptr);
7562 CombinedInfo.NonContigInfo.Dims.push_back(1);
7569 class CopyOverlappedEntryGaps {
7570 CodeGenFunction &CGF;
7571 MapCombinedInfoTy &CombinedInfo;
7572 OpenMPOffloadMappingFlags Flags = OpenMPOffloadMappingFlags::OMP_MAP_NONE;
7573 const ValueDecl *MapDecl =
nullptr;
7574 const Expr *MapExpr =
nullptr;
7576 bool IsNonContiguous =
false;
7580 const RecordDecl *LastParent =
nullptr;
7582 unsigned LastIndex = -1u;
7586 CopyOverlappedEntryGaps(CodeGenFunction &CGF,
7587 MapCombinedInfoTy &CombinedInfo,
7588 OpenMPOffloadMappingFlags Flags,
7589 const ValueDecl *MapDecl,
const Expr *MapExpr,
7590 Address BP, Address LB,
bool IsNonContiguous,
7592 : CGF(CGF), CombinedInfo(CombinedInfo), Flags(Flags), MapDecl(MapDecl),
7593 MapExpr(MapExpr), BP(BP), IsNonContiguous(IsNonContiguous),
7594 DimSize(DimSize), LB(LB) {}
7597 const OMPClauseMappableExprCommon::MappableComponent &MC,
7598 const FieldDecl *FD,
7599 llvm::function_ref<LValue(CodeGenFunction &,
const MemberExpr *)>
7600 EmitMemberExprBase) {
7610 LValue BaseLVal = EmitMemberExprBase(CGF, ME);
7622 copyUntilField(FD, ComponentLB);
7625 if (((int64_t)FieldOffset - (int64_t)Cursor) > 0)
7626 copyUntilField(FD, ComponentLB);
7628 Cursor = FieldOffset + FieldSize;
7633 void copyUntilField(
const FieldDecl *FD, Address ComponentLB) {
7637 CGF.
Builder.CreatePtrDiff(CGF.
Int8Ty, ComponentLBPtr, LBPtr);
7638 copySizedChunk(LBPtr, Size);
7641 void copyUntilEnd(Address HB) {
7643 const ASTRecordLayout &RL =
7652 copySizedChunk(LBPtr, Size);
7655 void copySizedChunk(llvm::Value *Base, llvm::Value *Size) {
7656 CombinedInfo.Exprs.emplace_back(MapDecl, MapExpr);
7658 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
7659 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
7660 CombinedInfo.Pointers.push_back(Base);
7661 CombinedInfo.Sizes.push_back(
7663 CombinedInfo.Types.push_back(Flags);
7664 CombinedInfo.Mappers.push_back(
nullptr);
7665 CombinedInfo.NonContigInfo.Dims.push_back(IsNonContiguous ? DimSize : 1);
7674 void generateInfoForComponentList(
7676 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
7678 MapCombinedInfoTy &CombinedInfo,
7679 MapCombinedInfoTy &StructBaseCombinedInfo,
7680 StructRangeInfoTy &PartialStruct, AttachInfoTy &AttachInfo,
7681 bool IsFirstComponentList,
bool IsImplicit,
7682 bool GenerateAllInfoForClauses,
const ValueDecl *Mapper =
nullptr,
7683 bool ForDeviceAddr =
false,
const ValueDecl *BaseDecl =
nullptr,
7684 const Expr *MapExpr =
nullptr,
7685 ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef>
7686 OverlappedElements = {})
const {
7904 bool IsCaptureFirstInfo = IsFirstComponentList;
7908 bool RequiresReference =
false;
7911 auto CI = Components.rbegin();
7912 auto CE = Components.rend();
7917 bool IsExpressionFirstInfo =
true;
7918 bool FirstPointerInComplexData =
false;
7921 const Expr *AssocExpr = I->getAssociatedExpression();
7922 const auto *AE = dyn_cast<ArraySubscriptExpr>(AssocExpr);
7923 const auto *OASE = dyn_cast<ArraySectionExpr>(AssocExpr);
7924 const auto *OAShE = dyn_cast<OMPArrayShapingExpr>(AssocExpr);
7927 const Expr *AttachPtrExpr = getAttachPtrExpr(Components);
7928 auto [AttachPtrAddr, AttachPteeBaseAddr] =
7929 getAttachPtrAddrAndPteeBaseAddr(AttachPtrExpr, CGF);
7931 bool HasAttachPtr = AttachPtrExpr !=
nullptr;
7932 bool FirstComponentIsForAttachPtr = AssocExpr == AttachPtrExpr;
7933 bool SeenAttachPtr = FirstComponentIsForAttachPtr;
7935 if (FirstComponentIsForAttachPtr) {
7943 }
else if ((AE &&
isa<CXXThisExpr>(AE->getBase()->IgnoreParenImpCasts())) ||
7957 if (
const auto *VD =
7958 dyn_cast_or_null<VarDecl>(I->getAssociatedDeclaration())) {
7959 if (std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
7960 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD)) {
7961 if ((*Res == OMPDeclareTargetDeclAttr::MT_Link) ||
7962 ((*Res == OMPDeclareTargetDeclAttr::MT_To ||
7963 *Res == OMPDeclareTargetDeclAttr::MT_Enter) &&
7965 RequiresReference =
true;
7975 I->getAssociatedDeclaration()->
getType().getNonReferenceType();
7980 const auto *VD = dyn_cast<VarDecl>(I->getAssociatedDeclaration());
7982 !VD || VD->hasLocalStorage() || HasAttachPtr)
7985 FirstPointerInComplexData =
true;
8004 bool ShouldBeMemberOf =
false;
8013 const MemberExpr *EncounteredME =
nullptr;
8025 bool IsNonContiguous =
8026 CombinedInfo.NonContigInfo.IsNonContiguous ||
8027 any_of(Components, [&](
const auto &Component) {
8029 dyn_cast<ArraySectionExpr>(Component.getAssociatedExpression());
8033 const Expr *StrideExpr = OASE->getStride();
8037 const auto Constant =
8042 return !Constant->isOne();
8045 bool IsPrevMemberReference =
false;
8047 bool IsPartialMapped =
8048 !PartialStruct.PreliminaryMapData.BasePointers.empty();
8055 bool IsMappingWholeStruct =
true;
8056 if (!GenerateAllInfoForClauses) {
8057 IsMappingWholeStruct =
false;
8059 for (
auto TempI = I; TempI != CE; ++TempI) {
8060 const MemberExpr *PossibleME =
8061 dyn_cast<MemberExpr>(TempI->getAssociatedExpression());
8063 IsMappingWholeStruct =
false;
8069 bool SeenFirstNonBinOpExprAfterAttachPtr =
false;
8070 for (; I != CE; ++I) {
8073 if (HasAttachPtr && !SeenAttachPtr) {
8074 SeenAttachPtr = I->getAssociatedExpression() == AttachPtrExpr;
8081 if (HasAttachPtr && !SeenFirstNonBinOpExprAfterAttachPtr) {
8082 const auto *BO = dyn_cast<BinaryOperator>(I->getAssociatedExpression());
8087 SeenFirstNonBinOpExprAfterAttachPtr =
true;
8088 BP = AttachPteeBaseAddr;
8092 if (!EncounteredME) {
8093 EncounteredME = dyn_cast<MemberExpr>(I->getAssociatedExpression());
8096 if (EncounteredME) {
8097 ShouldBeMemberOf =
true;
8100 if (FirstPointerInComplexData) {
8101 QualType Ty = std::prev(I)
8102 ->getAssociatedDeclaration()
8104 .getNonReferenceType();
8106 FirstPointerInComplexData =
false;
8111 auto Next = std::next(I);
8121 bool IsFinalArraySection =
8123 isFinalArraySectionExpression(I->getAssociatedExpression());
8127 const ValueDecl *MapDecl = (I->getAssociatedDeclaration())
8128 ? I->getAssociatedDeclaration()
8130 MapExpr = (I->getAssociatedExpression()) ? I->getAssociatedExpression()
8137 dyn_cast<ArraySectionExpr>(I->getAssociatedExpression());
8139 dyn_cast<OMPArrayShapingExpr>(I->getAssociatedExpression());
8140 const auto *UO = dyn_cast<UnaryOperator>(I->getAssociatedExpression());
8141 const auto *BO = dyn_cast<BinaryOperator>(I->getAssociatedExpression());
8147 I->getAssociatedExpression()->getType()->isAnyPointerType();
8148 bool IsMemberReference =
isa<MemberExpr>(I->getAssociatedExpression()) &&
8151 bool IsNonDerefPointer = IsPointer &&
8152 !(UO && UO->getOpcode() != UO_Deref) && !BO &&
8158 if (
Next == CE || IsMemberReference || IsNonDerefPointer ||
8159 IsFinalArraySection) {
8162 assert((
Next == CE ||
8169 "Unexpected expression");
8173 auto &&EmitMemberExprBase = [](CodeGenFunction &CGF,
8174 const MemberExpr *E) {
8175 const Expr *BaseExpr = E->getBase();
8180 LValueBaseInfo BaseInfo;
8181 TBAAAccessInfo TBAAInfo;
8195 OAShE->getBase()->getType()->getPointeeType()),
8197 OAShE->getBase()->getType()));
8198 }
else if (IsMemberReference) {
8200 LValue BaseLVal = EmitMemberExprBase(CGF, ME);
8215 FinalLowestElem = LowestElem;
8220 bool IsMemberPointerOrAddr =
8222 (((IsPointer || ForDeviceAddr) &&
8223 I->getAssociatedExpression() == EncounteredME) ||
8224 (IsPrevMemberReference && !IsPointer) ||
8225 (IsMemberReference &&
Next != CE &&
8226 !
Next->getAssociatedExpression()->getType()->isPointerType()));
8227 if (!OverlappedElements.empty() &&
Next == CE) {
8229 assert(!PartialStruct.Base.isValid() &&
"The base element is set.");
8230 assert(!IsPointer &&
8231 "Unexpected base element with the pointer type.");
8234 PartialStruct.LowestElem = {0, LowestElem};
8236 I->getAssociatedExpression()->getType());
8241 PartialStruct.HighestElem = {
8242 std::numeric_limits<
decltype(
8243 PartialStruct.HighestElem.first)>
::max(),
8245 PartialStruct.Base = BP;
8246 PartialStruct.LB = LB;
8248 PartialStruct.PreliminaryMapData.BasePointers.empty() &&
8249 "Overlapped elements must be used only once for the variable.");
8250 std::swap(PartialStruct.PreliminaryMapData, CombinedInfo);
8252 OpenMPOffloadMappingFlags Flags =
8253 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF |
8254 getMapTypeBits(MapType, MapModifiers, MotionModifiers, IsImplicit,
8256 false, IsNonContiguous);
8257 CopyOverlappedEntryGaps CopyGaps(CGF, CombinedInfo, Flags, MapDecl,
8258 MapExpr, BP, LB, IsNonContiguous,
8262 Component : OverlappedElements) {
8263 for (
const OMPClauseMappableExprCommon::MappableComponent &MC :
8266 if (
const auto *FD = dyn_cast<FieldDecl>(VD)) {
8267 CopyGaps.processField(MC, FD, EmitMemberExprBase);
8272 CopyGaps.copyUntilEnd(HB);
8275 llvm::Value *
Size = getExprTypeSize(I->getAssociatedExpression());
8282 if ((!IsMemberPointerOrAddr && !IsPartialMapped) ||
8284 if (!IsMappingWholeStruct) {
8285 CombinedInfo.Exprs.emplace_back(MapDecl, MapExpr);
8287 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
8288 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
8290 CombinedInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
8292 CombinedInfo.NonContigInfo.Dims.push_back(IsNonContiguous ? DimSize
8295 StructBaseCombinedInfo.Exprs.emplace_back(MapDecl, MapExpr);
8296 StructBaseCombinedInfo.BasePointers.push_back(
8298 StructBaseCombinedInfo.DevicePtrDecls.push_back(
nullptr);
8299 StructBaseCombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
8300 StructBaseCombinedInfo.Pointers.push_back(LB.
emitRawPointer(CGF));
8301 StructBaseCombinedInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
8303 StructBaseCombinedInfo.NonContigInfo.Dims.push_back(
8304 IsNonContiguous ? DimSize : 1);
8308 bool HasMapper = Mapper &&
Next == CE;
8309 if (!IsMappingWholeStruct)
8310 CombinedInfo.Mappers.push_back(HasMapper ? Mapper :
nullptr);
8312 StructBaseCombinedInfo.Mappers.push_back(HasMapper ? Mapper
8319 OpenMPOffloadMappingFlags Flags = getMapTypeBits(
8320 MapType, MapModifiers, MotionModifiers, IsImplicit,
8321 !IsExpressionFirstInfo || RequiresReference ||
8322 FirstPointerInComplexData || IsMemberReference,
8323 IsCaptureFirstInfo && !RequiresReference, IsNonContiguous);
8325 if (!IsExpressionFirstInfo || IsMemberReference) {
8328 if (IsPointer || (IsMemberReference &&
Next != CE))
8329 Flags &= ~(OpenMPOffloadMappingFlags::OMP_MAP_TO |
8330 OpenMPOffloadMappingFlags::OMP_MAP_FROM |
8331 OpenMPOffloadMappingFlags::OMP_MAP_ALWAYS |
8332 OpenMPOffloadMappingFlags::OMP_MAP_DELETE |
8333 OpenMPOffloadMappingFlags::OMP_MAP_CLOSE);
8335 if (ShouldBeMemberOf) {
8338 Flags |= OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF;
8341 ShouldBeMemberOf =
false;
8345 if (!IsMappingWholeStruct)
8346 CombinedInfo.Types.push_back(Flags);
8348 StructBaseCombinedInfo.Types.push_back(Flags);
8354 if (EncounteredME) {
8359 if (!PartialStruct.Base.isValid()) {
8360 PartialStruct.LowestElem = {FieldIndex, LowestElem};
8361 if (IsFinalArraySection && OASE) {
8365 PartialStruct.HighestElem = {FieldIndex, HB};
8367 PartialStruct.HighestElem = {FieldIndex, LowestElem};
8369 PartialStruct.Base = BP;
8370 PartialStruct.LB = BP;
8371 }
else if (FieldIndex < PartialStruct.LowestElem.first) {
8372 PartialStruct.LowestElem = {FieldIndex, LowestElem};
8373 }
else if (FieldIndex > PartialStruct.HighestElem.first) {
8374 if (IsFinalArraySection && OASE) {
8378 PartialStruct.HighestElem = {FieldIndex, HB};
8380 PartialStruct.HighestElem = {FieldIndex, LowestElem};
8386 if (IsFinalArraySection || IsNonContiguous)
8387 PartialStruct.IsArraySection =
true;
8390 if (IsFinalArraySection)
8395 BP = IsMemberReference ? LowestElem : LB;
8396 if (!IsPartialMapped)
8397 IsExpressionFirstInfo =
false;
8398 IsCaptureFirstInfo =
false;
8399 FirstPointerInComplexData =
false;
8400 IsPrevMemberReference = IsMemberReference;
8401 }
else if (FirstPointerInComplexData) {
8402 QualType Ty = Components.rbegin()
8403 ->getAssociatedDeclaration()
8405 .getNonReferenceType();
8407 FirstPointerInComplexData =
false;
8413 PartialStruct.HasCompleteRecord =
true;
8416 if (shouldEmitAttachEntry(AttachPtrExpr, BaseDecl, CGF, CurDir)) {
8417 AttachInfo.AttachPtrAddr = AttachPtrAddr;
8418 AttachInfo.AttachPteeAddr = FinalLowestElem;
8419 AttachInfo.AttachPtrDecl = BaseDecl;
8420 AttachInfo.AttachMapExpr = MapExpr;
8423 if (!IsNonContiguous)
8426 const ASTContext &Context = CGF.
getContext();
8430 MapValuesArrayTy CurOffsets = {llvm::ConstantInt::get(CGF.
CGM.
Int64Ty, 0)};
8431 MapValuesArrayTy CurCounts = {llvm::ConstantInt::get(CGF.
CGM.
Int64Ty, 1)};
8432 MapValuesArrayTy CurStrides;
8433 MapValuesArrayTy DimSizes{llvm::ConstantInt::get(CGF.
CGM.
Int64Ty, 1)};
8439 for (
const OMPClauseMappableExprCommon::MappableComponent &Component :
8441 const Expr *AssocExpr = Component.getAssociatedExpression();
8442 const auto *OASE = dyn_cast<ArraySectionExpr>(AssocExpr);
8452 assert((VAT || CAT || &Component == &*Components.begin()) &&
8453 "Should be either ConstantArray or VariableArray if not the "
8457 if (CurStrides.empty()) {
8458 const Type *ElementType =
nullptr;
8460 ElementType = CAT->getElementType().getTypePtr();
8462 ElementType = VAT->getElementType().getTypePtr();
8463 else if (&Component == &*Components.begin()) {
8470 if (
const auto *PtrType = Ty->
getAs<PointerType>())
8477 "Non-first components should not be raw pointers");
8485 if (&Component != &*Components.begin())
8489 CurStrides.push_back(
8490 llvm::ConstantInt::get(CGF.
Int64Ty, ElementTypeSize));
8495 if (DimSizes.size() < Components.size() - 1) {
8498 llvm::ConstantInt::get(CGF.
Int64Ty, CAT->getZExtSize()));
8500 DimSizes.push_back(CGF.
Builder.CreateIntCast(
8507 auto *DI = DimSizes.begin() + 1;
8509 llvm::Value *DimProd =
8510 llvm::ConstantInt::get(CGF.
CGM.
Int64Ty, ElementTypeSize);
8519 for (
const OMPClauseMappableExprCommon::MappableComponent &Component :
8521 const Expr *AssocExpr = Component.getAssociatedExpression();
8523 if (
const auto *AE = dyn_cast<ArraySubscriptExpr>(AssocExpr)) {
8524 llvm::Value *Offset = CGF.
Builder.CreateIntCast(
8527 CurOffsets.push_back(Offset);
8528 CurCounts.push_back(llvm::ConstantInt::get(CGF.
Int64Ty, 1));
8529 CurStrides.push_back(CurStrides.back());
8533 const auto *OASE = dyn_cast<ArraySectionExpr>(AssocExpr);
8539 const Expr *OffsetExpr = OASE->getLowerBound();
8540 llvm::Value *Offset =
nullptr;
8543 Offset = llvm::ConstantInt::get(CGF.
Int64Ty, 0);
8549 CurOffsets.push_back(Offset);
8552 const Expr *CountExpr = OASE->getLength();
8553 llvm::Value *Count =
nullptr;
8559 if (!OASE->getColonLocFirst().isValid() &&
8560 !OASE->getColonLocSecond().isValid()) {
8561 Count = llvm::ConstantInt::get(CGF.
Int64Ty, 1);
8567 const Expr *StrideExpr = OASE->getStride();
8568 llvm::Value *Stride =
8574 Count = CGF.
Builder.CreateUDiv(
8575 CGF.
Builder.CreateNUWSub(*DI, Offset), Stride);
8577 Count = CGF.
Builder.CreateNUWSub(*DI, Offset);
8583 CurCounts.push_back(Count);
8592 const Expr *StrideExpr = OASE->getStride();
8593 llvm::Value *Stride =
8598 DimProd = CGF.
Builder.CreateNUWMul(DimProd, *(DI - 1));
8600 CurStrides.push_back(CGF.
Builder.CreateNUWMul(DimProd, Stride));
8602 CurStrides.push_back(DimProd);
8603 if (DI != DimSizes.end())
8607 CombinedInfo.NonContigInfo.Offsets.push_back(CurOffsets);
8608 CombinedInfo.NonContigInfo.Counts.push_back(CurCounts);
8609 CombinedInfo.NonContigInfo.Strides.push_back(CurStrides);
8615 OpenMPOffloadMappingFlags
8616 getMapModifiersForPrivateClauses(
const CapturedStmt::Capture &Cap)
const {
8624 return OpenMPOffloadMappingFlags::OMP_MAP_TO |
8625 OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ;
8626 return OpenMPOffloadMappingFlags::OMP_MAP_PRIVATE |
8627 OpenMPOffloadMappingFlags::OMP_MAP_TO;
8630 if (I != LambdasMap.end())
8632 return getMapTypeBits(
8633 I->getSecond()->getMapType(), I->getSecond()->getMapTypeModifiers(),
8634 {}, I->getSecond()->isImplicit(),
8638 return OpenMPOffloadMappingFlags::OMP_MAP_TO |
8639 OpenMPOffloadMappingFlags::OMP_MAP_FROM;
8642 void getPlainLayout(
const CXXRecordDecl *RD,
8643 llvm::SmallVectorImpl<const FieldDecl *> &Layout,
8644 bool AsBase)
const {
8647 llvm::StructType *St =
8650 unsigned NumElements = St->getNumElements();
8652 llvm::PointerUnion<const CXXRecordDecl *, const FieldDecl *>, 4>
8653 RecordLayout(NumElements);
8656 for (
const auto &I : RD->
bases()) {
8660 QualType BaseTy = I.getType();
8671 RecordLayout[FieldIndex] =
Base;
8674 for (
const auto &I : RD->
vbases()) {
8675 QualType BaseTy = I.getType();
8682 if (RecordLayout[FieldIndex])
8684 RecordLayout[FieldIndex] =
Base;
8687 assert(!RD->
isUnion() &&
"Unexpected union.");
8688 for (
const auto *Field : RD->
fields()) {
8691 if (!
Field->isBitField() &&
8694 RecordLayout[FieldIndex] =
Field;
8697 for (
const llvm::PointerUnion<const CXXRecordDecl *, const FieldDecl *>
8698 &
Data : RecordLayout) {
8701 if (
const auto *Base = dyn_cast<const CXXRecordDecl *>(
Data))
8702 getPlainLayout(Base, Layout,
true);
8709 static Address getAttachPtrAddr(
const Expr *PointerExpr,
8710 CodeGenFunction &CGF) {
8711 assert(PointerExpr &&
"Cannot get addr from null attach-ptr expr");
8714 if (
auto *DRE = dyn_cast<DeclRefExpr>(PointerExpr)) {
8717 }
else if (
auto *OASE = dyn_cast<ArraySectionExpr>(PointerExpr)) {
8720 }
else if (
auto *ASE = dyn_cast<ArraySubscriptExpr>(PointerExpr)) {
8722 }
else if (
auto *ME = dyn_cast<MemberExpr>(PointerExpr)) {
8724 }
else if (
auto *UO = dyn_cast<UnaryOperator>(PointerExpr)) {
8725 assert(UO->getOpcode() == UO_Deref &&
8726 "Unexpected unary-operator on attach-ptr-expr");
8729 assert(AttachPtrAddr.
isValid() &&
8730 "Failed to get address for attach pointer expression");
8731 return AttachPtrAddr;
8738 static std::pair<Address, Address>
8739 getAttachPtrAddrAndPteeBaseAddr(
const Expr *AttachPtrExpr,
8740 CodeGenFunction &CGF) {
8745 Address AttachPtrAddr = getAttachPtrAddr(AttachPtrExpr, CGF);
8746 assert(AttachPtrAddr.
isValid() &&
"Invalid attach pointer addr");
8748 QualType AttachPtrType =
8753 AttachPtrAddr, AttachPtrType->
castAs<PointerType>());
8754 assert(AttachPteeBaseAddr.
isValid() &&
"Invalid attach pointee base addr");
8756 return {AttachPtrAddr, AttachPteeBaseAddr};
8762 shouldEmitAttachEntry(
const Expr *PointerExpr,
const ValueDecl *MapBaseDecl,
8763 CodeGenFunction &CGF,
8764 llvm::PointerUnion<
const OMPExecutableDirective *,
8765 const OMPDeclareMapperDecl *>
8775 ->getDirectiveKind());
8784 void collectAttachPtrExprInfo(
8786 llvm::PointerUnion<
const OMPExecutableDirective *,
8787 const OMPDeclareMapperDecl *>
8792 ? OMPD_declare_mapper
8795 const auto &[AttachPtrExpr, Depth] =
8799 AttachPtrComputationOrderMap.try_emplace(
8800 AttachPtrExpr, AttachPtrComputationOrderMap.size());
8801 AttachPtrComponentDepthMap.try_emplace(AttachPtrExpr, Depth);
8802 AttachPtrExprMap.try_emplace(Components, AttachPtrExpr);
8810 void generateAllInfoForClauses(
8811 ArrayRef<const OMPClause *> Clauses, MapCombinedInfoTy &CombinedInfo,
8812 llvm::OpenMPIRBuilder &OMPBuilder,
8813 const llvm::DenseSet<CanonicalDeclPtr<const Decl>> &SkipVarSet =
8814 llvm::DenseSet<CanonicalDeclPtr<const Decl>>())
const {
8819 llvm::MapVector<CanonicalDeclPtr<const Decl>,
8820 SmallVector<SmallVector<MapInfo, 8>, 4>>
8826 [&Info, &SkipVarSet](
8827 const ValueDecl *D, MapKind
Kind,
8830 ArrayRef<OpenMPMapModifierKind> MapModifiers,
8831 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
8832 bool ReturnDevicePointer,
bool IsImplicit,
const ValueDecl *Mapper,
8833 const Expr *VarRef =
nullptr,
bool ForDeviceAddr =
false) {
8834 if (SkipVarSet.contains(D))
8836 auto It = Info.try_emplace(D, Total).first;
8837 It->second[
Kind].emplace_back(
8838 L, MapType, MapModifiers, MotionModifiers, ReturnDevicePointer,
8839 IsImplicit, Mapper, VarRef, ForDeviceAddr);
8842 for (
const auto *
Cl : Clauses) {
8843 const auto *
C = dyn_cast<OMPMapClause>(
Cl);
8847 if (llvm::is_contained(
C->getMapTypeModifiers(),
8848 OMPC_MAP_MODIFIER_present))
8850 else if (
C->getMapType() == OMPC_MAP_alloc)
8852 const auto *EI =
C->getVarRefs().begin();
8853 for (
const auto L :
C->component_lists()) {
8854 const Expr *E = (
C->getMapLoc().isValid()) ? *EI :
nullptr;
8855 InfoGen(std::get<0>(L), Kind, std::get<1>(L),
C->getMapType(),
8856 C->getMapTypeModifiers(), {},
8857 false,
C->isImplicit(), std::get<2>(L),
8862 for (
const auto *
Cl : Clauses) {
8863 const auto *
C = dyn_cast<OMPToClause>(
Cl);
8867 if (llvm::is_contained(
C->getMotionModifiers(),
8868 OMPC_MOTION_MODIFIER_present))
8870 if (llvm::is_contained(
C->getMotionModifiers(),
8871 OMPC_MOTION_MODIFIER_iterator)) {
8872 if (
auto *IteratorExpr = dyn_cast<OMPIteratorExpr>(
8873 C->getIteratorModifier()->IgnoreParenImpCasts())) {
8874 const auto *VD =
cast<VarDecl>(IteratorExpr->getIteratorDecl(0));
8879 const auto *EI =
C->getVarRefs().begin();
8880 for (
const auto L :
C->component_lists()) {
8881 InfoGen(std::get<0>(L), Kind, std::get<1>(L), OMPC_MAP_to, {},
8882 C->getMotionModifiers(),
false,
8883 C->isImplicit(), std::get<2>(L), *EI);
8887 for (
const auto *
Cl : Clauses) {
8888 const auto *
C = dyn_cast<OMPFromClause>(
Cl);
8892 if (llvm::is_contained(
C->getMotionModifiers(),
8893 OMPC_MOTION_MODIFIER_present))
8895 if (llvm::is_contained(
C->getMotionModifiers(),
8896 OMPC_MOTION_MODIFIER_iterator)) {
8897 if (
auto *IteratorExpr = dyn_cast<OMPIteratorExpr>(
8898 C->getIteratorModifier()->IgnoreParenImpCasts())) {
8899 const auto *VD =
cast<VarDecl>(IteratorExpr->getIteratorDecl(0));
8904 const auto *EI =
C->getVarRefs().begin();
8905 for (
const auto L :
C->component_lists()) {
8906 InfoGen(std::get<0>(L), Kind, std::get<1>(L), OMPC_MAP_from, {},
8907 C->getMotionModifiers(),
8908 false,
C->isImplicit(), std::get<2>(L),
8921 MapCombinedInfoTy UseDeviceDataCombinedInfo;
8923 auto &&UseDeviceDataCombinedInfoGen =
8924 [&UseDeviceDataCombinedInfo](
const ValueDecl *VD, llvm::Value *Ptr,
8925 CodeGenFunction &CGF,
bool IsDevAddr) {
8926 UseDeviceDataCombinedInfo.Exprs.push_back(VD);
8927 UseDeviceDataCombinedInfo.BasePointers.emplace_back(Ptr);
8928 UseDeviceDataCombinedInfo.DevicePtrDecls.emplace_back(VD);
8929 UseDeviceDataCombinedInfo.DevicePointers.emplace_back(
8930 IsDevAddr ? DeviceInfoTy::Address : DeviceInfoTy::Pointer);
8936 UseDeviceDataCombinedInfo.Pointers.push_back(Ptr);
8937 UseDeviceDataCombinedInfo.Sizes.push_back(
8938 llvm::Constant::getNullValue(CGF.Int64Ty));
8939 UseDeviceDataCombinedInfo.Types.push_back(
8940 OpenMPOffloadMappingFlags::OMP_MAP_RETURN_PARAM);
8941 UseDeviceDataCombinedInfo.Mappers.push_back(
nullptr);
8945 [&UseDeviceDataCombinedInfoGen](
8946 CodeGenFunction &CGF,
const Expr *IE,
const ValueDecl *VD,
8949 bool IsDevAddr,
bool IEIsAttachPtrForDevAddr =
false) {
8953 if (IsDevAddr && !IEIsAttachPtrForDevAddr) {
8954 if (IE->isGLValue())
8961 bool TreatDevAddrAsDevPtr = IEIsAttachPtrForDevAddr;
8968 UseDeviceDataCombinedInfoGen(VD, Ptr, CGF, IsDevAddr &&
8969 !TreatDevAddrAsDevPtr);
8972 auto &&IsMapInfoExist = [&Info,
this](CodeGenFunction &CGF,
8973 const ValueDecl *VD,
const Expr *IE,
8974 const Expr *DesiredAttachPtrExpr,
8975 bool IsDevAddr) ->
bool {
8983 if (It != Info.end()) {
8985 for (
auto &
Data : It->second) {
8986 MapInfo *CI =
nullptr;
8990 auto *It = llvm::find_if(
Data, [&](
const MapInfo &MI) {
8991 if (MI.Components.back().getAssociatedDeclaration() != VD)
8994 const Expr *MapAttachPtr = getAttachPtrExpr(MI.Components);
8995 bool Match = AttachPtrComparator.areEqual(MapAttachPtr,
8996 DesiredAttachPtrExpr);
9000 if (It !=
Data.end())
9005 CI->ForDeviceAddr =
true;
9006 CI->ReturnDevicePointer =
true;
9010 auto PrevCI = std::next(CI->Components.rbegin());
9011 const auto *VarD = dyn_cast<VarDecl>(VD);
9012 const Expr *AttachPtrExpr = getAttachPtrExpr(CI->Components);
9013 if (CGF.CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory() ||
9015 !VD->getType().getNonReferenceType()->isPointerType() ||
9016 PrevCI == CI->Components.rend() ||
9018 VarD->hasLocalStorage() ||
9019 (isa_and_nonnull<DeclRefExpr>(AttachPtrExpr) &&
9021 CI->ForDeviceAddr = IsDevAddr;
9022 CI->ReturnDevicePointer =
true;
9040 for (
const auto *
Cl : Clauses) {
9041 const auto *
C = dyn_cast<OMPUseDevicePtrClause>(
Cl);
9044 for (
const auto L :
C->component_lists()) {
9047 assert(!Components.empty() &&
9048 "Not expecting empty list of components!");
9049 const ValueDecl *VD = Components.back().getAssociatedDeclaration();
9051 const Expr *IE = Components.back().getAssociatedExpression();
9059 const Expr *UDPOperandExpr =
9060 Components.front().getAssociatedExpression();
9061 if (IsMapInfoExist(CGF, VD, IE,
9065 MapInfoGen(CGF, IE, VD, Components,
false);
9069 llvm::SmallDenseSet<CanonicalDeclPtr<const Decl>, 4> Processed;
9070 for (
const auto *
Cl : Clauses) {
9071 const auto *
C = dyn_cast<OMPUseDeviceAddrClause>(
Cl);
9074 for (
const auto L :
C->component_lists()) {
9077 assert(!std::get<1>(L).empty() &&
9078 "Not expecting empty list of components!");
9079 const ValueDecl *VD = std::get<1>(L).back().getAssociatedDeclaration();
9080 if (!Processed.insert(VD).second)
9101 const Expr *UDAAttachPtrExpr = getAttachPtrExpr(Components);
9102 const Expr *IE = std::get<1>(L).back().getAssociatedExpression();
9103 assert((!UDAAttachPtrExpr || UDAAttachPtrExpr == IE) &&
9104 "use_device_addr operand has an attach-ptr, but does not match "
9105 "last component's expr.");
9106 if (IsMapInfoExist(CGF, VD, IE,
9110 MapInfoGen(CGF, IE, VD, Components,
9112 UDAAttachPtrExpr !=
nullptr);
9116 for (
const auto &
Data : Info) {
9117 MapCombinedInfoTy CurInfo;
9119 const ValueDecl *VD = cast_or_null<ValueDecl>(D);
9126 SmallVector<std::pair<const Expr *, MapInfo>, 16> AttachPtrMapInfoPairs;
9129 for (
const auto &M :
Data.second) {
9130 for (
const MapInfo &L : M) {
9131 assert(!L.Components.empty() &&
9132 "Not expecting declaration with no component lists.");
9134 const Expr *AttachPtrExpr = getAttachPtrExpr(L.Components);
9135 AttachPtrMapInfoPairs.emplace_back(AttachPtrExpr, L);
9140 llvm::stable_sort(AttachPtrMapInfoPairs,
9141 [
this](
const auto &LHS,
const auto &RHS) {
9142 return AttachPtrComparator(LHS.first, RHS.first);
9147 auto *It = AttachPtrMapInfoPairs.begin();
9148 while (It != AttachPtrMapInfoPairs.end()) {
9149 const Expr *AttachPtrExpr = It->first;
9151 SmallVector<MapInfo, 8> GroupLists;
9152 while (It != AttachPtrMapInfoPairs.end() &&
9153 (It->first == AttachPtrExpr ||
9154 AttachPtrComparator.areEqual(It->first, AttachPtrExpr))) {
9155 GroupLists.push_back(It->second);
9158 assert(!GroupLists.empty() &&
"GroupLists should not be empty");
9160 StructRangeInfoTy PartialStruct;
9161 AttachInfoTy AttachInfo;
9162 MapCombinedInfoTy GroupCurInfo;
9164 MapCombinedInfoTy GroupStructBaseCurInfo;
9165 for (
const MapInfo &L : GroupLists) {
9167 unsigned CurrentBasePointersIdx = GroupCurInfo.BasePointers.size();
9168 unsigned StructBasePointersIdx =
9169 GroupStructBaseCurInfo.BasePointers.size();
9171 GroupCurInfo.NonContigInfo.IsNonContiguous =
9172 L.Components.back().isNonContiguous();
9173 generateInfoForComponentList(
9174 L.MapType, L.MapModifiers, L.MotionModifiers, L.Components,
9175 GroupCurInfo, GroupStructBaseCurInfo, PartialStruct, AttachInfo,
9176 false, L.IsImplicit,
9177 true, L.Mapper, L.ForDeviceAddr, VD,
9182 if (L.ReturnDevicePointer) {
9186 assert((CurrentBasePointersIdx < GroupCurInfo.BasePointers.size() ||
9187 StructBasePointersIdx <
9188 GroupStructBaseCurInfo.BasePointers.size()) &&
9189 "Unexpected number of mapped base pointers.");
9192 const ValueDecl *RelevantVD =
9193 L.Components.back().getAssociatedDeclaration();
9194 assert(RelevantVD &&
9195 "No relevant declaration related with device pointer??");
9202 if (StructBasePointersIdx <
9203 GroupStructBaseCurInfo.BasePointers.size()) {
9204 GroupStructBaseCurInfo.DevicePtrDecls[StructBasePointersIdx] =
9206 GroupStructBaseCurInfo.DevicePointers[StructBasePointersIdx] =
9207 L.ForDeviceAddr ? DeviceInfoTy::Address
9208 : DeviceInfoTy::Pointer;
9209 GroupStructBaseCurInfo.Types[StructBasePointersIdx] |=
9210 OpenMPOffloadMappingFlags::OMP_MAP_RETURN_PARAM;
9212 GroupCurInfo.DevicePtrDecls[CurrentBasePointersIdx] = RelevantVD;
9213 GroupCurInfo.DevicePointers[CurrentBasePointersIdx] =
9214 L.ForDeviceAddr ? DeviceInfoTy::Address
9215 : DeviceInfoTy::Pointer;
9216 GroupCurInfo.Types[CurrentBasePointersIdx] |=
9217 OpenMPOffloadMappingFlags::OMP_MAP_RETURN_PARAM;
9224 MapCombinedInfoTy GroupUnionCurInfo;
9225 GroupUnionCurInfo.append(GroupStructBaseCurInfo);
9226 GroupUnionCurInfo.append(GroupCurInfo);
9230 if (PartialStruct.Base.isValid()) {
9238 GroupUnionCurInfo.NonContigInfo.Dims.insert(
9239 GroupUnionCurInfo.NonContigInfo.Dims.begin(), 1);
9241 CurInfo, GroupUnionCurInfo.Types, PartialStruct, AttachInfo,
9242 !VD, OMPBuilder, VD,
9243 CombinedInfo.BasePointers.size(),
9249 CurInfo.append(GroupUnionCurInfo);
9250 if (AttachInfo.isValid())
9251 emitAttachEntry(CGF, CurInfo, AttachInfo);
9255 CombinedInfo.append(CurInfo);
9258 CombinedInfo.append(UseDeviceDataCombinedInfo);
9262 MappableExprsHandler(
const OMPExecutableDirective &Dir, CodeGenFunction &CGF)
9263 : CurDir(&Dir), CGF(CGF), AttachPtrComparator(*this) {
9265 for (
const auto *
C : Dir.getClausesOfKind<OMPFirstprivateClause>())
9266 for (
const auto *D :
C->varlist())
9267 FirstPrivateDecls.try_emplace(
9270 for (
const auto *
C : Dir.getClausesOfKind<OMPUsesAllocatorsClause>()) {
9271 for (unsigned I = 0, E = C->getNumberOfAllocators(); I < E; ++I) {
9272 OMPUsesAllocatorsClause::Data D = C->getAllocatorData(I);
9273 if (const auto *DRE = dyn_cast_or_null<DeclRefExpr>(D.AllocatorTraits))
9274 FirstPrivateDecls.try_emplace(cast<VarDecl>(DRE->getDecl()),
9276 else if (const auto *VD = dyn_cast<VarDecl>(
9277 cast<DeclRefExpr>(D.Allocator->IgnoreParenImpCasts())
9279 FirstPrivateDecls.try_emplace(VD, true);
9283 for (
const auto *
C : Dir.getClausesOfKind<OMPDefaultmapClause>())
9284 if (
C->getDefaultmapModifier() == OMPC_DEFAULTMAP_MODIFIER_firstprivate)
9285 DefaultmapFirstprivateKinds.insert(
C->getDefaultmapKind());
9287 for (
const auto *
C : Dir.getClausesOfKind<OMPIsDevicePtrClause>())
9288 for (
auto L :
C->component_lists())
9289 DevPointersMap[std::get<0>(L)].push_back(std::get<1>(L));
9291 for (
const auto *
C : Dir.getClausesOfKind<OMPHasDeviceAddrClause>())
9292 for (
auto L :
C->component_lists())
9293 HasDevAddrsMap[std::get<0>(L)].push_back(std::get<1>(L));
9295 for (
const auto *
C : Dir.getClausesOfKind<OMPMapClause>()) {
9296 if (C->getMapType() != OMPC_MAP_to)
9298 for (auto L : C->component_lists()) {
9299 const ValueDecl *VD = std::get<0>(L);
9300 const auto *RD = VD ? VD->getType()
9302 .getNonReferenceType()
9303 ->getAsCXXRecordDecl()
9305 if (RD && RD->isLambda())
9306 LambdasMap.try_emplace(std::get<0>(L), C);
9310 auto CollectAttachPtrExprsForClauseComponents = [
this](
const auto *
C) {
9311 for (
auto L :
C->component_lists()) {
9314 if (!Components.empty())
9315 collectAttachPtrExprInfo(Components, CurDir);
9321 for (
const auto *
C : Dir.getClausesOfKind<OMPMapClause>())
9322 CollectAttachPtrExprsForClauseComponents(
C);
9323 for (
const auto *
C : Dir.getClausesOfKind<OMPToClause>())
9324 CollectAttachPtrExprsForClauseComponents(
C);
9325 for (
const auto *
C : Dir.getClausesOfKind<OMPFromClause>())
9326 CollectAttachPtrExprsForClauseComponents(
C);
9327 for (
const auto *
C : Dir.getClausesOfKind<OMPUseDevicePtrClause>())
9328 CollectAttachPtrExprsForClauseComponents(
C);
9329 for (
const auto *
C : Dir.getClausesOfKind<OMPUseDeviceAddrClause>())
9330 CollectAttachPtrExprsForClauseComponents(
C);
9331 for (
const auto *
C : Dir.getClausesOfKind<OMPIsDevicePtrClause>())
9332 CollectAttachPtrExprsForClauseComponents(
C);
9333 for (
const auto *
C : Dir.getClausesOfKind<OMPHasDeviceAddrClause>())
9334 CollectAttachPtrExprsForClauseComponents(
C);
9338 MappableExprsHandler(
const OMPDeclareMapperDecl &Dir,
CodeGenFunction &CGF)
9339 : CurDir(&Dir), CGF(CGF), AttachPtrComparator(*this) {}
9349 void emitCombinedEntry(MapCombinedInfoTy &CombinedInfo,
9350 MapFlagsArrayTy &CurTypes,
9351 const StructRangeInfoTy &PartialStruct,
9352 AttachInfoTy &AttachInfo,
bool IsMapThis,
9353 llvm::OpenMPIRBuilder &OMPBuilder,
const ValueDecl *VD,
9354 unsigned OffsetForMemberOfFlag,
9355 bool NotTargetParams)
const {
9356 if (CurTypes.size() == 1 &&
9357 ((CurTypes.back() & OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF) !=
9358 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF) &&
9359 !PartialStruct.IsArraySection)
9361 Address LBAddr = PartialStruct.LowestElem.second;
9362 Address HBAddr = PartialStruct.HighestElem.second;
9363 if (PartialStruct.HasCompleteRecord) {
9364 LBAddr = PartialStruct.LB;
9365 HBAddr = PartialStruct.LB;
9367 CombinedInfo.Exprs.push_back(VD);
9369 CombinedInfo.BasePointers.push_back(PartialStruct.Base.emitRawPointer(CGF));
9370 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
9371 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
9374 const CXXMethodDecl *MD =
9376 const CXXRecordDecl *RD = MD ? MD->
getParent() :
nullptr;
9377 bool HasBaseClass = RD && IsMapThis ? RD->
getNumBases() > 0 :
false;
9387 CombinedInfo.Pointers.push_back(PartialStruct.Base.emitRawPointer(CGF));
9392 CombinedInfo.Sizes.push_back(Size);
9394 CombinedInfo.Pointers.push_back(LB);
9397 llvm::Value *HAddr = CGF.
Builder.CreateConstGEP1_32(
9401 llvm::Value *Diff = CGF.
Builder.CreatePtrDiff(CGF.
Int8Ty, CHAddr, CLAddr);
9404 CombinedInfo.Sizes.push_back(Size);
9406 CombinedInfo.Mappers.push_back(
nullptr);
9408 CombinedInfo.Types.push_back(
9409 NotTargetParams ? OpenMPOffloadMappingFlags::OMP_MAP_NONE
9410 : !PartialStruct.PreliminaryMapData.BasePointers.empty()
9411 ? OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ
9412 : OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM);
9415 if (CurTypes.end() !=
9416 llvm::find_if(CurTypes, [](OpenMPOffloadMappingFlags
Type) {
9417 return static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>>(
9418 Type & OpenMPOffloadMappingFlags::OMP_MAP_PRESENT);
9420 CombinedInfo.Types.back() |= OpenMPOffloadMappingFlags::OMP_MAP_PRESENT;
9422 (*CurTypes.begin()) &= ~OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM;
9429 if (CurTypes.end() !=
9430 llvm::find_if(CurTypes, [](OpenMPOffloadMappingFlags
Type) {
9431 return static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>>(
9432 Type & OpenMPOffloadMappingFlags::OMP_MAP_OMPX_HOLD);
9434 CombinedInfo.Types.back() |= OpenMPOffloadMappingFlags::OMP_MAP_OMPX_HOLD;
9435 for (
auto &M : CurTypes)
9436 M |= OpenMPOffloadMappingFlags::OMP_MAP_OMPX_HOLD;
9443 OpenMPOffloadMappingFlags MemberOfFlag = OMPBuilder.getMemberOfFlag(
9444 OffsetForMemberOfFlag + CombinedInfo.BasePointers.size() - 1);
9445 for (
auto &M : CurTypes)
9446 OMPBuilder.setCorrectMemberOfFlag(M, MemberOfFlag);
9463 if (AttachInfo.isValid())
9464 AttachInfo.AttachPteeAddr = LBAddr;
9472 void generateAllInfo(
9473 MapCombinedInfoTy &CombinedInfo, llvm::OpenMPIRBuilder &OMPBuilder,
9474 const llvm::DenseSet<CanonicalDeclPtr<const Decl>> &SkipVarSet =
9475 llvm::DenseSet<CanonicalDeclPtr<const Decl>>())
const {
9477 "Expect a executable directive");
9479 generateAllInfoForClauses(CurExecDir->clauses(), CombinedInfo, OMPBuilder,
9486 void generateAllInfoForMapper(MapCombinedInfoTy &CombinedInfo,
9487 llvm::OpenMPIRBuilder &OMPBuilder)
const {
9489 "Expect a declare mapper directive");
9491 generateAllInfoForClauses(CurMapperDir->clauses(), CombinedInfo,
9496 void generateInfoForLambdaCaptures(
9497 const ValueDecl *VD, llvm::Value *Arg, MapCombinedInfoTy &CombinedInfo,
9498 llvm::DenseMap<llvm::Value *, llvm::Value *> &LambdaPointers)
const {
9506 llvm::DenseMap<const ValueDecl *, FieldDecl *> Captures;
9507 FieldDecl *ThisCapture =
nullptr;
9513 LambdaPointers.try_emplace(ThisLVal.getPointer(CGF),
9514 VDLVal.getPointer(CGF));
9515 CombinedInfo.Exprs.push_back(VD);
9516 CombinedInfo.BasePointers.push_back(ThisLVal.getPointer(CGF));
9517 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
9518 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
9519 CombinedInfo.Pointers.push_back(ThisLValVal.getPointer(CGF));
9520 CombinedInfo.Sizes.push_back(
9523 CombinedInfo.Types.push_back(
9524 OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ |
9525 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL |
9526 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF |
9527 OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT);
9528 CombinedInfo.Mappers.push_back(
nullptr);
9530 for (
const LambdaCapture &LC : RD->
captures()) {
9531 if (!LC.capturesVariable())
9536 auto It = Captures.find(VD);
9537 assert(It != Captures.end() &&
"Found lambda capture without field.");
9541 LambdaPointers.try_emplace(VarLVal.getPointer(CGF),
9542 VDLVal.getPointer(CGF));
9543 CombinedInfo.Exprs.push_back(VD);
9544 CombinedInfo.BasePointers.push_back(VarLVal.getPointer(CGF));
9545 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
9546 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
9547 CombinedInfo.Pointers.push_back(VarLValVal.getPointer(CGF));
9548 CombinedInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
9554 LambdaPointers.try_emplace(VarLVal.getPointer(CGF),
9555 VDLVal.getPointer(CGF));
9556 CombinedInfo.Exprs.push_back(VD);
9557 CombinedInfo.BasePointers.push_back(VarLVal.getPointer(CGF));
9558 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
9559 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
9560 CombinedInfo.Pointers.push_back(VarRVal.
getScalarVal());
9561 CombinedInfo.Sizes.push_back(llvm::ConstantInt::get(CGF.
Int64Ty, 0));
9563 CombinedInfo.Types.push_back(
9564 OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ |
9565 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL |
9566 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF |
9567 OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT);
9568 CombinedInfo.Mappers.push_back(
nullptr);
9573 void adjustMemberOfForLambdaCaptures(
9574 llvm::OpenMPIRBuilder &OMPBuilder,
9575 const llvm::DenseMap<llvm::Value *, llvm::Value *> &LambdaPointers,
9576 MapBaseValuesArrayTy &BasePointers, MapValuesArrayTy &Pointers,
9577 MapFlagsArrayTy &Types)
const {
9578 for (
unsigned I = 0, E = Types.size(); I < E; ++I) {
9580 if (Types[I] != (OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ |
9581 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL |
9582 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF |
9583 OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT))
9585 llvm::Value *BasePtr = LambdaPointers.lookup(BasePointers[I]);
9586 assert(BasePtr &&
"Unable to find base lambda address.");
9588 for (
unsigned J = I; J > 0; --J) {
9589 unsigned Idx = J - 1;
9590 if (Pointers[Idx] != BasePtr)
9595 assert(TgtIdx != -1 &&
"Unable to find parent lambda.");
9599 OpenMPOffloadMappingFlags MemberOfFlag =
9600 OMPBuilder.getMemberOfFlag(TgtIdx);
9601 OMPBuilder.setCorrectMemberOfFlag(Types[I], MemberOfFlag);
9607 void populateComponentListsForNonLambdaCaptureFromClauses(
9608 const ValueDecl *VD, MapDataArrayTy &DeclComponentLists,
9610 SmallVector<OMPClauseMappableExprCommon::MappableComponent, 8>>
9611 &StorageForImplicitlyAddedComponentLists)
const {
9612 if (VD && LambdasMap.count(VD))
9618 auto It = DevPointersMap.find(VD);
9619 if (It != DevPointersMap.end())
9620 for (
const auto &MCL : It->second)
9621 DeclComponentLists.emplace_back(MCL, OMPC_MAP_to,
Unknown,
9624 auto I = HasDevAddrsMap.find(VD);
9625 if (I != HasDevAddrsMap.end())
9626 for (
const auto &MCL : I->second)
9627 DeclComponentLists.emplace_back(MCL, OMPC_MAP_tofrom,
Unknown,
9631 "Expect a executable directive");
9633 for (
const auto *
C : CurExecDir->getClausesOfKind<OMPMapClause>()) {
9634 const auto *EI =
C->getVarRefs().begin();
9635 for (
const auto L :
C->decl_component_lists(VD)) {
9636 const ValueDecl *VDecl, *Mapper;
9638 const Expr *E = (
C->getMapLoc().isValid()) ? *EI :
nullptr;
9640 std::tie(VDecl, Components, Mapper) = L;
9641 assert(VDecl == VD &&
"We got information for the wrong declaration??");
9642 assert(!Components.empty() &&
9643 "Not expecting declaration with no component lists.");
9644 DeclComponentLists.emplace_back(Components,
C->getMapType(),
9645 C->getMapTypeModifiers(),
9646 C->isImplicit(), Mapper, E);
9655 addImplicitMapForAttachPtrBaseIfMemberOfCapturedVD(
9656 VD, DeclComponentLists, StorageForImplicitlyAddedComponentLists);
9658 llvm::stable_sort(DeclComponentLists, [](
const MapData &LHS,
9659 const MapData &RHS) {
9660 ArrayRef<OpenMPMapModifierKind> MapModifiers = std::get<2>(LHS);
9663 llvm::is_contained(MapModifiers, clang::OMPC_MAP_MODIFIER_present);
9664 bool HasAllocs = MapType == OMPC_MAP_alloc;
9665 MapModifiers = std::get<2>(RHS);
9666 MapType = std::get<1>(LHS);
9668 llvm::is_contained(MapModifiers, clang::OMPC_MAP_MODIFIER_present);
9669 bool HasAllocsR = MapType == OMPC_MAP_alloc;
9670 return (HasPresent && !HasPresentR) || (HasAllocs && !HasAllocsR);
9706 void addImplicitMapForAttachPtrBaseIfMemberOfCapturedVD(
9707 const ValueDecl *CapturedVD, MapDataArrayTy &DeclComponentLists,
9709 SmallVector<OMPClauseMappableExprCommon::MappableComponent, 8>>
9710 &ComponentVectorStorage)
const {
9711 bool IsThisCapture = CapturedVD ==
nullptr;
9713 for (
const auto &ComponentsAndAttachPtr : AttachPtrExprMap) {
9715 ComponentsWithAttachPtr = ComponentsAndAttachPtr.first;
9716 const Expr *AttachPtrExpr = ComponentsAndAttachPtr.second;
9720 const auto *ME = dyn_cast<MemberExpr>(AttachPtrExpr);
9724 const Expr *
Base = ME->getBase()->IgnoreParenImpCasts();
9745 bool FoundExistingMap =
false;
9746 for (
const MapData &ExistingL : DeclComponentLists) {
9748 ExistingComponents = std::get<0>(ExistingL);
9750 if (ExistingComponents.empty())
9754 const auto &FirstComponent = ExistingComponents.front();
9755 const Expr *FirstExpr = FirstComponent.getAssociatedExpression();
9761 if (AttachPtrComparator.areEqual(FirstExpr, AttachPtrExpr)) {
9762 FoundExistingMap =
true;
9767 if (IsThisCapture) {
9768 if (
const auto *OASE = dyn_cast<ArraySectionExpr>(FirstExpr)) {
9770 FoundExistingMap =
true;
9779 if (
const auto *DRE = dyn_cast<DeclRefExpr>(FirstExpr)) {
9780 if (DRE->getDecl() == CapturedVD) {
9781 FoundExistingMap =
true;
9787 if (FoundExistingMap)
9793 ComponentVectorStorage.emplace_back();
9794 auto &AttachPtrComponents = ComponentVectorStorage.back();
9797 bool SeenAttachPtrComponent =
false;
9803 for (
size_t i = 0; i < ComponentsWithAttachPtr.size(); ++i) {
9804 const auto &Component = ComponentsWithAttachPtr[i];
9805 const Expr *ComponentExpr = Component.getAssociatedExpression();
9807 if (!SeenAttachPtrComponent && ComponentExpr != AttachPtrExpr)
9809 SeenAttachPtrComponent =
true;
9811 AttachPtrComponents.emplace_back(Component.getAssociatedExpression(),
9812 Component.getAssociatedDeclaration(),
9813 Component.isNonContiguous());
9815 assert(!AttachPtrComponents.empty() &&
9816 "Could not populate component-lists for mapping attach-ptr");
9818 DeclComponentLists.emplace_back(
9819 AttachPtrComponents, OMPC_MAP_tofrom,
Unknown,
9820 true,
nullptr, AttachPtrExpr);
9827 void generateInfoForCaptureFromClauseInfo(
9828 const MapDataArrayTy &DeclComponentListsFromClauses,
9829 const CapturedStmt::Capture *Cap, llvm::Value *Arg,
9830 MapCombinedInfoTy &CurCaptureVarInfo, llvm::OpenMPIRBuilder &OMPBuilder,
9831 unsigned OffsetForMemberOfFlag)
const {
9833 "Not expecting to generate map info for a variable array type!");
9842 if (LambdasMap.count(VD))
9848 if (VD && (DevPointersMap.count(VD) || HasDevAddrsMap.count(VD))) {
9849 CurCaptureVarInfo.Exprs.push_back(VD);
9850 CurCaptureVarInfo.BasePointers.emplace_back(Arg);
9851 CurCaptureVarInfo.DevicePtrDecls.emplace_back(VD);
9852 CurCaptureVarInfo.DevicePointers.emplace_back(DeviceInfoTy::Pointer);
9853 CurCaptureVarInfo.Pointers.push_back(Arg);
9854 CurCaptureVarInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
9857 CurCaptureVarInfo.Types.push_back(
9858 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL |
9859 OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM);
9860 CurCaptureVarInfo.Mappers.push_back(
nullptr);
9864 auto GenerateInfoForComponentLists =
9865 [&](ArrayRef<MapData> DeclComponentListsFromClauses,
9866 bool IsEligibleForTargetParamFlag) {
9867 MapCombinedInfoTy CurInfoForComponentLists;
9868 StructRangeInfoTy PartialStruct;
9869 AttachInfoTy AttachInfo;
9871 if (DeclComponentListsFromClauses.empty())
9874 generateInfoForCaptureFromComponentLists(
9875 VD, DeclComponentListsFromClauses, CurInfoForComponentLists,
9876 PartialStruct, AttachInfo, IsEligibleForTargetParamFlag);
9881 if (PartialStruct.Base.isValid()) {
9882 CurCaptureVarInfo.append(PartialStruct.PreliminaryMapData);
9884 CurCaptureVarInfo, CurInfoForComponentLists.Types,
9885 PartialStruct, AttachInfo, Cap->
capturesThis(), OMPBuilder,
9886 nullptr, OffsetForMemberOfFlag,
9887 !IsEligibleForTargetParamFlag);
9892 CurCaptureVarInfo.append(CurInfoForComponentLists);
9893 if (AttachInfo.isValid())
9894 emitAttachEntry(CGF, CurCaptureVarInfo, AttachInfo);
9918 SmallVector<std::pair<const Expr *, MapData>, 16> AttachPtrMapDataPairs;
9920 for (
const MapData &L : DeclComponentListsFromClauses) {
9923 const Expr *AttachPtrExpr = getAttachPtrExpr(Components);
9924 AttachPtrMapDataPairs.emplace_back(AttachPtrExpr, L);
9928 llvm::stable_sort(AttachPtrMapDataPairs,
9929 [
this](
const auto &LHS,
const auto &RHS) {
9930 return AttachPtrComparator(LHS.first, RHS.first);
9933 bool NoDefaultMappingDoneForVD = CurCaptureVarInfo.BasePointers.empty();
9934 bool IsFirstGroup =
true;
9938 auto *It = AttachPtrMapDataPairs.begin();
9939 while (It != AttachPtrMapDataPairs.end()) {
9940 const Expr *AttachPtrExpr = It->first;
9942 MapDataArrayTy GroupLists;
9943 while (It != AttachPtrMapDataPairs.end() &&
9944 (It->first == AttachPtrExpr ||
9945 AttachPtrComparator.areEqual(It->first, AttachPtrExpr))) {
9946 GroupLists.push_back(It->second);
9949 assert(!GroupLists.empty() &&
"GroupLists should not be empty");
9954 bool IsEligibleForTargetParamFlag =
9955 IsFirstGroup && NoDefaultMappingDoneForVD;
9957 GenerateInfoForComponentLists(GroupLists, IsEligibleForTargetParamFlag);
9958 IsFirstGroup =
false;
9965 void generateInfoForCaptureFromComponentLists(
9966 const ValueDecl *VD, ArrayRef<MapData> DeclComponentLists,
9967 MapCombinedInfoTy &CurComponentListInfo, StructRangeInfoTy &PartialStruct,
9968 AttachInfoTy &AttachInfo,
bool IsListEligibleForTargetParamFlag)
const {
9970 llvm::SmallDenseMap<
9977 for (
const MapData &L : DeclComponentLists) {
9980 ArrayRef<OpenMPMapModifierKind> MapModifiers;
9982 const ValueDecl *Mapper;
9984 std::tie(Components, MapType, MapModifiers, IsImplicit, Mapper, VarRef) =
9987 for (
const MapData &L1 : ArrayRef(DeclComponentLists).slice(Count)) {
9989 std::tie(Components1, MapType, MapModifiers, IsImplicit, Mapper,
9991 auto CI = Components.rbegin();
9992 auto CE = Components.rend();
9993 auto SI = Components1.rbegin();
9994 auto SE = Components1.rend();
9995 for (; CI != CE && SI != SE; ++CI, ++SI) {
9996 if (CI->getAssociatedExpression()->getStmtClass() !=
9997 SI->getAssociatedExpression()->getStmtClass())
10000 if (CI->getAssociatedDeclaration() != SI->getAssociatedDeclaration())
10005 if (CI == CE || SI == SE) {
10007 if (CI == CE && SI == SE)
10009 const auto It = (SI == SE) ? CI : SI;
10016 (std::prev(It)->getAssociatedDeclaration() &&
10018 ->getAssociatedDeclaration()
10020 ->isPointerType()) ||
10021 (It->getAssociatedDeclaration() &&
10022 It->getAssociatedDeclaration()->getType()->isPointerType() &&
10023 std::next(It) != CE && std::next(It) != SE))
10025 const MapData &BaseData = CI == CE ? L : L1;
10027 SI == SE ? Components : Components1;
10028 OverlappedData[&BaseData].push_back(SubData);
10033 llvm::SmallVector<const FieldDecl *, 4> Layout;
10034 if (!OverlappedData.empty()) {
10037 while (BaseType != OrigType) {
10043 getPlainLayout(CRD, Layout,
false);
10049 for (
auto &Pair : OverlappedData) {
10056 auto CI = First.rbegin();
10057 auto CE = First.rend();
10058 auto SI = Second.rbegin();
10059 auto SE = Second.rend();
10060 for (; CI != CE && SI != SE; ++CI, ++SI) {
10061 if (CI->getAssociatedExpression()->getStmtClass() !=
10062 SI->getAssociatedExpression()->getStmtClass())
10065 if (CI->getAssociatedDeclaration() !=
10066 SI->getAssociatedDeclaration())
10071 if (CI == CE && SI == SE)
10075 if (CI == CE || SI == SE)
10080 if (FD1->getParent() == FD2->getParent())
10081 return FD1->getFieldIndex() < FD2->getFieldIndex();
10083 llvm::find_if(Layout, [FD1, FD2](
const FieldDecl *FD) {
10084 return FD == FD1 || FD == FD2;
10092 bool AddTargetParamFlag = IsListEligibleForTargetParamFlag;
10093 MapCombinedInfoTy StructBaseCombinedInfo;
10094 for (
const auto &Pair : OverlappedData) {
10095 const MapData &L = *Pair.getFirst();
10098 ArrayRef<OpenMPMapModifierKind> MapModifiers;
10100 const ValueDecl *Mapper;
10101 const Expr *VarRef;
10102 std::tie(Components, MapType, MapModifiers, IsImplicit, Mapper, VarRef) =
10104 ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef>
10105 OverlappedComponents = Pair.getSecond();
10106 generateInfoForComponentList(
10107 MapType, MapModifiers, {}, Components, CurComponentListInfo,
10108 StructBaseCombinedInfo, PartialStruct, AttachInfo, AddTargetParamFlag,
10109 IsImplicit,
false, Mapper,
10110 false, VD, VarRef, OverlappedComponents);
10111 AddTargetParamFlag =
false;
10114 for (
const MapData &L : DeclComponentLists) {
10117 ArrayRef<OpenMPMapModifierKind> MapModifiers;
10119 const ValueDecl *Mapper;
10120 const Expr *VarRef;
10121 std::tie(Components, MapType, MapModifiers, IsImplicit, Mapper, VarRef) =
10123 auto It = OverlappedData.find(&L);
10124 if (It == OverlappedData.end())
10125 generateInfoForComponentList(
10126 MapType, MapModifiers, {}, Components, CurComponentListInfo,
10127 StructBaseCombinedInfo, PartialStruct, AttachInfo,
10128 AddTargetParamFlag, IsImplicit,
false,
10129 Mapper,
false, VD, VarRef,
10131 AddTargetParamFlag =
false;
10137 bool isEffectivelyFirstprivate(
const VarDecl *VD, QualType
Type)
const {
10139 auto I = FirstPrivateDecls.find(VD);
10140 if (I != FirstPrivateDecls.end() && !I->getSecond())
10144 if (DefaultmapFirstprivateKinds.count(OMPC_DEFAULTMAP_scalar)) {
10145 if (
Type->isScalarType())
10150 if (DefaultmapFirstprivateKinds.count(OMPC_DEFAULTMAP_pointer)) {
10151 if (
Type->isAnyPointerType())
10156 if (DefaultmapFirstprivateKinds.count(OMPC_DEFAULTMAP_aggregate)) {
10157 if (
Type->isAggregateType())
10162 return DefaultmapFirstprivateKinds.count(OMPC_DEFAULTMAP_all);
10167 void generateDefaultMapInfo(
const CapturedStmt::Capture &CI,
10168 const FieldDecl &RI, llvm::Value *CV,
10169 MapCombinedInfoTy &CombinedInfo)
const {
10170 bool IsImplicit =
true;
10173 CombinedInfo.Exprs.push_back(
nullptr);
10174 CombinedInfo.BasePointers.push_back(CV);
10175 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
10176 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
10177 CombinedInfo.Pointers.push_back(CV);
10179 CombinedInfo.Sizes.push_back(
10183 CombinedInfo.Types.push_back(OpenMPOffloadMappingFlags::OMP_MAP_TO |
10184 OpenMPOffloadMappingFlags::OMP_MAP_FROM);
10188 CombinedInfo.BasePointers.push_back(CV);
10189 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
10190 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
10191 CombinedInfo.Pointers.push_back(CV);
10192 bool IsFirstprivate =
10198 CombinedInfo.Types.push_back(
10199 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL);
10200 CombinedInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
10202 }
else if (IsFirstprivate) {
10205 CombinedInfo.Types.push_back(
10206 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL);
10208 CombinedInfo.Sizes.push_back(llvm::Constant::getNullValue(CGF.
Int64Ty));
10212 CombinedInfo.Types.push_back(OpenMPOffloadMappingFlags::OMP_MAP_NONE);
10213 CombinedInfo.Sizes.push_back(llvm::Constant::getNullValue(CGF.
Int64Ty));
10215 auto I = FirstPrivateDecls.find(VD);
10216 if (I != FirstPrivateDecls.end())
10217 IsImplicit = I->getSecond();
10223 bool IsFirstprivate = isEffectivelyFirstprivate(VD, ElementType);
10225 CombinedInfo.BasePointers.push_back(CV);
10226 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
10227 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
10232 CombinedInfo.Pointers.push_back(CV);
10234 CombinedInfo.Sizes.push_back(llvm::Constant::getNullValue(CGF.
Int64Ty));
10235 CombinedInfo.Types.push_back(
10236 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL);
10238 CombinedInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
10243 CombinedInfo.Types.push_back(getMapModifiersForPrivateClauses(CI));
10244 CombinedInfo.Pointers.push_back(CV);
10246 auto I = FirstPrivateDecls.find(VD);
10247 if (I != FirstPrivateDecls.end())
10248 IsImplicit = I->getSecond();
10251 CombinedInfo.Types.back() |=
10252 OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM;
10256 CombinedInfo.Types.back() |= OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT;
10259 CombinedInfo.Mappers.push_back(
nullptr);
10271 dyn_cast<MemberExpr>(OASE->getBase()->IgnoreParenImpCasts()))
10272 return ME->getMemberDecl();
10278static llvm::Constant *
10280 MappableExprsHandler::MappingExprInfo &MapExprs) {
10282 uint32_t SrcLocStrSize;
10283 if (!MapExprs.getMapDecl() && !MapExprs.getMapExpr())
10284 return OMPBuilder.getOrCreateDefaultSrcLocStr(SrcLocStrSize);
10287 if (!MapExprs.getMapDecl() && MapExprs.getMapExpr()) {
10291 Loc = MapExprs.getMapExpr()->getExprLoc();
10293 Loc = MapExprs.getMapDecl()->getLocation();
10296 std::string ExprName;
10297 if (MapExprs.getMapExpr()) {
10299 llvm::raw_string_ostream OS(ExprName);
10300 MapExprs.getMapExpr()->printPretty(OS,
nullptr, P);
10302 ExprName = MapExprs.getMapDecl()->getNameAsString();
10311 return OMPBuilder.getOrCreateSrcLocStr(
FileName, ExprName, PLoc.
getLine(),
10318 CodeGenFunction &CGF, MappableExprsHandler::MapCombinedInfoTy &CombinedInfo,
10320 bool IsNonContiguous =
false,
bool ForEndCall =
false) {
10323 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
10326 InsertPointTy CodeGenIP(CGF.
Builder.GetInsertBlock(),
10327 CGF.
Builder.GetInsertPoint());
10329 auto DeviceAddrCB = [&](
unsigned int I, llvm::Value *NewDecl) {
10330 if (
const ValueDecl *DevVD = CombinedInfo.DevicePtrDecls[I]) {
10335 auto CustomMapperCB = [&](
unsigned int I) {
10336 llvm::Function *MFunc =
nullptr;
10337 if (CombinedInfo.Mappers[I]) {
10338 Info.HasMapper =
true;
10344 cantFail(OMPBuilder.emitOffloadingArraysAndArgs(
10345 AllocaIP, CodeGenIP, Info, Info.RTArgs, CombinedInfo, CustomMapperCB,
10346 IsNonContiguous, ForEndCall, DeviceAddrCB));
10350static const OMPExecutableDirective *
10352 const auto *CS = D.getInnermostCapturedStmt();
10355 const Stmt *ChildStmt =
10358 if (
const auto *NestedDir =
10359 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) {
10361 switch (D.getDirectiveKind()) {
10367 if (DKind == OMPD_teams) {
10368 Body = NestedDir->getInnermostCapturedStmt()->IgnoreContainers(
10373 if (
const auto *NND =
10374 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) {
10375 DKind = NND->getDirectiveKind();
10381 case OMPD_target_teams:
10385 case OMPD_target_parallel:
10386 case OMPD_target_simd:
10387 case OMPD_target_parallel_for:
10388 case OMPD_target_parallel_for_simd:
10390 case OMPD_target_teams_distribute:
10391 case OMPD_target_teams_distribute_simd:
10392 case OMPD_target_teams_distribute_parallel_for:
10393 case OMPD_target_teams_distribute_parallel_for_simd:
10394 case OMPD_parallel:
10396 case OMPD_parallel_for:
10397 case OMPD_parallel_master:
10398 case OMPD_parallel_sections:
10399 case OMPD_for_simd:
10400 case OMPD_parallel_for_simd:
10402 case OMPD_cancellation_point:
10404 case OMPD_threadprivate:
10405 case OMPD_allocate:
10410 case OMPD_sections:
10414 case OMPD_critical:
10415 case OMPD_taskyield:
10417 case OMPD_taskwait:
10418 case OMPD_taskgroup:
10424 case OMPD_target_data:
10425 case OMPD_target_exit_data:
10426 case OMPD_target_enter_data:
10427 case OMPD_distribute:
10428 case OMPD_distribute_simd:
10429 case OMPD_distribute_parallel_for:
10430 case OMPD_distribute_parallel_for_simd:
10431 case OMPD_teams_distribute:
10432 case OMPD_teams_distribute_simd:
10433 case OMPD_teams_distribute_parallel_for:
10434 case OMPD_teams_distribute_parallel_for_simd:
10435 case OMPD_target_update:
10436 case OMPD_declare_simd:
10437 case OMPD_declare_variant:
10438 case OMPD_begin_declare_variant:
10439 case OMPD_end_declare_variant:
10440 case OMPD_declare_target:
10441 case OMPD_end_declare_target:
10442 case OMPD_declare_reduction:
10443 case OMPD_declare_mapper:
10444 case OMPD_taskloop:
10445 case OMPD_taskloop_simd:
10446 case OMPD_master_taskloop:
10447 case OMPD_master_taskloop_simd:
10448 case OMPD_parallel_master_taskloop:
10449 case OMPD_parallel_master_taskloop_simd:
10450 case OMPD_requires:
10451 case OMPD_metadirective:
10454 llvm_unreachable(
"Unexpected directive.");
10495 if (
UDMMap.count(D) > 0)
10499 auto *MapperVarDecl =
10501 CharUnits ElementSize =
C.getTypeSizeInChars(Ty);
10502 llvm::Type *ElemTy =
CGM.getTypes().ConvertTypeForMem(Ty);
10505 MappableExprsHandler::MapCombinedInfoTy CombinedInfo;
10506 auto PrivatizeAndGenMapInfoCB =
10507 [&](llvm::OpenMPIRBuilder::InsertPointTy CodeGenIP, llvm::Value *PtrPHI,
10508 llvm::Value *BeginArg) -> llvm::OpenMPIRBuilder::MapInfosTy & {
10509 MapperCGF.
Builder.restoreIP(CodeGenIP);
10519 Scope.addPrivate(MapperVarDecl, PtrCurrent);
10520 (void)
Scope.Privatize();
10523 MappableExprsHandler MEHandler(*D, MapperCGF);
10524 MEHandler.generateAllInfoForMapper(CombinedInfo,
OMPBuilder);
10526 auto FillInfoMap = [&](MappableExprsHandler::MappingExprInfo &MapExpr) {
10529 if (
CGM.getCodeGenOpts().getDebugInfo() !=
10530 llvm::codegenoptions::NoDebugInfo) {
10531 CombinedInfo.Names.resize(CombinedInfo.Exprs.size());
10532 llvm::transform(CombinedInfo.Exprs, CombinedInfo.Names.begin(),
10536 return CombinedInfo;
10539 auto CustomMapperCB = [&](
unsigned I) {
10540 llvm::Function *MapperFunc =
nullptr;
10541 if (CombinedInfo.Mappers[I]) {
10545 assert(MapperFunc &&
"Expect a valid mapper function is available.");
10551 llvm::raw_svector_ostream Out(TyStr);
10552 CGM.getCXXABI().getMangleContext().mangleCanonicalTypeName(Ty, Out);
10553 std::string Name =
getName({
"omp_mapper", TyStr, D->
getName()});
10555 llvm::Function *NewFn = cantFail(
OMPBuilder.emitUserDefinedMapper(
10556 PrivatizeAndGenMapInfoCB, ElemTy, Name, CustomMapperCB));
10557 UDMMap.try_emplace(D, NewFn);
10564 auto I =
UDMMap.find(D);
10568 return UDMMap.lookup(D);
10581 Kind != OMPD_target_teams_loop)
10584 return llvm::ConstantInt::get(CGF.
Int64Ty, 0);
10587 if (llvm::Value *NumIterations = SizeEmitter(CGF, *LD))
10588 return NumIterations;
10589 return llvm::ConstantInt::get(CGF.
Int64Ty, 0);
10598 if (OffloadingMandatory) {
10599 CGF.
Builder.CreateUnreachable();
10601 if (RequiresOuterTask) {
10602 CapturedVars.clear();
10611 llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier>
Device,
10614 llvm::Value *DeviceID;
10615 if (
Device.getPointer()) {
10617 Device.getInt() == OMPC_DEVICE_device_num) &&
10618 "Expected device_num modifier.");
10623 DeviceID = CGF.
Builder.getInt64(OMP_DEVICEID_UNDEF);
10628static std::pair<llvm::Value *, OMPDynGroupprivateFallbackType>
10630 llvm::Value *DynGP = CGF.
Builder.getInt32(0);
10631 auto DynGPFallback = OMPDynGroupprivateFallbackType::Abort;
10635 llvm::Value *DynGPVal =
10639 auto FallbackModifier = DynGPClause->getDynGroupprivateFallbackModifier();
10640 switch (FallbackModifier) {
10641 case OMPC_DYN_GROUPPRIVATE_FALLBACK_abort:
10642 DynGPFallback = OMPDynGroupprivateFallbackType::Abort;
10644 case OMPC_DYN_GROUPPRIVATE_FALLBACK_null:
10645 DynGPFallback = OMPDynGroupprivateFallbackType::Null;
10647 case OMPC_DYN_GROUPPRIVATE_FALLBACK_default_mem:
10650 DynGPFallback = OMPDynGroupprivateFallbackType::DefaultMem;
10653 llvm_unreachable(
"Unknown fallback modifier for OpenMP dyn_groupprivate");
10655 }
else if (
auto *OMPXDynCGClause =
10658 llvm::Value *DynCGMemVal = CGF.
EmitScalarExpr(OMPXDynCGClause->getSize(),
10663 return {DynGP, DynGPFallback};
10669 llvm::OpenMPIRBuilder &OMPBuilder,
10671 MappableExprsHandler::MapCombinedInfoTy &CombinedInfo) {
10673 llvm::DenseMap<llvm::Value *, llvm::Value *> LambdaPointers;
10675 auto *CV = CapturedVars.begin();
10678 CI != CE; ++CI, ++RI, ++CV) {
10679 MappableExprsHandler::MapCombinedInfoTy CurInfo;
10684 CurInfo.Exprs.push_back(
nullptr);
10685 CurInfo.BasePointers.push_back(*CV);
10686 CurInfo.DevicePtrDecls.push_back(
nullptr);
10687 CurInfo.DevicePointers.push_back(
10688 MappableExprsHandler::DeviceInfoTy::None);
10689 CurInfo.Pointers.push_back(*CV);
10690 CurInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
10693 CurInfo.Types.push_back(OpenMPOffloadMappingFlags::OMP_MAP_LITERAL |
10694 OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM |
10695 OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT);
10696 CurInfo.Mappers.push_back(
nullptr);
10701 bool HasEntryWithCVAsAttachPtr =
false;
10703 HasEntryWithCVAsAttachPtr =
10704 MEHandler.hasAttachEntryForCapturedVar(CapturedVD);
10707 MappableExprsHandler::MapDataArrayTy DeclComponentLists;
10710 StorageForImplicitlyAddedComponentLists;
10711 MEHandler.populateComponentListsForNonLambdaCaptureFromClauses(
10712 CapturedVD, DeclComponentLists,
10713 StorageForImplicitlyAddedComponentLists);
10724 bool HasEntryWithoutAttachPtr =
10725 llvm::any_of(DeclComponentLists, [&](
const auto &MapData) {
10727 Components = std::get<0>(MapData);
10728 return !MEHandler.getAttachPtrExpr(Components);
10733 if (DeclComponentLists.empty() ||
10734 (!HasEntryWithCVAsAttachPtr && !HasEntryWithoutAttachPtr))
10735 MEHandler.generateDefaultMapInfo(*CI, **RI, *CV, CurInfo);
10739 MEHandler.generateInfoForCaptureFromClauseInfo(
10740 DeclComponentLists, CI, *CV, CurInfo, OMPBuilder,
10741 CombinedInfo.BasePointers.size());
10746 MappedVarSet.insert(
nullptr);
10751 MEHandler.generateInfoForLambdaCaptures(CI->
getCapturedVar(), *CV,
10752 CurInfo, LambdaPointers);
10755 assert(!CurInfo.BasePointers.empty() &&
10756 "Non-existing map pointer for capture!");
10757 assert(CurInfo.BasePointers.size() == CurInfo.Pointers.size() &&
10758 CurInfo.BasePointers.size() == CurInfo.Sizes.size() &&
10759 CurInfo.BasePointers.size() == CurInfo.Types.size() &&
10760 CurInfo.BasePointers.size() == CurInfo.Mappers.size() &&
10761 "Inconsistent map information sizes!");
10764 CombinedInfo.append(CurInfo);
10767 MEHandler.adjustMemberOfForLambdaCaptures(
10768 OMPBuilder, LambdaPointers, CombinedInfo.BasePointers,
10769 CombinedInfo.Pointers, CombinedInfo.Types);
10773 MappableExprsHandler::MapCombinedInfoTy &CombinedInfo,
10774 llvm::OpenMPIRBuilder &OMPBuilder,
10781 MEHandler.generateAllInfo(CombinedInfo, OMPBuilder, SkippedVarSet);
10783 auto FillInfoMap = [&](MappableExprsHandler::MappingExprInfo &MapExpr) {
10787 llvm::codegenoptions::NoDebugInfo) {
10788 CombinedInfo.Names.resize(CombinedInfo.Exprs.size());
10789 llvm::transform(CombinedInfo.Exprs, CombinedInfo.Names.begin(),
10797 llvm::OpenMPIRBuilder &OMPBuilder,
10798 MappableExprsHandler::MapCombinedInfoTy &CombinedInfo) {
10800 MappableExprsHandler MEHandler(D, CGF);
10801 llvm::DenseSet<CanonicalDeclPtr<const Decl>> MappedVarSet;
10804 MappedVarSet, CombinedInfo);
10805 genMapInfo(MEHandler, CGF, CombinedInfo, OMPBuilder, MappedVarSet);
10808template <
typename ClauseTy>
10813 const auto *
C = D.getSingleClause<ClauseTy>();
10814 assert(!
C->varlist_empty() &&
10815 "ompx_bare requires explicit num_teams and thread_limit");
10817 for (
auto *E :
C->varlist()) {
10829 llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier>
Device,
10831 llvm::Value *&MapTypesArray, llvm::Value *&MapNamesArray,
10836 llvm::OpenMPIRBuilder &OMPBuilder = OMPRuntime->
getOMPBuilder();
10839 MappableExprsHandler::MapCombinedInfoTy CombinedInfo;
10841 genMapInfo(D, CGF, CS, CapturedVars, OMPBuilder, CombinedInfo);
10855 MapTypesArray = Info.RTArgs.MapTypesArray;
10856 MapNamesArray = Info.RTArgs.MapNamesArray;
10858 auto &&ThenGen = [&OMPRuntime, OutlinedFn, &D, &CapturedVars,
10859 RequiresOuterTask, &CS, OffloadingMandatory,
Device,
10860 OutlinedFnID, &InputInfo, &MapTypesArray, &MapNamesArray,
10862 bool IsReverseOffloading =
Device.getInt() == OMPC_DEVICE_ancestor;
10864 if (IsReverseOffloading) {
10870 RequiresOuterTask, CS, OffloadingMandatory, CGF);
10874 bool HasNoWait = D.hasClausesOfKind<OMPNowaitClause>();
10875 unsigned NumTargetItems = InputInfo.NumberOfTargetItems;
10877 llvm::Value *BasePointersArray =
10878 InputInfo.BasePointersArray.emitRawPointer(CGF);
10879 llvm::Value *PointersArray = InputInfo.PointersArray.emitRawPointer(CGF);
10880 llvm::Value *SizesArray = InputInfo.SizesArray.emitRawPointer(CGF);
10881 llvm::Value *MappersArray = InputInfo.MappersArray.emitRawPointer(CGF);
10883 auto &&EmitTargetCallFallbackCB =
10884 [&OMPRuntime, OutlinedFn, &D, &CapturedVars, RequiresOuterTask, &CS,
10885 OffloadingMandatory, &CGF](llvm::OpenMPIRBuilder::InsertPointTy IP)
10886 -> llvm::OpenMPIRBuilder::InsertPointTy {
10889 RequiresOuterTask, CS, OffloadingMandatory, CGF);
10902 NumThreads.push_back(
10908 llvm::Value *NumIterations =
10911 llvm::OpenMPIRBuilder::InsertPointTy AllocaIP(
10914 llvm::OpenMPIRBuilder::TargetDataRTArgs RTArgs(
10915 BasePointersArray, PointersArray, SizesArray, MapTypesArray,
10916 nullptr , MappersArray, MapNamesArray);
10918 llvm::OpenMPIRBuilder::TargetKernelArgs Args(
10919 NumTargetItems, RTArgs, NumIterations, NumTeams, NumThreads,
10920 DynCGroupMem, HasNoWait, DynCGroupMemFallback);
10922 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
10924 CGF.
Builder, OutlinedFnID, EmitTargetCallFallbackCB, Args, DeviceID,
10926 CGF.
Builder.restoreIP(AfterIP);
10929 if (RequiresOuterTask)
10944 [&OMPRuntime, OutlinedFn, &D, &CapturedVars, RequiresOuterTask, &CS,
10947 RequiresOuterTask, CS, OffloadingMandatory, CGF);
10950 if (RequiresOuterTask) {
10960 llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID,
const Expr *IfCond,
10961 llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier>
Device,
10968 const bool OffloadingMandatory = !
CGM.getLangOpts().OpenMPIsTargetDevice &&
10969 CGM.getLangOpts().OpenMPOffloadMandatory;
10971 assert((OffloadingMandatory || OutlinedFn) &&
"Invalid outlined function!");
10973 const bool RequiresOuterTask =
10975 D.hasClausesOfKind<OMPNowaitClause>() ||
10976 D.hasClausesOfKind<OMPInReductionClause>() ||
10977 (
CGM.getLangOpts().OpenMP >= 51 &&
10981 const CapturedStmt &CS = *D.getCapturedStmt(OMPD_target);
10989 llvm::Value *MapTypesArray =
nullptr;
10990 llvm::Value *MapNamesArray =
nullptr;
10992 auto &&TargetThenGen = [
this, OutlinedFn, &D, &CapturedVars,
10993 RequiresOuterTask, &CS, OffloadingMandatory,
Device,
10994 OutlinedFnID, &InputInfo, &MapTypesArray,
10998 RequiresOuterTask, CS, OffloadingMandatory,
10999 Device, OutlinedFnID, InputInfo, MapTypesArray,
11000 MapNamesArray, SizeEmitter, CGF,
CGM);
11003 auto &&TargetElseGen =
11004 [
this, OutlinedFn, &D, &CapturedVars, RequiresOuterTask, &CS,
11007 CS, OffloadingMandatory, CGF);
11014 if (OutlinedFnID) {
11016 emitIfClause(CGF, IfCond, TargetThenGen, TargetElseGen);
11028 StringRef ParentName) {
11035 if (
auto *E = dyn_cast<OMPExecutableDirective>(S);
11044 bool RequiresDeviceCodegen =
11049 if (RequiresDeviceCodegen) {
11057 if (!
OMPBuilder.OffloadInfoManager.hasTargetRegionEntryInfo(EntryInfo))
11060 switch (E.getDirectiveKind()) {
11065 case OMPD_target_parallel:
11069 case OMPD_target_teams:
11073 case OMPD_target_teams_distribute:
11077 case OMPD_target_teams_distribute_simd:
11081 case OMPD_target_parallel_for:
11085 case OMPD_target_parallel_for_simd:
11089 case OMPD_target_simd:
11093 case OMPD_target_teams_distribute_parallel_for:
11098 case OMPD_target_teams_distribute_parallel_for_simd:
11104 case OMPD_target_teams_loop:
11108 case OMPD_target_parallel_loop:
11112 case OMPD_parallel:
11114 case OMPD_parallel_for:
11115 case OMPD_parallel_master:
11116 case OMPD_parallel_sections:
11117 case OMPD_for_simd:
11118 case OMPD_parallel_for_simd:
11120 case OMPD_cancellation_point:
11122 case OMPD_threadprivate:
11123 case OMPD_allocate:
11128 case OMPD_sections:
11132 case OMPD_critical:
11133 case OMPD_taskyield:
11135 case OMPD_taskwait:
11136 case OMPD_taskgroup:
11142 case OMPD_target_data:
11143 case OMPD_target_exit_data:
11144 case OMPD_target_enter_data:
11145 case OMPD_distribute:
11146 case OMPD_distribute_simd:
11147 case OMPD_distribute_parallel_for:
11148 case OMPD_distribute_parallel_for_simd:
11149 case OMPD_teams_distribute:
11150 case OMPD_teams_distribute_simd:
11151 case OMPD_teams_distribute_parallel_for:
11152 case OMPD_teams_distribute_parallel_for_simd:
11153 case OMPD_target_update:
11154 case OMPD_declare_simd:
11155 case OMPD_declare_variant:
11156 case OMPD_begin_declare_variant:
11157 case OMPD_end_declare_variant:
11158 case OMPD_declare_target:
11159 case OMPD_end_declare_target:
11160 case OMPD_declare_reduction:
11161 case OMPD_declare_mapper:
11162 case OMPD_taskloop:
11163 case OMPD_taskloop_simd:
11164 case OMPD_master_taskloop:
11165 case OMPD_master_taskloop_simd:
11166 case OMPD_parallel_master_taskloop:
11167 case OMPD_parallel_master_taskloop_simd:
11168 case OMPD_requires:
11169 case OMPD_metadirective:
11172 llvm_unreachable(
"Unknown target directive for OpenMP device codegen.");
11177 if (
const auto *E = dyn_cast<OMPExecutableDirective>(S)) {
11178 if (!E->hasAssociatedStmt() || !E->getAssociatedStmt())
11186 if (
const auto *L = dyn_cast<LambdaExpr>(S))
11195 std::optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
11196 OMPDeclareTargetDeclAttr::getDeviceType(VD);
11200 if (!IsDevice && DevTy == OMPDeclareTargetDeclAttr::DT_NoHost)
11203 if (IsDevice && DevTy == OMPDeclareTargetDeclAttr::DT_Host)
11211 if (!
CGM.getLangOpts().OpenMPIsTargetDevice) {
11212 if (
const auto *FD = dyn_cast<FunctionDecl>(GD.
getDecl()))
11214 CGM.getLangOpts().OpenMPIsTargetDevice))
11221 if (
const auto *FD = dyn_cast<FunctionDecl>(VD)) {
11222 StringRef Name =
CGM.getMangledName(GD);
11225 CGM.getLangOpts().OpenMPIsTargetDevice))
11230 return !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD) &&
11236 CGM.getLangOpts().OpenMPIsTargetDevice))
11239 if (!
CGM.getLangOpts().OpenMPIsTargetDevice)
11248 StringRef ParentName =
11253 StringRef ParentName =
11260 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
11261 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(
11263 if (!Res || *Res == OMPDeclareTargetDeclAttr::MT_Link ||
11264 ((*Res == OMPDeclareTargetDeclAttr::MT_To ||
11265 *Res == OMPDeclareTargetDeclAttr::MT_Enter) &&
11274 llvm::Constant *
Addr) {
11275 if (
CGM.getLangOpts().OMPTargetTriples.empty() &&
11276 !
CGM.getLangOpts().OpenMPIsTargetDevice)
11279 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
11280 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
11284 if (Res && *Res != OMPDeclareTargetDeclAttr::MT_Link &&
11289 if (
CGM.getLangOpts().OpenMPIsTargetDevice) {
11292 StringRef VarName =
CGM.getMangledName(VD);
11298 auto AddrOfGlobal = [&VD,
this]() {
return CGM.GetAddrOfGlobal(VD); };
11299 auto LinkageForVariable = [&VD,
this]() {
11300 return CGM.getLLVMLinkageVarDefinition(VD);
11303 std::vector<llvm::GlobalVariable *> GeneratedRefs;
11310 CGM.getMangledName(VD), GeneratedRefs,
CGM.getLangOpts().OpenMPSimd,
11311 CGM.getLangOpts().OMPTargetTriples, AddrOfGlobal, LinkageForVariable,
11312 CGM.getTypes().ConvertTypeForMem(
11313 CGM.getContext().getPointerType(VD->
getType())),
11316 for (
auto *ref : GeneratedRefs)
11317 CGM.addCompilerUsedGlobal(ref);
11330 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
11331 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
11334 if ((*Res == OMPDeclareTargetDeclAttr::MT_To ||
11335 *Res == OMPDeclareTargetDeclAttr::MT_Enter) &&
11337 CGM.EmitGlobal(VD);
11339 assert((*Res == OMPDeclareTargetDeclAttr::MT_Link ||
11340 ((*Res == OMPDeclareTargetDeclAttr::MT_To ||
11341 *Res == OMPDeclareTargetDeclAttr::MT_Enter) &&
11343 "Expected link clause or to clause with unified memory.");
11344 (void)
CGM.getOpenMPRuntime().getAddrOfDeclareTargetVar(VD);
11352 " Expected target-based directive.");
11357 if (Clause->getClauseKind() == OMPC_unified_shared_memory) {
11359 OMPBuilder.Config.setHasRequiresUnifiedSharedMemory(
true);
11360 }
else if (
const auto *AC =
11361 dyn_cast<OMPAtomicDefaultMemOrderClause>(Clause)) {
11362 switch (AC->getAtomicDefaultMemOrderKind()) {
11363 case OMPC_ATOMIC_DEFAULT_MEM_ORDER_acq_rel:
11366 case OMPC_ATOMIC_DEFAULT_MEM_ORDER_seq_cst:
11369 case OMPC_ATOMIC_DEFAULT_MEM_ORDER_relaxed:
11385 if (!VD || !VD->
hasAttr<OMPAllocateDeclAttr>())
11387 const auto *A = VD->
getAttr<OMPAllocateDeclAttr>();
11388 switch(A->getAllocatorType()) {
11389 case OMPAllocateDeclAttr::OMPNullMemAlloc:
11390 case OMPAllocateDeclAttr::OMPDefaultMemAlloc:
11392 case OMPAllocateDeclAttr::OMPLargeCapMemAlloc:
11393 case OMPAllocateDeclAttr::OMPCGroupMemAlloc:
11394 case OMPAllocateDeclAttr::OMPHighBWMemAlloc:
11395 case OMPAllocateDeclAttr::OMPLowLatMemAlloc:
11396 case OMPAllocateDeclAttr::OMPThreadMemAlloc:
11397 case OMPAllocateDeclAttr::OMPConstMemAlloc:
11398 case OMPAllocateDeclAttr::OMPPTeamMemAlloc:
11401 case OMPAllocateDeclAttr::OMPUserDefinedMemAlloc:
11402 llvm_unreachable(
"Expected predefined allocator for the variables with the "
11403 "static storage.");
11415 if (CGM.getLangOpts().OpenMPIsTargetDevice) {
11416 SavedShouldMarkAsGlobal = CGM.getOpenMPRuntime().ShouldMarkAsGlobal;
11417 CGM.getOpenMPRuntime().ShouldMarkAsGlobal = false;
11422 if (CGM.getLangOpts().OpenMPIsTargetDevice)
11423 CGM.getOpenMPRuntime().ShouldMarkAsGlobal = SavedShouldMarkAsGlobal;
11433 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(D)) {
11435 if (
auto *F = dyn_cast_or_null<llvm::Function>(
11436 CGM.GetGlobalValue(
CGM.getMangledName(GD))))
11437 return !F->isDeclaration();
11449 llvm::Function *OutlinedFn,
11458 llvm::Value *Args[] = {
11460 CGF.
Builder.getInt32(CapturedVars.size()),
11463 RealArgs.append(std::begin(Args), std::end(Args));
11464 RealArgs.append(CapturedVars.begin(), CapturedVars.end());
11466 llvm::FunctionCallee RTLFn =
OMPBuilder.getOrCreateRuntimeFunction(
11467 CGM.getModule(), OMPRTL___kmpc_fork_teams);
11472 const Expr *NumTeams,
11473 const Expr *ThreadLimit,
11480 llvm::Value *NumTeamsVal =
11486 llvm::Value *ThreadLimitVal =
11493 llvm::Value *PushNumTeamsArgs[] = {RTLoc,
getThreadID(CGF, Loc), NumTeamsVal,
11496 CGM.getModule(), OMPRTL___kmpc_push_num_teams),
11501 const Expr *ThreadLimit,
11504 llvm::Value *ThreadLimitVal =
11511 llvm::Value *ThreadLimitArgs[] = {RTLoc,
getThreadID(CGF, Loc),
11514 CGM.getModule(), OMPRTL___kmpc_set_thread_limit),
11529 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
11531 llvm::Value *IfCondVal =
nullptr;
11536 llvm::Value *DeviceID =
nullptr;
11541 DeviceID = CGF.
Builder.getInt64(OMP_DEVICEID_UNDEF);
11545 MappableExprsHandler::MapCombinedInfoTy CombinedInfo;
11546 auto GenMapInfoCB =
11547 [&](InsertPointTy CodeGenIP) -> llvm::OpenMPIRBuilder::MapInfosTy & {
11548 CGF.
Builder.restoreIP(CodeGenIP);
11550 MappableExprsHandler MEHandler(D, CGF);
11551 MEHandler.generateAllInfo(CombinedInfo,
OMPBuilder);
11553 auto FillInfoMap = [&](MappableExprsHandler::MappingExprInfo &MapExpr) {
11556 if (
CGM.getCodeGenOpts().getDebugInfo() !=
11557 llvm::codegenoptions::NoDebugInfo) {
11558 CombinedInfo.Names.resize(CombinedInfo.Exprs.size());
11559 llvm::transform(CombinedInfo.Exprs, CombinedInfo.Names.begin(),
11563 return CombinedInfo;
11565 using BodyGenTy = llvm::OpenMPIRBuilder::BodyGenTy;
11566 auto BodyCB = [&](InsertPointTy CodeGenIP, BodyGenTy BodyGenType) {
11567 CGF.
Builder.restoreIP(CodeGenIP);
11568 switch (BodyGenType) {
11569 case BodyGenTy::Priv:
11573 case BodyGenTy::DupNoPriv:
11575 CodeGen.setAction(NoPrivAction);
11579 case BodyGenTy::NoPriv:
11581 CodeGen.setAction(NoPrivAction);
11586 return InsertPointTy(CGF.
Builder.GetInsertBlock(),
11587 CGF.
Builder.GetInsertPoint());
11590 auto DeviceAddrCB = [&](
unsigned int I, llvm::Value *NewDecl) {
11591 if (
const ValueDecl *DevVD = CombinedInfo.DevicePtrDecls[I]) {
11596 auto CustomMapperCB = [&](
unsigned int I) {
11597 llvm::Function *MFunc =
nullptr;
11598 if (CombinedInfo.Mappers[I]) {
11599 Info.HasMapper =
true;
11611 InsertPointTy CodeGenIP(CGF.
Builder.GetInsertBlock(),
11612 CGF.
Builder.GetInsertPoint());
11613 llvm::OpenMPIRBuilder::LocationDescription OmpLoc(CodeGenIP);
11614 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
11616 OmpLoc, AllocaIP, CodeGenIP, DeviceID, IfCondVal, Info, GenMapInfoCB,
11618 nullptr, BodyCB, DeviceAddrCB, RTLoc));
11619 CGF.
Builder.restoreIP(AfterIP);
11631 "Expecting either target enter, exit data, or update directives.");
11634 llvm::Value *MapTypesArray =
nullptr;
11635 llvm::Value *MapNamesArray =
nullptr;
11637 auto &&ThenGen = [
this, &D,
Device, &InputInfo, &MapTypesArray,
11640 llvm::Value *DeviceID =
nullptr;
11645 DeviceID = CGF.
Builder.getInt64(OMP_DEVICEID_UNDEF);
11649 llvm::Constant *PointerNum =
11656 {RTLoc, DeviceID, PointerNum,
11664 const bool HasNowait = D.hasClausesOfKind<OMPNowaitClause>();
11665 RuntimeFunction RTLFn;
11666 switch (D.getDirectiveKind()) {
11667 case OMPD_target_enter_data:
11668 RTLFn = HasNowait ? OMPRTL___tgt_target_data_begin_nowait_mapper
11669 : OMPRTL___tgt_target_data_begin_mapper;
11671 case OMPD_target_exit_data:
11672 RTLFn = HasNowait ? OMPRTL___tgt_target_data_end_nowait_mapper
11673 : OMPRTL___tgt_target_data_end_mapper;
11675 case OMPD_target_update:
11676 RTLFn = HasNowait ? OMPRTL___tgt_target_data_update_nowait_mapper
11677 : OMPRTL___tgt_target_data_update_mapper;
11679 case OMPD_parallel:
11681 case OMPD_parallel_for:
11682 case OMPD_parallel_master:
11683 case OMPD_parallel_sections:
11684 case OMPD_for_simd:
11685 case OMPD_parallel_for_simd:
11687 case OMPD_cancellation_point:
11689 case OMPD_threadprivate:
11690 case OMPD_allocate:
11695 case OMPD_sections:
11699 case OMPD_critical:
11700 case OMPD_taskyield:
11702 case OMPD_taskwait:
11703 case OMPD_taskgroup:
11709 case OMPD_target_data:
11710 case OMPD_distribute:
11711 case OMPD_distribute_simd:
11712 case OMPD_distribute_parallel_for:
11713 case OMPD_distribute_parallel_for_simd:
11714 case OMPD_teams_distribute:
11715 case OMPD_teams_distribute_simd:
11716 case OMPD_teams_distribute_parallel_for:
11717 case OMPD_teams_distribute_parallel_for_simd:
11718 case OMPD_declare_simd:
11719 case OMPD_declare_variant:
11720 case OMPD_begin_declare_variant:
11721 case OMPD_end_declare_variant:
11722 case OMPD_declare_target:
11723 case OMPD_end_declare_target:
11724 case OMPD_declare_reduction:
11725 case OMPD_declare_mapper:
11726 case OMPD_taskloop:
11727 case OMPD_taskloop_simd:
11728 case OMPD_master_taskloop:
11729 case OMPD_master_taskloop_simd:
11730 case OMPD_parallel_master_taskloop:
11731 case OMPD_parallel_master_taskloop_simd:
11733 case OMPD_target_simd:
11734 case OMPD_target_teams_distribute:
11735 case OMPD_target_teams_distribute_simd:
11736 case OMPD_target_teams_distribute_parallel_for:
11737 case OMPD_target_teams_distribute_parallel_for_simd:
11738 case OMPD_target_teams:
11739 case OMPD_target_parallel:
11740 case OMPD_target_parallel_for:
11741 case OMPD_target_parallel_for_simd:
11742 case OMPD_requires:
11743 case OMPD_metadirective:
11746 llvm_unreachable(
"Unexpected standalone target data directive.");
11750 OffloadingArgs.push_back(llvm::Constant::getNullValue(CGF.
Int32Ty));
11751 OffloadingArgs.push_back(llvm::Constant::getNullValue(CGF.
VoidPtrTy));
11752 OffloadingArgs.push_back(llvm::Constant::getNullValue(CGF.
Int32Ty));
11753 OffloadingArgs.push_back(llvm::Constant::getNullValue(CGF.
VoidPtrTy));
11756 OMPBuilder.getOrCreateRuntimeFunction(
CGM.getModule(), RTLFn),
11760 auto &&TargetThenGen = [
this, &ThenGen, &D, &InputInfo, &MapTypesArray,
11764 MappableExprsHandler::MapCombinedInfoTy CombinedInfo;
11766 MappableExprsHandler MEHandler(D, CGF);
11772 D.hasClausesOfKind<OMPNowaitClause>();
11778 CGM.getPointerAlign());
11783 MapTypesArray = Info.RTArgs.MapTypesArray;
11784 MapNamesArray = Info.RTArgs.MapNamesArray;
11785 if (RequiresOuterTask)
11811struct ParamAttrTy {
11812 ParamKindTy Kind =
Vector;
11813 llvm::APSInt StrideOrArg;
11814 llvm::APSInt Alignment;
11815 bool HasVarStride =
false;
11848 unsigned Offset = 0;
11849 if (
const auto *MD = dyn_cast<CXXMethodDecl>(FD)) {
11850 if (ParamAttrs[Offset].Kind ==
Vector)
11851 CDT =
C.getPointerType(
C.getCanonicalTagType(MD->
getParent()));
11855 for (
unsigned I = 0, E = FD->
getNumParams(); I < E; ++I) {
11856 if (ParamAttrs[I + Offset].Kind ==
Vector) {
11868 return C.getTypeSize(CDT);
11876 llvm::raw_svector_ostream Out(Buffer);
11877 for (
const auto &ParamAttr : ParamAttrs) {
11878 switch (ParamAttr.Kind) {
11898 if (ParamAttr.HasVarStride)
11899 Out <<
"s" << ParamAttr.StrideOrArg;
11900 else if (ParamAttr.Kind == Linear || ParamAttr.Kind == LinearRef ||
11901 ParamAttr.Kind == LinearUVal || ParamAttr.Kind == LinearVal) {
11904 if (ParamAttr.StrideOrArg < 0)
11905 Out <<
'n' << -ParamAttr.StrideOrArg;
11906 else if (ParamAttr.StrideOrArg != 1)
11907 Out << ParamAttr.StrideOrArg;
11910 if (!!ParamAttr.Alignment)
11911 Out <<
'a' << ParamAttr.Alignment;
11914 return std::string(Out.str());
11919 const llvm::APSInt &VLENVal,
11921 OMPDeclareSimdDeclAttr::BranchStateTy State) {
11924 unsigned VecRegSize;
11926 ISADataTy ISAData[] = {
11942 case OMPDeclareSimdDeclAttr::BS_Undefined:
11943 Masked.push_back(
'N');
11944 Masked.push_back(
'M');
11946 case OMPDeclareSimdDeclAttr::BS_Notinbranch:
11947 Masked.push_back(
'N');
11949 case OMPDeclareSimdDeclAttr::BS_Inbranch:
11950 Masked.push_back(
'M');
11953 for (
char Mask : Masked) {
11954 for (
const ISADataTy &
Data : ISAData) {
11956 llvm::raw_svector_ostream Out(Buffer);
11957 Out <<
"_ZGV" <<
Data.ISA << Mask;
11960 assert(NumElts &&
"Non-zero simdlen/cdtsize expected");
11961 Out << llvm::APSInt::getUnsigned(
Data.VecRegSize / NumElts);
11966 Out <<
'_' << Fn->getName();
11967 Fn->addFnAttr(Out.str());
11985 if (Kind == ParamKindTy::Uniform)
11988 if (Kind == ParamKindTy::LinearUVal || Kind == ParamKindTy::LinearRef)
11991 if ((Kind == ParamKindTy::Linear || Kind == ParamKindTy::LinearVal) &&
12001 unsigned Size =
C.getTypeSize(QT);
12004 if (Size != 8 && Size != 16 && Size != 32 && Size != 64 && Size != 128)
12028 return C.getTypeSize(PTy);
12031 return C.getTypeSize(QT);
12033 return C.getTypeSize(
C.getUIntPtrType());
12039static std::tuple<unsigned, unsigned, bool>
12045 bool OutputBecomesInput =
false;
12049 Sizes.push_back(
getAArch64LS(RetType, ParamKindTy::Vector,
C));
12051 OutputBecomesInput =
true;
12053 for (
unsigned I = 0, E = FD->
getNumParams(); I < E; ++I) {
12058 assert(!Sizes.empty() &&
"Unable to determine NDS and WDS.");
12061 assert(llvm::all_of(Sizes,
12062 [](
unsigned Size) {
12063 return Size == 8 || Size == 16 || Size == 32 ||
12064 Size == 64 || Size == 128;
12068 return std::make_tuple(*llvm::min_element(Sizes), *llvm::max_element(Sizes),
12069 OutputBecomesInput);
12075template <
typename T>
12077 char ISA, StringRef ParSeq,
12078 StringRef MangledName,
bool OutputBecomesInput,
12079 llvm::Function *Fn) {
12081 llvm::raw_svector_ostream Out(Buffer);
12082 Out << Prefix << ISA << LMask << VLEN;
12083 if (OutputBecomesInput)
12085 Out << ParSeq <<
"_" << MangledName;
12086 Fn->addFnAttr(Out.str());
12092 StringRef Prefix,
char ISA,
12093 StringRef ParSeq, StringRef MangledName,
12094 bool OutputBecomesInput,
12095 llvm::Function *Fn) {
12099 OutputBecomesInput, Fn);
12101 OutputBecomesInput, Fn);
12105 OutputBecomesInput, Fn);
12107 OutputBecomesInput, Fn);
12111 OutputBecomesInput, Fn);
12113 OutputBecomesInput, Fn);
12118 OutputBecomesInput, Fn);
12121 llvm_unreachable(
"Scalar type is too wide.");
12129 OMPDeclareSimdDeclAttr::BranchStateTy State, StringRef MangledName,
12130 char ISA,
unsigned VecRegSize, llvm::Function *Fn,
SourceLocation SLoc) {
12134 const unsigned NDS = std::get<0>(
Data);
12135 const unsigned WDS = std::get<1>(
Data);
12136 const bool OutputBecomesInput = std::get<2>(
Data);
12140 if (UserVLEN == 1) {
12147 if (ISA ==
'n' && UserVLEN && !llvm::isPowerOf2_32(UserVLEN)) {
12154 if (ISA ==
's' && UserVLEN != 0) {
12155 if ((UserVLEN * WDS > 2048) || (UserVLEN * WDS % 128 != 0)) {
12163 StringRef Prefix =
"_ZGV";
12169 OutputBecomesInput, Fn);
12171 assert(ISA ==
'n' &&
"Expected ISA either 's' or 'n'.");
12175 case OMPDeclareSimdDeclAttr::BS_Undefined:
12177 OutputBecomesInput, Fn);
12179 OutputBecomesInput, Fn);
12181 case OMPDeclareSimdDeclAttr::BS_Notinbranch:
12183 OutputBecomesInput, Fn);
12185 case OMPDeclareSimdDeclAttr::BS_Inbranch:
12187 OutputBecomesInput, Fn);
12197 OutputBecomesInput, Fn);
12199 assert(ISA ==
'n' &&
"Expected ISA either 's' or 'n'.");
12204 case OMPDeclareSimdDeclAttr::BS_Undefined:
12206 OutputBecomesInput, Fn);
12208 OutputBecomesInput, Fn);
12210 case OMPDeclareSimdDeclAttr::BS_Notinbranch:
12212 OutputBecomesInput, Fn);
12214 case OMPDeclareSimdDeclAttr::BS_Inbranch:
12216 OutputBecomesInput, Fn);
12224 llvm::Function *Fn) {
12229 llvm::DenseMap<const Decl *, unsigned> ParamPositions;
12231 ParamPositions.try_emplace(FD, 0);
12232 unsigned ParamPos = ParamPositions.size();
12234 ParamPositions.try_emplace(P->getCanonicalDecl(), ParamPos);
12240 for (
const Expr *E :
Attr->uniforms()) {
12244 Pos = ParamPositions[FD];
12247 ->getCanonicalDecl();
12248 auto It = ParamPositions.find(PVD);
12249 assert(It != ParamPositions.end() &&
"Function parameter not found");
12252 ParamAttrs[Pos].Kind = Uniform;
12255 auto *NI =
Attr->alignments_begin();
12256 for (
const Expr *E :
Attr->aligneds()) {
12261 Pos = ParamPositions[FD];
12265 ->getCanonicalDecl();
12266 auto It = ParamPositions.find(PVD);
12267 assert(It != ParamPositions.end() &&
"Function parameter not found");
12269 ParmTy = PVD->getType();
12271 ParamAttrs[Pos].Alignment =
12273 ? (*NI)->EvaluateKnownConstInt(
C)
12274 : llvm::APSInt::getUnsigned(
12275 C.toCharUnitsFromBits(
C.getOpenMPDefaultSimdAlign(ParmTy))
12280 auto *SI =
Attr->steps_begin();
12281 auto *MI =
Attr->modifiers_begin();
12282 for (
const Expr *E :
Attr->linears()) {
12285 bool IsReferenceType =
false;
12288 unsigned PtrRescalingFactor = 1;
12290 Pos = ParamPositions[FD];
12292 PtrRescalingFactor =
CGM.getContext()
12293 .getTypeSizeInChars(P->getPointeeType())
12297 ->getCanonicalDecl();
12298 auto It = ParamPositions.find(PVD);
12299 assert(It != ParamPositions.end() &&
"Function parameter not found");
12301 if (
auto *P = dyn_cast<PointerType>(PVD->getType()))
12302 PtrRescalingFactor =
CGM.getContext()
12303 .getTypeSizeInChars(P->getPointeeType())
12305 else if (PVD->getType()->isReferenceType()) {
12306 IsReferenceType =
true;
12307 PtrRescalingFactor =
12309 .getTypeSizeInChars(PVD->getType().getNonReferenceType())
12313 ParamAttrTy &ParamAttr = ParamAttrs[Pos];
12314 if (*MI == OMPC_LINEAR_ref)
12315 ParamAttr.Kind = LinearRef;
12316 else if (*MI == OMPC_LINEAR_uval)
12317 ParamAttr.Kind = LinearUVal;
12318 else if (IsReferenceType)
12319 ParamAttr.Kind = LinearVal;
12321 ParamAttr.Kind = Linear;
12323 ParamAttr.StrideOrArg = llvm::APSInt::getUnsigned(1);
12327 if (
const auto *DRE =
12329 if (
const auto *StridePVD =
12330 dyn_cast<ParmVarDecl>(DRE->getDecl())) {
12331 ParamAttr.HasVarStride =
true;
12332 auto It = ParamPositions.find(StridePVD->getCanonicalDecl());
12333 assert(It != ParamPositions.end() &&
12334 "Function parameter not found");
12335 ParamAttr.StrideOrArg = llvm::APSInt::getUnsigned(It->second);
12339 ParamAttr.StrideOrArg =
Result.Val.getInt();
12345 if (!ParamAttr.HasVarStride &&
12346 (ParamAttr.Kind == Linear || ParamAttr.Kind == LinearRef))
12347 ParamAttr.StrideOrArg = ParamAttr.StrideOrArg * PtrRescalingFactor;
12351 llvm::APSInt VLENVal;
12353 const Expr *VLENExpr =
Attr->getSimdlen();
12358 OMPDeclareSimdDeclAttr::BranchStateTy State =
Attr->getBranchState();
12359 if (
CGM.getTriple().isX86()) {
12361 }
else if (
CGM.getTriple().getArch() == llvm::Triple::aarch64) {
12362 unsigned VLEN = VLENVal.getExtValue();
12363 StringRef MangledName = Fn->getName();
12364 if (
CGM.getTarget().hasFeature(
"sve"))
12366 MangledName,
's', 128, Fn, ExprLoc);
12367 else if (
CGM.getTarget().hasFeature(
"neon"))
12369 MangledName,
'n', 128, Fn, ExprLoc);
12378class DoacrossCleanupTy final :
public EHScopeStack::Cleanup {
12380 static const int DoacrossFinArgs = 2;
12383 llvm::FunctionCallee RTLFn;
12384 llvm::Value *Args[DoacrossFinArgs];
12387 DoacrossCleanupTy(llvm::FunctionCallee RTLFn,
12390 assert(CallArgs.size() == DoacrossFinArgs);
12391 std::copy(CallArgs.begin(), CallArgs.end(), std::begin(Args));
12408 QualType Int64Ty =
C.getIntTypeForBitwidth(64,
true);
12416 RD =
C.buildImplicitRecord(
"kmp_dim");
12424 RD =
KmpDimTy->castAsRecordDecl();
12426 llvm::APInt Size(32, NumIterations.size());
12432 enum { LowerFD = 0, UpperFD, StrideFD };
12434 for (
unsigned I = 0, E = NumIterations.size(); I < E; ++I) {
12439 DimsLVal, *std::next(RD->
field_begin(), UpperFD));
12441 CGF.
EmitScalarExpr(NumIterations[I]), NumIterations[I]->getType(),
12442 Int64Ty, NumIterations[I]->getExprLoc());
12446 DimsLVal, *std::next(RD->
field_begin(), StrideFD));
12453 llvm::Value *Args[] = {
12456 llvm::ConstantInt::getSigned(
CGM.Int32Ty, NumIterations.size()),
12461 llvm::FunctionCallee RTLFn =
OMPBuilder.getOrCreateRuntimeFunction(
12462 CGM.getModule(), OMPRTL___kmpc_doacross_init);
12464 llvm::Value *FiniArgs[DoacrossCleanupTy::DoacrossFinArgs] = {
12466 llvm::FunctionCallee FiniRTLFn =
OMPBuilder.getOrCreateRuntimeFunction(
12467 CGM.getModule(), OMPRTL___kmpc_doacross_fini);
12472template <
typename T>
12474 const T *
C, llvm::Value *ULoc,
12475 llvm::Value *ThreadID) {
12478 llvm::APInt Size(32,
C->getNumLoops());
12482 for (
unsigned I = 0, E =
C->getNumLoops(); I < E; ++I) {
12483 const Expr *CounterVal =
C->getLoopData(I);
12484 assert(CounterVal);
12491 llvm::Value *Args[] = {
12494 llvm::FunctionCallee RTLFn;
12496 OMPDoacrossKind<T> ODK;
12497 if (ODK.isSource(
C)) {
12499 OMPRTL___kmpc_doacross_post);
12501 assert(ODK.isSink(
C) &&
"Expect sink modifier.");
12503 OMPRTL___kmpc_doacross_wait);
12523 llvm::FunctionCallee Callee,
12525 assert(Loc.
isValid() &&
"Outlined function call location must be valid.");
12528 if (
auto *Fn = dyn_cast<llvm::Function>(Callee.getCallee())) {
12529 if (Fn->doesNotThrow()) {
12540 emitCall(CGF, Loc, OutlinedFn, Args);
12544 if (
const auto *FD = dyn_cast<FunctionDecl>(D))
12545 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(FD))
12551 const VarDecl *TargetParam)
const {
12558 const Expr *Allocator) {
12559 llvm::Value *AllocVal;
12569 AllocVal = llvm::Constant::getNullValue(
12579 if (!AllocateAlignment)
12582 return llvm::ConstantInt::get(
CGM.
SizeTy, AllocateAlignment->getQuantity());
12595 auto I = UntiedData.find(VD);
12596 if (I != UntiedData.end()) {
12597 UntiedAddr = I->second.first;
12598 UntiedRealAddr = I->second.second;
12602 if (CVD->
hasAttr<OMPAllocateDeclAttr>()) {
12611 Size = CGF.
Builder.CreateNUWAdd(
12613 Size = CGF.
Builder.CreateUDiv(Size,
CGM.getSize(Align));
12614 Size = CGF.
Builder.CreateNUWMul(Size,
CGM.getSize(Align));
12620 const auto *AA = CVD->
getAttr<OMPAllocateDeclAttr>();
12621 const Expr *Allocator = AA->getAllocator();
12625 Args.push_back(ThreadID);
12627 Args.push_back(Alignment);
12628 Args.push_back(Size);
12629 Args.push_back(AllocVal);
12630 llvm::omp::RuntimeFunction FnID =
12631 Alignment ? OMPRTL___kmpc_aligned_alloc : OMPRTL___kmpc_alloc;
12633 OMPBuilder.getOrCreateRuntimeFunction(
CGM.getModule(), FnID), Args,
12635 llvm::FunctionCallee FiniRTLFn =
OMPBuilder.getOrCreateRuntimeFunction(
12636 CGM.getModule(), OMPRTL___kmpc_free);
12644 class OMPAllocateCleanupTy final :
public EHScopeStack::Cleanup {
12645 llvm::FunctionCallee RTLFn;
12648 const Expr *AllocExpr;
12651 OMPAllocateCleanupTy(llvm::FunctionCallee RTLFn,
12653 const Expr *AllocExpr)
12654 : RTLFn(RTLFn), LocEncoding(LocEncoding),
Addr(
Addr),
12655 AllocExpr(AllocExpr) {}
12659 llvm::Value *Args[3];
12665 Args[2] = AllocVal;
12673 CGF.
EHStack.pushCleanup<OMPAllocateCleanupTy>(
12675 VDAddr, Allocator);
12676 if (UntiedRealAddr.
isValid())
12679 Region->emitUntiedSwitch(CGF);
12696 assert(CGM.getLangOpts().OpenMP &&
"Not in OpenMP mode.");
12700 CGM.getOpenMPRuntime().NontemporalDeclsStack.emplace_back();
12702 for (
const Stmt *Ref :
C->private_refs()) {
12703 const auto *SimpleRefExpr =
cast<Expr>(Ref)->IgnoreParenImpCasts();
12705 if (
const auto *DRE = dyn_cast<DeclRefExpr>(SimpleRefExpr)) {
12706 VD = DRE->getDecl();
12709 assert((ME->isImplicitCXXThis() ||
12711 "Expected member of current class.");
12712 VD = ME->getMemberDecl();
12722 CGM.getOpenMPRuntime().NontemporalDeclsStack.pop_back();
12728 std::pair<Address, Address>> &LocalVars)
12729 : CGM(CGF.CGM), NeedToPush(!LocalVars.empty()) {
12733 CGF.
CurFn, CGM.getOpenMPRuntime().UntiedLocalVarsStack.size());
12734 CGM.getOpenMPRuntime().UntiedLocalVarsStack.push_back(LocalVars);
12740 CGM.getOpenMPRuntime().UntiedLocalVarsStack.pop_back();
12744 assert(
CGM.getLangOpts().OpenMP &&
"Not in OpenMP mode.");
12746 return llvm::any_of(
12747 CGM.getOpenMPRuntime().NontemporalDeclsStack,
12751void CGOpenMPRuntime::LastprivateConditionalRAII::tryToDisableInnerAnalysis(
12755 llvm::DenseSet<CanonicalDeclPtr<const Decl>> NeedToCheckForLPCs;
12761 const CapturedStmt *CS = S.getCapturedStmt(CaptureRegions.front());
12768 for (
const auto *
C : S.getClausesOfKind<OMPPrivateClause>()) {
12769 for (
const Expr *Ref :
C->varlist()) {
12770 if (!Ref->getType()->isScalarType())
12772 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
12775 NeedToCheckForLPCs.insert(DRE->getDecl());
12778 for (
const auto *
C : S.getClausesOfKind<OMPFirstprivateClause>()) {
12779 for (
const Expr *Ref :
C->varlist()) {
12780 if (!Ref->getType()->isScalarType())
12782 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
12785 NeedToCheckForLPCs.insert(DRE->getDecl());
12788 for (
const auto *
C : S.getClausesOfKind<OMPLastprivateClause>()) {
12789 for (
const Expr *Ref :
C->varlist()) {
12790 if (!Ref->getType()->isScalarType())
12792 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
12795 NeedToCheckForLPCs.insert(DRE->getDecl());
12798 for (
const auto *
C : S.getClausesOfKind<OMPReductionClause>()) {
12799 for (
const Expr *Ref :
C->varlist()) {
12800 if (!Ref->getType()->isScalarType())
12802 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
12805 NeedToCheckForLPCs.insert(DRE->getDecl());
12808 for (
const auto *
C : S.getClausesOfKind<OMPLinearClause>()) {
12809 for (
const Expr *Ref :
C->varlist()) {
12810 if (!Ref->getType()->isScalarType())
12812 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
12815 NeedToCheckForLPCs.insert(DRE->getDecl());
12818 for (
const Decl *VD : NeedToCheckForLPCs) {
12820 llvm::reverse(
CGM.getOpenMPRuntime().LastprivateConditionalStack)) {
12821 if (
Data.DeclToUniqueName.count(VD) > 0) {
12822 if (!
Data.Disabled)
12823 NeedToAddForLPCsAsDisabled.insert(VD);
12830CGOpenMPRuntime::LastprivateConditionalRAII::LastprivateConditionalRAII(
12833 Action((CGM.getLangOpts().OpenMP >= 50 &&
12834 llvm::any_of(S.getClausesOfKind<OMPLastprivateClause>(),
12835 [](const OMPLastprivateClause *
C) {
12836 return C->getKind() ==
12837 OMPC_LASTPRIVATE_conditional;
12839 ? ActionToDo::PushAsLastprivateConditional
12840 : ActionToDo::DoNotPush) {
12841 assert(
CGM.getLangOpts().OpenMP &&
"Not in OpenMP mode.");
12842 if (
CGM.getLangOpts().OpenMP < 50 || Action == ActionToDo::DoNotPush)
12844 assert(Action == ActionToDo::PushAsLastprivateConditional &&
12845 "Expected a push action.");
12847 CGM.getOpenMPRuntime().LastprivateConditionalStack.emplace_back();
12848 for (
const auto *
C : S.getClausesOfKind<OMPLastprivateClause>()) {
12849 if (
C->getKind() != OMPC_LASTPRIVATE_conditional)
12852 for (
const Expr *Ref :
C->varlist()) {
12853 Data.DeclToUniqueName.insert(std::make_pair(
12858 Data.IVLVal = IVLVal;
12862CGOpenMPRuntime::LastprivateConditionalRAII::LastprivateConditionalRAII(
12864 :
CGM(CGF.
CGM), Action(ActionToDo::DoNotPush) {
12868 llvm::DenseSet<CanonicalDeclPtr<const Decl>> NeedToAddForLPCsAsDisabled;
12869 tryToDisableInnerAnalysis(S, NeedToAddForLPCsAsDisabled);
12870 if (!NeedToAddForLPCsAsDisabled.empty()) {
12871 Action = ActionToDo::DisableLastprivateConditional;
12872 LastprivateConditionalData &
Data =
12874 for (
const Decl *VD : NeedToAddForLPCsAsDisabled)
12875 Data.DeclToUniqueName.try_emplace(VD);
12877 Data.Disabled =
true;
12881CGOpenMPRuntime::LastprivateConditionalRAII
12884 return LastprivateConditionalRAII(CGF, S);
12888 if (CGM.getLangOpts().OpenMP < 50)
12890 if (Action == ActionToDo::DisableLastprivateConditional) {
12891 assert(CGM.getOpenMPRuntime().LastprivateConditionalStack.back().Disabled &&
12892 "Expected list of disabled private vars.");
12893 CGM.getOpenMPRuntime().LastprivateConditionalStack.pop_back();
12895 if (Action == ActionToDo::PushAsLastprivateConditional) {
12897 !CGM.getOpenMPRuntime().LastprivateConditionalStack.back().Disabled &&
12898 "Expected list of lastprivate conditional vars.");
12899 CGM.getOpenMPRuntime().LastprivateConditionalStack.pop_back();
12911 auto VI = I->getSecond().find(VD);
12912 if (VI == I->getSecond().end()) {
12913 RecordDecl *RD =
C.buildImplicitRecord(
"lasprivate.conditional");
12918 NewType =
C.getCanonicalTagType(RD);
12921 I->getSecond().try_emplace(VD, NewType, VDField, FiredField, BaseLVal);
12923 NewType = std::get<0>(VI->getSecond());
12924 VDField = std::get<1>(VI->getSecond());
12925 FiredField = std::get<2>(VI->getSecond());
12926 BaseLVal = std::get<3>(VI->getSecond());
12938class LastprivateConditionalRefChecker final
12941 const Expr *FoundE =
nullptr;
12942 const Decl *FoundD =
nullptr;
12943 StringRef UniqueDeclName;
12945 llvm::Function *FoundFn =
nullptr;
12951 llvm::reverse(LPM)) {
12952 auto It = D.DeclToUniqueName.find(E->
getDecl());
12953 if (It == D.DeclToUniqueName.end())
12959 UniqueDeclName = It->second;
12964 return FoundE == E;
12970 llvm::reverse(LPM)) {
12972 if (It == D.DeclToUniqueName.end())
12978 UniqueDeclName = It->second;
12983 return FoundE == E;
12985 bool VisitStmt(
const Stmt *S) {
12986 for (
const Stmt *Child : S->
children()) {
12989 if (
const auto *E = dyn_cast<Expr>(Child))
12997 explicit LastprivateConditionalRefChecker(
12998 ArrayRef<CGOpenMPRuntime::LastprivateConditionalData> LPM)
13000 std::tuple<const Expr *, const Decl *, StringRef, LValue, llvm::Function *>
13001 getFoundData()
const {
13002 return std::make_tuple(FoundE, FoundD, UniqueDeclName, IVLVal, FoundFn);
13009 StringRef UniqueDeclName,
13015 llvm::Constant *LastIV =
OMPBuilder.getOrCreateInternalVariable(
13016 LLIVTy,
getName({UniqueDeclName,
"iv"}));
13024 llvm::GlobalVariable *
Last =
OMPBuilder.getOrCreateInternalVariable(
13040 auto &&
CodeGen = [&LastIVLVal, &IVLVal, IVVal, &LVal, &LastLVal,
13046 llvm::Value *CmpRes;
13048 CmpRes = CGF.
Builder.CreateICmpSLE(LastIVVal, IVVal);
13051 "Loop iteration variable must be integer.");
13052 CmpRes = CGF.
Builder.CreateICmpULE(LastIVVal, IVVal);
13056 CGF.
Builder.CreateCondBr(CmpRes, ThenBB, ExitBB);
13077 "Aggregates are not supported in lastprivate conditional.");
13086 if (
CGM.getLangOpts().OpenMPSimd) {
13100 if (!Checker.Visit(LHS))
13102 const Expr *FoundE;
13103 const Decl *FoundD;
13104 StringRef UniqueDeclName;
13106 llvm::Function *FoundFn;
13107 std::tie(FoundE, FoundD, UniqueDeclName, IVLVal, FoundFn) =
13108 Checker.getFoundData();
13109 if (FoundFn != CGF.
CurFn) {
13114 "Lastprivate conditional is not found in outer region.");
13115 QualType StructTy = std::get<0>(It->getSecond());
13116 const FieldDecl* FiredDecl = std::get<2>(It->getSecond());
13127 FiredLVal, llvm::AtomicOrdering::Unordered,
13145 auto It = llvm::find_if(
13147 if (It == Range.end() || It->Fn != CGF.
CurFn)
13151 "Lastprivates must be registered already.");
13154 const CapturedStmt *CS = D.getCapturedStmt(CaptureRegions.back());
13155 for (
const auto &Pair : It->DeclToUniqueName) {
13156 const auto *VD =
cast<VarDecl>(Pair.first->getCanonicalDecl());
13159 auto I = LPCI->getSecond().find(Pair.first);
13160 assert(I != LPCI->getSecond().end() &&
13161 "Lastprivate must be rehistered already.");
13163 LValue BaseLVal = std::get<3>(I->getSecond());
13167 llvm::Value *Cmp = CGF.
Builder.CreateIsNotNull(Res);
13171 CGF.
Builder.CreateCondBr(Cmp, ThenBB, DoneBB);
13196 "Unknown lastprivate conditional variable.");
13197 StringRef UniqueName = It->second;
13198 llvm::GlobalVariable *GV =
CGM.getModule().getNamedGlobal(UniqueName);
13212 llvm_unreachable(
"Not supported in SIMD-only mode");
13219 llvm_unreachable(
"Not supported in SIMD-only mode");
13226 bool Tied,
unsigned &NumberOfParts) {
13227 llvm_unreachable(
"Not supported in SIMD-only mode");
13235 llvm_unreachable(
"Not supported in SIMD-only mode");
13241 const Expr *Hint) {
13242 llvm_unreachable(
"Not supported in SIMD-only mode");
13248 llvm_unreachable(
"Not supported in SIMD-only mode");
13254 const Expr *Filter) {
13255 llvm_unreachable(
"Not supported in SIMD-only mode");
13260 llvm_unreachable(
"Not supported in SIMD-only mode");
13266 llvm_unreachable(
"Not supported in SIMD-only mode");
13274 llvm_unreachable(
"Not supported in SIMD-only mode");
13281 llvm_unreachable(
"Not supported in SIMD-only mode");
13288 bool ForceSimpleCall) {
13289 llvm_unreachable(
"Not supported in SIMD-only mode");
13296 llvm_unreachable(
"Not supported in SIMD-only mode");
13301 llvm_unreachable(
"Not supported in SIMD-only mode");
13307 llvm_unreachable(
"Not supported in SIMD-only mode");
13313 llvm_unreachable(
"Not supported in SIMD-only mode");
13320 llvm_unreachable(
"Not supported in SIMD-only mode");
13326 llvm_unreachable(
"Not supported in SIMD-only mode");
13331 unsigned IVSize,
bool IVSigned,
13334 llvm_unreachable(
"Not supported in SIMD-only mode");
13342 llvm_unreachable(
"Not supported in SIMD-only mode");
13346 ProcBindKind ProcBind,
13348 llvm_unreachable(
"Not supported in SIMD-only mode");
13355 llvm_unreachable(
"Not supported in SIMD-only mode");
13361 llvm_unreachable(
"Not supported in SIMD-only mode");
13366 llvm_unreachable(
"Not supported in SIMD-only mode");
13372 llvm::AtomicOrdering AO) {
13373 llvm_unreachable(
"Not supported in SIMD-only mode");
13378 llvm::Function *TaskFunction,
13380 const Expr *IfCond,
13382 llvm_unreachable(
"Not supported in SIMD-only mode");
13389 llvm_unreachable(
"Not supported in SIMD-only mode");
13396 assert(Options.
SimpleReduction &&
"Only simple reduction is expected.");
13398 ReductionOps, Options);
13404 llvm_unreachable(
"Not supported in SIMD-only mode");
13409 bool IsWorksharingReduction) {
13410 llvm_unreachable(
"Not supported in SIMD-only mode");
13417 llvm_unreachable(
"Not supported in SIMD-only mode");
13422 llvm::Value *ReductionsPtr,
13424 llvm_unreachable(
"Not supported in SIMD-only mode");
13430 llvm_unreachable(
"Not supported in SIMD-only mode");
13436 llvm_unreachable(
"Not supported in SIMD-only mode");
13442 llvm_unreachable(
"Not supported in SIMD-only mode");
13447 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
13449 llvm_unreachable(
"Not supported in SIMD-only mode");
13454 llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID,
const Expr *IfCond,
13455 llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier>
Device,
13459 llvm_unreachable(
"Not supported in SIMD-only mode");
13463 llvm_unreachable(
"Not supported in SIMD-only mode");
13467 llvm_unreachable(
"Not supported in SIMD-only mode");
13477 llvm::Function *OutlinedFn,
13479 llvm_unreachable(
"Not supported in SIMD-only mode");
13483 const Expr *NumTeams,
13484 const Expr *ThreadLimit,
13486 llvm_unreachable(
"Not supported in SIMD-only mode");
13493 llvm_unreachable(
"Not supported in SIMD-only mode");
13499 llvm_unreachable(
"Not supported in SIMD-only mode");
13505 llvm_unreachable(
"Not supported in SIMD-only mode");
13510 llvm_unreachable(
"Not supported in SIMD-only mode");
13515 llvm_unreachable(
"Not supported in SIMD-only mode");
13520 const VarDecl *NativeParam)
const {
13521 llvm_unreachable(
"Not supported in SIMD-only mode");
13527 const VarDecl *TargetParam)
const {
13528 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)
This represents clause 'affinity' in the 'pragma omp task'-based directives.
ValueDecl * getAssociatedDeclaration() const
Expr * getAssociatedExpression() const
static std::pair< const Expr *, std::optional< size_t > > findAttachPtrExpr(MappableExprComponentListRef Components, OpenMPDirectiveKind CurDirKind)
Find the attach pointer expression from a list of mappable expression components.
static QualType getComponentExprElementType(const Expr *Exp)
Get the type of an element of a ComponentList Expr Exp.
ArrayRef< MappableComponent > MappableExprComponentListRef
This represents implicit clause 'depend' for the 'pragma omp task' directive.
This represents 'detach' clause in the 'pragma omp task' directive.
This represents 'device' clause in the 'pragma omp ...' directive.
This represents the 'doacross' clause for the 'pragma omp ordered' directive.
This represents 'dyn_groupprivate' clause in 'pragma omp target ...' and 'pragma omp teams ....
This represents clause 'map' in the 'pragma omp ...' directives.
This represents clause 'nontemporal' in the 'pragma omp ...' directives.
This represents 'num_teams' clause in the 'pragma omp ...' directive.
This represents 'thread_limit' clause in the 'pragma omp ...' directive.
This represents clause 'uses_allocators' in the 'pragma omp target'-based directives.
This represents 'ompx_attribute' clause in a directive that might generate an outlined function.
This represents 'ompx_bare' clause in the 'pragma omp target teams ...' directive.
This represents 'ompx_dyn_cgroup_mem' clause in the 'pragma omp target ...' directive.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
SourceManager & getSourceManager()
const ConstantArrayType * getAsConstantArrayType(QualType T) const
CharUnits getTypeAlignInChars(QualType T) const
Return the ABI-specified alignment of a (complete) type T, in characters.
const ASTRecordLayout & getASTRecordLayout(const RecordDecl *D) const
Get or compute information about the layout of the specified record (struct/union/class) D,...
QualType getPointerType(QualType T) const
Return the uniqued reference to the type for a pointer to the specified type.
QualType getConstantArrayType(QualType EltTy, const llvm::APInt &ArySize, const Expr *SizeExpr, ArraySizeModifier ASM, unsigned IndexTypeQuals) const
Return the unique reference to the type for a constant array of the specified element type.
const LangOptions & getLangOpts() const
QualType getIntTypeForBitwidth(unsigned DestWidth, unsigned Signed) const
getIntTypeForBitwidth - sets integer QualTy according to specified details: bitwidth,...
CharUnits getDeclAlign(const Decl *D, bool ForAlignof=false) const
Return a conservative estimate of the alignment of the specified decl D.
int64_t toBits(CharUnits CharSize) const
Convert a size in characters to a size in bits.
const ArrayType * getAsArrayType(QualType T) const
Type Query functions.
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
static bool hasSameType(QualType T1, QualType T2)
Determine whether the given types T1 and T2 are equivalent.
const VariableArrayType * getAsVariableArrayType(QualType T) const
QualType getSizeType() const
Return the unique type for "size_t" (C99 7.17), defined in <stddef.h>.
unsigned getTypeAlign(QualType T) const
Return the ABI-specified alignment of a (complete) type T, in bits.
CharUnits getSize() const
getSize - Get the record size in characters.
uint64_t getFieldOffset(unsigned FieldNo) const
getFieldOffset - Get the offset of the given field index, in bits.
CharUnits getNonVirtualSize() const
getNonVirtualSize - Get the non-virtual size (in chars) of an object, which is the size of the object...
static QualType getBaseOriginalType(const Expr *Base)
Return original type of the base expression for array section.
Represents an array type, per C99 6.7.5.2 - Array Declarators.
Attr - This represents one attribute.
Represents a base class of a C++ class.
Represents a C++ constructor within a class.
Represents a C++ destructor within a class.
const CXXRecordDecl * getParent() const
Return the parent of this method declaration, which is the class in which this method is defined.
QualType getFunctionObjectParameterType() const
Represents a C++ struct/union/class.
bool isLambda() const
Determine whether this class describes a lambda function object.
void getCaptureFields(llvm::DenseMap< const ValueDecl *, FieldDecl * > &Captures, FieldDecl *&ThisCapture) const
For a closure type, retrieve the mapping from captured variables and this to the non-static data memb...
unsigned getNumBases() const
Retrieves the number of base classes of this class.
base_class_range vbases()
capture_const_range captures() const
CXXDestructorDecl * getDestructor() const
Returns the destructor decl for this class.
CanProxy< U > castAs() const
A wrapper class around a pointer that always points to its canonical declaration.
Describes the capture of either a variable, or 'this', or variable-length array type.
bool capturesVariableByCopy() const
Determine whether this capture handles a variable by copy.
VarDecl * getCapturedVar() const
Retrieve the declaration of the variable being captured.
bool capturesVariableArrayType() const
Determine whether this capture handles a variable-length array type.
bool capturesThis() const
Determine whether this capture handles the C++ 'this' pointer.
bool capturesVariable() const
Determine whether this capture handles a variable (by reference).
This captures a statement into a function.
const Capture * const_capture_iterator
capture_iterator capture_end() const
Retrieve an iterator pointing past the end of the sequence of captures.
const RecordDecl * getCapturedRecordDecl() const
Retrieve the record declaration for captured variables.
Stmt * getCapturedStmt()
Retrieve the statement being captured.
bool capturesVariable(const VarDecl *Var) const
True if this variable has been captured.
capture_iterator capture_begin()
Retrieve an iterator pointing to the first capture.
CharUnits - This is an opaque type for sizes expressed in character units.
bool isZero() const
isZero - Test whether the quantity equals zero.
llvm::Align getAsAlign() const
getAsAlign - Returns Quantity as a valid llvm::Align, Beware llvm::Align assumes power of two 8-bit b...
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
CharUnits alignmentOfArrayElement(CharUnits elementSize) const
Given that this is the alignment of the first element of an array, return the minimum alignment of an...
static CharUnits fromQuantity(QuantityType Quantity)
fromQuantity - Construct a CharUnits quantity from a raw integer type.
CharUnits alignTo(const CharUnits &Align) const
alignTo - Returns the next integer (mod 2**64) that is greater than or equal to this quantity and is ...
Like RawAddress, an abstract representation of an aligned address, but the pointer contained in this ...
llvm::Value * emitRawPointer(CodeGenFunction &CGF) const
Return the pointer contained in this class after authenticating it and adding offset to it if necessa...
CharUnits getAlignment() const
llvm::Type * getElementType() const
Return the type of the values stored in this address.
Address withPointer(llvm::Value *NewPointer, KnownNonNull_t IsKnownNonNull) const
Return address with different pointer, but same element type and alignment.
Address withElementType(llvm::Type *ElemTy) const
Return address with different element type, but same pointer and alignment.
llvm::PointerType * getType() const
Return the type of the pointer value.
static ApplyDebugLocation CreateArtificial(CodeGenFunction &CGF)
Apply TemporaryLocation if it is valid.
static ApplyDebugLocation CreateDefaultArtificial(CodeGenFunction &CGF, SourceLocation TemporaryLocation)
Apply TemporaryLocation if it is valid.
static ApplyDebugLocation CreateEmpty(CodeGenFunction &CGF)
Set the IRBuilder to not attach debug locations.
llvm::StoreInst * CreateStore(llvm::Value *Val, Address Addr, bool IsVolatile=false)
Address CreateGEP(CodeGenFunction &CGF, Address Addr, llvm::Value *Index, const llvm::Twine &Name="")
Address CreatePointerBitCastOrAddrSpaceCast(Address Addr, llvm::Type *Ty, llvm::Type *ElementTy, const llvm::Twine &Name="")
Address CreateConstArrayGEP(Address Addr, uint64_t Index, const llvm::Twine &Name="")
Given addr = [n x T]* ... produce name = getelementptr inbounds addr, i64 0, i64 index where i64 is a...
llvm::LoadInst * CreateLoad(Address Addr, const llvm::Twine &Name="")
llvm::CallInst * CreateMemCpy(Address Dest, Address Src, llvm::Value *Size, bool IsVolatile=false)
Address CreateConstGEP(Address Addr, uint64_t Index, const llvm::Twine &Name="")
Given addr = T* ... produce name = getelementptr inbounds addr, i64 index where i64 is actually the t...
Address CreateAddrSpaceCast(Address Addr, llvm::Type *Ty, llvm::Type *ElementTy, const llvm::Twine &Name="")
CGFunctionInfo - Class to encapsulate the information about a function definition.
DisableAutoDeclareTargetRAII(CodeGenModule &CGM)
~DisableAutoDeclareTargetRAII()
~LastprivateConditionalRAII()
static LastprivateConditionalRAII disable(CodeGenFunction &CGF, const OMPExecutableDirective &S)
NontemporalDeclsRAII(CodeGenModule &CGM, const OMPLoopDirective &S)
Struct that keeps all the relevant information that should be kept throughout a 'target data' region.
llvm::DenseMap< const ValueDecl *, llvm::Value * > CaptureDeviceAddrMap
Map between the a declaration of a capture and the corresponding new llvm address where the runtime r...
~UntiedTaskLocalDeclsRAII()
UntiedTaskLocalDeclsRAII(CodeGenFunction &CGF, const llvm::MapVector< CanonicalDeclPtr< const VarDecl >, std::pair< Address, Address > > &LocalVars)
virtual Address emitThreadIDAddress(CodeGenFunction &CGF, SourceLocation Loc)
Emits address of the word in a memory where current thread id is stored.
llvm::StringSet ThreadPrivateWithDefinition
Set of threadprivate variables with the generated initializer.
CGOpenMPRuntime(CodeGenModule &CGM)
virtual void emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc, const OMPExecutableDirective &D, llvm::Function *TaskFunction, QualType SharedsTy, Address Shareds, const Expr *IfCond, const OMPTaskDataTy &Data)
Emit task region for the task directive.
void createOffloadEntriesAndInfoMetadata()
Creates all the offload entries in the current compilation unit along with the associated metadata.
const Expr * getNumTeamsExprForTargetDirective(CodeGenFunction &CGF, const OMPExecutableDirective &D, int32_t &MinTeamsVal, int32_t &MaxTeamsVal)
Emit the number of teams for a target directive.
virtual Address getAddrOfThreadPrivate(CodeGenFunction &CGF, const VarDecl *VD, Address VDAddr, SourceLocation Loc)
Returns address of the threadprivate variable for the current thread.
void emitDeferredTargetDecls() const
Emit deferred declare target variables marked for deferred emission.
virtual llvm::Value * emitForNext(CodeGenFunction &CGF, SourceLocation Loc, unsigned IVSize, bool IVSigned, Address IL, Address LB, Address UB, Address ST)
Call __kmpc_dispatch_next( ident_t *loc, kmp_int32 tid, kmp_int32 *p_lastiter, kmp_int[32|64] *p_lowe...
bool markAsGlobalTarget(GlobalDecl GD)
Marks the declaration as already emitted for the device code and returns true, if it was marked alrea...
virtual void emitParallelCall(CodeGenFunction &CGF, SourceLocation Loc, llvm::Function *OutlinedFn, ArrayRef< llvm::Value * > CapturedVars, const Expr *IfCond, llvm::Value *NumThreads, OpenMPNumThreadsClauseModifier NumThreadsModifier=OMPC_NUMTHREADS_unknown, OpenMPSeverityClauseKind Severity=OMPC_SEVERITY_fatal, const Expr *Message=nullptr)
Emits code for parallel or serial call of the OutlinedFn with variables captured in a record which ad...
llvm::SmallDenseSet< CanonicalDeclPtr< const Decl > > NontemporalDeclsSet
virtual void emitTargetDataStandAloneCall(CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, const Expr *Device)
Emit the data mapping/movement code associated with the directive D that should be of the form 'targe...
virtual void emitNumThreadsClause(CodeGenFunction &CGF, llvm::Value *NumThreads, SourceLocation Loc, OpenMPNumThreadsClauseModifier Modifier=OMPC_NUMTHREADS_unknown, OpenMPSeverityClauseKind Severity=OMPC_SEVERITY_fatal, SourceLocation SeverityLoc=SourceLocation(), const Expr *Message=nullptr, SourceLocation MessageLoc=SourceLocation())
Emits call to void __kmpc_push_num_threads(ident_t *loc, kmp_int32global_tid, kmp_int32 num_threads) ...
QualType SavedKmpTaskloopTQTy
Saved kmp_task_t for taskloop-based directive.
virtual void emitSingleRegion(CodeGenFunction &CGF, const RegionCodeGenTy &SingleOpGen, SourceLocation Loc, ArrayRef< const Expr * > CopyprivateVars, ArrayRef< const Expr * > DestExprs, ArrayRef< const Expr * > SrcExprs, ArrayRef< const Expr * > AssignmentOps)
Emits a single region.
virtual bool emitTargetGlobal(GlobalDecl GD)
Emit the global GD if it is meaningful for the target.
void setLocThreadIdInsertPt(CodeGenFunction &CGF, bool AtCurrentPoint=false)
std::string getOutlinedHelperName(StringRef Name) const
Get the function name of an outlined region.
bool HasEmittedDeclareTargetRegion
Flag for keeping track of weather a device routine has been emitted.
llvm::Constant * getOrCreateThreadPrivateCache(const VarDecl *VD)
If the specified mangled name is not in the module, create and return threadprivate cache object.
virtual Address getTaskReductionItem(CodeGenFunction &CGF, SourceLocation Loc, llvm::Value *ReductionsPtr, LValue SharedLVal)
Get the address of void * type of the privatue copy of the reduction item specified by the SharedLVal...
virtual void emitForDispatchDeinit(CodeGenFunction &CGF, SourceLocation Loc)
This is used for non static scheduled types and when the ordered clause is present on the loop constr...
void emitCall(CodeGenFunction &CGF, SourceLocation Loc, llvm::FunctionCallee Callee, ArrayRef< llvm::Value * > Args={}) const
Emits Callee function call with arguments Args with location Loc.
virtual void getDefaultScheduleAndChunk(CodeGenFunction &CGF, const OMPLoopDirective &S, OpenMPScheduleClauseKind &ScheduleKind, const Expr *&ChunkExpr) const
Choose default schedule type and chunk value for the schedule clause.
virtual std::pair< llvm::Function *, llvm::Function * > getUserDefinedReduction(const OMPDeclareReductionDecl *D)
Get combiner/initializer for the specified user-defined reduction, if any.
virtual bool isGPU() const
Returns true if the current target is a GPU.
static const Stmt * getSingleCompoundChild(ASTContext &Ctx, const Stmt *Body)
Checks if the Body is the CompoundStmt and returns its child statement iff there is only one that is ...
virtual void emitDeclareTargetFunction(const FunctionDecl *FD, llvm::GlobalValue *GV)
Emit code for handling declare target functions in the runtime.
bool HasRequiresUnifiedSharedMemory
Flag for keeping track of weather a requires unified_shared_memory directive is present.
llvm::Value * emitUpdateLocation(CodeGenFunction &CGF, SourceLocation Loc, unsigned Flags=0, bool EmitLoc=false)
Emits object of ident_t type with info for source location.
bool isLocalVarInUntiedTask(CodeGenFunction &CGF, const VarDecl *VD) const
Returns true if the variable is a local variable in untied task.
virtual void emitTeamsCall(CodeGenFunction &CGF, const OMPExecutableDirective &D, SourceLocation Loc, llvm::Function *OutlinedFn, ArrayRef< llvm::Value * > CapturedVars)
Emits code for teams call of the OutlinedFn with variables captured in a record which address is stor...
virtual void emitCancellationPointCall(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind CancelRegion)
Emit code for 'cancellation point' construct.
virtual llvm::Function * emitThreadPrivateVarDefinition(const VarDecl *VD, Address VDAddr, SourceLocation Loc, bool PerformInit, CodeGenFunction *CGF=nullptr)
Emit a code for initialization of threadprivate variable.
FunctionUDMMapTy FunctionUDMMap
virtual ConstantAddress getAddrOfDeclareTargetVar(const VarDecl *VD)
Returns the address of the variable marked as declare target with link clause OR as declare target wi...
llvm::Function * getOrCreateUserDefinedMapperFunc(const OMPDeclareMapperDecl *D)
Get the function for the specified user-defined mapper.
OpenMPLocThreadIDMapTy OpenMPLocThreadIDMap
virtual void functionFinished(CodeGenFunction &CGF)
Cleans up references to the objects in finished function.
virtual llvm::Function * emitTeamsOutlinedFunction(CodeGenFunction &CGF, const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen)
Emits outlined function for the specified OpenMP teams directive D.
QualType KmpTaskTQTy
Type typedef struct kmp_task { void * shareds; /**< pointer to block of pointers to shared vars / k...
llvm::OpenMPIRBuilder OMPBuilder
An OpenMP-IR-Builder instance.
virtual void emitDoacrossInit(CodeGenFunction &CGF, const OMPLoopDirective &D, ArrayRef< Expr * > NumIterations)
Emit initialization for doacross loop nesting support.
virtual void adjustTargetSpecificDataForLambdas(CodeGenFunction &CGF, const OMPExecutableDirective &D) const
Adjust some parameters for the target-based directives, like addresses of the variables captured by r...
FunctionUDRMapTy FunctionUDRMap
virtual void emitTargetDataCalls(CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, const Expr *Device, const RegionCodeGenTy &CodeGen, CGOpenMPRuntime::TargetDataInfo &Info)
Emit the target data mapping code associated with D.
virtual unsigned getDefaultLocationReserved2Flags() const
Returns additional flags that can be stored in reserved_2 field of the default location.
virtual Address getParameterAddress(CodeGenFunction &CGF, const VarDecl *NativeParam, const VarDecl *TargetParam) const
Gets the address of the native argument basing on the address of the target-specific parameter.
void emitUsesAllocatorsFini(CodeGenFunction &CGF, const Expr *Allocator)
Destroys user defined allocators specified in the uses_allocators clause.
QualType KmpTaskAffinityInfoTy
Type typedef struct kmp_task_affinity_info { kmp_intptr_t base_addr; size_t len; struct { bool flag1 ...
void emitPrivateReduction(CodeGenFunction &CGF, SourceLocation Loc, const Expr *Privates, const Expr *LHSExprs, const Expr *RHSExprs, const Expr *ReductionOps)
Emits code for private variable reduction.
llvm::Value * emitNumTeamsForTargetDirective(CodeGenFunction &CGF, const OMPExecutableDirective &D)
virtual void emitTargetOutlinedFunctionHelper(const OMPExecutableDirective &D, StringRef ParentName, llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID, bool IsOffloadEntry, const RegionCodeGenTy &CodeGen)
Helper to emit outlined function for 'target' directive.
void scanForTargetRegionsFunctions(const Stmt *S, StringRef ParentName)
Start scanning from statement S and emit all target regions found along the way.
SmallVector< llvm::Value *, 4 > emitDepobjElementsSizes(CodeGenFunction &CGF, QualType &KmpDependInfoTy, const OMPTaskDataTy::DependData &Data)
virtual llvm::Value * emitMessageClause(CodeGenFunction &CGF, const Expr *Message, SourceLocation Loc)
virtual void emitTaskgroupRegion(CodeGenFunction &CGF, const RegionCodeGenTy &TaskgroupOpGen, SourceLocation Loc)
Emit a taskgroup region.
llvm::DenseMap< llvm::Function *, llvm::DenseMap< CanonicalDeclPtr< const Decl >, std::tuple< QualType, const FieldDecl *, const FieldDecl *, LValue > > > LastprivateConditionalToTypes
Maps local variables marked as lastprivate conditional to their internal types.
virtual bool emitTargetGlobalVariable(GlobalDecl GD)
Emit the global variable if it is a valid device global variable.
virtual void emitNumTeamsClause(CodeGenFunction &CGF, const Expr *NumTeams, const Expr *ThreadLimit, SourceLocation Loc)
Emits call to void __kmpc_push_num_teams(ident_t *loc, kmp_int32global_tid, kmp_int32 num_teams,...
bool hasRequiresUnifiedSharedMemory() const
Return whether the unified_shared_memory has been specified.
virtual Address getAddrOfArtificialThreadPrivate(CodeGenFunction &CGF, QualType VarType, StringRef Name)
Creates artificial threadprivate variable with name Name and type VarType.
void emitUserDefinedMapper(const OMPDeclareMapperDecl *D, CodeGenFunction *CGF=nullptr)
Emit the function for the user defined mapper construct.
bool HasEmittedTargetRegion
Flag for keeping track of weather a target region has been emitted.
void emitDepobjElements(CodeGenFunction &CGF, QualType &KmpDependInfoTy, LValue PosLVal, const OMPTaskDataTy::DependData &Data, Address DependenciesArray)
std::string getReductionFuncName(StringRef Name) const
Get the function name of a reduction function.
virtual void processRequiresDirective(const OMPRequiresDecl *D)
Perform check on requires decl to ensure that target architecture supports unified addressing.
llvm::DenseSet< CanonicalDeclPtr< const Decl > > AlreadyEmittedTargetDecls
List of the emitted declarations.
virtual llvm::Value * emitTaskReductionInit(CodeGenFunction &CGF, SourceLocation Loc, ArrayRef< const Expr * > LHSExprs, ArrayRef< const Expr * > RHSExprs, const OMPTaskDataTy &Data)
Emit a code for initialization of task reduction clause.
llvm::Value * getThreadID(CodeGenFunction &CGF, SourceLocation Loc)
Gets thread id value for the current thread.
void emitUpdateClause(CodeGenFunction &CGF, LValue DepobjLVal, OpenMPDependClauseKind NewDepKind, SourceLocation Loc)
Updates the dependency kind in the specified depobj object.
virtual void emitLastprivateConditionalFinalUpdate(CodeGenFunction &CGF, LValue PrivLVal, const VarDecl *VD, SourceLocation Loc)
Gets the address of the global copy used for lastprivate conditional update, if any.
llvm::MapVector< CanonicalDeclPtr< const VarDecl >, std::pair< Address, Address > > UntiedLocalVarsAddressesMap
virtual void emitErrorCall(CodeGenFunction &CGF, SourceLocation Loc, Expr *ME, bool IsFatal)
Emit __kmpc_error call for error directive extern void __kmpc_error(ident_t *loc, int severity,...
void clearLocThreadIdInsertPt(CodeGenFunction &CGF)
virtual void emitTaskyieldCall(CodeGenFunction &CGF, SourceLocation Loc)
Emits code for a taskyield directive.
std::string getName(ArrayRef< StringRef > Parts) const
Get the platform-specific name separator.
QualType KmpRoutineEntryPtrQTy
void computeMinAndMaxThreadsAndTeams(const OMPExecutableDirective &D, CodeGenFunction &CGF, llvm::OpenMPIRBuilder::TargetKernelDefaultAttrs &Attrs)
Helper to determine the min/max number of threads/teams for D.
virtual void emitFlush(CodeGenFunction &CGF, ArrayRef< const Expr * > Vars, SourceLocation Loc, llvm::AtomicOrdering AO)
Emit flush of the variables specified in 'omp flush' directive.
virtual void emitTaskwaitCall(CodeGenFunction &CGF, SourceLocation Loc, const OMPTaskDataTy &Data)
Emit code for 'taskwait' directive.
virtual void emitProcBindClause(CodeGenFunction &CGF, llvm::omp::ProcBindKind ProcBind, SourceLocation Loc)
Emit call to void __kmpc_push_proc_bind(ident_t *loc, kmp_int32global_tid, int proc_bind) to generate...
void emitLastprivateConditionalUpdate(CodeGenFunction &CGF, LValue IVLVal, StringRef UniqueDeclName, LValue LVal, SourceLocation Loc)
Emit update for lastprivate conditional data.
virtual void emitTaskLoopCall(CodeGenFunction &CGF, SourceLocation Loc, const OMPLoopDirective &D, llvm::Function *TaskFunction, QualType SharedsTy, Address Shareds, const Expr *IfCond, const OMPTaskDataTy &Data)
Emit task region for the taskloop directive.
virtual void emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind Kind, bool EmitChecks=true, bool ForceSimpleCall=false)
Emit an implicit/explicit barrier for OpenMP threads.
static unsigned getDefaultFlagsForBarriers(OpenMPDirectiveKind Kind)
Returns default flags for the barriers depending on the directive, for which this barier is going to ...
virtual bool emitTargetFunctions(GlobalDecl GD)
Emit the target regions enclosed in GD function definition or the function itself in case it is a val...
TaskResultTy emitTaskInit(CodeGenFunction &CGF, SourceLocation Loc, const OMPExecutableDirective &D, llvm::Function *TaskFunction, QualType SharedsTy, Address Shareds, const OMPTaskDataTy &Data)
Emit task region for the task directive.
llvm::Value * emitTargetNumIterationsCall(CodeGenFunction &CGF, const OMPExecutableDirective &D, llvm::function_ref< llvm::Value *(CodeGenFunction &CGF, const OMPLoopDirective &D)> SizeEmitter)
Return the trip count of loops associated with constructs / 'target teams distribute' and 'teams dist...
llvm::StringMap< llvm::AssertingVH< llvm::GlobalVariable >, llvm::BumpPtrAllocator > InternalVars
An ordered map of auto-generated variables to their unique names.
virtual void emitDistributeStaticInit(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDistScheduleClauseKind SchedKind, const StaticRTInput &Values)
llvm::SmallVector< UntiedLocalVarsAddressesMap, 4 > UntiedLocalVarsStack
virtual void emitForStaticFinish(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind DKind)
Call the appropriate runtime routine to notify that we finished all the work with current loop.
virtual void emitThreadLimitClause(CodeGenFunction &CGF, const Expr *ThreadLimit, SourceLocation Loc)
Emits call to void __kmpc_set_thread_limit(ident_t *loc, kmp_int32global_tid, kmp_int32 thread_limit)...
void emitIfClause(CodeGenFunction &CGF, const Expr *Cond, const RegionCodeGenTy &ThenGen, const RegionCodeGenTy &ElseGen)
Emits code for OpenMP 'if' clause using specified CodeGen function.
Address emitDepobjDependClause(CodeGenFunction &CGF, const OMPTaskDataTy::DependData &Dependencies, SourceLocation Loc)
Emits list of dependecies based on the provided data (array of dependence/expression pairs) for depob...
bool isNontemporalDecl(const ValueDecl *VD) const
Checks if the VD variable is marked as nontemporal declaration in current context.
virtual llvm::Function * emitParallelOutlinedFunction(CodeGenFunction &CGF, const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen)
Emits outlined function for the specified OpenMP parallel directive D.
const Expr * getNumThreadsExprForTargetDirective(CodeGenFunction &CGF, const OMPExecutableDirective &D, int32_t &UpperBound, bool UpperBoundOnly, llvm::Value **CondExpr=nullptr, const Expr **ThreadLimitExpr=nullptr)
Check for a number of threads upper bound constant value (stored in UpperBound), or expression (retur...
virtual void registerVTableOffloadEntry(llvm::GlobalVariable *VTable, const VarDecl *VD)
Register VTable to OpenMP offload entry.
virtual llvm::Value * emitSeverityClause(OpenMPSeverityClauseKind Severity, SourceLocation Loc)
llvm::SmallVector< LastprivateConditionalData, 4 > LastprivateConditionalStack
Stack for list of addresses of declarations in current context marked as lastprivate conditional.
virtual void emitForStaticInit(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind DKind, const OpenMPScheduleTy &ScheduleKind, const StaticRTInput &Values)
Call the appropriate runtime routine to initialize it before start of loop.
virtual void emitDeclareSimdFunction(const FunctionDecl *FD, llvm::Function *Fn)
Marks function Fn with properly mangled versions of vector functions.
llvm::AtomicOrdering getDefaultMemoryOrdering() const
Gets default memory ordering as specified in requires directive.
virtual bool isStaticNonchunked(OpenMPScheduleClauseKind ScheduleKind, bool Chunked) const
Check if the specified ScheduleKind is static non-chunked.
virtual void emitAndRegisterVTable(CodeGenModule &CGM, CXXRecordDecl *CXXRecord, const VarDecl *VD)
Emit and register VTable for the C++ class in OpenMP offload entry.
llvm::Value * getCriticalRegionLock(StringRef CriticalName)
Returns corresponding lock object for the specified critical region name.
virtual void emitCancelCall(CodeGenFunction &CGF, SourceLocation Loc, const Expr *IfCond, OpenMPDirectiveKind CancelRegion)
Emit code for 'cancel' construct.
QualType SavedKmpTaskTQTy
Saved kmp_task_t for task directive.
virtual void emitMasterRegion(CodeGenFunction &CGF, const RegionCodeGenTy &MasterOpGen, SourceLocation Loc)
Emits a master region.
virtual llvm::Function * emitTaskOutlinedFunction(const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, const VarDecl *PartIDVar, const VarDecl *TaskTVar, OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen, bool Tied, unsigned &NumberOfParts)
Emits outlined function for the OpenMP task directive D.
llvm::DenseMap< llvm::Function *, unsigned > FunctionToUntiedTaskStackMap
Maps function to the position of the untied task locals stack.
void emitDestroyClause(CodeGenFunction &CGF, LValue DepobjLVal, SourceLocation Loc)
Emits the code to destroy the dependency object provided in depobj directive.
virtual void emitTaskReductionFixups(CodeGenFunction &CGF, SourceLocation Loc, ReductionCodeGen &RCG, unsigned N)
Required to resolve existing problems in the runtime.
llvm::ArrayType * KmpCriticalNameTy
Type kmp_critical_name, originally defined as typedef kmp_int32 kmp_critical_name[8];.
virtual void emitDoacrossOrdered(CodeGenFunction &CGF, const OMPDependClause *C)
Emit code for doacross ordered directive with 'depend' clause.
llvm::DenseMap< const OMPDeclareMapperDecl *, llvm::Function * > UDMMap
Map from the user-defined mapper declaration to its corresponding functions.
virtual void checkAndEmitLastprivateConditional(CodeGenFunction &CGF, const Expr *LHS)
Checks if the provided LVal is lastprivate conditional and emits the code to update the value of the ...
std::pair< llvm::Value *, LValue > getDepobjElements(CodeGenFunction &CGF, LValue DepobjLVal, SourceLocation Loc)
Returns the number of the elements and the address of the depobj dependency array.
llvm::SmallDenseSet< const VarDecl * > DeferredGlobalVariables
List of variables that can become declare target implicitly and, thus, must be emitted.
void emitUsesAllocatorsInit(CodeGenFunction &CGF, const Expr *Allocator, const Expr *AllocatorTraits)
Initializes user defined allocators specified in the uses_allocators clauses.
virtual void registerVTable(const OMPExecutableDirective &D)
Emit code for registering vtable by scanning through map clause in OpenMP target region.
llvm::Type * KmpRoutineEntryPtrTy
Type typedef kmp_int32 (* kmp_routine_entry_t)(kmp_int32, void *);.
llvm::Type * getIdentTyPointerTy()
Returns pointer to ident_t type.
void emitSingleReductionCombiner(CodeGenFunction &CGF, const Expr *ReductionOp, const Expr *PrivateRef, const DeclRefExpr *LHS, const DeclRefExpr *RHS)
Emits single reduction combiner.
llvm::OpenMPIRBuilder & getOMPBuilder()
virtual void emitTargetOutlinedFunction(const OMPExecutableDirective &D, StringRef ParentName, llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID, bool IsOffloadEntry, const RegionCodeGenTy &CodeGen)
Emit outilined function for 'target' directive.
virtual void emitCriticalRegion(CodeGenFunction &CGF, StringRef CriticalName, const RegionCodeGenTy &CriticalOpGen, SourceLocation Loc, const Expr *Hint=nullptr)
Emits a critical region.
virtual void emitForOrderedIterationEnd(CodeGenFunction &CGF, SourceLocation Loc, unsigned IVSize, bool IVSigned)
Call the appropriate runtime routine to notify that we finished iteration of the ordered loop with th...
virtual void emitOutlinedFunctionCall(CodeGenFunction &CGF, SourceLocation Loc, llvm::FunctionCallee OutlinedFn, ArrayRef< llvm::Value * > Args={}) const
Emits call of the outlined function with the provided arguments, translating these arguments to corre...
llvm::Value * emitNumThreadsForTargetDirective(CodeGenFunction &CGF, const OMPExecutableDirective &D)
Emit an expression that denotes the number of threads a target region shall use.
void emitThreadPrivateVarInit(CodeGenFunction &CGF, Address VDAddr, llvm::Value *Ctor, llvm::Value *CopyCtor, llvm::Value *Dtor, SourceLocation Loc)
Emits initialization code for the threadprivate variables.
virtual void emitUserDefinedReduction(CodeGenFunction *CGF, const OMPDeclareReductionDecl *D)
Emit code for the specified user defined reduction construct.
virtual void checkAndEmitSharedLastprivateConditional(CodeGenFunction &CGF, const OMPExecutableDirective &D, const llvm::DenseSet< CanonicalDeclPtr< const VarDecl > > &IgnoredDecls)
Checks if the lastprivate conditional was updated in inner region and writes the value.
QualType KmpDimTy
struct kmp_dim { // loop bounds info casted to kmp_int64 kmp_int64 lo; // lower kmp_int64 up; // uppe...
virtual void emitInlinedDirective(CodeGenFunction &CGF, OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen, bool HasCancel=false)
Emit code for the directive that does not require outlining.
virtual void registerTargetGlobalVariable(const VarDecl *VD, llvm::Constant *Addr)
Checks if the provided global decl GD is a declare target variable and registers it when emitting cod...
virtual void emitFunctionProlog(CodeGenFunction &CGF, const Decl *D)
Emits OpenMP-specific function prolog.
void emitKmpRoutineEntryT(QualType KmpInt32Ty)
Build type kmp_routine_entry_t (if not built yet).
virtual bool isStaticChunked(OpenMPScheduleClauseKind ScheduleKind, bool Chunked) const
Check if the specified ScheduleKind is static chunked.
virtual void emitTargetCall(CodeGenFunction &CGF, const OMPExecutableDirective &D, llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID, const Expr *IfCond, llvm::PointerIntPair< const Expr *, 2, OpenMPDeviceClauseModifier > Device, llvm::function_ref< llvm::Value *(CodeGenFunction &CGF, const OMPLoopDirective &D)> SizeEmitter)
Emit the target offloading code associated with D.
virtual bool hasAllocateAttributeForGlobalVar(const VarDecl *VD, LangAS &AS)
Checks if the variable has associated OMPAllocateDeclAttr attribute with the predefined allocator and...
llvm::AtomicOrdering RequiresAtomicOrdering
Atomic ordering from the omp requires directive.
virtual void emitReduction(CodeGenFunction &CGF, SourceLocation Loc, ArrayRef< const Expr * > Privates, ArrayRef< const Expr * > LHSExprs, ArrayRef< const Expr * > RHSExprs, ArrayRef< const Expr * > ReductionOps, ReductionOptionsTy Options)
Emit a code for reduction clause.
std::pair< llvm::Value *, Address > emitDependClause(CodeGenFunction &CGF, ArrayRef< OMPTaskDataTy::DependData > Dependencies, SourceLocation Loc)
Emits list of dependecies based on the provided data (array of dependence/expression pairs).
llvm::StringMap< llvm::WeakTrackingVH > EmittedNonTargetVariables
List of the global variables with their addresses that should not be emitted for the target.
virtual bool isDynamic(OpenMPScheduleClauseKind ScheduleKind) const
Check if the specified ScheduleKind is dynamic.
Address emitLastprivateConditionalInit(CodeGenFunction &CGF, const VarDecl *VD)
Create specialized alloca to handle lastprivate conditionals.
virtual void emitOrderedRegion(CodeGenFunction &CGF, const RegionCodeGenTy &OrderedOpGen, SourceLocation Loc, bool IsThreads)
Emit an ordered region.
virtual Address getAddressOfLocalVariable(CodeGenFunction &CGF, const VarDecl *VD)
Gets the OpenMP-specific address of the local variable.
virtual void emitTaskReductionFini(CodeGenFunction &CGF, SourceLocation Loc, bool IsWorksharingReduction)
Emits the following code for reduction clause with task modifier:
virtual void emitMaskedRegion(CodeGenFunction &CGF, const RegionCodeGenTy &MaskedOpGen, SourceLocation Loc, const Expr *Filter=nullptr)
Emits a masked region.
QualType KmpDependInfoTy
Type typedef struct kmp_depend_info { kmp_intptr_t base_addr; size_t len; struct { bool in:1; bool ou...
llvm::Function * emitReductionFunction(StringRef ReducerName, SourceLocation Loc, llvm::Type *ArgsElemType, ArrayRef< const Expr * > Privates, ArrayRef< const Expr * > LHSExprs, ArrayRef< const Expr * > RHSExprs, ArrayRef< const Expr * > ReductionOps)
Emits reduction function.
virtual void emitForDispatchInit(CodeGenFunction &CGF, SourceLocation Loc, const OpenMPScheduleTy &ScheduleKind, unsigned IVSize, bool IVSigned, bool Ordered, const DispatchRTInput &DispatchValues)
Call the appropriate runtime routine to initialize it before start of loop.
Address getTaskReductionItem(CodeGenFunction &CGF, SourceLocation Loc, llvm::Value *ReductionsPtr, LValue SharedLVal) override
Get the address of void * type of the privatue copy of the reduction item specified by the SharedLVal...
void emitCriticalRegion(CodeGenFunction &CGF, StringRef CriticalName, const RegionCodeGenTy &CriticalOpGen, SourceLocation Loc, const Expr *Hint=nullptr) override
Emits a critical region.
void emitDistributeStaticInit(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDistScheduleClauseKind SchedKind, const StaticRTInput &Values) override
void emitForStaticInit(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind DKind, const OpenMPScheduleTy &ScheduleKind, const StaticRTInput &Values) override
Call the appropriate runtime routine to initialize it before start of loop.
bool emitTargetGlobalVariable(GlobalDecl GD) override
Emit the global variable if it is a valid device global variable.
llvm::Value * emitForNext(CodeGenFunction &CGF, SourceLocation Loc, unsigned IVSize, bool IVSigned, Address IL, Address LB, Address UB, Address ST) override
Call __kmpc_dispatch_next( ident_t *loc, kmp_int32 tid, kmp_int32 *p_lastiter, kmp_int[32|64] *p_lowe...
llvm::Function * emitThreadPrivateVarDefinition(const VarDecl *VD, Address VDAddr, SourceLocation Loc, bool PerformInit, CodeGenFunction *CGF=nullptr) override
Emit a code for initialization of threadprivate variable.
void emitTargetDataStandAloneCall(CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, const Expr *Device) override
Emit the data mapping/movement code associated with the directive D that should be of the form 'targe...
llvm::Function * emitTeamsOutlinedFunction(CodeGenFunction &CGF, const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) override
Emits outlined function for the specified OpenMP teams directive D.
void emitParallelCall(CodeGenFunction &CGF, SourceLocation Loc, llvm::Function *OutlinedFn, ArrayRef< llvm::Value * > CapturedVars, const Expr *IfCond, llvm::Value *NumThreads, OpenMPNumThreadsClauseModifier NumThreadsModifier=OMPC_NUMTHREADS_unknown, OpenMPSeverityClauseKind Severity=OMPC_SEVERITY_fatal, const Expr *Message=nullptr) override
Emits code for parallel or serial call of the OutlinedFn with variables captured in a record which ad...
void emitReduction(CodeGenFunction &CGF, SourceLocation Loc, ArrayRef< const Expr * > Privates, ArrayRef< const Expr * > LHSExprs, ArrayRef< const Expr * > RHSExprs, ArrayRef< const Expr * > ReductionOps, ReductionOptionsTy Options) override
Emit a code for reduction clause.
void emitFlush(CodeGenFunction &CGF, ArrayRef< const Expr * > Vars, SourceLocation Loc, llvm::AtomicOrdering AO) override
Emit flush of the variables specified in 'omp flush' directive.
void emitDoacrossOrdered(CodeGenFunction &CGF, const OMPDependClause *C) override
Emit code for doacross ordered directive with 'depend' clause.
void emitTaskyieldCall(CodeGenFunction &CGF, SourceLocation Loc) override
Emits a masked region.
Address getAddrOfArtificialThreadPrivate(CodeGenFunction &CGF, QualType VarType, StringRef Name) override
Creates artificial threadprivate variable with name Name and type VarType.
Address getAddrOfThreadPrivate(CodeGenFunction &CGF, const VarDecl *VD, Address VDAddr, SourceLocation Loc) override
Returns address of the threadprivate variable for the current thread.
void emitSingleRegion(CodeGenFunction &CGF, const RegionCodeGenTy &SingleOpGen, SourceLocation Loc, ArrayRef< const Expr * > CopyprivateVars, ArrayRef< const Expr * > DestExprs, ArrayRef< const Expr * > SrcExprs, ArrayRef< const Expr * > AssignmentOps) override
Emits a single region.
void emitTaskReductionFixups(CodeGenFunction &CGF, SourceLocation Loc, ReductionCodeGen &RCG, unsigned N) override
Required to resolve existing problems in the runtime.
llvm::Function * emitParallelOutlinedFunction(CodeGenFunction &CGF, const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) override
Emits outlined function for the specified OpenMP parallel directive D.
void emitCancellationPointCall(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind CancelRegion) override
Emit code for 'cancellation point' construct.
void emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind Kind, bool EmitChecks=true, bool ForceSimpleCall=false) override
Emit an implicit/explicit barrier for OpenMP threads.
Address getParameterAddress(CodeGenFunction &CGF, const VarDecl *NativeParam, const VarDecl *TargetParam) const override
Gets the address of the native argument basing on the address of the target-specific parameter.
void emitTeamsCall(CodeGenFunction &CGF, const OMPExecutableDirective &D, SourceLocation Loc, llvm::Function *OutlinedFn, ArrayRef< llvm::Value * > CapturedVars) override
Emits code for teams call of the OutlinedFn with variables captured in a record which address is stor...
void emitForOrderedIterationEnd(CodeGenFunction &CGF, SourceLocation Loc, unsigned IVSize, bool IVSigned) override
Call the appropriate runtime routine to notify that we finished iteration of the ordered loop with th...
bool emitTargetGlobal(GlobalDecl GD) override
Emit the global GD if it is meaningful for the target.
void emitTaskReductionFini(CodeGenFunction &CGF, SourceLocation Loc, bool IsWorksharingReduction) override
Emits the following code for reduction clause with task modifier:
void emitOrderedRegion(CodeGenFunction &CGF, const RegionCodeGenTy &OrderedOpGen, SourceLocation Loc, bool IsThreads) override
Emit an ordered region.
void emitForStaticFinish(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind DKind) override
Call the appropriate runtime routine to notify that we finished all the work with current loop.
llvm::Value * emitTaskReductionInit(CodeGenFunction &CGF, SourceLocation Loc, ArrayRef< const Expr * > LHSExprs, ArrayRef< const Expr * > RHSExprs, const OMPTaskDataTy &Data) override
Emit a code for initialization of task reduction clause.
void emitProcBindClause(CodeGenFunction &CGF, llvm::omp::ProcBindKind ProcBind, SourceLocation Loc) override
Emit call to void __kmpc_push_proc_bind(ident_t *loc, kmp_int32global_tid, int proc_bind) to generate...
void emitTargetOutlinedFunction(const OMPExecutableDirective &D, StringRef ParentName, llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID, bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) override
Emit outilined function for 'target' directive.
void emitMasterRegion(CodeGenFunction &CGF, const RegionCodeGenTy &MasterOpGen, SourceLocation Loc) override
Emits a master region.
void emitNumTeamsClause(CodeGenFunction &CGF, const Expr *NumTeams, const Expr *ThreadLimit, SourceLocation Loc) override
Emits call to void __kmpc_push_num_teams(ident_t *loc, kmp_int32global_tid, kmp_int32 num_teams,...
void emitForDispatchDeinit(CodeGenFunction &CGF, SourceLocation Loc) override
This is used for non static scheduled types and when the ordered clause is present on the loop constr...
const VarDecl * translateParameter(const FieldDecl *FD, const VarDecl *NativeParam) const override
Translates the native parameter of outlined function if this is required for target.
void emitNumThreadsClause(CodeGenFunction &CGF, llvm::Value *NumThreads, SourceLocation Loc, OpenMPNumThreadsClauseModifier Modifier=OMPC_NUMTHREADS_unknown, OpenMPSeverityClauseKind Severity=OMPC_SEVERITY_fatal, SourceLocation SeverityLoc=SourceLocation(), const Expr *Message=nullptr, SourceLocation MessageLoc=SourceLocation()) override
Emits call to void __kmpc_push_num_threads(ident_t *loc, kmp_int32global_tid, kmp_int32 num_threads) ...
void emitMaskedRegion(CodeGenFunction &CGF, const RegionCodeGenTy &MaskedOpGen, SourceLocation Loc, const Expr *Filter=nullptr) override
Emits a masked region.
void emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc, const OMPExecutableDirective &D, llvm::Function *TaskFunction, QualType SharedsTy, Address Shareds, const Expr *IfCond, const OMPTaskDataTy &Data) override
Emit task region for the task directive.
void emitTargetCall(CodeGenFunction &CGF, const OMPExecutableDirective &D, llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID, const Expr *IfCond, llvm::PointerIntPair< const Expr *, 2, OpenMPDeviceClauseModifier > Device, llvm::function_ref< llvm::Value *(CodeGenFunction &CGF, const OMPLoopDirective &D)> SizeEmitter) override
Emit the target offloading code associated with D.
bool emitTargetFunctions(GlobalDecl GD) override
Emit the target regions enclosed in GD function definition or the function itself in case it is a val...
void emitDoacrossInit(CodeGenFunction &CGF, const OMPLoopDirective &D, ArrayRef< Expr * > NumIterations) override
Emit initialization for doacross loop nesting support.
void emitCancelCall(CodeGenFunction &CGF, SourceLocation Loc, const Expr *IfCond, OpenMPDirectiveKind CancelRegion) override
Emit code for 'cancel' construct.
void emitTaskwaitCall(CodeGenFunction &CGF, SourceLocation Loc, const OMPTaskDataTy &Data) override
Emit code for 'taskwait' directive.
void emitTaskgroupRegion(CodeGenFunction &CGF, const RegionCodeGenTy &TaskgroupOpGen, SourceLocation Loc) override
Emit a taskgroup region.
void emitTargetDataCalls(CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, const Expr *Device, const RegionCodeGenTy &CodeGen, CGOpenMPRuntime::TargetDataInfo &Info) override
Emit the target data mapping code associated with D.
void emitForDispatchInit(CodeGenFunction &CGF, SourceLocation Loc, const OpenMPScheduleTy &ScheduleKind, unsigned IVSize, bool IVSigned, bool Ordered, const DispatchRTInput &DispatchValues) override
This is used for non static scheduled types and when the ordered clause is present on the loop constr...
llvm::Function * emitTaskOutlinedFunction(const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, const VarDecl *PartIDVar, const VarDecl *TaskTVar, OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen, bool Tied, unsigned &NumberOfParts) override
Emits outlined function for the OpenMP task directive D.
void emitTaskLoopCall(CodeGenFunction &CGF, SourceLocation Loc, const OMPLoopDirective &D, llvm::Function *TaskFunction, QualType SharedsTy, Address Shareds, const Expr *IfCond, const OMPTaskDataTy &Data) override
Emit task region for the taskloop directive.
unsigned getNonVirtualBaseLLVMFieldNo(const CXXRecordDecl *RD) const
llvm::StructType * getLLVMType() const
Return the "complete object" LLVM type associated with this record.
llvm::StructType * getBaseSubobjectLLVMType() const
Return the "base subobject" LLVM type associated with this record.
unsigned getLLVMFieldNo(const FieldDecl *FD) const
Return llvm::StructType element number that corresponds to the field FD.
unsigned getVirtualBaseIndex(const CXXRecordDecl *base) const
Return the LLVM field index corresponding to the given virtual base.
API for captured statement code generation.
virtual void EmitBody(CodeGenFunction &CGF, const Stmt *S)
Emit the captured statement body.
virtual const FieldDecl * lookup(const VarDecl *VD) const
Lookup the captured field decl for a variable.
RAII for correct setting/restoring of CapturedStmtInfo.
The scope used to remap some variables as private in the OpenMP loop body (or other captured region e...
bool Privatize()
Privatizes local variables previously registered as private.
bool addPrivate(const VarDecl *LocalVD, Address Addr)
Registers LocalVD variable as a private with Addr as the address of the corresponding private variabl...
An RAII object to set (and then clear) a mapping for an OpaqueValueExpr.
Enters a new scope for capturing cleanups, all of which will be executed once the scope is exited.
CodeGenFunction - This class organizes the per-function state that is used while generating LLVM code...
LValue EmitLoadOfReferenceLValue(LValue RefLVal)
void EmitBranchOnBoolExpr(const Expr *Cond, llvm::BasicBlock *TrueBlock, llvm::BasicBlock *FalseBlock, uint64_t TrueCount, Stmt::Likelihood LH=Stmt::LH_None, const Expr *ConditionalOp=nullptr, const VarDecl *ConditionalDecl=nullptr)
EmitBranchOnBoolExpr - Emit a branch on a boolean condition (e.g.
void emitDestroy(Address addr, QualType type, Destroyer *destroyer, bool useEHCleanupForArray)
emitDestroy - Immediately perform the destruction of the given object.
JumpDest getJumpDestInCurrentScope(llvm::BasicBlock *Target)
The given basic block lies in the current EH scope, but may be a target of a potentially scope-crossi...
static void EmitOMPTargetParallelDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetParallelDirective &S)
void EmitNullInitialization(Address DestPtr, QualType Ty)
EmitNullInitialization - Generate code to set a value of the given type to null, If the type contains...
Address LoadCXXThisAddress()
CGCapturedStmtInfo * CapturedStmtInfo
ComplexPairTy EmitLoadOfComplex(LValue src, SourceLocation loc)
EmitLoadOfComplex - Load a complex number from the specified l-value.
static void EmitOMPTargetDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetDirective &S)
Emit device code for the target directive.
static void EmitOMPTargetTeamsDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsDirective &S)
Emit device code for the target teams directive.
static void EmitOMPTargetTeamsDistributeDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsDistributeDirective &S)
Emit device code for the target teams distribute directive.
llvm::BasicBlock * createBasicBlock(const Twine &name="", llvm::Function *parent=nullptr, llvm::BasicBlock *before=nullptr)
createBasicBlock - Create an LLVM basic block.
const LangOptions & getLangOpts() const
AutoVarEmission EmitAutoVarAlloca(const VarDecl &var)
EmitAutoVarAlloca - Emit the alloca and debug information for a local variable.
void pushDestroy(QualType::DestructionKind dtorKind, Address addr, QualType type)
pushDestroy - Push the standard destructor for the given type as at least a normal cleanup.
Address EmitLoadOfPointer(Address Ptr, const PointerType *PtrTy, LValueBaseInfo *BaseInfo=nullptr, TBAAAccessInfo *TBAAInfo=nullptr)
Load a pointer with type PtrTy stored at address Ptr.
void EmitBranchThroughCleanup(JumpDest Dest)
EmitBranchThroughCleanup - Emit a branch from the current insert block through the normal cleanup han...
const Decl * CurCodeDecl
CurCodeDecl - This is the inner-most code context, which includes blocks.
Destroyer * getDestroyer(QualType::DestructionKind destructionKind)
llvm::AssertingVH< llvm::Instruction > AllocaInsertPt
AllocaInsertPoint - This is an instruction in the entry block before which we prefer to insert alloca...
void EmitAggregateAssign(LValue Dest, LValue Src, QualType EltTy)
Emit an aggregate assignment.
JumpDest ReturnBlock
ReturnBlock - Unified return block.
void EmitAggregateCopy(LValue Dest, LValue Src, QualType EltTy, AggValueSlot::Overlap_t MayOverlap, bool isVolatile=false)
EmitAggregateCopy - Emit an aggregate copy.
LValue EmitLValueForField(LValue Base, const FieldDecl *Field, bool IsInBounds=true)
RawAddress CreateDefaultAlignTempAlloca(llvm::Type *Ty, const Twine &Name="tmp")
CreateDefaultAlignedTempAlloca - This creates an alloca with the default ABI alignment of the given L...
void GenerateOpenMPCapturedVars(const CapturedStmt &S, SmallVectorImpl< llvm::Value * > &CapturedVars)
void EmitIgnoredExpr(const Expr *E)
EmitIgnoredExpr - Emit an expression in a context which ignores the result.
RValue EmitLoadOfLValue(LValue V, SourceLocation Loc)
EmitLoadOfLValue - Given an expression that represents a value lvalue, this method emits the address ...
LValue EmitArraySectionExpr(const ArraySectionExpr *E, bool IsLowerBound=true)
LValue EmitOMPSharedLValue(const Expr *E)
Emits the lvalue for the expression with possibly captured variable.
void StartFunction(GlobalDecl GD, QualType RetTy, llvm::Function *Fn, const CGFunctionInfo &FnInfo, const FunctionArgList &Args, SourceLocation Loc=SourceLocation(), SourceLocation StartLoc=SourceLocation())
Emit code for the start of a function.
void EmitOMPCopy(QualType OriginalType, Address DestAddr, Address SrcAddr, const VarDecl *DestVD, const VarDecl *SrcVD, const Expr *Copy)
Emit proper copying of data from one variable to another.
llvm::Value * EvaluateExprAsBool(const Expr *E)
EvaluateExprAsBool - Perform the usual unary conversions on the specified expression and compare the ...
JumpDest getOMPCancelDestination(OpenMPDirectiveKind Kind)
llvm::Value * emitArrayLength(const ArrayType *arrayType, QualType &baseType, Address &addr)
emitArrayLength - Compute the length of an array, even if it's a VLA, and drill down to the base elem...
void EmitOMPAggregateAssign(Address DestAddr, Address SrcAddr, QualType OriginalType, const llvm::function_ref< void(Address, Address)> CopyGen)
Perform element by element copying of arrays with type OriginalType from SrcAddr to DestAddr using co...
bool HaveInsertPoint() const
HaveInsertPoint - True if an insertion point is defined.
CGDebugInfo * getDebugInfo()
llvm::Value * getTypeSize(QualType Ty)
Returns calculated size of the specified type.
LValue MakeRawAddrLValue(llvm::Value *V, QualType T, CharUnits Alignment, AlignmentSource Source=AlignmentSource::Type)
Same as MakeAddrLValue above except that the pointer is known to be unsigned.
LValue EmitLValueForFieldInitialization(LValue Base, const FieldDecl *Field)
EmitLValueForFieldInitialization - Like EmitLValueForField, except that if the Field is a reference,...
VlaSizePair getVLASize(const VariableArrayType *vla)
Returns an LLVM value that corresponds to the size, in non-variably-sized elements,...
llvm::CallInst * EmitNounwindRuntimeCall(llvm::FunctionCallee callee, const Twine &name="")
ASTContext & getContext() const
llvm::Value * EmitLoadOfScalar(Address Addr, bool Volatile, QualType Ty, SourceLocation Loc, AlignmentSource Source=AlignmentSource::Type, bool isNontemporal=false)
EmitLoadOfScalar - Load a scalar value from an address, taking care to appropriately convert from the...
void EmitStoreOfComplex(ComplexPairTy V, LValue dest, bool isInit)
EmitStoreOfComplex - Store a complex number into the specified l-value.
const Decl * CurFuncDecl
CurFuncDecl - Holds the Decl for the current outermost non-closure context.
void EmitAutoVarCleanups(const AutoVarEmission &emission)
void EmitStoreThroughLValue(RValue Src, LValue Dst, bool isInit=false)
EmitStoreThroughLValue - Store the specified rvalue into the specified lvalue, where both are guarant...
LValue EmitLoadOfPointerLValue(Address Ptr, const PointerType *PtrTy)
void EmitAnyExprToMem(const Expr *E, Address Location, Qualifiers Quals, bool IsInitializer)
EmitAnyExprToMem - Emits the code necessary to evaluate an arbitrary expression into the given memory...
bool needsEHCleanup(QualType::DestructionKind kind)
Determines whether an EH cleanup is required to destroy a type with the given destruction kind.
llvm::DenseMap< const ValueDecl *, FieldDecl * > LambdaCaptureFields
llvm::CallInst * EmitRuntimeCall(llvm::FunctionCallee callee, const Twine &name="")
llvm::Type * ConvertTypeForMem(QualType T)
static void EmitOMPTargetTeamsDistributeParallelForDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsDistributeParallelForDirective &S)
static void EmitOMPTargetParallelForSimdDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetParallelForSimdDirective &S)
Emit device code for the target parallel for simd directive.
CodeGenTypes & getTypes() const
static TypeEvaluationKind getEvaluationKind(QualType T)
getEvaluationKind - Return the TypeEvaluationKind of QualType T.
void EmitOMPTargetTaskBasedDirective(const OMPExecutableDirective &S, const RegionCodeGenTy &BodyGen, OMPTargetDataInfo &InputInfo)
Address EmitPointerWithAlignment(const Expr *Addr, LValueBaseInfo *BaseInfo=nullptr, TBAAAccessInfo *TBAAInfo=nullptr, KnownNonNull_t IsKnownNonNull=NotKnownNonNull)
EmitPointerWithAlignment - Given an expression with a pointer type, emit the value and compute our be...
static void EmitOMPTargetTeamsDistributeParallelForSimdDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsDistributeParallelForSimdDirective &S)
Emit device code for the target teams distribute parallel for simd directive.
void EmitBranch(llvm::BasicBlock *Block)
EmitBranch - Emit a branch to the specified basic block from the current insert block,...
llvm::Function * GenerateOpenMPCapturedStmtFunction(const CapturedStmt &S, const OMPExecutableDirective &D)
RawAddress CreateMemTemp(QualType T, const Twine &Name="tmp", RawAddress *Alloca=nullptr)
CreateMemTemp - Create a temporary memory object of the given type, with appropriate alignmen and cas...
void EmitVarDecl(const VarDecl &D)
EmitVarDecl - Emit a local variable declaration.
llvm::Value * EmitCheckedInBoundsGEP(llvm::Type *ElemTy, llvm::Value *Ptr, ArrayRef< llvm::Value * > IdxList, bool SignedIndices, bool IsSubtraction, SourceLocation Loc, const Twine &Name="")
Same as IRBuilder::CreateInBoundsGEP, but additionally emits a check to detect undefined behavior whe...
static void EmitOMPTargetParallelGenericLoopDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetParallelGenericLoopDirective &S)
Emit device code for the target parallel loop directive.
llvm::Value * EmitScalarExpr(const Expr *E, bool IgnoreResultAssign=false)
EmitScalarExpr - Emit the computation of the specified expression of LLVM scalar type,...
static bool IsWrappedCXXThis(const Expr *E)
Check if E is a C++ "this" pointer wrapped in value-preserving casts.
LValue MakeAddrLValue(Address Addr, QualType T, AlignmentSource Source=AlignmentSource::Type)
void FinishFunction(SourceLocation EndLoc=SourceLocation())
FinishFunction - Complete IR generation of the current function.
void EmitAtomicStore(RValue rvalue, LValue lvalue, bool isInit)
static void EmitOMPTargetSimdDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetSimdDirective &S)
Emit device code for the target simd directive.
static void EmitOMPTargetParallelForDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetParallelForDirective &S)
Emit device code for the target parallel for directive.
Address GetAddrOfLocalVar(const VarDecl *VD)
GetAddrOfLocalVar - Return the address of a local variable.
bool ConstantFoldsToSimpleInteger(const Expr *Cond, bool &Result, bool AllowLabels=false)
ConstantFoldsToSimpleInteger - If the specified expression does not fold to a constant,...
static void EmitOMPTargetTeamsGenericLoopDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsGenericLoopDirective &S)
Emit device code for the target teams loop directive.
LValue EmitMemberExpr(const MemberExpr *E)
std::pair< llvm::Value *, llvm::Value * > ComplexPairTy
Address ReturnValue
ReturnValue - The temporary alloca to hold the return value.
LValue EmitLValue(const Expr *E, KnownNonNull_t IsKnownNonNull=NotKnownNonNull)
EmitLValue - Emit code to compute a designator that specifies the location of the expression.
void incrementProfileCounter(const Stmt *S, llvm::Value *StepV=nullptr)
Increment the profiler's counter for the given statement by StepV.
static void EmitOMPTargetTeamsDistributeSimdDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsDistributeSimdDirective &S)
Emit device code for the target teams distribute simd directive.
llvm::Value * EmitScalarConversion(llvm::Value *Src, QualType SrcTy, QualType DstTy, SourceLocation Loc)
Emit a conversion from the specified type to the specified destination type, both of which are LLVM s...
void EmitVariablyModifiedType(QualType Ty)
EmitVLASize - Capture all the sizes for the VLA expressions in the given variably-modified type and s...
bool isTrivialInitializer(const Expr *Init)
Determine whether the given initializer is trivial in the sense that it requires no code to be genera...
void EmitStoreOfScalar(llvm::Value *Value, Address Addr, bool Volatile, QualType Ty, AlignmentSource Source=AlignmentSource::Type, bool isInit=false, bool isNontemporal=false)
EmitStoreOfScalar - Store a scalar value to an address, taking care to appropriately convert from the...
void EmitBlock(llvm::BasicBlock *BB, bool IsFinished=false)
EmitBlock - Emit the given block.
void EmitExprAsInit(const Expr *init, const ValueDecl *D, LValue lvalue, bool capturedByInit)
EmitExprAsInit - Emits the code necessary to initialize a location in memory with the given initializ...
LValue MakeNaturalAlignRawAddrLValue(llvm::Value *V, QualType T)
This class organizes the cross-function state that is used while generating LLVM code.
void SetInternalFunctionAttributes(GlobalDecl GD, llvm::Function *F, const CGFunctionInfo &FI)
Set the attributes on the LLVM function for the given decl and function info.
llvm::Module & getModule() const
const IntrusiveRefCntPtr< llvm::vfs::FileSystem > & getFileSystem() const
DiagnosticsEngine & getDiags() const
const LangOptions & getLangOpts() const
CharUnits getNaturalTypeAlignment(QualType T, LValueBaseInfo *BaseInfo=nullptr, TBAAAccessInfo *TBAAInfo=nullptr, bool forPointeeType=false)
CodeGenTypes & getTypes()
CGOpenMPRuntime & getOpenMPRuntime()
Return a reference to the configured OpenMP runtime.
TBAAAccessInfo getTBAAInfoForSubobject(LValue Base, QualType AccessType)
getTBAAInfoForSubobject - Get TBAA information for an access with a given base lvalue.
ASTContext & getContext() const
const CodeGenOptions & getCodeGenOpts() const
StringRef getMangledName(GlobalDecl GD)
std::optional< CharUnits > getOMPAllocateAlignment(const VarDecl *VD)
Return the alignment specified in an allocate directive, if present.
llvm::Constant * EmitNullConstant(QualType T)
Return the result of value-initializing the given type, i.e.
llvm::Type * ConvertType(QualType T)
ConvertType - Convert type T into a llvm::Type.
llvm::FunctionType * GetFunctionType(const CGFunctionInfo &Info)
GetFunctionType - Get the LLVM function type for.
const CGFunctionInfo & arrangeBuiltinFunctionDeclaration(QualType resultType, const FunctionArgList &args)
A builtin function is a freestanding function using the default C conventions.
const CGRecordLayout & getCGRecordLayout(const RecordDecl *)
getCGRecordLayout - Return record layout info for the given record decl.
llvm::GlobalVariable * GetAddrOfVTable(const CXXRecordDecl *RD)
GetAddrOfVTable - Get the address of the VTable for the given record decl.
A specialization of Address that requires the address to be an LLVM Constant.
static ConstantAddress invalid()
bool requiresLandingPad() const
void pushTerminate()
Push a terminate handler on the stack.
void popTerminate()
Pops a terminate handler off the stack.
FunctionArgList - Type for representing both the decl and type of parameters to a function.
LValue - This represents an lvalue references.
CharUnits getAlignment() const
llvm::Value * getPointer(CodeGenFunction &CGF) const
const Qualifiers & getQuals() const
Address getAddress() const
LValueBaseInfo getBaseInfo() const
TBAAAccessInfo getTBAAInfo() const
A basic class for pre|post-action for advanced codegen sequence for OpenMP region.
virtual void Enter(CodeGenFunction &CGF)
RValue - This trivial value class is used to represent the result of an expression that is evaluated.
static RValue get(llvm::Value *V)
static RValue getComplex(llvm::Value *V1, llvm::Value *V2)
llvm::Value * getScalarVal() const
getScalarVal() - Return the Value* of this scalar value.
An abstract representation of an aligned address.
llvm::Type * getElementType() const
Return the type of the values stored in this address.
llvm::Value * getPointer() const
static RawAddress invalid()
Class intended to support codegen of all kind of the reduction clauses.
LValue getSharedLValue(unsigned N) const
Returns LValue for the reduction item.
const Expr * getRefExpr(unsigned N) const
Returns the base declaration of the reduction item.
LValue getOrigLValue(unsigned N) const
Returns LValue for the original reduction item.
bool needCleanups(unsigned N)
Returns true if the private copy requires cleanups.
void emitAggregateType(CodeGenFunction &CGF, unsigned N)
Emits the code for the variable-modified type, if required.
const VarDecl * getBaseDecl(unsigned N) const
Returns the base declaration of the reduction item.
QualType getPrivateType(unsigned N) const
Return the type of the private item.
bool usesReductionInitializer(unsigned N) const
Returns true if the initialization of the reduction item uses initializer from declare reduction cons...
void emitSharedOrigLValue(CodeGenFunction &CGF, unsigned N)
Emits lvalue for the shared and original reduction item.
void emitInitialization(CodeGenFunction &CGF, unsigned N, Address PrivateAddr, Address SharedAddr, llvm::function_ref< bool(CodeGenFunction &)> DefaultInit)
Performs initialization of the private copy for the reduction item.
std::pair< llvm::Value *, llvm::Value * > getSizes(unsigned N) const
Returns the size of the reduction item (in chars and total number of elements in the item),...
ReductionCodeGen(ArrayRef< const Expr * > Shareds, ArrayRef< const Expr * > Origs, ArrayRef< const Expr * > Privates, ArrayRef< const Expr * > ReductionOps)
void emitCleanups(CodeGenFunction &CGF, unsigned N, Address PrivateAddr)
Emits cleanup code for the reduction item.
Address adjustPrivateAddress(CodeGenFunction &CGF, unsigned N, Address PrivateAddr)
Adjusts PrivatedAddr for using instead of the original variable address in normal operations.
Class provides a way to call simple version of codegen for OpenMP region, or an advanced with possibl...
void operator()(CodeGenFunction &CGF) const
void setAction(PrePostActionTy &Action) const
ConstStmtVisitor - This class implements a simple visitor for Stmt subclasses.
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
void addDecl(Decl *D)
Add the declaration D into this context.
A reference to a declared variable, function, enum, etc.
Decl - This represents one declaration (or definition), e.g.
ASTContext & getASTContext() const LLVM_READONLY
virtual Stmt * getBody() const
getBody - If this Decl represents a declaration for a body of code, such as a function or method defi...
llvm::iterator_range< specific_attr_iterator< T > > specific_attrs() const
SourceLocation getLocation() const
DeclContext * getDeclContext()
virtual Decl * getCanonicalDecl()
Retrieves the "canonical" declaration of the given declaration.
SourceLocation getBeginLoc() const LLVM_READONLY
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
This represents one expression.
bool isIntegerConstantExpr(const ASTContext &Ctx) const
Expr * IgnoreParenNoopCasts(const ASTContext &Ctx) LLVM_READONLY
Skip past any parentheses and casts which do not change the value (including ptr->int casts of the sa...
@ SE_AllowSideEffects
Allow any unmodeled side effect.
@ SE_AllowUndefinedBehavior
Allow UB that we can give a value, but not arbitrary unmodeled side effects.
Expr * IgnoreParenCasts() LLVM_READONLY
Skip past any parentheses and casts which might surround this expression until reaching a fixed point...
llvm::APSInt EvaluateKnownConstInt(const ASTContext &Ctx) const
EvaluateKnownConstInt - Call EvaluateAsRValue and return the folded integer.
Expr * IgnoreParenImpCasts() LLVM_READONLY
Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...
bool isEvaluatable(const ASTContext &Ctx, SideEffectsKind AllowSideEffects=SE_NoSideEffects) const
isEvaluatable - Call EvaluateAsRValue to see if this expression can be constant folded without side-e...
std::optional< llvm::APSInt > getIntegerConstantExpr(const ASTContext &Ctx) const
isIntegerConstantExpr - Return the value if this expression is a valid integer constant expression.
bool HasSideEffects(const ASTContext &Ctx, bool IncludePossibleEffects=true) const
HasSideEffects - This routine returns true for all those expressions which have any effect other than...
bool EvaluateAsBooleanCondition(bool &Result, const ASTContext &Ctx, bool InConstantContext=false) const
EvaluateAsBooleanCondition - Return true if this is a constant which we can fold and convert to a boo...
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
static bool isSameComparisonOperand(const Expr *E1, const Expr *E2)
Checks that the two Expr's will refer to the same value as a comparison operand.
bool hasNonTrivialCall(const ASTContext &Ctx) const
Determine whether this expression involves a call to any function that is not trivial.
Represents a member of a struct/union/class.
unsigned getFieldIndex() const
Returns the index of this field within its record, as appropriate for passing to ASTRecordLayout::get...
const RecordDecl * getParent() const
Returns the parent of this field declaration, which is the struct in which this field is defined.
static FieldDecl * Create(const ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, const IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, Expr *BW, bool Mutable, InClassInitStyle InitStyle)
Represents a function declaration or definition.
const ParmVarDecl * getParamDecl(unsigned i) const
QualType getReturnType() const
ArrayRef< ParmVarDecl * > parameters() const
FunctionDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
FunctionDecl * getMostRecentDecl()
Returns the most recent (re)declaration of this declaration.
unsigned getNumParams() const
Return the number of parameters this function must have based on its FunctionType.
FunctionDecl * getPreviousDecl()
Return the previous declaration of this declaration or NULL if this is the first declaration.
GlobalDecl - represents a global declaration.
const Decl * getDecl() const
static ImplicitParamDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation IdLoc, IdentifierInfo *Id, QualType T, ImplicitParamKind ParamKind)
Create implicit parameter.
static IntegerLiteral * Create(const ASTContext &C, const llvm::APInt &V, QualType type, SourceLocation l)
Returns a new integer literal with value 'V' and type 'type'.
An lvalue reference type, per C++11 [dcl.ref].
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
ValueDecl * getMemberDecl() const
Retrieve the member declaration to which this expression refers.
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
bool isExternallyVisible() const
const Stmt * getPreInitStmt() const
Get pre-initialization statement for the clause.
This is a basic class for representing single OpenMP clause.
This represents 'pragma omp declare mapper ...' directive.
Expr * getMapperVarRef()
Get the variable declared in the mapper.
This represents 'pragma omp declare reduction ...' directive.
Expr * getInitializer()
Get initializer expression (if specified) of the declare reduction construct.
Expr * getInitPriv()
Get Priv variable of the initializer.
Expr * getCombinerOut()
Get Out variable of the combiner.
Expr * getCombinerIn()
Get In variable of the combiner.
Expr * getCombiner()
Get combiner expression of the declare reduction construct.
Expr * getInitOrig()
Get Orig variable of the initializer.
OMPDeclareReductionInitKind getInitializerKind() const
Get initializer kind.
This represents 'if' clause in the 'pragma omp ...' directive.
Expr * getCondition() const
Returns condition.
OMPIteratorHelperData & getHelper(unsigned I)
Fetches helper data for the specified iteration space.
unsigned numOfIterators() const
Returns number of iterator definitions.
This represents 'num_threads' clause in the 'pragma omp ...' directive.
This represents 'pragma omp requires...' directive.
clauselist_range clauselists()
This represents 'threadset' clause in the 'pragma omp task ...' directive.
OpaqueValueExpr - An expression referring to an opaque object of a fixed type and value class.
Represents a parameter to a function.
PointerType - C99 6.7.5.1 - Pointer Declarators.
Represents an unpacked "presumed" location which can be presented to the user.
unsigned getColumn() const
Return the presumed column number of this location.
const char * getFilename() const
Return the presumed filename of this location.
unsigned getLine() const
Return the presumed line number of this location.
A (possibly-)qualified type.
void addRestrict()
Add the restrict qualifier to this QualType.
QualType withRestrict() const
bool isNull() const
Return true if this QualType doesn't point to a type yet.
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
Qualifiers getQualifiers() const
Retrieve the set of qualifiers applied to this type.
QualType getNonReferenceType() const
If Type is a reference type (e.g., const int&), returns the type that the reference refers to ("const...
QualType getCanonicalType() const
DestructionKind isDestructedType() const
Returns a nonzero value if objects of this type require non-trivial work to clean up after.
Represents a struct/union/class.
field_iterator field_end() const
field_range fields() const
virtual void completeDefinition()
Note that the definition of this type is now complete.
field_iterator field_begin() const
Scope - A scope is a transient data structure that is used while parsing the program.
Encodes a location in the source.
static SourceLocation getFromRawEncoding(UIntTy Encoding)
Turn a raw encoding of a SourceLocation object into a real SourceLocation.
bool isValid() const
Return true if this is a valid SourceLocation object.
UIntTy getRawEncoding() const
When a SourceLocation itself cannot be used, this returns an (opaque) 32-bit integer encoding for it.
This class handles loading and caching of source files into memory.
PresumedLoc getPresumedLoc(SourceLocation Loc, bool UseLineDirectives=true) const
Returns the "presumed" location of a SourceLocation specifies.
Stmt - This represents one statement.
StmtClass getStmtClass() const
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Stmt * IgnoreContainers(bool IgnoreCaptured=false)
Skip no-op (attributed, compound) container stmts and skip captured stmt at the top,...
SourceLocation getBeginLoc() const LLVM_READONLY
void startDefinition()
Starts the definition of this tag declaration.
The base class of the type hierarchy.
const Type * getPointeeOrArrayElementType() const
If this is a pointer type, return the pointee type.
bool isSignedIntegerType() const
Return true if this is an integer type that is signed, according to C99 6.2.5p4 [char,...
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
RecordDecl * getAsRecordDecl() const
Retrieves the RecordDecl this type refers to.
bool isPointerType() const
CanQualType getCanonicalTypeUnqualified() const
bool isIntegerType() const
isIntegerType() does not include complex integers (a GCC extension).
const T * castAs() const
Member-template castAs<specific type>.
bool isReferenceType() const
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
bool isLValueReferenceType() const
bool isAggregateType() const
Determines whether the type is a C++ aggregate type or C aggregate or union type.
RecordDecl * castAsRecordDecl() const
QualType getCanonicalTypeInternal() const
const Type * getBaseElementTypeUnsafe() const
Get the base element type of this type, potentially discarding type qualifiers.
bool isVariablyModifiedType() const
Whether this type is a variably-modified type (C99 6.7.5).
const ArrayType * getAsArrayTypeUnsafe() const
A variant of getAs<> for array types which silently discards qualifiers from the outermost type.
bool isFloatingType() const
bool isUnsignedIntegerType() const
Return true if this is an integer type that is unsigned, according to C99 6.2.5p6 [which returns true...
bool isAnyPointerType() const
const T * getAs() const
Member-template getAs<specific type>'.
bool isRecordType() const
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Represents a variable declaration or definition.
VarDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
VarDecl * getDefinition(ASTContext &)
Get the real (not just tentative) definition for this declaration.
const Expr * getInit() const
bool hasExternalStorage() const
Returns true if a variable has extern or private_extern storage.
@ DeclarationOnly
This declaration is only a declaration.
DefinitionKind hasDefinition(ASTContext &) const
Check whether this variable is defined in this translation unit.
bool isLocalVarDeclOrParm() const
Similar to isLocalVarDecl but also includes parameters.
const Expr * getAnyInitializer() const
Get the initializer for this variable, no matter which declaration it is attached to.
Represents a C array with a specified size that is not an integer-constant-expression.
Expr * getSizeExpr() const
specific_attr_iterator - Iterates over a subrange of an AttrVec, only providing attributes that are o...
bool isEmptyRecordForLayout(const ASTContext &Context, QualType T)
isEmptyRecordForLayout - Return true iff a structure contains only empty base classes (per isEmptyRec...
@ Type
The l-value was considered opaque, so the alignment was determined from a type.
@ Decl
The l-value was an access to a declared entity or something equivalently strong, like the address of ...
bool isEmptyFieldForLayout(const ASTContext &Context, const FieldDecl *FD)
isEmptyFieldForLayout - Return true iff the field is "empty", that is, either a zero-width bit-field ...
ComparisonResult
Indicates the result of a tentative comparison.
The JSON file list parser is used to communicate input to InstallAPI.
bool isOpenMPWorksharingDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a worksharing directive.
CanQual< Type > CanQualType
Represents a canonical, potentially-qualified type.
bool needsTaskBasedThreadLimit(OpenMPDirectiveKind DKind)
Checks if the specified target directive, combined or not, needs task based thread_limit.
@ Match
This is not an overload because the signature exactly matches an existing declaration.
@ Ctor_Complete
Complete object ctor.
Privates[]
This class represents the 'transparent' clause in the 'pragma omp task' directive.
bool isa(CodeGen::Address addr)
if(T->getSizeExpr()) TRY_TO(TraverseStmt(const_cast< Expr * >(T -> getSizeExpr())))
bool isOpenMPTargetDataManagementDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a target data offload directive.
static bool classof(const OMPClause *T)
@ Conditional
A conditional (?:) operator.
@ ICIS_NoInit
No in-class initializer.
bool isOpenMPDistributeDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a distribute directive.
@ LCK_ByRef
Capturing by reference.
LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE()
@ Private
'private' clause, allowed on 'parallel', 'serial', 'loop', 'parallel loop', and 'serial loop' constru...
@ 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.
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.
Data for list of allocators.
Expr * AllocatorTraits
Allocator traits.
Expr * Allocator
Allocator.
Maps the expression for the lastprivate variable to the global copy used to store new value because o...
llvm::SmallVector< bool, 8 > IsPrivateVarReduction
A jump destination is an abstract label, branching to which may require a jump out through normal cle...
llvm::BasicBlock * getBlock() const
unsigned NumberOfTargetItems
Address BasePointersArray
llvm::PointerType * VoidPtrTy
llvm::IntegerType * Int64Ty
llvm::IntegerType * Int8Ty
i8, i16, i32, and i64
llvm::CallingConv::ID getRuntimeCC() const
llvm::IntegerType * SizeTy
llvm::PointerType * VoidPtrPtrTy
llvm::IntegerType * Int32Ty
llvm::IntegerType * IntPtrTy
llvm::IntegerType * IntTy
int
CharUnits getPointerAlign() const
OpenMPDependClauseKind DepKind
const Expr * IteratorExpr
SmallVector< const Expr *, 4 > DepExprs
EvalResult is a struct with detailed info about an evaluated expression.
Extra information about a function prototype.
Expr * CounterUpdate
Updater for the internal counter: ++CounterVD;.
Scheduling data for loop-based OpenMP directives.
OpenMPScheduleClauseModifier M2
OpenMPScheduleClauseModifier M1
OpenMPScheduleClauseKind Schedule
Describes how types, statements, expressions, and declarations should be printed.