31#include "llvm/ADT/ArrayRef.h"
32#include "llvm/ADT/SmallSet.h"
33#include "llvm/ADT/SmallVector.h"
34#include "llvm/ADT/StringExtras.h"
35#include "llvm/Bitcode/BitcodeReader.h"
36#include "llvm/IR/Constants.h"
37#include "llvm/IR/DerivedTypes.h"
38#include "llvm/IR/GlobalValue.h"
39#include "llvm/IR/InstrTypes.h"
40#include "llvm/IR/Value.h"
41#include "llvm/Support/AtomicOrdering.h"
42#include "llvm/Support/raw_ostream.h"
50using namespace llvm::omp;
57 enum CGOpenMPRegionKind {
60 ParallelOutlinedRegion,
70 CGOpenMPRegionInfo(
const CapturedStmt &CS,
71 const CGOpenMPRegionKind RegionKind,
74 : CGCapturedStmtInfo(CS,
CR_OpenMP), RegionKind(RegionKind),
75 CodeGen(CodeGen), Kind(Kind), HasCancel(HasCancel) {}
77 CGOpenMPRegionInfo(
const CGOpenMPRegionKind RegionKind,
80 : CGCapturedStmtInfo(
CR_OpenMP), RegionKind(RegionKind), CodeGen(CodeGen),
81 Kind(Kind), HasCancel(HasCancel) {}
85 virtual const VarDecl *getThreadIDVariable()
const = 0;
88 void EmitBody(CodeGenFunction &CGF,
const Stmt *S)
override;
92 virtual LValue getThreadIDVariableLValue(CodeGenFunction &CGF);
94 virtual void emitUntiedSwitch(CodeGenFunction & ) {}
96 CGOpenMPRegionKind getRegionKind()
const {
return RegionKind; }
100 bool hasCancel()
const {
return HasCancel; }
102 static bool classof(
const CGCapturedStmtInfo *Info) {
106 ~CGOpenMPRegionInfo()
override =
default;
109 CGOpenMPRegionKind RegionKind;
110 RegionCodeGenTy CodeGen;
116class CGOpenMPOutlinedRegionInfo final :
public CGOpenMPRegionInfo {
118 CGOpenMPOutlinedRegionInfo(
const CapturedStmt &CS,
const VarDecl *ThreadIDVar,
119 const RegionCodeGenTy &CodeGen,
121 StringRef HelperName)
122 : CGOpenMPRegionInfo(CS, ParallelOutlinedRegion, CodeGen,
Kind,
124 ThreadIDVar(ThreadIDVar), HelperName(HelperName) {
125 assert(ThreadIDVar !=
nullptr &&
"No ThreadID in OpenMP region.");
130 const VarDecl *getThreadIDVariable()
const override {
return ThreadIDVar; }
133 StringRef getHelperName()
const override {
return HelperName; }
135 static bool classof(
const CGCapturedStmtInfo *Info) {
136 return CGOpenMPRegionInfo::classof(Info) &&
138 ParallelOutlinedRegion;
144 const VarDecl *ThreadIDVar;
145 StringRef HelperName;
149class CGOpenMPTaskOutlinedRegionInfo final :
public CGOpenMPRegionInfo {
151 class UntiedTaskActionTy final :
public PrePostActionTy {
153 const VarDecl *PartIDVar;
154 const RegionCodeGenTy UntiedCodeGen;
155 llvm::SwitchInst *UntiedSwitch =
nullptr;
158 UntiedTaskActionTy(
bool Tied,
const VarDecl *PartIDVar,
159 const RegionCodeGenTy &UntiedCodeGen)
160 : Untied(!Tied), PartIDVar(PartIDVar), UntiedCodeGen(UntiedCodeGen) {}
161 void Enter(CodeGenFunction &CGF)
override {
166 PartIDVar->
getType()->castAs<PointerType>());
170 UntiedSwitch = CGF.
Builder.CreateSwitch(Res, DoneBB);
174 UntiedSwitch->addCase(CGF.
Builder.getInt32(0),
176 emitUntiedSwitch(CGF);
179 void emitUntiedSwitch(CodeGenFunction &CGF)
const {
183 PartIDVar->
getType()->castAs<PointerType>());
187 CodeGenFunction::JumpDest CurPoint =
191 UntiedSwitch->addCase(CGF.
Builder.getInt32(UntiedSwitch->getNumCases()),
197 unsigned getNumberOfParts()
const {
return UntiedSwitch->getNumCases(); }
199 CGOpenMPTaskOutlinedRegionInfo(
const CapturedStmt &CS,
200 const VarDecl *ThreadIDVar,
201 const RegionCodeGenTy &CodeGen,
203 const UntiedTaskActionTy &Action)
204 : CGOpenMPRegionInfo(CS, TaskOutlinedRegion, CodeGen,
Kind, HasCancel),
205 ThreadIDVar(ThreadIDVar), Action(Action) {
206 assert(ThreadIDVar !=
nullptr &&
"No ThreadID in OpenMP region.");
211 const VarDecl *getThreadIDVariable()
const override {
return ThreadIDVar; }
214 LValue getThreadIDVariableLValue(CodeGenFunction &CGF)
override;
217 StringRef getHelperName()
const override {
return ".omp_outlined."; }
219 void emitUntiedSwitch(CodeGenFunction &CGF)
override {
220 Action.emitUntiedSwitch(CGF);
223 static bool classof(
const CGCapturedStmtInfo *Info) {
224 return CGOpenMPRegionInfo::classof(Info) &&
232 const VarDecl *ThreadIDVar;
234 const UntiedTaskActionTy &Action;
239class CGOpenMPInlinedRegionInfo :
public CGOpenMPRegionInfo {
241 CGOpenMPInlinedRegionInfo(CodeGenFunction::CGCapturedStmtInfo *OldCSI,
242 const RegionCodeGenTy &CodeGen,
244 : CGOpenMPRegionInfo(InlinedRegion, CodeGen,
Kind, HasCancel),
246 OuterRegionInfo(dyn_cast_or_null<CGOpenMPRegionInfo>(OldCSI)) {}
249 llvm::Value *getContextValue()
const override {
251 return OuterRegionInfo->getContextValue();
252 llvm_unreachable(
"No context value for inlined OpenMP region");
255 void setContextValue(llvm::Value *
V)
override {
256 if (OuterRegionInfo) {
257 OuterRegionInfo->setContextValue(
V);
260 llvm_unreachable(
"No context value for inlined OpenMP region");
264 const FieldDecl *lookup(
const VarDecl *VD)
const override {
266 return OuterRegionInfo->lookup(VD);
272 FieldDecl *getThisFieldDecl()
const override {
274 return OuterRegionInfo->getThisFieldDecl();
280 const VarDecl *getThreadIDVariable()
const override {
282 return OuterRegionInfo->getThreadIDVariable();
287 LValue getThreadIDVariableLValue(CodeGenFunction &CGF)
override {
289 return OuterRegionInfo->getThreadIDVariableLValue(CGF);
290 llvm_unreachable(
"No LValue for inlined OpenMP construct");
294 StringRef getHelperName()
const override {
295 if (
auto *OuterRegionInfo = getOldCSI())
296 return OuterRegionInfo->getHelperName();
297 llvm_unreachable(
"No helper name for inlined OpenMP construct");
300 void emitUntiedSwitch(CodeGenFunction &CGF)
override {
302 OuterRegionInfo->emitUntiedSwitch(CGF);
305 CodeGenFunction::CGCapturedStmtInfo *getOldCSI()
const {
return OldCSI; }
307 static bool classof(
const CGCapturedStmtInfo *Info) {
308 return CGOpenMPRegionInfo::classof(Info) &&
312 ~CGOpenMPInlinedRegionInfo()
override =
default;
316 CodeGenFunction::CGCapturedStmtInfo *OldCSI;
317 CGOpenMPRegionInfo *OuterRegionInfo;
325class CGOpenMPTargetRegionInfo final :
public CGOpenMPRegionInfo {
327 CGOpenMPTargetRegionInfo(
const CapturedStmt &CS,
328 const RegionCodeGenTy &CodeGen, StringRef HelperName)
329 : CGOpenMPRegionInfo(CS, TargetRegion, CodeGen, OMPD_target,
331 HelperName(HelperName) {}
335 const VarDecl *getThreadIDVariable()
const override {
return nullptr; }
338 StringRef getHelperName()
const override {
return HelperName; }
340 static bool classof(
const CGCapturedStmtInfo *Info) {
341 return CGOpenMPRegionInfo::classof(Info) &&
346 StringRef HelperName;
350 llvm_unreachable(
"No codegen for expressions");
354class CGOpenMPInnerExprInfo final :
public CGOpenMPInlinedRegionInfo {
356 CGOpenMPInnerExprInfo(CodeGenFunction &CGF,
const CapturedStmt &CS)
357 : CGOpenMPInlinedRegionInfo(CGF.CapturedStmtInfo, EmptyCodeGen,
365 if (!C.capturesVariable() && !C.capturesVariableByCopy())
368 const VarDecl *VD = C.getCapturedVar();
369 if (VD->isLocalVarDeclOrParm())
372 DeclRefExpr DRE(CGF.getContext(), const_cast<VarDecl *>(VD),
374 VD->getType().getNonReferenceType(), VK_LValue,
376 PrivScope.addPrivate(VD, CGF.EmitLValue(&DRE).getAddress());
378 (
void)PrivScope.Privatize();
382 const FieldDecl *lookup(
const VarDecl *VD)
const override {
383 if (
const FieldDecl *FD = CGOpenMPInlinedRegionInfo::lookup(VD))
389 void EmitBody(CodeGenFunction &CGF,
const Stmt *S)
override {
390 llvm_unreachable(
"No body for expressions");
395 const VarDecl *getThreadIDVariable()
const override {
396 llvm_unreachable(
"No thread id for expressions");
400 StringRef getHelperName()
const override {
401 llvm_unreachable(
"No helper name for expressions");
404 static bool classof(
const CGCapturedStmtInfo *Info) {
return false; }
408 CodeGenFunction::OMPPrivateScope PrivScope;
412class InlinedOpenMPRegionRAII {
413 CodeGenFunction &CGF;
414 llvm::DenseMap<const ValueDecl *, FieldDecl *> LambdaCaptureFields;
415 FieldDecl *LambdaThisCaptureField =
nullptr;
416 const CodeGen::CGBlockInfo *BlockInfo =
nullptr;
417 bool NoInheritance =
false;
424 InlinedOpenMPRegionRAII(CodeGenFunction &CGF,
const RegionCodeGenTy &CodeGen,
426 bool NoInheritance =
true)
427 : CGF(CGF), NoInheritance(NoInheritance) {
429 CGF.CapturedStmtInfo =
new CGOpenMPInlinedRegionInfo(
430 CGF.CapturedStmtInfo, CodeGen, Kind, HasCancel);
432 std::swap(CGF.LambdaCaptureFields, LambdaCaptureFields);
433 LambdaThisCaptureField = CGF.LambdaThisCaptureField;
434 CGF.LambdaThisCaptureField =
nullptr;
435 BlockInfo = CGF.BlockInfo;
436 CGF.BlockInfo =
nullptr;
440 ~InlinedOpenMPRegionRAII() {
444 delete CGF.CapturedStmtInfo;
445 CGF.CapturedStmtInfo = OldCSI;
447 std::swap(CGF.LambdaCaptureFields, LambdaCaptureFields);
448 CGF.LambdaThisCaptureField = LambdaThisCaptureField;
449 CGF.BlockInfo = BlockInfo;
457enum OpenMPLocationFlags :
unsigned {
459 OMP_IDENT_IMD = 0x01,
461 OMP_IDENT_KMPC = 0x02,
463 OMP_ATOMIC_REDUCE = 0x10,
465 OMP_IDENT_BARRIER_EXPL = 0x20,
467 OMP_IDENT_BARRIER_IMPL = 0x40,
469 OMP_IDENT_BARRIER_IMPL_FOR = 0x40,
471 OMP_IDENT_BARRIER_IMPL_SECTIONS = 0xC0,
473 OMP_IDENT_BARRIER_IMPL_SINGLE = 0x140,
475 OMP_IDENT_WORK_LOOP = 0x200,
477 OMP_IDENT_WORK_SECTIONS = 0x400,
479 OMP_IDENT_WORK_DISTRIBUTE = 0x800,
509enum IdentFieldIndex {
511 IdentField_Reserved_1,
515 IdentField_Reserved_2,
517 IdentField_Reserved_3,
526enum OpenMPSchedType {
529 OMP_sch_static_chunked = 33,
531 OMP_sch_dynamic_chunked = 35,
532 OMP_sch_guided_chunked = 36,
533 OMP_sch_runtime = 37,
536 OMP_sch_static_balanced_chunked = 45,
539 OMP_ord_static_chunked = 65,
541 OMP_ord_dynamic_chunked = 67,
542 OMP_ord_guided_chunked = 68,
543 OMP_ord_runtime = 69,
545 OMP_sch_default = OMP_sch_static,
547 OMP_dist_sch_static_chunked = 91,
548 OMP_dist_sch_static = 92,
551 OMP_sch_modifier_monotonic = (1 << 29),
553 OMP_sch_modifier_nonmonotonic = (1 << 30),
558class CleanupTy final :
public EHScopeStack::Cleanup {
559 PrePostActionTy *Action;
562 explicit CleanupTy(PrePostActionTy *Action) : Action(Action) {}
563 void Emit(CodeGenFunction &CGF, Flags )
override {
576 Callback(CodeGen, CGF, *PrePostAction);
579 Callback(CodeGen, CGF, Action);
587 if (
const auto *CE = dyn_cast<CallExpr>(ReductionOp))
588 if (
const auto *OVE = dyn_cast<OpaqueValueExpr>(CE->getCallee()))
589 if (
const auto *DRE =
590 dyn_cast<DeclRefExpr>(OVE->getSourceExpr()->IgnoreImpCasts()))
591 if (
const auto *DRD = dyn_cast<OMPDeclareReductionDecl>(DRE->getDecl()))
602 std::pair<llvm::Function *, llvm::Function *>
Reduction =
622 auto *GV =
new llvm::GlobalVariable(
624 llvm::GlobalValue::PrivateLinkage,
Init, Name);
665 llvm::Value *NumElements = CGF.
emitArrayLength(ArrayTy, ElementTy, DestAddr);
669 llvm::Value *SrcBegin =
nullptr;
671 SrcBegin = SrcAddr.emitRawPointer(CGF);
674 llvm::Value *DestEnd =
679 llvm::Value *IsEmpty =
680 CGF.
Builder.CreateICmpEQ(DestBegin, DestEnd,
"omp.arrayinit.isempty");
681 CGF.
Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
684 llvm::BasicBlock *EntryBB = CGF.
Builder.GetInsertBlock();
689 llvm::PHINode *SrcElementPHI =
nullptr;
692 SrcElementPHI = CGF.
Builder.CreatePHI(SrcBegin->getType(), 2,
693 "omp.arraycpy.srcElementPast");
694 SrcElementPHI->addIncoming(SrcBegin, EntryBB);
696 Address(SrcElementPHI, SrcAddr.getElementType(),
697 SrcAddr.getAlignment().alignmentOfArrayElement(ElementSize));
699 llvm::PHINode *DestElementPHI = CGF.
Builder.CreatePHI(
700 DestBegin->getType(), 2,
"omp.arraycpy.destElementPast");
701 DestElementPHI->addIncoming(DestBegin, EntryBB);
709 if (EmitDeclareReductionInit) {
711 SrcElementCurrent, ElementTy);
719 llvm::Value *SrcElementNext = CGF.
Builder.CreateConstGEP1_32(
720 SrcAddr.getElementType(), SrcElementPHI, 1,
721 "omp.arraycpy.dest.element");
722 SrcElementPHI->addIncoming(SrcElementNext, CGF.
Builder.GetInsertBlock());
726 llvm::Value *DestElementNext = CGF.
Builder.CreateConstGEP1_32(
728 "omp.arraycpy.dest.element");
731 CGF.
Builder.CreateICmpEQ(DestElementNext, DestEnd,
"omp.arraycpy.done");
732 CGF.
Builder.CreateCondBr(Done, DoneBB, BodyBB);
733 DestElementPHI->addIncoming(DestElementNext, CGF.
Builder.GetInsertBlock());
745 if (
const auto *OASE = dyn_cast<ArraySectionExpr>(E))
750void ReductionCodeGen::emitAggregateInitialization(
752 const OMPDeclareReductionDecl *DRD) {
756 const auto *PrivateVD =
758 bool EmitDeclareReductionInit =
761 EmitDeclareReductionInit,
762 EmitDeclareReductionInit ? ClausesData[N].ReductionOp
763 : PrivateVD->getInit(),
771 ClausesData.reserve(Shareds.size());
772 SharedAddresses.reserve(Shareds.size());
773 Sizes.reserve(Shareds.size());
774 BaseDecls.reserve(Shareds.size());
775 const auto *IOrig = Origs.begin();
776 const auto *IPriv =
Privates.begin();
777 const auto *IRed = ReductionOps.begin();
778 for (
const Expr *Ref : Shareds) {
779 ClausesData.emplace_back(Ref, *IOrig, *IPriv, *IRed);
780 std::advance(IOrig, 1);
781 std::advance(IPriv, 1);
782 std::advance(IRed, 1);
787 assert(SharedAddresses.size() == N && OrigAddresses.size() == N &&
788 "Number of generated lvalues must be exactly N.");
789 LValue First = emitSharedLValue(CGF, ClausesData[N].Shared);
790 LValue Second = emitSharedLValueUB(CGF, ClausesData[N].Shared);
791 SharedAddresses.emplace_back(
First, Second);
792 if (ClausesData[N].Shared == ClausesData[N].Ref) {
793 OrigAddresses.emplace_back(
First, Second);
795 LValue First = emitSharedLValue(CGF, ClausesData[N].Ref);
796 LValue Second = emitSharedLValueUB(CGF, ClausesData[N].Ref);
797 OrigAddresses.emplace_back(
First, Second);
806 CGF.
getTypeSize(OrigAddresses[N].first.getType().getNonReferenceType()),
811 llvm::Value *SizeInChars;
812 auto *ElemType = OrigAddresses[N].first.getAddress().getElementType();
813 auto *ElemSizeOf = llvm::ConstantExpr::getSizeOf(ElemType);
814 if (AsArraySection) {
815 Size = CGF.
Builder.CreatePtrDiff(ElemType,
816 OrigAddresses[N].second.getPointer(CGF),
817 OrigAddresses[N].first.getPointer(CGF));
818 Size = CGF.
Builder.CreateZExtOrTrunc(Size, ElemSizeOf->getType());
819 Size = CGF.
Builder.CreateNUWAdd(
820 Size, llvm::ConstantInt::get(Size->getType(), 1));
821 SizeInChars = CGF.
Builder.CreateNUWMul(Size, ElemSizeOf);
824 CGF.
getTypeSize(OrigAddresses[N].first.getType().getNonReferenceType());
825 Size = CGF.
Builder.CreateExactUDiv(SizeInChars, ElemSizeOf);
827 Sizes.emplace_back(SizeInChars, Size);
840 assert(!Size && !Sizes[N].second &&
841 "Size should be nullptr for non-variably modified reduction "
856 assert(SharedAddresses.size() > N &&
"No variable was generated");
857 const auto *PrivateVD =
863 (void)DefaultInit(CGF);
864 emitAggregateInitialization(CGF, N, PrivateAddr, SharedAddr, DRD);
865 }
else if (DRD && (DRD->
getInitializer() || !PrivateVD->hasInit())) {
866 (void)DefaultInit(CGF);
867 QualType SharedType = SharedAddresses[N].first.getType();
869 PrivateAddr, SharedAddr, SharedType);
870 }
else if (!DefaultInit(CGF) && PrivateVD->hasInit() &&
873 PrivateVD->
getType().getQualifiers(),
891 CGF.
pushDestroy(DTorKind, PrivateAddr, PrivateType);
910 BaseLV.getType(), BaseLV.getBaseInfo(),
944 const VarDecl *OrigVD =
nullptr;
945 if (
const auto *OASE = dyn_cast<ArraySectionExpr>(Ref)) {
946 const Expr *
Base = OASE->getBase()->IgnoreParenImpCasts();
947 while (
const auto *TempOASE = dyn_cast<ArraySectionExpr>(
Base))
948 Base = TempOASE->getBase()->IgnoreParenImpCasts();
949 while (
const auto *TempASE = dyn_cast<ArraySubscriptExpr>(
Base))
950 Base = TempASE->getBase()->IgnoreParenImpCasts();
953 }
else if (
const auto *ASE = dyn_cast<ArraySubscriptExpr>(Ref)) {
954 const Expr *
Base = ASE->getBase()->IgnoreParenImpCasts();
955 while (
const auto *TempASE = dyn_cast<ArraySubscriptExpr>(
Base))
956 Base = TempASE->getBase()->IgnoreParenImpCasts();
967 BaseDecls.emplace_back(OrigVD);
970 loadToBegin(CGF, OrigVD->getType(), SharedAddresses[N].first.getType(),
972 Address SharedAddr = SharedAddresses[N].first.getAddress();
973 llvm::Value *Adjustment = CGF.
Builder.CreatePtrDiff(
976 llvm::Value *PrivatePointer =
982 SharedAddresses[N].first.getType(),
985 BaseDecls.emplace_back(
999 getThreadIDVariable()->
getType()->castAs<PointerType>());
1017LValue CGOpenMPTaskOutlinedRegionInfo::getThreadIDVariableLValue(
1020 getThreadIDVariable()->
getType(),
1038 llvm::OpenMPIRBuilderConfig Config(
1039 CGM.getLangOpts().OpenMPIsTargetDevice,
isGPU(),
1040 CGM.getLangOpts().OpenMPOffloadMandatory,
1043 Config.setDefaultTargetAS(
1045 Config.setRuntimeCC(
CGM.getRuntimeCC());
1050 CGM.getLangOpts().OpenMPIsTargetDevice
1051 ?
CGM.getLangOpts().OMPHostIRFile
1056 if (
CGM.getLangOpts().OpenMPForceUSM) {
1058 OMPBuilder.Config.setHasRequiresUnifiedSharedMemory(
true);
1066 if (!
Data.getValue().pointsToAliveValue())
1068 auto *GV = dyn_cast<llvm::GlobalVariable>(
Data.getValue());
1071 if (!GV->isDeclaration() || GV->getNumUses() > 0)
1073 GV->eraseFromParent();
1078 return OMPBuilder.createPlatformSpecificName(Parts);
1081static llvm::Function *
1083 const Expr *CombinerInitializer,
const VarDecl *In,
1084 const VarDecl *Out,
bool IsCombiner) {
1087 QualType PtrTy =
C.getPointerType(Ty).withRestrict();
1093 Args.push_back(&OmpOutParm);
1094 Args.push_back(&OmpInParm);
1099 {IsCombiner ?
"omp_combiner" :
"omp_initializer",
""});
1100 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
1104 Fn->addFnAttr(
"sample-profile-suffix-elision-policy",
"selected");
1106 Fn->removeFnAttr(llvm::Attribute::NoInline);
1107 Fn->removeFnAttr(llvm::Attribute::OptimizeNone);
1108 Fn->addFnAttr(llvm::Attribute::AlwaysInline);
1114 Out->getLocation());
1124 (void)
Scope.Privatize();
1125 if (!IsCombiner && Out->hasInit() &&
1128 Out->getType().getQualifiers(),
1131 if (CombinerInitializer)
1133 Scope.ForceCleanup();
1162std::pair<llvm::Function *, llvm::Function *>
1174struct PushAndPopStackRAII {
1175 PushAndPopStackRAII(llvm::OpenMPIRBuilder *OMPBuilder,
CodeGenFunction &CGF,
1176 bool HasCancel, llvm::omp::Directive Kind)
1177 : OMPBuilder(OMPBuilder) {
1193 auto FiniCB = [&CGF](llvm::OpenMPIRBuilder::InsertPointTy IP) {
1194 assert(IP.getBlock()->end() == IP.getPoint() &&
1195 "Clang CG should cause non-terminated block!");
1196 CGBuilderTy::InsertPointGuard IPG(CGF.
Builder);
1201 return llvm::Error::success();
1206 llvm::OpenMPIRBuilder::FinalizationInfo FI({FiniCB, Kind, HasCancel});
1207 OMPBuilder->pushFinalizationCB(std::move(FI));
1209 ~PushAndPopStackRAII() {
1211 OMPBuilder->popFinalizationCB();
1213 llvm::OpenMPIRBuilder *OMPBuilder;
1222 "thread id variable must be of type kmp_int32 *");
1224 bool HasCancel =
false;
1225 if (
const auto *OPD = dyn_cast<OMPParallelDirective>(&D))
1226 HasCancel = OPD->hasCancel();
1227 else if (
const auto *OPD = dyn_cast<OMPTargetParallelDirective>(&D))
1228 HasCancel = OPD->hasCancel();
1229 else if (
const auto *OPSD = dyn_cast<OMPParallelSectionsDirective>(&D))
1230 HasCancel = OPSD->hasCancel();
1231 else if (
const auto *OPFD = dyn_cast<OMPParallelForDirective>(&D))
1232 HasCancel = OPFD->hasCancel();
1233 else if (
const auto *OPFD = dyn_cast<OMPTargetParallelForDirective>(&D))
1234 HasCancel = OPFD->hasCancel();
1235 else if (
const auto *OPFD = dyn_cast<OMPDistributeParallelForDirective>(&D))
1236 HasCancel = OPFD->hasCancel();
1237 else if (
const auto *OPFD =
1238 dyn_cast<OMPTeamsDistributeParallelForDirective>(&D))
1239 HasCancel = OPFD->hasCancel();
1240 else if (
const auto *OPFD =
1241 dyn_cast<OMPTargetTeamsDistributeParallelForDirective>(&D))
1242 HasCancel = OPFD->hasCancel();
1247 PushAndPopStackRAII PSR(&OMPBuilder, CGF, HasCancel, InnermostKind);
1248 CGOpenMPOutlinedRegionInfo CGInfo(*CS, ThreadIDVar,
CodeGen, InnermostKind,
1249 HasCancel, OutlinedHelperName);
1255 std::string Suffix =
getName({
"omp_outlined"});
1256 return (Name + Suffix).str();
1264 std::string Suffix =
getName({
"omp",
"reduction",
"reduction_func"});
1265 return (Name + Suffix).str();
1272 const CapturedStmt *CS = D.getCapturedStmt(OMPD_parallel);
1282 const CapturedStmt *CS = D.getCapturedStmt(OMPD_teams);
1292 bool Tied,
unsigned &NumberOfParts) {
1295 llvm::Value *ThreadID =
getThreadID(CGF, D.getBeginLoc());
1297 llvm::Value *TaskArgs[] = {
1299 CGF.EmitLoadOfPointerLValue(CGF.GetAddrOfLocalVar(TaskTVar),
1302 CGF.EmitRuntimeCall(
OMPBuilder.getOrCreateRuntimeFunction(
1303 CGM.getModule(), OMPRTL___kmpc_omp_task),
1306 CGOpenMPTaskOutlinedRegionInfo::UntiedTaskActionTy Action(Tied, PartIDVar,
1310 "thread id variable must be of type kmp_int32 for tasks");
1315 bool HasCancel =
false;
1316 if (
const auto *TD = dyn_cast<OMPTaskDirective>(&D))
1317 HasCancel = TD->hasCancel();
1318 else if (
const auto *TD = dyn_cast<OMPTaskLoopDirective>(&D))
1319 HasCancel = TD->hasCancel();
1320 else if (
const auto *TD = dyn_cast<OMPMasterTaskLoopDirective>(&D))
1321 HasCancel = TD->hasCancel();
1322 else if (
const auto *TD = dyn_cast<OMPParallelMasterTaskLoopDirective>(&D))
1323 HasCancel = TD->hasCancel();
1326 CGOpenMPTaskOutlinedRegionInfo CGInfo(*CS, ThreadIDVar,
CodeGen,
1327 InnermostKind, HasCancel, Action);
1329 llvm::Function *Res = CGF.GenerateCapturedStmtFunction(*CS);
1331 NumberOfParts = Action.getNumberOfParts();
1336 bool AtCurrentPoint) {
1338 assert(!Elem.ServiceInsertPt &&
"Insert point is set already.");
1340 llvm::Value *Undef = llvm::UndefValue::get(CGF.
Int32Ty);
1341 if (AtCurrentPoint) {
1342 Elem.ServiceInsertPt =
new llvm::BitCastInst(Undef, CGF.
Int32Ty,
"svcpt",
1343 CGF.
Builder.GetInsertBlock());
1345 Elem.ServiceInsertPt =
new llvm::BitCastInst(Undef, CGF.
Int32Ty,
"svcpt");
1346 Elem.ServiceInsertPt->insertAfter(CGF.
AllocaInsertPt->getIterator());
1352 if (Elem.ServiceInsertPt) {
1353 llvm::Instruction *Ptr = Elem.ServiceInsertPt;
1354 Elem.ServiceInsertPt =
nullptr;
1355 Ptr->eraseFromParent();
1362 llvm::raw_svector_ostream OS(Buffer);
1371 if (
const auto *FD = dyn_cast_or_null<FunctionDecl>(CGF.
CurFuncDecl))
1372 OS << FD->getQualifiedNameAsString();
1379 unsigned Flags,
bool EmitLoc) {
1380 uint32_t SrcLocStrSize;
1381 llvm::Constant *SrcLocStr;
1382 if ((!EmitLoc &&
CGM.getCodeGenOpts().getDebugInfo() ==
1383 llvm::codegenoptions::NoDebugInfo) ||
1385 SrcLocStr =
OMPBuilder.getOrCreateDefaultSrcLocStr(SrcLocStrSize);
1387 std::string FunctionName;
1389 if (
const auto *FD = dyn_cast_or_null<FunctionDecl>(CGF.
CurFuncDecl))
1390 FunctionName = FD->getQualifiedNameAsString();
1403 SrcLocStr, SrcLocStrSize, llvm::omp::IdentFlag(Flags), Reserved2Flags);
1408 assert(CGF.
CurFn &&
"No function in current CodeGenFunction.");
1411 if (
CGM.getLangOpts().OpenMPIRBuilder) {
1414 uint32_t SrcLocStrSize;
1415 auto *SrcLocStr =
OMPBuilder.getOrCreateSrcLocStr(
1418 OMPBuilder.getOrCreateIdent(SrcLocStr, SrcLocStrSize));
1421 llvm::Value *ThreadID =
nullptr;
1426 ThreadID = I->second.ThreadID;
1427 if (ThreadID !=
nullptr)
1431 if (
auto *OMPRegionInfo =
1433 if (OMPRegionInfo->getThreadIDVariable()) {
1435 LValue LVal = OMPRegionInfo->getThreadIDVariableLValue(CGF);
1439 CGF.
Builder.GetInsertBlock() == TopBlock ||
1444 CGF.
Builder.GetInsertBlock()) {
1448 if (CGF.
Builder.GetInsertBlock() == TopBlock)
1460 if (!Elem.ServiceInsertPt)
1462 CGBuilderTy::InsertPointGuard IPG(CGF.
Builder);
1463 CGF.
Builder.SetInsertPoint(Elem.ServiceInsertPt);
1467 OMPRTL___kmpc_global_thread_num),
1470 Elem.ThreadID =
Call;
1475 assert(CGF.
CurFn &&
"No function in current CodeGenFunction.");
1481 for (
const auto *D : I->second)
1486 for (
const auto *D : I->second)
1498static llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseKind
1500 std::optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
1501 OMPDeclareTargetDeclAttr::getDeviceType(VD);
1503 return llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseNone;
1505 switch ((
int)*DevTy) {
1506 case OMPDeclareTargetDeclAttr::DT_Host:
1507 return llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseHost;
1509 case OMPDeclareTargetDeclAttr::DT_NoHost:
1510 return llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseNoHost;
1512 case OMPDeclareTargetDeclAttr::DT_Any:
1513 return llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseAny;
1516 return llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseNone;
1521static llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryKind
1523 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> MapType =
1524 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
1526 return llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryNone;
1527 switch ((
int)*MapType) {
1528 case OMPDeclareTargetDeclAttr::MapTypeTy::MT_To:
1529 return llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryTo;
1531 case OMPDeclareTargetDeclAttr::MapTypeTy::MT_Enter:
1532 return llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryEnter;
1534 case OMPDeclareTargetDeclAttr::MapTypeTy::MT_Link:
1535 return llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryLink;
1538 return llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryNone;
1547 auto FileInfoCallBack = [&]() {
1552 PLoc =
SM.getPresumedLoc(BeginLoc,
false);
1557 return OMPBuilder.getTargetEntryUniqueInfo(FileInfoCallBack,
1562 auto AddrOfGlobal = [&VD,
this]() {
return CGM.GetAddrOfGlobal(VD); };
1564 auto LinkageForVariable = [&VD,
this]() {
1565 return CGM.getLLVMLinkageVarDefinition(VD);
1568 std::vector<llvm::GlobalVariable *> GeneratedRefs;
1570 llvm::Type *LlvmPtrTy =
CGM.getTypes().ConvertTypeForMem(
1571 CGM.getContext().getPointerType(VD->
getType()));
1572 llvm::Constant *addr =
OMPBuilder.getAddrOfDeclareTargetVar(
1578 CGM.getMangledName(VD), GeneratedRefs,
CGM.getLangOpts().OpenMPSimd,
1579 CGM.getLangOpts().OMPTargetTriples, LlvmPtrTy, AddrOfGlobal,
1580 LinkageForVariable);
1589 assert(!
CGM.getLangOpts().OpenMPUseTLS ||
1590 !
CGM.getContext().getTargetInfo().isTLSSupported());
1592 std::string Suffix =
getName({
"cache",
""});
1593 return OMPBuilder.getOrCreateInternalVariable(
1594 CGM.Int8PtrPtrTy, Twine(
CGM.getMangledName(VD)).concat(Suffix).str());
1601 if (
CGM.getLangOpts().OpenMPUseTLS &&
1602 CGM.getContext().getTargetInfo().isTLSSupported())
1606 llvm::Value *Args[] = {
1609 CGM.getSize(
CGM.GetTargetTypeStoreSize(VarTy)),
1614 CGM.getModule(), OMPRTL___kmpc_threadprivate_cached),
1626 CGM.getModule(), OMPRTL___kmpc_global_thread_num),
1630 llvm::Value *Args[] = {
1633 Ctor, CopyCtor, Dtor};
1636 CGM.getModule(), OMPRTL___kmpc_threadprivate_register),
1643 if (
CGM.getLangOpts().OpenMPUseTLS &&
1644 CGM.getContext().getTargetInfo().isTLSSupported())
1651 llvm::Value *Ctor =
nullptr, *CopyCtor =
nullptr, *Dtor =
nullptr;
1653 if (
CGM.getLangOpts().CPlusPlus && PerformInit) {
1659 nullptr,
CGM.getContext().VoidPtrTy,
1661 Args.push_back(&Dst);
1663 const auto &FI =
CGM.getTypes().arrangeBuiltinFunctionDeclaration(
1664 CGM.getContext().VoidPtrTy, Args);
1665 llvm::FunctionType *FTy =
CGM.getTypes().GetFunctionType(FI);
1666 std::string Name =
getName({
"__kmpc_global_ctor_",
""});
1667 llvm::Function *Fn =
1668 CGM.CreateGlobalInitOrCleanUpFunction(FTy, Name, FI, Loc);
1691 nullptr,
CGM.getContext().VoidPtrTy,
1693 Args.push_back(&Dst);
1695 const auto &FI =
CGM.getTypes().arrangeBuiltinFunctionDeclaration(
1696 CGM.getContext().VoidTy, Args);
1697 llvm::FunctionType *FTy =
CGM.getTypes().GetFunctionType(FI);
1698 std::string Name =
getName({
"__kmpc_global_dtor_",
""});
1699 llvm::Function *Fn =
1700 CGM.CreateGlobalInitOrCleanUpFunction(FTy, Name, FI, Loc);
1723 CopyCtor = llvm::Constant::getNullValue(
CGM.DefaultPtrTy);
1724 if (Ctor ==
nullptr) {
1725 Ctor = llvm::Constant::getNullValue(
CGM.DefaultPtrTy);
1727 if (Dtor ==
nullptr) {
1728 Dtor = llvm::Constant::getNullValue(
CGM.DefaultPtrTy);
1731 auto *InitFunctionTy =
1732 llvm::FunctionType::get(
CGM.VoidTy,
false);
1733 std::string Name =
getName({
"__omp_threadprivate_init_",
""});
1734 llvm::Function *InitFunction =
CGM.CreateGlobalInitOrCleanUpFunction(
1735 InitFunctionTy, Name,
CGM.getTypes().arrangeNullaryFunction());
1739 CGM.getTypes().arrangeNullaryFunction(), ArgList,
1743 return InitFunction;
1751 llvm::GlobalValue *GV) {
1752 std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr =
1753 OMPDeclareTargetDeclAttr::getActiveAttr(FD);
1756 if (!ActiveAttr || !(*ActiveAttr)->getIndirect())
1763 OMPBuilder.OffloadInfoManager.getTargetRegionEntryFnName(Name, EntryInfo);
1769 llvm::GlobalValue *
Addr = GV;
1770 if (
CGM.getLangOpts().OpenMPIsTargetDevice) {
1771 llvm::PointerType *FnPtrTy = llvm::PointerType::get(
1772 CGM.getLLVMContext(),
1773 CGM.getModule().getDataLayout().getProgramAddressSpace());
1774 Addr =
new llvm::GlobalVariable(
1775 CGM.getModule(), FnPtrTy,
1776 true, llvm::GlobalValue::ExternalLinkage, GV, Name,
1777 nullptr, llvm::GlobalValue::NotThreadLocal,
1778 CGM.getModule().getDataLayout().getDefaultGlobalsAddressSpace());
1779 Addr->setVisibility(llvm::GlobalValue::ProtectedVisibility);
1786 OMPBuilder.OffloadInfoManager.registerDeviceGlobalVarEntryInfo(
1787 Name,
Addr,
CGM.GetTargetTypeStoreSize(
CGM.VoidPtrTy).getQuantity(),
1788 llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryIndirect,
1789 llvm::GlobalValue::WeakODRLinkage);
1802 llvm::OpenMPIRBuilder &
OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
1818 llvm::GlobalVariable *
Addr = VTable;
1820 OMPBuilder.OffloadInfoManager.getTargetRegionEntryFnName(AddrName, EntryInfo);
1821 AddrName.append(
"addr");
1823 if (
CGM.getLangOpts().OpenMPIsTargetDevice) {
1824 Addr =
new llvm::GlobalVariable(
1825 CGM.getModule(), VTable->getType(),
1826 true, llvm::GlobalValue::ExternalLinkage, VTable,
1828 nullptr, llvm::GlobalValue::NotThreadLocal,
1829 CGM.getModule().getDataLayout().getDefaultGlobalsAddressSpace());
1830 Addr->setVisibility(llvm::GlobalValue::ProtectedVisibility);
1832 OMPBuilder.OffloadInfoManager.registerDeviceGlobalVarEntryInfo(
1834 CGM.getDataLayout().getTypeAllocSize(VTable->getInitializer()->getType()),
1835 llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryIndirectVTable,
1836 llvm::GlobalValue::WeakODRLinkage);
1845 !
CGM.getOpenMPRuntime().VTableDeclMap.contains(
CXXRecord)) {
1846 auto Res =
CGM.getOpenMPRuntime().VTableDeclMap.try_emplace(
CXXRecord, VD);
1851 assert(VTablesAddr &&
"Expected non-null VTable address");
1852 CGM.getOpenMPRuntime().registerVTableOffloadEntry(VTablesAddr, VD);
1870 auto GetVTableDecl = [](
const Expr *E) {
1881 if (
auto *DRE = dyn_cast<DeclRefExpr>(E)) {
1883 }
else if (
auto *MRE = dyn_cast<MemberExpr>(E)) {
1884 if (
auto *BaseDRE = dyn_cast<DeclRefExpr>(MRE->getBase())) {
1885 if (
auto *BaseVD = dyn_cast<VarDecl>(BaseDRE->getDecl()))
1889 return std::pair<CXXRecordDecl *, const VarDecl *>(
CXXRecord, VD);
1893 for (
const auto *E :
C->varlist()) {
1894 auto DeclPair = GetVTableDecl(E);
1896 if (DeclPair.second)
1905 std::string Suffix =
getName({
"artificial",
""});
1907 llvm::GlobalVariable *GAddr =
OMPBuilder.getOrCreateInternalVariable(
1908 VarLVType, Twine(Name).concat(Suffix).str());
1909 if (
CGM.getLangOpts().OpenMP &&
CGM.getLangOpts().OpenMPUseTLS &&
1910 CGM.getTarget().isTLSSupported()) {
1911 GAddr->setThreadLocal(
true);
1912 return Address(GAddr, GAddr->getValueType(),
1913 CGM.getContext().getTypeAlignInChars(VarType));
1915 std::string CacheSuffix =
getName({
"cache",
""});
1916 llvm::Value *Args[] = {
1924 Twine(Name).concat(Suffix).concat(CacheSuffix).str())};
1929 CGM.getModule(), OMPRTL___kmpc_threadprivate_cached),
1932 VarLVType,
CGM.getContext().getTypeAlignInChars(VarType));
1982 auto &M =
CGM.getModule();
1983 auto &&ThenGen = [&M, OutlinedFn, CapturedVars, RTLoc,
1986 llvm::Value *Args[] = {
1988 CGF.
Builder.getInt32(CapturedVars.size()),
1991 RealArgs.append(std::begin(Args), std::end(Args));
1992 RealArgs.append(CapturedVars.begin(), CapturedVars.end());
1994 llvm::FunctionCallee RTLFn =
1995 OMPBuilder.getOrCreateRuntimeFunction(M, OMPRTL___kmpc_fork_call);
1998 auto &&ElseGen = [&M, OutlinedFn, CapturedVars, RTLoc, Loc,
2004 llvm::Value *Args[] = {RTLoc, ThreadID};
2006 M, OMPRTL___kmpc_serialized_parallel),
2013 ".bound.zero.addr");
2018 OutlinedFnArgs.push_back(ZeroAddrBound.
getPointer());
2019 OutlinedFnArgs.append(CapturedVars.begin(), CapturedVars.end());
2027 OutlinedFn->removeFnAttr(llvm::Attribute::AlwaysInline);
2028 OutlinedFn->addFnAttr(llvm::Attribute::NoInline);
2034 M, OMPRTL___kmpc_end_serialized_parallel),
2053 if (
auto *OMPRegionInfo =
2055 if (OMPRegionInfo->getThreadIDVariable())
2056 return OMPRegionInfo->getThreadIDVariableLValue(CGF).getAddress();
2065 return ThreadIDTemp;
2069 std::string Prefix = Twine(
"gomp_critical_user_", CriticalName).str();
2070 std::string Name =
getName({Prefix,
"var"});
2077 llvm::FunctionCallee EnterCallee;
2079 llvm::FunctionCallee ExitCallee;
2082 llvm::BasicBlock *ContBlock =
nullptr;
2085 CommonActionTy(llvm::FunctionCallee EnterCallee,
2087 llvm::FunctionCallee ExitCallee,
2089 : EnterCallee(EnterCallee), EnterArgs(EnterArgs), ExitCallee(ExitCallee),
2094 llvm::Value *CallBool = CGF.
Builder.CreateIsNotNull(EnterRes);
2098 CGF.
Builder.CreateCondBr(CallBool, ThenBlock, ContBlock);
2102 void Done(CodeGenFunction &CGF) {
2107 void Exit(CodeGenFunction &CGF)
override {
2114 StringRef CriticalName,
2123 llvm::FunctionCallee RuntimeFcn =
OMPBuilder.getOrCreateRuntimeFunction(
2125 Hint ? OMPRTL___kmpc_critical_with_hint : OMPRTL___kmpc_critical);
2127 unsigned LockVarArgIdx = 2;
2129 RuntimeFcn.getFunctionType()
2130 ->getParamType(LockVarArgIdx)
2131 ->getPointerAddressSpace())
2133 LockVar, RuntimeFcn.getFunctionType()->getParamType(LockVarArgIdx));
2139 EnterArgs.push_back(CGF.
Builder.CreateIntCast(
2142 CommonActionTy Action(RuntimeFcn, EnterArgs,
2144 CGM.getModule(), OMPRTL___kmpc_end_critical),
2161 CommonActionTy Action(
OMPBuilder.getOrCreateRuntimeFunction(
2162 CGM.getModule(), OMPRTL___kmpc_master),
2165 CGM.getModule(), OMPRTL___kmpc_end_master),
2183 llvm::Value *FilterVal = Filter
2185 : llvm::ConstantInt::get(
CGM.Int32Ty, 0);
2190 CommonActionTy Action(
OMPBuilder.getOrCreateRuntimeFunction(
2191 CGM.getModule(), OMPRTL___kmpc_masked),
2194 CGM.getModule(), OMPRTL___kmpc_end_masked),
2210 llvm::Value *Args[] = {
2212 llvm::ConstantInt::get(
CGM.IntTy, 0,
true)};
2214 CGM.getModule(), OMPRTL___kmpc_omp_taskyield),
2218 if (
auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.
CapturedStmtInfo))
2219 Region->emitUntiedSwitch(CGF);
2232 CommonActionTy Action(
OMPBuilder.getOrCreateRuntimeFunction(
2233 CGM.getModule(), OMPRTL___kmpc_taskgroup),
2236 CGM.getModule(), OMPRTL___kmpc_end_taskgroup),
2245 unsigned Index,
const VarDecl *Var) {
2266 Args.push_back(&LHSArg);
2267 Args.push_back(&RHSArg);
2273 llvm::GlobalValue::InternalLinkage, Name,
2277 Fn->addFnAttr(
"sample-profile-suffix-elision-policy",
"selected");
2278 Fn->setDoesNotRecurse();
2295 for (
unsigned I = 0, E = AssignmentOps.size(); I < E; ++I) {
2296 const auto *DestVar =
2300 const auto *SrcVar =
2306 CGF.
EmitOMPCopy(
Type, DestAddr, SrcAddr, DestVar, SrcVar, AssignmentOps[I]);
2321 assert(CopyprivateVars.size() == SrcExprs.size() &&
2322 CopyprivateVars.size() == DstExprs.size() &&
2323 CopyprivateVars.size() == AssignmentOps.size());
2335 if (!CopyprivateVars.empty()) {
2338 C.getIntTypeForBitwidth(32, 1);
2339 DidIt = CGF.
CreateMemTemp(KmpInt32Ty,
".omp.copyprivate.did_it");
2344 CommonActionTy Action(
OMPBuilder.getOrCreateRuntimeFunction(
2345 CGM.getModule(), OMPRTL___kmpc_single),
2348 CGM.getModule(), OMPRTL___kmpc_end_single),
2361 llvm::APInt ArraySize(32, CopyprivateVars.size());
2362 QualType CopyprivateArrayTy =
C.getConstantArrayType(
2367 CGF.
CreateMemTemp(CopyprivateArrayTy,
".omp.copyprivate.cpr_list");
2368 for (
unsigned I = 0, E = CopyprivateVars.size(); I < E; ++I) {
2380 SrcExprs, DstExprs, AssignmentOps, Loc);
2381 llvm::Value *BufSize = CGF.
getTypeSize(CopyprivateArrayTy);
2385 llvm::Value *Args[] = {
2389 CL.emitRawPointer(CGF),
2394 CGM.getModule(), OMPRTL___kmpc_copyprivate),
2410 CommonActionTy Action(
OMPBuilder.getOrCreateRuntimeFunction(
2411 CGM.getModule(), OMPRTL___kmpc_ordered),
2414 CGM.getModule(), OMPRTL___kmpc_end_ordered),
2425 if (Kind == OMPD_for)
2426 Flags = OMP_IDENT_BARRIER_IMPL_FOR;
2427 else if (Kind == OMPD_sections)
2428 Flags = OMP_IDENT_BARRIER_IMPL_SECTIONS;
2429 else if (Kind == OMPD_single)
2430 Flags = OMP_IDENT_BARRIER_IMPL_SINGLE;
2431 else if (Kind == OMPD_barrier)
2432 Flags = OMP_IDENT_BARRIER_EXPL;
2434 Flags = OMP_IDENT_BARRIER_IMPL;
2444 S.getClausesOfKind<OMPOrderedClause>(),
2445 [](
const OMPOrderedClause *
C) { return C->getNumForLoops(); })) {
2446 ScheduleKind = OMPC_SCHEDULE_static;
2448 llvm::APInt ChunkSize(32, 1);
2458 bool ForceSimpleCall) {
2460 auto *OMPRegionInfo =
2463 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
2466 CGF.
Builder.restoreIP(AfterIP);
2479 if (OMPRegionInfo) {
2480 if (!ForceSimpleCall && OMPRegionInfo->hasCancel()) {
2483 OMPRTL___kmpc_cancel_barrier),
2492 CGF.
Builder.CreateCondBr(
Cmp, ExitBB, ContBB);
2504 CGM.getModule(), OMPRTL___kmpc_barrier),
2509 Expr *ME,
bool IsFatal) {
2511 : llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
2514 llvm::Value *Args[] = {
2516 llvm::ConstantInt::get(
CGM.Int32Ty, IsFatal ? 2 : 1),
2517 CGF.
Builder.CreatePointerCast(MVL,
CGM.Int8PtrTy)};
2519 CGM.getModule(), OMPRTL___kmpc_error),
2525 bool Chunked,
bool Ordered) {
2526 switch (ScheduleKind) {
2527 case OMPC_SCHEDULE_static:
2528 return Chunked ? (Ordered ? OMP_ord_static_chunked : OMP_sch_static_chunked)
2529 : (Ordered ? OMP_ord_static : OMP_sch_static);
2530 case OMPC_SCHEDULE_dynamic:
2531 return Ordered ? OMP_ord_dynamic_chunked : OMP_sch_dynamic_chunked;
2532 case OMPC_SCHEDULE_guided:
2533 return Ordered ? OMP_ord_guided_chunked : OMP_sch_guided_chunked;
2534 case OMPC_SCHEDULE_runtime:
2535 return Ordered ? OMP_ord_runtime : OMP_sch_runtime;
2536 case OMPC_SCHEDULE_auto:
2537 return Ordered ? OMP_ord_auto : OMP_sch_auto;
2539 assert(!Chunked &&
"chunk was specified but schedule kind not known");
2540 return Ordered ? OMP_ord_static : OMP_sch_static;
2542 llvm_unreachable(
"Unexpected runtime schedule");
2546static OpenMPSchedType
2549 return Chunked ? OMP_dist_sch_static_chunked : OMP_dist_sch_static;
2553 bool Chunked)
const {
2554 OpenMPSchedType Schedule =
2556 return Schedule == OMP_sch_static;
2562 return Schedule == OMP_dist_sch_static;
2566 bool Chunked)
const {
2567 OpenMPSchedType Schedule =
2569 return Schedule == OMP_sch_static_chunked;
2575 return Schedule == OMP_dist_sch_static_chunked;
2579 OpenMPSchedType Schedule =
2581 assert(Schedule != OMP_sch_static_chunked &&
"cannot be chunked here");
2582 return Schedule != OMP_sch_static;
2590 case OMPC_SCHEDULE_MODIFIER_monotonic:
2591 Modifier = OMP_sch_modifier_monotonic;
2593 case OMPC_SCHEDULE_MODIFIER_nonmonotonic:
2594 Modifier = OMP_sch_modifier_nonmonotonic;
2596 case OMPC_SCHEDULE_MODIFIER_simd:
2597 if (Schedule == OMP_sch_static_chunked)
2598 Schedule = OMP_sch_static_balanced_chunked;
2605 case OMPC_SCHEDULE_MODIFIER_monotonic:
2606 Modifier = OMP_sch_modifier_monotonic;
2608 case OMPC_SCHEDULE_MODIFIER_nonmonotonic:
2609 Modifier = OMP_sch_modifier_nonmonotonic;
2611 case OMPC_SCHEDULE_MODIFIER_simd:
2612 if (Schedule == OMP_sch_static_chunked)
2613 Schedule = OMP_sch_static_balanced_chunked;
2625 if (CGM.
getLangOpts().OpenMP >= 50 && Modifier == 0) {
2626 if (!(Schedule == OMP_sch_static_chunked || Schedule == OMP_sch_static ||
2627 Schedule == OMP_sch_static_balanced_chunked ||
2628 Schedule == OMP_ord_static_chunked || Schedule == OMP_ord_static ||
2629 Schedule == OMP_dist_sch_static_chunked ||
2630 Schedule == OMP_dist_sch_static))
2631 Modifier = OMP_sch_modifier_nonmonotonic;
2633 return Schedule | Modifier;
2643 ScheduleKind.
Schedule, DispatchValues.
Chunk !=
nullptr, Ordered);
2645 (Schedule != OMP_sch_static && Schedule != OMP_sch_static_chunked &&
2646 Schedule != OMP_ord_static && Schedule != OMP_ord_static_chunked &&
2647 Schedule != OMP_sch_static_balanced_chunked));
2654 llvm::Value *Chunk = DispatchValues.
Chunk ? DispatchValues.
Chunk
2655 : CGF.
Builder.getIntN(IVSize, 1);
2656 llvm::Value *Args[] = {
2660 CGM, Schedule, ScheduleKind.
M1, ScheduleKind.
M2)),
2663 CGF.
Builder.getIntN(IVSize, 1),
2680 CodeGenFunction &CGF, llvm::Value *UpdateLocation, llvm::Value *ThreadId,
2681 llvm::FunctionCallee ForStaticInitFunction, OpenMPSchedType Schedule,
2688 assert(Schedule == OMP_sch_static || Schedule == OMP_sch_static_chunked ||
2689 Schedule == OMP_sch_static_balanced_chunked ||
2690 Schedule == OMP_ord_static || Schedule == OMP_ord_static_chunked ||
2691 Schedule == OMP_dist_sch_static ||
2692 Schedule == OMP_dist_sch_static_chunked);
2699 llvm::Value *Chunk = Values.
Chunk;
2700 if (Chunk ==
nullptr) {
2701 assert((Schedule == OMP_sch_static || Schedule == OMP_ord_static ||
2702 Schedule == OMP_dist_sch_static) &&
2703 "expected static non-chunked schedule");
2707 assert((Schedule == OMP_sch_static_chunked ||
2708 Schedule == OMP_sch_static_balanced_chunked ||
2709 Schedule == OMP_ord_static_chunked ||
2710 Schedule == OMP_dist_sch_static_chunked) &&
2711 "expected static chunked schedule");
2713 llvm::Value *Args[] = {
2736 "Expected loop-based or sections-based directive.");
2739 ? OMP_IDENT_WORK_LOOP
2740 : OMP_IDENT_WORK_SECTIONS);
2742 llvm::FunctionCallee StaticInitFunction =
2747 ScheduleNum, ScheduleKind.
M1, ScheduleKind.
M2, Values);
2754 OpenMPSchedType ScheduleNum =
2756 llvm::Value *UpdatedLocation =
2759 llvm::FunctionCallee StaticInitFunction;
2760 bool isGPUDistribute =
2761 CGM.getLangOpts().OpenMPIsTargetDevice &&
CGM.getTriple().isGPU();
2762 StaticInitFunction =
OMPBuilder.createForStaticInitFunction(
2773 assert((DKind == OMPD_distribute || DKind == OMPD_for ||
2774 DKind == OMPD_sections) &&
2775 "Expected distribute, for, or sections directive kind");
2779 llvm::Value *Args[] = {
2782 (DKind == OMPD_target_teams_loop)
2783 ? OMP_IDENT_WORK_DISTRIBUTE
2785 ? OMP_IDENT_WORK_LOOP
2786 : OMP_IDENT_WORK_SECTIONS),
2790 CGM.getLangOpts().OpenMPIsTargetDevice &&
CGM.getTriple().isGPU())
2793 CGM.getModule(), OMPRTL___kmpc_distribute_static_fini),
2797 CGM.getModule(), OMPRTL___kmpc_for_static_fini),
2822 llvm::Value *Args[] = {
2830 OMPBuilder.createDispatchNextFunction(IVSize, IVSigned), Args);
2837 const Expr *Message,
2840 return llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
2849 return llvm::ConstantInt::get(
CGM.Int32Ty,
2850 Severity == OMPC_SEVERITY_warning ? 1 : 2);
2866 RuntimeFunction FnID = OMPRTL___kmpc_push_num_threads;
2867 if (Modifier == OMPC_NUMTHREADS_strict) {
2868 FnID = OMPRTL___kmpc_push_num_threads_strict;
2873 OMPBuilder.getOrCreateRuntimeFunction(
CGM.getModule(), FnID), Args);
2877 ProcBindKind ProcBind,
2881 assert(ProcBind != OMP_PROC_BIND_unknown &&
"Unsupported proc_bind value.");
2883 llvm::Value *Args[] = {
2885 llvm::ConstantInt::get(
CGM.IntTy,
unsigned(ProcBind),
true)};
2887 CGM.getModule(), OMPRTL___kmpc_push_proc_bind),
2900 CGM.getModule(), OMPRTL___kmpc_flush),
2907enum KmpTaskTFields {
2934 if (
CGM.getLangOpts().OpenMPSimd ||
OMPBuilder.OffloadInfoManager.empty())
2937 llvm::OpenMPIRBuilder::EmitMetadataErrorReportFunctionTy &&ErrorReportFn =
2938 [
this](llvm::OpenMPIRBuilder::EmitMetadataErrorKind Kind,
2939 const llvm::TargetRegionEntryInfo &EntryInfo) ->
void {
2941 if (Kind != llvm::OpenMPIRBuilder::EMIT_MD_GLOBAL_VAR_LINK_ERROR) {
2942 for (
auto I =
CGM.getContext().getSourceManager().fileinfo_begin(),
2943 E =
CGM.getContext().getSourceManager().fileinfo_end();
2945 if (I->getFirst().getUniqueID().getDevice() == EntryInfo.DeviceID &&
2946 I->getFirst().getUniqueID().getFile() == EntryInfo.FileID) {
2947 Loc =
CGM.getContext().getSourceManager().translateFileLineCol(
2948 I->getFirst(), EntryInfo.Line, 1);
2954 case llvm::OpenMPIRBuilder::EMIT_MD_TARGET_REGION_ERROR: {
2955 CGM.getDiags().Report(Loc,
2956 diag::err_target_region_offloading_entry_incorrect)
2957 << EntryInfo.ParentName;
2959 case llvm::OpenMPIRBuilder::EMIT_MD_DECLARE_TARGET_ERROR: {
2960 CGM.getDiags().Report(
2961 Loc, diag::err_target_var_offloading_entry_incorrect_with_parent)
2962 << EntryInfo.ParentName;
2964 case llvm::OpenMPIRBuilder::EMIT_MD_GLOBAL_VAR_LINK_ERROR: {
2965 CGM.getDiags().Report(diag::err_target_var_offloading_entry_incorrect);
2967 case llvm::OpenMPIRBuilder::EMIT_MD_GLOBAL_VAR_INDIRECT_ERROR: {
2968 unsigned DiagID =
CGM.getDiags().getCustomDiagID(
2970 "target variable is incorrect: the "
2971 "address is invalid.");
2972 CGM.getDiags().Report(DiagID);
2977 OMPBuilder.createOffloadEntriesAndInfoMetadata(ErrorReportFn);
2984 QualType KmpRoutineEntryTyArgs[] = {KmpInt32Ty,
C.VoidPtrTy};
2987 C.getFunctionType(KmpInt32Ty, KmpRoutineEntryTyArgs, EPI));
2993struct PrivateHelpersTy {
2994 PrivateHelpersTy(
const Expr *OriginalRef,
const VarDecl *Original,
2996 : OriginalRef(OriginalRef), Original(Original), PrivateCopy(PrivateCopy),
2997 PrivateElemInit(PrivateElemInit) {}
2998 PrivateHelpersTy(
const VarDecl *Original) : Original(Original) {}
2999 const Expr *OriginalRef =
nullptr;
3000 const VarDecl *Original =
nullptr;
3001 const VarDecl *PrivateCopy =
nullptr;
3002 const VarDecl *PrivateElemInit =
nullptr;
3003 bool isLocalPrivate()
const {
3004 return !OriginalRef && !PrivateCopy && !PrivateElemInit;
3007typedef std::pair<CharUnits , PrivateHelpersTy> PrivateDataTy;
3012 if (!CVD->
hasAttr<OMPAllocateDeclAttr>())
3014 const auto *AA = CVD->
getAttr<OMPAllocateDeclAttr>();
3016 return !(AA->getAllocatorType() == OMPAllocateDeclAttr::OMPDefaultMemAlloc &&
3017 !AA->getAllocator());
3027 RecordDecl *RD =
C.buildImplicitRecord(
".kmp_privates.t");
3029 for (
const auto &Pair :
Privates) {
3030 const VarDecl *VD = Pair.second.Original;
3034 if (Pair.second.isLocalPrivate()) {
3057 QualType KmpRoutineEntryPointerQTy) {
3077 CanQualType KmpCmplrdataTy =
C.getCanonicalTagType(UD);
3078 RecordDecl *RD =
C.buildImplicitRecord(
"kmp_task_t");
3108 RecordDecl *RD =
C.buildImplicitRecord(
"kmp_task_t_with_privates");
3128static llvm::Function *
3131 QualType KmpTaskTWithPrivatesPtrQTy,
3133 QualType SharedsPtrTy, llvm::Function *TaskFunction,
3134 llvm::Value *TaskPrivatesMap) {
3142 Args.push_back(&GtidArg);
3143 Args.push_back(&TaskTypeArg);
3144 const auto &TaskEntryFnInfo =
3146 llvm::FunctionType *TaskEntryTy =
3149 auto *TaskEntry = llvm::Function::Create(
3150 TaskEntryTy, llvm::GlobalValue::InternalLinkage, Name, &CGM.
getModule());
3153 TaskEntry->addFnAttr(
"sample-profile-suffix-elision-policy",
"selected");
3154 TaskEntry->setDoesNotRecurse();
3169 const auto *KmpTaskTWithPrivatesQTyRD =
3174 auto PartIdFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTPartId);
3176 llvm::Value *PartidParam = PartIdLVal.getPointer(CGF);
3178 auto SharedsFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTShareds);
3184 auto PrivatesFI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin(), 1);
3185 llvm::Value *PrivatesParam;
3186 if (PrivatesFI != KmpTaskTWithPrivatesQTyRD->field_end()) {
3189 PrivatesLVal.getPointer(CGF), CGF.
VoidPtrTy);
3191 PrivatesParam = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
3194 llvm::Value *CommonArgs[] = {
3195 GtidParam, PartidParam, PrivatesParam, TaskPrivatesMap,
3201 std::end(CommonArgs));
3203 auto LBFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound);
3206 auto UBFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound);
3209 auto StFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTStride);
3212 auto LIFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLastIter);
3215 auto RFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTReductions);
3218 CallArgs.push_back(LBParam);
3219 CallArgs.push_back(UBParam);
3220 CallArgs.push_back(StParam);
3221 CallArgs.push_back(LIParam);
3222 CallArgs.push_back(RParam);
3224 CallArgs.push_back(SharedsParam);
3237 QualType KmpTaskTWithPrivatesPtrQTy,
3238 QualType KmpTaskTWithPrivatesQTy) {
3246 Args.push_back(&GtidArg);
3247 Args.push_back(&TaskTypeArg);
3248 const auto &DestructorFnInfo =
3250 llvm::FunctionType *DestructorFnTy =
3254 auto *DestructorFn =
3255 llvm::Function::Create(DestructorFnTy, llvm::GlobalValue::InternalLinkage,
3260 DestructorFn->addFnAttr(
"sample-profile-suffix-elision-policy",
"selected");
3261 DestructorFn->setDoesNotRecurse();
3269 const auto *KmpTaskTWithPrivatesQTyRD =
3271 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin());
3273 for (
const auto *Field : FI->getType()->castAsRecordDecl()->fields()) {
3275 Field->getType().isDestructedType()) {
3277 CGF.
pushDestroy(DtorKind, FieldLValue.getAddress(), Field->getType());
3281 return DestructorFn;
3301 C,
nullptr, Loc,
nullptr,
3302 C.getPointerType(PrivatesQTy).withConst().withRestrict(),
3304 Args.push_back(&TaskPrivatesArg);
3305 llvm::DenseMap<CanonicalDeclPtr<const VarDecl>,
unsigned> PrivateVarsPos;
3306 unsigned Counter = 1;
3307 for (
const Expr *E :
Data.PrivateVars) {
3309 C,
nullptr, Loc,
nullptr,
3310 C.getPointerType(
C.getPointerType(E->
getType()))
3315 PrivateVarsPos[VD] = Counter;
3318 for (
const Expr *E :
Data.FirstprivateVars) {
3320 C,
nullptr, Loc,
nullptr,
3321 C.getPointerType(
C.getPointerType(E->
getType()))
3326 PrivateVarsPos[VD] = Counter;
3329 for (
const Expr *E :
Data.LastprivateVars) {
3331 C,
nullptr, Loc,
nullptr,
3332 C.getPointerType(
C.getPointerType(E->
getType()))
3337 PrivateVarsPos[VD] = Counter;
3343 Ty =
C.getPointerType(Ty);
3345 Ty =
C.getPointerType(Ty);
3347 C,
nullptr, Loc,
nullptr,
3348 C.getPointerType(
C.getPointerType(Ty)).withConst().withRestrict(),
3350 PrivateVarsPos[VD] = Counter;
3353 const auto &TaskPrivatesMapFnInfo =
3355 llvm::FunctionType *TaskPrivatesMapTy =
3359 auto *TaskPrivatesMap = llvm::Function::Create(
3360 TaskPrivatesMapTy, llvm::GlobalValue::InternalLinkage, Name,
3363 TaskPrivatesMapFnInfo);
3365 TaskPrivatesMap->addFnAttr(
"sample-profile-suffix-elision-policy",
3368 TaskPrivatesMap->removeFnAttr(llvm::Attribute::NoInline);
3369 TaskPrivatesMap->removeFnAttr(llvm::Attribute::OptimizeNone);
3370 TaskPrivatesMap->addFnAttr(llvm::Attribute::AlwaysInline);
3374 TaskPrivatesMapFnInfo, Args, Loc, Loc);
3382 for (
const FieldDecl *Field : PrivatesQTyRD->fields()) {
3384 const VarDecl *VD = Args[PrivateVarsPos[
Privates[Counter].second.Original]];
3388 RefLVal.getAddress(), RefLVal.getType()->castAs<
PointerType>());
3393 return TaskPrivatesMap;
3399 Address KmpTaskSharedsPtr, LValue TDBase,
3405 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->
field_begin());
3419 if ((!IsTargetTask && !
Data.FirstprivateVars.empty() && ForDup) ||
3420 (IsTargetTask && KmpTaskSharedsPtr.
isValid())) {
3427 FI = FI->getType()->castAsRecordDecl()->field_begin();
3428 for (
const PrivateDataTy &Pair :
Privates) {
3430 if (Pair.second.isLocalPrivate()) {
3434 const VarDecl *VD = Pair.second.PrivateCopy;
3439 if (
const VarDecl *Elem = Pair.second.PrivateElemInit) {
3440 const VarDecl *OriginalVD = Pair.second.Original;
3443 LValue SharedRefLValue;
3446 if (IsTargetTask && !SharedField) {
3450 ->getNumParams() == 0 &&
3453 ->getDeclContext()) &&
3454 "Expected artificial target data variable.");
3457 }
else if (ForDup) {
3460 SharedRefLValue.getAddress().withAlignment(
3461 C.getDeclAlign(OriginalVD)),
3463 SharedRefLValue.getTBAAInfo());
3465 Pair.second.Original->getCanonicalDecl()) > 0 ||
3467 SharedRefLValue = CGF.
EmitLValue(Pair.second.OriginalRef);
3470 InlinedOpenMPRegionRAII Region(
3473 SharedRefLValue = CGF.
EmitLValue(Pair.second.OriginalRef);
3484 PrivateLValue.getAddress(), SharedRefLValue.getAddress(),
Type,
3485 [&CGF, Elem,
Init, &CapturesInfo](
Address DestElement,
3488 CodeGenFunction::OMPPrivateScope InitScope(CGF);
3489 InitScope.addPrivate(Elem, SrcElement);
3490 (void)InitScope.Privatize();
3492 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(
3493 CGF, &CapturesInfo);
3494 CGF.EmitAnyExprToMem(Init, DestElement,
3495 Init->getType().getQualifiers(),
3501 InitScope.addPrivate(Elem, SharedRefLValue.getAddress());
3502 (void)InitScope.Privatize();
3518 bool InitRequired =
false;
3519 for (
const PrivateDataTy &Pair :
Privates) {
3520 if (Pair.second.isLocalPrivate())
3522 const VarDecl *VD = Pair.second.PrivateCopy;
3524 InitRequired = InitRequired || (isa_and_nonnull<CXXConstructExpr>(
Init) &&
3529 return InitRequired;
3546 QualType KmpTaskTWithPrivatesPtrQTy,
3554 KmpTaskTWithPrivatesPtrQTy,
3557 KmpTaskTWithPrivatesPtrQTy,
3561 Args.push_back(&DstArg);
3562 Args.push_back(&SrcArg);
3563 Args.push_back(&LastprivArg);
3564 const auto &TaskDupFnInfo =
3568 auto *TaskDup = llvm::Function::Create(
3569 TaskDupTy, llvm::GlobalValue::InternalLinkage, Name, &CGM.
getModule());
3572 TaskDup->addFnAttr(
"sample-profile-suffix-elision-policy",
"selected");
3573 TaskDup->setDoesNotRecurse();
3583 auto LIFI = std::next(KmpTaskTQTyRD->
field_begin(), KmpTaskTLastIter);
3585 TDBase, *KmpTaskTWithPrivatesQTyRD->
field_begin());
3595 if (!
Data.FirstprivateVars.empty()) {
3600 TDBase, *KmpTaskTWithPrivatesQTyRD->
field_begin());
3608 emitPrivatesInit(CGF, D, KmpTaskSharedsPtr, TDBase, KmpTaskTWithPrivatesQTyRD,
3619 for (
const PrivateDataTy &P :
Privates) {
3620 if (P.second.isLocalPrivate())
3622 QualType Ty = P.second.Original->getType().getNonReferenceType();
3631class OMPIteratorGeneratorScope final
3633 CodeGenFunction &CGF;
3634 const OMPIteratorExpr *E =
nullptr;
3635 SmallVector<CodeGenFunction::JumpDest, 4> ContDests;
3636 SmallVector<CodeGenFunction::JumpDest, 4> ExitDests;
3637 OMPIteratorGeneratorScope() =
delete;
3638 OMPIteratorGeneratorScope(OMPIteratorGeneratorScope &) =
delete;
3641 OMPIteratorGeneratorScope(CodeGenFunction &CGF,
const OMPIteratorExpr *E)
3642 : CodeGenFunction::OMPPrivateScope(CGF), CGF(CGF), E(E) {
3645 SmallVector<llvm::Value *, 4> Uppers;
3647 Uppers.push_back(CGF.EmitScalarExpr(E->getHelper(I).Upper));
3648 const auto *VD = cast<VarDecl>(E->getIteratorDecl(I));
3649 addPrivate(VD, CGF.CreateMemTemp(VD->getType(), VD->getName()));
3650 const OMPIteratorHelperData &HelperData = E->getHelper(I);
3652 HelperData.CounterVD,
3653 CGF.CreateMemTemp(HelperData.CounterVD->getType(),
"counter.addr"));
3658 const OMPIteratorHelperData &HelperData = E->getHelper(I);
3660 CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(HelperData.CounterVD),
3661 HelperData.CounterVD->getType());
3663 CGF.EmitStoreOfScalar(
3664 llvm::ConstantInt::get(CLVal.getAddress().getElementType(), 0),
3666 CodeGenFunction::JumpDest &ContDest =
3667 ContDests.emplace_back(CGF.getJumpDestInCurrentScope(
"iter.cont"));
3668 CodeGenFunction::JumpDest &ExitDest =
3669 ExitDests.emplace_back(CGF.getJumpDestInCurrentScope(
"iter.exit"));
3671 llvm::Value *N = Uppers[I];
3674 CGF.EmitBlock(ContDest.getBlock());
3676 CGF.EmitLoadOfScalar(CLVal, HelperData.CounterVD->getLocation());
3678 HelperData.CounterVD->getType()->isSignedIntegerOrEnumerationType()
3679 ? CGF.Builder.CreateICmpSLT(CVal, N)
3680 : CGF.Builder.CreateICmpULT(CVal, N);
3681 llvm::BasicBlock *BodyBB = CGF.createBasicBlock(
"iter.body");
3682 CGF.Builder.CreateCondBr(Cmp, BodyBB, ExitDest.getBlock());
3684 CGF.EmitBlock(BodyBB);
3686 CGF.EmitIgnoredExpr(HelperData.Update);
3689 ~OMPIteratorGeneratorScope() {
3694 const OMPIteratorHelperData &HelperData = E->
getHelper(I - 1);
3699 CGF.
EmitBlock(ExitDests[I - 1].getBlock(), I == 1);
3705static std::pair<llvm::Value *, llvm::Value *>
3707 const auto *OASE = dyn_cast<OMPArrayShapingExpr>(E);
3710 const Expr *
Base = OASE->getBase();
3715 llvm::Value *SizeVal;
3718 SizeVal = CGF.
getTypeSize(OASE->getBase()->getType()->getPointeeType());
3719 for (
const Expr *SE : OASE->getDimensions()) {
3723 SizeVal = CGF.
Builder.CreateNUWMul(SizeVal, Sz);
3725 }
else if (
const auto *ASE =
3728 Address UpAddrAddress = UpAddrLVal.getAddress();
3729 llvm::Value *UpAddr = CGF.
Builder.CreateConstGEP1_32(
3733 llvm::Value *UpIntPtr = CGF.
Builder.CreatePtrToInt(UpAddr, CGF.
SizeTy);
3734 SizeVal = CGF.
Builder.CreateNUWSub(UpIntPtr, LowIntPtr);
3738 return std::make_pair(
Addr, SizeVal);
3743 QualType FlagsTy =
C.getIntTypeForBitwidth(32,
false);
3744 if (KmpTaskAffinityInfoTy.
isNull()) {
3746 C.buildImplicitRecord(
"kmp_task_affinity_info_t");
3752 KmpTaskAffinityInfoTy =
C.getCanonicalTagType(KmpAffinityInfoRD);
3759 llvm::Function *TaskFunction,
QualType SharedsTy,
3764 const auto *I =
Data.PrivateCopies.begin();
3765 for (
const Expr *E :
Data.PrivateVars) {
3773 I =
Data.FirstprivateCopies.begin();
3774 const auto *IElemInitRef =
Data.FirstprivateInits.begin();
3775 for (
const Expr *E :
Data.FirstprivateVars) {
3785 I =
Data.LastprivateCopies.begin();
3786 for (
const Expr *E :
Data.LastprivateVars) {
3796 Privates.emplace_back(
CGM.getPointerAlign(), PrivateHelpersTy(VD));
3798 Privates.emplace_back(
C.getDeclAlign(VD), PrivateHelpersTy(VD));
3801 [](
const PrivateDataTy &L,
const PrivateDataTy &R) {
3802 return L.first > R.first;
3804 QualType KmpInt32Ty =
C.getIntTypeForBitwidth(32, 1);
3815 assert((D.getDirectiveKind() == OMPD_task ||
3818 "Expected taskloop, task or target directive");
3825 const auto *KmpTaskTQTyRD =
KmpTaskTQTy->castAsRecordDecl();
3827 const RecordDecl *KmpTaskTWithPrivatesQTyRD =
3830 C.getCanonicalTagType(KmpTaskTWithPrivatesQTyRD);
3831 QualType KmpTaskTWithPrivatesPtrQTy =
3832 C.getPointerType(KmpTaskTWithPrivatesQTy);
3833 llvm::Type *KmpTaskTWithPrivatesPtrTy = CGF.
Builder.getPtrTy(0);
3834 llvm::Value *KmpTaskTWithPrivatesTySize =
3836 QualType SharedsPtrTy =
C.getPointerType(SharedsTy);
3839 llvm::Value *TaskPrivatesMap =
nullptr;
3840 llvm::Type *TaskPrivatesMapTy =
3841 std::next(TaskFunction->arg_begin(), 3)->getType();
3843 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->
field_begin());
3847 TaskPrivatesMap, TaskPrivatesMapTy);
3849 TaskPrivatesMap = llvm::ConstantPointerNull::get(
3855 CGM, Loc, D.getDirectiveKind(), KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy,
3856 KmpTaskTWithPrivatesQTy,
KmpTaskTQTy, SharedsPtrTy, TaskFunction,
3868 DestructorsFlag = 0x8,
3869 PriorityFlag = 0x20,
3870 DetachableFlag = 0x40,
3871 FreeAgentFlag = 0x80,
3872 TransparentFlag = 0x100,
3874 unsigned Flags =
Data.Tied ? TiedFlag : 0;
3875 bool NeedsCleanup =
false;
3880 Flags = Flags | DestructorsFlag;
3884 if (Kind == OMPC_THREADSET_omp_pool)
3885 Flags = Flags | FreeAgentFlag;
3887 if (D.getSingleClause<OMPTransparentClause>())
3888 Flags |= TransparentFlag;
3890 if (
Data.Priority.getInt())
3891 Flags = Flags | PriorityFlag;
3893 Flags = Flags | DetachableFlag;
3894 llvm::Value *TaskFlags =
3895 Data.Final.getPointer()
3896 ? CGF.
Builder.CreateSelect(
Data.Final.getPointer(),
3897 CGF.
Builder.getInt32(FinalFlag),
3899 : CGF.
Builder.getInt32(
Data.Final.getInt() ? FinalFlag : 0);
3900 TaskFlags = CGF.
Builder.CreateOr(TaskFlags, CGF.
Builder.getInt32(Flags));
3901 llvm::Value *SharedsSize =
CGM.getSize(
C.getTypeSizeInChars(SharedsTy));
3903 getThreadID(CGF, Loc), TaskFlags, KmpTaskTWithPrivatesTySize,
3906 llvm::Value *NewTask;
3907 if (D.hasClausesOfKind<OMPNowaitClause>()) {
3913 llvm::Value *DeviceID;
3918 DeviceID = CGF.
Builder.getInt64(OMP_DEVICEID_UNDEF);
3919 AllocArgs.push_back(DeviceID);
3922 CGM.getModule(), OMPRTL___kmpc_omp_target_task_alloc),
3927 CGM.getModule(), OMPRTL___kmpc_omp_task_alloc),
3940 llvm::Value *Tid =
getThreadID(CGF, DC->getBeginLoc());
3941 Tid = CGF.
Builder.CreateIntCast(Tid, CGF.
IntTy,
false);
3944 CGM.getModule(), OMPRTL___kmpc_task_allow_completion_event),
3945 {Loc, Tid, NewTask});
3956 llvm::Value *NumOfElements =
nullptr;
3957 unsigned NumAffinities = 0;
3959 if (
const Expr *Modifier =
C->getModifier()) {
3961 for (
unsigned I = 0, E = IE->numOfIterators(); I < E; ++I) {
3965 NumOfElements ? CGF.
Builder.CreateNUWMul(NumOfElements, Sz) : Sz;
3968 NumAffinities +=
C->varlist_size();
3973 enum RTLAffinityInfoFieldsTy { BaseAddr, Len, Flags };
3975 QualType KmpTaskAffinityInfoArrayTy;
3976 if (NumOfElements) {
3977 NumOfElements = CGF.
Builder.CreateNUWAdd(
3978 llvm::ConstantInt::get(CGF.
SizeTy, NumAffinities), NumOfElements);
3981 C.getIntTypeForBitwidth(
C.getTypeSize(
C.getSizeType()), 0),
3985 KmpTaskAffinityInfoArrayTy =
C.getVariableArrayType(
3993 NumOfElements = CGF.
Builder.CreateIntCast(NumOfElements, CGF.
Int32Ty,
3996 KmpTaskAffinityInfoArrayTy =
C.getConstantArrayType(
3998 llvm::APInt(
C.getTypeSize(
C.getSizeType()), NumAffinities),
nullptr,
4001 CGF.
CreateMemTemp(KmpTaskAffinityInfoArrayTy,
".affs.arr.addr");
4003 NumOfElements = llvm::ConstantInt::get(
CGM.Int32Ty, NumAffinities,
4010 bool HasIterator =
false;
4012 if (
C->getModifier()) {
4016 for (
const Expr *E :
C->varlist()) {
4025 Base, *std::next(KmpAffinityInfoRD->field_begin(), BaseAddr));
4030 Base, *std::next(KmpAffinityInfoRD->field_begin(), Len));
4044 const Expr *Modifier =
C->getModifier();
4047 OMPIteratorGeneratorScope IteratorScope(
4049 for (
const Expr *E :
C->varlist()) {
4059 Base, *std::next(KmpAffinityInfoRD->field_begin(), BaseAddr));
4064 Base, *std::next(KmpAffinityInfoRD->field_begin(), Len));
4066 Idx = CGF.
Builder.CreateNUWAdd(
4067 Idx, llvm::ConstantInt::get(Idx->getType(), 1));
4082 CGM.getModule(), OMPRTL___kmpc_omp_reg_task_with_affinity),
4083 {LocRef, GTid, NewTask, NumOfElements, AffinListPtr});
4085 llvm::Value *NewTaskNewTaskTTy =
4087 NewTask, KmpTaskTWithPrivatesPtrTy);
4089 KmpTaskTWithPrivatesQTy);
4100 *std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTShareds)),
4102 CGF.
Int8Ty,
CGM.getNaturalTypeAlignment(SharedsTy));
4116 CGM, Loc, D, KmpTaskTWithPrivatesPtrQTy, KmpTaskTWithPrivatesQTyRD,
4117 KmpTaskTQTyRD, SharedsTy, SharedsPtrTy,
Data,
Privates,
4118 !
Data.LastprivateVars.empty());
4122 enum { Priority = 0, Destructors = 1 };
4124 auto FI = std::next(KmpTaskTQTyRD->field_begin(), Data1);
4125 const auto *KmpCmplrdataUD = (*FI)->getType()->castAsRecordDecl();
4126 assert(KmpCmplrdataUD->isUnion());
4129 CGM, Loc, KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy,
4130 KmpTaskTWithPrivatesQTy);
4133 Data1LV, *std::next(KmpCmplrdataUD->field_begin(), Destructors));
4139 if (
Data.Priority.getInt()) {
4141 TDBase, *std::next(KmpTaskTQTyRD->field_begin(), Data2));
4143 Data2LV, *std::next(KmpCmplrdataUD->field_begin(), Priority));
4146 Result.NewTask = NewTask;
4147 Result.TaskEntry = TaskEntry;
4148 Result.NewTaskNewTaskTTy = NewTaskNewTaskTTy;
4150 Result.KmpTaskTQTyRD = KmpTaskTQTyRD;
4156 RTLDependenceKindTy DepKind;
4158 case OMPC_DEPEND_in:
4159 DepKind = RTLDependenceKindTy::DepIn;
4162 case OMPC_DEPEND_out:
4163 case OMPC_DEPEND_inout:
4164 DepKind = RTLDependenceKindTy::DepInOut;
4166 case OMPC_DEPEND_mutexinoutset:
4167 DepKind = RTLDependenceKindTy::DepMutexInOutSet;
4169 case OMPC_DEPEND_inoutset:
4170 DepKind = RTLDependenceKindTy::DepInOutSet;
4172 case OMPC_DEPEND_outallmemory:
4173 DepKind = RTLDependenceKindTy::DepOmpAllMem;
4175 case OMPC_DEPEND_source:
4176 case OMPC_DEPEND_sink:
4177 case OMPC_DEPEND_depobj:
4178 case OMPC_DEPEND_inoutallmemory:
4180 llvm_unreachable(
"Unknown task dependence type");
4188 FlagsTy =
C.getIntTypeForBitwidth(
C.getTypeSize(
C.BoolTy),
false);
4189 if (KmpDependInfoTy.
isNull()) {
4190 RecordDecl *KmpDependInfoRD =
C.buildImplicitRecord(
"kmp_depend_info");
4196 KmpDependInfoTy =
C.getCanonicalTagType(KmpDependInfoRD);
4200std::pair<llvm::Value *, LValue>
4213 CGF,
Base.getAddress(),
4214 llvm::ConstantInt::get(CGF.
IntPtrTy, -1,
true));
4220 *std::next(KmpDependInfoRD->field_begin(),
4221 static_cast<unsigned int>(RTLDependInfoFields::BaseAddr)));
4223 return std::make_pair(NumDeps,
Base);
4227 llvm::PointerUnion<unsigned *, LValue *> Pos,
4237 OMPIteratorGeneratorScope IteratorScope(
4238 CGF, cast_or_null<OMPIteratorExpr>(
4239 Data.IteratorExpr ?
Data.IteratorExpr->IgnoreParenImpCasts()
4241 for (
const Expr *E :
Data.DepExprs) {
4251 Size = llvm::ConstantInt::get(CGF.
SizeTy, 0);
4254 if (
unsigned *P = dyn_cast<unsigned *>(Pos)) {
4258 assert(E &&
"Expected a non-null expression");
4267 *std::next(KmpDependInfoRD->field_begin(),
4268 static_cast<unsigned int>(RTLDependInfoFields::BaseAddr)));
4272 Base, *std::next(KmpDependInfoRD->field_begin(),
4273 static_cast<unsigned int>(RTLDependInfoFields::Len)));
4279 *std::next(KmpDependInfoRD->field_begin(),
4280 static_cast<unsigned int>(RTLDependInfoFields::Flags)));
4282 llvm::ConstantInt::get(LLVMFlagsTy,
static_cast<unsigned int>(DepKind)),
4284 if (
unsigned *P = dyn_cast<unsigned *>(Pos)) {
4289 Idx = CGF.
Builder.CreateNUWAdd(Idx,
4290 llvm::ConstantInt::get(Idx->getType(), 1));
4299 assert(
Data.DepKind == OMPC_DEPEND_depobj &&
4300 "Expected depobj dependency kind.");
4305 OMPIteratorGeneratorScope IteratorScope(
4306 CGF, cast_or_null<OMPIteratorExpr>(
4307 Data.IteratorExpr ?
Data.IteratorExpr->IgnoreParenImpCasts()
4309 for (
const Expr *E :
Data.DepExprs) {
4310 llvm::Value *NumDeps;
4313 std::tie(NumDeps,
Base) =
4317 C.getUIntPtrType());
4321 llvm::Value *Add = CGF.
Builder.CreateNUWAdd(PrevVal, NumDeps);
4323 SizeLVals.push_back(NumLVal);
4326 for (
unsigned I = 0, E = SizeLVals.size(); I < E; ++I) {
4329 Sizes.push_back(Size);
4339 assert(
Data.DepKind == OMPC_DEPEND_depobj &&
4340 "Expected depobj dependency kind.");
4343 OMPIteratorGeneratorScope IteratorScope(
4344 CGF, cast_or_null<OMPIteratorExpr>(
4345 Data.IteratorExpr ?
Data.IteratorExpr->IgnoreParenImpCasts()
4347 for (
const Expr *E :
Data.DepExprs) {
4348 llvm::Value *NumDeps;
4351 std::tie(NumDeps,
Base) =
4355 llvm::Value *Size = CGF.
Builder.CreateNUWMul(
4364 llvm::Value *Add = CGF.
Builder.CreateNUWAdd(Pos, NumDeps);
4380 llvm::Value *NumOfElements =
nullptr;
4381 unsigned NumDependencies = std::accumulate(
4382 Dependencies.begin(), Dependencies.end(), 0,
4384 return D.DepKind == OMPC_DEPEND_depobj
4386 : (V + (D.IteratorExpr ? 0 : D.DepExprs.size()));
4390 bool HasDepobjDeps =
false;
4391 bool HasRegularWithIterators =
false;
4392 llvm::Value *NumOfDepobjElements = llvm::ConstantInt::get(CGF.
IntPtrTy, 0);
4393 llvm::Value *NumOfRegularWithIterators =
4394 llvm::ConstantInt::get(CGF.
IntPtrTy, 0);
4398 if (D.
DepKind == OMPC_DEPEND_depobj) {
4401 for (llvm::Value *Size : Sizes) {
4402 NumOfDepobjElements =
4403 CGF.
Builder.CreateNUWAdd(NumOfDepobjElements, Size);
4405 HasDepobjDeps =
true;
4410 if (
const auto *IE = cast_or_null<OMPIteratorExpr>(D.
IteratorExpr)) {
4411 llvm::Value *ClauseIteratorSpace =
4412 llvm::ConstantInt::get(CGF.
IntPtrTy, 1);
4416 ClauseIteratorSpace = CGF.
Builder.CreateNUWMul(Sz, ClauseIteratorSpace);
4418 llvm::Value *NumClauseDeps = CGF.
Builder.CreateNUWMul(
4419 ClauseIteratorSpace,
4421 NumOfRegularWithIterators =
4422 CGF.
Builder.CreateNUWAdd(NumOfRegularWithIterators, NumClauseDeps);
4423 HasRegularWithIterators =
true;
4429 if (HasDepobjDeps || HasRegularWithIterators) {
4430 NumOfElements = llvm::ConstantInt::get(
CGM.IntPtrTy, NumDependencies,
4432 if (HasDepobjDeps) {
4434 CGF.
Builder.CreateNUWAdd(NumOfDepobjElements, NumOfElements);
4436 if (HasRegularWithIterators) {
4438 CGF.
Builder.CreateNUWAdd(NumOfRegularWithIterators, NumOfElements);
4441 Loc,
C.getIntTypeForBitwidth(64, 0),
4445 KmpDependInfoArrayTy =
4454 NumOfElements = CGF.
Builder.CreateIntCast(NumOfElements, CGF.
Int32Ty,
4457 KmpDependInfoArrayTy =
C.getConstantArrayType(
4463 NumOfElements = llvm::ConstantInt::get(
CGM.Int32Ty, NumDependencies,
4468 if (Dep.DepKind == OMPC_DEPEND_depobj || Dep.IteratorExpr)
4474 CGF.
CreateMemTemp(
C.getSizeType(),
"dep.counter.addr"),
C.getSizeType());
4477 if (Dep.DepKind == OMPC_DEPEND_depobj || !Dep.IteratorExpr)
4482 if (HasDepobjDeps) {
4484 if (Dep.DepKind != OMPC_DEPEND_depobj)
4491 return std::make_pair(NumOfElements, DependenciesArray);
4502 unsigned NumDependencies = Dependencies.
DepExprs.size();
4512 llvm::Value *NumDepsVal;
4514 if (
const auto *IE =
4515 cast_or_null<OMPIteratorExpr>(Dependencies.
IteratorExpr)) {
4516 NumDepsVal = llvm::ConstantInt::get(CGF.
SizeTy, 1);
4520 NumDepsVal = CGF.
Builder.CreateNUWMul(NumDepsVal, Sz);
4522 Size = CGF.
Builder.CreateNUWAdd(llvm::ConstantInt::get(CGF.
SizeTy, 1),
4526 llvm::Value *RecSize =
CGM.getSize(SizeInBytes);
4527 Size = CGF.
Builder.CreateNUWMul(Size, RecSize);
4531 QualType KmpDependInfoArrayTy =
C.getConstantArrayType(
4534 CharUnits Sz =
C.getTypeSizeInChars(KmpDependInfoArrayTy);
4536 NumDepsVal = llvm::ConstantInt::get(CGF.
IntPtrTy, NumDependencies);
4541 llvm::Value *Allocator = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
4542 llvm::Value *Args[] = {ThreadID, Size, Allocator};
4546 CGM.getModule(), OMPRTL___kmpc_alloc),
4547 Args,
".dep.arr.addr");
4551 DependenciesArray =
Address(
Addr, KmpDependInfoLlvmTy, Align);
4557 *std::next(KmpDependInfoRD->field_begin(),
4558 static_cast<unsigned int>(RTLDependInfoFields::BaseAddr)));
4560 llvm::PointerUnion<unsigned *, LValue *> Pos;
4577 return DependenciesArray;
4592 Addr.getElementType(),
Addr.emitRawPointer(CGF),
4593 llvm::ConstantInt::get(CGF.
IntPtrTy, -1,
true));
4598 llvm::Value *Allocator = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
4599 llvm::Value *Args[] = {ThreadID, DepObjAddr, Allocator};
4603 CGM.getModule(), OMPRTL___kmpc_free),
4615 llvm::Value *NumDeps;
4626 llvm::BasicBlock *EntryBB = CGF.
Builder.GetInsertBlock();
4628 llvm::PHINode *ElementPHI =
4633 Base.getTBAAInfo());
4637 Base, *std::next(KmpDependInfoRD->field_begin(),
4638 static_cast<unsigned int>(RTLDependInfoFields::Flags)));
4640 llvm::ConstantInt::get(LLVMFlagsTy,
static_cast<unsigned int>(DepKind)),
4644 llvm::Value *ElementNext =
4647 ElementPHI->addIncoming(ElementNext, CGF.
Builder.GetInsertBlock());
4648 llvm::Value *IsEmpty =
4649 CGF.
Builder.CreateICmpEQ(ElementNext, End,
"omp.isempty");
4650 CGF.
Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
4657 llvm::Function *TaskFunction,
4666 llvm::Value *NewTask =
Result.NewTask;
4667 llvm::Function *TaskEntry =
Result.TaskEntry;
4668 llvm::Value *NewTaskNewTaskTTy =
Result.NewTaskNewTaskTTy;
4673 llvm::Value *NumOfElements;
4674 std::tie(NumOfElements, DependenciesArray) =
4685 llvm::Value *TaskArgs[] = { UpLoc, ThreadID, NewTask };
4686 llvm::Value *DepTaskArgs[7];
4687 if (!
Data.Dependences.empty()) {
4688 DepTaskArgs[0] = UpLoc;
4689 DepTaskArgs[1] = ThreadID;
4690 DepTaskArgs[2] = NewTask;
4691 DepTaskArgs[3] = NumOfElements;
4693 DepTaskArgs[5] = CGF.
Builder.getInt32(0);
4694 DepTaskArgs[6] = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
4696 auto &&ThenCodeGen = [
this, &
Data, TDBase, KmpTaskTQTyRD, &TaskArgs,
4699 auto PartIdFI = std::next(KmpTaskTQTyRD->
field_begin(), KmpTaskTPartId);
4703 if (!
Data.Dependences.empty()) {
4706 CGM.getModule(), OMPRTL___kmpc_omp_task_with_deps),
4710 CGM.getModule(), OMPRTL___kmpc_omp_task),
4716 Region->emitUntiedSwitch(CGF);
4719 llvm::Value *DepWaitTaskArgs[7];
4720 if (!
Data.Dependences.empty()) {
4721 DepWaitTaskArgs[0] = UpLoc;
4722 DepWaitTaskArgs[1] = ThreadID;
4723 DepWaitTaskArgs[2] = NumOfElements;
4725 DepWaitTaskArgs[4] = CGF.
Builder.getInt32(0);
4726 DepWaitTaskArgs[5] = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
4727 DepWaitTaskArgs[6] =
4728 llvm::ConstantInt::get(CGF.
Int32Ty,
Data.HasNowaitClause);
4730 auto &M =
CGM.getModule();
4731 auto &&ElseCodeGen = [
this, &M, &TaskArgs, ThreadID, NewTaskNewTaskTTy,
4732 TaskEntry, &
Data, &DepWaitTaskArgs,
4739 if (!
Data.Dependences.empty())
4741 M, OMPRTL___kmpc_omp_taskwait_deps_51),
4744 auto &&
CodeGen = [TaskEntry, ThreadID, NewTaskNewTaskTTy,
4747 llvm::Value *OutlinedFnArgs[] = {ThreadID, NewTaskNewTaskTTy};
4748 CGF.CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, Loc, TaskEntry,
4757 CommonActionTy Action(
OMPBuilder.getOrCreateRuntimeFunction(
4758 M, OMPRTL___kmpc_omp_task_begin_if0),
4761 M, OMPRTL___kmpc_omp_task_complete_if0),
4777 llvm::Function *TaskFunction,
4797 IfVal = llvm::ConstantInt::getSigned(CGF.
IntTy, 1);
4802 *std::next(
Result.KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound));
4809 *std::next(
Result.KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound));
4816 *std::next(
Result.KmpTaskTQTyRD->field_begin(), KmpTaskTStride));
4824 *std::next(
Result.KmpTaskTQTyRD->field_begin(), KmpTaskTReductions));
4825 if (
Data.Reductions) {
4831 enum { NoSchedule = 0, Grainsize = 1, NumTasks = 2 };
4840 llvm::ConstantInt::getSigned(
4842 llvm::ConstantInt::getSigned(
4844 ?
Data.Schedule.getInt() ? NumTasks : Grainsize
4846 Data.Schedule.getPointer()
4849 : llvm::ConstantInt::get(CGF.
Int64Ty, 0)};
4850 if (
Data.HasModifier)
4851 TaskArgs.push_back(llvm::ConstantInt::get(CGF.
Int32Ty, 1));
4853 TaskArgs.push_back(
Result.TaskDupFn
4856 : llvm::ConstantPointerNull::get(CGF.
VoidPtrTy));
4858 CGM.getModule(),
Data.HasModifier
4859 ? OMPRTL___kmpc_taskloop_5
4860 : OMPRTL___kmpc_taskloop),
4877 const Expr *,
const Expr *)> &RedOpGen,
4878 const Expr *XExpr =
nullptr,
const Expr *EExpr =
nullptr,
4879 const Expr *UpExpr =
nullptr) {
4887 llvm::Value *NumElements = CGF.
emitArrayLength(ArrayTy, ElementTy, LHSAddr);
4892 llvm::Value *LHSEnd =
4897 llvm::Value *IsEmpty =
4898 CGF.
Builder.CreateICmpEQ(LHSBegin, LHSEnd,
"omp.arraycpy.isempty");
4899 CGF.
Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
4902 llvm::BasicBlock *EntryBB = CGF.
Builder.GetInsertBlock();
4907 llvm::PHINode *RHSElementPHI = CGF.
Builder.CreatePHI(
4908 RHSBegin->getType(), 2,
"omp.arraycpy.srcElementPast");
4909 RHSElementPHI->addIncoming(RHSBegin, EntryBB);
4914 llvm::PHINode *LHSElementPHI = CGF.
Builder.CreatePHI(
4915 LHSBegin->getType(), 2,
"omp.arraycpy.destElementPast");
4916 LHSElementPHI->addIncoming(LHSBegin, EntryBB);
4923 Scope.addPrivate(LHSVar, LHSElementCurrent);
4924 Scope.addPrivate(RHSVar, RHSElementCurrent);
4926 RedOpGen(CGF, XExpr, EExpr, UpExpr);
4927 Scope.ForceCleanup();
4930 llvm::Value *LHSElementNext = CGF.
Builder.CreateConstGEP1_32(
4932 "omp.arraycpy.dest.element");
4933 llvm::Value *RHSElementNext = CGF.
Builder.CreateConstGEP1_32(
4935 "omp.arraycpy.src.element");
4938 CGF.
Builder.CreateICmpEQ(LHSElementNext, LHSEnd,
"omp.arraycpy.done");
4939 CGF.
Builder.CreateCondBr(Done, DoneBB, BodyBB);
4940 LHSElementPHI->addIncoming(LHSElementNext, CGF.
Builder.GetInsertBlock());
4941 RHSElementPHI->addIncoming(RHSElementNext, CGF.
Builder.GetInsertBlock());
4951 const Expr *ReductionOp) {
4952 if (
const auto *CE = dyn_cast<CallExpr>(ReductionOp))
4953 if (
const auto *OVE = dyn_cast<OpaqueValueExpr>(CE->getCallee()))
4954 if (
const auto *DRE =
4955 dyn_cast<DeclRefExpr>(OVE->getSourceExpr()->IgnoreImpCasts()))
4956 if (
const auto *DRD =
4957 dyn_cast<OMPDeclareReductionDecl>(DRE->getDecl())) {
4958 std::pair<llvm::Function *, llvm::Function *>
Reduction =
4969 StringRef ReducerName,
SourceLocation Loc, llvm::Type *ArgsElemType,
4980 Args.push_back(&LHSArg);
4981 Args.push_back(&RHSArg);
4983 CGM.getTypes().arrangeBuiltinFunctionDeclaration(
C.VoidTy, Args);
4985 auto *Fn = llvm::Function::Create(
CGM.getTypes().GetFunctionType(CGFI),
4986 llvm::GlobalValue::InternalLinkage, Name,
4989 if (!
CGM.getCodeGenOpts().SampleProfileFile.empty())
4990 Fn->addFnAttr(
"sample-profile-suffix-elision-policy",
"selected");
4991 Fn->setDoesNotRecurse();
5010 const auto *IPriv =
Privates.begin();
5012 for (
unsigned I = 0, E = ReductionOps.size(); I < E; ++I, ++IPriv, ++Idx) {
5013 const auto *RHSVar =
5016 const auto *LHSVar =
5019 QualType PrivTy = (*IPriv)->getType();
5035 const auto *ILHS = LHSExprs.begin();
5036 const auto *IRHS = RHSExprs.begin();
5037 for (
const Expr *E : ReductionOps) {
5038 if ((*IPriv)->getType()->isArrayType()) {
5043 CGF, (*IPriv)->getType(), LHSVar, RHSVar,
5045 emitReductionCombiner(CGF, E);
5055 Scope.ForceCleanup();
5061 const Expr *ReductionOp,
5062 const Expr *PrivateRef,
5070 CGF, PrivateRef->
getType(), LHSVar, RHSVar,
5072 emitReductionCombiner(CGF, ReductionOp);
5081 llvm::StringRef Prefix,
const Expr *Ref);
5085 const Expr *LHSExprs,
const Expr *RHSExprs,
const Expr *ReductionOps) {
5112 std::string ReductionVarNameStr;
5113 if (
const auto *DRE = dyn_cast<DeclRefExpr>(
Privates->IgnoreParenCasts()))
5114 ReductionVarNameStr =
5117 ReductionVarNameStr =
"unnamed_priv_var";
5120 std::string SharedName =
5121 CGM.getOpenMPRuntime().getName({
"internal_pivate_", ReductionVarNameStr});
5122 llvm::GlobalVariable *SharedVar =
OMPBuilder.getOrCreateInternalVariable(
5123 LLVMType,
".omp.reduction." + SharedName);
5125 SharedVar->setAlignment(
5133 llvm::Value *BarrierArgs[] = {BarrierLoc, ThreadId};
5138 llvm::Value *IsWorker = CGF.
Builder.CreateICmpEQ(
5139 ThreadId, llvm::ConstantInt::get(ThreadId->getType(), 0));
5140 CGF.
Builder.CreateCondBr(IsWorker, InitBB, InitEndBB);
5144 auto EmitSharedInit = [&]() {
5147 std::pair<llvm::Function *, llvm::Function *> FnPair =
5149 llvm::Function *InitializerFn = FnPair.second;
5150 if (InitializerFn) {
5151 if (
const auto *CE =
5152 dyn_cast<CallExpr>(UDRInitExpr->IgnoreParenImpCasts())) {
5159 LocalScope.addPrivate(OutVD, SharedResult);
5161 (void)LocalScope.Privatize();
5162 if (
const auto *OVE = dyn_cast<OpaqueValueExpr>(
5163 CE->getCallee()->IgnoreParenImpCasts())) {
5189 if (
const auto *DRE = dyn_cast<DeclRefExpr>(
Privates)) {
5190 if (
const auto *VD = dyn_cast<VarDecl>(DRE->getDecl())) {
5201 CGF.
Builder.CreateBr(InitEndBB);
5205 CGM.getModule(), OMPRTL___kmpc_barrier),
5208 const Expr *ReductionOp = ReductionOps;
5213 auto EmitCriticalReduction = [&](
auto ReductionGen) {
5214 std::string CriticalName =
getName({
"reduction_critical"});
5222 std::pair<llvm::Function *, llvm::Function *> FnPair =
5225 if (
const auto *CE = dyn_cast<CallExpr>(ReductionOp)) {
5237 (void)LocalScope.Privatize();
5242 EmitCriticalReduction(ReductionGen);
5247 if (
const auto *Cleanup = dyn_cast<ExprWithCleanups>(ReductionClauseExpr))
5250 const Expr *AssignRHS =
nullptr;
5251 if (
const auto *BinOp = dyn_cast<BinaryOperator>(ReductionClauseExpr)) {
5252 if (BinOp->getOpcode() == BO_Assign)
5253 AssignRHS = BinOp->getRHS();
5254 }
else if (
const auto *OpCall =
5255 dyn_cast<CXXOperatorCallExpr>(ReductionClauseExpr)) {
5256 if (OpCall->getOperator() == OO_Equal)
5257 AssignRHS = OpCall->getArg(1);
5261 "Private Variable Reduction : Invalid ReductionOp expression");
5266 const auto *OmpOutDRE =
5268 const auto *OmpInDRE =
5271 OmpOutDRE && OmpInDRE &&
5272 "Private Variable Reduction : LHSExpr/RHSExpr must be DeclRefExprs");
5276 LocalScope.addPrivate(OmpOutVD, SharedLV.
getAddress());
5277 LocalScope.addPrivate(OmpInVD, LHSLV.
getAddress());
5278 (void)LocalScope.Privatize();
5282 EmitCriticalReduction(ReductionGen);
5286 CGM.getModule(), OMPRTL___kmpc_barrier),
5292 llvm::Value *FinalResultVal =
nullptr;
5296 FinalResultAddr = SharedResult;
5310 CGM.getModule(), OMPRTL___kmpc_barrier),
5321 EmitCriticalReduction(OriginalListCombiner);
5373 if (SimpleReduction) {
5375 const auto *IPriv = OrgPrivates.begin();
5376 const auto *ILHS = OrgLHSExprs.begin();
5377 const auto *IRHS = OrgRHSExprs.begin();
5378 for (
const Expr *E : OrgReductionOps) {
5391 FilteredRHSExprs, FilteredReductionOps;
5392 for (
unsigned I : llvm::seq<unsigned>(
5393 std::min(OrgReductionOps.size(), OrgLHSExprs.size()))) {
5395 FilteredPrivates.emplace_back(OrgPrivates[I]);
5396 FilteredLHSExprs.emplace_back(OrgLHSExprs[I]);
5397 FilteredRHSExprs.emplace_back(OrgRHSExprs[I]);
5398 FilteredReductionOps.emplace_back(OrgReductionOps[I]);
5410 auto Size = RHSExprs.size();
5416 llvm::APInt ArraySize(32, Size);
5417 QualType ReductionArrayTy =
C.getConstantArrayType(
5421 CGF.
CreateMemTemp(ReductionArrayTy,
".omp.reduction.red_list");
5422 const auto *IPriv =
Privates.begin();
5424 for (
unsigned I = 0, E = RHSExprs.size(); I < E; ++I, ++IPriv, ++Idx) {
5430 if ((*IPriv)->getType()->isVariablyModifiedType()) {
5434 llvm::Value *Size = CGF.
Builder.CreateIntCast(
5447 Privates, LHSExprs, RHSExprs, ReductionOps);
5450 std::string Name =
getName({
"reduction"});
5457 llvm::Value *ReductionArrayTySize = CGF.
getTypeSize(ReductionArrayTy);
5460 llvm::Value *Args[] = {
5463 CGF.
Builder.getInt32(RHSExprs.size()),
5464 ReductionArrayTySize,
5472 WithNowait ? OMPRTL___kmpc_reduce_nowait : OMPRTL___kmpc_reduce),
5476 llvm::BasicBlock *DefaultBB = CGF.
createBasicBlock(
".omp.reduction.default");
5477 llvm::SwitchInst *SwInst =
5478 CGF.
Builder.CreateSwitch(Res, DefaultBB, 2);
5487 SwInst->addCase(CGF.
Builder.getInt32(1), Case1BB);
5491 llvm::Value *EndArgs[] = {
5499 const auto *IPriv =
Privates.begin();
5500 const auto *ILHS = LHSExprs.begin();
5501 const auto *IRHS = RHSExprs.begin();
5502 for (
const Expr *E : ReductionOps) {
5511 CommonActionTy Action(
5514 CGM.getModule(), WithNowait ? OMPRTL___kmpc_end_reduce_nowait
5515 : OMPRTL___kmpc_end_reduce),
5528 SwInst->addCase(CGF.
Builder.getInt32(2), Case2BB);
5531 auto &&AtomicCodeGen = [Loc,
Privates, LHSExprs, RHSExprs, ReductionOps](
5533 const auto *ILHS = LHSExprs.begin();
5534 const auto *IRHS = RHSExprs.begin();
5535 const auto *IPriv =
Privates.begin();
5536 for (
const Expr *E : ReductionOps) {
5537 const Expr *XExpr =
nullptr;
5538 const Expr *EExpr =
nullptr;
5539 const Expr *UpExpr =
nullptr;
5541 if (
const auto *BO = dyn_cast<BinaryOperator>(E)) {
5542 if (BO->getOpcode() == BO_Assign) {
5543 XExpr = BO->getLHS();
5544 UpExpr = BO->getRHS();
5548 const Expr *RHSExpr = UpExpr;
5551 if (
const auto *ACO = dyn_cast<AbstractConditionalOperator>(
5555 RHSExpr = ACO->getCond();
5557 if (
const auto *BORHS =
5559 EExpr = BORHS->getRHS();
5560 BO = BORHS->getOpcode();
5565 auto &&AtomicRedGen = [BO, VD,
5567 const Expr *EExpr,
const Expr *UpExpr) {
5568 LValue X = CGF.EmitLValue(XExpr);
5571 E = CGF.EmitAnyExpr(EExpr);
5572 CGF.EmitOMPAtomicSimpleUpdateExpr(
5574 llvm::AtomicOrdering::Monotonic, Loc,
5575 [&CGF, UpExpr, VD, Loc](
RValue XRValue) {
5577 Address LHSTemp = CGF.CreateMemTemp(VD->getType());
5578 CGF.emitOMPSimpleStore(
5579 CGF.MakeAddrLValue(LHSTemp, VD->
getType()), XRValue,
5580 VD->getType().getNonReferenceType(), Loc);
5583 return CGF.EmitAnyExpr(UpExpr);
5586 if ((*IPriv)->getType()->isArrayType()) {
5588 const auto *RHSVar =
5591 AtomicRedGen, XExpr, EExpr, UpExpr);
5594 AtomicRedGen(CGF, XExpr, EExpr, UpExpr);
5601 std::string Name = RT.
getName({
"atomic_reduction"});
5610 if ((*IPriv)->getType()->isArrayType()) {
5611 const auto *LHSVar =
5613 const auto *RHSVar =
5618 CritRedGen(CGF,
nullptr,
nullptr,
nullptr);
5629 llvm::Value *EndArgs[] = {
5634 CommonActionTy Action(
nullptr, {},
5636 CGM.getModule(), OMPRTL___kmpc_end_reduce),
5646 assert(OrgLHSExprs.size() == OrgPrivates.size() &&
5647 "PrivateVarReduction: Privates size mismatch");
5648 assert(OrgLHSExprs.size() == OrgReductionOps.size() &&
5649 "PrivateVarReduction: ReductionOps size mismatch");
5650 for (
unsigned I : llvm::seq<unsigned>(
5651 std::min(OrgReductionOps.size(), OrgLHSExprs.size()))) {
5654 OrgRHSExprs[I], OrgReductionOps[I]);
5663 llvm::raw_svector_ostream Out(Buffer);
5671 Out << Prefix << Name <<
"_"
5673 return std::string(Out.str());
5695 Args.emplace_back(&Param);
5696 Args.emplace_back(&ParamOrig);
5697 const auto &FnInfo =
5701 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
5705 Fn->addFnAttr(
"sample-profile-suffix-elision-policy",
"selected");
5706 Fn->setDoesNotRecurse();
5713 llvm::Value *Size =
nullptr;
5756 const Expr *ReductionOp,
5758 const Expr *PrivateRef) {
5767 Args.emplace_back(&ParamInOut);
5768 Args.emplace_back(&ParamIn);
5769 const auto &FnInfo =
5773 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
5777 Fn->addFnAttr(
"sample-profile-suffix-elision-policy",
"selected");
5778 Fn->setDoesNotRecurse();
5781 llvm::Value *Size =
nullptr;
5802 C.getPointerType(LHSVD->getType())->castAs<
PointerType>()));
5809 C.getPointerType(RHSVD->getType())->castAs<
PointerType>()));
5838 Args.emplace_back(&Param);
5839 const auto &FnInfo =
5843 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
5847 Fn->addFnAttr(
"sample-profile-suffix-elision-policy",
"selected");
5848 Fn->setDoesNotRecurse();
5853 llvm::Value *Size =
nullptr;
5888 RecordDecl *RD =
C.buildImplicitRecord(
"kmp_taskred_input_t");
5897 C, RD,
C.getIntTypeForBitwidth(32,
false));
5900 unsigned Size =
Data.ReductionVars.size();
5901 llvm::APInt ArraySize(64, Size);
5903 C.getConstantArrayType(RDType, ArraySize,
nullptr,
5908 Data.ReductionCopies,
Data.ReductionOps);
5909 for (
unsigned Cnt = 0; Cnt < Size; ++Cnt) {
5911 llvm::Value *Idxs[] = {llvm::ConstantInt::get(
CGM.SizeTy, 0),
5912 llvm::ConstantInt::get(
CGM.SizeTy, Cnt)};
5928 llvm::Value *SizeValInChars;
5929 llvm::Value *SizeVal;
5930 std::tie(SizeValInChars, SizeVal) = RCG.
getSizes(Cnt);
5936 bool DelayedCreation = !!SizeVal;
5937 SizeValInChars = CGF.
Builder.CreateIntCast(SizeValInChars,
CGM.SizeTy,
5948 llvm::Value *FiniAddr =
5949 Fini ? Fini : llvm::ConstantPointerNull::get(
CGM.VoidPtrTy);
5954 CGM, Loc, RCG, Cnt,
Data.ReductionOps[Cnt], LHSExprs[Cnt],
5955 RHSExprs[Cnt],
Data.ReductionCopies[Cnt]);
5959 if (DelayedCreation) {
5961 llvm::ConstantInt::get(
CGM.Int32Ty, 1,
true),
5966 if (
Data.IsReductionWithTaskMod) {
5972 llvm::Value *Args[] = {
5974 llvm::ConstantInt::get(
CGM.IntTy,
Data.IsWorksharingReduction ? 1 : 0,
5976 llvm::ConstantInt::get(
CGM.IntTy, Size,
true),
5981 CGM.getModule(), OMPRTL___kmpc_taskred_modifier_init),
5985 llvm::Value *Args[] = {
5988 llvm::ConstantInt::get(
CGM.IntTy, Size,
true),
5992 CGM.getModule(), OMPRTL___kmpc_taskred_init),
5998 bool IsWorksharingReduction) {
6004 llvm::Value *Args[] = {IdentTLoc, GTid,
6005 llvm::ConstantInt::get(
CGM.IntTy,
6006 IsWorksharingReduction ? 1 : 0,
6010 CGM.getModule(), OMPRTL___kmpc_task_reduction_modifier_fini),
6022 llvm::Value *SizeVal = CGF.
Builder.CreateIntCast(Sizes.second,
CGM.SizeTy,
6025 CGF,
CGM.getContext().getSizeType(),
6033 llvm::Value *ReductionsPtr,
6046 CGM.getModule(), OMPRTL___kmpc_task_reduction_get_th_data),
6062 auto &M =
CGM.getModule();
6064 llvm::Value *NumOfElements;
6065 std::tie(NumOfElements, DependenciesArray) =
6067 if (!
Data.Dependences.empty()) {
6068 llvm::Value *DepWaitTaskArgs[7];
6069 DepWaitTaskArgs[0] = UpLoc;
6070 DepWaitTaskArgs[1] = ThreadID;
6071 DepWaitTaskArgs[2] = NumOfElements;
6073 DepWaitTaskArgs[4] = CGF.
Builder.getInt32(0);
6074 DepWaitTaskArgs[5] = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
6075 DepWaitTaskArgs[6] =
6076 llvm::ConstantInt::get(CGF.
Int32Ty,
Data.HasNowaitClause);
6085 M, OMPRTL___kmpc_omp_taskwait_deps_51),
6092 llvm::Value *Args[] = {UpLoc, ThreadID};
6095 OMPBuilder.getOrCreateRuntimeFunction(M, OMPRTL___kmpc_omp_taskwait),
6100 if (
auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.
CapturedStmtInfo))
6101 Region->emitUntiedSwitch(CGF);
6110 InlinedOpenMPRegionRAII Region(CGF,
CodeGen, InnerKind, HasCancel,
6111 InnerKind != OMPD_critical &&
6112 InnerKind != OMPD_master &&
6113 InnerKind != OMPD_masked);
6128 RTCancelKind CancelKind = CancelNoreq;
6129 if (CancelRegion == OMPD_parallel)
6130 CancelKind = CancelParallel;
6131 else if (CancelRegion == OMPD_for)
6132 CancelKind = CancelLoop;
6133 else if (CancelRegion == OMPD_sections)
6134 CancelKind = CancelSections;
6136 assert(CancelRegion == OMPD_taskgroup);
6137 CancelKind = CancelTaskgroup;
6149 if (
auto *OMPRegionInfo =
6153 if (CancelRegion == OMPD_taskgroup || OMPRegionInfo->hasCancel()) {
6154 llvm::Value *Args[] = {
6160 CGM.getModule(), OMPRTL___kmpc_cancellationpoint),
6169 CGF.
Builder.CreateCondBr(
Cmp, ExitBB, ContBB);
6171 if (CancelRegion == OMPD_parallel)
6189 auto &M =
CGM.getModule();
6190 if (
auto *OMPRegionInfo =
6192 auto &&ThenGen = [
this, &M, Loc, CancelRegion,
6195 llvm::Value *Args[] = {
6199 llvm::Value *
Result = CGF.EmitRuntimeCall(
6200 OMPBuilder.getOrCreateRuntimeFunction(M, OMPRTL___kmpc_cancel), Args);
6205 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(
".cancel.exit");
6206 llvm::BasicBlock *ContBB = CGF.createBasicBlock(
".cancel.continue");
6207 llvm::Value *
Cmp = CGF.Builder.CreateIsNotNull(
Result);
6208 CGF.Builder.CreateCondBr(
Cmp, ExitBB, ContBB);
6209 CGF.EmitBlock(ExitBB);
6210 if (CancelRegion == OMPD_parallel)
6214 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind());
6215 CGF.EmitBranchThroughCleanup(CancelDest);
6216 CGF.EmitBlock(ContBB,
true);
6234 OMPUsesAllocatorsActionTy(
6235 ArrayRef<std::pair<const Expr *, const Expr *>> Allocators)
6236 : Allocators(Allocators) {}
6240 for (
const auto &AllocatorData : Allocators) {
6242 CGF, AllocatorData.first, AllocatorData.second);
6245 void Exit(CodeGenFunction &CGF)
override {
6248 for (
const auto &AllocatorData : Allocators) {
6250 AllocatorData.first);
6258 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
6260 assert(!ParentName.empty() &&
"Invalid target entry parent name!");
6264 for (
unsigned I = 0, E =
C->getNumberOfAllocators(); I < E; ++I) {
6271 OMPUsesAllocatorsActionTy UsesAllocatorAction(Allocators);
6272 CodeGen.setAction(UsesAllocatorAction);
6278 const Expr *Allocator,
6279 const Expr *AllocatorTraits) {
6281 ThreadId = CGF.
Builder.CreateIntCast(ThreadId, CGF.
IntTy,
true);
6283 llvm::Value *MemSpaceHandle = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
6284 llvm::Value *NumTraits = llvm::ConstantInt::get(
6288 .getLimitedValue());
6295 llvm::Value *Traits =
Addr.emitRawPointer(CGF);
6297 llvm::Value *AllocatorVal =
6299 CGM.getModule(), OMPRTL___kmpc_init_allocator),
6300 {ThreadId, MemSpaceHandle, NumTraits, Traits});
6312 const Expr *Allocator) {
6314 ThreadId = CGF.
Builder.CreateIntCast(ThreadId, CGF.
IntTy,
true);
6316 llvm::Value *AllocatorVal =
6323 OMPRTL___kmpc_destroy_allocator),
6324 {ThreadId, AllocatorVal});
6329 llvm::OpenMPIRBuilder::TargetKernelDefaultAttrs &Attrs) {
6330 assert(Attrs.MaxTeams.size() == 1 && Attrs.MaxThreads.size() == 1 &&
6331 "invalid default attrs structure");
6332 int32_t &MaxTeamsVal = Attrs.MaxTeams.front();
6333 int32_t &MaxThreadsVal = Attrs.MaxThreads.front();
6340 for (
auto *A :
C->getAttrs()) {
6341 int32_t AttrMinThreadsVal = 1, AttrMaxThreadsVal = -1;
6342 int32_t AttrMinBlocksVal = 1, AttrMaxBlocksVal = -1;
6343 if (
auto *
Attr = dyn_cast<CUDALaunchBoundsAttr>(A))
6344 CGM.handleCUDALaunchBoundsAttr(
nullptr,
Attr, &AttrMaxThreadsVal,
6345 &AttrMinBlocksVal, &AttrMaxBlocksVal);
6346 else if (
auto *
Attr = dyn_cast<AMDGPUFlatWorkGroupSizeAttr>(A))
6347 CGM.handleAMDGPUFlatWorkGroupSizeAttr(
6348 nullptr,
Attr,
nullptr, &AttrMinThreadsVal,
6349 &AttrMaxThreadsVal);
6353 Attrs.MinThreads = std::max(Attrs.MinThreads, AttrMinThreadsVal);
6354 if (AttrMaxThreadsVal > 0)
6355 MaxThreadsVal = MaxThreadsVal > 0
6356 ? std::min(MaxThreadsVal, AttrMaxThreadsVal)
6357 : AttrMaxThreadsVal;
6358 Attrs.MinTeams = std::max(Attrs.MinTeams, AttrMinBlocksVal);
6359 if (AttrMaxBlocksVal > 0)
6360 MaxTeamsVal = MaxTeamsVal > 0 ? std::min(MaxTeamsVal, AttrMaxBlocksVal)
6368 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
6371 llvm::TargetRegionEntryInfo EntryInfo =
6375 llvm::OpenMPIRBuilder::FunctionGenCallback &&GenerateOutlinedFunction =
6376 [&CGF, &D, &
CodeGen](StringRef EntryFnName) {
6377 const CapturedStmt &CS = *D.getCapturedStmt(OMPD_target);
6379 CGOpenMPTargetRegionInfo CGInfo(CS,
CodeGen, EntryFnName);
6384 cantFail(
OMPBuilder.emitTargetRegionFunction(
6385 EntryInfo, GenerateOutlinedFunction, IsOffloadEntry, OutlinedFn,
6391 CGM.getTargetCodeGenInfo().setTargetAttributes(
nullptr, OutlinedFn,
CGM);
6394 for (
auto *A :
C->getAttrs()) {
6395 if (
auto *
Attr = dyn_cast<AMDGPUWavesPerEUAttr>(A))
6396 CGM.handleAMDGPUWavesPerEUAttr(OutlinedFn,
Attr);
6415 while (
const auto *
C = dyn_cast_or_null<CompoundStmt>(Child)) {
6417 for (
const Stmt *S :
C->body()) {
6418 if (
const auto *E = dyn_cast<Expr>(S)) {
6427 if (
const auto *DS = dyn_cast<DeclStmt>(S)) {
6428 if (llvm::all_of(DS->decls(), [](
const Decl *D) {
6429 if (isa<EmptyDecl>(D) || isa<DeclContext>(D) ||
6430 isa<TypeDecl>(D) || isa<PragmaCommentDecl>(D) ||
6431 isa<PragmaDetectMismatchDecl>(D) || isa<UsingDecl>(D) ||
6432 isa<UsingDirectiveDecl>(D) ||
6433 isa<OMPDeclareReductionDecl>(D) ||
6434 isa<OMPThreadPrivateDecl>(D) || isa<OMPAllocateDecl>(D))
6436 const auto *VD = dyn_cast<VarDecl>(D);
6439 return VD->hasGlobalStorage() || !VD->isUsed();
6449 Child = Child->IgnoreContainers();
6456 int32_t &MaxTeamsVal) {
6460 "Expected target-based executable directive.");
6461 switch (DirectiveKind) {
6463 const auto *CS = D.getInnermostCapturedStmt();
6466 const Stmt *ChildStmt =
6468 if (
const auto *NestedDir =
6469 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) {
6478 MinTeamsVal = MaxTeamsVal = Constant->getExtValue();
6481 MinTeamsVal = MaxTeamsVal = 0;
6484 MinTeamsVal = MaxTeamsVal = 1;
6488 MinTeamsVal = MaxTeamsVal = -1;
6491 case OMPD_target_teams_loop:
6492 case OMPD_target_teams:
6493 case OMPD_target_teams_distribute:
6494 case OMPD_target_teams_distribute_simd:
6495 case OMPD_target_teams_distribute_parallel_for:
6496 case OMPD_target_teams_distribute_parallel_for_simd: {
6498 const Expr *NumTeams =
6502 MinTeamsVal = MaxTeamsVal = Constant->getExtValue();
6505 MinTeamsVal = MaxTeamsVal = 0;
6508 case OMPD_target_parallel:
6509 case OMPD_target_parallel_for:
6510 case OMPD_target_parallel_for_simd:
6511 case OMPD_target_parallel_loop:
6512 case OMPD_target_simd:
6513 MinTeamsVal = MaxTeamsVal = 1;
6517 case OMPD_parallel_for:
6518 case OMPD_parallel_loop:
6519 case OMPD_parallel_master:
6520 case OMPD_parallel_sections:
6522 case OMPD_parallel_for_simd:
6524 case OMPD_cancellation_point:
6526 case OMPD_threadprivate:
6537 case OMPD_taskyield:
6540 case OMPD_taskgroup:
6546 case OMPD_target_data:
6547 case OMPD_target_exit_data:
6548 case OMPD_target_enter_data:
6549 case OMPD_distribute:
6550 case OMPD_distribute_simd:
6551 case OMPD_distribute_parallel_for:
6552 case OMPD_distribute_parallel_for_simd:
6553 case OMPD_teams_distribute:
6554 case OMPD_teams_distribute_simd:
6555 case OMPD_teams_distribute_parallel_for:
6556 case OMPD_teams_distribute_parallel_for_simd:
6557 case OMPD_target_update:
6558 case OMPD_declare_simd:
6559 case OMPD_declare_variant:
6560 case OMPD_begin_declare_variant:
6561 case OMPD_end_declare_variant:
6562 case OMPD_declare_target:
6563 case OMPD_end_declare_target:
6564 case OMPD_declare_reduction:
6565 case OMPD_declare_mapper:
6567 case OMPD_taskloop_simd:
6568 case OMPD_master_taskloop:
6569 case OMPD_master_taskloop_simd:
6570 case OMPD_parallel_master_taskloop:
6571 case OMPD_parallel_master_taskloop_simd:
6573 case OMPD_metadirective:
6579 llvm_unreachable(
"Unexpected directive kind.");
6585 "Clauses associated with the teams directive expected to be emitted "
6586 "only for the host!");
6588 int32_t MinNT = -1, MaxNT = -1;
6589 const Expr *NumTeams =
6591 if (NumTeams !=
nullptr) {
6594 switch (DirectiveKind) {
6596 const auto *CS = D.getInnermostCapturedStmt();
6597 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6601 return Bld.CreateIntCast(NumTeamsVal, CGF.
Int32Ty,
6604 case OMPD_target_teams:
6605 case OMPD_target_teams_distribute:
6606 case OMPD_target_teams_distribute_simd:
6607 case OMPD_target_teams_distribute_parallel_for:
6608 case OMPD_target_teams_distribute_parallel_for_simd: {
6612 return Bld.CreateIntCast(NumTeamsVal, CGF.
Int32Ty,
6620 assert(MinNT == MaxNT &&
"Num threads ranges require handling here.");
6621 return llvm::ConstantInt::getSigned(CGF.
Int32Ty, MinNT);
6629 const Expr **E, int32_t &UpperBound,
6630 bool UpperBoundOnly, llvm::Value **CondVal) {
6633 const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child);
6640 if (CondVal && Dir->hasClausesOfKind<
OMPIfClause>()) {
6641 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6644 for (
const auto *
C : Dir->getClausesOfKind<
OMPIfClause>()) {
6645 if (
C->getNameModifier() == OMPD_unknown ||
6646 C->getNameModifier() == OMPD_parallel) {
6661 if (
const auto *PreInit =
6663 for (
const auto *I : PreInit->decls()) {
6664 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
6680 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6682 const auto *NumThreadsClause =
6684 const Expr *NTExpr = NumThreadsClause->getNumThreads();
6685 if (NTExpr->isIntegerConstantExpr(CGF.
getContext()))
6686 if (
auto Constant = NTExpr->getIntegerConstantExpr(CGF.
getContext()))
6689 ? Constant->getZExtValue()
6690 : std::min(UpperBound,
6691 static_cast<int32_t
>(Constant->getZExtValue()));
6694 if (UpperBound == -1)
6699 if (
const auto *PreInit =
6700 cast_or_null<DeclStmt>(NumThreadsClause->getPreInitStmt())) {
6701 for (
const auto *I : PreInit->decls()) {
6702 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
6721 bool UpperBoundOnly, llvm::Value **CondVal,
const Expr **ThreadLimitExpr) {
6722 assert((!CGF.
getLangOpts().OpenMPIsTargetDevice || UpperBoundOnly) &&
6723 "Clauses associated with the teams directive expected to be emitted "
6724 "only for the host!");
6727 "Expected target-based executable directive.");
6729 const Expr *NT =
nullptr;
6730 const Expr **NTPtr = UpperBoundOnly ?
nullptr : &NT;
6732 auto CheckForConstExpr = [&](
const Expr *E,
const Expr **EPtr) {
6735 UpperBound = UpperBound ? Constant->getZExtValue()
6736 : std::min(UpperBound,
6737 int32_t(Constant->getZExtValue()));
6741 if (UpperBound == -1)
6747 auto ReturnSequential = [&]() {
6752 switch (DirectiveKind) {
6755 getNumThreads(CGF, CS, NTPtr, UpperBound, UpperBoundOnly, CondVal);
6761 if (
const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) {
6763 ThreadLimitClause = TLC;
6764 if (ThreadLimitExpr) {
6765 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6769 ThreadLimitClause->getThreadLimit().front()->getSourceRange());
6770 if (
const auto *PreInit =
6771 cast_or_null<DeclStmt>(ThreadLimitClause->getPreInitStmt())) {
6772 for (
const auto *I : PreInit->decls()) {
6773 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
6785 if (ThreadLimitClause)
6786 CheckForConstExpr(ThreadLimitClause->getThreadLimit().front(),
6788 if (
const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) {
6791 CS = Dir->getInnermostCapturedStmt();
6794 Dir = dyn_cast_or_null<OMPExecutableDirective>(Child);
6797 CS = Dir->getInnermostCapturedStmt();
6798 getNumThreads(CGF, CS, NTPtr, UpperBound, UpperBoundOnly, CondVal);
6800 return ReturnSequential();
6804 case OMPD_target_teams: {
6808 CheckForConstExpr(ThreadLimitClause->getThreadLimit().front(),
6812 getNumThreads(CGF, CS, NTPtr, UpperBound, UpperBoundOnly, CondVal);
6815 if (
const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) {
6816 if (Dir->getDirectiveKind() == OMPD_distribute) {
6817 CS = Dir->getInnermostCapturedStmt();
6818 getNumThreads(CGF, CS, NTPtr, UpperBound, UpperBoundOnly, CondVal);
6823 case OMPD_target_teams_distribute:
6827 CheckForConstExpr(ThreadLimitClause->getThreadLimit().front(),
6830 getNumThreads(CGF, D.getInnermostCapturedStmt(), NTPtr, UpperBound,
6831 UpperBoundOnly, CondVal);
6833 case OMPD_target_teams_loop:
6834 case OMPD_target_parallel_loop:
6835 case OMPD_target_parallel:
6836 case OMPD_target_parallel_for:
6837 case OMPD_target_parallel_for_simd:
6838 case OMPD_target_teams_distribute_parallel_for:
6839 case OMPD_target_teams_distribute_parallel_for_simd: {
6840 if (CondVal && D.hasClausesOfKind<
OMPIfClause>()) {
6842 for (
const auto *
C : D.getClausesOfKind<
OMPIfClause>()) {
6843 if (
C->getNameModifier() == OMPD_unknown ||
6844 C->getNameModifier() == OMPD_parallel) {
6854 return ReturnSequential();
6864 CheckForConstExpr(ThreadLimitClause->getThreadLimit().front(),
6870 CheckForConstExpr(NumThreadsClause->getNumThreads(),
nullptr);
6871 return NumThreadsClause->getNumThreads();
6875 case OMPD_target_teams_distribute_simd:
6876 case OMPD_target_simd:
6877 return ReturnSequential();
6881 llvm_unreachable(
"Unsupported directive kind.");
6886 llvm::Value *NumThreadsVal =
nullptr;
6887 llvm::Value *CondVal =
nullptr;
6888 llvm::Value *ThreadLimitVal =
nullptr;
6889 const Expr *ThreadLimitExpr =
nullptr;
6890 int32_t UpperBound = -1;
6893 CGF, D, UpperBound,
false, &CondVal,
6897 if (ThreadLimitExpr) {
6900 ThreadLimitVal = CGF.
Builder.CreateIntCast(ThreadLimitVal, CGF.
Int32Ty,
6905 if (UpperBound == 1) {
6906 NumThreadsVal = CGF.
Builder.getInt32(UpperBound);
6909 NumThreadsVal = CGF.
Builder.CreateIntCast(NumThreadsVal, CGF.
Int32Ty,
6911 }
else if (ThreadLimitVal) {
6914 NumThreadsVal = ThreadLimitVal;
6915 ThreadLimitVal =
nullptr;
6918 assert(!ThreadLimitVal &&
"Default not applicable with thread limit value");
6919 NumThreadsVal = CGF.
Builder.getInt32(0);
6926 NumThreadsVal = CGF.
Builder.CreateSelect(CondVal, NumThreadsVal,
6932 if (ThreadLimitVal) {
6933 NumThreadsVal = CGF.
Builder.CreateSelect(
6934 CGF.
Builder.CreateICmpULT(ThreadLimitVal, NumThreadsVal),
6935 ThreadLimitVal, NumThreadsVal);
6938 return NumThreadsVal;
6948class MappableExprsHandler {
6954 struct AttachPtrExprComparator {
6955 const MappableExprsHandler &Handler;
6957 mutable llvm::DenseMap<std::pair<const Expr *, const Expr *>,
bool>
6958 CachedEqualityComparisons;
6960 AttachPtrExprComparator(
const MappableExprsHandler &H) : Handler(H) {}
6961 AttachPtrExprComparator() =
delete;
6964 bool operator()(
const Expr *LHS,
const Expr *RHS)
const {
6969 const auto ItLHS = Handler.AttachPtrComponentDepthMap.find(LHS);
6970 const auto ItRHS = Handler.AttachPtrComponentDepthMap.find(RHS);
6972 std::optional<size_t> DepthLHS =
6973 (ItLHS != Handler.AttachPtrComponentDepthMap.end()) ? ItLHS->second
6975 std::optional<size_t> DepthRHS =
6976 (ItRHS != Handler.AttachPtrComponentDepthMap.end()) ? ItRHS->second
6980 if (!DepthLHS.has_value() && !DepthRHS.has_value()) {
6982 if (areEqual(LHS, RHS))
6985 return wasComputedBefore(LHS, RHS);
6987 if (!DepthLHS.has_value())
6989 if (!DepthRHS.has_value())
6993 if (DepthLHS.value() != DepthRHS.value())
6994 return DepthLHS.value() < DepthRHS.value();
6997 if (areEqual(LHS, RHS))
7000 return wasComputedBefore(LHS, RHS);
7006 bool areEqual(
const Expr *LHS,
const Expr *RHS)
const {
7008 const auto CachedResultIt = CachedEqualityComparisons.find({LHS, RHS});
7009 if (CachedResultIt != CachedEqualityComparisons.end())
7010 return CachedResultIt->second;
7024 bool wasComputedBefore(
const Expr *LHS,
const Expr *RHS)
const {
7025 const size_t &OrderLHS = Handler.AttachPtrComputationOrderMap.at(LHS);
7026 const size_t &OrderRHS = Handler.AttachPtrComputationOrderMap.at(RHS);
7028 return OrderLHS < OrderRHS;
7037 bool areSemanticallyEqual(
const Expr *LHS,
const Expr *RHS)
const {
7059 if (
const auto *LD = dyn_cast<DeclRefExpr>(LHS)) {
7060 const auto *RD = dyn_cast<DeclRefExpr>(RHS);
7063 return LD->getDecl()->getCanonicalDecl() ==
7064 RD->getDecl()->getCanonicalDecl();
7068 if (
const auto *LA = dyn_cast<ArraySubscriptExpr>(LHS)) {
7069 const auto *RA = dyn_cast<ArraySubscriptExpr>(RHS);
7072 return areSemanticallyEqual(LA->getBase(), RA->getBase()) &&
7073 areSemanticallyEqual(LA->getIdx(), RA->getIdx());
7077 if (
const auto *LM = dyn_cast<MemberExpr>(LHS)) {
7078 const auto *RM = dyn_cast<MemberExpr>(RHS);
7081 if (LM->getMemberDecl()->getCanonicalDecl() !=
7082 RM->getMemberDecl()->getCanonicalDecl())
7084 return areSemanticallyEqual(LM->getBase(), RM->getBase());
7088 if (
const auto *LU = dyn_cast<UnaryOperator>(LHS)) {
7089 const auto *RU = dyn_cast<UnaryOperator>(RHS);
7092 if (LU->getOpcode() != RU->getOpcode())
7094 return areSemanticallyEqual(LU->getSubExpr(), RU->getSubExpr());
7098 if (
const auto *LB = dyn_cast<BinaryOperator>(LHS)) {
7099 const auto *RB = dyn_cast<BinaryOperator>(RHS);
7102 if (LB->getOpcode() != RB->getOpcode())
7104 return areSemanticallyEqual(LB->getLHS(), RB->getLHS()) &&
7105 areSemanticallyEqual(LB->getRHS(), RB->getRHS());
7111 if (
const auto *LAS = dyn_cast<ArraySectionExpr>(LHS)) {
7112 const auto *RAS = dyn_cast<ArraySectionExpr>(RHS);
7115 return areSemanticallyEqual(LAS->getBase(), RAS->getBase()) &&
7116 areSemanticallyEqual(LAS->getLowerBound(),
7117 RAS->getLowerBound()) &&
7118 areSemanticallyEqual(LAS->getLength(), RAS->getLength());
7122 if (
const auto *LC = dyn_cast<CastExpr>(LHS)) {
7123 const auto *RC = dyn_cast<CastExpr>(RHS);
7126 if (LC->getCastKind() != RC->getCastKind())
7128 return areSemanticallyEqual(LC->getSubExpr(), RC->getSubExpr());
7136 if (
const auto *LI = dyn_cast<IntegerLiteral>(LHS)) {
7137 const auto *RI = dyn_cast<IntegerLiteral>(RHS);
7140 return LI->getValue() == RI->getValue();
7144 if (
const auto *LC = dyn_cast<CharacterLiteral>(LHS)) {
7145 const auto *RC = dyn_cast<CharacterLiteral>(RHS);
7148 return LC->getValue() == RC->getValue();
7152 if (
const auto *LF = dyn_cast<FloatingLiteral>(LHS)) {
7153 const auto *RF = dyn_cast<FloatingLiteral>(RHS);
7157 return LF->getValue().bitwiseIsEqual(RF->getValue());
7161 if (
const auto *LS = dyn_cast<StringLiteral>(LHS)) {
7162 const auto *RS = dyn_cast<StringLiteral>(RHS);
7165 return LS->getString() == RS->getString();
7173 if (
const auto *LB = dyn_cast<CXXBoolLiteralExpr>(LHS)) {
7174 const auto *RB = dyn_cast<CXXBoolLiteralExpr>(RHS);
7177 return LB->getValue() == RB->getValue();
7186 static unsigned getFlagMemberOffset() {
7187 unsigned Offset = 0;
7188 for (uint64_t Remain =
7189 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
7190 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF);
7191 !(Remain & 1); Remain = Remain >> 1)
7198 class MappingExprInfo {
7200 const ValueDecl *MapDecl =
nullptr;
7203 const Expr *MapExpr =
nullptr;
7206 MappingExprInfo(
const ValueDecl *MapDecl,
const Expr *MapExpr =
nullptr)
7207 : MapDecl(MapDecl), MapExpr(MapExpr) {}
7209 const ValueDecl *getMapDecl()
const {
return MapDecl; }
7210 const Expr *getMapExpr()
const {
return MapExpr; }
7213 using DeviceInfoTy = llvm::OpenMPIRBuilder::DeviceInfoTy;
7214 using MapBaseValuesArrayTy = llvm::OpenMPIRBuilder::MapValuesArrayTy;
7215 using MapValuesArrayTy = llvm::OpenMPIRBuilder::MapValuesArrayTy;
7216 using MapFlagsArrayTy = llvm::OpenMPIRBuilder::MapFlagsArrayTy;
7217 using MapDimArrayTy = llvm::OpenMPIRBuilder::MapDimArrayTy;
7218 using MapNonContiguousArrayTy =
7219 llvm::OpenMPIRBuilder::MapNonContiguousArrayTy;
7220 using MapExprsArrayTy = SmallVector<MappingExprInfo, 4>;
7221 using MapValueDeclsArrayTy = SmallVector<const ValueDecl *, 4>;
7225 bool ,
const ValueDecl *,
const Expr *>;
7226 using MapDataArrayTy = SmallVector<MapData, 4>;
7231 struct MapCombinedInfoTy : llvm::OpenMPIRBuilder::MapInfosTy {
7232 MapExprsArrayTy Exprs;
7233 MapValueDeclsArrayTy Mappers;
7234 MapValueDeclsArrayTy DevicePtrDecls;
7237 void append(MapCombinedInfoTy &CurInfo) {
7238 Exprs.append(CurInfo.Exprs.begin(), CurInfo.Exprs.end());
7239 DevicePtrDecls.append(CurInfo.DevicePtrDecls.begin(),
7240 CurInfo.DevicePtrDecls.end());
7241 Mappers.append(CurInfo.Mappers.begin(), CurInfo.Mappers.end());
7242 llvm::OpenMPIRBuilder::MapInfosTy::append(CurInfo);
7250 struct StructRangeInfoTy {
7251 MapCombinedInfoTy PreliminaryMapData;
7252 std::pair<
unsigned , Address > LowestElem = {
7254 std::pair<
unsigned , Address > HighestElem = {
7258 bool IsArraySection =
false;
7259 bool HasCompleteRecord =
false;
7264 struct AttachInfoTy {
7267 const ValueDecl *AttachPtrDecl =
nullptr;
7268 const Expr *AttachMapExpr =
nullptr;
7270 bool isValid()
const {
7277 bool hasAttachEntryForCapturedVar(
const ValueDecl *VD)
const {
7278 for (
const auto &AttachEntry : AttachPtrExprMap) {
7279 if (AttachEntry.second) {
7282 if (
const auto *DRE = dyn_cast<DeclRefExpr>(AttachEntry.second))
7283 if (DRE->getDecl() == VD)
7291 const Expr *getAttachPtrExpr(
7294 const auto It = AttachPtrExprMap.find(Components);
7295 if (It != AttachPtrExprMap.end())
7306 ArrayRef<OpenMPMapModifierKind> MapModifiers;
7307 ArrayRef<OpenMPMotionModifierKind> MotionModifiers;
7308 bool ReturnDevicePointer =
false;
7309 bool IsImplicit =
false;
7310 const ValueDecl *Mapper =
nullptr;
7311 const Expr *VarRef =
nullptr;
7312 bool ForDeviceAddr =
false;
7313 bool HasUdpFbNullify =
false;
7315 MapInfo() =
default;
7319 ArrayRef<OpenMPMapModifierKind> MapModifiers,
7320 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
7321 bool ReturnDevicePointer,
bool IsImplicit,
7322 const ValueDecl *Mapper =
nullptr,
const Expr *VarRef =
nullptr,
7323 bool ForDeviceAddr =
false,
bool HasUdpFbNullify =
false)
7324 : Components(Components), MapType(MapType), MapModifiers(MapModifiers),
7325 MotionModifiers(MotionModifiers),
7326 ReturnDevicePointer(ReturnDevicePointer), IsImplicit(IsImplicit),
7327 Mapper(Mapper), VarRef(VarRef), ForDeviceAddr(ForDeviceAddr),
7328 HasUdpFbNullify(HasUdpFbNullify) {}
7333 llvm::PointerUnion<
const OMPExecutableDirective *,
7334 const OMPDeclareMapperDecl *>
7338 CodeGenFunction &CGF;
7343 llvm::DenseMap<CanonicalDeclPtr<const VarDecl>,
bool> FirstPrivateDecls;
7346 llvm::SmallSet<OpenMPDefaultmapClauseKind, 4> DefaultmapFirstprivateKinds;
7352 SmallVector<OMPClauseMappableExprCommon::MappableExprComponentListRef, 4>>
7359 SmallVector<OMPClauseMappableExprCommon::MappableExprComponentListRef, 4>>
7363 llvm::DenseMap<const ValueDecl *, const OMPMapClause *> LambdasMap;
7378 llvm::DenseMap<const Expr *, std::optional<size_t>>
7379 AttachPtrComponentDepthMap = {{
nullptr, std::nullopt}};
7383 llvm::DenseMap<const Expr *, size_t> AttachPtrComputationOrderMap = {
7388 AttachPtrExprComparator AttachPtrComparator;
7390 llvm::Value *getExprTypeSize(
const Expr *E)
const {
7394 if (
const auto *OAE = dyn_cast<OMPArrayShapingExpr>(E)) {
7396 CGF.
getTypeSize(OAE->getBase()->getType()->getPointeeType());
7397 for (
const Expr *SE : OAE->getDimensions()) {
7408 if (
const auto *RefTy = ExprTy->
getAs<ReferenceType>())
7414 if (
const auto *OAE = dyn_cast<ArraySectionExpr>(E)) {
7416 OAE->getBase()->IgnoreParenImpCasts())
7422 if (!OAE->getLength() && OAE->getColonLocFirst().isValid() &&
7423 !OAE->getLowerBound())
7426 llvm::Value *ElemSize;
7427 if (
const auto *PTy = BaseTy->
getAs<PointerType>()) {
7428 ElemSize = CGF.
getTypeSize(PTy->getPointeeType().getCanonicalType());
7431 assert(ATy &&
"Expecting array type if not a pointer type.");
7432 ElemSize = CGF.
getTypeSize(ATy->getElementType().getCanonicalType());
7437 if (!OAE->getLength() && OAE->getColonLocFirst().isInvalid())
7440 if (
const Expr *LenExpr = OAE->getLength()) {
7444 LenExpr->getExprLoc());
7445 return CGF.
Builder.CreateNUWMul(LengthVal, ElemSize);
7447 assert(!OAE->getLength() && OAE->getColonLocFirst().isValid() &&
7448 OAE->getLowerBound() &&
"expected array_section[lb:].");
7454 OAE->getLowerBound()->getExprLoc());
7455 LBVal = CGF.
Builder.CreateNUWMul(LBVal, ElemSize);
7456 llvm::Value *
Cmp = CGF.
Builder.CreateICmpUGT(LengthVal, LBVal);
7457 llvm::Value *TrueVal = CGF.
Builder.CreateNUWSub(LengthVal, LBVal);
7458 LengthVal = CGF.
Builder.CreateSelect(
7459 Cmp, TrueVal, llvm::ConstantInt::get(CGF.
SizeTy, 0));
7469 OpenMPOffloadMappingFlags getMapTypeBits(
7471 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
bool IsImplicit,
7472 bool AddPtrFlag,
bool AddIsTargetParamFlag,
bool IsNonContiguous)
const {
7473 OpenMPOffloadMappingFlags Bits =
7474 IsImplicit ? OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT
7475 : OpenMPOffloadMappingFlags::OMP_MAP_NONE;
7477 case OMPC_MAP_alloc:
7478 case OMPC_MAP_release:
7485 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_TO;
7488 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_FROM;
7490 case OMPC_MAP_tofrom:
7491 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_TO |
7492 OpenMPOffloadMappingFlags::OMP_MAP_FROM;
7494 case OMPC_MAP_delete:
7495 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_DELETE;
7498 llvm_unreachable(
"Unexpected map type!");
7501 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ;
7502 if (AddIsTargetParamFlag)
7503 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM;
7504 if (llvm::is_contained(MapModifiers, OMPC_MAP_MODIFIER_always))
7505 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_ALWAYS;
7506 if (llvm::is_contained(MapModifiers, OMPC_MAP_MODIFIER_close))
7507 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_CLOSE;
7508 if (llvm::is_contained(MapModifiers, OMPC_MAP_MODIFIER_present) ||
7509 llvm::is_contained(MotionModifiers, OMPC_MOTION_MODIFIER_present))
7510 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_PRESENT;
7511 if (llvm::is_contained(MapModifiers, OMPC_MAP_MODIFIER_ompx_hold))
7512 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_OMPX_HOLD;
7513 if (IsNonContiguous)
7514 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_NON_CONTIG;
7520 bool isFinalArraySectionExpression(
const Expr *E)
const {
7521 const auto *OASE = dyn_cast<ArraySectionExpr>(E);
7528 if (OASE->getColonLocFirst().isInvalid())
7531 const Expr *Length = OASE->getLength();
7538 OASE->getBase()->IgnoreParenImpCasts())
7540 if (
const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.
getTypePtr()))
7541 return ATy->getSExtSize() != 1;
7553 llvm::APSInt ConstLength =
Result.Val.getInt();
7554 return ConstLength.getSExtValue() != 1;
7561 void emitAttachEntry(CodeGenFunction &CGF, MapCombinedInfoTy &CombinedInfo,
7562 const AttachInfoTy &AttachInfo)
const {
7563 assert(AttachInfo.isValid() &&
7564 "Expected valid attach pointer/pointee information!");
7568 llvm::Value *PointerSize = CGF.
Builder.CreateIntCast(
7569 llvm::ConstantInt::get(
7575 CombinedInfo.Exprs.emplace_back(AttachInfo.AttachPtrDecl,
7576 AttachInfo.AttachMapExpr);
7577 CombinedInfo.BasePointers.push_back(
7578 AttachInfo.AttachPtrAddr.emitRawPointer(CGF));
7579 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
7580 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
7581 CombinedInfo.Pointers.push_back(
7582 AttachInfo.AttachPteeAddr.emitRawPointer(CGF));
7583 CombinedInfo.Sizes.push_back(PointerSize);
7584 CombinedInfo.Types.push_back(OpenMPOffloadMappingFlags::OMP_MAP_ATTACH);
7585 CombinedInfo.Mappers.push_back(
nullptr);
7586 CombinedInfo.NonContigInfo.Dims.push_back(1);
7593 class CopyOverlappedEntryGaps {
7594 CodeGenFunction &CGF;
7595 MapCombinedInfoTy &CombinedInfo;
7596 OpenMPOffloadMappingFlags Flags = OpenMPOffloadMappingFlags::OMP_MAP_NONE;
7597 const ValueDecl *MapDecl =
nullptr;
7598 const Expr *MapExpr =
nullptr;
7600 bool IsNonContiguous =
false;
7604 const RecordDecl *LastParent =
nullptr;
7606 unsigned LastIndex = -1u;
7610 CopyOverlappedEntryGaps(CodeGenFunction &CGF,
7611 MapCombinedInfoTy &CombinedInfo,
7612 OpenMPOffloadMappingFlags Flags,
7613 const ValueDecl *MapDecl,
const Expr *MapExpr,
7614 Address BP, Address LB,
bool IsNonContiguous,
7616 : CGF(CGF), CombinedInfo(CombinedInfo), Flags(Flags), MapDecl(MapDecl),
7617 MapExpr(MapExpr), BP(BP), IsNonContiguous(IsNonContiguous),
7618 DimSize(DimSize), LB(LB) {}
7621 const OMPClauseMappableExprCommon::MappableComponent &MC,
7622 const FieldDecl *FD,
7623 llvm::function_ref<LValue(CodeGenFunction &,
const MemberExpr *)>
7624 EmitMemberExprBase) {
7634 LValue BaseLVal = EmitMemberExprBase(CGF, ME);
7646 copyUntilField(FD, ComponentLB);
7649 if (((int64_t)FieldOffset - (int64_t)Cursor) > 0)
7650 copyUntilField(FD, ComponentLB);
7652 Cursor = FieldOffset + FieldSize;
7657 void copyUntilField(
const FieldDecl *FD, Address ComponentLB) {
7660 llvm::Value *
Size = CGF.
Builder.CreatePtrDiff(ComponentLBPtr, LBPtr);
7661 copySizedChunk(LBPtr, Size);
7664 void copyUntilEnd(Address HB) {
7666 const ASTRecordLayout &RL =
7674 copySizedChunk(LBPtr, Size);
7677 void copySizedChunk(llvm::Value *Base, llvm::Value *Size) {
7678 CombinedInfo.Exprs.emplace_back(MapDecl, MapExpr);
7680 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
7681 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
7682 CombinedInfo.Pointers.push_back(Base);
7683 CombinedInfo.Sizes.push_back(
7685 CombinedInfo.Types.push_back(Flags);
7686 CombinedInfo.Mappers.push_back(
nullptr);
7687 CombinedInfo.NonContigInfo.Dims.push_back(IsNonContiguous ? DimSize : 1);
7696 void generateInfoForComponentList(
7698 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
7700 MapCombinedInfoTy &CombinedInfo,
7701 MapCombinedInfoTy &StructBaseCombinedInfo,
7702 StructRangeInfoTy &PartialStruct, AttachInfoTy &AttachInfo,
7703 bool IsFirstComponentList,
bool IsImplicit,
7704 bool GenerateAllInfoForClauses,
const ValueDecl *Mapper =
nullptr,
7705 bool ForDeviceAddr =
false,
const ValueDecl *BaseDecl =
nullptr,
7706 const Expr *MapExpr =
nullptr,
7707 ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef>
7708 OverlappedElements = {})
const {
7926 bool IsCaptureFirstInfo = IsFirstComponentList;
7930 bool RequiresReference =
false;
7933 auto CI = Components.rbegin();
7934 auto CE = Components.rend();
7939 bool IsExpressionFirstInfo =
true;
7940 bool FirstPointerInComplexData =
false;
7943 const Expr *AssocExpr = I->getAssociatedExpression();
7944 const auto *AE = dyn_cast<ArraySubscriptExpr>(AssocExpr);
7945 const auto *OASE = dyn_cast<ArraySectionExpr>(AssocExpr);
7946 const auto *OAShE = dyn_cast<OMPArrayShapingExpr>(AssocExpr);
7949 const Expr *AttachPtrExpr = getAttachPtrExpr(Components);
7950 auto [AttachPtrAddr, AttachPteeBaseAddr] =
7951 getAttachPtrAddrAndPteeBaseAddr(AttachPtrExpr, CGF);
7953 bool HasAttachPtr = AttachPtrExpr !=
nullptr;
7954 bool FirstComponentIsForAttachPtr = AssocExpr == AttachPtrExpr;
7955 bool SeenAttachPtr = FirstComponentIsForAttachPtr;
7957 if (FirstComponentIsForAttachPtr) {
7965 }
else if ((AE &&
isa<CXXThisExpr>(AE->getBase()->IgnoreParenImpCasts())) ||
7979 if (
const auto *VD =
7980 dyn_cast_or_null<VarDecl>(I->getAssociatedDeclaration())) {
7981 if (std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
7982 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD)) {
7983 if ((*Res == OMPDeclareTargetDeclAttr::MT_Link) ||
7984 ((*Res == OMPDeclareTargetDeclAttr::MT_To ||
7985 *Res == OMPDeclareTargetDeclAttr::MT_Enter) &&
7987 RequiresReference =
true;
7997 I->getAssociatedDeclaration()->
getType().getNonReferenceType();
8002 const auto *VD = dyn_cast<VarDecl>(I->getAssociatedDeclaration());
8004 !VD || VD->hasLocalStorage() || HasAttachPtr)
8007 FirstPointerInComplexData =
true;
8026 bool ShouldBeMemberOf =
false;
8035 const MemberExpr *EncounteredME =
nullptr;
8047 bool IsNonContiguous =
8048 CombinedInfo.NonContigInfo.IsNonContiguous ||
8049 any_of(Components, [&](
const auto &Component) {
8051 dyn_cast<ArraySectionExpr>(Component.getAssociatedExpression());
8055 const Expr *StrideExpr = OASE->getStride();
8059 const auto Constant =
8064 return !Constant->isOne();
8067 bool IsPrevMemberReference =
false;
8069 bool IsPartialMapped =
8070 !PartialStruct.PreliminaryMapData.BasePointers.empty();
8077 bool IsMappingWholeStruct =
true;
8078 if (!GenerateAllInfoForClauses) {
8079 IsMappingWholeStruct =
false;
8081 for (
auto TempI = I; TempI != CE; ++TempI) {
8082 const MemberExpr *PossibleME =
8083 dyn_cast<MemberExpr>(TempI->getAssociatedExpression());
8085 IsMappingWholeStruct =
false;
8091 bool SeenFirstNonBinOpExprAfterAttachPtr =
false;
8092 for (; I != CE; ++I) {
8095 if (HasAttachPtr && !SeenAttachPtr) {
8096 SeenAttachPtr = I->getAssociatedExpression() == AttachPtrExpr;
8103 if (HasAttachPtr && !SeenFirstNonBinOpExprAfterAttachPtr) {
8104 const auto *BO = dyn_cast<BinaryOperator>(I->getAssociatedExpression());
8109 SeenFirstNonBinOpExprAfterAttachPtr =
true;
8110 BP = AttachPteeBaseAddr;
8114 if (!EncounteredME) {
8115 EncounteredME = dyn_cast<MemberExpr>(I->getAssociatedExpression());
8118 if (EncounteredME) {
8119 ShouldBeMemberOf =
true;
8122 if (FirstPointerInComplexData) {
8123 QualType Ty = std::prev(I)
8124 ->getAssociatedDeclaration()
8126 .getNonReferenceType();
8128 FirstPointerInComplexData =
false;
8133 auto Next = std::next(I);
8143 bool IsFinalArraySection =
8145 isFinalArraySectionExpression(I->getAssociatedExpression());
8149 const ValueDecl *MapDecl = (I->getAssociatedDeclaration())
8150 ? I->getAssociatedDeclaration()
8152 MapExpr = (I->getAssociatedExpression()) ? I->getAssociatedExpression()
8159 dyn_cast<ArraySectionExpr>(I->getAssociatedExpression());
8161 dyn_cast<OMPArrayShapingExpr>(I->getAssociatedExpression());
8162 const auto *UO = dyn_cast<UnaryOperator>(I->getAssociatedExpression());
8163 const auto *BO = dyn_cast<BinaryOperator>(I->getAssociatedExpression());
8169 I->getAssociatedExpression()->getType()->isAnyPointerType();
8170 bool IsMemberReference =
isa<MemberExpr>(I->getAssociatedExpression()) &&
8173 bool IsNonDerefPointer = IsPointer &&
8174 !(UO && UO->getOpcode() != UO_Deref) && !BO &&
8180 if (
Next == CE || IsMemberReference || IsNonDerefPointer ||
8181 IsFinalArraySection) {
8184 assert((
Next == CE ||
8191 "Unexpected expression");
8195 auto &&EmitMemberExprBase = [](CodeGenFunction &CGF,
8196 const MemberExpr *E) {
8197 const Expr *BaseExpr = E->getBase();
8202 LValueBaseInfo BaseInfo;
8203 TBAAAccessInfo TBAAInfo;
8217 OAShE->getBase()->getType()->getPointeeType()),
8219 OAShE->getBase()->getType()));
8220 }
else if (IsMemberReference) {
8222 LValue BaseLVal = EmitMemberExprBase(CGF, ME);
8237 FinalLowestElem = LowestElem;
8242 bool IsMemberPointerOrAddr =
8244 (((IsPointer || ForDeviceAddr) &&
8245 I->getAssociatedExpression() == EncounteredME) ||
8246 (IsPrevMemberReference && !IsPointer) ||
8247 (IsMemberReference &&
Next != CE &&
8248 !
Next->getAssociatedExpression()->getType()->isPointerType()));
8249 if (!OverlappedElements.empty() &&
Next == CE) {
8251 assert(!PartialStruct.Base.isValid() &&
"The base element is set.");
8252 assert(!IsPointer &&
8253 "Unexpected base element with the pointer type.");
8256 PartialStruct.LowestElem = {0, LowestElem};
8258 I->getAssociatedExpression()->getType());
8263 PartialStruct.HighestElem = {
8264 std::numeric_limits<
decltype(
8265 PartialStruct.HighestElem.first)>
::max(),
8267 PartialStruct.Base = BP;
8268 PartialStruct.LB = LB;
8270 PartialStruct.PreliminaryMapData.BasePointers.empty() &&
8271 "Overlapped elements must be used only once for the variable.");
8272 std::swap(PartialStruct.PreliminaryMapData, CombinedInfo);
8274 OpenMPOffloadMappingFlags Flags =
8275 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF |
8276 getMapTypeBits(MapType, MapModifiers, MotionModifiers, IsImplicit,
8278 false, IsNonContiguous);
8279 CopyOverlappedEntryGaps CopyGaps(CGF, CombinedInfo, Flags, MapDecl,
8280 MapExpr, BP, LB, IsNonContiguous,
8284 Component : OverlappedElements) {
8285 for (
const OMPClauseMappableExprCommon::MappableComponent &MC :
8288 if (
const auto *FD = dyn_cast<FieldDecl>(VD)) {
8289 CopyGaps.processField(MC, FD, EmitMemberExprBase);
8294 CopyGaps.copyUntilEnd(HB);
8297 llvm::Value *
Size = getExprTypeSize(I->getAssociatedExpression());
8304 if ((!IsMemberPointerOrAddr && !IsPartialMapped) ||
8306 if (!IsMappingWholeStruct) {
8307 CombinedInfo.Exprs.emplace_back(MapDecl, MapExpr);
8309 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
8310 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
8312 CombinedInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
8314 CombinedInfo.NonContigInfo.Dims.push_back(IsNonContiguous ? DimSize
8317 StructBaseCombinedInfo.Exprs.emplace_back(MapDecl, MapExpr);
8318 StructBaseCombinedInfo.BasePointers.push_back(
8320 StructBaseCombinedInfo.DevicePtrDecls.push_back(
nullptr);
8321 StructBaseCombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
8322 StructBaseCombinedInfo.Pointers.push_back(LB.
emitRawPointer(CGF));
8323 StructBaseCombinedInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
8325 StructBaseCombinedInfo.NonContigInfo.Dims.push_back(
8326 IsNonContiguous ? DimSize : 1);
8330 bool HasMapper = Mapper &&
Next == CE;
8331 if (!IsMappingWholeStruct)
8332 CombinedInfo.Mappers.push_back(HasMapper ? Mapper :
nullptr);
8334 StructBaseCombinedInfo.Mappers.push_back(HasMapper ? Mapper
8341 OpenMPOffloadMappingFlags Flags = getMapTypeBits(
8342 MapType, MapModifiers, MotionModifiers, IsImplicit,
8343 !IsExpressionFirstInfo || RequiresReference ||
8344 FirstPointerInComplexData || IsMemberReference,
8345 IsCaptureFirstInfo && !RequiresReference, IsNonContiguous);
8347 if (!IsExpressionFirstInfo || IsMemberReference) {
8350 if (IsPointer || (IsMemberReference &&
Next != CE))
8351 Flags &= ~(OpenMPOffloadMappingFlags::OMP_MAP_TO |
8352 OpenMPOffloadMappingFlags::OMP_MAP_FROM |
8353 OpenMPOffloadMappingFlags::OMP_MAP_ALWAYS |
8354 OpenMPOffloadMappingFlags::OMP_MAP_DELETE |
8355 OpenMPOffloadMappingFlags::OMP_MAP_CLOSE);
8357 if (ShouldBeMemberOf) {
8360 Flags |= OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF;
8363 ShouldBeMemberOf =
false;
8367 if (!IsMappingWholeStruct)
8368 CombinedInfo.Types.push_back(Flags);
8370 StructBaseCombinedInfo.Types.push_back(Flags);
8376 if (EncounteredME) {
8381 if (!PartialStruct.Base.isValid()) {
8382 PartialStruct.LowestElem = {FieldIndex, LowestElem};
8383 if (IsFinalArraySection && OASE) {
8387 PartialStruct.HighestElem = {FieldIndex, HB};
8389 PartialStruct.HighestElem = {FieldIndex, LowestElem};
8391 PartialStruct.Base = BP;
8392 PartialStruct.LB = BP;
8393 }
else if (FieldIndex < PartialStruct.LowestElem.first) {
8394 PartialStruct.LowestElem = {FieldIndex, LowestElem};
8395 }
else if (FieldIndex > PartialStruct.HighestElem.first) {
8396 if (IsFinalArraySection && OASE) {
8400 PartialStruct.HighestElem = {FieldIndex, HB};
8402 PartialStruct.HighestElem = {FieldIndex, LowestElem};
8408 if (IsFinalArraySection || IsNonContiguous)
8409 PartialStruct.IsArraySection =
true;
8412 if (IsFinalArraySection)
8417 BP = IsMemberReference ? LowestElem : LB;
8418 if (!IsPartialMapped)
8419 IsExpressionFirstInfo =
false;
8420 IsCaptureFirstInfo =
false;
8421 FirstPointerInComplexData =
false;
8422 IsPrevMemberReference = IsMemberReference;
8423 }
else if (FirstPointerInComplexData) {
8424 QualType Ty = Components.rbegin()
8425 ->getAssociatedDeclaration()
8427 .getNonReferenceType();
8429 FirstPointerInComplexData =
false;
8435 PartialStruct.HasCompleteRecord =
true;
8438 if (shouldEmitAttachEntry(AttachPtrExpr, BaseDecl, CGF, CurDir)) {
8439 AttachInfo.AttachPtrAddr = AttachPtrAddr;
8440 AttachInfo.AttachPteeAddr = FinalLowestElem;
8441 AttachInfo.AttachPtrDecl = BaseDecl;
8442 AttachInfo.AttachMapExpr = MapExpr;
8445 if (!IsNonContiguous)
8448 const ASTContext &Context = CGF.
getContext();
8452 MapValuesArrayTy CurOffsets = {llvm::ConstantInt::get(CGF.
CGM.
Int64Ty, 0)};
8453 MapValuesArrayTy CurCounts = {llvm::ConstantInt::get(CGF.
CGM.
Int64Ty, 1)};
8454 MapValuesArrayTy CurStrides;
8455 MapValuesArrayTy DimSizes{llvm::ConstantInt::get(CGF.
CGM.
Int64Ty, 1)};
8461 for (
const OMPClauseMappableExprCommon::MappableComponent &Component :
8463 const Expr *AssocExpr = Component.getAssociatedExpression();
8464 const auto *OASE = dyn_cast<ArraySectionExpr>(AssocExpr);
8474 assert((VAT || CAT || &Component == &*Components.begin()) &&
8475 "Should be either ConstantArray or VariableArray if not the "
8479 if (CurStrides.empty()) {
8480 const Type *ElementType =
nullptr;
8482 ElementType = CAT->getElementType().getTypePtr();
8484 ElementType = VAT->getElementType().getTypePtr();
8485 else if (&Component == &*Components.begin()) {
8492 if (
const auto *PtrType = Ty->
getAs<PointerType>())
8499 "Non-first components should not be raw pointers");
8507 if (&Component != &*Components.begin())
8511 CurStrides.push_back(
8512 llvm::ConstantInt::get(CGF.
Int64Ty, ElementTypeSize));
8517 if (DimSizes.size() < Components.size() - 1) {
8520 llvm::ConstantInt::get(CGF.
Int64Ty, CAT->getZExtSize()));
8522 DimSizes.push_back(CGF.
Builder.CreateIntCast(
8529 auto *DI = DimSizes.begin() + 1;
8531 llvm::Value *DimProd =
8532 llvm::ConstantInt::get(CGF.
CGM.
Int64Ty, ElementTypeSize);
8541 for (
const OMPClauseMappableExprCommon::MappableComponent &Component :
8543 const Expr *AssocExpr = Component.getAssociatedExpression();
8545 if (
const auto *AE = dyn_cast<ArraySubscriptExpr>(AssocExpr)) {
8546 llvm::Value *Offset = CGF.
Builder.CreateIntCast(
8549 CurOffsets.push_back(Offset);
8550 CurCounts.push_back(llvm::ConstantInt::get(CGF.
Int64Ty, 1));
8551 CurStrides.push_back(CurStrides.back());
8555 const auto *OASE = dyn_cast<ArraySectionExpr>(AssocExpr);
8561 const Expr *OffsetExpr = OASE->getLowerBound();
8562 llvm::Value *Offset =
nullptr;
8565 Offset = llvm::ConstantInt::get(CGF.
Int64Ty, 0);
8571 CurOffsets.push_back(Offset);
8574 const Expr *CountExpr = OASE->getLength();
8575 llvm::Value *Count =
nullptr;
8581 if (!OASE->getColonLocFirst().isValid() &&
8582 !OASE->getColonLocSecond().isValid()) {
8583 Count = llvm::ConstantInt::get(CGF.
Int64Ty, 1);
8589 const Expr *StrideExpr = OASE->getStride();
8590 llvm::Value *Stride =
8596 Count = CGF.
Builder.CreateUDiv(
8597 CGF.
Builder.CreateNUWSub(*DI, Offset), Stride);
8599 Count = CGF.
Builder.CreateNUWSub(*DI, Offset);
8605 CurCounts.push_back(Count);
8614 const Expr *StrideExpr = OASE->getStride();
8615 llvm::Value *Stride =
8620 DimProd = CGF.
Builder.CreateNUWMul(DimProd, *(DI - 1));
8622 CurStrides.push_back(CGF.
Builder.CreateNUWMul(DimProd, Stride));
8624 CurStrides.push_back(DimProd);
8625 if (DI != DimSizes.end())
8629 CombinedInfo.NonContigInfo.Offsets.push_back(CurOffsets);
8630 CombinedInfo.NonContigInfo.Counts.push_back(CurCounts);
8631 CombinedInfo.NonContigInfo.Strides.push_back(CurStrides);
8637 OpenMPOffloadMappingFlags
8638 getMapModifiersForPrivateClauses(
const CapturedStmt::Capture &Cap)
const {
8646 return OpenMPOffloadMappingFlags::OMP_MAP_TO |
8647 OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ;
8648 return OpenMPOffloadMappingFlags::OMP_MAP_PRIVATE |
8649 OpenMPOffloadMappingFlags::OMP_MAP_TO;
8652 if (I != LambdasMap.end())
8654 return getMapTypeBits(
8655 I->getSecond()->getMapType(), I->getSecond()->getMapTypeModifiers(),
8656 {}, I->getSecond()->isImplicit(),
8660 return OpenMPOffloadMappingFlags::OMP_MAP_TO |
8661 OpenMPOffloadMappingFlags::OMP_MAP_FROM;
8664 void getPlainLayout(
const CXXRecordDecl *RD,
8665 llvm::SmallVectorImpl<const FieldDecl *> &Layout,
8666 bool AsBase)
const {
8669 llvm::StructType *St =
8672 unsigned NumElements = St->getNumElements();
8674 llvm::PointerUnion<const CXXRecordDecl *, const FieldDecl *>, 4>
8675 RecordLayout(NumElements);
8678 for (
const auto &I : RD->
bases()) {
8682 QualType BaseTy = I.getType();
8693 RecordLayout[FieldIndex] =
Base;
8696 for (
const auto &I : RD->
vbases()) {
8697 QualType BaseTy = I.getType();
8704 if (RecordLayout[FieldIndex])
8706 RecordLayout[FieldIndex] =
Base;
8709 assert(!RD->
isUnion() &&
"Unexpected union.");
8710 for (
const auto *Field : RD->
fields()) {
8713 if (!
Field->isBitField() &&
8716 RecordLayout[FieldIndex] =
Field;
8719 for (
const llvm::PointerUnion<const CXXRecordDecl *, const FieldDecl *>
8720 &
Data : RecordLayout) {
8723 if (
const auto *Base = dyn_cast<const CXXRecordDecl *>(
Data))
8724 getPlainLayout(Base, Layout,
true);
8731 static Address getAttachPtrAddr(
const Expr *PointerExpr,
8732 CodeGenFunction &CGF) {
8733 assert(PointerExpr &&
"Cannot get addr from null attach-ptr expr");
8736 if (
auto *DRE = dyn_cast<DeclRefExpr>(PointerExpr)) {
8739 }
else if (
auto *OASE = dyn_cast<ArraySectionExpr>(PointerExpr)) {
8742 }
else if (
auto *ASE = dyn_cast<ArraySubscriptExpr>(PointerExpr)) {
8744 }
else if (
auto *ME = dyn_cast<MemberExpr>(PointerExpr)) {
8746 }
else if (
auto *UO = dyn_cast<UnaryOperator>(PointerExpr)) {
8747 assert(UO->getOpcode() == UO_Deref &&
8748 "Unexpected unary-operator on attach-ptr-expr");
8751 assert(AttachPtrAddr.
isValid() &&
8752 "Failed to get address for attach pointer expression");
8753 return AttachPtrAddr;
8760 static std::pair<Address, Address>
8761 getAttachPtrAddrAndPteeBaseAddr(
const Expr *AttachPtrExpr,
8762 CodeGenFunction &CGF) {
8767 Address AttachPtrAddr = getAttachPtrAddr(AttachPtrExpr, CGF);
8768 assert(AttachPtrAddr.
isValid() &&
"Invalid attach pointer addr");
8770 QualType AttachPtrType =
8775 AttachPtrAddr, AttachPtrType->
castAs<PointerType>());
8776 assert(AttachPteeBaseAddr.
isValid() &&
"Invalid attach pointee base addr");
8778 return {AttachPtrAddr, AttachPteeBaseAddr};
8784 shouldEmitAttachEntry(
const Expr *PointerExpr,
const ValueDecl *MapBaseDecl,
8785 CodeGenFunction &CGF,
8786 llvm::PointerUnion<
const OMPExecutableDirective *,
8787 const OMPDeclareMapperDecl *>
8797 ->getDirectiveKind());
8806 void collectAttachPtrExprInfo(
8808 llvm::PointerUnion<
const OMPExecutableDirective *,
8809 const OMPDeclareMapperDecl *>
8814 ? OMPD_declare_mapper
8817 const auto &[AttachPtrExpr, Depth] =
8821 AttachPtrComputationOrderMap.try_emplace(
8822 AttachPtrExpr, AttachPtrComputationOrderMap.size());
8823 AttachPtrComponentDepthMap.try_emplace(AttachPtrExpr, Depth);
8824 AttachPtrExprMap.try_emplace(Components, AttachPtrExpr);
8832 void generateAllInfoForClauses(
8833 ArrayRef<const OMPClause *> Clauses, MapCombinedInfoTy &CombinedInfo,
8834 llvm::OpenMPIRBuilder &OMPBuilder,
8835 const llvm::DenseSet<CanonicalDeclPtr<const Decl>> &SkipVarSet =
8836 llvm::DenseSet<CanonicalDeclPtr<const Decl>>())
const {
8841 llvm::MapVector<CanonicalDeclPtr<const Decl>,
8842 SmallVector<SmallVector<MapInfo, 8>, 4>>
8848 [&Info, &SkipVarSet](
8849 const ValueDecl *D, MapKind
Kind,
8852 ArrayRef<OpenMPMapModifierKind> MapModifiers,
8853 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
8854 bool ReturnDevicePointer,
bool IsImplicit,
const ValueDecl *Mapper,
8855 const Expr *VarRef =
nullptr,
bool ForDeviceAddr =
false) {
8856 if (SkipVarSet.contains(D))
8858 auto It = Info.try_emplace(D, Total).first;
8859 It->second[
Kind].emplace_back(
8860 L, MapType, MapModifiers, MotionModifiers, ReturnDevicePointer,
8861 IsImplicit, Mapper, VarRef, ForDeviceAddr);
8864 for (
const auto *
Cl : Clauses) {
8865 const auto *
C = dyn_cast<OMPMapClause>(
Cl);
8869 if (llvm::is_contained(
C->getMapTypeModifiers(),
8870 OMPC_MAP_MODIFIER_present))
8872 else if (
C->getMapType() == OMPC_MAP_alloc)
8874 const auto *EI =
C->getVarRefs().begin();
8875 for (
const auto L :
C->component_lists()) {
8876 const Expr *E = (
C->getMapLoc().isValid()) ? *EI :
nullptr;
8877 InfoGen(std::get<0>(L), Kind, std::get<1>(L),
C->getMapType(),
8878 C->getMapTypeModifiers(), {},
8879 false,
C->isImplicit(), std::get<2>(L),
8884 for (
const auto *
Cl : Clauses) {
8885 const auto *
C = dyn_cast<OMPToClause>(
Cl);
8889 if (llvm::is_contained(
C->getMotionModifiers(),
8890 OMPC_MOTION_MODIFIER_present))
8892 if (llvm::is_contained(
C->getMotionModifiers(),
8893 OMPC_MOTION_MODIFIER_iterator)) {
8894 if (
auto *IteratorExpr = dyn_cast<OMPIteratorExpr>(
8895 C->getIteratorModifier()->IgnoreParenImpCasts())) {
8896 const auto *VD =
cast<VarDecl>(IteratorExpr->getIteratorDecl(0));
8901 const auto *EI =
C->getVarRefs().begin();
8902 for (
const auto L :
C->component_lists()) {
8903 InfoGen(std::get<0>(L), Kind, std::get<1>(L), OMPC_MAP_to, {},
8904 C->getMotionModifiers(),
false,
8905 C->isImplicit(), std::get<2>(L), *EI);
8909 for (
const auto *
Cl : Clauses) {
8910 const auto *
C = dyn_cast<OMPFromClause>(
Cl);
8914 if (llvm::is_contained(
C->getMotionModifiers(),
8915 OMPC_MOTION_MODIFIER_present))
8917 if (llvm::is_contained(
C->getMotionModifiers(),
8918 OMPC_MOTION_MODIFIER_iterator)) {
8919 if (
auto *IteratorExpr = dyn_cast<OMPIteratorExpr>(
8920 C->getIteratorModifier()->IgnoreParenImpCasts())) {
8921 const auto *VD =
cast<VarDecl>(IteratorExpr->getIteratorDecl(0));
8926 const auto *EI =
C->getVarRefs().begin();
8927 for (
const auto L :
C->component_lists()) {
8928 InfoGen(std::get<0>(L), Kind, std::get<1>(L), OMPC_MAP_from, {},
8929 C->getMotionModifiers(),
8930 false,
C->isImplicit(), std::get<2>(L),
8943 MapCombinedInfoTy UseDeviceDataCombinedInfo;
8945 auto &&UseDeviceDataCombinedInfoGen =
8946 [&UseDeviceDataCombinedInfo](
const ValueDecl *VD, llvm::Value *Ptr,
8947 CodeGenFunction &CGF,
bool IsDevAddr,
8948 bool HasUdpFbNullify =
false) {
8949 UseDeviceDataCombinedInfo.Exprs.push_back(VD);
8950 UseDeviceDataCombinedInfo.BasePointers.emplace_back(Ptr);
8951 UseDeviceDataCombinedInfo.DevicePtrDecls.emplace_back(VD);
8952 UseDeviceDataCombinedInfo.DevicePointers.emplace_back(
8953 IsDevAddr ? DeviceInfoTy::Address : DeviceInfoTy::Pointer);
8959 UseDeviceDataCombinedInfo.Pointers.push_back(Ptr);
8960 UseDeviceDataCombinedInfo.Sizes.push_back(
8961 llvm::Constant::getNullValue(CGF.Int64Ty));
8962 OpenMPOffloadMappingFlags Flags =
8963 OpenMPOffloadMappingFlags::OMP_MAP_RETURN_PARAM;
8964 if (HasUdpFbNullify)
8965 Flags |= OpenMPOffloadMappingFlags::OMP_MAP_FB_NULLIFY;
8966 UseDeviceDataCombinedInfo.Types.push_back(Flags);
8967 UseDeviceDataCombinedInfo.Mappers.push_back(
nullptr);
8971 [&UseDeviceDataCombinedInfoGen](
8972 CodeGenFunction &CGF,
const Expr *IE,
const ValueDecl *VD,
8975 bool IsDevAddr,
bool IEIsAttachPtrForDevAddr =
false,
8976 bool HasUdpFbNullify =
false) {
8980 if (IsDevAddr && !IEIsAttachPtrForDevAddr) {
8981 if (IE->isGLValue())
8988 bool TreatDevAddrAsDevPtr = IEIsAttachPtrForDevAddr;
8995 UseDeviceDataCombinedInfoGen(VD, Ptr, CGF, IsDevAddr &&
8996 !TreatDevAddrAsDevPtr,
9000 auto &&IsMapInfoExist =
9001 [&Info,
this](CodeGenFunction &CGF,
const ValueDecl *VD,
const Expr *IE,
9002 const Expr *DesiredAttachPtrExpr,
bool IsDevAddr,
9003 bool HasUdpFbNullify =
false) ->
bool {
9011 if (It != Info.end()) {
9013 for (
auto &
Data : It->second) {
9014 MapInfo *CI =
nullptr;
9018 auto *It = llvm::find_if(
Data, [&](
const MapInfo &MI) {
9019 if (MI.Components.back().getAssociatedDeclaration() != VD)
9022 const Expr *MapAttachPtr = getAttachPtrExpr(MI.Components);
9023 bool Match = AttachPtrComparator.areEqual(MapAttachPtr,
9024 DesiredAttachPtrExpr);
9028 if (It !=
Data.end())
9033 CI->ForDeviceAddr =
true;
9034 CI->ReturnDevicePointer =
true;
9035 CI->HasUdpFbNullify = HasUdpFbNullify;
9039 auto PrevCI = std::next(CI->Components.rbegin());
9040 const auto *VarD = dyn_cast<VarDecl>(VD);
9041 const Expr *AttachPtrExpr = getAttachPtrExpr(CI->Components);
9042 if (CGF.CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory() ||
9044 !VD->getType().getNonReferenceType()->isPointerType() ||
9045 PrevCI == CI->Components.rend() ||
9047 VarD->hasLocalStorage() ||
9048 (isa_and_nonnull<DeclRefExpr>(AttachPtrExpr) &&
9050 CI->ForDeviceAddr = IsDevAddr;
9051 CI->ReturnDevicePointer =
true;
9052 CI->HasUdpFbNullify = HasUdpFbNullify;
9070 for (
const auto *
Cl : Clauses) {
9071 const auto *
C = dyn_cast<OMPUseDevicePtrClause>(
Cl);
9074 bool HasUdpFbNullify =
9075 C->getFallbackModifier() == OMPC_USE_DEVICE_PTR_FALLBACK_fb_nullify;
9076 for (
const auto L :
C->component_lists()) {
9079 assert(!Components.empty() &&
9080 "Not expecting empty list of components!");
9081 const ValueDecl *VD = Components.back().getAssociatedDeclaration();
9083 const Expr *IE = Components.back().getAssociatedExpression();
9091 const Expr *UDPOperandExpr =
9092 Components.front().getAssociatedExpression();
9093 if (IsMapInfoExist(CGF, VD, IE,
9095 false, HasUdpFbNullify))
9097 MapInfoGen(CGF, IE, VD, Components,
false,
9098 false, HasUdpFbNullify);
9102 llvm::SmallDenseSet<CanonicalDeclPtr<const Decl>, 4> Processed;
9103 for (
const auto *
Cl : Clauses) {
9104 const auto *
C = dyn_cast<OMPUseDeviceAddrClause>(
Cl);
9107 for (
const auto L :
C->component_lists()) {
9110 assert(!std::get<1>(L).empty() &&
9111 "Not expecting empty list of components!");
9112 const ValueDecl *VD = std::get<1>(L).back().getAssociatedDeclaration();
9113 if (!Processed.insert(VD).second)
9134 const Expr *UDAAttachPtrExpr = getAttachPtrExpr(Components);
9135 const Expr *IE = std::get<1>(L).back().getAssociatedExpression();
9136 assert((!UDAAttachPtrExpr || UDAAttachPtrExpr == IE) &&
9137 "use_device_addr operand has an attach-ptr, but does not match "
9138 "last component's expr.");
9139 if (IsMapInfoExist(CGF, VD, IE,
9143 MapInfoGen(CGF, IE, VD, Components,
9145 UDAAttachPtrExpr !=
nullptr);
9149 for (
const auto &
Data : Info) {
9150 MapCombinedInfoTy CurInfo;
9152 const ValueDecl *VD = cast_or_null<ValueDecl>(D);
9159 SmallVector<std::pair<const Expr *, MapInfo>, 16> AttachPtrMapInfoPairs;
9162 for (
const auto &M :
Data.second) {
9163 for (
const MapInfo &L : M) {
9164 assert(!L.Components.empty() &&
9165 "Not expecting declaration with no component lists.");
9167 const Expr *AttachPtrExpr = getAttachPtrExpr(L.Components);
9168 AttachPtrMapInfoPairs.emplace_back(AttachPtrExpr, L);
9173 llvm::stable_sort(AttachPtrMapInfoPairs,
9174 [
this](
const auto &LHS,
const auto &RHS) {
9175 return AttachPtrComparator(LHS.first, RHS.first);
9180 auto *It = AttachPtrMapInfoPairs.begin();
9181 while (It != AttachPtrMapInfoPairs.end()) {
9182 const Expr *AttachPtrExpr = It->first;
9184 SmallVector<MapInfo, 8> GroupLists;
9185 while (It != AttachPtrMapInfoPairs.end() &&
9186 (It->first == AttachPtrExpr ||
9187 AttachPtrComparator.areEqual(It->first, AttachPtrExpr))) {
9188 GroupLists.push_back(It->second);
9191 assert(!GroupLists.empty() &&
"GroupLists should not be empty");
9193 StructRangeInfoTy PartialStruct;
9194 AttachInfoTy AttachInfo;
9195 MapCombinedInfoTy GroupCurInfo;
9197 MapCombinedInfoTy GroupStructBaseCurInfo;
9198 for (
const MapInfo &L : GroupLists) {
9200 unsigned CurrentBasePointersIdx = GroupCurInfo.BasePointers.size();
9201 unsigned StructBasePointersIdx =
9202 GroupStructBaseCurInfo.BasePointers.size();
9204 GroupCurInfo.NonContigInfo.IsNonContiguous =
9205 L.Components.back().isNonContiguous();
9206 generateInfoForComponentList(
9207 L.MapType, L.MapModifiers, L.MotionModifiers, L.Components,
9208 GroupCurInfo, GroupStructBaseCurInfo, PartialStruct, AttachInfo,
9209 false, L.IsImplicit,
9210 true, L.Mapper, L.ForDeviceAddr, VD,
9215 if (L.ReturnDevicePointer) {
9219 assert((CurrentBasePointersIdx < GroupCurInfo.BasePointers.size() ||
9220 StructBasePointersIdx <
9221 GroupStructBaseCurInfo.BasePointers.size()) &&
9222 "Unexpected number of mapped base pointers.");
9225 const ValueDecl *RelevantVD =
9226 L.Components.back().getAssociatedDeclaration();
9227 assert(RelevantVD &&
9228 "No relevant declaration related with device pointer??");
9235 auto SetDevicePointerInfo = [&](MapCombinedInfoTy &Info,
9237 Info.DevicePtrDecls[Idx] = RelevantVD;
9238 Info.DevicePointers[Idx] = L.ForDeviceAddr
9239 ? DeviceInfoTy::Address
9240 : DeviceInfoTy::Pointer;
9242 OpenMPOffloadMappingFlags::OMP_MAP_RETURN_PARAM;
9243 if (L.HasUdpFbNullify)
9245 OpenMPOffloadMappingFlags::OMP_MAP_FB_NULLIFY;
9248 if (StructBasePointersIdx <
9249 GroupStructBaseCurInfo.BasePointers.size())
9250 SetDevicePointerInfo(GroupStructBaseCurInfo,
9251 StructBasePointersIdx);
9253 SetDevicePointerInfo(GroupCurInfo, CurrentBasePointersIdx);
9259 MapCombinedInfoTy GroupUnionCurInfo;
9260 GroupUnionCurInfo.append(GroupStructBaseCurInfo);
9261 GroupUnionCurInfo.append(GroupCurInfo);
9265 if (PartialStruct.Base.isValid()) {
9273 GroupUnionCurInfo.NonContigInfo.Dims.insert(
9274 GroupUnionCurInfo.NonContigInfo.Dims.begin(), 1);
9276 CurInfo, GroupUnionCurInfo.Types, PartialStruct, AttachInfo,
9277 !VD, OMPBuilder, VD,
9278 CombinedInfo.BasePointers.size(),
9284 CurInfo.append(GroupUnionCurInfo);
9285 if (AttachInfo.isValid())
9286 emitAttachEntry(CGF, CurInfo, AttachInfo);
9290 CombinedInfo.append(CurInfo);
9293 CombinedInfo.append(UseDeviceDataCombinedInfo);
9297 MappableExprsHandler(
const OMPExecutableDirective &Dir, CodeGenFunction &CGF)
9298 : CurDir(&Dir), CGF(CGF), AttachPtrComparator(*this) {
9300 for (
const auto *
C : Dir.getClausesOfKind<OMPFirstprivateClause>())
9301 for (
const auto *D :
C->varlist())
9302 FirstPrivateDecls.try_emplace(
9305 for (
const auto *
C : Dir.getClausesOfKind<OMPUsesAllocatorsClause>()) {
9306 for (unsigned I = 0, E = C->getNumberOfAllocators(); I < E; ++I) {
9307 OMPUsesAllocatorsClause::Data D = C->getAllocatorData(I);
9308 if (const auto *DRE = dyn_cast_or_null<DeclRefExpr>(D.AllocatorTraits))
9309 FirstPrivateDecls.try_emplace(cast<VarDecl>(DRE->getDecl()),
9311 else if (const auto *VD = dyn_cast<VarDecl>(
9312 cast<DeclRefExpr>(D.Allocator->IgnoreParenImpCasts())
9314 FirstPrivateDecls.try_emplace(VD, true);
9318 for (
const auto *
C : Dir.getClausesOfKind<OMPDefaultmapClause>())
9319 if (
C->getDefaultmapModifier() == OMPC_DEFAULTMAP_MODIFIER_firstprivate)
9320 DefaultmapFirstprivateKinds.insert(
C->getDefaultmapKind());
9322 for (
const auto *
C : Dir.getClausesOfKind<OMPIsDevicePtrClause>())
9323 for (
auto L :
C->component_lists())
9324 DevPointersMap[std::get<0>(L)].push_back(std::get<1>(L));
9326 for (
const auto *
C : Dir.getClausesOfKind<OMPHasDeviceAddrClause>())
9327 for (
auto L :
C->component_lists())
9328 HasDevAddrsMap[std::get<0>(L)].push_back(std::get<1>(L));
9330 for (
const auto *
C : Dir.getClausesOfKind<OMPMapClause>()) {
9331 if (C->getMapType() != OMPC_MAP_to)
9333 for (auto L : C->component_lists()) {
9334 const ValueDecl *VD = std::get<0>(L);
9335 const auto *RD = VD ? VD->getType()
9337 .getNonReferenceType()
9338 ->getAsCXXRecordDecl()
9340 if (RD && RD->isLambda())
9341 LambdasMap.try_emplace(std::get<0>(L), C);
9345 auto CollectAttachPtrExprsForClauseComponents = [
this](
const auto *
C) {
9346 for (
auto L :
C->component_lists()) {
9349 if (!Components.empty())
9350 collectAttachPtrExprInfo(Components, CurDir);
9356 for (
const auto *
C : Dir.getClausesOfKind<OMPMapClause>())
9357 CollectAttachPtrExprsForClauseComponents(
C);
9358 for (
const auto *
C : Dir.getClausesOfKind<OMPToClause>())
9359 CollectAttachPtrExprsForClauseComponents(
C);
9360 for (
const auto *
C : Dir.getClausesOfKind<OMPFromClause>())
9361 CollectAttachPtrExprsForClauseComponents(
C);
9362 for (
const auto *
C : Dir.getClausesOfKind<OMPUseDevicePtrClause>())
9363 CollectAttachPtrExprsForClauseComponents(
C);
9364 for (
const auto *
C : Dir.getClausesOfKind<OMPUseDeviceAddrClause>())
9365 CollectAttachPtrExprsForClauseComponents(
C);
9366 for (
const auto *
C : Dir.getClausesOfKind<OMPIsDevicePtrClause>())
9367 CollectAttachPtrExprsForClauseComponents(
C);
9368 for (
const auto *
C : Dir.getClausesOfKind<OMPHasDeviceAddrClause>())
9369 CollectAttachPtrExprsForClauseComponents(
C);
9373 MappableExprsHandler(
const OMPDeclareMapperDecl &Dir,
CodeGenFunction &CGF)
9374 : CurDir(&Dir), CGF(CGF), AttachPtrComparator(*this) {}
9384 void emitCombinedEntry(MapCombinedInfoTy &CombinedInfo,
9385 MapFlagsArrayTy &CurTypes,
9386 const StructRangeInfoTy &PartialStruct,
9387 AttachInfoTy &AttachInfo,
bool IsMapThis,
9388 llvm::OpenMPIRBuilder &OMPBuilder,
const ValueDecl *VD,
9389 unsigned OffsetForMemberOfFlag,
9390 bool NotTargetParams)
const {
9391 if (CurTypes.size() == 1 &&
9392 ((CurTypes.back() & OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF) !=
9393 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF) &&
9394 !PartialStruct.IsArraySection)
9396 Address LBAddr = PartialStruct.LowestElem.second;
9397 Address HBAddr = PartialStruct.HighestElem.second;
9398 if (PartialStruct.HasCompleteRecord) {
9399 LBAddr = PartialStruct.LB;
9400 HBAddr = PartialStruct.LB;
9402 CombinedInfo.Exprs.push_back(VD);
9404 CombinedInfo.BasePointers.push_back(PartialStruct.Base.emitRawPointer(CGF));
9405 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
9406 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
9409 const CXXMethodDecl *MD =
9411 const CXXRecordDecl *RD = MD ? MD->
getParent() :
nullptr;
9412 bool HasBaseClass = RD && IsMapThis ? RD->
getNumBases() > 0 :
false;
9422 CombinedInfo.Pointers.push_back(PartialStruct.Base.emitRawPointer(CGF));
9427 CombinedInfo.Sizes.push_back(Size);
9429 CombinedInfo.Pointers.push_back(LB);
9432 llvm::Value *HAddr = CGF.
Builder.CreateConstGEP1_32(
9436 llvm::Value *Diff = CGF.
Builder.CreatePtrDiff(CHAddr, CLAddr);
9439 CombinedInfo.Sizes.push_back(Size);
9441 CombinedInfo.Mappers.push_back(
nullptr);
9443 CombinedInfo.Types.push_back(
9444 NotTargetParams ? OpenMPOffloadMappingFlags::OMP_MAP_NONE
9445 : !PartialStruct.PreliminaryMapData.BasePointers.empty()
9446 ? OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ
9447 : OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM);
9450 if (CurTypes.end() !=
9451 llvm::find_if(CurTypes, [](OpenMPOffloadMappingFlags
Type) {
9452 return static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>>(
9453 Type & OpenMPOffloadMappingFlags::OMP_MAP_PRESENT);
9455 CombinedInfo.Types.back() |= OpenMPOffloadMappingFlags::OMP_MAP_PRESENT;
9457 (*CurTypes.begin()) &= ~OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM;
9464 if (CurTypes.end() !=
9465 llvm::find_if(CurTypes, [](OpenMPOffloadMappingFlags
Type) {
9466 return static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>>(
9467 Type & OpenMPOffloadMappingFlags::OMP_MAP_OMPX_HOLD);
9469 CombinedInfo.Types.back() |= OpenMPOffloadMappingFlags::OMP_MAP_OMPX_HOLD;
9470 for (
auto &M : CurTypes)
9471 M |= OpenMPOffloadMappingFlags::OMP_MAP_OMPX_HOLD;
9478 OpenMPOffloadMappingFlags MemberOfFlag = OMPBuilder.getMemberOfFlag(
9479 OffsetForMemberOfFlag + CombinedInfo.BasePointers.size() - 1);
9480 for (
auto &M : CurTypes)
9481 OMPBuilder.setCorrectMemberOfFlag(M, MemberOfFlag);
9498 if (AttachInfo.isValid())
9499 AttachInfo.AttachPteeAddr = LBAddr;
9507 void generateAllInfo(
9508 MapCombinedInfoTy &CombinedInfo, llvm::OpenMPIRBuilder &OMPBuilder,
9509 const llvm::DenseSet<CanonicalDeclPtr<const Decl>> &SkipVarSet =
9510 llvm::DenseSet<CanonicalDeclPtr<const Decl>>())
const {
9512 "Expect a executable directive");
9514 generateAllInfoForClauses(CurExecDir->clauses(), CombinedInfo, OMPBuilder,
9521 void generateAllInfoForMapper(MapCombinedInfoTy &CombinedInfo,
9522 llvm::OpenMPIRBuilder &OMPBuilder)
const {
9524 "Expect a declare mapper directive");
9526 generateAllInfoForClauses(CurMapperDir->clauses(), CombinedInfo,
9531 void generateInfoForLambdaCaptures(
9532 const ValueDecl *VD, llvm::Value *Arg, MapCombinedInfoTy &CombinedInfo,
9533 llvm::DenseMap<llvm::Value *, llvm::Value *> &LambdaPointers)
const {
9541 llvm::DenseMap<const ValueDecl *, FieldDecl *> Captures;
9542 FieldDecl *ThisCapture =
nullptr;
9548 LambdaPointers.try_emplace(ThisLVal.getPointer(CGF),
9549 VDLVal.getPointer(CGF));
9550 CombinedInfo.Exprs.push_back(VD);
9551 CombinedInfo.BasePointers.push_back(ThisLVal.getPointer(CGF));
9552 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
9553 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
9554 CombinedInfo.Pointers.push_back(ThisLValVal.getPointer(CGF));
9555 CombinedInfo.Sizes.push_back(
9558 CombinedInfo.Types.push_back(
9559 OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ |
9560 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL |
9561 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF |
9562 OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT);
9563 CombinedInfo.Mappers.push_back(
nullptr);
9565 for (
const LambdaCapture &LC : RD->
captures()) {
9566 if (!LC.capturesVariable())
9571 auto It = Captures.find(VD);
9572 assert(It != Captures.end() &&
"Found lambda capture without field.");
9576 LambdaPointers.try_emplace(VarLVal.getPointer(CGF),
9577 VDLVal.getPointer(CGF));
9578 CombinedInfo.Exprs.push_back(VD);
9579 CombinedInfo.BasePointers.push_back(VarLVal.getPointer(CGF));
9580 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
9581 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
9582 CombinedInfo.Pointers.push_back(VarLValVal.getPointer(CGF));
9583 CombinedInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
9589 LambdaPointers.try_emplace(VarLVal.getPointer(CGF),
9590 VDLVal.getPointer(CGF));
9591 CombinedInfo.Exprs.push_back(VD);
9592 CombinedInfo.BasePointers.push_back(VarLVal.getPointer(CGF));
9593 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
9594 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
9595 CombinedInfo.Pointers.push_back(VarRVal.
getScalarVal());
9596 CombinedInfo.Sizes.push_back(llvm::ConstantInt::get(CGF.
Int64Ty, 0));
9598 CombinedInfo.Types.push_back(
9599 OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ |
9600 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL |
9601 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF |
9602 OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT);
9603 CombinedInfo.Mappers.push_back(
nullptr);
9608 void adjustMemberOfForLambdaCaptures(
9609 llvm::OpenMPIRBuilder &OMPBuilder,
9610 const llvm::DenseMap<llvm::Value *, llvm::Value *> &LambdaPointers,
9611 MapBaseValuesArrayTy &BasePointers, MapValuesArrayTy &Pointers,
9612 MapFlagsArrayTy &Types)
const {
9613 for (
unsigned I = 0, E = Types.size(); I < E; ++I) {
9615 if (Types[I] != (OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ |
9616 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL |
9617 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF |
9618 OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT))
9620 llvm::Value *BasePtr = LambdaPointers.lookup(BasePointers[I]);
9621 assert(BasePtr &&
"Unable to find base lambda address.");
9623 for (
unsigned J = I; J > 0; --J) {
9624 unsigned Idx = J - 1;
9625 if (Pointers[Idx] != BasePtr)
9630 assert(TgtIdx != -1 &&
"Unable to find parent lambda.");
9634 OpenMPOffloadMappingFlags MemberOfFlag =
9635 OMPBuilder.getMemberOfFlag(TgtIdx);
9636 OMPBuilder.setCorrectMemberOfFlag(Types[I], MemberOfFlag);
9642 void populateComponentListsForNonLambdaCaptureFromClauses(
9643 const ValueDecl *VD, MapDataArrayTy &DeclComponentLists,
9645 SmallVector<OMPClauseMappableExprCommon::MappableComponent, 8>>
9646 &StorageForImplicitlyAddedComponentLists)
const {
9647 if (VD && LambdasMap.count(VD))
9653 auto It = DevPointersMap.find(VD);
9654 if (It != DevPointersMap.end())
9655 for (
const auto &MCL : It->second)
9656 DeclComponentLists.emplace_back(MCL, OMPC_MAP_to,
Unknown,
9659 auto I = HasDevAddrsMap.find(VD);
9660 if (I != HasDevAddrsMap.end())
9661 for (
const auto &MCL : I->second)
9662 DeclComponentLists.emplace_back(MCL, OMPC_MAP_tofrom,
Unknown,
9666 "Expect a executable directive");
9668 for (
const auto *
C : CurExecDir->getClausesOfKind<OMPMapClause>()) {
9669 const auto *EI =
C->getVarRefs().begin();
9670 for (
const auto L :
C->decl_component_lists(VD)) {
9671 const ValueDecl *VDecl, *Mapper;
9673 const Expr *E = (
C->getMapLoc().isValid()) ? *EI :
nullptr;
9675 std::tie(VDecl, Components, Mapper) = L;
9676 assert(VDecl == VD &&
"We got information for the wrong declaration??");
9677 assert(!Components.empty() &&
9678 "Not expecting declaration with no component lists.");
9679 DeclComponentLists.emplace_back(Components,
C->getMapType(),
9680 C->getMapTypeModifiers(),
9681 C->isImplicit(), Mapper, E);
9690 addImplicitMapForAttachPtrBaseIfMemberOfCapturedVD(
9691 VD, DeclComponentLists, StorageForImplicitlyAddedComponentLists);
9693 llvm::stable_sort(DeclComponentLists, [](
const MapData &LHS,
9694 const MapData &RHS) {
9695 ArrayRef<OpenMPMapModifierKind> MapModifiers = std::get<2>(LHS);
9698 llvm::is_contained(MapModifiers, clang::OMPC_MAP_MODIFIER_present);
9699 bool HasAllocs = MapType == OMPC_MAP_alloc;
9700 MapModifiers = std::get<2>(RHS);
9701 MapType = std::get<1>(LHS);
9703 llvm::is_contained(MapModifiers, clang::OMPC_MAP_MODIFIER_present);
9704 bool HasAllocsR = MapType == OMPC_MAP_alloc;
9705 return (HasPresent && !HasPresentR) || (HasAllocs && !HasAllocsR);
9741 void addImplicitMapForAttachPtrBaseIfMemberOfCapturedVD(
9742 const ValueDecl *CapturedVD, MapDataArrayTy &DeclComponentLists,
9744 SmallVector<OMPClauseMappableExprCommon::MappableComponent, 8>>
9745 &ComponentVectorStorage)
const {
9746 bool IsThisCapture = CapturedVD ==
nullptr;
9748 for (
const auto &ComponentsAndAttachPtr : AttachPtrExprMap) {
9750 ComponentsWithAttachPtr = ComponentsAndAttachPtr.first;
9751 const Expr *AttachPtrExpr = ComponentsAndAttachPtr.second;
9755 const auto *ME = dyn_cast<MemberExpr>(AttachPtrExpr);
9759 const Expr *
Base = ME->getBase()->IgnoreParenImpCasts();
9780 bool FoundExistingMap =
false;
9781 for (
const MapData &ExistingL : DeclComponentLists) {
9783 ExistingComponents = std::get<0>(ExistingL);
9785 if (ExistingComponents.empty())
9789 const auto &FirstComponent = ExistingComponents.front();
9790 const Expr *FirstExpr = FirstComponent.getAssociatedExpression();
9796 if (AttachPtrComparator.areEqual(FirstExpr, AttachPtrExpr)) {
9797 FoundExistingMap =
true;
9802 if (IsThisCapture) {
9803 if (
const auto *OASE = dyn_cast<ArraySectionExpr>(FirstExpr)) {
9805 FoundExistingMap =
true;
9814 if (
const auto *DRE = dyn_cast<DeclRefExpr>(FirstExpr)) {
9815 if (DRE->getDecl() == CapturedVD) {
9816 FoundExistingMap =
true;
9822 if (FoundExistingMap)
9828 ComponentVectorStorage.emplace_back();
9829 auto &AttachPtrComponents = ComponentVectorStorage.back();
9832 bool SeenAttachPtrComponent =
false;
9838 for (
size_t i = 0; i < ComponentsWithAttachPtr.size(); ++i) {
9839 const auto &Component = ComponentsWithAttachPtr[i];
9840 const Expr *ComponentExpr = Component.getAssociatedExpression();
9842 if (!SeenAttachPtrComponent && ComponentExpr != AttachPtrExpr)
9844 SeenAttachPtrComponent =
true;
9846 AttachPtrComponents.emplace_back(Component.getAssociatedExpression(),
9847 Component.getAssociatedDeclaration(),
9848 Component.isNonContiguous());
9850 assert(!AttachPtrComponents.empty() &&
9851 "Could not populate component-lists for mapping attach-ptr");
9853 DeclComponentLists.emplace_back(
9854 AttachPtrComponents, OMPC_MAP_tofrom,
Unknown,
9855 true,
nullptr, AttachPtrExpr);
9862 void generateInfoForCaptureFromClauseInfo(
9863 const MapDataArrayTy &DeclComponentListsFromClauses,
9864 const CapturedStmt::Capture *Cap, llvm::Value *Arg,
9865 MapCombinedInfoTy &CurCaptureVarInfo, llvm::OpenMPIRBuilder &OMPBuilder,
9866 unsigned OffsetForMemberOfFlag)
const {
9868 "Not expecting to generate map info for a variable array type!");
9877 if (LambdasMap.count(VD))
9883 if (VD && (DevPointersMap.count(VD) || HasDevAddrsMap.count(VD))) {
9884 CurCaptureVarInfo.Exprs.push_back(VD);
9885 CurCaptureVarInfo.BasePointers.emplace_back(Arg);
9886 CurCaptureVarInfo.DevicePtrDecls.emplace_back(VD);
9887 CurCaptureVarInfo.DevicePointers.emplace_back(DeviceInfoTy::Pointer);
9888 CurCaptureVarInfo.Pointers.push_back(Arg);
9889 CurCaptureVarInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
9892 CurCaptureVarInfo.Types.push_back(
9893 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL |
9894 OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM);
9895 CurCaptureVarInfo.Mappers.push_back(
nullptr);
9899 auto GenerateInfoForComponentLists =
9900 [&](ArrayRef<MapData> DeclComponentListsFromClauses,
9901 bool IsEligibleForTargetParamFlag) {
9902 MapCombinedInfoTy CurInfoForComponentLists;
9903 StructRangeInfoTy PartialStruct;
9904 AttachInfoTy AttachInfo;
9906 if (DeclComponentListsFromClauses.empty())
9909 generateInfoForCaptureFromComponentLists(
9910 VD, DeclComponentListsFromClauses, CurInfoForComponentLists,
9911 PartialStruct, AttachInfo, IsEligibleForTargetParamFlag);
9916 if (PartialStruct.Base.isValid()) {
9917 CurCaptureVarInfo.append(PartialStruct.PreliminaryMapData);
9919 CurCaptureVarInfo, CurInfoForComponentLists.Types,
9920 PartialStruct, AttachInfo, Cap->
capturesThis(), OMPBuilder,
9921 nullptr, OffsetForMemberOfFlag,
9922 !IsEligibleForTargetParamFlag);
9927 CurCaptureVarInfo.append(CurInfoForComponentLists);
9928 if (AttachInfo.isValid())
9929 emitAttachEntry(CGF, CurCaptureVarInfo, AttachInfo);
9953 SmallVector<std::pair<const Expr *, MapData>, 16> AttachPtrMapDataPairs;
9955 for (
const MapData &L : DeclComponentListsFromClauses) {
9958 const Expr *AttachPtrExpr = getAttachPtrExpr(Components);
9959 AttachPtrMapDataPairs.emplace_back(AttachPtrExpr, L);
9963 llvm::stable_sort(AttachPtrMapDataPairs,
9964 [
this](
const auto &LHS,
const auto &RHS) {
9965 return AttachPtrComparator(LHS.first, RHS.first);
9968 bool NoDefaultMappingDoneForVD = CurCaptureVarInfo.BasePointers.empty();
9969 bool IsFirstGroup =
true;
9973 auto *It = AttachPtrMapDataPairs.begin();
9974 while (It != AttachPtrMapDataPairs.end()) {
9975 const Expr *AttachPtrExpr = It->first;
9977 MapDataArrayTy GroupLists;
9978 while (It != AttachPtrMapDataPairs.end() &&
9979 (It->first == AttachPtrExpr ||
9980 AttachPtrComparator.areEqual(It->first, AttachPtrExpr))) {
9981 GroupLists.push_back(It->second);
9984 assert(!GroupLists.empty() &&
"GroupLists should not be empty");
9989 bool IsEligibleForTargetParamFlag =
9990 IsFirstGroup && NoDefaultMappingDoneForVD;
9992 GenerateInfoForComponentLists(GroupLists, IsEligibleForTargetParamFlag);
9993 IsFirstGroup =
false;
10000 void generateInfoForCaptureFromComponentLists(
10001 const ValueDecl *VD, ArrayRef<MapData> DeclComponentLists,
10002 MapCombinedInfoTy &CurComponentListInfo, StructRangeInfoTy &PartialStruct,
10003 AttachInfoTy &AttachInfo,
bool IsListEligibleForTargetParamFlag)
const {
10005 llvm::SmallDenseMap<
10012 for (
const MapData &L : DeclComponentLists) {
10015 ArrayRef<OpenMPMapModifierKind> MapModifiers;
10017 const ValueDecl *Mapper;
10018 const Expr *VarRef;
10019 std::tie(Components, MapType, MapModifiers, IsImplicit, Mapper, VarRef) =
10022 for (
const MapData &L1 : ArrayRef(DeclComponentLists).slice(Count)) {
10024 std::tie(Components1, MapType, MapModifiers, IsImplicit, Mapper,
10026 auto CI = Components.rbegin();
10027 auto CE = Components.rend();
10028 auto SI = Components1.rbegin();
10029 auto SE = Components1.rend();
10030 for (; CI != CE && SI != SE; ++CI, ++SI) {
10031 if (CI->getAssociatedExpression()->getStmtClass() !=
10032 SI->getAssociatedExpression()->getStmtClass())
10035 if (CI->getAssociatedDeclaration() != SI->getAssociatedDeclaration())
10040 if (CI == CE || SI == SE) {
10042 if (CI == CE && SI == SE)
10044 const auto It = (SI == SE) ? CI : SI;
10051 (std::prev(It)->getAssociatedDeclaration() &&
10053 ->getAssociatedDeclaration()
10055 ->isPointerType()) ||
10056 (It->getAssociatedDeclaration() &&
10057 It->getAssociatedDeclaration()->getType()->isPointerType() &&
10058 std::next(It) != CE && std::next(It) != SE))
10060 const MapData &BaseData = CI == CE ? L : L1;
10062 SI == SE ? Components : Components1;
10063 OverlappedData[&BaseData].push_back(SubData);
10068 llvm::SmallVector<const FieldDecl *, 4> Layout;
10069 if (!OverlappedData.empty()) {
10072 while (BaseType != OrigType) {
10078 getPlainLayout(CRD, Layout,
false);
10084 for (
auto &Pair : OverlappedData) {
10091 auto CI = First.rbegin();
10092 auto CE = First.rend();
10093 auto SI = Second.rbegin();
10094 auto SE = Second.rend();
10095 for (; CI != CE && SI != SE; ++CI, ++SI) {
10096 if (CI->getAssociatedExpression()->getStmtClass() !=
10097 SI->getAssociatedExpression()->getStmtClass())
10100 if (CI->getAssociatedDeclaration() !=
10101 SI->getAssociatedDeclaration())
10106 if (CI == CE && SI == SE)
10110 if (CI == CE || SI == SE)
10115 if (FD1->getParent() == FD2->getParent())
10116 return FD1->getFieldIndex() < FD2->getFieldIndex();
10118 llvm::find_if(Layout, [FD1, FD2](
const FieldDecl *FD) {
10119 return FD == FD1 || FD == FD2;
10127 bool AddTargetParamFlag = IsListEligibleForTargetParamFlag;
10128 MapCombinedInfoTy StructBaseCombinedInfo;
10129 for (
const auto &Pair : OverlappedData) {
10130 const MapData &L = *Pair.getFirst();
10133 ArrayRef<OpenMPMapModifierKind> MapModifiers;
10135 const ValueDecl *Mapper;
10136 const Expr *VarRef;
10137 std::tie(Components, MapType, MapModifiers, IsImplicit, Mapper, VarRef) =
10139 ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef>
10140 OverlappedComponents = Pair.getSecond();
10141 generateInfoForComponentList(
10142 MapType, MapModifiers, {}, Components, CurComponentListInfo,
10143 StructBaseCombinedInfo, PartialStruct, AttachInfo, AddTargetParamFlag,
10144 IsImplicit,
false, Mapper,
10145 false, VD, VarRef, OverlappedComponents);
10146 AddTargetParamFlag =
false;
10149 for (
const MapData &L : DeclComponentLists) {
10152 ArrayRef<OpenMPMapModifierKind> MapModifiers;
10154 const ValueDecl *Mapper;
10155 const Expr *VarRef;
10156 std::tie(Components, MapType, MapModifiers, IsImplicit, Mapper, VarRef) =
10158 auto It = OverlappedData.find(&L);
10159 if (It == OverlappedData.end())
10160 generateInfoForComponentList(
10161 MapType, MapModifiers, {}, Components, CurComponentListInfo,
10162 StructBaseCombinedInfo, PartialStruct, AttachInfo,
10163 AddTargetParamFlag, IsImplicit,
false,
10164 Mapper,
false, VD, VarRef,
10166 AddTargetParamFlag =
false;
10172 bool isEffectivelyFirstprivate(
const VarDecl *VD, QualType
Type)
const {
10174 auto I = FirstPrivateDecls.find(VD);
10175 if (I != FirstPrivateDecls.end() && !I->getSecond())
10179 if (DefaultmapFirstprivateKinds.count(OMPC_DEFAULTMAP_scalar)) {
10180 if (
Type->isScalarType())
10185 if (DefaultmapFirstprivateKinds.count(OMPC_DEFAULTMAP_pointer)) {
10186 if (
Type->isAnyPointerType())
10191 if (DefaultmapFirstprivateKinds.count(OMPC_DEFAULTMAP_aggregate)) {
10192 if (
Type->isAggregateType())
10197 return DefaultmapFirstprivateKinds.count(OMPC_DEFAULTMAP_all);
10202 void generateDefaultMapInfo(
const CapturedStmt::Capture &CI,
10203 const FieldDecl &RI, llvm::Value *CV,
10204 MapCombinedInfoTy &CombinedInfo)
const {
10205 bool IsImplicit =
true;
10208 CombinedInfo.Exprs.push_back(
nullptr);
10209 CombinedInfo.BasePointers.push_back(CV);
10210 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
10211 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
10212 CombinedInfo.Pointers.push_back(CV);
10214 CombinedInfo.Sizes.push_back(
10218 CombinedInfo.Types.push_back(OpenMPOffloadMappingFlags::OMP_MAP_TO |
10219 OpenMPOffloadMappingFlags::OMP_MAP_FROM);
10223 CombinedInfo.BasePointers.push_back(CV);
10224 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
10225 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
10226 CombinedInfo.Pointers.push_back(CV);
10227 bool IsFirstprivate =
10233 CombinedInfo.Types.push_back(
10234 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL);
10235 CombinedInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
10237 }
else if (IsFirstprivate) {
10240 CombinedInfo.Types.push_back(
10241 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL);
10243 CombinedInfo.Sizes.push_back(llvm::Constant::getNullValue(CGF.
Int64Ty));
10247 CombinedInfo.Types.push_back(OpenMPOffloadMappingFlags::OMP_MAP_NONE);
10248 CombinedInfo.Sizes.push_back(llvm::Constant::getNullValue(CGF.
Int64Ty));
10250 auto I = FirstPrivateDecls.find(VD);
10251 if (I != FirstPrivateDecls.end())
10252 IsImplicit = I->getSecond();
10258 bool IsFirstprivate = isEffectivelyFirstprivate(VD, ElementType);
10260 CombinedInfo.BasePointers.push_back(CV);
10261 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
10262 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
10267 CombinedInfo.Pointers.push_back(CV);
10269 CombinedInfo.Sizes.push_back(llvm::Constant::getNullValue(CGF.
Int64Ty));
10270 CombinedInfo.Types.push_back(
10271 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL);
10273 CombinedInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
10278 CombinedInfo.Types.push_back(getMapModifiersForPrivateClauses(CI));
10279 CombinedInfo.Pointers.push_back(CV);
10281 auto I = FirstPrivateDecls.find(VD);
10282 if (I != FirstPrivateDecls.end())
10283 IsImplicit = I->getSecond();
10286 CombinedInfo.Types.back() |=
10287 OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM;
10291 CombinedInfo.Types.back() |= OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT;
10294 CombinedInfo.Mappers.push_back(
nullptr);
10306 dyn_cast<MemberExpr>(OASE->getBase()->IgnoreParenImpCasts()))
10307 return ME->getMemberDecl();
10313static llvm::Constant *
10315 MappableExprsHandler::MappingExprInfo &MapExprs) {
10317 uint32_t SrcLocStrSize;
10318 if (!MapExprs.getMapDecl() && !MapExprs.getMapExpr())
10319 return OMPBuilder.getOrCreateDefaultSrcLocStr(SrcLocStrSize);
10322 if (!MapExprs.getMapDecl() && MapExprs.getMapExpr()) {
10326 Loc = MapExprs.getMapExpr()->getExprLoc();
10328 Loc = MapExprs.getMapDecl()->getLocation();
10331 std::string ExprName;
10332 if (MapExprs.getMapExpr()) {
10334 llvm::raw_string_ostream OS(ExprName);
10335 MapExprs.getMapExpr()->printPretty(OS,
nullptr, P);
10337 ExprName = MapExprs.getMapDecl()->getNameAsString();
10346 return OMPBuilder.getOrCreateSrcLocStr(
FileName, ExprName, PLoc.
getLine(),
10353 CodeGenFunction &CGF, MappableExprsHandler::MapCombinedInfoTy &CombinedInfo,
10355 bool IsNonContiguous =
false,
bool ForEndCall =
false) {
10358 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
10361 InsertPointTy CodeGenIP(CGF.
Builder.GetInsertBlock(),
10362 CGF.
Builder.GetInsertPoint());
10364 auto DeviceAddrCB = [&](
unsigned int I, llvm::Value *NewDecl) {
10365 if (
const ValueDecl *DevVD = CombinedInfo.DevicePtrDecls[I]) {
10370 auto CustomMapperCB = [&](
unsigned int I) {
10371 llvm::Function *MFunc =
nullptr;
10372 if (CombinedInfo.Mappers[I]) {
10373 Info.HasMapper =
true;
10379 cantFail(OMPBuilder.emitOffloadingArraysAndArgs(
10380 AllocaIP, CodeGenIP, Info, Info.RTArgs, CombinedInfo, CustomMapperCB,
10381 IsNonContiguous, ForEndCall, DeviceAddrCB));
10385static const OMPExecutableDirective *
10387 const auto *CS = D.getInnermostCapturedStmt();
10390 const Stmt *ChildStmt =
10393 if (
const auto *NestedDir =
10394 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) {
10396 switch (D.getDirectiveKind()) {
10402 if (DKind == OMPD_teams) {
10403 Body = NestedDir->getInnermostCapturedStmt()->IgnoreContainers(
10408 if (
const auto *NND =
10409 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) {
10410 DKind = NND->getDirectiveKind();
10416 case OMPD_target_teams:
10420 case OMPD_target_parallel:
10421 case OMPD_target_simd:
10422 case OMPD_target_parallel_for:
10423 case OMPD_target_parallel_for_simd:
10425 case OMPD_target_teams_distribute:
10426 case OMPD_target_teams_distribute_simd:
10427 case OMPD_target_teams_distribute_parallel_for:
10428 case OMPD_target_teams_distribute_parallel_for_simd:
10429 case OMPD_parallel:
10431 case OMPD_parallel_for:
10432 case OMPD_parallel_master:
10433 case OMPD_parallel_sections:
10434 case OMPD_for_simd:
10435 case OMPD_parallel_for_simd:
10437 case OMPD_cancellation_point:
10439 case OMPD_threadprivate:
10440 case OMPD_allocate:
10445 case OMPD_sections:
10449 case OMPD_critical:
10450 case OMPD_taskyield:
10452 case OMPD_taskwait:
10453 case OMPD_taskgroup:
10459 case OMPD_target_data:
10460 case OMPD_target_exit_data:
10461 case OMPD_target_enter_data:
10462 case OMPD_distribute:
10463 case OMPD_distribute_simd:
10464 case OMPD_distribute_parallel_for:
10465 case OMPD_distribute_parallel_for_simd:
10466 case OMPD_teams_distribute:
10467 case OMPD_teams_distribute_simd:
10468 case OMPD_teams_distribute_parallel_for:
10469 case OMPD_teams_distribute_parallel_for_simd:
10470 case OMPD_target_update:
10471 case OMPD_declare_simd:
10472 case OMPD_declare_variant:
10473 case OMPD_begin_declare_variant:
10474 case OMPD_end_declare_variant:
10475 case OMPD_declare_target:
10476 case OMPD_end_declare_target:
10477 case OMPD_declare_reduction:
10478 case OMPD_declare_mapper:
10479 case OMPD_taskloop:
10480 case OMPD_taskloop_simd:
10481 case OMPD_master_taskloop:
10482 case OMPD_master_taskloop_simd:
10483 case OMPD_parallel_master_taskloop:
10484 case OMPD_parallel_master_taskloop_simd:
10485 case OMPD_requires:
10486 case OMPD_metadirective:
10489 llvm_unreachable(
"Unexpected directive.");
10528 if (
UDMMap.count(D) > 0)
10532 auto *MapperVarDecl =
10534 CharUnits ElementSize =
C.getTypeSizeInChars(Ty);
10535 llvm::Type *ElemTy =
CGM.getTypes().ConvertTypeForMem(Ty);
10538 MappableExprsHandler::MapCombinedInfoTy CombinedInfo;
10539 auto PrivatizeAndGenMapInfoCB =
10540 [&](llvm::OpenMPIRBuilder::InsertPointTy CodeGenIP, llvm::Value *PtrPHI,
10541 llvm::Value *BeginArg) -> llvm::OpenMPIRBuilder::MapInfosTy & {
10542 MapperCGF.
Builder.restoreIP(CodeGenIP);
10552 Scope.addPrivate(MapperVarDecl, PtrCurrent);
10553 (void)
Scope.Privatize();
10556 MappableExprsHandler MEHandler(*D, MapperCGF);
10557 MEHandler.generateAllInfoForMapper(CombinedInfo,
OMPBuilder);
10559 auto FillInfoMap = [&](MappableExprsHandler::MappingExprInfo &MapExpr) {
10562 if (
CGM.getCodeGenOpts().getDebugInfo() !=
10563 llvm::codegenoptions::NoDebugInfo) {
10564 CombinedInfo.Names.resize(CombinedInfo.Exprs.size());
10565 llvm::transform(CombinedInfo.Exprs, CombinedInfo.Names.begin(),
10569 return CombinedInfo;
10572 auto CustomMapperCB = [&](
unsigned I) {
10573 llvm::Function *MapperFunc =
nullptr;
10574 if (CombinedInfo.Mappers[I]) {
10578 assert(MapperFunc &&
"Expect a valid mapper function is available.");
10584 llvm::raw_svector_ostream Out(TyStr);
10585 CGM.getCXXABI().getMangleContext().mangleCanonicalTypeName(Ty, Out);
10586 std::string Name =
getName({
"omp_mapper", TyStr, D->
getName()});
10588 llvm::Function *NewFn = cantFail(
OMPBuilder.emitUserDefinedMapper(
10589 PrivatizeAndGenMapInfoCB, ElemTy, Name, CustomMapperCB));
10590 UDMMap.try_emplace(D, NewFn);
10597 auto I =
UDMMap.find(D);
10601 return UDMMap.lookup(D);
10614 Kind != OMPD_target_teams_loop)
10617 return llvm::ConstantInt::get(CGF.
Int64Ty, 0);
10620 if (llvm::Value *NumIterations = SizeEmitter(CGF, *LD))
10621 return NumIterations;
10622 return llvm::ConstantInt::get(CGF.
Int64Ty, 0);
10631 if (OffloadingMandatory) {
10632 CGF.
Builder.CreateUnreachable();
10634 if (RequiresOuterTask) {
10635 CapturedVars.clear();
10644 llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier>
Device,
10647 llvm::Value *DeviceID;
10648 if (
Device.getPointer()) {
10650 Device.getInt() == OMPC_DEVICE_device_num) &&
10651 "Expected device_num modifier.");
10656 DeviceID = CGF.
Builder.getInt64(OMP_DEVICEID_UNDEF);
10661static std::pair<llvm::Value *, OMPDynGroupprivateFallbackType>
10663 llvm::Value *DynGP = CGF.
Builder.getInt32(0);
10664 auto DynGPFallback = OMPDynGroupprivateFallbackType::Abort;
10668 llvm::Value *DynGPVal =
10672 auto FallbackModifier = DynGPClause->getDynGroupprivateFallbackModifier();
10673 switch (FallbackModifier) {
10674 case OMPC_DYN_GROUPPRIVATE_FALLBACK_abort:
10675 DynGPFallback = OMPDynGroupprivateFallbackType::Abort;
10677 case OMPC_DYN_GROUPPRIVATE_FALLBACK_null:
10678 DynGPFallback = OMPDynGroupprivateFallbackType::Null;
10680 case OMPC_DYN_GROUPPRIVATE_FALLBACK_default_mem:
10683 DynGPFallback = OMPDynGroupprivateFallbackType::DefaultMem;
10686 llvm_unreachable(
"Unknown fallback modifier for OpenMP dyn_groupprivate");
10688 }
else if (
auto *OMPXDynCGClause =
10691 llvm::Value *DynCGMemVal = CGF.
EmitScalarExpr(OMPXDynCGClause->getSize(),
10696 return {DynGP, DynGPFallback};
10702 llvm::OpenMPIRBuilder &OMPBuilder,
10704 MappableExprsHandler::MapCombinedInfoTy &CombinedInfo) {
10706 llvm::DenseMap<llvm::Value *, llvm::Value *> LambdaPointers;
10708 auto *CV = CapturedVars.begin();
10711 CI != CE; ++CI, ++RI, ++CV) {
10712 MappableExprsHandler::MapCombinedInfoTy CurInfo;
10717 CurInfo.Exprs.push_back(
nullptr);
10718 CurInfo.BasePointers.push_back(*CV);
10719 CurInfo.DevicePtrDecls.push_back(
nullptr);
10720 CurInfo.DevicePointers.push_back(
10721 MappableExprsHandler::DeviceInfoTy::None);
10722 CurInfo.Pointers.push_back(*CV);
10723 CurInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
10726 CurInfo.Types.push_back(OpenMPOffloadMappingFlags::OMP_MAP_LITERAL |
10727 OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM |
10728 OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT);
10729 CurInfo.Mappers.push_back(
nullptr);
10734 bool HasEntryWithCVAsAttachPtr =
false;
10736 HasEntryWithCVAsAttachPtr =
10737 MEHandler.hasAttachEntryForCapturedVar(CapturedVD);
10740 MappableExprsHandler::MapDataArrayTy DeclComponentLists;
10743 StorageForImplicitlyAddedComponentLists;
10744 MEHandler.populateComponentListsForNonLambdaCaptureFromClauses(
10745 CapturedVD, DeclComponentLists,
10746 StorageForImplicitlyAddedComponentLists);
10757 bool HasEntryWithoutAttachPtr =
10758 llvm::any_of(DeclComponentLists, [&](
const auto &MapData) {
10760 Components = std::get<0>(MapData);
10761 return !MEHandler.getAttachPtrExpr(Components);
10766 if (DeclComponentLists.empty() ||
10767 (!HasEntryWithCVAsAttachPtr && !HasEntryWithoutAttachPtr))
10768 MEHandler.generateDefaultMapInfo(*CI, **RI, *CV, CurInfo);
10772 MEHandler.generateInfoForCaptureFromClauseInfo(
10773 DeclComponentLists, CI, *CV, CurInfo, OMPBuilder,
10774 CombinedInfo.BasePointers.size());
10779 MappedVarSet.insert(
nullptr);
10784 MEHandler.generateInfoForLambdaCaptures(CI->
getCapturedVar(), *CV,
10785 CurInfo, LambdaPointers);
10788 assert(!CurInfo.BasePointers.empty() &&
10789 "Non-existing map pointer for capture!");
10790 assert(CurInfo.BasePointers.size() == CurInfo.Pointers.size() &&
10791 CurInfo.BasePointers.size() == CurInfo.Sizes.size() &&
10792 CurInfo.BasePointers.size() == CurInfo.Types.size() &&
10793 CurInfo.BasePointers.size() == CurInfo.Mappers.size() &&
10794 "Inconsistent map information sizes!");
10797 CombinedInfo.append(CurInfo);
10800 MEHandler.adjustMemberOfForLambdaCaptures(
10801 OMPBuilder, LambdaPointers, CombinedInfo.BasePointers,
10802 CombinedInfo.Pointers, CombinedInfo.Types);
10806 MappableExprsHandler::MapCombinedInfoTy &CombinedInfo,
10807 llvm::OpenMPIRBuilder &OMPBuilder,
10814 MEHandler.generateAllInfo(CombinedInfo, OMPBuilder, SkippedVarSet);
10816 auto FillInfoMap = [&](MappableExprsHandler::MappingExprInfo &MapExpr) {
10820 llvm::codegenoptions::NoDebugInfo) {
10821 CombinedInfo.Names.resize(CombinedInfo.Exprs.size());
10822 llvm::transform(CombinedInfo.Exprs, CombinedInfo.Names.begin(),
10830 llvm::OpenMPIRBuilder &OMPBuilder,
10831 MappableExprsHandler::MapCombinedInfoTy &CombinedInfo) {
10833 MappableExprsHandler MEHandler(D, CGF);
10834 llvm::DenseSet<CanonicalDeclPtr<const Decl>> MappedVarSet;
10837 MappedVarSet, CombinedInfo);
10838 genMapInfo(MEHandler, CGF, CombinedInfo, OMPBuilder, MappedVarSet);
10841template <
typename ClauseTy>
10846 const auto *
C = D.getSingleClause<ClauseTy>();
10847 assert(!
C->varlist_empty() &&
10848 "ompx_bare requires explicit num_teams and thread_limit");
10850 for (
auto *E :
C->varlist()) {
10862 llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier>
Device,
10864 llvm::Value *&MapTypesArray, llvm::Value *&MapNamesArray,
10869 llvm::OpenMPIRBuilder &OMPBuilder = OMPRuntime->
getOMPBuilder();
10872 MappableExprsHandler::MapCombinedInfoTy CombinedInfo;
10874 genMapInfo(D, CGF, CS, CapturedVars, OMPBuilder, CombinedInfo);
10888 MapTypesArray = Info.RTArgs.MapTypesArray;
10889 MapNamesArray = Info.RTArgs.MapNamesArray;
10891 auto &&ThenGen = [&OMPRuntime, OutlinedFn, &D, &CapturedVars,
10892 RequiresOuterTask, &CS, OffloadingMandatory,
Device,
10893 OutlinedFnID, &InputInfo, &MapTypesArray, &MapNamesArray,
10895 bool IsReverseOffloading =
Device.getInt() == OMPC_DEVICE_ancestor;
10897 if (IsReverseOffloading) {
10903 RequiresOuterTask, CS, OffloadingMandatory, CGF);
10907 bool HasNoWait = D.hasClausesOfKind<OMPNowaitClause>();
10908 unsigned NumTargetItems = InputInfo.NumberOfTargetItems;
10910 llvm::Value *BasePointersArray =
10911 InputInfo.BasePointersArray.emitRawPointer(CGF);
10912 llvm::Value *PointersArray = InputInfo.PointersArray.emitRawPointer(CGF);
10913 llvm::Value *SizesArray = InputInfo.SizesArray.emitRawPointer(CGF);
10914 llvm::Value *MappersArray = InputInfo.MappersArray.emitRawPointer(CGF);
10916 auto &&EmitTargetCallFallbackCB =
10917 [&OMPRuntime, OutlinedFn, &D, &CapturedVars, RequiresOuterTask, &CS,
10918 OffloadingMandatory, &CGF](llvm::OpenMPIRBuilder::InsertPointTy IP)
10919 -> llvm::OpenMPIRBuilder::InsertPointTy {
10922 RequiresOuterTask, CS, OffloadingMandatory, CGF);
10935 NumThreads.push_back(
10941 llvm::Value *NumIterations =
10944 llvm::OpenMPIRBuilder::InsertPointTy AllocaIP(
10947 llvm::OpenMPIRBuilder::TargetDataRTArgs RTArgs(
10948 BasePointersArray, PointersArray, SizesArray, MapTypesArray,
10949 nullptr , MappersArray, MapNamesArray);
10951 llvm::OpenMPIRBuilder::TargetKernelArgs Args(
10952 NumTargetItems, RTArgs, NumIterations, NumTeams, NumThreads,
10953 DynCGroupMem, HasNoWait, DynCGroupMemFallback);
10955 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
10957 CGF.
Builder, OutlinedFnID, EmitTargetCallFallbackCB, Args, DeviceID,
10959 CGF.
Builder.restoreIP(AfterIP);
10962 if (RequiresOuterTask)
10977 [&OMPRuntime, OutlinedFn, &D, &CapturedVars, RequiresOuterTask, &CS,
10980 RequiresOuterTask, CS, OffloadingMandatory, CGF);
10983 if (RequiresOuterTask) {
10993 llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID,
const Expr *IfCond,
10994 llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier>
Device,
11001 const bool OffloadingMandatory = !
CGM.getLangOpts().OpenMPIsTargetDevice &&
11002 CGM.getLangOpts().OpenMPOffloadMandatory;
11004 assert((OffloadingMandatory || OutlinedFn) &&
"Invalid outlined function!");
11006 const bool RequiresOuterTask =
11008 D.hasClausesOfKind<OMPNowaitClause>() ||
11009 D.hasClausesOfKind<OMPInReductionClause>() ||
11010 (
CGM.getLangOpts().OpenMP >= 51 &&
11014 const CapturedStmt &CS = *D.getCapturedStmt(OMPD_target);
11022 llvm::Value *MapTypesArray =
nullptr;
11023 llvm::Value *MapNamesArray =
nullptr;
11025 auto &&TargetThenGen = [
this, OutlinedFn, &D, &CapturedVars,
11026 RequiresOuterTask, &CS, OffloadingMandatory,
Device,
11027 OutlinedFnID, &InputInfo, &MapTypesArray,
11031 RequiresOuterTask, CS, OffloadingMandatory,
11032 Device, OutlinedFnID, InputInfo, MapTypesArray,
11033 MapNamesArray, SizeEmitter, CGF,
CGM);
11036 auto &&TargetElseGen =
11037 [
this, OutlinedFn, &D, &CapturedVars, RequiresOuterTask, &CS,
11040 CS, OffloadingMandatory, CGF);
11047 if (OutlinedFnID) {
11049 emitIfClause(CGF, IfCond, TargetThenGen, TargetElseGen);
11061 StringRef ParentName) {
11068 if (
auto *E = dyn_cast<OMPExecutableDirective>(S);
11077 bool RequiresDeviceCodegen =
11082 if (RequiresDeviceCodegen) {
11090 if (!
OMPBuilder.OffloadInfoManager.hasTargetRegionEntryInfo(EntryInfo))
11093 switch (E.getDirectiveKind()) {
11098 case OMPD_target_parallel:
11102 case OMPD_target_teams:
11106 case OMPD_target_teams_distribute:
11110 case OMPD_target_teams_distribute_simd:
11114 case OMPD_target_parallel_for:
11118 case OMPD_target_parallel_for_simd:
11122 case OMPD_target_simd:
11126 case OMPD_target_teams_distribute_parallel_for:
11131 case OMPD_target_teams_distribute_parallel_for_simd:
11137 case OMPD_target_teams_loop:
11141 case OMPD_target_parallel_loop:
11145 case OMPD_parallel:
11147 case OMPD_parallel_for:
11148 case OMPD_parallel_master:
11149 case OMPD_parallel_sections:
11150 case OMPD_for_simd:
11151 case OMPD_parallel_for_simd:
11153 case OMPD_cancellation_point:
11155 case OMPD_threadprivate:
11156 case OMPD_allocate:
11161 case OMPD_sections:
11165 case OMPD_critical:
11166 case OMPD_taskyield:
11168 case OMPD_taskwait:
11169 case OMPD_taskgroup:
11175 case OMPD_target_data:
11176 case OMPD_target_exit_data:
11177 case OMPD_target_enter_data:
11178 case OMPD_distribute:
11179 case OMPD_distribute_simd:
11180 case OMPD_distribute_parallel_for:
11181 case OMPD_distribute_parallel_for_simd:
11182 case OMPD_teams_distribute:
11183 case OMPD_teams_distribute_simd:
11184 case OMPD_teams_distribute_parallel_for:
11185 case OMPD_teams_distribute_parallel_for_simd:
11186 case OMPD_target_update:
11187 case OMPD_declare_simd:
11188 case OMPD_declare_variant:
11189 case OMPD_begin_declare_variant:
11190 case OMPD_end_declare_variant:
11191 case OMPD_declare_target:
11192 case OMPD_end_declare_target:
11193 case OMPD_declare_reduction:
11194 case OMPD_declare_mapper:
11195 case OMPD_taskloop:
11196 case OMPD_taskloop_simd:
11197 case OMPD_master_taskloop:
11198 case OMPD_master_taskloop_simd:
11199 case OMPD_parallel_master_taskloop:
11200 case OMPD_parallel_master_taskloop_simd:
11201 case OMPD_requires:
11202 case OMPD_metadirective:
11205 llvm_unreachable(
"Unknown target directive for OpenMP device codegen.");
11210 if (
const auto *E = dyn_cast<OMPExecutableDirective>(S)) {
11211 if (!E->hasAssociatedStmt() || !E->getAssociatedStmt())
11219 if (
const auto *L = dyn_cast<LambdaExpr>(S))
11228 std::optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
11229 OMPDeclareTargetDeclAttr::getDeviceType(VD);
11233 if (!IsDevice && DevTy == OMPDeclareTargetDeclAttr::DT_NoHost)
11236 if (IsDevice && DevTy == OMPDeclareTargetDeclAttr::DT_Host)
11244 if (!
CGM.getLangOpts().OpenMPIsTargetDevice) {
11245 if (
const auto *FD = dyn_cast<FunctionDecl>(GD.
getDecl()))
11247 CGM.getLangOpts().OpenMPIsTargetDevice))
11254 if (
const auto *FD = dyn_cast<FunctionDecl>(VD)) {
11255 StringRef Name =
CGM.getMangledName(GD);
11258 CGM.getLangOpts().OpenMPIsTargetDevice))
11263 return !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD) &&
11269 CGM.getLangOpts().OpenMPIsTargetDevice))
11272 if (!
CGM.getLangOpts().OpenMPIsTargetDevice)
11281 StringRef ParentName =
11286 StringRef ParentName =
11293 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
11294 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(
11296 if (!Res || *Res == OMPDeclareTargetDeclAttr::MT_Link ||
11297 ((*Res == OMPDeclareTargetDeclAttr::MT_To ||
11298 *Res == OMPDeclareTargetDeclAttr::MT_Enter) &&
11307 llvm::Constant *
Addr) {
11308 if (
CGM.getLangOpts().OMPTargetTriples.empty() &&
11309 !
CGM.getLangOpts().OpenMPIsTargetDevice)
11312 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
11313 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
11317 if (Res && *Res != OMPDeclareTargetDeclAttr::MT_Link &&
11322 if (
CGM.getLangOpts().OpenMPIsTargetDevice) {
11325 StringRef VarName =
CGM.getMangledName(VD);
11331 auto AddrOfGlobal = [&VD,
this]() {
return CGM.GetAddrOfGlobal(VD); };
11332 auto LinkageForVariable = [&VD,
this]() {
11333 return CGM.getLLVMLinkageVarDefinition(VD);
11336 std::vector<llvm::GlobalVariable *> GeneratedRefs;
11343 CGM.getMangledName(VD), GeneratedRefs,
CGM.getLangOpts().OpenMPSimd,
11344 CGM.getLangOpts().OMPTargetTriples, AddrOfGlobal, LinkageForVariable,
11345 CGM.getTypes().ConvertTypeForMem(
11346 CGM.getContext().getPointerType(VD->
getType())),
11349 for (
auto *ref : GeneratedRefs)
11350 CGM.addCompilerUsedGlobal(ref);
11363 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
11364 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
11367 if ((*Res == OMPDeclareTargetDeclAttr::MT_To ||
11368 *Res == OMPDeclareTargetDeclAttr::MT_Enter) &&
11370 CGM.EmitGlobal(VD);
11372 assert((*Res == OMPDeclareTargetDeclAttr::MT_Link ||
11373 ((*Res == OMPDeclareTargetDeclAttr::MT_To ||
11374 *Res == OMPDeclareTargetDeclAttr::MT_Enter) &&
11376 "Expected link clause or to clause with unified memory.");
11377 (void)
CGM.getOpenMPRuntime().getAddrOfDeclareTargetVar(VD);
11385 " Expected target-based directive.");
11390 if (Clause->getClauseKind() == OMPC_unified_shared_memory) {
11392 OMPBuilder.Config.setHasRequiresUnifiedSharedMemory(
true);
11393 }
else if (
const auto *AC =
11394 dyn_cast<OMPAtomicDefaultMemOrderClause>(Clause)) {
11395 switch (AC->getAtomicDefaultMemOrderKind()) {
11396 case OMPC_ATOMIC_DEFAULT_MEM_ORDER_acq_rel:
11399 case OMPC_ATOMIC_DEFAULT_MEM_ORDER_seq_cst:
11402 case OMPC_ATOMIC_DEFAULT_MEM_ORDER_relaxed:
11418 if (!VD || !VD->
hasAttr<OMPAllocateDeclAttr>())
11420 const auto *A = VD->
getAttr<OMPAllocateDeclAttr>();
11421 switch(A->getAllocatorType()) {
11422 case OMPAllocateDeclAttr::OMPNullMemAlloc:
11423 case OMPAllocateDeclAttr::OMPDefaultMemAlloc:
11425 case OMPAllocateDeclAttr::OMPLargeCapMemAlloc:
11426 case OMPAllocateDeclAttr::OMPCGroupMemAlloc:
11427 case OMPAllocateDeclAttr::OMPHighBWMemAlloc:
11428 case OMPAllocateDeclAttr::OMPLowLatMemAlloc:
11429 case OMPAllocateDeclAttr::OMPThreadMemAlloc:
11430 case OMPAllocateDeclAttr::OMPConstMemAlloc:
11431 case OMPAllocateDeclAttr::OMPPTeamMemAlloc:
11434 case OMPAllocateDeclAttr::OMPUserDefinedMemAlloc:
11435 llvm_unreachable(
"Expected predefined allocator for the variables with the "
11436 "static storage.");
11448 if (CGM.getLangOpts().OpenMPIsTargetDevice) {
11449 SavedShouldMarkAsGlobal = CGM.getOpenMPRuntime().ShouldMarkAsGlobal;
11450 CGM.getOpenMPRuntime().ShouldMarkAsGlobal = false;
11455 if (CGM.getLangOpts().OpenMPIsTargetDevice)
11456 CGM.getOpenMPRuntime().ShouldMarkAsGlobal = SavedShouldMarkAsGlobal;
11466 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(D)) {
11468 if (
auto *F = dyn_cast_or_null<llvm::Function>(
11469 CGM.GetGlobalValue(
CGM.getMangledName(GD))))
11470 return !F->isDeclaration();
11482 llvm::Function *OutlinedFn,
11491 llvm::Value *Args[] = {
11493 CGF.
Builder.getInt32(CapturedVars.size()),
11496 RealArgs.append(std::begin(Args), std::end(Args));
11497 RealArgs.append(CapturedVars.begin(), CapturedVars.end());
11499 llvm::FunctionCallee RTLFn =
OMPBuilder.getOrCreateRuntimeFunction(
11500 CGM.getModule(), OMPRTL___kmpc_fork_teams);
11505 const Expr *NumTeams,
11506 const Expr *ThreadLimit,
11513 llvm::Value *NumTeamsVal =
11519 llvm::Value *ThreadLimitVal =
11526 llvm::Value *PushNumTeamsArgs[] = {RTLoc,
getThreadID(CGF, Loc), NumTeamsVal,
11529 CGM.getModule(), OMPRTL___kmpc_push_num_teams),
11534 const Expr *ThreadLimit,
11537 llvm::Value *ThreadLimitVal =
11544 llvm::Value *ThreadLimitArgs[] = {RTLoc,
getThreadID(CGF, Loc),
11547 CGM.getModule(), OMPRTL___kmpc_set_thread_limit),
11562 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
11564 llvm::Value *IfCondVal =
nullptr;
11569 llvm::Value *DeviceID =
nullptr;
11574 DeviceID = CGF.
Builder.getInt64(OMP_DEVICEID_UNDEF);
11578 MappableExprsHandler::MapCombinedInfoTy CombinedInfo;
11579 auto GenMapInfoCB =
11580 [&](InsertPointTy CodeGenIP) -> llvm::OpenMPIRBuilder::MapInfosTy & {
11581 CGF.
Builder.restoreIP(CodeGenIP);
11583 MappableExprsHandler MEHandler(D, CGF);
11584 MEHandler.generateAllInfo(CombinedInfo,
OMPBuilder);
11586 auto FillInfoMap = [&](MappableExprsHandler::MappingExprInfo &MapExpr) {
11589 if (
CGM.getCodeGenOpts().getDebugInfo() !=
11590 llvm::codegenoptions::NoDebugInfo) {
11591 CombinedInfo.Names.resize(CombinedInfo.Exprs.size());
11592 llvm::transform(CombinedInfo.Exprs, CombinedInfo.Names.begin(),
11596 return CombinedInfo;
11598 using BodyGenTy = llvm::OpenMPIRBuilder::BodyGenTy;
11599 auto BodyCB = [&](InsertPointTy CodeGenIP, BodyGenTy BodyGenType) {
11600 CGF.
Builder.restoreIP(CodeGenIP);
11601 switch (BodyGenType) {
11602 case BodyGenTy::Priv:
11606 case BodyGenTy::DupNoPriv:
11608 CodeGen.setAction(NoPrivAction);
11612 case BodyGenTy::NoPriv:
11614 CodeGen.setAction(NoPrivAction);
11619 return InsertPointTy(CGF.
Builder.GetInsertBlock(),
11620 CGF.
Builder.GetInsertPoint());
11623 auto DeviceAddrCB = [&](
unsigned int I, llvm::Value *NewDecl) {
11624 if (
const ValueDecl *DevVD = CombinedInfo.DevicePtrDecls[I]) {
11629 auto CustomMapperCB = [&](
unsigned int I) {
11630 llvm::Function *MFunc =
nullptr;
11631 if (CombinedInfo.Mappers[I]) {
11632 Info.HasMapper =
true;
11644 InsertPointTy CodeGenIP(CGF.
Builder.GetInsertBlock(),
11645 CGF.
Builder.GetInsertPoint());
11646 llvm::OpenMPIRBuilder::LocationDescription OmpLoc(CodeGenIP);
11647 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
11649 OmpLoc, AllocaIP, CodeGenIP, DeviceID, IfCondVal, Info, GenMapInfoCB,
11651 nullptr, BodyCB, DeviceAddrCB, RTLoc));
11652 CGF.
Builder.restoreIP(AfterIP);
11664 "Expecting either target enter, exit data, or update directives.");
11667 llvm::Value *MapTypesArray =
nullptr;
11668 llvm::Value *MapNamesArray =
nullptr;
11670 auto &&ThenGen = [
this, &D,
Device, &InputInfo, &MapTypesArray,
11673 llvm::Value *DeviceID =
nullptr;
11678 DeviceID = CGF.
Builder.getInt64(OMP_DEVICEID_UNDEF);
11682 llvm::Constant *PointerNum =
11689 {RTLoc, DeviceID, PointerNum,
11697 const bool HasNowait = D.hasClausesOfKind<OMPNowaitClause>();
11698 RuntimeFunction RTLFn;
11699 switch (D.getDirectiveKind()) {
11700 case OMPD_target_enter_data:
11701 RTLFn = HasNowait ? OMPRTL___tgt_target_data_begin_nowait_mapper
11702 : OMPRTL___tgt_target_data_begin_mapper;
11704 case OMPD_target_exit_data:
11705 RTLFn = HasNowait ? OMPRTL___tgt_target_data_end_nowait_mapper
11706 : OMPRTL___tgt_target_data_end_mapper;
11708 case OMPD_target_update:
11709 RTLFn = HasNowait ? OMPRTL___tgt_target_data_update_nowait_mapper
11710 : OMPRTL___tgt_target_data_update_mapper;
11712 case OMPD_parallel:
11714 case OMPD_parallel_for:
11715 case OMPD_parallel_master:
11716 case OMPD_parallel_sections:
11717 case OMPD_for_simd:
11718 case OMPD_parallel_for_simd:
11720 case OMPD_cancellation_point:
11722 case OMPD_threadprivate:
11723 case OMPD_allocate:
11728 case OMPD_sections:
11732 case OMPD_critical:
11733 case OMPD_taskyield:
11735 case OMPD_taskwait:
11736 case OMPD_taskgroup:
11742 case OMPD_target_data:
11743 case OMPD_distribute:
11744 case OMPD_distribute_simd:
11745 case OMPD_distribute_parallel_for:
11746 case OMPD_distribute_parallel_for_simd:
11747 case OMPD_teams_distribute:
11748 case OMPD_teams_distribute_simd:
11749 case OMPD_teams_distribute_parallel_for:
11750 case OMPD_teams_distribute_parallel_for_simd:
11751 case OMPD_declare_simd:
11752 case OMPD_declare_variant:
11753 case OMPD_begin_declare_variant:
11754 case OMPD_end_declare_variant:
11755 case OMPD_declare_target:
11756 case OMPD_end_declare_target:
11757 case OMPD_declare_reduction:
11758 case OMPD_declare_mapper:
11759 case OMPD_taskloop:
11760 case OMPD_taskloop_simd:
11761 case OMPD_master_taskloop:
11762 case OMPD_master_taskloop_simd:
11763 case OMPD_parallel_master_taskloop:
11764 case OMPD_parallel_master_taskloop_simd:
11766 case OMPD_target_simd:
11767 case OMPD_target_teams_distribute:
11768 case OMPD_target_teams_distribute_simd:
11769 case OMPD_target_teams_distribute_parallel_for:
11770 case OMPD_target_teams_distribute_parallel_for_simd:
11771 case OMPD_target_teams:
11772 case OMPD_target_parallel:
11773 case OMPD_target_parallel_for:
11774 case OMPD_target_parallel_for_simd:
11775 case OMPD_requires:
11776 case OMPD_metadirective:
11779 llvm_unreachable(
"Unexpected standalone target data directive.");
11783 OffloadingArgs.push_back(llvm::Constant::getNullValue(CGF.
Int32Ty));
11784 OffloadingArgs.push_back(llvm::Constant::getNullValue(CGF.
VoidPtrTy));
11785 OffloadingArgs.push_back(llvm::Constant::getNullValue(CGF.
Int32Ty));
11786 OffloadingArgs.push_back(llvm::Constant::getNullValue(CGF.
VoidPtrTy));
11789 OMPBuilder.getOrCreateRuntimeFunction(
CGM.getModule(), RTLFn),
11793 auto &&TargetThenGen = [
this, &ThenGen, &D, &InputInfo, &MapTypesArray,
11797 MappableExprsHandler::MapCombinedInfoTy CombinedInfo;
11799 MappableExprsHandler MEHandler(D, CGF);
11805 D.hasClausesOfKind<OMPNowaitClause>();
11811 CGM.getPointerAlign());
11816 MapTypesArray = Info.RTArgs.MapTypesArray;
11817 MapNamesArray = Info.RTArgs.MapNamesArray;
11818 if (RequiresOuterTask)
11844struct ParamAttrTy {
11845 ParamKindTy Kind =
Vector;
11846 llvm::APSInt StrideOrArg;
11847 llvm::APSInt Alignment;
11848 bool HasVarStride =
false;
11881 unsigned Offset = 0;
11882 if (
const auto *MD = dyn_cast<CXXMethodDecl>(FD)) {
11883 if (ParamAttrs[Offset].Kind ==
Vector)
11884 CDT =
C.getPointerType(
C.getCanonicalTagType(MD->
getParent()));
11888 for (
unsigned I = 0, E = FD->
getNumParams(); I < E; ++I) {
11889 if (ParamAttrs[I + Offset].Kind ==
Vector) {
11901 return C.getTypeSize(CDT);
11909 llvm::raw_svector_ostream Out(Buffer);
11910 for (
const auto &ParamAttr : ParamAttrs) {
11911 switch (ParamAttr.Kind) {
11931 if (ParamAttr.HasVarStride)
11932 Out <<
"s" << ParamAttr.StrideOrArg;
11933 else if (ParamAttr.Kind == Linear || ParamAttr.Kind == LinearRef ||
11934 ParamAttr.Kind == LinearUVal || ParamAttr.Kind == LinearVal) {
11937 if (ParamAttr.StrideOrArg < 0)
11938 Out <<
'n' << -ParamAttr.StrideOrArg;
11939 else if (ParamAttr.StrideOrArg != 1)
11940 Out << ParamAttr.StrideOrArg;
11943 if (!!ParamAttr.Alignment)
11944 Out <<
'a' << ParamAttr.Alignment;
11947 return std::string(Out.str());
11952 const llvm::APSInt &VLENVal,
11954 OMPDeclareSimdDeclAttr::BranchStateTy State) {
11957 unsigned VecRegSize;
11959 ISADataTy ISAData[] = {
11975 case OMPDeclareSimdDeclAttr::BS_Undefined:
11976 Masked.push_back(
'N');
11977 Masked.push_back(
'M');
11979 case OMPDeclareSimdDeclAttr::BS_Notinbranch:
11980 Masked.push_back(
'N');
11982 case OMPDeclareSimdDeclAttr::BS_Inbranch:
11983 Masked.push_back(
'M');
11986 for (
char Mask : Masked) {
11987 for (
const ISADataTy &
Data : ISAData) {
11989 llvm::raw_svector_ostream Out(Buffer);
11990 Out <<
"_ZGV" <<
Data.ISA << Mask;
11993 assert(NumElts &&
"Non-zero simdlen/cdtsize expected");
11994 Out << llvm::APSInt::getUnsigned(
Data.VecRegSize / NumElts);
11999 Out <<
'_' << Fn->getName();
12000 Fn->addFnAttr(Out.str());
12018 if (Kind == ParamKindTy::Uniform)
12021 if (Kind == ParamKindTy::LinearUVal || Kind == ParamKindTy::LinearRef)
12024 if ((Kind == ParamKindTy::Linear || Kind == ParamKindTy::LinearVal) &&
12034 unsigned Size =
C.getTypeSize(QT);
12037 if (Size != 8 && Size != 16 && Size != 32 && Size != 64 && Size != 128)
12061 return C.getTypeSize(PTy);
12064 return C.getTypeSize(QT);
12066 return C.getTypeSize(
C.getUIntPtrType());
12072static std::tuple<unsigned, unsigned, bool>
12078 bool OutputBecomesInput =
false;
12082 Sizes.push_back(
getAArch64LS(RetType, ParamKindTy::Vector,
C));
12084 OutputBecomesInput =
true;
12086 for (
unsigned I = 0, E = FD->
getNumParams(); I < E; ++I) {
12091 assert(!Sizes.empty() &&
"Unable to determine NDS and WDS.");
12094 assert(llvm::all_of(Sizes,
12095 [](
unsigned Size) {
12096 return Size == 8 || Size == 16 || Size == 32 ||
12097 Size == 64 || Size == 128;
12101 return std::make_tuple(*llvm::min_element(Sizes), *llvm::max_element(Sizes),
12102 OutputBecomesInput);
12108template <
typename T>
12110 char ISA, StringRef ParSeq,
12111 StringRef MangledName,
bool OutputBecomesInput,
12112 llvm::Function *Fn) {
12114 llvm::raw_svector_ostream Out(Buffer);
12115 Out << Prefix << ISA << LMask << VLEN;
12116 if (OutputBecomesInput)
12118 Out << ParSeq <<
"_" << MangledName;
12119 Fn->addFnAttr(Out.str());
12125 StringRef Prefix,
char ISA,
12126 StringRef ParSeq, StringRef MangledName,
12127 bool OutputBecomesInput,
12128 llvm::Function *Fn) {
12132 OutputBecomesInput, Fn);
12134 OutputBecomesInput, Fn);
12138 OutputBecomesInput, Fn);
12140 OutputBecomesInput, Fn);
12144 OutputBecomesInput, Fn);
12146 OutputBecomesInput, Fn);
12151 OutputBecomesInput, Fn);
12154 llvm_unreachable(
"Scalar type is too wide.");
12162 OMPDeclareSimdDeclAttr::BranchStateTy State, StringRef MangledName,
12163 char ISA,
unsigned VecRegSize, llvm::Function *Fn,
SourceLocation SLoc) {
12167 const unsigned NDS = std::get<0>(
Data);
12168 const unsigned WDS = std::get<1>(
Data);
12169 const bool OutputBecomesInput = std::get<2>(
Data);
12173 if (UserVLEN == 1) {
12180 if (ISA ==
'n' && UserVLEN && !llvm::isPowerOf2_32(UserVLEN)) {
12187 if (ISA ==
's' && UserVLEN != 0) {
12188 if ((UserVLEN * WDS > 2048) || (UserVLEN * WDS % 128 != 0)) {
12196 StringRef Prefix =
"_ZGV";
12202 OutputBecomesInput, Fn);
12204 assert(ISA ==
'n' &&
"Expected ISA either 's' or 'n'.");
12208 case OMPDeclareSimdDeclAttr::BS_Undefined:
12210 OutputBecomesInput, Fn);
12212 OutputBecomesInput, Fn);
12214 case OMPDeclareSimdDeclAttr::BS_Notinbranch:
12216 OutputBecomesInput, Fn);
12218 case OMPDeclareSimdDeclAttr::BS_Inbranch:
12220 OutputBecomesInput, Fn);
12230 OutputBecomesInput, Fn);
12232 assert(ISA ==
'n' &&
"Expected ISA either 's' or 'n'.");
12237 case OMPDeclareSimdDeclAttr::BS_Undefined:
12239 OutputBecomesInput, Fn);
12241 OutputBecomesInput, Fn);
12243 case OMPDeclareSimdDeclAttr::BS_Notinbranch:
12245 OutputBecomesInput, Fn);
12247 case OMPDeclareSimdDeclAttr::BS_Inbranch:
12249 OutputBecomesInput, Fn);
12257 llvm::Function *Fn) {
12262 llvm::DenseMap<const Decl *, unsigned> ParamPositions;
12264 ParamPositions.try_emplace(FD, 0);
12265 unsigned ParamPos = ParamPositions.size();
12267 ParamPositions.try_emplace(P->getCanonicalDecl(), ParamPos);
12273 for (
const Expr *E :
Attr->uniforms()) {
12277 Pos = ParamPositions[FD];
12280 ->getCanonicalDecl();
12281 auto It = ParamPositions.find(PVD);
12282 assert(It != ParamPositions.end() &&
"Function parameter not found");
12285 ParamAttrs[Pos].Kind = Uniform;
12288 auto *NI =
Attr->alignments_begin();
12289 for (
const Expr *E :
Attr->aligneds()) {
12294 Pos = ParamPositions[FD];
12298 ->getCanonicalDecl();
12299 auto It = ParamPositions.find(PVD);
12300 assert(It != ParamPositions.end() &&
"Function parameter not found");
12302 ParmTy = PVD->getType();
12304 ParamAttrs[Pos].Alignment =
12306 ? (*NI)->EvaluateKnownConstInt(
C)
12307 : llvm::APSInt::getUnsigned(
12308 C.toCharUnitsFromBits(
C.getOpenMPDefaultSimdAlign(ParmTy))
12313 auto *SI =
Attr->steps_begin();
12314 auto *MI =
Attr->modifiers_begin();
12315 for (
const Expr *E :
Attr->linears()) {
12318 bool IsReferenceType =
false;
12321 unsigned PtrRescalingFactor = 1;
12323 Pos = ParamPositions[FD];
12325 PtrRescalingFactor =
CGM.getContext()
12326 .getTypeSizeInChars(P->getPointeeType())
12330 ->getCanonicalDecl();
12331 auto It = ParamPositions.find(PVD);
12332 assert(It != ParamPositions.end() &&
"Function parameter not found");
12334 if (
auto *P = dyn_cast<PointerType>(PVD->getType()))
12335 PtrRescalingFactor =
CGM.getContext()
12336 .getTypeSizeInChars(P->getPointeeType())
12338 else if (PVD->getType()->isReferenceType()) {
12339 IsReferenceType =
true;
12340 PtrRescalingFactor =
12342 .getTypeSizeInChars(PVD->getType().getNonReferenceType())
12346 ParamAttrTy &ParamAttr = ParamAttrs[Pos];
12347 if (*MI == OMPC_LINEAR_ref)
12348 ParamAttr.Kind = LinearRef;
12349 else if (*MI == OMPC_LINEAR_uval)
12350 ParamAttr.Kind = LinearUVal;
12351 else if (IsReferenceType)
12352 ParamAttr.Kind = LinearVal;
12354 ParamAttr.Kind = Linear;
12356 ParamAttr.StrideOrArg = llvm::APSInt::getUnsigned(1);
12360 if (
const auto *DRE =
12362 if (
const auto *StridePVD =
12363 dyn_cast<ParmVarDecl>(DRE->getDecl())) {
12364 ParamAttr.HasVarStride =
true;
12365 auto It = ParamPositions.find(StridePVD->getCanonicalDecl());
12366 assert(It != ParamPositions.end() &&
12367 "Function parameter not found");
12368 ParamAttr.StrideOrArg = llvm::APSInt::getUnsigned(It->second);
12372 ParamAttr.StrideOrArg =
Result.Val.getInt();
12378 if (!ParamAttr.HasVarStride &&
12379 (ParamAttr.Kind == Linear || ParamAttr.Kind == LinearRef))
12380 ParamAttr.StrideOrArg = ParamAttr.StrideOrArg * PtrRescalingFactor;
12384 llvm::APSInt VLENVal;
12386 const Expr *VLENExpr =
Attr->getSimdlen();
12391 OMPDeclareSimdDeclAttr::BranchStateTy State =
Attr->getBranchState();
12392 if (
CGM.getTriple().isX86()) {
12394 }
else if (
CGM.getTriple().getArch() == llvm::Triple::aarch64) {
12395 unsigned VLEN = VLENVal.getExtValue();
12396 StringRef MangledName = Fn->getName();
12397 if (
CGM.getTarget().hasFeature(
"sve"))
12399 MangledName,
's', 128, Fn, ExprLoc);
12400 else if (
CGM.getTarget().hasFeature(
"neon"))
12402 MangledName,
'n', 128, Fn, ExprLoc);
12411class DoacrossCleanupTy final :
public EHScopeStack::Cleanup {
12413 static const int DoacrossFinArgs = 2;
12416 llvm::FunctionCallee RTLFn;
12417 llvm::Value *Args[DoacrossFinArgs];
12420 DoacrossCleanupTy(llvm::FunctionCallee RTLFn,
12423 assert(CallArgs.size() == DoacrossFinArgs);
12424 std::copy(CallArgs.begin(), CallArgs.end(), std::begin(Args));
12441 QualType Int64Ty =
C.getIntTypeForBitwidth(64,
true);
12449 RD =
C.buildImplicitRecord(
"kmp_dim");
12457 RD =
KmpDimTy->castAsRecordDecl();
12459 llvm::APInt Size(32, NumIterations.size());
12465 enum { LowerFD = 0, UpperFD, StrideFD };
12467 for (
unsigned I = 0, E = NumIterations.size(); I < E; ++I) {
12472 DimsLVal, *std::next(RD->
field_begin(), UpperFD));
12474 CGF.
EmitScalarExpr(NumIterations[I]), NumIterations[I]->getType(),
12475 Int64Ty, NumIterations[I]->getExprLoc());
12479 DimsLVal, *std::next(RD->
field_begin(), StrideFD));
12486 llvm::Value *Args[] = {
12489 llvm::ConstantInt::getSigned(
CGM.Int32Ty, NumIterations.size()),
12494 llvm::FunctionCallee RTLFn =
OMPBuilder.getOrCreateRuntimeFunction(
12495 CGM.getModule(), OMPRTL___kmpc_doacross_init);
12497 llvm::Value *FiniArgs[DoacrossCleanupTy::DoacrossFinArgs] = {
12499 llvm::FunctionCallee FiniRTLFn =
OMPBuilder.getOrCreateRuntimeFunction(
12500 CGM.getModule(), OMPRTL___kmpc_doacross_fini);
12505template <
typename T>
12507 const T *
C, llvm::Value *ULoc,
12508 llvm::Value *ThreadID) {
12511 llvm::APInt Size(32,
C->getNumLoops());
12515 for (
unsigned I = 0, E =
C->getNumLoops(); I < E; ++I) {
12516 const Expr *CounterVal =
C->getLoopData(I);
12517 assert(CounterVal);
12524 llvm::Value *Args[] = {
12527 llvm::FunctionCallee RTLFn;
12529 OMPDoacrossKind<T> ODK;
12530 if (ODK.isSource(
C)) {
12532 OMPRTL___kmpc_doacross_post);
12534 assert(ODK.isSink(
C) &&
"Expect sink modifier.");
12536 OMPRTL___kmpc_doacross_wait);
12556 llvm::FunctionCallee Callee,
12558 assert(Loc.
isValid() &&
"Outlined function call location must be valid.");
12561 if (
auto *Fn = dyn_cast<llvm::Function>(Callee.getCallee())) {
12562 if (Fn->doesNotThrow()) {
12573 emitCall(CGF, Loc, OutlinedFn, Args);
12577 if (
const auto *FD = dyn_cast<FunctionDecl>(D))
12578 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(FD))
12584 const VarDecl *TargetParam)
const {
12591 const Expr *Allocator) {
12592 llvm::Value *AllocVal;
12602 AllocVal = llvm::Constant::getNullValue(
12612 if (!AllocateAlignment)
12615 return llvm::ConstantInt::get(
CGM.
SizeTy, AllocateAlignment->getQuantity());
12628 auto I = UntiedData.find(VD);
12629 if (I != UntiedData.end()) {
12630 UntiedAddr = I->second.first;
12631 UntiedRealAddr = I->second.second;
12635 if (CVD->
hasAttr<OMPAllocateDeclAttr>()) {
12644 Size = CGF.
Builder.CreateNUWAdd(
12646 Size = CGF.
Builder.CreateUDiv(Size,
CGM.getSize(Align));
12647 Size = CGF.
Builder.CreateNUWMul(Size,
CGM.getSize(Align));
12653 const auto *AA = CVD->
getAttr<OMPAllocateDeclAttr>();
12654 const Expr *Allocator = AA->getAllocator();
12658 Args.push_back(ThreadID);
12660 Args.push_back(Alignment);
12661 Args.push_back(Size);
12662 Args.push_back(AllocVal);
12663 llvm::omp::RuntimeFunction FnID =
12664 Alignment ? OMPRTL___kmpc_aligned_alloc : OMPRTL___kmpc_alloc;
12666 OMPBuilder.getOrCreateRuntimeFunction(
CGM.getModule(), FnID), Args,
12668 llvm::FunctionCallee FiniRTLFn =
OMPBuilder.getOrCreateRuntimeFunction(
12669 CGM.getModule(), OMPRTL___kmpc_free);
12677 class OMPAllocateCleanupTy final :
public EHScopeStack::Cleanup {
12678 llvm::FunctionCallee RTLFn;
12681 const Expr *AllocExpr;
12684 OMPAllocateCleanupTy(llvm::FunctionCallee RTLFn,
12686 const Expr *AllocExpr)
12687 : RTLFn(RTLFn), LocEncoding(LocEncoding),
Addr(
Addr),
12688 AllocExpr(AllocExpr) {}
12692 llvm::Value *Args[3];
12698 Args[2] = AllocVal;
12706 CGF.
EHStack.pushCleanup<OMPAllocateCleanupTy>(
12708 VDAddr, Allocator);
12709 if (UntiedRealAddr.
isValid())
12712 Region->emitUntiedSwitch(CGF);
12729 assert(CGM.getLangOpts().OpenMP &&
"Not in OpenMP mode.");
12733 CGM.getOpenMPRuntime().NontemporalDeclsStack.emplace_back();
12735 for (
const Stmt *Ref :
C->private_refs()) {
12736 const auto *SimpleRefExpr =
cast<Expr>(Ref)->IgnoreParenImpCasts();
12738 if (
const auto *DRE = dyn_cast<DeclRefExpr>(SimpleRefExpr)) {
12739 VD = DRE->getDecl();
12742 assert((ME->isImplicitCXXThis() ||
12744 "Expected member of current class.");
12745 VD = ME->getMemberDecl();
12755 CGM.getOpenMPRuntime().NontemporalDeclsStack.pop_back();
12761 std::pair<Address, Address>> &LocalVars)
12762 : CGM(CGF.CGM), NeedToPush(!LocalVars.empty()) {
12766 CGF.
CurFn, CGM.getOpenMPRuntime().UntiedLocalVarsStack.size());
12767 CGM.getOpenMPRuntime().UntiedLocalVarsStack.push_back(LocalVars);
12773 CGM.getOpenMPRuntime().UntiedLocalVarsStack.pop_back();
12777 assert(
CGM.getLangOpts().OpenMP &&
"Not in OpenMP mode.");
12779 return llvm::any_of(
12780 CGM.getOpenMPRuntime().NontemporalDeclsStack,
12784void CGOpenMPRuntime::LastprivateConditionalRAII::tryToDisableInnerAnalysis(
12788 llvm::DenseSet<CanonicalDeclPtr<const Decl>> NeedToCheckForLPCs;
12794 const CapturedStmt *CS = S.getCapturedStmt(CaptureRegions.front());
12801 for (
const auto *
C : S.getClausesOfKind<OMPPrivateClause>()) {
12802 for (
const Expr *Ref :
C->varlist()) {
12803 if (!Ref->getType()->isScalarType())
12805 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
12808 NeedToCheckForLPCs.insert(DRE->getDecl());
12811 for (
const auto *
C : S.getClausesOfKind<OMPFirstprivateClause>()) {
12812 for (
const Expr *Ref :
C->varlist()) {
12813 if (!Ref->getType()->isScalarType())
12815 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
12818 NeedToCheckForLPCs.insert(DRE->getDecl());
12821 for (
const auto *
C : S.getClausesOfKind<OMPLastprivateClause>()) {
12822 for (
const Expr *Ref :
C->varlist()) {
12823 if (!Ref->getType()->isScalarType())
12825 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
12828 NeedToCheckForLPCs.insert(DRE->getDecl());
12831 for (
const auto *
C : S.getClausesOfKind<OMPReductionClause>()) {
12832 for (
const Expr *Ref :
C->varlist()) {
12833 if (!Ref->getType()->isScalarType())
12835 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
12838 NeedToCheckForLPCs.insert(DRE->getDecl());
12841 for (
const auto *
C : S.getClausesOfKind<OMPLinearClause>()) {
12842 for (
const Expr *Ref :
C->varlist()) {
12843 if (!Ref->getType()->isScalarType())
12845 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
12848 NeedToCheckForLPCs.insert(DRE->getDecl());
12851 for (
const Decl *VD : NeedToCheckForLPCs) {
12853 llvm::reverse(
CGM.getOpenMPRuntime().LastprivateConditionalStack)) {
12854 if (
Data.DeclToUniqueName.count(VD) > 0) {
12855 if (!
Data.Disabled)
12856 NeedToAddForLPCsAsDisabled.insert(VD);
12863CGOpenMPRuntime::LastprivateConditionalRAII::LastprivateConditionalRAII(
12866 Action((CGM.getLangOpts().OpenMP >= 50 &&
12867 llvm::any_of(S.getClausesOfKind<OMPLastprivateClause>(),
12868 [](const OMPLastprivateClause *
C) {
12869 return C->getKind() ==
12870 OMPC_LASTPRIVATE_conditional;
12872 ? ActionToDo::PushAsLastprivateConditional
12873 : ActionToDo::DoNotPush) {
12874 assert(
CGM.getLangOpts().OpenMP &&
"Not in OpenMP mode.");
12875 if (
CGM.getLangOpts().OpenMP < 50 || Action == ActionToDo::DoNotPush)
12877 assert(Action == ActionToDo::PushAsLastprivateConditional &&
12878 "Expected a push action.");
12880 CGM.getOpenMPRuntime().LastprivateConditionalStack.emplace_back();
12881 for (
const auto *
C : S.getClausesOfKind<OMPLastprivateClause>()) {
12882 if (
C->getKind() != OMPC_LASTPRIVATE_conditional)
12885 for (
const Expr *Ref :
C->varlist()) {
12886 Data.DeclToUniqueName.insert(std::make_pair(
12891 Data.IVLVal = IVLVal;
12895CGOpenMPRuntime::LastprivateConditionalRAII::LastprivateConditionalRAII(
12897 :
CGM(CGF.
CGM), Action(ActionToDo::DoNotPush) {
12901 llvm::DenseSet<CanonicalDeclPtr<const Decl>> NeedToAddForLPCsAsDisabled;
12902 tryToDisableInnerAnalysis(S, NeedToAddForLPCsAsDisabled);
12903 if (!NeedToAddForLPCsAsDisabled.empty()) {
12904 Action = ActionToDo::DisableLastprivateConditional;
12905 LastprivateConditionalData &
Data =
12907 for (
const Decl *VD : NeedToAddForLPCsAsDisabled)
12908 Data.DeclToUniqueName.try_emplace(VD);
12910 Data.Disabled =
true;
12914CGOpenMPRuntime::LastprivateConditionalRAII
12917 return LastprivateConditionalRAII(CGF, S);
12921 if (CGM.getLangOpts().OpenMP < 50)
12923 if (Action == ActionToDo::DisableLastprivateConditional) {
12924 assert(CGM.getOpenMPRuntime().LastprivateConditionalStack.back().Disabled &&
12925 "Expected list of disabled private vars.");
12926 CGM.getOpenMPRuntime().LastprivateConditionalStack.pop_back();
12928 if (Action == ActionToDo::PushAsLastprivateConditional) {
12930 !CGM.getOpenMPRuntime().LastprivateConditionalStack.back().Disabled &&
12931 "Expected list of lastprivate conditional vars.");
12932 CGM.getOpenMPRuntime().LastprivateConditionalStack.pop_back();
12944 auto VI = I->getSecond().find(VD);
12945 if (VI == I->getSecond().end()) {
12946 RecordDecl *RD =
C.buildImplicitRecord(
"lasprivate.conditional");
12951 NewType =
C.getCanonicalTagType(RD);
12954 I->getSecond().try_emplace(VD, NewType, VDField, FiredField, BaseLVal);
12956 NewType = std::get<0>(VI->getSecond());
12957 VDField = std::get<1>(VI->getSecond());
12958 FiredField = std::get<2>(VI->getSecond());
12959 BaseLVal = std::get<3>(VI->getSecond());
12971class LastprivateConditionalRefChecker final
12974 const Expr *FoundE =
nullptr;
12975 const Decl *FoundD =
nullptr;
12976 StringRef UniqueDeclName;
12978 llvm::Function *FoundFn =
nullptr;
12984 llvm::reverse(LPM)) {
12985 auto It = D.DeclToUniqueName.find(E->
getDecl());
12986 if (It == D.DeclToUniqueName.end())
12992 UniqueDeclName = It->second;
12997 return FoundE == E;
13003 llvm::reverse(LPM)) {
13005 if (It == D.DeclToUniqueName.end())
13011 UniqueDeclName = It->second;
13016 return FoundE == E;
13018 bool VisitStmt(
const Stmt *S) {
13019 for (
const Stmt *Child : S->
children()) {
13022 if (
const auto *E = dyn_cast<Expr>(Child))
13030 explicit LastprivateConditionalRefChecker(
13031 ArrayRef<CGOpenMPRuntime::LastprivateConditionalData> LPM)
13033 std::tuple<const Expr *, const Decl *, StringRef, LValue, llvm::Function *>
13034 getFoundData()
const {
13035 return std::make_tuple(FoundE, FoundD, UniqueDeclName, IVLVal, FoundFn);
13042 StringRef UniqueDeclName,
13048 llvm::Constant *LastIV =
OMPBuilder.getOrCreateInternalVariable(
13049 LLIVTy,
getName({UniqueDeclName,
"iv"}));
13057 llvm::GlobalVariable *
Last =
OMPBuilder.getOrCreateInternalVariable(
13073 auto &&
CodeGen = [&LastIVLVal, &IVLVal, IVVal, &LVal, &LastLVal,
13079 llvm::Value *CmpRes;
13081 CmpRes = CGF.
Builder.CreateICmpSLE(LastIVVal, IVVal);
13084 "Loop iteration variable must be integer.");
13085 CmpRes = CGF.
Builder.CreateICmpULE(LastIVVal, IVVal);
13089 CGF.
Builder.CreateCondBr(CmpRes, ThenBB, ExitBB);
13110 "Aggregates are not supported in lastprivate conditional.");
13119 if (
CGM.getLangOpts().OpenMPSimd) {
13133 if (!Checker.Visit(LHS))
13135 const Expr *FoundE;
13136 const Decl *FoundD;
13137 StringRef UniqueDeclName;
13139 llvm::Function *FoundFn;
13140 std::tie(FoundE, FoundD, UniqueDeclName, IVLVal, FoundFn) =
13141 Checker.getFoundData();
13142 if (FoundFn != CGF.
CurFn) {
13147 "Lastprivate conditional is not found in outer region.");
13148 QualType StructTy = std::get<0>(It->getSecond());
13149 const FieldDecl* FiredDecl = std::get<2>(It->getSecond());
13160 FiredLVal, llvm::AtomicOrdering::Unordered,
13178 auto It = llvm::find_if(
13180 if (It == Range.end() || It->Fn != CGF.
CurFn)
13184 "Lastprivates must be registered already.");
13187 const CapturedStmt *CS = D.getCapturedStmt(CaptureRegions.back());
13188 for (
const auto &Pair : It->DeclToUniqueName) {
13189 const auto *VD =
cast<VarDecl>(Pair.first->getCanonicalDecl());
13192 auto I = LPCI->getSecond().find(Pair.first);
13193 assert(I != LPCI->getSecond().end() &&
13194 "Lastprivate must be rehistered already.");
13196 LValue BaseLVal = std::get<3>(I->getSecond());
13200 llvm::Value *
Cmp = CGF.
Builder.CreateIsNotNull(Res);
13204 CGF.
Builder.CreateCondBr(
Cmp, ThenBB, DoneBB);
13229 "Unknown lastprivate conditional variable.");
13230 StringRef UniqueName = It->second;
13231 llvm::GlobalVariable *GV =
CGM.getModule().getNamedGlobal(UniqueName);
13245 llvm_unreachable(
"Not supported in SIMD-only mode");
13252 llvm_unreachable(
"Not supported in SIMD-only mode");
13259 bool Tied,
unsigned &NumberOfParts) {
13260 llvm_unreachable(
"Not supported in SIMD-only mode");
13268 llvm_unreachable(
"Not supported in SIMD-only mode");
13274 const Expr *Hint) {
13275 llvm_unreachable(
"Not supported in SIMD-only mode");
13281 llvm_unreachable(
"Not supported in SIMD-only mode");
13287 const Expr *Filter) {
13288 llvm_unreachable(
"Not supported in SIMD-only mode");
13293 llvm_unreachable(
"Not supported in SIMD-only mode");
13299 llvm_unreachable(
"Not supported in SIMD-only mode");
13307 llvm_unreachable(
"Not supported in SIMD-only mode");
13314 llvm_unreachable(
"Not supported in SIMD-only mode");
13321 bool ForceSimpleCall) {
13322 llvm_unreachable(
"Not supported in SIMD-only mode");
13329 llvm_unreachable(
"Not supported in SIMD-only mode");
13334 llvm_unreachable(
"Not supported in SIMD-only mode");
13340 llvm_unreachable(
"Not supported in SIMD-only mode");
13346 llvm_unreachable(
"Not supported in SIMD-only mode");
13353 llvm_unreachable(
"Not supported in SIMD-only mode");
13359 llvm_unreachable(
"Not supported in SIMD-only mode");
13364 unsigned IVSize,
bool IVSigned,
13367 llvm_unreachable(
"Not supported in SIMD-only mode");
13375 llvm_unreachable(
"Not supported in SIMD-only mode");
13379 ProcBindKind ProcBind,
13381 llvm_unreachable(
"Not supported in SIMD-only mode");
13388 llvm_unreachable(
"Not supported in SIMD-only mode");
13394 llvm_unreachable(
"Not supported in SIMD-only mode");
13399 llvm_unreachable(
"Not supported in SIMD-only mode");
13405 llvm::AtomicOrdering AO) {
13406 llvm_unreachable(
"Not supported in SIMD-only mode");
13411 llvm::Function *TaskFunction,
13413 const Expr *IfCond,
13415 llvm_unreachable(
"Not supported in SIMD-only mode");
13422 llvm_unreachable(
"Not supported in SIMD-only mode");
13429 assert(Options.
SimpleReduction &&
"Only simple reduction is expected.");
13431 ReductionOps, Options);
13437 llvm_unreachable(
"Not supported in SIMD-only mode");
13442 bool IsWorksharingReduction) {
13443 llvm_unreachable(
"Not supported in SIMD-only mode");
13450 llvm_unreachable(
"Not supported in SIMD-only mode");
13455 llvm::Value *ReductionsPtr,
13457 llvm_unreachable(
"Not supported in SIMD-only mode");
13463 llvm_unreachable(
"Not supported in SIMD-only mode");
13469 llvm_unreachable(
"Not supported in SIMD-only mode");
13475 llvm_unreachable(
"Not supported in SIMD-only mode");
13480 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
13482 llvm_unreachable(
"Not supported in SIMD-only mode");
13487 llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID,
const Expr *IfCond,
13488 llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier>
Device,
13492 llvm_unreachable(
"Not supported in SIMD-only mode");
13496 llvm_unreachable(
"Not supported in SIMD-only mode");
13500 llvm_unreachable(
"Not supported in SIMD-only mode");
13510 llvm::Function *OutlinedFn,
13512 llvm_unreachable(
"Not supported in SIMD-only mode");
13516 const Expr *NumTeams,
13517 const Expr *ThreadLimit,
13519 llvm_unreachable(
"Not supported in SIMD-only mode");
13526 llvm_unreachable(
"Not supported in SIMD-only mode");
13532 llvm_unreachable(
"Not supported in SIMD-only mode");
13538 llvm_unreachable(
"Not supported in SIMD-only mode");
13543 llvm_unreachable(
"Not supported in SIMD-only mode");
13548 llvm_unreachable(
"Not supported in SIMD-only mode");
13553 const VarDecl *NativeParam)
const {
13554 llvm_unreachable(
"Not supported in SIMD-only mode");
13560 const VarDecl *TargetParam)
const {
13561 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 ...
std::string SampleProfileFile
Name of the profile file to use with -fprofile-sample-use.
Like RawAddress, an abstract representation of an aligned address, but the pointer contained in this ...
llvm::Value * emitRawPointer(CodeGenFunction &CGF) const
Return the pointer contained in this class after authenticating it and adding offset to it if necessa...
CharUnits getAlignment() const
llvm::Type * getElementType() const
Return the type of the values stored in this address.
Address withPointer(llvm::Value *NewPointer, KnownNonNull_t IsKnownNonNull) const
Return address with different pointer, but same element type and alignment.
Address withElementType(llvm::Type *ElemTy) const
Return address with different element type, but same pointer and alignment.
llvm::PointerType * getType() const
Return the type of the pointer value.
static ApplyDebugLocation CreateArtificial(CodeGenFunction &CGF)
Apply TemporaryLocation if it is valid.
static ApplyDebugLocation CreateDefaultArtificial(CodeGenFunction &CGF, SourceLocation TemporaryLocation)
Apply TemporaryLocation if it is valid.
static ApplyDebugLocation CreateEmpty(CodeGenFunction &CGF)
Set the IRBuilder to not attach debug locations.
llvm::StoreInst * CreateStore(llvm::Value *Val, Address Addr, bool IsVolatile=false)
Address CreateGEP(CodeGenFunction &CGF, Address Addr, llvm::Value *Index, const llvm::Twine &Name="")
Address CreatePointerBitCastOrAddrSpaceCast(Address Addr, llvm::Type *Ty, llvm::Type *ElementTy, const llvm::Twine &Name="")
Address CreateConstArrayGEP(Address Addr, uint64_t Index, const llvm::Twine &Name="")
Given addr = [n x T]* ... produce name = getelementptr inbounds addr, i64 0, i64 index where i64 is a...
llvm::LoadInst * CreateLoad(Address Addr, const llvm::Twine &Name="")
llvm::CallInst * CreateMemCpy(Address Dest, Address Src, llvm::Value *Size, bool IsVolatile=false)
Address CreateConstGEP(Address Addr, uint64_t Index, const llvm::Twine &Name="")
Given addr = T* ... produce name = getelementptr inbounds addr, i64 index where i64 is actually the t...
Address CreateAddrSpaceCast(Address Addr, llvm::Type *Ty, llvm::Type *ElementTy, const llvm::Twine &Name="")
CGFunctionInfo - Class to encapsulate the information about a function definition.
DisableAutoDeclareTargetRAII(CodeGenModule &CGM)
~DisableAutoDeclareTargetRAII()
~LastprivateConditionalRAII()
static LastprivateConditionalRAII disable(CodeGenFunction &CGF, const OMPExecutableDirective &S)
NontemporalDeclsRAII(CodeGenModule &CGM, const OMPLoopDirective &S)
Struct that keeps all the relevant information that should be kept throughout a 'target data' region.
llvm::DenseMap< const ValueDecl *, llvm::Value * > CaptureDeviceAddrMap
Map between the a declaration of a capture and the corresponding new llvm address where the runtime r...
~UntiedTaskLocalDeclsRAII()
UntiedTaskLocalDeclsRAII(CodeGenFunction &CGF, const llvm::MapVector< CanonicalDeclPtr< const VarDecl >, std::pair< Address, Address > > &LocalVars)
virtual Address emitThreadIDAddress(CodeGenFunction &CGF, SourceLocation Loc)
Emits address of the word in a memory where current thread id is stored.
llvm::StringSet ThreadPrivateWithDefinition
Set of threadprivate variables with the generated initializer.
CGOpenMPRuntime(CodeGenModule &CGM)
virtual void emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc, const OMPExecutableDirective &D, llvm::Function *TaskFunction, QualType SharedsTy, Address Shareds, const Expr *IfCond, const OMPTaskDataTy &Data)
Emit task region for the task directive.
void createOffloadEntriesAndInfoMetadata()
Creates all the offload entries in the current compilation unit along with the associated metadata.
const Expr * getNumTeamsExprForTargetDirective(CodeGenFunction &CGF, const OMPExecutableDirective &D, int32_t &MinTeamsVal, int32_t &MaxTeamsVal)
Emit the number of teams for a target directive.
virtual Address getAddrOfThreadPrivate(CodeGenFunction &CGF, const VarDecl *VD, Address VDAddr, SourceLocation Loc)
Returns address of the threadprivate variable for the current thread.
void emitDeferredTargetDecls() const
Emit deferred declare target variables marked for deferred emission.
virtual llvm::Value * emitForNext(CodeGenFunction &CGF, SourceLocation Loc, unsigned IVSize, bool IVSigned, Address IL, Address LB, Address UB, Address ST)
Call __kmpc_dispatch_next( ident_t *loc, kmp_int32 tid, kmp_int32 *p_lastiter, kmp_int[32|64] *p_lowe...
bool markAsGlobalTarget(GlobalDecl GD)
Marks the declaration as already emitted for the device code and returns true, if it was marked alrea...
virtual void emitParallelCall(CodeGenFunction &CGF, SourceLocation Loc, llvm::Function *OutlinedFn, ArrayRef< llvm::Value * > CapturedVars, const Expr *IfCond, llvm::Value *NumThreads, OpenMPNumThreadsClauseModifier NumThreadsModifier=OMPC_NUMTHREADS_unknown, OpenMPSeverityClauseKind Severity=OMPC_SEVERITY_fatal, const Expr *Message=nullptr)
Emits code for parallel or serial call of the OutlinedFn with variables captured in a record which ad...
llvm::SmallDenseSet< CanonicalDeclPtr< const Decl > > NontemporalDeclsSet
virtual void emitTargetDataStandAloneCall(CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, const Expr *Device)
Emit the data mapping/movement code associated with the directive D that should be of the form 'targe...
virtual void emitNumThreadsClause(CodeGenFunction &CGF, llvm::Value *NumThreads, SourceLocation Loc, OpenMPNumThreadsClauseModifier Modifier=OMPC_NUMTHREADS_unknown, OpenMPSeverityClauseKind Severity=OMPC_SEVERITY_fatal, SourceLocation SeverityLoc=SourceLocation(), const Expr *Message=nullptr, SourceLocation MessageLoc=SourceLocation())
Emits call to void __kmpc_push_num_threads(ident_t *loc, kmp_int32global_tid, kmp_int32 num_threads) ...
QualType SavedKmpTaskloopTQTy
Saved kmp_task_t for taskloop-based directive.
virtual void emitSingleRegion(CodeGenFunction &CGF, const RegionCodeGenTy &SingleOpGen, SourceLocation Loc, ArrayRef< const Expr * > CopyprivateVars, ArrayRef< const Expr * > DestExprs, ArrayRef< const Expr * > SrcExprs, ArrayRef< const Expr * > AssignmentOps)
Emits a single region.
virtual bool emitTargetGlobal(GlobalDecl GD)
Emit the global GD if it is meaningful for the target.
void setLocThreadIdInsertPt(CodeGenFunction &CGF, bool AtCurrentPoint=false)
std::string getOutlinedHelperName(StringRef Name) const
Get the function name of an outlined region.
bool HasEmittedDeclareTargetRegion
Flag for keeping track of weather a device routine has been emitted.
llvm::Constant * getOrCreateThreadPrivateCache(const VarDecl *VD)
If the specified mangled name is not in the module, create and return threadprivate cache object.
virtual Address getTaskReductionItem(CodeGenFunction &CGF, SourceLocation Loc, llvm::Value *ReductionsPtr, LValue SharedLVal)
Get the address of void * type of the privatue copy of the reduction item specified by the SharedLVal...
virtual void emitForDispatchDeinit(CodeGenFunction &CGF, SourceLocation Loc)
This is used for non static scheduled types and when the ordered clause is present on the loop constr...
void emitCall(CodeGenFunction &CGF, SourceLocation Loc, llvm::FunctionCallee Callee, ArrayRef< llvm::Value * > Args={}) const
Emits Callee function call with arguments Args with location Loc.
virtual void getDefaultScheduleAndChunk(CodeGenFunction &CGF, const OMPLoopDirective &S, OpenMPScheduleClauseKind &ScheduleKind, const Expr *&ChunkExpr) const
Choose default schedule type and chunk value for the schedule clause.
virtual std::pair< llvm::Function *, llvm::Function * > getUserDefinedReduction(const OMPDeclareReductionDecl *D)
Get combiner/initializer for the specified user-defined reduction, if any.
virtual bool isGPU() const
Returns true if the current target is a GPU.
static const Stmt * getSingleCompoundChild(ASTContext &Ctx, const Stmt *Body)
Checks if the Body is the CompoundStmt and returns its child statement iff there is only one that is ...
virtual void emitDeclareTargetFunction(const FunctionDecl *FD, llvm::GlobalValue *GV)
Emit code for handling declare target functions in the runtime.
bool HasRequiresUnifiedSharedMemory
Flag for keeping track of weather a requires unified_shared_memory directive is present.
llvm::Value * emitUpdateLocation(CodeGenFunction &CGF, SourceLocation Loc, unsigned Flags=0, bool EmitLoc=false)
Emits object of ident_t type with info for source location.
bool isLocalVarInUntiedTask(CodeGenFunction &CGF, const VarDecl *VD) const
Returns true if the variable is a local variable in untied task.
virtual void emitTeamsCall(CodeGenFunction &CGF, const OMPExecutableDirective &D, SourceLocation Loc, llvm::Function *OutlinedFn, ArrayRef< llvm::Value * > CapturedVars)
Emits code for teams call of the OutlinedFn with variables captured in a record which address is stor...
virtual void emitCancellationPointCall(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind CancelRegion)
Emit code for 'cancellation point' construct.
virtual llvm::Function * emitThreadPrivateVarDefinition(const VarDecl *VD, Address VDAddr, SourceLocation Loc, bool PerformInit, CodeGenFunction *CGF=nullptr)
Emit a code for initialization of threadprivate variable.
FunctionUDMMapTy FunctionUDMMap
virtual ConstantAddress getAddrOfDeclareTargetVar(const VarDecl *VD)
Returns the address of the variable marked as declare target with link clause OR as declare target wi...
llvm::Function * getOrCreateUserDefinedMapperFunc(const OMPDeclareMapperDecl *D)
Get the function for the specified user-defined mapper.
OpenMPLocThreadIDMapTy OpenMPLocThreadIDMap
virtual void functionFinished(CodeGenFunction &CGF)
Cleans up references to the objects in finished function.
virtual llvm::Function * emitTeamsOutlinedFunction(CodeGenFunction &CGF, const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen)
Emits outlined function for the specified OpenMP teams directive D.
QualType KmpTaskTQTy
Type typedef struct kmp_task { void * shareds; /**< pointer to block of pointers to shared vars / k...
llvm::OpenMPIRBuilder OMPBuilder
An OpenMP-IR-Builder instance.
virtual void emitDoacrossInit(CodeGenFunction &CGF, const OMPLoopDirective &D, ArrayRef< Expr * > NumIterations)
Emit initialization for doacross loop nesting support.
virtual void adjustTargetSpecificDataForLambdas(CodeGenFunction &CGF, const OMPExecutableDirective &D) const
Adjust some parameters for the target-based directives, like addresses of the variables captured by r...
FunctionUDRMapTy FunctionUDRMap
virtual void emitTargetDataCalls(CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, const Expr *Device, const RegionCodeGenTy &CodeGen, CGOpenMPRuntime::TargetDataInfo &Info)
Emit the target data mapping code associated with D.
virtual unsigned getDefaultLocationReserved2Flags() const
Returns additional flags that can be stored in reserved_2 field of the default location.
virtual Address getParameterAddress(CodeGenFunction &CGF, const VarDecl *NativeParam, const VarDecl *TargetParam) const
Gets the address of the native argument basing on the address of the target-specific parameter.
void emitUsesAllocatorsFini(CodeGenFunction &CGF, const Expr *Allocator)
Destroys user defined allocators specified in the uses_allocators clause.
QualType KmpTaskAffinityInfoTy
Type typedef struct kmp_task_affinity_info { kmp_intptr_t base_addr; size_t len; struct { bool flag1 ...
void emitPrivateReduction(CodeGenFunction &CGF, SourceLocation Loc, const Expr *Privates, const Expr *LHSExprs, const Expr *RHSExprs, const Expr *ReductionOps)
Emits code for private variable reduction.
llvm::Value * emitNumTeamsForTargetDirective(CodeGenFunction &CGF, const OMPExecutableDirective &D)
virtual void emitTargetOutlinedFunctionHelper(const OMPExecutableDirective &D, StringRef ParentName, llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID, bool IsOffloadEntry, const RegionCodeGenTy &CodeGen)
Helper to emit outlined function for 'target' directive.
void scanForTargetRegionsFunctions(const Stmt *S, StringRef ParentName)
Start scanning from statement S and emit all target regions found along the way.
SmallVector< llvm::Value *, 4 > emitDepobjElementsSizes(CodeGenFunction &CGF, QualType &KmpDependInfoTy, const OMPTaskDataTy::DependData &Data)
virtual llvm::Value * emitMessageClause(CodeGenFunction &CGF, const Expr *Message, SourceLocation Loc)
virtual void emitTaskgroupRegion(CodeGenFunction &CGF, const RegionCodeGenTy &TaskgroupOpGen, SourceLocation Loc)
Emit a taskgroup region.
llvm::DenseMap< llvm::Function *, llvm::DenseMap< CanonicalDeclPtr< const Decl >, std::tuple< QualType, const FieldDecl *, const FieldDecl *, LValue > > > LastprivateConditionalToTypes
Maps local variables marked as lastprivate conditional to their internal types.
virtual bool emitTargetGlobalVariable(GlobalDecl GD)
Emit the global variable if it is a valid device global variable.
virtual void emitNumTeamsClause(CodeGenFunction &CGF, const Expr *NumTeams, const Expr *ThreadLimit, SourceLocation Loc)
Emits call to void __kmpc_push_num_teams(ident_t *loc, kmp_int32global_tid, kmp_int32 num_teams,...
bool hasRequiresUnifiedSharedMemory() const
Return whether the unified_shared_memory has been specified.
virtual Address getAddrOfArtificialThreadPrivate(CodeGenFunction &CGF, QualType VarType, StringRef Name)
Creates artificial threadprivate variable with name Name and type VarType.
void emitUserDefinedMapper(const OMPDeclareMapperDecl *D, CodeGenFunction *CGF=nullptr)
Emit the function for the user defined mapper construct.
bool HasEmittedTargetRegion
Flag for keeping track of weather a target region has been emitted.
void emitDepobjElements(CodeGenFunction &CGF, QualType &KmpDependInfoTy, LValue PosLVal, const OMPTaskDataTy::DependData &Data, Address DependenciesArray)
std::string getReductionFuncName(StringRef Name) const
Get the function name of a reduction function.
virtual void processRequiresDirective(const OMPRequiresDecl *D)
Perform check on requires decl to ensure that target architecture supports unified addressing.
llvm::DenseSet< CanonicalDeclPtr< const Decl > > AlreadyEmittedTargetDecls
List of the emitted declarations.
virtual llvm::Value * emitTaskReductionInit(CodeGenFunction &CGF, SourceLocation Loc, ArrayRef< const Expr * > LHSExprs, ArrayRef< const Expr * > RHSExprs, const OMPTaskDataTy &Data)
Emit a code for initialization of task reduction clause.
llvm::Value * getThreadID(CodeGenFunction &CGF, SourceLocation Loc)
Gets thread id value for the current thread.
void emitUpdateClause(CodeGenFunction &CGF, LValue DepobjLVal, OpenMPDependClauseKind NewDepKind, SourceLocation Loc)
Updates the dependency kind in the specified depobj object.
virtual void emitLastprivateConditionalFinalUpdate(CodeGenFunction &CGF, LValue PrivLVal, const VarDecl *VD, SourceLocation Loc)
Gets the address of the global copy used for lastprivate conditional update, if any.
llvm::MapVector< CanonicalDeclPtr< const VarDecl >, std::pair< Address, Address > > UntiedLocalVarsAddressesMap
virtual void emitErrorCall(CodeGenFunction &CGF, SourceLocation Loc, Expr *ME, bool IsFatal)
Emit __kmpc_error call for error directive extern void __kmpc_error(ident_t *loc, int severity,...
void clearLocThreadIdInsertPt(CodeGenFunction &CGF)
virtual void emitTaskyieldCall(CodeGenFunction &CGF, SourceLocation Loc)
Emits code for a taskyield directive.
std::string getName(ArrayRef< StringRef > Parts) const
Get the platform-specific name separator.
QualType KmpRoutineEntryPtrQTy
void computeMinAndMaxThreadsAndTeams(const OMPExecutableDirective &D, CodeGenFunction &CGF, llvm::OpenMPIRBuilder::TargetKernelDefaultAttrs &Attrs)
Helper to determine the min/max number of threads/teams for D.
virtual void emitFlush(CodeGenFunction &CGF, ArrayRef< const Expr * > Vars, SourceLocation Loc, llvm::AtomicOrdering AO)
Emit flush of the variables specified in 'omp flush' directive.
virtual void emitTaskwaitCall(CodeGenFunction &CGF, SourceLocation Loc, const OMPTaskDataTy &Data)
Emit code for 'taskwait' directive.
virtual void emitProcBindClause(CodeGenFunction &CGF, llvm::omp::ProcBindKind ProcBind, SourceLocation Loc)
Emit call to void __kmpc_push_proc_bind(ident_t *loc, kmp_int32global_tid, int proc_bind) to generate...
void emitLastprivateConditionalUpdate(CodeGenFunction &CGF, LValue IVLVal, StringRef UniqueDeclName, LValue LVal, SourceLocation Loc)
Emit update for lastprivate conditional data.
virtual void emitTaskLoopCall(CodeGenFunction &CGF, SourceLocation Loc, const OMPLoopDirective &D, llvm::Function *TaskFunction, QualType SharedsTy, Address Shareds, const Expr *IfCond, const OMPTaskDataTy &Data)
Emit task region for the taskloop directive.
virtual void emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind Kind, bool EmitChecks=true, bool ForceSimpleCall=false)
Emit an implicit/explicit barrier for OpenMP threads.
static unsigned getDefaultFlagsForBarriers(OpenMPDirectiveKind Kind)
Returns default flags for the barriers depending on the directive, for which this barier is going to ...
virtual bool emitTargetFunctions(GlobalDecl GD)
Emit the target regions enclosed in GD function definition or the function itself in case it is a val...
TaskResultTy emitTaskInit(CodeGenFunction &CGF, SourceLocation Loc, const OMPExecutableDirective &D, llvm::Function *TaskFunction, QualType SharedsTy, Address Shareds, const OMPTaskDataTy &Data)
Emit task region for the task directive.
llvm::Value * emitTargetNumIterationsCall(CodeGenFunction &CGF, const OMPExecutableDirective &D, llvm::function_ref< llvm::Value *(CodeGenFunction &CGF, const OMPLoopDirective &D)> SizeEmitter)
Return the trip count of loops associated with constructs / 'target teams distribute' and 'teams dist...
llvm::StringMap< llvm::AssertingVH< llvm::GlobalVariable >, llvm::BumpPtrAllocator > InternalVars
An ordered map of auto-generated variables to their unique names.
virtual void emitDistributeStaticInit(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDistScheduleClauseKind SchedKind, const StaticRTInput &Values)
llvm::SmallVector< UntiedLocalVarsAddressesMap, 4 > UntiedLocalVarsStack
virtual void emitForStaticFinish(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind DKind)
Call the appropriate runtime routine to notify that we finished all the work with current loop.
virtual void emitThreadLimitClause(CodeGenFunction &CGF, const Expr *ThreadLimit, SourceLocation Loc)
Emits call to void __kmpc_set_thread_limit(ident_t *loc, kmp_int32global_tid, kmp_int32 thread_limit)...
void emitIfClause(CodeGenFunction &CGF, const Expr *Cond, const RegionCodeGenTy &ThenGen, const RegionCodeGenTy &ElseGen)
Emits code for OpenMP 'if' clause using specified CodeGen function.
Address emitDepobjDependClause(CodeGenFunction &CGF, const OMPTaskDataTy::DependData &Dependencies, SourceLocation Loc)
Emits list of dependecies based on the provided data (array of dependence/expression pairs) for depob...
bool isNontemporalDecl(const ValueDecl *VD) const
Checks if the VD variable is marked as nontemporal declaration in current context.
virtual llvm::Function * emitParallelOutlinedFunction(CodeGenFunction &CGF, const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen)
Emits outlined function for the specified OpenMP parallel directive D.
const Expr * getNumThreadsExprForTargetDirective(CodeGenFunction &CGF, const OMPExecutableDirective &D, int32_t &UpperBound, bool UpperBoundOnly, llvm::Value **CondExpr=nullptr, const Expr **ThreadLimitExpr=nullptr)
Check for a number of threads upper bound constant value (stored in UpperBound), or expression (retur...
virtual void registerVTableOffloadEntry(llvm::GlobalVariable *VTable, const VarDecl *VD)
Register VTable to OpenMP offload entry.
virtual llvm::Value * emitSeverityClause(OpenMPSeverityClauseKind Severity, SourceLocation Loc)
llvm::SmallVector< LastprivateConditionalData, 4 > LastprivateConditionalStack
Stack for list of addresses of declarations in current context marked as lastprivate conditional.
virtual void emitForStaticInit(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind DKind, const OpenMPScheduleTy &ScheduleKind, const StaticRTInput &Values)
Call the appropriate runtime routine to initialize it before start of loop.
virtual void emitDeclareSimdFunction(const FunctionDecl *FD, llvm::Function *Fn)
Marks function Fn with properly mangled versions of vector functions.
llvm::AtomicOrdering getDefaultMemoryOrdering() const
Gets default memory ordering as specified in requires directive.
virtual bool isStaticNonchunked(OpenMPScheduleClauseKind ScheduleKind, bool Chunked) const
Check if the specified ScheduleKind is static non-chunked.
virtual void emitAndRegisterVTable(CodeGenModule &CGM, CXXRecordDecl *CXXRecord, const VarDecl *VD)
Emit and register VTable for the C++ class in OpenMP offload entry.
llvm::Value * getCriticalRegionLock(StringRef CriticalName)
Returns corresponding lock object for the specified critical region name.
virtual void emitCancelCall(CodeGenFunction &CGF, SourceLocation Loc, const Expr *IfCond, OpenMPDirectiveKind CancelRegion)
Emit code for 'cancel' construct.
QualType SavedKmpTaskTQTy
Saved kmp_task_t for task directive.
virtual void emitMasterRegion(CodeGenFunction &CGF, const RegionCodeGenTy &MasterOpGen, SourceLocation Loc)
Emits a master region.
virtual llvm::Function * emitTaskOutlinedFunction(const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, const VarDecl *PartIDVar, const VarDecl *TaskTVar, OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen, bool Tied, unsigned &NumberOfParts)
Emits outlined function for the OpenMP task directive D.
llvm::DenseMap< llvm::Function *, unsigned > FunctionToUntiedTaskStackMap
Maps function to the position of the untied task locals stack.
void emitDestroyClause(CodeGenFunction &CGF, LValue DepobjLVal, SourceLocation Loc)
Emits the code to destroy the dependency object provided in depobj directive.
virtual void emitTaskReductionFixups(CodeGenFunction &CGF, SourceLocation Loc, ReductionCodeGen &RCG, unsigned N)
Required to resolve existing problems in the runtime.
llvm::ArrayType * KmpCriticalNameTy
Type kmp_critical_name, originally defined as typedef kmp_int32 kmp_critical_name[8];.
virtual void emitDoacrossOrdered(CodeGenFunction &CGF, const OMPDependClause *C)
Emit code for doacross ordered directive with 'depend' clause.
llvm::DenseMap< const OMPDeclareMapperDecl *, llvm::Function * > UDMMap
Map from the user-defined mapper declaration to its corresponding functions.
virtual void checkAndEmitLastprivateConditional(CodeGenFunction &CGF, const Expr *LHS)
Checks if the provided LVal is lastprivate conditional and emits the code to update the value of the ...
std::pair< llvm::Value *, LValue > getDepobjElements(CodeGenFunction &CGF, LValue DepobjLVal, SourceLocation Loc)
Returns the number of the elements and the address of the depobj dependency array.
llvm::SmallDenseSet< const VarDecl * > DeferredGlobalVariables
List of variables that can become declare target implicitly and, thus, must be emitted.
void emitUsesAllocatorsInit(CodeGenFunction &CGF, const Expr *Allocator, const Expr *AllocatorTraits)
Initializes user defined allocators specified in the uses_allocators clauses.
virtual void registerVTable(const OMPExecutableDirective &D)
Emit code for registering vtable by scanning through map clause in OpenMP target region.
llvm::Type * KmpRoutineEntryPtrTy
Type typedef kmp_int32 (* kmp_routine_entry_t)(kmp_int32, void *);.
llvm::Type * getIdentTyPointerTy()
Returns pointer to ident_t type.
void emitSingleReductionCombiner(CodeGenFunction &CGF, const Expr *ReductionOp, const Expr *PrivateRef, const DeclRefExpr *LHS, const DeclRefExpr *RHS)
Emits single reduction combiner.
llvm::OpenMPIRBuilder & getOMPBuilder()
virtual void emitTargetOutlinedFunction(const OMPExecutableDirective &D, StringRef ParentName, llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID, bool IsOffloadEntry, const RegionCodeGenTy &CodeGen)
Emit outilined function for 'target' directive.
virtual void emitCriticalRegion(CodeGenFunction &CGF, StringRef CriticalName, const RegionCodeGenTy &CriticalOpGen, SourceLocation Loc, const Expr *Hint=nullptr)
Emits a critical region.
virtual void emitForOrderedIterationEnd(CodeGenFunction &CGF, SourceLocation Loc, unsigned IVSize, bool IVSigned)
Call the appropriate runtime routine to notify that we finished iteration of the ordered loop with th...
virtual void emitOutlinedFunctionCall(CodeGenFunction &CGF, SourceLocation Loc, llvm::FunctionCallee OutlinedFn, ArrayRef< llvm::Value * > Args={}) const
Emits call of the outlined function with the provided arguments, translating these arguments to corre...
llvm::Value * emitNumThreadsForTargetDirective(CodeGenFunction &CGF, const OMPExecutableDirective &D)
Emit an expression that denotes the number of threads a target region shall use.
void emitThreadPrivateVarInit(CodeGenFunction &CGF, Address VDAddr, llvm::Value *Ctor, llvm::Value *CopyCtor, llvm::Value *Dtor, SourceLocation Loc)
Emits initialization code for the threadprivate variables.
virtual void emitUserDefinedReduction(CodeGenFunction *CGF, const OMPDeclareReductionDecl *D)
Emit code for the specified user defined reduction construct.
virtual void checkAndEmitSharedLastprivateConditional(CodeGenFunction &CGF, const OMPExecutableDirective &D, const llvm::DenseSet< CanonicalDeclPtr< const VarDecl > > &IgnoredDecls)
Checks if the lastprivate conditional was updated in inner region and writes the value.
QualType KmpDimTy
struct kmp_dim { // loop bounds info casted to kmp_int64 kmp_int64 lo; // lower kmp_int64 up; // uppe...
virtual void emitInlinedDirective(CodeGenFunction &CGF, OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen, bool HasCancel=false)
Emit code for the directive that does not require outlining.
virtual void registerTargetGlobalVariable(const VarDecl *VD, llvm::Constant *Addr)
Checks if the provided global decl GD is a declare target variable and registers it when emitting cod...
virtual void emitFunctionProlog(CodeGenFunction &CGF, const Decl *D)
Emits OpenMP-specific function prolog.
void emitKmpRoutineEntryT(QualType KmpInt32Ty)
Build type kmp_routine_entry_t (if not built yet).
virtual bool isStaticChunked(OpenMPScheduleClauseKind ScheduleKind, bool Chunked) const
Check if the specified ScheduleKind is static chunked.
virtual void emitTargetCall(CodeGenFunction &CGF, const OMPExecutableDirective &D, llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID, const Expr *IfCond, llvm::PointerIntPair< const Expr *, 2, OpenMPDeviceClauseModifier > Device, llvm::function_ref< llvm::Value *(CodeGenFunction &CGF, const OMPLoopDirective &D)> SizeEmitter)
Emit the target offloading code associated with D.
virtual bool hasAllocateAttributeForGlobalVar(const VarDecl *VD, LangAS &AS)
Checks if the variable has associated OMPAllocateDeclAttr attribute with the predefined allocator and...
llvm::AtomicOrdering RequiresAtomicOrdering
Atomic ordering from the omp requires directive.
virtual void emitReduction(CodeGenFunction &CGF, SourceLocation Loc, ArrayRef< const Expr * > Privates, ArrayRef< const Expr * > LHSExprs, ArrayRef< const Expr * > RHSExprs, ArrayRef< const Expr * > ReductionOps, ReductionOptionsTy Options)
Emit a code for reduction clause.
std::pair< llvm::Value *, Address > emitDependClause(CodeGenFunction &CGF, ArrayRef< OMPTaskDataTy::DependData > Dependencies, SourceLocation Loc)
Emits list of dependecies based on the provided data (array of dependence/expression pairs).
llvm::StringMap< llvm::WeakTrackingVH > EmittedNonTargetVariables
List of the global variables with their addresses that should not be emitted for the target.
virtual bool isDynamic(OpenMPScheduleClauseKind ScheduleKind) const
Check if the specified ScheduleKind is dynamic.
Address emitLastprivateConditionalInit(CodeGenFunction &CGF, const VarDecl *VD)
Create specialized alloca to handle lastprivate conditionals.
virtual void emitOrderedRegion(CodeGenFunction &CGF, const RegionCodeGenTy &OrderedOpGen, SourceLocation Loc, bool IsThreads)
Emit an ordered region.
virtual Address getAddressOfLocalVariable(CodeGenFunction &CGF, const VarDecl *VD)
Gets the OpenMP-specific address of the local variable.
virtual void emitTaskReductionFini(CodeGenFunction &CGF, SourceLocation Loc, bool IsWorksharingReduction)
Emits the following code for reduction clause with task modifier:
virtual void emitMaskedRegion(CodeGenFunction &CGF, const RegionCodeGenTy &MaskedOpGen, SourceLocation Loc, const Expr *Filter=nullptr)
Emits a masked region.
QualType KmpDependInfoTy
Type typedef struct kmp_depend_info { kmp_intptr_t base_addr; size_t len; struct { bool in:1; bool ou...
llvm::Function * emitReductionFunction(StringRef ReducerName, SourceLocation Loc, llvm::Type *ArgsElemType, ArrayRef< const Expr * > Privates, ArrayRef< const Expr * > LHSExprs, ArrayRef< const Expr * > RHSExprs, ArrayRef< const Expr * > ReductionOps)
Emits reduction function.
virtual void emitForDispatchInit(CodeGenFunction &CGF, SourceLocation Loc, const OpenMPScheduleTy &ScheduleKind, unsigned IVSize, bool IVSigned, bool Ordered, const DispatchRTInput &DispatchValues)
Call the appropriate runtime routine to initialize it before start of loop.
Address getTaskReductionItem(CodeGenFunction &CGF, SourceLocation Loc, llvm::Value *ReductionsPtr, LValue SharedLVal) override
Get the address of void * type of the privatue copy of the reduction item specified by the SharedLVal...
void emitCriticalRegion(CodeGenFunction &CGF, StringRef CriticalName, const RegionCodeGenTy &CriticalOpGen, SourceLocation Loc, const Expr *Hint=nullptr) override
Emits a critical region.
void emitDistributeStaticInit(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDistScheduleClauseKind SchedKind, const StaticRTInput &Values) override
void emitForStaticInit(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind DKind, const OpenMPScheduleTy &ScheduleKind, const StaticRTInput &Values) override
Call the appropriate runtime routine to initialize it before start of loop.
bool emitTargetGlobalVariable(GlobalDecl GD) override
Emit the global variable if it is a valid device global variable.
llvm::Value * emitForNext(CodeGenFunction &CGF, SourceLocation Loc, unsigned IVSize, bool IVSigned, Address IL, Address LB, Address UB, Address ST) override
Call __kmpc_dispatch_next( ident_t *loc, kmp_int32 tid, kmp_int32 *p_lastiter, kmp_int[32|64] *p_lowe...
llvm::Function * emitThreadPrivateVarDefinition(const VarDecl *VD, Address VDAddr, SourceLocation Loc, bool PerformInit, CodeGenFunction *CGF=nullptr) override
Emit a code for initialization of threadprivate variable.
void emitTargetDataStandAloneCall(CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, const Expr *Device) override
Emit the data mapping/movement code associated with the directive D that should be of the form 'targe...
llvm::Function * emitTeamsOutlinedFunction(CodeGenFunction &CGF, const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) override
Emits outlined function for the specified OpenMP teams directive D.
void emitParallelCall(CodeGenFunction &CGF, SourceLocation Loc, llvm::Function *OutlinedFn, ArrayRef< llvm::Value * > CapturedVars, const Expr *IfCond, llvm::Value *NumThreads, OpenMPNumThreadsClauseModifier NumThreadsModifier=OMPC_NUMTHREADS_unknown, OpenMPSeverityClauseKind Severity=OMPC_SEVERITY_fatal, const Expr *Message=nullptr) override
Emits code for parallel or serial call of the OutlinedFn with variables captured in a record which ad...
void emitReduction(CodeGenFunction &CGF, SourceLocation Loc, ArrayRef< const Expr * > Privates, ArrayRef< const Expr * > LHSExprs, ArrayRef< const Expr * > RHSExprs, ArrayRef< const Expr * > ReductionOps, ReductionOptionsTy Options) override
Emit a code for reduction clause.
void emitFlush(CodeGenFunction &CGF, ArrayRef< const Expr * > Vars, SourceLocation Loc, llvm::AtomicOrdering AO) override
Emit flush of the variables specified in 'omp flush' directive.
void emitDoacrossOrdered(CodeGenFunction &CGF, const OMPDependClause *C) override
Emit code for doacross ordered directive with 'depend' clause.
void emitTaskyieldCall(CodeGenFunction &CGF, SourceLocation Loc) override
Emits a masked region.
Address getAddrOfArtificialThreadPrivate(CodeGenFunction &CGF, QualType VarType, StringRef Name) override
Creates artificial threadprivate variable with name Name and type VarType.
Address getAddrOfThreadPrivate(CodeGenFunction &CGF, const VarDecl *VD, Address VDAddr, SourceLocation Loc) override
Returns address of the threadprivate variable for the current thread.
void emitSingleRegion(CodeGenFunction &CGF, const RegionCodeGenTy &SingleOpGen, SourceLocation Loc, ArrayRef< const Expr * > CopyprivateVars, ArrayRef< const Expr * > DestExprs, ArrayRef< const Expr * > SrcExprs, ArrayRef< const Expr * > AssignmentOps) override
Emits a single region.
void emitTaskReductionFixups(CodeGenFunction &CGF, SourceLocation Loc, ReductionCodeGen &RCG, unsigned N) override
Required to resolve existing problems in the runtime.
llvm::Function * emitParallelOutlinedFunction(CodeGenFunction &CGF, const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) override
Emits outlined function for the specified OpenMP parallel directive D.
void emitCancellationPointCall(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind CancelRegion) override
Emit code for 'cancellation point' construct.
void emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind Kind, bool EmitChecks=true, bool ForceSimpleCall=false) override
Emit an implicit/explicit barrier for OpenMP threads.
Address getParameterAddress(CodeGenFunction &CGF, const VarDecl *NativeParam, const VarDecl *TargetParam) const override
Gets the address of the native argument basing on the address of the target-specific parameter.
void emitTeamsCall(CodeGenFunction &CGF, const OMPExecutableDirective &D, SourceLocation Loc, llvm::Function *OutlinedFn, ArrayRef< llvm::Value * > CapturedVars) override
Emits code for teams call of the OutlinedFn with variables captured in a record which address is stor...
void emitForOrderedIterationEnd(CodeGenFunction &CGF, SourceLocation Loc, unsigned IVSize, bool IVSigned) override
Call the appropriate runtime routine to notify that we finished iteration of the ordered loop with th...
bool emitTargetGlobal(GlobalDecl GD) override
Emit the global GD if it is meaningful for the target.
void emitTaskReductionFini(CodeGenFunction &CGF, SourceLocation Loc, bool IsWorksharingReduction) override
Emits the following code for reduction clause with task modifier:
void emitOrderedRegion(CodeGenFunction &CGF, const RegionCodeGenTy &OrderedOpGen, SourceLocation Loc, bool IsThreads) override
Emit an ordered region.
void emitForStaticFinish(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind DKind) override
Call the appropriate runtime routine to notify that we finished all the work with current loop.
llvm::Value * emitTaskReductionInit(CodeGenFunction &CGF, SourceLocation Loc, ArrayRef< const Expr * > LHSExprs, ArrayRef< const Expr * > RHSExprs, const OMPTaskDataTy &Data) override
Emit a code for initialization of task reduction clause.
void emitProcBindClause(CodeGenFunction &CGF, llvm::omp::ProcBindKind ProcBind, SourceLocation Loc) override
Emit call to void __kmpc_push_proc_bind(ident_t *loc, kmp_int32global_tid, int proc_bind) to generate...
void emitTargetOutlinedFunction(const OMPExecutableDirective &D, StringRef ParentName, llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID, bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) override
Emit outilined function for 'target' directive.
void emitMasterRegion(CodeGenFunction &CGF, const RegionCodeGenTy &MasterOpGen, SourceLocation Loc) override
Emits a master region.
void emitNumTeamsClause(CodeGenFunction &CGF, const Expr *NumTeams, const Expr *ThreadLimit, SourceLocation Loc) override
Emits call to void __kmpc_push_num_teams(ident_t *loc, kmp_int32global_tid, kmp_int32 num_teams,...
void emitForDispatchDeinit(CodeGenFunction &CGF, SourceLocation Loc) override
This is used for non static scheduled types and when the ordered clause is present on the loop constr...
const VarDecl * translateParameter(const FieldDecl *FD, const VarDecl *NativeParam) const override
Translates the native parameter of outlined function if this is required for target.
void emitNumThreadsClause(CodeGenFunction &CGF, llvm::Value *NumThreads, SourceLocation Loc, OpenMPNumThreadsClauseModifier Modifier=OMPC_NUMTHREADS_unknown, OpenMPSeverityClauseKind Severity=OMPC_SEVERITY_fatal, SourceLocation SeverityLoc=SourceLocation(), const Expr *Message=nullptr, SourceLocation MessageLoc=SourceLocation()) override
Emits call to void __kmpc_push_num_threads(ident_t *loc, kmp_int32global_tid, kmp_int32 num_threads) ...
void emitMaskedRegion(CodeGenFunction &CGF, const RegionCodeGenTy &MaskedOpGen, SourceLocation Loc, const Expr *Filter=nullptr) override
Emits a masked region.
void emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc, const OMPExecutableDirective &D, llvm::Function *TaskFunction, QualType SharedsTy, Address Shareds, const Expr *IfCond, const OMPTaskDataTy &Data) override
Emit task region for the task directive.
void emitTargetCall(CodeGenFunction &CGF, const OMPExecutableDirective &D, llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID, const Expr *IfCond, llvm::PointerIntPair< const Expr *, 2, OpenMPDeviceClauseModifier > Device, llvm::function_ref< llvm::Value *(CodeGenFunction &CGF, const OMPLoopDirective &D)> SizeEmitter) override
Emit the target offloading code associated with D.
bool emitTargetFunctions(GlobalDecl GD) override
Emit the target regions enclosed in GD function definition or the function itself in case it is a val...
void emitDoacrossInit(CodeGenFunction &CGF, const OMPLoopDirective &D, ArrayRef< Expr * > NumIterations) override
Emit initialization for doacross loop nesting support.
void emitCancelCall(CodeGenFunction &CGF, SourceLocation Loc, const Expr *IfCond, OpenMPDirectiveKind CancelRegion) override
Emit code for 'cancel' construct.
void emitTaskwaitCall(CodeGenFunction &CGF, SourceLocation Loc, const OMPTaskDataTy &Data) override
Emit code for 'taskwait' directive.
void emitTaskgroupRegion(CodeGenFunction &CGF, const RegionCodeGenTy &TaskgroupOpGen, SourceLocation Loc) override
Emit a taskgroup region.
void emitTargetDataCalls(CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, const Expr *Device, const RegionCodeGenTy &CodeGen, CGOpenMPRuntime::TargetDataInfo &Info) override
Emit the target data mapping code associated with D.
void emitForDispatchInit(CodeGenFunction &CGF, SourceLocation Loc, const OpenMPScheduleTy &ScheduleKind, unsigned IVSize, bool IVSigned, bool Ordered, const DispatchRTInput &DispatchValues) override
This is used for non static scheduled types and when the ordered clause is present on the loop constr...
llvm::Function * emitTaskOutlinedFunction(const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, const VarDecl *PartIDVar, const VarDecl *TaskTVar, OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen, bool Tied, unsigned &NumberOfParts) override
Emits outlined function for the OpenMP task directive D.
void emitTaskLoopCall(CodeGenFunction &CGF, SourceLocation Loc, const OMPLoopDirective &D, llvm::Function *TaskFunction, QualType SharedsTy, Address Shareds, const Expr *IfCond, const OMPTaskDataTy &Data) override
Emit task region for the taskloop directive.
unsigned getNonVirtualBaseLLVMFieldNo(const CXXRecordDecl *RD) const
llvm::StructType * getLLVMType() const
Return the "complete object" LLVM type associated with this record.
llvm::StructType * getBaseSubobjectLLVMType() const
Return the "base subobject" LLVM type associated with this record.
unsigned getLLVMFieldNo(const FieldDecl *FD) const
Return llvm::StructType element number that corresponds to the field FD.
unsigned getVirtualBaseIndex(const CXXRecordDecl *base) const
Return the LLVM field index corresponding to the given virtual base.
API for captured statement code generation.
virtual void EmitBody(CodeGenFunction &CGF, const Stmt *S)
Emit the captured statement body.
virtual const FieldDecl * lookup(const VarDecl *VD) const
Lookup the captured field decl for a variable.
RAII for correct setting/restoring of CapturedStmtInfo.
The scope used to remap some variables as private in the OpenMP loop body (or other captured region e...
bool Privatize()
Privatizes local variables previously registered as private.
bool addPrivate(const VarDecl *LocalVD, Address Addr)
Registers LocalVD variable as a private with Addr as the address of the corresponding private variabl...
An RAII object to set (and then clear) a mapping for an OpaqueValueExpr.
Enters a new scope for capturing cleanups, all of which will be executed once the scope is exited.
CodeGenFunction - This class organizes the per-function state that is used while generating LLVM code...
LValue EmitLoadOfReferenceLValue(LValue RefLVal)
void EmitBranchOnBoolExpr(const Expr *Cond, llvm::BasicBlock *TrueBlock, llvm::BasicBlock *FalseBlock, uint64_t TrueCount, Stmt::Likelihood LH=Stmt::LH_None, const Expr *ConditionalOp=nullptr, const VarDecl *ConditionalDecl=nullptr)
EmitBranchOnBoolExpr - Emit a branch on a boolean condition (e.g.
void emitDestroy(Address addr, QualType type, Destroyer *destroyer, bool useEHCleanupForArray)
emitDestroy - Immediately perform the destruction of the given object.
JumpDest getJumpDestInCurrentScope(llvm::BasicBlock *Target)
The given basic block lies in the current EH scope, but may be a target of a potentially scope-crossi...
static void EmitOMPTargetParallelDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetParallelDirective &S)
void EmitNullInitialization(Address DestPtr, QualType Ty)
EmitNullInitialization - Generate code to set a value of the given type to null, If the type contains...
Address LoadCXXThisAddress()
CGCapturedStmtInfo * CapturedStmtInfo
ComplexPairTy EmitLoadOfComplex(LValue src, SourceLocation loc)
EmitLoadOfComplex - Load a complex number from the specified l-value.
static void EmitOMPTargetDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetDirective &S)
Emit device code for the target directive.
static void EmitOMPTargetTeamsDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsDirective &S)
Emit device code for the target teams directive.
static void EmitOMPTargetTeamsDistributeDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsDistributeDirective &S)
Emit device code for the target teams distribute directive.
llvm::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.
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.