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/VirtualFileSystem.h"
43#include "llvm/Support/raw_ostream.h"
51using namespace llvm::omp;
58 enum CGOpenMPRegionKind {
61 ParallelOutlinedRegion,
71 CGOpenMPRegionInfo(
const CapturedStmt &CS,
72 const CGOpenMPRegionKind RegionKind,
75 : CGCapturedStmtInfo(CS,
CR_OpenMP), RegionKind(RegionKind),
76 CodeGen(CodeGen), Kind(Kind), HasCancel(HasCancel) {}
78 CGOpenMPRegionInfo(
const CGOpenMPRegionKind RegionKind,
81 : CGCapturedStmtInfo(
CR_OpenMP), RegionKind(RegionKind), CodeGen(CodeGen),
82 Kind(Kind), HasCancel(HasCancel) {}
86 virtual const VarDecl *getThreadIDVariable()
const = 0;
89 void EmitBody(CodeGenFunction &CGF,
const Stmt *S)
override;
93 virtual LValue getThreadIDVariableLValue(CodeGenFunction &CGF);
95 virtual void emitUntiedSwitch(CodeGenFunction & ) {}
97 CGOpenMPRegionKind getRegionKind()
const {
return RegionKind; }
101 bool hasCancel()
const {
return HasCancel; }
103 static bool classof(
const CGCapturedStmtInfo *Info) {
107 ~CGOpenMPRegionInfo()
override =
default;
110 CGOpenMPRegionKind RegionKind;
111 RegionCodeGenTy CodeGen;
117class CGOpenMPOutlinedRegionInfo final :
public CGOpenMPRegionInfo {
119 CGOpenMPOutlinedRegionInfo(
const CapturedStmt &CS,
const VarDecl *ThreadIDVar,
120 const RegionCodeGenTy &CodeGen,
122 StringRef HelperName)
123 : CGOpenMPRegionInfo(CS, ParallelOutlinedRegion, CodeGen,
Kind,
125 ThreadIDVar(ThreadIDVar), HelperName(HelperName) {
126 assert(ThreadIDVar !=
nullptr &&
"No ThreadID in OpenMP region.");
131 const VarDecl *getThreadIDVariable()
const override {
return ThreadIDVar; }
134 StringRef getHelperName()
const override {
return HelperName; }
136 static bool classof(
const CGCapturedStmtInfo *Info) {
137 return CGOpenMPRegionInfo::classof(Info) &&
139 ParallelOutlinedRegion;
145 const VarDecl *ThreadIDVar;
146 StringRef HelperName;
150class CGOpenMPTaskOutlinedRegionInfo final :
public CGOpenMPRegionInfo {
152 class UntiedTaskActionTy final :
public PrePostActionTy {
154 const VarDecl *PartIDVar;
155 const RegionCodeGenTy UntiedCodeGen;
156 llvm::SwitchInst *UntiedSwitch =
nullptr;
159 UntiedTaskActionTy(
bool Tied,
const VarDecl *PartIDVar,
160 const RegionCodeGenTy &UntiedCodeGen)
161 : Untied(!Tied), PartIDVar(PartIDVar), UntiedCodeGen(UntiedCodeGen) {}
162 void Enter(CodeGenFunction &CGF)
override {
167 PartIDVar->
getType()->castAs<PointerType>());
171 UntiedSwitch = CGF.
Builder.CreateSwitch(Res, DoneBB);
175 UntiedSwitch->addCase(CGF.
Builder.getInt32(0),
177 emitUntiedSwitch(CGF);
180 void emitUntiedSwitch(CodeGenFunction &CGF)
const {
184 PartIDVar->
getType()->castAs<PointerType>());
188 CodeGenFunction::JumpDest CurPoint =
192 UntiedSwitch->addCase(CGF.
Builder.getInt32(UntiedSwitch->getNumCases()),
198 unsigned getNumberOfParts()
const {
return UntiedSwitch->getNumCases(); }
200 CGOpenMPTaskOutlinedRegionInfo(
const CapturedStmt &CS,
201 const VarDecl *ThreadIDVar,
202 const RegionCodeGenTy &CodeGen,
204 const UntiedTaskActionTy &Action)
205 : CGOpenMPRegionInfo(CS, TaskOutlinedRegion, CodeGen,
Kind, HasCancel),
206 ThreadIDVar(ThreadIDVar), Action(Action) {
207 assert(ThreadIDVar !=
nullptr &&
"No ThreadID in OpenMP region.");
212 const VarDecl *getThreadIDVariable()
const override {
return ThreadIDVar; }
215 LValue getThreadIDVariableLValue(CodeGenFunction &CGF)
override;
218 StringRef getHelperName()
const override {
return ".omp_outlined."; }
220 void emitUntiedSwitch(CodeGenFunction &CGF)
override {
221 Action.emitUntiedSwitch(CGF);
224 static bool classof(
const CGCapturedStmtInfo *Info) {
225 return CGOpenMPRegionInfo::classof(Info) &&
233 const VarDecl *ThreadIDVar;
235 const UntiedTaskActionTy &Action;
240class CGOpenMPInlinedRegionInfo :
public CGOpenMPRegionInfo {
242 CGOpenMPInlinedRegionInfo(CodeGenFunction::CGCapturedStmtInfo *OldCSI,
243 const RegionCodeGenTy &CodeGen,
245 : CGOpenMPRegionInfo(InlinedRegion, CodeGen,
Kind, HasCancel),
247 OuterRegionInfo(dyn_cast_or_null<CGOpenMPRegionInfo>(OldCSI)) {}
250 llvm::Value *getContextValue()
const override {
252 return OuterRegionInfo->getContextValue();
253 llvm_unreachable(
"No context value for inlined OpenMP region");
256 void setContextValue(llvm::Value *
V)
override {
257 if (OuterRegionInfo) {
258 OuterRegionInfo->setContextValue(
V);
261 llvm_unreachable(
"No context value for inlined OpenMP region");
265 const FieldDecl *lookup(
const VarDecl *VD)
const override {
267 return OuterRegionInfo->lookup(VD);
273 FieldDecl *getThisFieldDecl()
const override {
275 return OuterRegionInfo->getThisFieldDecl();
281 const VarDecl *getThreadIDVariable()
const override {
283 return OuterRegionInfo->getThreadIDVariable();
288 LValue getThreadIDVariableLValue(CodeGenFunction &CGF)
override {
290 return OuterRegionInfo->getThreadIDVariableLValue(CGF);
291 llvm_unreachable(
"No LValue for inlined OpenMP construct");
295 StringRef getHelperName()
const override {
296 if (
auto *OuterRegionInfo = getOldCSI())
297 return OuterRegionInfo->getHelperName();
298 llvm_unreachable(
"No helper name for inlined OpenMP construct");
301 void emitUntiedSwitch(CodeGenFunction &CGF)
override {
303 OuterRegionInfo->emitUntiedSwitch(CGF);
306 CodeGenFunction::CGCapturedStmtInfo *getOldCSI()
const {
return OldCSI; }
308 static bool classof(
const CGCapturedStmtInfo *Info) {
309 return CGOpenMPRegionInfo::classof(Info) &&
313 ~CGOpenMPInlinedRegionInfo()
override =
default;
317 CodeGenFunction::CGCapturedStmtInfo *OldCSI;
318 CGOpenMPRegionInfo *OuterRegionInfo;
326class CGOpenMPTargetRegionInfo final :
public CGOpenMPRegionInfo {
328 CGOpenMPTargetRegionInfo(
const CapturedStmt &CS,
329 const RegionCodeGenTy &CodeGen, StringRef HelperName)
330 : CGOpenMPRegionInfo(CS, TargetRegion, CodeGen, OMPD_target,
332 HelperName(HelperName) {}
336 const VarDecl *getThreadIDVariable()
const override {
return nullptr; }
339 StringRef getHelperName()
const override {
return HelperName; }
341 static bool classof(
const CGCapturedStmtInfo *Info) {
342 return CGOpenMPRegionInfo::classof(Info) &&
347 StringRef HelperName;
351 llvm_unreachable(
"No codegen for expressions");
355class CGOpenMPInnerExprInfo final :
public CGOpenMPInlinedRegionInfo {
357 CGOpenMPInnerExprInfo(CodeGenFunction &CGF,
const CapturedStmt &CS)
358 : CGOpenMPInlinedRegionInfo(CGF.CapturedStmtInfo, EmptyCodeGen,
366 if (!C.capturesVariable() && !C.capturesVariableByCopy())
369 const VarDecl *VD = C.getCapturedVar();
370 if (VD->isLocalVarDeclOrParm())
373 DeclRefExpr DRE(CGF.getContext(), const_cast<VarDecl *>(VD),
375 VD->getType().getNonReferenceType(), VK_LValue,
377 PrivScope.addPrivate(VD, CGF.EmitLValue(&DRE).getAddress());
379 (
void)PrivScope.Privatize();
383 const FieldDecl *lookup(
const VarDecl *VD)
const override {
384 if (
const FieldDecl *FD = CGOpenMPInlinedRegionInfo::lookup(VD))
390 void EmitBody(CodeGenFunction &CGF,
const Stmt *S)
override {
391 llvm_unreachable(
"No body for expressions");
396 const VarDecl *getThreadIDVariable()
const override {
397 llvm_unreachable(
"No thread id for expressions");
401 StringRef getHelperName()
const override {
402 llvm_unreachable(
"No helper name for expressions");
405 static bool classof(
const CGCapturedStmtInfo *Info) {
return false; }
409 CodeGenFunction::OMPPrivateScope PrivScope;
413class InlinedOpenMPRegionRAII {
414 CodeGenFunction &CGF;
415 llvm::DenseMap<const ValueDecl *, FieldDecl *> LambdaCaptureFields;
416 FieldDecl *LambdaThisCaptureField =
nullptr;
417 const CodeGen::CGBlockInfo *BlockInfo =
nullptr;
418 bool NoInheritance =
false;
425 InlinedOpenMPRegionRAII(CodeGenFunction &CGF,
const RegionCodeGenTy &CodeGen,
427 bool NoInheritance =
true)
428 : CGF(CGF), NoInheritance(NoInheritance) {
430 CGF.CapturedStmtInfo =
new CGOpenMPInlinedRegionInfo(
431 CGF.CapturedStmtInfo, CodeGen, Kind, HasCancel);
433 std::swap(CGF.LambdaCaptureFields, LambdaCaptureFields);
434 LambdaThisCaptureField = CGF.LambdaThisCaptureField;
435 CGF.LambdaThisCaptureField =
nullptr;
436 BlockInfo = CGF.BlockInfo;
437 CGF.BlockInfo =
nullptr;
441 ~InlinedOpenMPRegionRAII() {
445 delete CGF.CapturedStmtInfo;
446 CGF.CapturedStmtInfo = OldCSI;
448 std::swap(CGF.LambdaCaptureFields, LambdaCaptureFields);
449 CGF.LambdaThisCaptureField = LambdaThisCaptureField;
450 CGF.BlockInfo = BlockInfo;
458enum OpenMPLocationFlags :
unsigned {
460 OMP_IDENT_IMD = 0x01,
462 OMP_IDENT_KMPC = 0x02,
464 OMP_ATOMIC_REDUCE = 0x10,
466 OMP_IDENT_BARRIER_EXPL = 0x20,
468 OMP_IDENT_BARRIER_IMPL = 0x40,
470 OMP_IDENT_BARRIER_IMPL_FOR = 0x40,
472 OMP_IDENT_BARRIER_IMPL_SECTIONS = 0xC0,
474 OMP_IDENT_BARRIER_IMPL_SINGLE = 0x140,
476 OMP_IDENT_WORK_LOOP = 0x200,
478 OMP_IDENT_WORK_SECTIONS = 0x400,
480 OMP_IDENT_WORK_DISTRIBUTE = 0x800,
510enum IdentFieldIndex {
512 IdentField_Reserved_1,
516 IdentField_Reserved_2,
518 IdentField_Reserved_3,
527enum OpenMPSchedType {
530 OMP_sch_static_chunked = 33,
532 OMP_sch_dynamic_chunked = 35,
533 OMP_sch_guided_chunked = 36,
534 OMP_sch_runtime = 37,
537 OMP_sch_static_balanced_chunked = 45,
540 OMP_ord_static_chunked = 65,
542 OMP_ord_dynamic_chunked = 67,
543 OMP_ord_guided_chunked = 68,
544 OMP_ord_runtime = 69,
546 OMP_sch_default = OMP_sch_static,
548 OMP_dist_sch_static_chunked = 91,
549 OMP_dist_sch_static = 92,
555 OMP_dist_sch_static_chunked_sch_static_chunkone = 93,
558 OMP_sch_modifier_monotonic = (1 << 29),
560 OMP_sch_modifier_nonmonotonic = (1 << 30),
565class CleanupTy final :
public EHScopeStack::Cleanup {
566 PrePostActionTy *Action;
569 explicit CleanupTy(PrePostActionTy *Action) : Action(Action) {}
570 void Emit(CodeGenFunction &CGF, Flags )
override {
583 Callback(CodeGen, CGF, *PrePostAction);
594 if (
const auto *CE = dyn_cast<CallExpr>(ReductionOp))
595 if (
const auto *OVE = dyn_cast<OpaqueValueExpr>(CE->getCallee()))
596 if (
const auto *DRE =
597 dyn_cast<DeclRefExpr>(OVE->getSourceExpr()->IgnoreImpCasts()))
598 if (
const auto *DRD = dyn_cast<OMPDeclareReductionDecl>(DRE->getDecl()))
609 std::pair<llvm::Function *, llvm::Function *>
Reduction =
629 auto *GV =
new llvm::GlobalVariable(
631 llvm::GlobalValue::PrivateLinkage,
Init, Name);
672 llvm::Value *NumElements = CGF.
emitArrayLength(ArrayTy, ElementTy, DestAddr);
676 llvm::Value *SrcBegin =
nullptr;
678 SrcBegin = SrcAddr.emitRawPointer(CGF);
681 llvm::Value *DestEnd =
686 llvm::Value *IsEmpty =
687 CGF.
Builder.CreateICmpEQ(DestBegin, DestEnd,
"omp.arrayinit.isempty");
688 CGF.
Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
691 llvm::BasicBlock *EntryBB = CGF.
Builder.GetInsertBlock();
696 llvm::PHINode *SrcElementPHI =
nullptr;
699 SrcElementPHI = CGF.
Builder.CreatePHI(SrcBegin->getType(), 2,
700 "omp.arraycpy.srcElementPast");
701 SrcElementPHI->addIncoming(SrcBegin, EntryBB);
703 Address(SrcElementPHI, SrcAddr.getElementType(),
704 SrcAddr.getAlignment().alignmentOfArrayElement(ElementSize));
706 llvm::PHINode *DestElementPHI = CGF.
Builder.CreatePHI(
707 DestBegin->getType(), 2,
"omp.arraycpy.destElementPast");
708 DestElementPHI->addIncoming(DestBegin, EntryBB);
716 if (EmitDeclareReductionInit) {
718 SrcElementCurrent, ElementTy);
726 llvm::Value *SrcElementNext = CGF.
Builder.CreateConstGEP1_32(
727 SrcAddr.getElementType(), SrcElementPHI, 1,
728 "omp.arraycpy.dest.element");
729 SrcElementPHI->addIncoming(SrcElementNext, CGF.
Builder.GetInsertBlock());
733 llvm::Value *DestElementNext = CGF.
Builder.CreateConstGEP1_32(
735 "omp.arraycpy.dest.element");
738 CGF.
Builder.CreateICmpEQ(DestElementNext, DestEnd,
"omp.arraycpy.done");
739 CGF.
Builder.CreateCondBr(Done, DoneBB, BodyBB);
740 DestElementPHI->addIncoming(DestElementNext, CGF.
Builder.GetInsertBlock());
752 if (
const auto *OASE = dyn_cast<ArraySectionExpr>(E))
757void ReductionCodeGen::emitAggregateInitialization(
759 const OMPDeclareReductionDecl *DRD) {
763 const auto *PrivateVD =
765 bool EmitDeclareReductionInit =
768 EmitDeclareReductionInit,
769 EmitDeclareReductionInit ? ClausesData[N].ReductionOp
770 : PrivateVD->getInit(),
778 ClausesData.reserve(Shareds.size());
779 SharedAddresses.reserve(Shareds.size());
780 Sizes.reserve(Shareds.size());
781 BaseDecls.reserve(Shareds.size());
782 const auto *IOrig = Origs.begin();
783 const auto *IPriv =
Privates.begin();
784 const auto *IRed = ReductionOps.begin();
785 for (
const Expr *Ref : Shareds) {
786 ClausesData.emplace_back(Ref, *IOrig, *IPriv, *IRed);
787 std::advance(IOrig, 1);
788 std::advance(IPriv, 1);
789 std::advance(IRed, 1);
794 assert(SharedAddresses.size() == N && OrigAddresses.size() == N &&
795 "Number of generated lvalues must be exactly N.");
796 LValue First = emitSharedLValue(CGF, ClausesData[N].Shared);
797 LValue Second = emitSharedLValueUB(CGF, ClausesData[N].Shared);
798 SharedAddresses.emplace_back(
First, Second);
799 if (ClausesData[N].Shared == ClausesData[N].Ref) {
800 OrigAddresses.emplace_back(
First, Second);
802 LValue First = emitSharedLValue(CGF, ClausesData[N].Ref);
803 LValue Second = emitSharedLValueUB(CGF, ClausesData[N].Ref);
804 OrigAddresses.emplace_back(
First, Second);
813 CGF.
getTypeSize(OrigAddresses[N].first.getType().getNonReferenceType()),
818 llvm::Value *SizeInChars;
819 auto *ElemType = OrigAddresses[N].first.getAddress().getElementType();
820 auto *ElemSizeOf = llvm::ConstantInt::get(
822 if (AsArraySection) {
824 CGF.
Builder.CreatePtrDiff(OrigAddresses[N].second.getPointer(CGF),
825 OrigAddresses[N].first.getPointer(CGF));
826 SizeInChars = CGF.
Builder.CreateNUWAdd(SizeInChars, ElemSizeOf);
829 CGF.
getTypeSize(OrigAddresses[N].first.getType().getNonReferenceType());
831 Size = ElemSizeOf->isOne()
833 : CGF.
Builder.CreateExactUDiv(SizeInChars, ElemSizeOf);
834 Sizes.emplace_back(SizeInChars, Size);
847 assert(!Size && !Sizes[N].second &&
848 "Size should be nullptr for non-variably modified reduction "
863 assert(SharedAddresses.size() > N &&
"No variable was generated");
864 const auto *PrivateVD =
870 (void)DefaultInit(CGF);
871 emitAggregateInitialization(CGF, N, PrivateAddr, SharedAddr, DRD);
872 }
else if (DRD && (DRD->
getInitializer() || !PrivateVD->hasInit())) {
873 (void)DefaultInit(CGF);
874 QualType SharedType = SharedAddresses[N].first.getType();
876 PrivateAddr, SharedAddr, SharedType);
877 }
else if (!DefaultInit(CGF) && PrivateVD->hasInit() &&
880 PrivateVD->
getType().getQualifiers(),
898 CGF.
pushDestroy(DTorKind, PrivateAddr, PrivateType);
917 BaseLV.getType(), BaseLV.getBaseInfo(),
951 const VarDecl *OrigVD =
nullptr;
952 if (
const auto *OASE = dyn_cast<ArraySectionExpr>(Ref)) {
953 const Expr *
Base = OASE->getBase()->IgnoreParenImpCasts();
954 while (
const auto *TempOASE = dyn_cast<ArraySectionExpr>(
Base))
955 Base = TempOASE->getBase()->IgnoreParenImpCasts();
956 while (
const auto *TempASE = dyn_cast<ArraySubscriptExpr>(
Base))
957 Base = TempASE->getBase()->IgnoreParenImpCasts();
960 }
else if (
const auto *ASE = dyn_cast<ArraySubscriptExpr>(Ref)) {
961 const Expr *
Base = ASE->getBase()->IgnoreParenImpCasts();
962 while (
const auto *TempASE = dyn_cast<ArraySubscriptExpr>(
Base))
963 Base = TempASE->getBase()->IgnoreParenImpCasts();
974 BaseDecls.emplace_back(OrigVD);
977 loadToBegin(CGF, OrigVD->getType(), SharedAddresses[N].first.getType(),
979 Address SharedAddr = SharedAddresses[N].first.getAddress();
980 llvm::Value *Adjustment = CGF.
Builder.CreatePtrDiff(
983 llvm::Value *PrivatePointer =
989 SharedAddresses[N].first.getType(),
992 BaseDecls.emplace_back(
1006 getThreadIDVariable()->
getType()->castAs<PointerType>());
1024LValue CGOpenMPTaskOutlinedRegionInfo::getThreadIDVariableLValue(
1027 getThreadIDVariable()->
getType(),
1045 llvm::OpenMPIRBuilderConfig Config(
1046 CGM.getLangOpts().OpenMPIsTargetDevice,
isGPU(),
1047 CGM.getLangOpts().OpenMPOffloadMandatory,
1050 Config.setDefaultTargetAS(
1052 Config.setRuntimeCC(
CGM.getRuntimeCC());
1057 CGM.getLangOpts().OpenMPIsTargetDevice
1058 ?
CGM.getLangOpts().OMPHostIRFile
1063 if (
CGM.getLangOpts().OpenMPForceUSM) {
1065 OMPBuilder.Config.setHasRequiresUnifiedSharedMemory(
true);
1073 if (!
Data.getValue().pointsToAliveValue())
1075 auto *GV = dyn_cast<llvm::GlobalVariable>(
Data.getValue());
1078 if (!GV->isDeclaration() || GV->getNumUses() > 0)
1080 GV->eraseFromParent();
1085 return OMPBuilder.createPlatformSpecificName(Parts);
1088static llvm::Function *
1090 const Expr *CombinerInitializer,
const VarDecl *In,
1091 const VarDecl *Out,
bool IsCombiner) {
1094 QualType PtrTy =
C.getPointerType(Ty).withRestrict();
1096 C,
nullptr, Out->getLocation(),
1099 C,
nullptr, In->getLocation(),
1106 {IsCombiner ?
"omp_combiner" :
"omp_initializer",
""});
1107 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
1111 Fn->addFnAttr(
"sample-profile-suffix-elision-policy",
"selected");
1113 Fn->removeFnAttr(llvm::Attribute::NoInline);
1114 Fn->removeFnAttr(llvm::Attribute::OptimizeNone);
1115 Fn->addFnAttr(llvm::Attribute::AlwaysInline);
1121 Out->getLocation());
1131 (void)
Scope.Privatize();
1132 if (!IsCombiner && Out->hasInit() &&
1135 Out->getType().getQualifiers(),
1138 if (CombinerInitializer)
1140 Scope.ForceCleanup();
1169std::pair<llvm::Function *, llvm::Function *>
1181struct PushAndPopStackRAII {
1182 PushAndPopStackRAII(llvm::OpenMPIRBuilder *OMPBuilder,
CodeGenFunction &CGF,
1183 bool HasCancel, llvm::omp::Directive Kind)
1184 : OMPBuilder(OMPBuilder) {
1200 auto FiniCB = [&CGF](llvm::OpenMPIRBuilder::InsertPointTy IP) {
1201 assert(IP.getBlock()->end() == IP.getPoint() &&
1202 "Clang CG should cause non-terminated block!");
1203 CGBuilderTy::InsertPointGuard IPG(CGF.
Builder);
1208 return llvm::Error::success();
1213 llvm::OpenMPIRBuilder::FinalizationInfo FI({FiniCB, Kind, HasCancel});
1214 OMPBuilder->pushFinalizationCB(std::move(FI));
1216 ~PushAndPopStackRAII() {
1218 OMPBuilder->popFinalizationCB();
1220 llvm::OpenMPIRBuilder *OMPBuilder;
1229 "thread id variable must be of type kmp_int32 *");
1231 bool HasCancel =
false;
1232 if (
const auto *OPD = dyn_cast<OMPParallelDirective>(&D))
1233 HasCancel = OPD->hasCancel();
1234 else if (
const auto *OPD = dyn_cast<OMPTargetParallelDirective>(&D))
1235 HasCancel = OPD->hasCancel();
1236 else if (
const auto *OPSD = dyn_cast<OMPParallelSectionsDirective>(&D))
1237 HasCancel = OPSD->hasCancel();
1238 else if (
const auto *OPFD = dyn_cast<OMPParallelForDirective>(&D))
1239 HasCancel = OPFD->hasCancel();
1240 else if (
const auto *OPFD = dyn_cast<OMPTargetParallelForDirective>(&D))
1241 HasCancel = OPFD->hasCancel();
1242 else if (
const auto *OPFD = dyn_cast<OMPDistributeParallelForDirective>(&D))
1243 HasCancel = OPFD->hasCancel();
1244 else if (
const auto *OPFD =
1245 dyn_cast<OMPTeamsDistributeParallelForDirective>(&D))
1246 HasCancel = OPFD->hasCancel();
1247 else if (
const auto *OPFD =
1248 dyn_cast<OMPTargetTeamsDistributeParallelForDirective>(&D))
1249 HasCancel = OPFD->hasCancel();
1254 PushAndPopStackRAII PSR(&OMPBuilder, CGF, HasCancel, InnermostKind);
1255 CGOpenMPOutlinedRegionInfo CGInfo(*CS, ThreadIDVar,
CodeGen, InnermostKind,
1256 HasCancel, OutlinedHelperName);
1262 std::string Suffix =
getName({
"omp_outlined"});
1263 return (Name + Suffix).str();
1271 std::string Suffix =
getName({
"omp",
"reduction",
"reduction_func"});
1272 return (Name + Suffix).str();
1279 const CapturedStmt *CS = D.getCapturedStmt(OMPD_parallel);
1289 const CapturedStmt *CS = D.getCapturedStmt(OMPD_teams);
1296 OutlinedFn->setDoesNotRecurse();
1304 bool Tied,
unsigned &NumberOfParts) {
1307 llvm::Value *ThreadID =
getThreadID(CGF, D.getBeginLoc());
1309 llvm::Value *TaskArgs[] = {
1311 CGF.EmitLoadOfPointerLValue(CGF.GetAddrOfLocalVar(TaskTVar),
1314 CGF.EmitRuntimeCall(
OMPBuilder.getOrCreateRuntimeFunction(
1315 CGM.getModule(), OMPRTL___kmpc_omp_task),
1318 CGOpenMPTaskOutlinedRegionInfo::UntiedTaskActionTy Action(Tied, PartIDVar,
1322 "thread id variable must be of type kmp_int32 for tasks");
1327 bool HasCancel =
false;
1328 if (
const auto *TD = dyn_cast<OMPTaskDirective>(&D))
1329 HasCancel = TD->hasCancel();
1330 else if (
const auto *TD = dyn_cast<OMPTaskLoopDirective>(&D))
1331 HasCancel = TD->hasCancel();
1332 else if (
const auto *TD = dyn_cast<OMPMasterTaskLoopDirective>(&D))
1333 HasCancel = TD->hasCancel();
1334 else if (
const auto *TD = dyn_cast<OMPParallelMasterTaskLoopDirective>(&D))
1335 HasCancel = TD->hasCancel();
1338 CGOpenMPTaskOutlinedRegionInfo CGInfo(*CS, ThreadIDVar,
CodeGen,
1339 InnermostKind, HasCancel, Action);
1341 llvm::Function *Res = CGF.GenerateCapturedStmtFunction(*CS);
1343 NumberOfParts = Action.getNumberOfParts();
1348 bool AtCurrentPoint) {
1350 assert(!Elem.ServiceInsertPt &&
"Insert point is set already.");
1352 llvm::Value *Undef = llvm::UndefValue::get(CGF.
Int32Ty);
1353 if (AtCurrentPoint) {
1354 Elem.ServiceInsertPt =
new llvm::BitCastInst(Undef, CGF.
Int32Ty,
"svcpt",
1355 CGF.
Builder.GetInsertBlock());
1357 Elem.ServiceInsertPt =
new llvm::BitCastInst(Undef, CGF.
Int32Ty,
"svcpt");
1358 Elem.ServiceInsertPt->insertAfter(CGF.
AllocaInsertPt->getIterator());
1364 if (Elem.ServiceInsertPt) {
1365 llvm::Instruction *Ptr = Elem.ServiceInsertPt;
1366 Elem.ServiceInsertPt =
nullptr;
1367 Ptr->eraseFromParent();
1374 llvm::raw_svector_ostream OS(Buffer);
1383 if (
const auto *FD = dyn_cast_or_null<FunctionDecl>(CGF.
CurFuncDecl))
1384 OS << FD->getQualifiedNameAsString();
1391 unsigned Flags,
bool EmitLoc) {
1392 uint32_t SrcLocStrSize;
1393 llvm::Constant *SrcLocStr;
1394 if ((!EmitLoc &&
CGM.getCodeGenOpts().getDebugInfo() ==
1395 llvm::codegenoptions::NoDebugInfo) ||
1397 SrcLocStr =
OMPBuilder.getOrCreateDefaultSrcLocStr(SrcLocStrSize);
1399 std::string FunctionName;
1401 if (
const auto *FD = dyn_cast_or_null<FunctionDecl>(CGF.
CurFuncDecl))
1402 FunctionName = FD->getQualifiedNameAsString();
1415 SrcLocStr, SrcLocStrSize, llvm::omp::IdentFlag(Flags), Reserved2Flags);
1420 assert(CGF.
CurFn &&
"No function in current CodeGenFunction.");
1423 if (
CGM.getLangOpts().OpenMPIRBuilder) {
1426 uint32_t SrcLocStrSize;
1427 auto *SrcLocStr =
OMPBuilder.getOrCreateSrcLocStr(
1430 OMPBuilder.getOrCreateIdent(SrcLocStr, SrcLocStrSize));
1433 llvm::Value *ThreadID =
nullptr;
1438 ThreadID = I->second.ThreadID;
1439 if (ThreadID !=
nullptr)
1443 if (
auto *OMPRegionInfo =
1445 if (OMPRegionInfo->getThreadIDVariable()) {
1447 LValue LVal = OMPRegionInfo->getThreadIDVariableLValue(CGF);
1451 CGF.
Builder.GetInsertBlock() == TopBlock ||
1456 CGF.
Builder.GetInsertBlock()) {
1460 if (CGF.
Builder.GetInsertBlock() == TopBlock)
1472 if (!Elem.ServiceInsertPt)
1474 CGBuilderTy::InsertPointGuard IPG(CGF.
Builder);
1475 CGF.
Builder.SetInsertPoint(Elem.ServiceInsertPt);
1479 OMPRTL___kmpc_global_thread_num),
1482 Elem.ThreadID =
Call;
1487 assert(CGF.
CurFn &&
"No function in current CodeGenFunction.");
1493 for (
const auto *D : I->second)
1498 for (
const auto *D : I->second)
1510static llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseKind
1512 std::optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
1513 OMPDeclareTargetDeclAttr::getDeviceType(VD);
1515 return llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseNone;
1517 switch ((
int)*DevTy) {
1518 case OMPDeclareTargetDeclAttr::DT_Host:
1519 return llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseHost;
1521 case OMPDeclareTargetDeclAttr::DT_NoHost:
1522 return llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseNoHost;
1524 case OMPDeclareTargetDeclAttr::DT_Any:
1525 return llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseAny;
1528 return llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseNone;
1533static llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryKind
1535 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> MapType =
1536 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
1538 return llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryNone;
1539 switch ((
int)*MapType) {
1540 case OMPDeclareTargetDeclAttr::MapTypeTy::MT_To:
1541 return llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryTo;
1543 case OMPDeclareTargetDeclAttr::MapTypeTy::MT_Enter:
1544 return llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryEnter;
1545 case OMPDeclareTargetDeclAttr::MapTypeTy::MT_Link:
1546 return llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryLink;
1548 case OMPDeclareTargetDeclAttr::MapTypeTy::MT_Local:
1550 llvm_unreachable(
"MT_Local should not reach convertCaptureClause");
1553 return llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryNone;
1562 auto FileInfoCallBack = [&]() {
1572 return OMPBuilder.getTargetEntryUniqueInfo(FileInfoCallBack,
1577 auto AddrOfGlobal = [&VD,
this]() {
return CGM.GetAddrOfGlobal(VD); };
1579 auto LinkageForVariable = [&VD,
this]() {
1580 return CGM.getLLVMLinkageVarDefinition(VD);
1583 std::vector<llvm::GlobalVariable *> GeneratedRefs;
1585 llvm::Type *LlvmPtrTy =
CGM.getTypes().ConvertTypeForMem(
1586 CGM.getContext().getPointerType(VD->
getType()));
1587 llvm::Constant *addr =
OMPBuilder.getAddrOfDeclareTargetVar(
1593 CGM.getMangledName(VD), GeneratedRefs,
CGM.getLangOpts().OpenMPSimd,
1594 CGM.getLangOpts().OMPTargetTriples, LlvmPtrTy, AddrOfGlobal,
1595 LinkageForVariable);
1604 assert(!
CGM.getLangOpts().OpenMPUseTLS ||
1605 !
CGM.getContext().getTargetInfo().isTLSSupported());
1607 std::string Suffix =
getName({
"cache",
""});
1608 return OMPBuilder.getOrCreateInternalVariable(
1609 CGM.Int8PtrPtrTy, Twine(
CGM.getMangledName(VD)).concat(Suffix).str());
1616 if (
CGM.getLangOpts().OpenMPUseTLS &&
1617 CGM.getContext().getTargetInfo().isTLSSupported())
1621 llvm::Value *Args[] = {
1624 CGM.getSize(
CGM.GetTargetTypeStoreSize(VarTy)),
1629 CGM.getModule(), OMPRTL___kmpc_threadprivate_cached),
1641 CGM.getModule(), OMPRTL___kmpc_global_thread_num),
1645 llvm::Value *Args[] = {
1648 Ctor, CopyCtor, Dtor};
1651 CGM.getModule(), OMPRTL___kmpc_threadprivate_register),
1658 if (
CGM.getLangOpts().OpenMPUseTLS &&
1659 CGM.getContext().getTargetInfo().isTLSSupported())
1666 llvm::Value *Ctor =
nullptr, *CopyCtor =
nullptr, *Dtor =
nullptr;
1668 if (
CGM.getLangOpts().CPlusPlus && PerformInit) {
1673 CGM.getContext(),
nullptr, Loc,
1677 const auto &FI =
CGM.getTypes().arrangeBuiltinFunctionDeclaration(
1678 CGM.getContext().VoidPtrTy, Args);
1679 llvm::FunctionType *FTy =
CGM.getTypes().GetFunctionType(FI);
1680 std::string Name =
getName({
"__kmpc_global_ctor_",
""});
1681 llvm::Function *Fn =
1682 CGM.CreateGlobalInitOrCleanUpFunction(FTy, Name, FI, Loc);
1687 CGM.getContext().VoidPtrTy, Dst->getLocation());
1694 CGM.getContext().VoidPtrTy, Dst->getLocation());
1704 CGM.getContext(),
nullptr, Loc,
1708 const auto &FI =
CGM.getTypes().arrangeBuiltinFunctionDeclaration(
1709 CGM.getContext().VoidTy, Args);
1710 llvm::FunctionType *FTy =
CGM.getTypes().GetFunctionType(FI);
1711 std::string Name =
getName({
"__kmpc_global_dtor_",
""});
1712 llvm::Function *Fn =
1713 CGM.CreateGlobalInitOrCleanUpFunction(FTy, Name, FI, Loc);
1721 false,
CGM.getContext().VoidPtrTy, Dst->getLocation());
1736 CopyCtor = llvm::Constant::getNullValue(
CGM.DefaultPtrTy);
1737 if (Ctor ==
nullptr) {
1738 Ctor = llvm::Constant::getNullValue(
CGM.DefaultPtrTy);
1740 if (Dtor ==
nullptr) {
1741 Dtor = llvm::Constant::getNullValue(
CGM.DefaultPtrTy);
1744 auto *InitFunctionTy =
1745 llvm::FunctionType::get(
CGM.VoidTy,
false);
1746 std::string Name =
getName({
"__omp_threadprivate_init_",
""});
1747 llvm::Function *InitFunction =
CGM.CreateGlobalInitOrCleanUpFunction(
1748 InitFunctionTy, Name,
CGM.getTypes().arrangeNullaryFunction());
1752 CGM.getTypes().arrangeNullaryFunction(), ArgList,
1756 return InitFunction;
1764 llvm::GlobalValue *GV) {
1765 std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr =
1766 OMPDeclareTargetDeclAttr::getActiveAttr(FD);
1769 if (!ActiveAttr || !(*ActiveAttr)->getIndirect())
1776 OMPBuilder.OffloadInfoManager.getTargetRegionEntryFnName(Name, EntryInfo);
1782 llvm::GlobalValue *
Addr = GV;
1783 if (
CGM.getLangOpts().OpenMPIsTargetDevice) {
1784 llvm::PointerType *FnPtrTy = llvm::PointerType::get(
1785 CGM.getLLVMContext(),
1786 CGM.getModule().getDataLayout().getProgramAddressSpace());
1787 Addr =
new llvm::GlobalVariable(
1788 CGM.getModule(), FnPtrTy,
1789 true, llvm::GlobalValue::ExternalLinkage, GV, Name,
1790 nullptr, llvm::GlobalValue::NotThreadLocal,
1791 CGM.getModule().getDataLayout().getDefaultGlobalsAddressSpace());
1792 Addr->setVisibility(llvm::GlobalValue::ProtectedVisibility);
1799 OMPBuilder.OffloadInfoManager.registerDeviceGlobalVarEntryInfo(
1800 Name,
Addr,
CGM.GetTargetTypeStoreSize(
CGM.VoidPtrTy).getQuantity(),
1801 llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryIndirect,
1802 llvm::GlobalValue::WeakODRLinkage);
1815 llvm::OpenMPIRBuilder &
OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
1831 llvm::GlobalVariable *
Addr = VTable;
1833 OMPBuilder.OffloadInfoManager.getTargetRegionEntryFnName(AddrName, EntryInfo);
1834 AddrName.append(
"addr");
1836 if (
CGM.getLangOpts().OpenMPIsTargetDevice) {
1837 Addr =
new llvm::GlobalVariable(
1838 CGM.getModule(), VTable->getType(),
1839 true, llvm::GlobalValue::ExternalLinkage, VTable,
1841 nullptr, llvm::GlobalValue::NotThreadLocal,
1842 CGM.getModule().getDataLayout().getDefaultGlobalsAddressSpace());
1843 Addr->setVisibility(llvm::GlobalValue::ProtectedVisibility);
1845 OMPBuilder.OffloadInfoManager.registerDeviceGlobalVarEntryInfo(
1847 CGM.getDataLayout().getTypeAllocSize(VTable->getInitializer()->getType()),
1848 llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryIndirectVTable,
1849 llvm::GlobalValue::WeakODRLinkage);
1858 !
CGM.getOpenMPRuntime().VTableDeclMap.contains(
CXXRecord)) {
1859 auto Res =
CGM.getOpenMPRuntime().VTableDeclMap.try_emplace(
CXXRecord, VD);
1864 assert(VTablesAddr &&
"Expected non-null VTable address");
1866 if (VTablesAddr->hasExternalLinkage())
1867 VTablesAddr->setLinkage(llvm::GlobalValue::WeakODRLinkage);
1868 CGM.getOpenMPRuntime().registerVTableOffloadEntry(VTablesAddr, VD);
1886 auto GetVTableDecl = [](
const Expr *E) {
1897 if (
auto *DRE = dyn_cast<DeclRefExpr>(E)) {
1899 }
else if (
auto *MRE = dyn_cast<MemberExpr>(E)) {
1900 if (
auto *BaseDRE = dyn_cast<DeclRefExpr>(MRE->getBase())) {
1901 if (
auto *BaseVD = dyn_cast<VarDecl>(BaseDRE->getDecl()))
1905 return std::pair<CXXRecordDecl *, const VarDecl *>(
CXXRecord, VD);
1909 for (
const auto *E :
C->varlist()) {
1910 auto DeclPair = GetVTableDecl(E);
1912 if (DeclPair.second)
1921 std::string Suffix =
getName({
"artificial",
""});
1923 llvm::GlobalVariable *GAddr =
OMPBuilder.getOrCreateInternalVariable(
1924 VarLVType, Twine(Name).concat(Suffix).str());
1925 if (
CGM.getLangOpts().OpenMP &&
CGM.getLangOpts().OpenMPUseTLS &&
1926 CGM.getTarget().isTLSSupported()) {
1927 GAddr->setThreadLocal(
true);
1928 return Address(GAddr, GAddr->getValueType(),
1929 CGM.getContext().getTypeAlignInChars(VarType));
1931 std::string CacheSuffix =
getName({
"cache",
""});
1932 llvm::Value *Args[] = {
1940 Twine(Name).concat(Suffix).concat(CacheSuffix).str())};
1945 CGM.getModule(), OMPRTL___kmpc_threadprivate_cached),
1948 VarLVType,
CGM.getContext().getTypeAlignInChars(VarType));
1998 auto &M =
CGM.getModule();
1999 auto &&ThenGen = [&M, OutlinedFn, CapturedVars, RTLoc,
2002 llvm::Value *Args[] = {
2004 CGF.
Builder.getInt32(CapturedVars.size()),
2007 RealArgs.append(std::begin(Args), std::end(Args));
2008 RealArgs.append(CapturedVars.begin(), CapturedVars.end());
2010 llvm::FunctionCallee RTLFn =
2011 OMPBuilder.getOrCreateRuntimeFunction(M, OMPRTL___kmpc_fork_call);
2014 auto &&ElseGen = [&M, OutlinedFn, CapturedVars, RTLoc, Loc,
2020 llvm::Value *Args[] = {RTLoc, ThreadID};
2022 M, OMPRTL___kmpc_serialized_parallel),
2029 ".bound.zero.addr");
2034 OutlinedFnArgs.push_back(ZeroAddrBound.
getPointer());
2035 OutlinedFnArgs.append(CapturedVars.begin(), CapturedVars.end());
2043 OutlinedFn->removeFnAttr(llvm::Attribute::AlwaysInline);
2044 OutlinedFn->addFnAttr(llvm::Attribute::NoInline);
2050 M, OMPRTL___kmpc_end_serialized_parallel),
2069 if (
auto *OMPRegionInfo =
2071 if (OMPRegionInfo->getThreadIDVariable())
2072 return OMPRegionInfo->getThreadIDVariableLValue(CGF).getAddress();
2082 return ThreadIDTemp;
2086 std::string Prefix = Twine(
"gomp_critical_user_", CriticalName).str();
2087 std::string Name =
getName({Prefix,
"var"});
2088 llvm::GlobalVariable *GV =
2090 CGM.setDSOLocal(GV);
2097 llvm::FunctionCallee EnterCallee;
2099 llvm::FunctionCallee ExitCallee;
2102 llvm::BasicBlock *ContBlock =
nullptr;
2105 CommonActionTy(llvm::FunctionCallee EnterCallee,
2107 llvm::FunctionCallee ExitCallee,
2109 : EnterCallee(EnterCallee), EnterArgs(EnterArgs), ExitCallee(ExitCallee),
2114 llvm::Value *CallBool = CGF.
Builder.CreateIsNotNull(EnterRes);
2118 CGF.
Builder.CreateCondBr(CallBool, ThenBlock, ContBlock);
2122 void Done(CodeGenFunction &CGF) {
2127 void Exit(CodeGenFunction &CGF)
override {
2134 StringRef CriticalName,
2143 llvm::FunctionCallee RuntimeFcn =
OMPBuilder.getOrCreateRuntimeFunction(
2145 Hint ? OMPRTL___kmpc_critical_with_hint : OMPRTL___kmpc_critical);
2147 unsigned LockVarArgIdx = 2;
2149 RuntimeFcn.getFunctionType()
2150 ->getParamType(LockVarArgIdx)
2151 ->getPointerAddressSpace())
2153 LockVar, RuntimeFcn.getFunctionType()->getParamType(LockVarArgIdx));
2159 EnterArgs.push_back(CGF.
Builder.CreateIntCast(
2162 CommonActionTy Action(RuntimeFcn, EnterArgs,
2164 CGM.getModule(), OMPRTL___kmpc_end_critical),
2181 CommonActionTy Action(
OMPBuilder.getOrCreateRuntimeFunction(
2182 CGM.getModule(), OMPRTL___kmpc_master),
2185 CGM.getModule(), OMPRTL___kmpc_end_master),
2203 llvm::Value *FilterVal = Filter
2205 : llvm::ConstantInt::get(
CGM.Int32Ty, 0);
2210 CommonActionTy Action(
OMPBuilder.getOrCreateRuntimeFunction(
2211 CGM.getModule(), OMPRTL___kmpc_masked),
2214 CGM.getModule(), OMPRTL___kmpc_end_masked),
2230 llvm::Value *Args[] = {
2232 llvm::ConstantInt::get(
CGM.IntTy, 0,
true)};
2234 CGM.getModule(), OMPRTL___kmpc_omp_taskyield),
2238 if (
auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.
CapturedStmtInfo))
2239 Region->emitUntiedSwitch(CGF);
2252 CommonActionTy Action(
OMPBuilder.getOrCreateRuntimeFunction(
2253 CGM.getModule(), OMPRTL___kmpc_taskgroup),
2256 CGM.getModule(), OMPRTL___kmpc_end_taskgroup),
2265 unsigned Index,
const VarDecl *Var) {
2294 llvm::GlobalValue::InternalLinkage, Name,
2298 Fn->addFnAttr(
"sample-profile-suffix-elision-policy",
"selected");
2299 Fn->setDoesNotRecurse();
2316 for (
unsigned I = 0, E = AssignmentOps.size(); I < E; ++I) {
2317 const auto *DestVar =
2321 const auto *SrcVar =
2327 CGF.
EmitOMPCopy(
Type, DestAddr, SrcAddr, DestVar, SrcVar, AssignmentOps[I]);
2342 assert(CopyprivateVars.size() == SrcExprs.size() &&
2343 CopyprivateVars.size() == DstExprs.size() &&
2344 CopyprivateVars.size() == AssignmentOps.size());
2356 if (!CopyprivateVars.empty()) {
2359 C.getIntTypeForBitwidth(32, 1);
2365 CommonActionTy Action(
OMPBuilder.getOrCreateRuntimeFunction(
2366 CGM.getModule(), OMPRTL___kmpc_single),
2369 CGM.getModule(), OMPRTL___kmpc_end_single),
2382 llvm::APInt ArraySize(32, CopyprivateVars.size());
2383 QualType CopyprivateArrayTy =
C.getConstantArrayType(
2388 CopyprivateArrayTy,
".omp.copyprivate.cpr_list");
2389 for (
unsigned I = 0, E = CopyprivateVars.size(); I < E; ++I) {
2401 SrcExprs, DstExprs, AssignmentOps, Loc);
2402 llvm::Value *BufSize = CGF.
getTypeSize(CopyprivateArrayTy);
2406 llvm::Value *Args[] = {
2410 CL.emitRawPointer(CGF),
2415 CGM.getModule(), OMPRTL___kmpc_copyprivate),
2431 CommonActionTy Action(
OMPBuilder.getOrCreateRuntimeFunction(
2432 CGM.getModule(), OMPRTL___kmpc_ordered),
2435 CGM.getModule(), OMPRTL___kmpc_end_ordered),
2446 if (Kind == OMPD_for)
2447 Flags = OMP_IDENT_BARRIER_IMPL_FOR;
2448 else if (Kind == OMPD_sections)
2449 Flags = OMP_IDENT_BARRIER_IMPL_SECTIONS;
2450 else if (Kind == OMPD_single)
2451 Flags = OMP_IDENT_BARRIER_IMPL_SINGLE;
2452 else if (Kind == OMPD_barrier)
2453 Flags = OMP_IDENT_BARRIER_EXPL;
2455 Flags = OMP_IDENT_BARRIER_IMPL;
2465 S.getClausesOfKind<OMPOrderedClause>(),
2466 [](
const OMPOrderedClause *
C) { return C->getNumForLoops(); })) {
2467 ScheduleKind = OMPC_SCHEDULE_static;
2469 llvm::APInt ChunkSize(32, 1);
2479 bool ForceSimpleCall) {
2481 auto *OMPRegionInfo =
2484 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
2487 CGF.
Builder.restoreIP(AfterIP);
2500 if (OMPRegionInfo) {
2501 if (!ForceSimpleCall && OMPRegionInfo->hasCancel()) {
2504 OMPRTL___kmpc_cancel_barrier),
2513 CGF.
Builder.CreateCondBr(
Cmp, ExitBB, ContBB);
2525 CGM.getModule(), OMPRTL___kmpc_barrier),
2530 Expr *ME,
bool IsFatal) {
2532 : llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
2535 llvm::Value *Args[] = {
2537 llvm::ConstantInt::get(
CGM.Int32Ty, IsFatal ? 2 : 1),
2538 CGF.
Builder.CreatePointerCast(MVL,
CGM.Int8PtrTy)};
2540 CGM.getModule(), OMPRTL___kmpc_error),
2546 bool Chunked,
bool Ordered) {
2547 switch (ScheduleKind) {
2548 case OMPC_SCHEDULE_static:
2549 return Chunked ? (Ordered ? OMP_ord_static_chunked : OMP_sch_static_chunked)
2550 : (Ordered ? OMP_ord_static : OMP_sch_static);
2551 case OMPC_SCHEDULE_dynamic:
2552 return Ordered ? OMP_ord_dynamic_chunked : OMP_sch_dynamic_chunked;
2553 case OMPC_SCHEDULE_guided:
2554 return Ordered ? OMP_ord_guided_chunked : OMP_sch_guided_chunked;
2555 case OMPC_SCHEDULE_runtime:
2556 return Ordered ? OMP_ord_runtime : OMP_sch_runtime;
2557 case OMPC_SCHEDULE_auto:
2558 return Ordered ? OMP_ord_auto : OMP_sch_auto;
2560 assert(!Chunked &&
"chunk was specified but schedule kind not known");
2561 return Ordered ? OMP_ord_static : OMP_sch_static;
2563 llvm_unreachable(
"Unexpected runtime schedule");
2567static OpenMPSchedType
2570 return Chunked ? OMP_dist_sch_static_chunked : OMP_dist_sch_static;
2574 bool Chunked)
const {
2575 OpenMPSchedType Schedule =
2577 return Schedule == OMP_sch_static;
2583 return Schedule == OMP_dist_sch_static;
2587 bool Chunked)
const {
2588 OpenMPSchedType Schedule =
2590 return Schedule == OMP_sch_static_chunked;
2596 return Schedule == OMP_dist_sch_static_chunked;
2600 OpenMPSchedType Schedule =
2602 assert(Schedule != OMP_sch_static_chunked &&
"cannot be chunked here");
2603 return Schedule != OMP_sch_static;
2611 case OMPC_SCHEDULE_MODIFIER_monotonic:
2612 Modifier = OMP_sch_modifier_monotonic;
2614 case OMPC_SCHEDULE_MODIFIER_nonmonotonic:
2615 Modifier = OMP_sch_modifier_nonmonotonic;
2617 case OMPC_SCHEDULE_MODIFIER_simd:
2618 if (Schedule == OMP_sch_static_chunked)
2619 Schedule = OMP_sch_static_balanced_chunked;
2626 case OMPC_SCHEDULE_MODIFIER_monotonic:
2627 Modifier = OMP_sch_modifier_monotonic;
2629 case OMPC_SCHEDULE_MODIFIER_nonmonotonic:
2630 Modifier = OMP_sch_modifier_nonmonotonic;
2632 case OMPC_SCHEDULE_MODIFIER_simd:
2633 if (Schedule == OMP_sch_static_chunked)
2634 Schedule = OMP_sch_static_balanced_chunked;
2646 if (CGM.
getLangOpts().OpenMP >= 50 && Modifier == 0) {
2647 if (!(Schedule == OMP_sch_static_chunked || Schedule == OMP_sch_static ||
2648 Schedule == OMP_sch_static_balanced_chunked ||
2649 Schedule == OMP_ord_static_chunked || Schedule == OMP_ord_static ||
2650 Schedule == OMP_dist_sch_static_chunked ||
2651 Schedule == OMP_dist_sch_static ||
2652 Schedule == OMP_dist_sch_static_chunked_sch_static_chunkone))
2653 Modifier = OMP_sch_modifier_nonmonotonic;
2655 return Schedule | Modifier;
2665 ScheduleKind.
Schedule, DispatchValues.
Chunk !=
nullptr, Ordered);
2667 (Schedule != OMP_sch_static && Schedule != OMP_sch_static_chunked &&
2668 Schedule != OMP_ord_static && Schedule != OMP_ord_static_chunked &&
2669 Schedule != OMP_sch_static_balanced_chunked));
2676 llvm::Value *Chunk = DispatchValues.
Chunk ? DispatchValues.
Chunk
2677 : CGF.
Builder.getIntN(IVSize, 1);
2678 llvm::Value *Args[] = {
2682 CGM, Schedule, ScheduleKind.
M1, ScheduleKind.
M2)),
2685 CGF.
Builder.getIntN(IVSize, 1),
2702 CodeGenFunction &CGF, llvm::Value *UpdateLocation, llvm::Value *ThreadId,
2703 llvm::FunctionCallee ForStaticInitFunction, OpenMPSchedType Schedule,
2710 assert(Schedule == OMP_sch_static || Schedule == OMP_sch_static_chunked ||
2711 Schedule == OMP_sch_static_balanced_chunked ||
2712 Schedule == OMP_ord_static || Schedule == OMP_ord_static_chunked ||
2713 Schedule == OMP_dist_sch_static ||
2714 Schedule == OMP_dist_sch_static_chunked ||
2715 Schedule == OMP_dist_sch_static_chunked_sch_static_chunkone);
2722 llvm::Value *Chunk = Values.
Chunk;
2723 if (Chunk ==
nullptr) {
2724 assert((Schedule == OMP_sch_static || Schedule == OMP_ord_static ||
2725 Schedule == OMP_dist_sch_static) &&
2726 "expected static non-chunked schedule");
2730 assert((Schedule == OMP_sch_static_chunked ||
2731 Schedule == OMP_sch_static_balanced_chunked ||
2732 Schedule == OMP_ord_static_chunked ||
2733 Schedule == OMP_dist_sch_static_chunked ||
2734 Schedule == OMP_dist_sch_static_chunked_sch_static_chunkone) &&
2735 "expected static chunked schedule");
2737 llvm::Value *Args[] = {
2757 OpenMPSchedType ScheduleNum =
2759 ? OMP_dist_sch_static_chunked_sch_static_chunkone
2763 "Expected loop-based or sections-based directive.");
2766 ? OMP_IDENT_WORK_LOOP
2767 : OMP_IDENT_WORK_SECTIONS);
2769 llvm::FunctionCallee StaticInitFunction =
2774 ScheduleNum, ScheduleKind.
M1, ScheduleKind.
M2, Values);
2781 OpenMPSchedType ScheduleNum =
2783 llvm::Value *UpdatedLocation =
2786 llvm::FunctionCallee StaticInitFunction;
2787 bool isGPUDistribute =
2788 CGM.getLangOpts().OpenMPIsTargetDevice &&
CGM.getTriple().isGPU();
2789 StaticInitFunction =
OMPBuilder.createForStaticInitFunction(
2800 assert((DKind == OMPD_distribute || DKind == OMPD_for ||
2801 DKind == OMPD_sections) &&
2802 "Expected distribute, for, or sections directive kind");
2806 llvm::Value *Args[] = {
2809 (DKind == OMPD_target_teams_loop)
2810 ? OMP_IDENT_WORK_DISTRIBUTE
2812 ? OMP_IDENT_WORK_LOOP
2813 : OMP_IDENT_WORK_SECTIONS),
2817 CGM.getLangOpts().OpenMPIsTargetDevice &&
CGM.getTriple().isGPU())
2820 CGM.getModule(), OMPRTL___kmpc_distribute_static_fini),
2824 CGM.getModule(), OMPRTL___kmpc_for_static_fini),
2849 llvm::Value *Args[] = {
2857 OMPBuilder.createDispatchNextFunction(IVSize, IVSigned), Args);
2864 const Expr *Message,
2867 return llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
2876 return llvm::ConstantInt::get(
CGM.Int32Ty,
2877 Severity == OMPC_SEVERITY_warning ? 1 : 2);
2893 RuntimeFunction FnID = OMPRTL___kmpc_push_num_threads;
2894 if (Modifier == OMPC_NUMTHREADS_strict) {
2895 FnID = OMPRTL___kmpc_push_num_threads_strict;
2900 OMPBuilder.getOrCreateRuntimeFunction(
CGM.getModule(), FnID), Args);
2904 ProcBindKind ProcBind,
2908 assert(ProcBind != OMP_PROC_BIND_unknown &&
"Unsupported proc_bind value.");
2910 llvm::Value *Args[] = {
2912 llvm::ConstantInt::get(
CGM.IntTy,
unsigned(ProcBind),
true)};
2914 CGM.getModule(), OMPRTL___kmpc_push_proc_bind),
2927 CGM.getModule(), OMPRTL___kmpc_flush),
2934enum KmpTaskTFields {
2961 if (
CGM.getLangOpts().OpenMPSimd ||
OMPBuilder.OffloadInfoManager.empty())
2964 llvm::OpenMPIRBuilder::EmitMetadataErrorReportFunctionTy &&ErrorReportFn =
2965 [
this](llvm::OpenMPIRBuilder::EmitMetadataErrorKind Kind,
2966 const llvm::TargetRegionEntryInfo &EntryInfo) ->
void {
2968 if (Kind != llvm::OpenMPIRBuilder::EMIT_MD_GLOBAL_VAR_LINK_ERROR) {
2969 for (
auto I =
CGM.getContext().getSourceManager().fileinfo_begin(),
2970 E =
CGM.getContext().getSourceManager().fileinfo_end();
2972 if (I->getFirst().getUniqueID().getDevice() == EntryInfo.DeviceID &&
2973 I->getFirst().getUniqueID().getFile() == EntryInfo.FileID) {
2974 Loc =
CGM.getContext().getSourceManager().translateFileLineCol(
2975 I->getFirst(), EntryInfo.Line, 1);
2981 case llvm::OpenMPIRBuilder::EMIT_MD_TARGET_REGION_ERROR: {
2982 CGM.getDiags().Report(Loc,
2983 diag::err_target_region_offloading_entry_incorrect)
2984 << EntryInfo.ParentName;
2986 case llvm::OpenMPIRBuilder::EMIT_MD_DECLARE_TARGET_ERROR: {
2987 CGM.getDiags().Report(
2988 Loc, diag::err_target_var_offloading_entry_incorrect_with_parent)
2989 << EntryInfo.ParentName;
2991 case llvm::OpenMPIRBuilder::EMIT_MD_GLOBAL_VAR_LINK_ERROR: {
2992 CGM.getDiags().Report(diag::err_target_var_offloading_entry_incorrect);
2994 case llvm::OpenMPIRBuilder::EMIT_MD_GLOBAL_VAR_INDIRECT_ERROR: {
2995 unsigned DiagID =
CGM.getDiags().getCustomDiagID(
2997 "target variable is incorrect: the "
2998 "address is invalid.");
2999 CGM.getDiags().Report(DiagID);
3004 OMPBuilder.createOffloadEntriesAndInfoMetadata(ErrorReportFn);
3011 QualType KmpRoutineEntryTyArgs[] = {KmpInt32Ty,
C.VoidPtrTy};
3014 C.getFunctionType(KmpInt32Ty, KmpRoutineEntryTyArgs, EPI));
3020struct PrivateHelpersTy {
3021 PrivateHelpersTy(
const Expr *OriginalRef,
const VarDecl *Original,
3023 : OriginalRef(OriginalRef), Original(Original), PrivateCopy(PrivateCopy),
3024 PrivateElemInit(PrivateElemInit) {}
3025 PrivateHelpersTy(
const VarDecl *Original) : Original(Original) {}
3026 const Expr *OriginalRef =
nullptr;
3027 const VarDecl *Original =
nullptr;
3028 const VarDecl *PrivateCopy =
nullptr;
3029 const VarDecl *PrivateElemInit =
nullptr;
3030 bool isLocalPrivate()
const {
3031 return !OriginalRef && !PrivateCopy && !PrivateElemInit;
3034typedef std::pair<CharUnits , PrivateHelpersTy> PrivateDataTy;
3039 if (!CVD->
hasAttr<OMPAllocateDeclAttr>())
3041 const auto *AA = CVD->
getAttr<OMPAllocateDeclAttr>();
3043 return !(AA->getAllocatorType() == OMPAllocateDeclAttr::OMPDefaultMemAlloc &&
3044 !AA->getAllocator());
3054 RecordDecl *RD =
C.buildImplicitRecord(
".kmp_privates.t");
3056 for (
const auto &Pair :
Privates) {
3057 const VarDecl *VD = Pair.second.Original;
3061 if (Pair.second.isLocalPrivate()) {
3084 QualType KmpRoutineEntryPointerQTy) {
3104 CanQualType KmpCmplrdataTy =
C.getCanonicalTagType(UD);
3105 RecordDecl *RD =
C.buildImplicitRecord(
"kmp_task_t");
3135 RecordDecl *RD =
C.buildImplicitRecord(
"kmp_task_t_with_privates");
3155static llvm::Function *
3158 QualType KmpTaskTWithPrivatesPtrQTy,
3160 QualType SharedsPtrTy, llvm::Function *TaskFunction,
3161 llvm::Value *TaskPrivatesMap) {
3167 C,
nullptr, Loc,
nullptr,
3170 const auto &TaskEntryFnInfo =
3172 llvm::FunctionType *TaskEntryTy =
3175 auto *TaskEntry = llvm::Function::Create(
3176 TaskEntryTy, llvm::GlobalValue::InternalLinkage, Name, &CGM.
getModule());
3179 TaskEntry->addFnAttr(
"sample-profile-suffix-elision-policy",
"selected");
3180 TaskEntry->setDoesNotRecurse();
3195 const auto *KmpTaskTWithPrivatesQTyRD =
3200 auto PartIdFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTPartId);
3202 llvm::Value *PartidParam = PartIdLVal.getPointer(CGF);
3204 auto SharedsFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTShareds);
3210 auto PrivatesFI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin(), 1);
3211 llvm::Value *PrivatesParam;
3212 if (PrivatesFI != KmpTaskTWithPrivatesQTyRD->field_end()) {
3215 PrivatesLVal.getPointer(CGF), CGF.
VoidPtrTy);
3217 PrivatesParam = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
3220 llvm::Value *CommonArgs[] = {
3221 GtidParam, PartidParam, PrivatesParam, TaskPrivatesMap,
3227 std::end(CommonArgs));
3229 auto LBFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound);
3232 auto UBFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound);
3235 auto StFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTStride);
3238 auto LIFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLastIter);
3241 auto RFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTReductions);
3244 CallArgs.push_back(LBParam);
3245 CallArgs.push_back(UBParam);
3246 CallArgs.push_back(StParam);
3247 CallArgs.push_back(LIParam);
3248 CallArgs.push_back(RParam);
3250 CallArgs.push_back(SharedsParam);
3263 QualType KmpTaskTWithPrivatesPtrQTy,
3264 QualType KmpTaskTWithPrivatesQTy) {
3270 C,
nullptr, Loc,
nullptr,
3273 const auto &DestructorFnInfo =
3275 llvm::FunctionType *DestructorFnTy =
3279 auto *DestructorFn =
3280 llvm::Function::Create(DestructorFnTy, llvm::GlobalValue::InternalLinkage,
3285 DestructorFn->addFnAttr(
"sample-profile-suffix-elision-policy",
"selected");
3286 DestructorFn->setDoesNotRecurse();
3294 const auto *KmpTaskTWithPrivatesQTyRD =
3296 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin());
3298 for (
const auto *Field : FI->getType()->castAsRecordDecl()->fields()) {
3300 Field->getType().isDestructedType()) {
3302 CGF.
pushDestroy(DtorKind, FieldLValue.getAddress(), Field->getType());
3306 return DestructorFn;
3326 C,
nullptr, Loc,
nullptr,
3327 C.getPointerType(PrivatesQTy).withConst().withRestrict(),
3329 Args.push_back(TaskPrivatesArg);
3330 llvm::DenseMap<CanonicalDeclPtr<const VarDecl>,
unsigned> PrivateVarsPos;
3331 unsigned Counter = 1;
3332 for (
const Expr *E :
Data.PrivateVars) {
3334 C,
nullptr, Loc,
nullptr,
3335 C.getPointerType(
C.getPointerType(E->
getType()))
3340 PrivateVarsPos[VD] = Counter;
3343 for (
const Expr *E :
Data.FirstprivateVars) {
3345 C,
nullptr, Loc,
nullptr,
3346 C.getPointerType(
C.getPointerType(E->
getType()))
3351 PrivateVarsPos[VD] = Counter;
3354 for (
const Expr *E :
Data.LastprivateVars) {
3356 C,
nullptr, Loc,
nullptr,
3357 C.getPointerType(
C.getPointerType(E->
getType()))
3362 PrivateVarsPos[VD] = Counter;
3368 Ty =
C.getPointerType(Ty);
3370 Ty =
C.getPointerType(Ty);
3372 C,
nullptr, Loc,
nullptr,
3373 C.getPointerType(
C.getPointerType(Ty)).withConst().withRestrict(),
3375 PrivateVarsPos[VD] = Counter;
3378 const auto &TaskPrivatesMapFnInfo =
3380 llvm::FunctionType *TaskPrivatesMapTy =
3384 auto *TaskPrivatesMap = llvm::Function::Create(
3385 TaskPrivatesMapTy, llvm::GlobalValue::InternalLinkage, Name,
3388 TaskPrivatesMapFnInfo);
3390 TaskPrivatesMap->addFnAttr(
"sample-profile-suffix-elision-policy",
3393 TaskPrivatesMap->removeFnAttr(llvm::Attribute::NoInline);
3394 TaskPrivatesMap->removeFnAttr(llvm::Attribute::OptimizeNone);
3395 TaskPrivatesMap->addFnAttr(llvm::Attribute::AlwaysInline);
3399 TaskPrivatesMapFnInfo, Args, Loc, Loc);
3407 for (
const FieldDecl *Field : PrivatesQTyRD->fields()) {
3409 const VarDecl *VD = Args[PrivateVarsPos[
Privates[Counter].second.Original]];
3413 RefLVal.getAddress(), RefLVal.getType()->castAs<
PointerType>());
3418 return TaskPrivatesMap;
3424 Address KmpTaskSharedsPtr, LValue TDBase,
3430 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->
field_begin());
3444 if ((!IsTargetTask && !
Data.FirstprivateVars.empty() && ForDup) ||
3445 (IsTargetTask && KmpTaskSharedsPtr.
isValid())) {
3452 FI = FI->getType()->castAsRecordDecl()->field_begin();
3453 for (
const PrivateDataTy &Pair :
Privates) {
3455 if (Pair.second.isLocalPrivate()) {
3459 const VarDecl *VD = Pair.second.PrivateCopy;
3464 if (
const VarDecl *Elem = Pair.second.PrivateElemInit) {
3465 const VarDecl *OriginalVD = Pair.second.Original;
3468 LValue SharedRefLValue;
3471 if (IsTargetTask && !SharedField) {
3475 ->getNumParams() == 0 &&
3478 ->getDeclContext()) &&
3479 "Expected artificial target data variable.");
3482 }
else if (ForDup) {
3485 SharedRefLValue.getAddress().withAlignment(
3486 C.getDeclAlign(OriginalVD)),
3488 SharedRefLValue.getTBAAInfo());
3490 Pair.second.Original->getCanonicalDecl()) > 0 ||
3492 SharedRefLValue = CGF.
EmitLValue(Pair.second.OriginalRef);
3495 InlinedOpenMPRegionRAII Region(
3498 SharedRefLValue = CGF.
EmitLValue(Pair.second.OriginalRef);
3509 PrivateLValue.getAddress(), SharedRefLValue.getAddress(),
Type,
3510 [&CGF, Elem,
Init, &CapturesInfo](
Address DestElement,
3513 CodeGenFunction::OMPPrivateScope InitScope(CGF);
3514 InitScope.addPrivate(Elem, SrcElement);
3515 (void)InitScope.Privatize();
3517 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(
3518 CGF, &CapturesInfo);
3519 CGF.EmitAnyExprToMem(Init, DestElement,
3520 Init->getType().getQualifiers(),
3526 InitScope.addPrivate(Elem, SharedRefLValue.getAddress());
3527 (void)InitScope.Privatize();
3543 bool InitRequired =
false;
3544 for (
const PrivateDataTy &Pair :
Privates) {
3545 if (Pair.second.isLocalPrivate())
3547 const VarDecl *VD = Pair.second.PrivateCopy;
3549 InitRequired = InitRequired || (isa_and_nonnull<CXXConstructExpr>(
Init) &&
3554 return InitRequired;
3571 QualType KmpTaskTWithPrivatesPtrQTy,
3578 C,
nullptr, Loc,
nullptr, KmpTaskTWithPrivatesPtrQTy,
3581 C,
nullptr, Loc,
nullptr, KmpTaskTWithPrivatesPtrQTy,
3587 const auto &TaskDupFnInfo =
3591 auto *TaskDup = llvm::Function::Create(
3592 TaskDupTy, llvm::GlobalValue::InternalLinkage, Name, &CGM.
getModule());
3595 TaskDup->addFnAttr(
"sample-profile-suffix-elision-policy",
"selected");
3596 TaskDup->setDoesNotRecurse();
3606 auto LIFI = std::next(KmpTaskTQTyRD->
field_begin(), KmpTaskTLastIter);
3608 TDBase, *KmpTaskTWithPrivatesQTyRD->
field_begin());
3618 if (!
Data.FirstprivateVars.empty()) {
3623 TDBase, *KmpTaskTWithPrivatesQTyRD->
field_begin());
3631 emitPrivatesInit(CGF, D, KmpTaskSharedsPtr, TDBase, KmpTaskTWithPrivatesQTyRD,
3642 for (
const PrivateDataTy &P :
Privates) {
3643 if (P.second.isLocalPrivate())
3645 QualType Ty = P.second.Original->getType().getNonReferenceType();
3654class OMPIteratorGeneratorScope final
3656 CodeGenFunction &CGF;
3657 const OMPIteratorExpr *E =
nullptr;
3658 SmallVector<CodeGenFunction::JumpDest, 4> ContDests;
3659 SmallVector<CodeGenFunction::JumpDest, 4> ExitDests;
3660 OMPIteratorGeneratorScope() =
delete;
3661 OMPIteratorGeneratorScope(OMPIteratorGeneratorScope &) =
delete;
3664 OMPIteratorGeneratorScope(CodeGenFunction &CGF,
const OMPIteratorExpr *E)
3665 : CodeGenFunction::OMPPrivateScope(CGF), CGF(CGF), E(E) {
3668 SmallVector<llvm::Value *, 4> Uppers;
3670 Uppers.push_back(CGF.EmitScalarExpr(E->getHelper(I).Upper));
3671 const auto *VD = cast<VarDecl>(E->getIteratorDecl(I));
3672 addPrivate(VD, CGF.CreateMemTemp(VD->getType(), VD->getName()));
3673 const OMPIteratorHelperData &HelperData = E->getHelper(I);
3675 HelperData.CounterVD,
3676 CGF.CreateMemTemp(HelperData.CounterVD->getType(),
"counter.addr"));
3681 const OMPIteratorHelperData &HelperData = E->getHelper(I);
3683 CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(HelperData.CounterVD),
3684 HelperData.CounterVD->getType());
3686 CGF.EmitStoreOfScalar(
3687 llvm::ConstantInt::get(CLVal.getAddress().getElementType(), 0),
3689 CodeGenFunction::JumpDest &ContDest =
3690 ContDests.emplace_back(CGF.getJumpDestInCurrentScope(
"iter.cont"));
3691 CodeGenFunction::JumpDest &ExitDest =
3692 ExitDests.emplace_back(CGF.getJumpDestInCurrentScope(
"iter.exit"));
3694 llvm::Value *N = Uppers[I];
3697 CGF.EmitBlock(ContDest.getBlock());
3699 CGF.EmitLoadOfScalar(CLVal, HelperData.CounterVD->getLocation());
3701 HelperData.CounterVD->getType()->isSignedIntegerOrEnumerationType()
3702 ? CGF.Builder.CreateICmpSLT(CVal, N)
3703 : CGF.Builder.CreateICmpULT(CVal, N);
3704 llvm::BasicBlock *BodyBB = CGF.createBasicBlock(
"iter.body");
3705 CGF.Builder.CreateCondBr(Cmp, BodyBB, ExitDest.getBlock());
3707 CGF.EmitBlock(BodyBB);
3709 CGF.EmitIgnoredExpr(HelperData.Update);
3712 ~OMPIteratorGeneratorScope() {
3717 const OMPIteratorHelperData &HelperData = E->
getHelper(I - 1);
3722 CGF.
EmitBlock(ExitDests[I - 1].getBlock(), I == 1);
3728static std::pair<llvm::Value *, llvm::Value *>
3730 const auto *OASE = dyn_cast<OMPArrayShapingExpr>(E);
3733 const Expr *
Base = OASE->getBase();
3738 llvm::Value *SizeVal;
3741 SizeVal = CGF.
getTypeSize(OASE->getBase()->getType()->getPointeeType());
3742 for (
const Expr *SE : OASE->getDimensions()) {
3746 SizeVal = CGF.
Builder.CreateNUWMul(SizeVal, Sz);
3748 }
else if (
const auto *ASE =
3751 Address UpAddrAddress = UpAddrLVal.getAddress();
3752 llvm::Value *UpAddr = CGF.
Builder.CreateConstGEP1_32(
3755 SizeVal = CGF.
Builder.CreatePtrDiff(UpAddr,
Addr,
"",
true);
3759 return std::make_pair(
Addr, SizeVal);
3764 QualType FlagsTy =
C.getIntTypeForBitwidth(32,
false);
3765 if (KmpTaskAffinityInfoTy.
isNull()) {
3767 C.buildImplicitRecord(
"kmp_task_affinity_info_t");
3773 KmpTaskAffinityInfoTy =
C.getCanonicalTagType(KmpAffinityInfoRD);
3780 llvm::Function *TaskFunction,
QualType SharedsTy,
3785 const auto *I =
Data.PrivateCopies.begin();
3786 for (
const Expr *E :
Data.PrivateVars) {
3794 I =
Data.FirstprivateCopies.begin();
3795 const auto *IElemInitRef =
Data.FirstprivateInits.begin();
3796 for (
const Expr *E :
Data.FirstprivateVars) {
3806 I =
Data.LastprivateCopies.begin();
3807 for (
const Expr *E :
Data.LastprivateVars) {
3817 Privates.emplace_back(
CGM.getPointerAlign(), PrivateHelpersTy(VD));
3819 Privates.emplace_back(
C.getDeclAlign(VD), PrivateHelpersTy(VD));
3822 [](
const PrivateDataTy &L,
const PrivateDataTy &R) {
3823 return L.first > R.first;
3825 QualType KmpInt32Ty =
C.getIntTypeForBitwidth(32, 1);
3836 assert((D.getDirectiveKind() == OMPD_task ||
3839 "Expected taskloop, task or target directive");
3846 const auto *KmpTaskTQTyRD =
KmpTaskTQTy->castAsRecordDecl();
3848 const RecordDecl *KmpTaskTWithPrivatesQTyRD =
3851 C.getCanonicalTagType(KmpTaskTWithPrivatesQTyRD);
3852 QualType KmpTaskTWithPrivatesPtrQTy =
3853 C.getPointerType(KmpTaskTWithPrivatesQTy);
3854 llvm::Type *KmpTaskTWithPrivatesPtrTy = CGF.
Builder.getPtrTy(0);
3855 llvm::Value *KmpTaskTWithPrivatesTySize =
3857 QualType SharedsPtrTy =
C.getPointerType(SharedsTy);
3860 llvm::Value *TaskPrivatesMap =
nullptr;
3861 llvm::Type *TaskPrivatesMapTy =
3862 std::next(TaskFunction->arg_begin(), 3)->getType();
3864 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->
field_begin());
3868 TaskPrivatesMap, TaskPrivatesMapTy);
3870 TaskPrivatesMap = llvm::ConstantPointerNull::get(
3876 CGM, Loc, D.getDirectiveKind(), KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy,
3877 KmpTaskTWithPrivatesQTy,
KmpTaskTQTy, SharedsPtrTy, TaskFunction,
3889 DestructorsFlag = 0x8,
3890 PriorityFlag = 0x20,
3891 DetachableFlag = 0x40,
3892 FreeAgentFlag = 0x80,
3893 TransparentFlag = 0x100,
3895 unsigned Flags =
Data.Tied ? TiedFlag : 0;
3896 bool NeedsCleanup =
false;
3901 Flags = Flags | DestructorsFlag;
3905 if (Kind == OMPC_THREADSET_omp_pool)
3906 Flags = Flags | FreeAgentFlag;
3908 if (D.getSingleClause<OMPTransparentClause>())
3909 Flags |= TransparentFlag;
3911 if (
Data.Priority.getInt())
3912 Flags = Flags | PriorityFlag;
3914 Flags = Flags | DetachableFlag;
3915 llvm::Value *TaskFlags =
3916 Data.Final.getPointer()
3917 ? CGF.
Builder.CreateSelect(
Data.Final.getPointer(),
3918 CGF.
Builder.getInt32(FinalFlag),
3920 : CGF.
Builder.getInt32(
Data.Final.getInt() ? FinalFlag : 0);
3921 TaskFlags = CGF.
Builder.CreateOr(TaskFlags, CGF.
Builder.getInt32(Flags));
3922 llvm::Value *SharedsSize =
CGM.getSize(
C.getTypeSizeInChars(SharedsTy));
3924 getThreadID(CGF, Loc), TaskFlags, KmpTaskTWithPrivatesTySize,
3927 llvm::Value *NewTask;
3928 if (D.hasClausesOfKind<OMPNowaitClause>()) {
3934 llvm::Value *DeviceID;
3939 DeviceID = CGF.
Builder.getInt64(OMP_DEVICEID_UNDEF);
3940 AllocArgs.push_back(DeviceID);
3943 CGM.getModule(), OMPRTL___kmpc_omp_target_task_alloc),
3948 CGM.getModule(), OMPRTL___kmpc_omp_task_alloc),
3961 llvm::Value *Tid =
getThreadID(CGF, DC->getBeginLoc());
3962 Tid = CGF.
Builder.CreateIntCast(Tid, CGF.
IntTy,
false);
3965 CGM.getModule(), OMPRTL___kmpc_task_allow_completion_event),
3966 {Loc, Tid, NewTask});
3977 llvm::Value *NumOfElements =
nullptr;
3978 unsigned NumAffinities = 0;
3980 if (
const Expr *Modifier =
C->getModifier()) {
3982 for (
unsigned I = 0, E = IE->numOfIterators(); I < E; ++I) {
3986 NumOfElements ? CGF.
Builder.CreateNUWMul(NumOfElements, Sz) : Sz;
3989 NumAffinities +=
C->varlist_size();
3994 enum RTLAffinityInfoFieldsTy { BaseAddr, Len, Flags };
3996 QualType KmpTaskAffinityInfoArrayTy;
3997 if (NumOfElements) {
3998 NumOfElements = CGF.
Builder.CreateNUWAdd(
3999 llvm::ConstantInt::get(CGF.
SizeTy, NumAffinities), NumOfElements);
4002 C.getIntTypeForBitwidth(
C.getTypeSize(
C.getSizeType()), 0),
4006 KmpTaskAffinityInfoArrayTy =
C.getVariableArrayType(
4014 NumOfElements = CGF.
Builder.CreateIntCast(NumOfElements, CGF.
Int32Ty,
4017 KmpTaskAffinityInfoArrayTy =
C.getConstantArrayType(
4019 llvm::APInt(
C.getTypeSize(
C.getSizeType()), NumAffinities),
nullptr,
4024 NumOfElements = llvm::ConstantInt::get(
CGM.Int32Ty, NumAffinities,
4031 bool HasIterator =
false;
4033 if (
C->getModifier()) {
4037 for (
const Expr *E :
C->varlist()) {
4046 Base, *std::next(KmpAffinityInfoRD->field_begin(), BaseAddr));
4051 Base, *std::next(KmpAffinityInfoRD->field_begin(), Len));
4065 const Expr *Modifier =
C->getModifier();
4068 OMPIteratorGeneratorScope IteratorScope(
4070 for (
const Expr *E :
C->varlist()) {
4080 Base, *std::next(KmpAffinityInfoRD->field_begin(), BaseAddr));
4085 Base, *std::next(KmpAffinityInfoRD->field_begin(), Len));
4087 Idx = CGF.
Builder.CreateNUWAdd(
4088 Idx, llvm::ConstantInt::get(Idx->getType(), 1));
4103 CGM.getModule(), OMPRTL___kmpc_omp_reg_task_with_affinity),
4104 {LocRef, GTid, NewTask, NumOfElements, AffinListPtr});
4106 llvm::Value *NewTaskNewTaskTTy =
4108 NewTask, KmpTaskTWithPrivatesPtrTy);
4110 KmpTaskTWithPrivatesQTy);
4121 *std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTShareds)),
4123 CGF.
Int8Ty,
CGM.getNaturalTypeAlignment(SharedsTy));
4137 CGM, Loc, D, KmpTaskTWithPrivatesPtrQTy, KmpTaskTWithPrivatesQTyRD,
4138 KmpTaskTQTyRD, SharedsTy, SharedsPtrTy,
Data,
Privates,
4139 !
Data.LastprivateVars.empty());
4143 enum { Priority = 0, Destructors = 1 };
4145 auto FI = std::next(KmpTaskTQTyRD->field_begin(), Data1);
4146 const auto *KmpCmplrdataUD = (*FI)->getType()->castAsRecordDecl();
4147 assert(KmpCmplrdataUD->isUnion());
4150 CGM, Loc, KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy,
4151 KmpTaskTWithPrivatesQTy);
4154 Data1LV, *std::next(KmpCmplrdataUD->field_begin(), Destructors));
4160 if (
Data.Priority.getInt()) {
4162 TDBase, *std::next(KmpTaskTQTyRD->field_begin(), Data2));
4164 Data2LV, *std::next(KmpCmplrdataUD->field_begin(), Priority));
4167 Result.NewTask = NewTask;
4168 Result.TaskEntry = TaskEntry;
4169 Result.NewTaskNewTaskTTy = NewTaskNewTaskTTy;
4171 Result.KmpTaskTQTyRD = KmpTaskTQTyRD;
4177 RTLDependenceKindTy DepKind;
4179 case OMPC_DEPEND_in:
4180 DepKind = RTLDependenceKindTy::DepIn;
4183 case OMPC_DEPEND_out:
4184 case OMPC_DEPEND_inout:
4185 DepKind = RTLDependenceKindTy::DepInOut;
4187 case OMPC_DEPEND_mutexinoutset:
4188 DepKind = RTLDependenceKindTy::DepMutexInOutSet;
4190 case OMPC_DEPEND_inoutset:
4191 DepKind = RTLDependenceKindTy::DepInOutSet;
4193 case OMPC_DEPEND_outallmemory:
4194 DepKind = RTLDependenceKindTy::DepOmpAllMem;
4196 case OMPC_DEPEND_source:
4197 case OMPC_DEPEND_sink:
4198 case OMPC_DEPEND_depobj:
4199 case OMPC_DEPEND_inoutallmemory:
4201 llvm_unreachable(
"Unknown task dependence type");
4209 FlagsTy =
C.getIntTypeForBitwidth(
C.getTypeSize(
C.BoolTy),
false);
4210 if (KmpDependInfoTy.
isNull()) {
4211 RecordDecl *KmpDependInfoRD =
C.buildImplicitRecord(
"kmp_depend_info");
4217 KmpDependInfoTy =
C.getCanonicalTagType(KmpDependInfoRD);
4221std::pair<llvm::Value *, LValue>
4234 CGF,
Base.getAddress(),
4235 llvm::ConstantInt::get(CGF.
IntPtrTy, -1,
true));
4241 *std::next(KmpDependInfoRD->field_begin(),
4242 static_cast<unsigned int>(RTLDependInfoFields::BaseAddr)));
4244 return std::make_pair(NumDeps,
Base);
4248 llvm::PointerUnion<unsigned *, LValue *> Pos,
4258 OMPIteratorGeneratorScope IteratorScope(
4259 CGF, cast_or_null<OMPIteratorExpr>(
4260 Data.IteratorExpr ?
Data.IteratorExpr->IgnoreParenImpCasts()
4262 for (
const Expr *E :
Data.DepExprs) {
4272 Size = llvm::ConstantInt::get(CGF.
SizeTy, 0);
4275 if (
unsigned *P = dyn_cast<unsigned *>(Pos)) {
4279 assert(E &&
"Expected a non-null expression");
4288 *std::next(KmpDependInfoRD->field_begin(),
4289 static_cast<unsigned int>(RTLDependInfoFields::BaseAddr)));
4293 Base, *std::next(KmpDependInfoRD->field_begin(),
4294 static_cast<unsigned int>(RTLDependInfoFields::Len)));
4300 *std::next(KmpDependInfoRD->field_begin(),
4301 static_cast<unsigned int>(RTLDependInfoFields::Flags)));
4303 llvm::ConstantInt::get(LLVMFlagsTy,
static_cast<unsigned int>(DepKind)),
4305 if (
unsigned *P = dyn_cast<unsigned *>(Pos)) {
4310 Idx = CGF.
Builder.CreateNUWAdd(Idx,
4311 llvm::ConstantInt::get(Idx->getType(), 1));
4320 assert(
Data.DepKind == OMPC_DEPEND_depobj &&
4321 "Expected depobj dependency kind.");
4326 OMPIteratorGeneratorScope IteratorScope(
4327 CGF, cast_or_null<OMPIteratorExpr>(
4328 Data.IteratorExpr ?
Data.IteratorExpr->IgnoreParenImpCasts()
4330 for (
const Expr *E :
Data.DepExprs) {
4331 llvm::Value *NumDeps;
4334 std::tie(NumDeps,
Base) =
4338 C.getUIntPtrType());
4342 llvm::Value *Add = CGF.
Builder.CreateNUWAdd(PrevVal, NumDeps);
4344 SizeLVals.push_back(NumLVal);
4347 for (
unsigned I = 0, E = SizeLVals.size(); I < E; ++I) {
4350 Sizes.push_back(Size);
4360 assert(
Data.DepKind == OMPC_DEPEND_depobj &&
4361 "Expected depobj dependency kind.");
4364 OMPIteratorGeneratorScope IteratorScope(
4365 CGF, cast_or_null<OMPIteratorExpr>(
4366 Data.IteratorExpr ?
Data.IteratorExpr->IgnoreParenImpCasts()
4368 for (
const Expr *E :
Data.DepExprs) {
4369 llvm::Value *NumDeps;
4372 std::tie(NumDeps,
Base) =
4376 llvm::Value *Size = CGF.
Builder.CreateNUWMul(
4385 llvm::Value *Add = CGF.
Builder.CreateNUWAdd(Pos, NumDeps);
4401 llvm::Value *NumOfElements =
nullptr;
4402 unsigned NumDependencies = std::accumulate(
4403 Dependencies.begin(), Dependencies.end(), 0,
4405 return D.DepKind == OMPC_DEPEND_depobj
4407 : (V + (D.IteratorExpr ? 0 : D.DepExprs.size()));
4411 bool HasDepobjDeps =
false;
4412 bool HasRegularWithIterators =
false;
4413 llvm::Value *NumOfDepobjElements = llvm::ConstantInt::get(CGF.
IntPtrTy, 0);
4414 llvm::Value *NumOfRegularWithIterators =
4415 llvm::ConstantInt::get(CGF.
IntPtrTy, 0);
4419 if (D.
DepKind == OMPC_DEPEND_depobj) {
4422 for (llvm::Value *Size : Sizes) {
4423 NumOfDepobjElements =
4424 CGF.
Builder.CreateNUWAdd(NumOfDepobjElements, Size);
4426 HasDepobjDeps =
true;
4431 if (
const auto *IE = cast_or_null<OMPIteratorExpr>(D.
IteratorExpr)) {
4432 llvm::Value *ClauseIteratorSpace =
4433 llvm::ConstantInt::get(CGF.
IntPtrTy, 1);
4437 ClauseIteratorSpace = CGF.
Builder.CreateNUWMul(Sz, ClauseIteratorSpace);
4439 llvm::Value *NumClauseDeps = CGF.
Builder.CreateNUWMul(
4440 ClauseIteratorSpace,
4442 NumOfRegularWithIterators =
4443 CGF.
Builder.CreateNUWAdd(NumOfRegularWithIterators, NumClauseDeps);
4444 HasRegularWithIterators =
true;
4450 if (HasDepobjDeps || HasRegularWithIterators) {
4451 NumOfElements = llvm::ConstantInt::get(
CGM.IntPtrTy, NumDependencies,
4453 if (HasDepobjDeps) {
4455 CGF.
Builder.CreateNUWAdd(NumOfDepobjElements, NumOfElements);
4457 if (HasRegularWithIterators) {
4459 CGF.
Builder.CreateNUWAdd(NumOfRegularWithIterators, NumOfElements);
4462 Loc,
C.getIntTypeForBitwidth(64, 0),
4466 KmpDependInfoArrayTy =
4475 NumOfElements = CGF.
Builder.CreateIntCast(NumOfElements, CGF.
Int32Ty,
4478 KmpDependInfoArrayTy =
C.getConstantArrayType(
4484 NumOfElements = llvm::ConstantInt::get(
CGM.Int32Ty, NumDependencies,
4489 if (Dep.DepKind == OMPC_DEPEND_depobj || Dep.IteratorExpr)
4499 if (Dep.DepKind == OMPC_DEPEND_depobj || !Dep.IteratorExpr)
4504 if (HasDepobjDeps) {
4506 if (Dep.DepKind != OMPC_DEPEND_depobj)
4513 return std::make_pair(NumOfElements, DependenciesArray);
4524 unsigned NumDependencies = Dependencies.
DepExprs.size();
4534 llvm::Value *NumDepsVal;
4536 if (
const auto *IE =
4537 cast_or_null<OMPIteratorExpr>(Dependencies.
IteratorExpr)) {
4538 NumDepsVal = llvm::ConstantInt::get(CGF.
SizeTy, 1);
4542 NumDepsVal = CGF.
Builder.CreateNUWMul(NumDepsVal, Sz);
4544 Size = CGF.
Builder.CreateNUWAdd(llvm::ConstantInt::get(CGF.
SizeTy, 1),
4548 llvm::Value *RecSize =
CGM.getSize(SizeInBytes);
4549 Size = CGF.
Builder.CreateNUWMul(Size, RecSize);
4553 QualType KmpDependInfoArrayTy =
C.getConstantArrayType(
4556 CharUnits Sz =
C.getTypeSizeInChars(KmpDependInfoArrayTy);
4558 NumDepsVal = llvm::ConstantInt::get(CGF.
IntPtrTy, NumDependencies);
4563 llvm::Value *Allocator = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
4564 llvm::Value *Args[] = {ThreadID, Size, Allocator};
4568 CGM.getModule(), OMPRTL___kmpc_alloc),
4569 Args,
".dep.arr.addr");
4573 DependenciesArray =
Address(
Addr, KmpDependInfoLlvmTy, Align);
4579 *std::next(KmpDependInfoRD->field_begin(),
4580 static_cast<unsigned int>(RTLDependInfoFields::BaseAddr)));
4582 llvm::PointerUnion<unsigned *, LValue *> Pos;
4599 return DependenciesArray;
4614 Addr.getElementType(),
Addr.emitRawPointer(CGF),
4615 llvm::ConstantInt::get(CGF.
IntPtrTy, -1,
true));
4620 llvm::Value *Allocator = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
4621 llvm::Value *Args[] = {ThreadID, DepObjAddr, Allocator};
4625 CGM.getModule(), OMPRTL___kmpc_free),
4637 llvm::Value *NumDeps;
4648 llvm::BasicBlock *EntryBB = CGF.
Builder.GetInsertBlock();
4650 llvm::PHINode *ElementPHI =
4655 Base.getTBAAInfo());
4659 Base, *std::next(KmpDependInfoRD->field_begin(),
4660 static_cast<unsigned int>(RTLDependInfoFields::Flags)));
4662 llvm::ConstantInt::get(LLVMFlagsTy,
static_cast<unsigned int>(DepKind)),
4666 llvm::Value *ElementNext =
4669 ElementPHI->addIncoming(ElementNext, CGF.
Builder.GetInsertBlock());
4670 llvm::Value *IsEmpty =
4671 CGF.
Builder.CreateICmpEQ(ElementNext, End,
"omp.isempty");
4672 CGF.
Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
4679 llvm::Function *TaskFunction,
4688 llvm::Value *NewTask =
Result.NewTask;
4689 llvm::Function *TaskEntry =
Result.TaskEntry;
4690 llvm::Value *NewTaskNewTaskTTy =
Result.NewTaskNewTaskTTy;
4695 llvm::Value *NumOfElements;
4696 std::tie(NumOfElements, DependenciesArray) =
4707 llvm::Value *TaskArgs[] = { UpLoc, ThreadID, NewTask };
4708 llvm::Value *DepTaskArgs[7];
4709 if (!
Data.Dependences.empty()) {
4710 DepTaskArgs[0] = UpLoc;
4711 DepTaskArgs[1] = ThreadID;
4712 DepTaskArgs[2] = NewTask;
4713 DepTaskArgs[3] = NumOfElements;
4715 DepTaskArgs[5] = CGF.
Builder.getInt32(0);
4716 DepTaskArgs[6] = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
4718 auto &&ThenCodeGen = [
this, &
Data, TDBase, KmpTaskTQTyRD, &TaskArgs,
4721 auto PartIdFI = std::next(KmpTaskTQTyRD->
field_begin(), KmpTaskTPartId);
4725 if (!
Data.Dependences.empty()) {
4728 CGM.getModule(), OMPRTL___kmpc_omp_task_with_deps),
4732 CGM.getModule(), OMPRTL___kmpc_omp_task),
4738 Region->emitUntiedSwitch(CGF);
4741 llvm::Value *DepWaitTaskArgs[7];
4742 if (!
Data.Dependences.empty()) {
4743 DepWaitTaskArgs[0] = UpLoc;
4744 DepWaitTaskArgs[1] = ThreadID;
4745 DepWaitTaskArgs[2] = NumOfElements;
4747 DepWaitTaskArgs[4] = CGF.
Builder.getInt32(0);
4748 DepWaitTaskArgs[5] = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
4749 DepWaitTaskArgs[6] =
4750 llvm::ConstantInt::get(CGF.
Int32Ty,
Data.HasNowaitClause);
4752 auto &M =
CGM.getModule();
4753 auto &&ElseCodeGen = [
this, &M, &TaskArgs, ThreadID, NewTaskNewTaskTTy,
4754 TaskEntry, &
Data, &DepWaitTaskArgs,
4761 if (!
Data.Dependences.empty())
4763 M, OMPRTL___kmpc_omp_taskwait_deps_51),
4766 auto &&
CodeGen = [TaskEntry, ThreadID, NewTaskNewTaskTTy,
4769 llvm::Value *OutlinedFnArgs[] = {ThreadID, NewTaskNewTaskTTy};
4770 CGF.CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, Loc, TaskEntry,
4779 CommonActionTy Action(
OMPBuilder.getOrCreateRuntimeFunction(
4780 M, OMPRTL___kmpc_omp_task_begin_if0),
4783 M, OMPRTL___kmpc_omp_task_complete_if0),
4799 llvm::Function *TaskFunction,
4819 IfVal = llvm::ConstantInt::getSigned(CGF.
IntTy, 1);
4824 *std::next(
Result.KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound));
4831 *std::next(
Result.KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound));
4838 *std::next(
Result.KmpTaskTQTyRD->field_begin(), KmpTaskTStride));
4846 *std::next(
Result.KmpTaskTQTyRD->field_begin(), KmpTaskTReductions));
4847 if (
Data.Reductions) {
4853 enum { NoSchedule = 0, Grainsize = 1, NumTasks = 2 };
4862 llvm::ConstantInt::getSigned(
4864 llvm::ConstantInt::getSigned(
4866 ?
Data.Schedule.getInt() ? NumTasks : Grainsize
4868 Data.Schedule.getPointer()
4871 : llvm::ConstantInt::get(CGF.
Int64Ty, 0)};
4872 if (
Data.HasModifier)
4873 TaskArgs.push_back(llvm::ConstantInt::get(CGF.
Int32Ty, 1));
4875 TaskArgs.push_back(
Result.TaskDupFn
4878 : llvm::ConstantPointerNull::get(CGF.
VoidPtrTy));
4880 CGM.getModule(),
Data.HasModifier
4881 ? OMPRTL___kmpc_taskloop_5
4882 : OMPRTL___kmpc_taskloop),
4899 const Expr *,
const Expr *)> &RedOpGen,
4900 const Expr *XExpr =
nullptr,
const Expr *EExpr =
nullptr,
4901 const Expr *UpExpr =
nullptr) {
4909 llvm::Value *NumElements = CGF.
emitArrayLength(ArrayTy, ElementTy, LHSAddr);
4914 llvm::Value *LHSEnd =
4919 llvm::Value *IsEmpty =
4920 CGF.
Builder.CreateICmpEQ(LHSBegin, LHSEnd,
"omp.arraycpy.isempty");
4921 CGF.
Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
4924 llvm::BasicBlock *EntryBB = CGF.
Builder.GetInsertBlock();
4929 llvm::PHINode *RHSElementPHI = CGF.
Builder.CreatePHI(
4930 RHSBegin->getType(), 2,
"omp.arraycpy.srcElementPast");
4931 RHSElementPHI->addIncoming(RHSBegin, EntryBB);
4936 llvm::PHINode *LHSElementPHI = CGF.
Builder.CreatePHI(
4937 LHSBegin->getType(), 2,
"omp.arraycpy.destElementPast");
4938 LHSElementPHI->addIncoming(LHSBegin, EntryBB);
4945 Scope.addPrivate(LHSVar, LHSElementCurrent);
4946 Scope.addPrivate(RHSVar, RHSElementCurrent);
4948 RedOpGen(CGF, XExpr, EExpr, UpExpr);
4949 Scope.ForceCleanup();
4952 llvm::Value *LHSElementNext = CGF.
Builder.CreateConstGEP1_32(
4954 "omp.arraycpy.dest.element");
4955 llvm::Value *RHSElementNext = CGF.
Builder.CreateConstGEP1_32(
4957 "omp.arraycpy.src.element");
4960 CGF.
Builder.CreateICmpEQ(LHSElementNext, LHSEnd,
"omp.arraycpy.done");
4961 CGF.
Builder.CreateCondBr(Done, DoneBB, BodyBB);
4962 LHSElementPHI->addIncoming(LHSElementNext, CGF.
Builder.GetInsertBlock());
4963 RHSElementPHI->addIncoming(RHSElementNext, CGF.
Builder.GetInsertBlock());
4973 const Expr *ReductionOp) {
4974 if (
const auto *CE = dyn_cast<CallExpr>(ReductionOp))
4975 if (
const auto *OVE = dyn_cast<OpaqueValueExpr>(CE->getCallee()))
4976 if (
const auto *DRE =
4977 dyn_cast<DeclRefExpr>(OVE->getSourceExpr()->IgnoreImpCasts()))
4978 if (
const auto *DRD =
4979 dyn_cast<OMPDeclareReductionDecl>(DRE->getDecl())) {
4980 std::pair<llvm::Function *, llvm::Function *>
Reduction =
4991 StringRef ReducerName,
SourceLocation Loc, llvm::Type *ArgsElemType,
5005 CGM.getTypes().arrangeBuiltinFunctionDeclaration(
C.VoidTy, Args);
5007 auto *Fn = llvm::Function::Create(
CGM.getTypes().GetFunctionType(CGFI),
5008 llvm::GlobalValue::InternalLinkage, Name,
5011 if (!
CGM.getCodeGenOpts().SampleProfileFile.empty())
5012 Fn->addFnAttr(
"sample-profile-suffix-elision-policy",
"selected");
5013 Fn->setDoesNotRecurse();
5032 const auto *IPriv =
Privates.begin();
5034 for (
unsigned I = 0, E = ReductionOps.size(); I < E; ++I, ++IPriv, ++Idx) {
5035 const auto *RHSVar =
5038 const auto *LHSVar =
5041 QualType PrivTy = (*IPriv)->getType();
5057 const auto *ILHS = LHSExprs.begin();
5058 const auto *IRHS = RHSExprs.begin();
5059 for (
const Expr *E : ReductionOps) {
5060 if ((*IPriv)->getType()->isArrayType()) {
5065 CGF, (*IPriv)->getType(), LHSVar, RHSVar,
5067 emitReductionCombiner(CGF, E);
5077 Scope.ForceCleanup();
5083 const Expr *ReductionOp,
5084 const Expr *PrivateRef,
5092 CGF, PrivateRef->
getType(), LHSVar, RHSVar,
5094 emitReductionCombiner(CGF, ReductionOp);
5103 llvm::StringRef Prefix,
const Expr *Ref);
5107 const Expr *LHSExprs,
const Expr *RHSExprs,
const Expr *ReductionOps) {
5134 std::string ReductionVarNameStr;
5135 if (
const auto *DRE = dyn_cast<DeclRefExpr>(
Privates->IgnoreParenCasts()))
5136 ReductionVarNameStr =
5139 ReductionVarNameStr =
"unnamed_priv_var";
5142 std::string SharedName =
5143 CGM.getOpenMPRuntime().getName({
"internal_pivate_", ReductionVarNameStr});
5144 llvm::GlobalVariable *SharedVar =
OMPBuilder.getOrCreateInternalVariable(
5145 LLVMType,
".omp.reduction." + SharedName);
5147 SharedVar->setAlignment(
5155 llvm::Value *BarrierArgs[] = {BarrierLoc, ThreadId};
5160 llvm::Value *IsWorker = CGF.
Builder.CreateICmpEQ(
5161 ThreadId, llvm::ConstantInt::get(ThreadId->getType(), 0));
5162 CGF.
Builder.CreateCondBr(IsWorker, InitBB, InitEndBB);
5166 auto EmitSharedInit = [&]() {
5169 std::pair<llvm::Function *, llvm::Function *> FnPair =
5171 llvm::Function *InitializerFn = FnPair.second;
5172 if (InitializerFn) {
5173 if (
const auto *CE =
5174 dyn_cast<CallExpr>(UDRInitExpr->IgnoreParenImpCasts())) {
5181 LocalScope.addPrivate(OutVD, SharedResult);
5183 (void)LocalScope.Privatize();
5184 if (
const auto *OVE = dyn_cast<OpaqueValueExpr>(
5185 CE->getCallee()->IgnoreParenImpCasts())) {
5211 if (
const auto *DRE = dyn_cast<DeclRefExpr>(
Privates)) {
5212 if (
const auto *VD = dyn_cast<VarDecl>(DRE->getDecl())) {
5223 CGF.
Builder.CreateBr(InitEndBB);
5227 CGM.getModule(), OMPRTL___kmpc_barrier),
5230 const Expr *ReductionOp = ReductionOps;
5235 auto EmitCriticalReduction = [&](
auto ReductionGen) {
5236 std::string CriticalName =
getName({
"reduction_critical"});
5244 std::pair<llvm::Function *, llvm::Function *> FnPair =
5247 if (
const auto *CE = dyn_cast<CallExpr>(ReductionOp)) {
5259 (void)LocalScope.Privatize();
5264 EmitCriticalReduction(ReductionGen);
5269 if (
const auto *Cleanup = dyn_cast<ExprWithCleanups>(ReductionClauseExpr))
5272 const Expr *AssignRHS =
nullptr;
5273 if (
const auto *BinOp = dyn_cast<BinaryOperator>(ReductionClauseExpr)) {
5274 if (BinOp->getOpcode() == BO_Assign)
5275 AssignRHS = BinOp->getRHS();
5276 }
else if (
const auto *OpCall =
5277 dyn_cast<CXXOperatorCallExpr>(ReductionClauseExpr)) {
5278 if (OpCall->getOperator() == OO_Equal)
5279 AssignRHS = OpCall->getArg(1);
5283 "Private Variable Reduction : Invalid ReductionOp expression");
5288 const auto *OmpOutDRE =
5290 const auto *OmpInDRE =
5293 OmpOutDRE && OmpInDRE &&
5294 "Private Variable Reduction : LHSExpr/RHSExpr must be DeclRefExprs");
5298 LocalScope.addPrivate(OmpOutVD, SharedLV.
getAddress());
5299 LocalScope.addPrivate(OmpInVD, LHSLV.
getAddress());
5300 (void)LocalScope.Privatize();
5304 EmitCriticalReduction(ReductionGen);
5308 CGM.getModule(), OMPRTL___kmpc_barrier),
5314 llvm::Value *FinalResultVal =
nullptr;
5318 FinalResultAddr = SharedResult;
5332 CGM.getModule(), OMPRTL___kmpc_barrier),
5343 EmitCriticalReduction(OriginalListCombiner);
5395 if (SimpleReduction) {
5397 const auto *IPriv = OrgPrivates.begin();
5398 const auto *ILHS = OrgLHSExprs.begin();
5399 const auto *IRHS = OrgRHSExprs.begin();
5400 for (
const Expr *E : OrgReductionOps) {
5413 FilteredRHSExprs, FilteredReductionOps;
5414 for (
unsigned I : llvm::seq<unsigned>(
5415 std::min(OrgReductionOps.size(), OrgLHSExprs.size()))) {
5417 FilteredPrivates.emplace_back(OrgPrivates[I]);
5418 FilteredLHSExprs.emplace_back(OrgLHSExprs[I]);
5419 FilteredRHSExprs.emplace_back(OrgRHSExprs[I]);
5420 FilteredReductionOps.emplace_back(OrgReductionOps[I]);
5432 auto Size = RHSExprs.size();
5438 llvm::APInt ArraySize(32, Size);
5439 QualType ReductionArrayTy =
C.getConstantArrayType(
5443 CGF.
CreateMemTemp(ReductionArrayTy,
".omp.reduction.red_list");
5444 const auto *IPriv =
Privates.begin();
5446 for (
unsigned I = 0, E = RHSExprs.size(); I < E; ++I, ++IPriv, ++Idx) {
5452 if ((*IPriv)->getType()->isVariablyModifiedType()) {
5456 llvm::Value *Size = CGF.
Builder.CreateIntCast(
5469 Privates, LHSExprs, RHSExprs, ReductionOps);
5472 std::string Name =
getName({
"reduction"});
5479 llvm::Value *ReductionArrayTySize = CGF.
getTypeSize(ReductionArrayTy);
5482 llvm::Value *Args[] = {
5485 CGF.
Builder.getInt32(RHSExprs.size()),
5486 ReductionArrayTySize,
5494 WithNowait ? OMPRTL___kmpc_reduce_nowait : OMPRTL___kmpc_reduce),
5498 llvm::BasicBlock *DefaultBB = CGF.
createBasicBlock(
".omp.reduction.default");
5499 llvm::SwitchInst *SwInst =
5500 CGF.
Builder.CreateSwitch(Res, DefaultBB, 2);
5509 SwInst->addCase(CGF.
Builder.getInt32(1), Case1BB);
5513 llvm::Value *EndArgs[] = {
5521 const auto *IPriv =
Privates.begin();
5522 const auto *ILHS = LHSExprs.begin();
5523 const auto *IRHS = RHSExprs.begin();
5524 for (
const Expr *E : ReductionOps) {
5533 CommonActionTy Action(
5536 CGM.getModule(), WithNowait ? OMPRTL___kmpc_end_reduce_nowait
5537 : OMPRTL___kmpc_end_reduce),
5550 SwInst->addCase(CGF.
Builder.getInt32(2), Case2BB);
5553 auto &&AtomicCodeGen = [Loc,
Privates, LHSExprs, RHSExprs, ReductionOps](
5555 const auto *ILHS = LHSExprs.begin();
5556 const auto *IRHS = RHSExprs.begin();
5557 const auto *IPriv =
Privates.begin();
5558 for (
const Expr *E : ReductionOps) {
5559 const Expr *XExpr =
nullptr;
5560 const Expr *EExpr =
nullptr;
5561 const Expr *UpExpr =
nullptr;
5563 if (
const auto *BO = dyn_cast<BinaryOperator>(E)) {
5564 if (BO->getOpcode() == BO_Assign) {
5565 XExpr = BO->getLHS();
5566 UpExpr = BO->getRHS();
5570 const Expr *RHSExpr = UpExpr;
5573 if (
const auto *ACO = dyn_cast<AbstractConditionalOperator>(
5577 RHSExpr = ACO->getCond();
5579 if (
const auto *BORHS =
5581 EExpr = BORHS->getRHS();
5582 BO = BORHS->getOpcode();
5587 auto &&AtomicRedGen = [BO, VD,
5589 const Expr *EExpr,
const Expr *UpExpr) {
5590 LValue X = CGF.EmitLValue(XExpr);
5593 E = CGF.EmitAnyExpr(EExpr);
5594 CGF.EmitOMPAtomicSimpleUpdateExpr(
5596 llvm::AtomicOrdering::Monotonic, Loc,
5597 [&CGF, UpExpr, VD, Loc](
RValue XRValue) {
5599 Address LHSTemp = CGF.CreateMemTemp(VD->getType());
5600 CGF.emitOMPSimpleStore(
5601 CGF.MakeAddrLValue(LHSTemp, VD->
getType()), XRValue,
5602 VD->getType().getNonReferenceType(), Loc);
5605 return CGF.EmitAnyExpr(UpExpr);
5608 if ((*IPriv)->getType()->isArrayType()) {
5610 const auto *RHSVar =
5613 AtomicRedGen, XExpr, EExpr, UpExpr);
5616 AtomicRedGen(CGF, XExpr, EExpr, UpExpr);
5623 std::string Name = RT.
getName({
"atomic_reduction"});
5632 if ((*IPriv)->getType()->isArrayType()) {
5633 const auto *LHSVar =
5635 const auto *RHSVar =
5640 CritRedGen(CGF,
nullptr,
nullptr,
nullptr);
5651 llvm::Value *EndArgs[] = {
5656 CommonActionTy Action(
nullptr, {},
5658 CGM.getModule(), OMPRTL___kmpc_end_reduce),
5668 assert(OrgLHSExprs.size() == OrgPrivates.size() &&
5669 "PrivateVarReduction: Privates size mismatch");
5670 assert(OrgLHSExprs.size() == OrgReductionOps.size() &&
5671 "PrivateVarReduction: ReductionOps size mismatch");
5672 for (
unsigned I : llvm::seq<unsigned>(
5673 std::min(OrgReductionOps.size(), OrgLHSExprs.size()))) {
5676 OrgRHSExprs[I], OrgReductionOps[I]);
5685 llvm::raw_svector_ostream Out(Buffer);
5693 Out << Prefix << Name <<
"_"
5695 return std::string(Out.str());
5719 Args.emplace_back(Param);
5720 Args.emplace_back(ParamOrig);
5721 const auto &FnInfo =
5725 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
5729 Fn->addFnAttr(
"sample-profile-suffix-elision-policy",
"selected");
5730 Fn->setDoesNotRecurse();
5737 llvm::Value *Size =
nullptr;
5780 const Expr *ReductionOp,
5782 const Expr *PrivateRef) {
5793 Args.emplace_back(ParamInOut);
5794 Args.emplace_back(ParamIn);
5795 const auto &FnInfo =
5799 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
5803 Fn->addFnAttr(
"sample-profile-suffix-elision-policy",
"selected");
5804 Fn->setDoesNotRecurse();
5807 llvm::Value *Size =
nullptr;
5828 C.getPointerType(LHSVD->getType())->castAs<
PointerType>()));
5835 C.getPointerType(RHSVD->getType())->castAs<
PointerType>()));
5865 Args.emplace_back(Param);
5866 const auto &FnInfo =
5870 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
5874 Fn->addFnAttr(
"sample-profile-suffix-elision-policy",
"selected");
5875 Fn->setDoesNotRecurse();
5880 llvm::Value *Size =
nullptr;
5915 RecordDecl *RD =
C.buildImplicitRecord(
"kmp_taskred_input_t");
5924 C, RD,
C.getIntTypeForBitwidth(32,
false));
5927 unsigned Size =
Data.ReductionVars.size();
5928 llvm::APInt ArraySize(64, Size);
5930 C.getConstantArrayType(RDType, ArraySize,
nullptr,
5935 Data.ReductionCopies,
Data.ReductionOps);
5936 for (
unsigned Cnt = 0; Cnt < Size; ++Cnt) {
5938 llvm::Value *Idxs[] = {llvm::ConstantInt::get(
CGM.SizeTy, 0),
5939 llvm::ConstantInt::get(
CGM.SizeTy, Cnt)};
5955 llvm::Value *SizeValInChars;
5956 llvm::Value *SizeVal;
5957 std::tie(SizeValInChars, SizeVal) = RCG.
getSizes(Cnt);
5963 bool DelayedCreation = !!SizeVal;
5964 SizeValInChars = CGF.
Builder.CreateIntCast(SizeValInChars,
CGM.SizeTy,
5975 llvm::Value *FiniAddr =
5976 Fini ? Fini : llvm::ConstantPointerNull::get(
CGM.VoidPtrTy);
5981 CGM, Loc, RCG, Cnt,
Data.ReductionOps[Cnt], LHSExprs[Cnt],
5982 RHSExprs[Cnt],
Data.ReductionCopies[Cnt]);
5986 if (DelayedCreation) {
5988 llvm::ConstantInt::get(
CGM.Int32Ty, 1,
true),
5993 if (
Data.IsReductionWithTaskMod) {
5999 llvm::Value *Args[] = {
6001 llvm::ConstantInt::get(
CGM.IntTy,
Data.IsWorksharingReduction ? 1 : 0,
6003 llvm::ConstantInt::get(
CGM.IntTy, Size,
true),
6008 CGM.getModule(), OMPRTL___kmpc_taskred_modifier_init),
6012 llvm::Value *Args[] = {
6015 llvm::ConstantInt::get(
CGM.IntTy, Size,
true),
6019 CGM.getModule(), OMPRTL___kmpc_taskred_init),
6025 bool IsWorksharingReduction) {
6031 llvm::Value *Args[] = {IdentTLoc, GTid,
6032 llvm::ConstantInt::get(
CGM.IntTy,
6033 IsWorksharingReduction ? 1 : 0,
6037 CGM.getModule(), OMPRTL___kmpc_task_reduction_modifier_fini),
6049 llvm::Value *SizeVal = CGF.
Builder.CreateIntCast(Sizes.second,
CGM.SizeTy,
6052 CGF,
CGM.getContext().getSizeType(),
6060 llvm::Value *ReductionsPtr,
6073 CGM.getModule(), OMPRTL___kmpc_task_reduction_get_th_data),
6089 auto &M =
CGM.getModule();
6091 llvm::Value *NumOfElements;
6092 std::tie(NumOfElements, DependenciesArray) =
6094 if (!
Data.Dependences.empty()) {
6095 llvm::Value *DepWaitTaskArgs[7];
6096 DepWaitTaskArgs[0] = UpLoc;
6097 DepWaitTaskArgs[1] = ThreadID;
6098 DepWaitTaskArgs[2] = NumOfElements;
6100 DepWaitTaskArgs[4] = CGF.
Builder.getInt32(0);
6101 DepWaitTaskArgs[5] = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
6102 DepWaitTaskArgs[6] =
6103 llvm::ConstantInt::get(CGF.
Int32Ty,
Data.HasNowaitClause);
6112 M, OMPRTL___kmpc_omp_taskwait_deps_51),
6119 llvm::Value *Args[] = {UpLoc, ThreadID};
6122 OMPBuilder.getOrCreateRuntimeFunction(M, OMPRTL___kmpc_omp_taskwait),
6127 if (
auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.
CapturedStmtInfo))
6128 Region->emitUntiedSwitch(CGF);
6137 InlinedOpenMPRegionRAII Region(CGF,
CodeGen, InnerKind, HasCancel,
6138 InnerKind != OMPD_critical &&
6139 InnerKind != OMPD_master &&
6140 InnerKind != OMPD_masked);
6155 RTCancelKind CancelKind = CancelNoreq;
6156 if (CancelRegion == OMPD_parallel)
6157 CancelKind = CancelParallel;
6158 else if (CancelRegion == OMPD_for)
6159 CancelKind = CancelLoop;
6160 else if (CancelRegion == OMPD_sections)
6161 CancelKind = CancelSections;
6163 assert(CancelRegion == OMPD_taskgroup);
6164 CancelKind = CancelTaskgroup;
6176 if (
auto *OMPRegionInfo =
6180 if (CancelRegion == OMPD_taskgroup || OMPRegionInfo->hasCancel()) {
6181 llvm::Value *Args[] = {
6187 CGM.getModule(), OMPRTL___kmpc_cancellationpoint),
6196 CGF.
Builder.CreateCondBr(
Cmp, ExitBB, ContBB);
6198 if (CancelRegion == OMPD_parallel)
6216 auto &M =
CGM.getModule();
6217 if (
auto *OMPRegionInfo =
6219 auto &&ThenGen = [
this, &M, Loc, CancelRegion,
6222 llvm::Value *Args[] = {
6226 llvm::Value *
Result = CGF.EmitRuntimeCall(
6227 OMPBuilder.getOrCreateRuntimeFunction(M, OMPRTL___kmpc_cancel), Args);
6232 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(
".cancel.exit");
6233 llvm::BasicBlock *ContBB = CGF.createBasicBlock(
".cancel.continue");
6234 llvm::Value *
Cmp = CGF.Builder.CreateIsNotNull(
Result);
6235 CGF.Builder.CreateCondBr(
Cmp, ExitBB, ContBB);
6236 CGF.EmitBlock(ExitBB);
6237 if (CancelRegion == OMPD_parallel)
6241 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind());
6242 CGF.EmitBranchThroughCleanup(CancelDest);
6243 CGF.EmitBlock(ContBB,
true);
6261 OMPUsesAllocatorsActionTy(
6262 ArrayRef<std::pair<const Expr *, const Expr *>> Allocators)
6263 : Allocators(Allocators) {}
6267 for (
const auto &AllocatorData : Allocators) {
6269 CGF, AllocatorData.first, AllocatorData.second);
6272 void Exit(CodeGenFunction &CGF)
override {
6275 for (
const auto &AllocatorData : Allocators) {
6277 AllocatorData.first);
6285 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
6287 assert(!ParentName.empty() &&
"Invalid target entry parent name!");
6291 for (
unsigned I = 0, E =
C->getNumberOfAllocators(); I < E; ++I) {
6298 OMPUsesAllocatorsActionTy UsesAllocatorAction(Allocators);
6299 CodeGen.setAction(UsesAllocatorAction);
6305 const Expr *Allocator,
6306 const Expr *AllocatorTraits) {
6308 ThreadId = CGF.
Builder.CreateIntCast(ThreadId, CGF.
IntTy,
true);
6310 llvm::Value *MemSpaceHandle = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
6311 llvm::Value *NumTraits = llvm::ConstantInt::get(
6315 .getLimitedValue());
6322 llvm::Value *Traits =
Addr.emitRawPointer(CGF);
6324 llvm::Value *AllocatorVal =
6326 CGM.getModule(), OMPRTL___kmpc_init_allocator),
6327 {ThreadId, MemSpaceHandle, NumTraits, Traits});
6339 const Expr *Allocator) {
6341 ThreadId = CGF.
Builder.CreateIntCast(ThreadId, CGF.
IntTy,
true);
6343 llvm::Value *AllocatorVal =
6350 OMPRTL___kmpc_destroy_allocator),
6351 {ThreadId, AllocatorVal});
6356 llvm::OpenMPIRBuilder::TargetKernelDefaultAttrs &Attrs) {
6357 assert(Attrs.MaxTeams.size() == 1 && Attrs.MaxThreads.size() == 1 &&
6358 "invalid default attrs structure");
6359 int32_t &MaxTeamsVal = Attrs.MaxTeams.front();
6360 int32_t &MaxThreadsVal = Attrs.MaxThreads.front();
6368 for (
auto *A :
C->getAttrs()) {
6369 int32_t AttrMinThreadsVal = 1, AttrMaxThreadsVal = -1;
6370 int32_t AttrMinBlocksVal = 1, AttrMaxBlocksVal = -1;
6371 if (
auto *
Attr = dyn_cast<CUDALaunchBoundsAttr>(A))
6372 CGM.handleCUDALaunchBoundsAttr(
nullptr,
Attr, &AttrMaxThreadsVal,
6373 &AttrMinBlocksVal, &AttrMaxBlocksVal);
6374 else if (
auto *
Attr = dyn_cast<AMDGPUFlatWorkGroupSizeAttr>(A))
6375 CGM.handleAMDGPUFlatWorkGroupSizeAttr(
6376 nullptr,
Attr,
nullptr, &AttrMinThreadsVal,
6377 &AttrMaxThreadsVal);
6381 Attrs.MinThreads.front() =
6382 std::max(Attrs.MinThreads.front(), AttrMinThreadsVal);
6383 if (AttrMaxThreadsVal > 0)
6384 MaxThreadsVal = MaxThreadsVal > 0
6385 ? std::min(MaxThreadsVal, AttrMaxThreadsVal)
6386 : AttrMaxThreadsVal;
6387 Attrs.MinTeams.front() =
6388 std::max(Attrs.MinTeams.front(), AttrMinBlocksVal);
6389 if (AttrMaxBlocksVal > 0)
6390 MaxTeamsVal = MaxTeamsVal > 0 ? std::min(MaxTeamsVal, AttrMaxBlocksVal)
6398 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
6401 llvm::TargetRegionEntryInfo EntryInfo =
6405 llvm::OpenMPIRBuilder::FunctionGenCallback &&GenerateOutlinedFunction =
6406 [&CGF, &D, &
CodeGen,
this](StringRef EntryFnName) {
6407 const CapturedStmt &CS = *D.getCapturedStmt(OMPD_target);
6409 CGOpenMPTargetRegionInfo CGInfo(CS,
CodeGen, EntryFnName);
6411 if (
CGM.getLangOpts().OpenMPIsTargetDevice && !
isGPU())
6416 cantFail(
OMPBuilder.emitTargetRegionFunction(
6417 EntryInfo, GenerateOutlinedFunction, IsOffloadEntry, OutlinedFn,
6425 OutlinedFn->setDoesNotRecurse();
6427 CGM.getTargetCodeGenInfo().setTargetAttributes(
nullptr, OutlinedFn,
CGM);
6430 for (
auto *A :
C->getAttrs()) {
6431 if (
auto *
Attr = dyn_cast<AMDGPUWavesPerEUAttr>(A))
6432 CGM.handleAMDGPUWavesPerEUAttr(OutlinedFn,
Attr);
6451 while (
const auto *
C = dyn_cast_or_null<CompoundStmt>(Child)) {
6453 for (
const Stmt *S :
C->body()) {
6454 if (
const auto *E = dyn_cast<Expr>(S)) {
6463 if (
const auto *DS = dyn_cast<DeclStmt>(S)) {
6464 if (llvm::all_of(DS->decls(), [](
const Decl *D) {
6465 if (isa<EmptyDecl>(D) || isa<DeclContext>(D) ||
6466 isa<TypeDecl>(D) || isa<PragmaCommentDecl>(D) ||
6467 isa<PragmaDetectMismatchDecl>(D) || isa<UsingDecl>(D) ||
6468 isa<UsingDirectiveDecl>(D) ||
6469 isa<OMPDeclareReductionDecl>(D) ||
6470 isa<OMPThreadPrivateDecl>(D) || isa<OMPAllocateDecl>(D))
6472 const auto *VD = dyn_cast<VarDecl>(D);
6475 return VD->hasGlobalStorage() || !VD->isUsed();
6485 Child = Child->IgnoreContainers();
6492 int32_t &MaxTeamsVal) {
6496 "Expected target-based executable directive.");
6497 switch (DirectiveKind) {
6499 const auto *CS = D.getInnermostCapturedStmt();
6502 const Stmt *ChildStmt =
6504 if (
const auto *NestedDir =
6505 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) {
6514 MinTeamsVal = MaxTeamsVal =
Constant->getExtValue();
6517 MinTeamsVal = MaxTeamsVal = 0;
6520 MinTeamsVal = MaxTeamsVal = 1;
6524 MinTeamsVal = MaxTeamsVal = -1;
6527 case OMPD_target_teams_loop:
6528 case OMPD_target_teams:
6529 case OMPD_target_teams_distribute:
6530 case OMPD_target_teams_distribute_simd:
6531 case OMPD_target_teams_distribute_parallel_for:
6532 case OMPD_target_teams_distribute_parallel_for_simd: {
6534 const Expr *NumTeams =
6538 MinTeamsVal = MaxTeamsVal =
Constant->getExtValue();
6541 MinTeamsVal = MaxTeamsVal = 0;
6544 case OMPD_target_parallel:
6545 case OMPD_target_parallel_for:
6546 case OMPD_target_parallel_for_simd:
6547 case OMPD_target_parallel_loop:
6548 case OMPD_target_simd:
6549 MinTeamsVal = MaxTeamsVal = 1;
6553 case OMPD_parallel_for:
6554 case OMPD_parallel_loop:
6555 case OMPD_parallel_master:
6556 case OMPD_parallel_sections:
6558 case OMPD_parallel_for_simd:
6560 case OMPD_cancellation_point:
6561 case OMPD_ordered_standalone:
6562 case OMPD_ordered_blockassoc:
6563 case OMPD_threadprivate:
6574 case OMPD_taskyield:
6577 case OMPD_taskgroup:
6583 case OMPD_target_data:
6584 case OMPD_target_exit_data:
6585 case OMPD_target_enter_data:
6586 case OMPD_distribute:
6587 case OMPD_distribute_simd:
6588 case OMPD_distribute_parallel_for:
6589 case OMPD_distribute_parallel_for_simd:
6590 case OMPD_teams_distribute:
6591 case OMPD_teams_distribute_simd:
6592 case OMPD_teams_distribute_parallel_for:
6593 case OMPD_teams_distribute_parallel_for_simd:
6594 case OMPD_target_update:
6595 case OMPD_declare_simd:
6596 case OMPD_declare_variant:
6597 case OMPD_begin_declare_variant:
6598 case OMPD_end_declare_variant:
6599 case OMPD_declare_target:
6600 case OMPD_end_declare_target:
6601 case OMPD_declare_reduction:
6602 case OMPD_declare_mapper:
6604 case OMPD_taskloop_simd:
6605 case OMPD_master_taskloop:
6606 case OMPD_master_taskloop_simd:
6607 case OMPD_parallel_master_taskloop:
6608 case OMPD_parallel_master_taskloop_simd:
6610 case OMPD_metadirective:
6616 llvm_unreachable(
"Unexpected directive kind.");
6622 "Clauses associated with the teams directive expected to be emitted "
6623 "only for the host!");
6625 int32_t MinNT = -1, MaxNT = -1;
6626 const Expr *NumTeams =
6628 if (NumTeams !=
nullptr) {
6631 switch (DirectiveKind) {
6633 const auto *CS = D.getInnermostCapturedStmt();
6634 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6638 return Bld.CreateIntCast(NumTeamsVal, CGF.
Int32Ty,
6641 case OMPD_target_teams:
6642 case OMPD_target_teams_distribute:
6643 case OMPD_target_teams_distribute_simd:
6644 case OMPD_target_teams_distribute_parallel_for:
6645 case OMPD_target_teams_distribute_parallel_for_simd: {
6649 return Bld.CreateIntCast(NumTeamsVal, CGF.
Int32Ty,
6657 assert(MinNT == MaxNT &&
"Num threads ranges require handling here.");
6658 return llvm::ConstantInt::getSigned(CGF.
Int32Ty, MinNT);
6672 UpperBound = UpperBound > 0 ? std::min(UpperBound, Val) : Val;
6681 bool UpperBoundOnly, llvm::Value **CondVal) {
6684 const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child);
6691 if (CondVal && Dir->hasClausesOfKind<
OMPIfClause>()) {
6692 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6695 for (
const auto *
C : Dir->getClausesOfKind<
OMPIfClause>()) {
6696 if (
C->getNameModifier() == OMPD_unknown ||
6697 C->getNameModifier() == OMPD_parallel) {
6712 if (
const auto *PreInit =
6714 for (
const auto *I : PreInit->decls()) {
6715 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
6731 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6733 const auto *NumThreadsClause =
6735 const Expr *NTExpr = NumThreadsClause->getNumThreads().front();
6736 if (NTExpr->isIntegerConstantExpr(CGF.
getContext()))
6742 if (UpperBound == -1)
6747 if (
const auto *PreInit =
6748 cast_or_null<DeclStmt>(NumThreadsClause->getPreInitStmt())) {
6749 for (
const auto *I : PreInit->decls()) {
6750 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
6769 bool UpperBoundOnly, llvm::Value **CondVal,
const Expr **ThreadLimitExpr) {
6770 assert((!CGF.
getLangOpts().OpenMPIsTargetDevice || UpperBoundOnly) &&
6771 "Clauses associated with the teams directive expected to be emitted "
6772 "only for the host!");
6775 "Expected target-based executable directive.");
6777 const Expr *NT =
nullptr;
6778 const Expr **NTPtr = UpperBoundOnly ?
nullptr : &NT;
6780 auto CheckForConstExpr = [&](
const Expr *E,
const Expr **EPtr) {
6784 UpperBound,
static_cast<int32_t
>(
Constant->getZExtValue()));
6788 if (UpperBound == -1)
6794 auto ReturnSequential = [&]() {
6799 switch (DirectiveKind) {
6802 getNumThreads(CGF, CS, NTPtr, UpperBound, UpperBoundOnly, CondVal);
6808 if (
const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) {
6810 ThreadLimitClause = TLC;
6811 if (ThreadLimitExpr) {
6812 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6816 ThreadLimitClause->getThreadLimit().front()->getSourceRange());
6817 if (
const auto *PreInit =
6818 cast_or_null<DeclStmt>(ThreadLimitClause->getPreInitStmt())) {
6819 for (
const auto *I : PreInit->decls()) {
6820 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
6832 if (ThreadLimitClause)
6833 CheckForConstExpr(ThreadLimitClause->getThreadLimit().front(),
6835 if (
const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) {
6838 CS = Dir->getInnermostCapturedStmt();
6852 Dir = dyn_cast_or_null<OMPExecutableDirective>(Child);
6855 CS = Dir->getInnermostCapturedStmt();
6856 getNumThreads(CGF, CS, NTPtr, UpperBound, UpperBoundOnly, CondVal);
6858 return ReturnSequential();
6862 case OMPD_target_teams: {
6866 CheckForConstExpr(ThreadLimitClause->getThreadLimit().front(),
6870 getNumThreads(CGF, CS, NTPtr, UpperBound, UpperBoundOnly, CondVal);
6873 if (
const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) {
6874 if (Dir->getDirectiveKind() == OMPD_distribute) {
6875 CS = Dir->getInnermostCapturedStmt();
6876 getNumThreads(CGF, CS, NTPtr, UpperBound, UpperBoundOnly, CondVal);
6881 case OMPD_target_teams_distribute:
6885 CheckForConstExpr(ThreadLimitClause->getThreadLimit().front(),
6888 getNumThreads(CGF, D.getInnermostCapturedStmt(), NTPtr, UpperBound,
6889 UpperBoundOnly, CondVal);
6891 case OMPD_target_teams_loop:
6892 case OMPD_target_parallel_loop:
6893 case OMPD_target_parallel:
6894 case OMPD_target_parallel_for:
6895 case OMPD_target_parallel_for_simd:
6896 case OMPD_target_teams_distribute_parallel_for:
6897 case OMPD_target_teams_distribute_parallel_for_simd: {
6898 if (CondVal && D.hasClausesOfKind<
OMPIfClause>()) {
6900 for (
const auto *
C : D.getClausesOfKind<
OMPIfClause>()) {
6901 if (
C->getNameModifier() == OMPD_unknown ||
6902 C->getNameModifier() == OMPD_parallel) {
6912 return ReturnSequential();
6922 CheckForConstExpr(ThreadLimitClause->getThreadLimit().front(),
6928 CheckForConstExpr(NumThreadsClause->getNumThreads().front(),
nullptr);
6929 return NumThreadsClause->getNumThreads().front();
6933 case OMPD_target_teams_distribute_simd:
6934 case OMPD_target_simd:
6935 return ReturnSequential();
6939 llvm_unreachable(
"Unsupported directive kind.");
6944 llvm::Value *NumThreadsVal =
nullptr;
6945 llvm::Value *CondVal =
nullptr;
6946 llvm::Value *ThreadLimitVal =
nullptr;
6947 const Expr *ThreadLimitExpr =
nullptr;
6948 int32_t UpperBound = -1;
6951 CGF, D, UpperBound,
false, &CondVal,
6955 if (ThreadLimitExpr) {
6958 ThreadLimitVal = CGF.
Builder.CreateIntCast(ThreadLimitVal, CGF.
Int32Ty,
6963 if (UpperBound == 1) {
6964 NumThreadsVal = CGF.
Builder.getInt32(UpperBound);
6967 NumThreadsVal = CGF.
Builder.CreateIntCast(NumThreadsVal, CGF.
Int32Ty,
6969 }
else if (ThreadLimitVal) {
6972 NumThreadsVal = ThreadLimitVal;
6973 ThreadLimitVal =
nullptr;
6976 assert(!ThreadLimitVal &&
"Default not applicable with thread limit value");
6977 NumThreadsVal = CGF.
Builder.getInt32(0);
6984 NumThreadsVal = CGF.
Builder.CreateSelect(CondVal, NumThreadsVal,
6990 if (ThreadLimitVal) {
6991 NumThreadsVal = CGF.
Builder.CreateSelect(
6992 CGF.
Builder.CreateICmpULT(ThreadLimitVal, NumThreadsVal),
6993 ThreadLimitVal, NumThreadsVal);
6996 return NumThreadsVal;
7006class MappableExprsHandler {
7012 struct AttachPtrExprComparator {
7013 const MappableExprsHandler &Handler;
7015 mutable llvm::DenseMap<std::pair<const Expr *, const Expr *>,
bool>
7016 CachedEqualityComparisons;
7018 AttachPtrExprComparator(
const MappableExprsHandler &H) : Handler(H) {}
7019 AttachPtrExprComparator() =
delete;
7022 bool operator()(
const Expr *LHS,
const Expr *RHS)
const {
7027 const auto ItLHS = Handler.AttachPtrComponentDepthMap.find(LHS);
7028 const auto ItRHS = Handler.AttachPtrComponentDepthMap.find(RHS);
7030 std::optional<size_t> DepthLHS =
7031 (ItLHS != Handler.AttachPtrComponentDepthMap.end()) ? ItLHS->second
7033 std::optional<size_t> DepthRHS =
7034 (ItRHS != Handler.AttachPtrComponentDepthMap.end()) ? ItRHS->second
7038 if (!DepthLHS.has_value() && !DepthRHS.has_value()) {
7040 if (areEqual(LHS, RHS))
7043 return wasComputedBefore(LHS, RHS);
7045 if (!DepthLHS.has_value())
7047 if (!DepthRHS.has_value())
7051 if (DepthLHS.value() != DepthRHS.value())
7052 return DepthLHS.value() < DepthRHS.value();
7055 if (areEqual(LHS, RHS))
7058 return wasComputedBefore(LHS, RHS);
7064 bool areEqual(
const Expr *LHS,
const Expr *RHS)
const {
7066 const auto CachedResultIt = CachedEqualityComparisons.find({LHS, RHS});
7067 if (CachedResultIt != CachedEqualityComparisons.end())
7068 return CachedResultIt->second;
7082 bool wasComputedBefore(
const Expr *LHS,
const Expr *RHS)
const {
7083 const size_t &OrderLHS = Handler.AttachPtrComputationOrderMap.at(LHS);
7084 const size_t &OrderRHS = Handler.AttachPtrComputationOrderMap.at(RHS);
7086 return OrderLHS < OrderRHS;
7095 bool areSemanticallyEqual(
const Expr *LHS,
const Expr *RHS)
const {
7117 if (
const auto *LD = dyn_cast<DeclRefExpr>(LHS)) {
7118 const auto *RD = dyn_cast<DeclRefExpr>(RHS);
7121 return LD->getDecl()->getCanonicalDecl() ==
7122 RD->getDecl()->getCanonicalDecl();
7126 if (
const auto *LA = dyn_cast<ArraySubscriptExpr>(LHS)) {
7127 const auto *RA = dyn_cast<ArraySubscriptExpr>(RHS);
7130 return areSemanticallyEqual(LA->getBase(), RA->getBase()) &&
7131 areSemanticallyEqual(LA->getIdx(), RA->getIdx());
7135 if (
const auto *LM = dyn_cast<MemberExpr>(LHS)) {
7136 const auto *RM = dyn_cast<MemberExpr>(RHS);
7139 if (LM->getMemberDecl()->getCanonicalDecl() !=
7140 RM->getMemberDecl()->getCanonicalDecl())
7142 return areSemanticallyEqual(LM->getBase(), RM->getBase());
7146 if (
const auto *LU = dyn_cast<UnaryOperator>(LHS)) {
7147 const auto *RU = dyn_cast<UnaryOperator>(RHS);
7150 if (LU->getOpcode() != RU->getOpcode())
7152 return areSemanticallyEqual(LU->getSubExpr(), RU->getSubExpr());
7156 if (
const auto *LB = dyn_cast<BinaryOperator>(LHS)) {
7157 const auto *RB = dyn_cast<BinaryOperator>(RHS);
7160 if (LB->getOpcode() != RB->getOpcode())
7162 return areSemanticallyEqual(LB->getLHS(), RB->getLHS()) &&
7163 areSemanticallyEqual(LB->getRHS(), RB->getRHS());
7169 if (
const auto *LAS = dyn_cast<ArraySectionExpr>(LHS)) {
7170 const auto *RAS = dyn_cast<ArraySectionExpr>(RHS);
7173 return areSemanticallyEqual(LAS->getBase(), RAS->getBase()) &&
7174 areSemanticallyEqual(LAS->getLowerBound(),
7175 RAS->getLowerBound()) &&
7176 areSemanticallyEqual(LAS->getLength(), RAS->getLength());
7180 if (
const auto *LC = dyn_cast<CastExpr>(LHS)) {
7181 const auto *RC = dyn_cast<CastExpr>(RHS);
7184 if (LC->getCastKind() != RC->getCastKind())
7186 return areSemanticallyEqual(LC->getSubExpr(), RC->getSubExpr());
7194 if (
const auto *LI = dyn_cast<IntegerLiteral>(LHS)) {
7195 const auto *RI = dyn_cast<IntegerLiteral>(RHS);
7198 return LI->getValue() == RI->getValue();
7202 if (
const auto *LC = dyn_cast<CharacterLiteral>(LHS)) {
7203 const auto *RC = dyn_cast<CharacterLiteral>(RHS);
7206 return LC->getValue() == RC->getValue();
7210 if (
const auto *LF = dyn_cast<FloatingLiteral>(LHS)) {
7211 const auto *RF = dyn_cast<FloatingLiteral>(RHS);
7215 return LF->getValue().bitwiseIsEqual(RF->getValue());
7219 if (
const auto *LS = dyn_cast<StringLiteral>(LHS)) {
7220 const auto *RS = dyn_cast<StringLiteral>(RHS);
7223 return LS->getString() == RS->getString();
7231 if (
const auto *LB = dyn_cast<CXXBoolLiteralExpr>(LHS)) {
7232 const auto *RB = dyn_cast<CXXBoolLiteralExpr>(RHS);
7235 return LB->getValue() == RB->getValue();
7244 static unsigned getFlagMemberOffset() {
7245 unsigned Offset = 0;
7246 for (uint64_t Remain =
7247 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
7248 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF);
7249 !(Remain & 1); Remain = Remain >> 1)
7256 class MappingExprInfo {
7258 const ValueDecl *MapDecl =
nullptr;
7261 const Expr *MapExpr =
nullptr;
7264 MappingExprInfo(
const ValueDecl *MapDecl,
const Expr *MapExpr =
nullptr)
7265 : MapDecl(MapDecl), MapExpr(MapExpr) {}
7267 const ValueDecl *getMapDecl()
const {
return MapDecl; }
7268 const Expr *getMapExpr()
const {
return MapExpr; }
7271 using DeviceInfoTy = llvm::OpenMPIRBuilder::DeviceInfoTy;
7272 using MapBaseValuesArrayTy = llvm::OpenMPIRBuilder::MapValuesArrayTy;
7273 using MapValuesArrayTy = llvm::OpenMPIRBuilder::MapValuesArrayTy;
7274 using MapFlagsArrayTy = llvm::OpenMPIRBuilder::MapFlagsArrayTy;
7275 using MapDimArrayTy = llvm::OpenMPIRBuilder::MapDimArrayTy;
7276 using MapNonContiguousArrayTy =
7277 llvm::OpenMPIRBuilder::MapNonContiguousArrayTy;
7278 using MapExprsArrayTy = SmallVector<MappingExprInfo, 4>;
7279 using MapValueDeclsArrayTy = SmallVector<const ValueDecl *, 4>;
7283 bool ,
const ValueDecl *,
const Expr *>;
7284 using MapDataArrayTy = SmallVector<MapData, 4>;
7289 struct MapCombinedInfoTy : llvm::OpenMPIRBuilder::MapInfosTy {
7290 MapExprsArrayTy Exprs;
7291 MapValueDeclsArrayTy Mappers;
7292 MapValueDeclsArrayTy DevicePtrDecls;
7295 void append(MapCombinedInfoTy &CurInfo) {
7296 Exprs.append(CurInfo.Exprs.begin(), CurInfo.Exprs.end());
7297 DevicePtrDecls.append(CurInfo.DevicePtrDecls.begin(),
7298 CurInfo.DevicePtrDecls.end());
7299 Mappers.append(CurInfo.Mappers.begin(), CurInfo.Mappers.end());
7300 llvm::OpenMPIRBuilder::MapInfosTy::append(CurInfo);
7308 struct StructRangeInfoTy {
7309 MapCombinedInfoTy PreliminaryMapData;
7310 std::pair<
unsigned ,
Address > LowestElem = {
7312 std::pair<
unsigned ,
Address > HighestElem = {
7316 bool IsArraySection =
false;
7317 bool HasCompleteRecord =
false;
7322 struct AttachInfoTy {
7325 const ValueDecl *AttachPtrDecl =
nullptr;
7326 const Expr *AttachMapExpr =
nullptr;
7328 bool isValid()
const {
7335 bool hasAttachEntryForCapturedVar(
const ValueDecl *VD)
const {
7336 for (
const auto &AttachEntry : AttachPtrExprMap) {
7337 if (AttachEntry.second) {
7340 if (
const auto *DRE = dyn_cast<DeclRefExpr>(AttachEntry.second))
7341 if (DRE->getDecl() == VD)
7349 const Expr *getAttachPtrExpr(
7352 const auto It = AttachPtrExprMap.find(Components);
7353 if (It != AttachPtrExprMap.end())
7364 ArrayRef<OpenMPMapModifierKind> MapModifiers;
7365 ArrayRef<OpenMPMotionModifierKind> MotionModifiers;
7366 bool ReturnDevicePointer =
false;
7367 bool IsImplicit =
false;
7368 const ValueDecl *Mapper =
nullptr;
7369 const Expr *VarRef =
nullptr;
7370 bool ForDeviceAddr =
false;
7371 bool HasUdpFbNullify =
false;
7373 MapInfo() =
default;
7377 ArrayRef<OpenMPMapModifierKind> MapModifiers,
7378 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
7379 bool ReturnDevicePointer,
bool IsImplicit,
7380 const ValueDecl *Mapper =
nullptr,
const Expr *VarRef =
nullptr,
7381 bool ForDeviceAddr =
false,
bool HasUdpFbNullify =
false)
7382 : Components(Components), MapType(MapType), MapModifiers(MapModifiers),
7383 MotionModifiers(MotionModifiers),
7384 ReturnDevicePointer(ReturnDevicePointer), IsImplicit(IsImplicit),
7385 Mapper(Mapper), VarRef(VarRef), ForDeviceAddr(ForDeviceAddr),
7386 HasUdpFbNullify(HasUdpFbNullify) {}
7391 llvm::PointerUnion<
const OMPExecutableDirective *,
7392 const OMPDeclareMapperDecl *>
7396 CodeGenFunction &CGF;
7401 llvm::DenseMap<CanonicalDeclPtr<const VarDecl>,
bool> FirstPrivateDecls;
7404 llvm::SmallSet<OpenMPDefaultmapClauseKind, 4> DefaultmapFirstprivateKinds;
7410 SmallVector<OMPClauseMappableExprCommon::MappableExprComponentListRef, 4>>
7417 SmallVector<OMPClauseMappableExprCommon::MappableExprComponentListRef, 4>>
7421 llvm::DenseMap<const ValueDecl *, const OMPMapClause *> LambdasMap;
7436 llvm::DenseMap<const Expr *, std::optional<size_t>>
7437 AttachPtrComponentDepthMap = {{
nullptr, std::nullopt}};
7441 llvm::DenseMap<const Expr *, size_t> AttachPtrComputationOrderMap = {
7446 AttachPtrExprComparator AttachPtrComparator;
7448 llvm::Value *getExprTypeSize(
const Expr *E)
const {
7452 if (
const auto *OAE = dyn_cast<OMPArrayShapingExpr>(E)) {
7454 CGF.
getTypeSize(OAE->getBase()->getType()->getPointeeType());
7455 for (
const Expr *SE : OAE->getDimensions()) {
7466 if (
const auto *RefTy = ExprTy->
getAs<ReferenceType>())
7472 if (
const auto *OAE = dyn_cast<ArraySectionExpr>(E)) {
7474 OAE->getBase()->IgnoreParenImpCasts())
7480 if (!OAE->getLength() && OAE->getColonLocFirst().isValid() &&
7481 !OAE->getLowerBound())
7484 llvm::Value *ElemSize;
7485 if (
const auto *PTy = BaseTy->
getAs<PointerType>()) {
7486 ElemSize = CGF.
getTypeSize(PTy->getPointeeType().getCanonicalType());
7489 assert(ATy &&
"Expecting array type if not a pointer type.");
7490 ElemSize = CGF.
getTypeSize(ATy->getElementType().getCanonicalType());
7495 if (!OAE->getLength() && OAE->getColonLocFirst().isInvalid())
7498 if (
const Expr *LenExpr = OAE->getLength()) {
7502 LenExpr->getExprLoc());
7503 return CGF.
Builder.CreateNUWMul(LengthVal, ElemSize);
7505 assert(!OAE->getLength() && OAE->getColonLocFirst().isValid() &&
7506 OAE->getLowerBound() &&
"expected array_section[lb:].");
7512 OAE->getLowerBound()->getExprLoc());
7513 LBVal = CGF.
Builder.CreateNUWMul(LBVal, ElemSize);
7514 llvm::Value *
Cmp = CGF.
Builder.CreateICmpUGT(LengthVal, LBVal);
7515 llvm::Value *TrueVal = CGF.
Builder.CreateNUWSub(LengthVal, LBVal);
7516 LengthVal = CGF.
Builder.CreateSelect(
7517 Cmp, TrueVal, llvm::ConstantInt::get(CGF.
SizeTy, 0));
7527 OpenMPOffloadMappingFlags getMapTypeBits(
7529 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
bool IsImplicit,
7530 bool AddPtrFlag,
bool AddIsTargetParamFlag,
bool IsNonContiguous)
const {
7531 OpenMPOffloadMappingFlags Bits =
7532 IsImplicit ? OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT
7533 : OpenMPOffloadMappingFlags::OMP_MAP_NONE;
7535 case OMPC_MAP_alloc:
7536 case OMPC_MAP_release:
7543 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_TO;
7546 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_FROM;
7548 case OMPC_MAP_tofrom:
7549 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_TO |
7550 OpenMPOffloadMappingFlags::OMP_MAP_FROM;
7552 case OMPC_MAP_delete:
7553 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_DELETE;
7556 llvm_unreachable(
"Unexpected map type!");
7559 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ;
7560 if (AddIsTargetParamFlag)
7561 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM;
7562 if (llvm::is_contained(MapModifiers, OMPC_MAP_MODIFIER_always))
7563 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_ALWAYS;
7564 if (llvm::is_contained(MapModifiers, OMPC_MAP_MODIFIER_close))
7565 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_CLOSE;
7566 if (llvm::is_contained(MapModifiers, OMPC_MAP_MODIFIER_present) ||
7567 llvm::is_contained(MotionModifiers, OMPC_MOTION_MODIFIER_present))
7568 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_PRESENT;
7569 if (llvm::is_contained(MapModifiers, OMPC_MAP_MODIFIER_ompx_hold))
7570 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_OMPX_HOLD;
7571 if (IsNonContiguous)
7572 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_NON_CONTIG;
7578 bool isFinalArraySectionExpression(
const Expr *E)
const {
7579 const auto *OASE = dyn_cast<ArraySectionExpr>(E);
7586 if (OASE->getColonLocFirst().isInvalid())
7589 const Expr *Length = OASE->getLength();
7596 OASE->getBase()->IgnoreParenImpCasts())
7598 if (
const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.
getTypePtr()))
7599 return ATy->getSExtSize() != 1;
7611 llvm::APSInt ConstLength =
Result.Val.getInt();
7612 return ConstLength.getSExtValue() != 1;
7619 void emitAttachEntry(CodeGenFunction &CGF, MapCombinedInfoTy &CombinedInfo,
7620 const AttachInfoTy &AttachInfo)
const {
7621 assert(AttachInfo.isValid() &&
7622 "Expected valid attach pointer/pointee information!");
7626 llvm::Value *PointerSize = CGF.
Builder.CreateIntCast(
7627 llvm::ConstantInt::get(
7633 CombinedInfo.Exprs.emplace_back(AttachInfo.AttachPtrDecl,
7634 AttachInfo.AttachMapExpr);
7635 CombinedInfo.BasePointers.push_back(
7636 AttachInfo.AttachPtrAddr.emitRawPointer(CGF));
7637 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
7638 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
7639 CombinedInfo.Pointers.push_back(
7640 AttachInfo.AttachPteeAddr.emitRawPointer(CGF));
7641 CombinedInfo.Sizes.push_back(PointerSize);
7642 CombinedInfo.Types.push_back(OpenMPOffloadMappingFlags::OMP_MAP_ATTACH);
7644 CombinedInfo.HasAttachPtr.push_back(
false);
7645 CombinedInfo.Mappers.push_back(
nullptr);
7646 CombinedInfo.NonContigInfo.Dims.push_back(1);
7653 class CopyOverlappedEntryGaps {
7654 CodeGenFunction &CGF;
7655 MapCombinedInfoTy &CombinedInfo;
7656 OpenMPOffloadMappingFlags Flags = OpenMPOffloadMappingFlags::OMP_MAP_NONE;
7657 const ValueDecl *MapDecl =
nullptr;
7658 const Expr *MapExpr =
nullptr;
7660 bool IsNonContiguous =
false;
7664 const RecordDecl *LastParent =
nullptr;
7666 unsigned LastIndex = -1u;
7670 CopyOverlappedEntryGaps(CodeGenFunction &CGF,
7671 MapCombinedInfoTy &CombinedInfo,
7672 OpenMPOffloadMappingFlags Flags,
7673 const ValueDecl *MapDecl,
const Expr *MapExpr,
7674 Address BP, Address LB,
bool IsNonContiguous,
7676 : CGF(CGF), CombinedInfo(CombinedInfo), Flags(Flags), MapDecl(MapDecl),
7677 MapExpr(MapExpr), BP(BP), IsNonContiguous(IsNonContiguous),
7678 DimSize(DimSize), LB(LB) {}
7681 const OMPClauseMappableExprCommon::MappableComponent &MC,
7682 const FieldDecl *FD,
7683 llvm::function_ref<LValue(CodeGenFunction &,
const MemberExpr *)>
7684 EmitMemberExprBase) {
7694 LValue BaseLVal = EmitMemberExprBase(CGF, ME);
7706 copyUntilField(FD, ComponentLB);
7709 if (((int64_t)FieldOffset - (int64_t)Cursor) > 0)
7710 copyUntilField(FD, ComponentLB);
7712 Cursor = FieldOffset + FieldSize;
7717 void copyUntilField(
const FieldDecl *FD, Address ComponentLB) {
7720 llvm::Value *
Size = CGF.
Builder.CreatePtrDiff(ComponentLBPtr, LBPtr);
7721 copySizedChunk(LBPtr, Size);
7724 void copyUntilEnd(Address HB) {
7726 const ASTRecordLayout &RL =
7734 copySizedChunk(LBPtr, Size);
7737 void copySizedChunk(llvm::Value *Base, llvm::Value *Size) {
7738 CombinedInfo.Exprs.emplace_back(MapDecl, MapExpr);
7740 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
7741 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
7742 CombinedInfo.Pointers.push_back(Base);
7743 CombinedInfo.Sizes.push_back(
7745 CombinedInfo.Types.push_back(Flags);
7746 CombinedInfo.HasAttachPtr.push_back(
false);
7747 CombinedInfo.Mappers.push_back(
nullptr);
7748 CombinedInfo.NonContigInfo.Dims.push_back(IsNonContiguous ? DimSize : 1);
7757 void generateInfoForComponentList(
7759 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
7761 MapCombinedInfoTy &CombinedInfo,
7762 MapCombinedInfoTy &StructBaseCombinedInfo,
7763 StructRangeInfoTy &PartialStruct, AttachInfoTy &AttachInfo,
7764 bool IsFirstComponentList,
bool IsImplicit,
7765 bool GenerateAllInfoForClauses,
const ValueDecl *Mapper =
nullptr,
7766 bool ForDeviceAddr =
false,
const ValueDecl *BaseDecl =
nullptr,
7767 const Expr *MapExpr =
nullptr,
7768 ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef>
7769 OverlappedElements = {})
const {
7987 bool IsCaptureFirstInfo = IsFirstComponentList;
7991 bool RequiresReference =
false;
7994 auto CI = Components.rbegin();
7995 auto CE = Components.rend();
8000 bool IsExpressionFirstInfo =
true;
8001 bool FirstPointerInComplexData =
false;
8004 const Expr *AssocExpr = I->getAssociatedExpression();
8005 const auto *AE = dyn_cast<ArraySubscriptExpr>(AssocExpr);
8006 const auto *OASE = dyn_cast<ArraySectionExpr>(AssocExpr);
8007 const auto *OAShE = dyn_cast<OMPArrayShapingExpr>(AssocExpr);
8010 const Expr *AttachPtrExpr = getAttachPtrExpr(Components);
8011 auto [AttachPtrAddr, AttachPteeBaseAddr] =
8012 getAttachPtrAddrAndPteeBaseAddr(AttachPtrExpr, CGF);
8014 bool HasAttachPtr = AttachPtrExpr !=
nullptr;
8015 bool FirstComponentIsForAttachPtr = AssocExpr == AttachPtrExpr;
8016 bool SeenAttachPtr = FirstComponentIsForAttachPtr;
8018 if (FirstComponentIsForAttachPtr) {
8026 }
else if ((AE &&
isa<CXXThisExpr>(AE->getBase()->IgnoreParenImpCasts())) ||
8040 if (
const auto *VD =
8041 dyn_cast_or_null<VarDecl>(I->getAssociatedDeclaration())) {
8042 if (std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
8043 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD)) {
8044 if ((*Res == OMPDeclareTargetDeclAttr::MT_Link) ||
8045 ((*Res == OMPDeclareTargetDeclAttr::MT_To ||
8046 *Res == OMPDeclareTargetDeclAttr::MT_Enter) &&
8048 RequiresReference =
true;
8058 I->getAssociatedDeclaration()->
getType().getNonReferenceType();
8063 const auto *VD = dyn_cast<VarDecl>(I->getAssociatedDeclaration());
8065 !VD || VD->hasLocalStorage() || HasAttachPtr)
8068 FirstPointerInComplexData =
true;
8087 bool ShouldBeMemberOf =
false;
8096 const MemberExpr *EncounteredME =
nullptr;
8108 bool IsNonContiguous =
8109 CombinedInfo.NonContigInfo.IsNonContiguous ||
8110 any_of(Components, [&](
const auto &Component) {
8112 dyn_cast<ArraySectionExpr>(Component.getAssociatedExpression());
8116 const Expr *StrideExpr = OASE->getStride();
8121 "Stride expression must be of integer type");
8134 bool IsPrevMemberReference =
false;
8136 bool IsPartialMapped =
8137 !PartialStruct.PreliminaryMapData.BasePointers.empty();
8144 bool IsMappingWholeStruct =
true;
8145 if (!GenerateAllInfoForClauses) {
8146 IsMappingWholeStruct =
false;
8148 for (
auto TempI = I; TempI != CE; ++TempI) {
8149 const MemberExpr *PossibleME =
8150 dyn_cast<MemberExpr>(TempI->getAssociatedExpression());
8152 IsMappingWholeStruct =
false;
8158 bool SeenFirstNonBinOpExprAfterAttachPtr =
false;
8159 for (; I != CE; ++I) {
8162 if (HasAttachPtr && !SeenAttachPtr) {
8163 SeenAttachPtr = I->getAssociatedExpression() == AttachPtrExpr;
8170 if (HasAttachPtr && !SeenFirstNonBinOpExprAfterAttachPtr) {
8171 const auto *BO = dyn_cast<BinaryOperator>(I->getAssociatedExpression());
8176 SeenFirstNonBinOpExprAfterAttachPtr =
true;
8177 BP = AttachPteeBaseAddr;
8181 if (!EncounteredME) {
8182 EncounteredME = dyn_cast<MemberExpr>(I->getAssociatedExpression());
8185 if (EncounteredME) {
8186 ShouldBeMemberOf =
true;
8189 if (FirstPointerInComplexData) {
8190 QualType Ty = std::prev(I)
8191 ->getAssociatedDeclaration()
8193 .getNonReferenceType();
8195 FirstPointerInComplexData =
false;
8200 auto Next = std::next(I);
8210 bool IsFinalArraySection =
8212 isFinalArraySectionExpression(I->getAssociatedExpression());
8216 const ValueDecl *MapDecl = (I->getAssociatedDeclaration())
8217 ? I->getAssociatedDeclaration()
8219 MapExpr = (I->getAssociatedExpression()) ? I->getAssociatedExpression()
8226 dyn_cast<ArraySectionExpr>(I->getAssociatedExpression());
8228 dyn_cast<OMPArrayShapingExpr>(I->getAssociatedExpression());
8229 const auto *UO = dyn_cast<UnaryOperator>(I->getAssociatedExpression());
8230 const auto *BO = dyn_cast<BinaryOperator>(I->getAssociatedExpression());
8236 I->getAssociatedExpression()->getType()->isAnyPointerType();
8237 bool IsMemberReference =
isa<MemberExpr>(I->getAssociatedExpression()) &&
8240 bool IsNonDerefPointer = IsPointer &&
8241 !(UO && UO->getOpcode() != UO_Deref) && !BO &&
8247 if (
Next == CE || IsMemberReference || IsNonDerefPointer ||
8248 IsFinalArraySection) {
8251 assert((
Next == CE ||
8258 "Unexpected expression");
8262 auto &&EmitMemberExprBase = [](CodeGenFunction &CGF,
8263 const MemberExpr *E) {
8264 const Expr *BaseExpr = E->getBase();
8269 LValueBaseInfo BaseInfo;
8270 TBAAAccessInfo TBAAInfo;
8284 OAShE->getBase()->getType()->getPointeeType()),
8286 OAShE->getBase()->getType()));
8287 }
else if (IsMemberReference) {
8289 LValue BaseLVal = EmitMemberExprBase(CGF, ME);
8304 FinalLowestElem = LowestElem;
8309 bool IsMemberPointerOrAddr =
8311 (((IsPointer || ForDeviceAddr) &&
8312 I->getAssociatedExpression() == EncounteredME) ||
8313 (IsPrevMemberReference && !IsPointer) ||
8314 (IsMemberReference &&
Next != CE &&
8315 !
Next->getAssociatedExpression()->getType()->isPointerType()));
8316 if (!OverlappedElements.empty() &&
Next == CE) {
8318 assert(!PartialStruct.Base.isValid() &&
"The base element is set.");
8319 assert(!IsPointer &&
8320 "Unexpected base element with the pointer type.");
8323 PartialStruct.LowestElem = {0, LowestElem};
8325 I->getAssociatedExpression()->getType());
8330 PartialStruct.HighestElem = {
8331 std::numeric_limits<
decltype(
8332 PartialStruct.HighestElem.first)>
::max(),
8334 PartialStruct.Base = BP;
8335 PartialStruct.LB = LB;
8337 PartialStruct.PreliminaryMapData.BasePointers.empty() &&
8338 "Overlapped elements must be used only once for the variable.");
8339 std::swap(PartialStruct.PreliminaryMapData, CombinedInfo);
8341 OpenMPOffloadMappingFlags Flags =
8342 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF |
8343 getMapTypeBits(MapType, MapModifiers, MotionModifiers, IsImplicit,
8345 false, IsNonContiguous);
8346 CopyOverlappedEntryGaps CopyGaps(CGF, CombinedInfo, Flags, MapDecl,
8347 MapExpr, BP, LB, IsNonContiguous,
8351 Component : OverlappedElements) {
8352 for (
const OMPClauseMappableExprCommon::MappableComponent &MC :
8355 if (
const auto *FD = dyn_cast<FieldDecl>(VD)) {
8356 CopyGaps.processField(MC, FD, EmitMemberExprBase);
8361 CopyGaps.copyUntilEnd(HB);
8364 llvm::Value *
Size = getExprTypeSize(I->getAssociatedExpression());
8371 if ((!IsMemberPointerOrAddr && !IsPartialMapped) ||
8373 if (!IsMappingWholeStruct) {
8374 CombinedInfo.Exprs.emplace_back(MapDecl, MapExpr);
8376 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
8377 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
8379 CombinedInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
8381 CombinedInfo.NonContigInfo.Dims.push_back(IsNonContiguous ? DimSize
8384 StructBaseCombinedInfo.Exprs.emplace_back(MapDecl, MapExpr);
8385 StructBaseCombinedInfo.BasePointers.push_back(
8387 StructBaseCombinedInfo.DevicePtrDecls.push_back(
nullptr);
8388 StructBaseCombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
8389 StructBaseCombinedInfo.Pointers.push_back(LB.
emitRawPointer(CGF));
8390 StructBaseCombinedInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
8392 StructBaseCombinedInfo.NonContigInfo.Dims.push_back(
8393 IsNonContiguous ? DimSize : 1);
8397 bool HasMapper = Mapper &&
Next == CE;
8398 if (!IsMappingWholeStruct)
8399 CombinedInfo.Mappers.push_back(HasMapper ? Mapper :
nullptr);
8401 StructBaseCombinedInfo.Mappers.push_back(HasMapper ? Mapper
8408 OpenMPOffloadMappingFlags Flags = getMapTypeBits(
8409 MapType, MapModifiers, MotionModifiers, IsImplicit,
8410 !IsExpressionFirstInfo || RequiresReference ||
8411 FirstPointerInComplexData || IsMemberReference,
8412 IsCaptureFirstInfo && !RequiresReference, IsNonContiguous);
8414 if (!IsExpressionFirstInfo || IsMemberReference) {
8417 if (IsPointer || (IsMemberReference &&
Next != CE))
8418 Flags &= ~(OpenMPOffloadMappingFlags::OMP_MAP_TO |
8419 OpenMPOffloadMappingFlags::OMP_MAP_FROM |
8420 OpenMPOffloadMappingFlags::OMP_MAP_ALWAYS |
8421 OpenMPOffloadMappingFlags::OMP_MAP_DELETE |
8422 OpenMPOffloadMappingFlags::OMP_MAP_CLOSE);
8424 if (ShouldBeMemberOf) {
8427 Flags |= OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF;
8430 ShouldBeMemberOf =
false;
8434 if (!IsMappingWholeStruct) {
8435 CombinedInfo.Types.push_back(Flags);
8437 CombinedInfo.HasAttachPtr.push_back(HasAttachPtr);
8439 StructBaseCombinedInfo.Types.push_back(Flags);
8440 StructBaseCombinedInfo.HasAttachPtr.push_back(HasAttachPtr);
8447 if (EncounteredME) {
8452 if (!PartialStruct.Base.isValid()) {
8453 PartialStruct.LowestElem = {FieldIndex, LowestElem};
8454 if (IsFinalArraySection && OASE) {
8458 PartialStruct.HighestElem = {FieldIndex, HB};
8460 PartialStruct.HighestElem = {FieldIndex, LowestElem};
8462 PartialStruct.Base = BP;
8463 PartialStruct.LB = BP;
8464 }
else if (FieldIndex < PartialStruct.LowestElem.first) {
8465 PartialStruct.LowestElem = {FieldIndex, LowestElem};
8466 }
else if (FieldIndex > PartialStruct.HighestElem.first) {
8467 if (IsFinalArraySection && OASE) {
8471 PartialStruct.HighestElem = {FieldIndex, HB};
8473 PartialStruct.HighestElem = {FieldIndex, LowestElem};
8479 if (IsFinalArraySection || IsNonContiguous)
8480 PartialStruct.IsArraySection =
true;
8483 if (IsFinalArraySection)
8488 BP = IsMemberReference ? LowestElem : LB;
8489 if (!IsPartialMapped)
8490 IsExpressionFirstInfo =
false;
8491 IsCaptureFirstInfo =
false;
8492 FirstPointerInComplexData =
false;
8493 IsPrevMemberReference = IsMemberReference;
8494 }
else if (FirstPointerInComplexData) {
8495 QualType Ty = Components.rbegin()
8496 ->getAssociatedDeclaration()
8498 .getNonReferenceType();
8500 FirstPointerInComplexData =
false;
8506 PartialStruct.HasCompleteRecord =
true;
8509 if (shouldEmitAttachEntry(AttachPtrExpr, BaseDecl, CGF, CurDir)) {
8510 AttachInfo.AttachPtrAddr = AttachPtrAddr;
8511 AttachInfo.AttachPteeAddr = FinalLowestElem;
8512 AttachInfo.AttachPtrDecl = BaseDecl;
8513 AttachInfo.AttachMapExpr = MapExpr;
8516 if (!IsNonContiguous)
8519 const ASTContext &Context = CGF.
getContext();
8523 MapValuesArrayTy CurOffsets = {llvm::ConstantInt::get(CGF.
CGM.
Int64Ty, 0)};
8524 MapValuesArrayTy CurCounts;
8525 MapValuesArrayTy CurStrides = {llvm::ConstantInt::get(CGF.
CGM.
Int64Ty, 1)};
8526 MapValuesArrayTy DimSizes{llvm::ConstantInt::get(CGF.
CGM.
Int64Ty, 1)};
8532 for (
const OMPClauseMappableExprCommon::MappableComponent &Component :
8534 const Expr *AssocExpr = Component.getAssociatedExpression();
8535 const auto *OASE = dyn_cast<ArraySectionExpr>(AssocExpr);
8545 assert((VAT || CAT || &Component == &*Components.begin()) &&
8546 "Should be either ConstantArray or VariableArray if not the "
8550 if (CurCounts.empty()) {
8551 const Type *ElementType =
nullptr;
8553 ElementType = CAT->getElementType().getTypePtr();
8555 ElementType = VAT->getElementType().getTypePtr();
8556 else if (&Component == &*Components.begin()) {
8563 if (
const auto *PtrType = Ty->
getAs<PointerType>())
8564 ElementType = PtrType->getPointeeType().getTypePtr();
8570 "Non-first components should not be raw pointers");
8578 if (&Component != &*Components.begin())
8579 ElementType = ElementType->getPointeeOrArrayElementType();
8582 CurCounts.push_back(
8583 llvm::ConstantInt::get(CGF.
Int64Ty, ElementTypeSize));
8588 if (DimSizes.size() < Components.size() - 1) {
8591 llvm::ConstantInt::get(CGF.
Int64Ty, CAT->getZExtSize()));
8593 DimSizes.push_back(CGF.
Builder.CreateIntCast(
8600 auto *DI = DimSizes.begin() + 1;
8602 llvm::Value *DimProd =
8603 llvm::ConstantInt::get(CGF.
CGM.
Int64Ty, ElementTypeSize);
8612 for (
const OMPClauseMappableExprCommon::MappableComponent &Component :
8614 const Expr *AssocExpr = Component.getAssociatedExpression();
8616 if (
const auto *AE = dyn_cast<ArraySubscriptExpr>(AssocExpr)) {
8617 llvm::Value *Offset = CGF.
Builder.CreateIntCast(
8620 CurOffsets.push_back(Offset);
8621 CurCounts.push_back(llvm::ConstantInt::get(CGF.
Int64Ty, 1));
8622 CurStrides.push_back(CurStrides.back());
8626 const auto *OASE = dyn_cast<ArraySectionExpr>(AssocExpr);
8632 const Expr *OffsetExpr = OASE->getLowerBound();
8633 llvm::Value *Offset =
nullptr;
8636 Offset = llvm::ConstantInt::get(CGF.
Int64Ty, 0);
8644 const Expr *CountExpr = OASE->getLength();
8645 llvm::Value *Count =
nullptr;
8651 if (!OASE->getColonLocFirst().isValid() &&
8652 !OASE->getColonLocSecond().isValid()) {
8653 Count = llvm::ConstantInt::get(CGF.
Int64Ty, 1);
8659 const Expr *StrideExpr = OASE->getStride();
8660 llvm::Value *Stride =
8666 Count = CGF.
Builder.CreateUDiv(
8667 CGF.
Builder.CreateNUWSub(*DI, Offset), Stride);
8669 Count = CGF.
Builder.CreateNUWSub(*DI, Offset);
8675 CurCounts.push_back(Count);
8685 const Expr *StrideExpr = OASE->getStride();
8686 llvm::Value *Stride =
8691 DimProd = CGF.
Builder.CreateNUWMul(DimProd, *(DI - 1));
8693 CurStrides.push_back(CGF.
Builder.CreateNUWMul(DimProd, Stride));
8695 CurStrides.push_back(DimProd);
8697 Offset = CGF.
Builder.CreateNUWMul(DimProd, Offset);
8698 CurOffsets.push_back(Offset);
8700 if (DI != DimSizes.end())
8704 CombinedInfo.NonContigInfo.Offsets.push_back(CurOffsets);
8705 CombinedInfo.NonContigInfo.Counts.push_back(CurCounts);
8706 CombinedInfo.NonContigInfo.Strides.push_back(CurStrides);
8712 OpenMPOffloadMappingFlags
8713 getMapModifiersForPrivateClauses(
const CapturedStmt::Capture &Cap)
const {
8721 return OpenMPOffloadMappingFlags::OMP_MAP_TO |
8722 OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ;
8723 return OpenMPOffloadMappingFlags::OMP_MAP_PRIVATE |
8724 OpenMPOffloadMappingFlags::OMP_MAP_TO;
8727 if (I != LambdasMap.end())
8729 return getMapTypeBits(
8730 I->getSecond()->getMapType(), I->getSecond()->getMapTypeModifiers(),
8731 {}, I->getSecond()->isImplicit(),
8735 return OpenMPOffloadMappingFlags::OMP_MAP_TO |
8736 OpenMPOffloadMappingFlags::OMP_MAP_FROM;
8739 void getPlainLayout(
const CXXRecordDecl *RD,
8740 llvm::SmallVectorImpl<const FieldDecl *> &Layout,
8741 bool AsBase)
const {
8744 llvm::StructType *St =
8747 unsigned NumElements = St->getNumElements();
8749 llvm::PointerUnion<const CXXRecordDecl *, const FieldDecl *>, 4>
8750 RecordLayout(NumElements);
8753 for (
const auto &I : RD->
bases()) {
8757 QualType BaseTy = I.getType();
8768 RecordLayout[FieldIndex] =
Base;
8771 for (
const auto &I : RD->
vbases()) {
8772 QualType BaseTy = I.getType();
8779 if (RecordLayout[FieldIndex])
8781 RecordLayout[FieldIndex] =
Base;
8784 assert(!RD->
isUnion() &&
"Unexpected union.");
8785 for (
const auto *Field : RD->
fields()) {
8788 if (!
Field->isBitField() &&
8791 RecordLayout[FieldIndex] =
Field;
8794 for (
const llvm::PointerUnion<const CXXRecordDecl *, const FieldDecl *>
8795 &
Data : RecordLayout) {
8798 if (
const auto *Base = dyn_cast<const CXXRecordDecl *>(
Data))
8799 getPlainLayout(Base, Layout,
true);
8806 static Address getAttachPtrAddr(
const Expr *PointerExpr,
8807 CodeGenFunction &CGF) {
8808 assert(PointerExpr &&
"Cannot get addr from null attach-ptr expr");
8811 if (
auto *DRE = dyn_cast<DeclRefExpr>(PointerExpr)) {
8814 }
else if (
auto *OASE = dyn_cast<ArraySectionExpr>(PointerExpr)) {
8817 }
else if (
auto *ASE = dyn_cast<ArraySubscriptExpr>(PointerExpr)) {
8819 }
else if (
auto *ME = dyn_cast<MemberExpr>(PointerExpr)) {
8821 }
else if (
auto *UO = dyn_cast<UnaryOperator>(PointerExpr)) {
8822 assert(UO->getOpcode() == UO_Deref &&
8823 "Unexpected unary-operator on attach-ptr-expr");
8826 assert(AttachPtrAddr.
isValid() &&
8827 "Failed to get address for attach pointer expression");
8828 return AttachPtrAddr;
8835 static std::pair<Address, Address>
8836 getAttachPtrAddrAndPteeBaseAddr(
const Expr *AttachPtrExpr,
8837 CodeGenFunction &CGF) {
8842 Address AttachPtrAddr = getAttachPtrAddr(AttachPtrExpr, CGF);
8843 assert(AttachPtrAddr.
isValid() &&
"Invalid attach pointer addr");
8845 QualType AttachPtrType =
8850 AttachPtrAddr, AttachPtrType->
castAs<PointerType>());
8851 assert(AttachPteeBaseAddr.
isValid() &&
"Invalid attach pointee base addr");
8853 return {AttachPtrAddr, AttachPteeBaseAddr};
8859 shouldEmitAttachEntry(
const Expr *PointerExpr,
const ValueDecl *MapBaseDecl,
8860 CodeGenFunction &CGF,
8861 llvm::PointerUnion<
const OMPExecutableDirective *,
8862 const OMPDeclareMapperDecl *>
8872 ->getDirectiveKind());
8881 void collectAttachPtrExprInfo(
8883 llvm::PointerUnion<
const OMPExecutableDirective *,
8884 const OMPDeclareMapperDecl *>
8889 ? OMPD_declare_mapper
8892 const auto &[AttachPtrExpr, Depth] =
8896 AttachPtrComputationOrderMap.try_emplace(
8897 AttachPtrExpr, AttachPtrComputationOrderMap.size());
8898 AttachPtrComponentDepthMap.try_emplace(AttachPtrExpr, Depth);
8899 AttachPtrExprMap.try_emplace(Components, AttachPtrExpr);
8907 void generateAllInfoForClauses(
8908 ArrayRef<const OMPClause *> Clauses, MapCombinedInfoTy &CombinedInfo,
8909 llvm::OpenMPIRBuilder &OMPBuilder,
8910 const llvm::DenseSet<CanonicalDeclPtr<const Decl>> &SkipVarSet =
8911 llvm::DenseSet<CanonicalDeclPtr<const Decl>>())
const {
8916 llvm::MapVector<CanonicalDeclPtr<const Decl>,
8917 SmallVector<SmallVector<MapInfo, 8>, 4>>
8923 [&Info, &SkipVarSet](
8924 const ValueDecl *D, MapKind
Kind,
8927 ArrayRef<OpenMPMapModifierKind> MapModifiers,
8928 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
8929 bool ReturnDevicePointer,
bool IsImplicit,
const ValueDecl *Mapper,
8930 const Expr *VarRef =
nullptr,
bool ForDeviceAddr =
false) {
8931 if (SkipVarSet.contains(D))
8933 auto It = Info.try_emplace(D, Total).first;
8934 It->second[
Kind].emplace_back(
8935 L, MapType, MapModifiers, MotionModifiers, ReturnDevicePointer,
8936 IsImplicit, Mapper, VarRef, ForDeviceAddr);
8939 for (
const auto *
Cl : Clauses) {
8940 const auto *
C = dyn_cast<OMPMapClause>(
Cl);
8944 if (llvm::is_contained(
C->getMapTypeModifiers(),
8945 OMPC_MAP_MODIFIER_present))
8947 else if (
C->getMapType() == OMPC_MAP_alloc)
8949 const auto *EI =
C->getVarRefs().begin();
8950 for (
const auto L :
C->component_lists()) {
8951 const Expr *E = (
C->getMapLoc().isValid()) ? *EI :
nullptr;
8952 InfoGen(std::get<0>(L), Kind, std::get<1>(L),
C->getMapType(),
8953 C->getMapTypeModifiers(), {},
8954 false,
C->isImplicit(), std::get<2>(L),
8959 for (
const auto *
Cl : Clauses) {
8960 const auto *
C = dyn_cast<OMPToClause>(
Cl);
8964 if (llvm::is_contained(
C->getMotionModifiers(),
8965 OMPC_MOTION_MODIFIER_present))
8967 if (llvm::is_contained(
C->getMotionModifiers(),
8968 OMPC_MOTION_MODIFIER_iterator)) {
8969 if (
auto *IteratorExpr = dyn_cast<OMPIteratorExpr>(
8970 C->getIteratorModifier()->IgnoreParenImpCasts())) {
8971 const auto *VD =
cast<VarDecl>(IteratorExpr->getIteratorDecl(0));
8976 const auto *EI =
C->getVarRefs().begin();
8977 for (
const auto L :
C->component_lists()) {
8978 InfoGen(std::get<0>(L), Kind, std::get<1>(L), OMPC_MAP_to, {},
8979 C->getMotionModifiers(),
false,
8980 C->isImplicit(), std::get<2>(L), *EI);
8984 for (
const auto *
Cl : Clauses) {
8985 const auto *
C = dyn_cast<OMPFromClause>(
Cl);
8989 if (llvm::is_contained(
C->getMotionModifiers(),
8990 OMPC_MOTION_MODIFIER_present))
8992 if (llvm::is_contained(
C->getMotionModifiers(),
8993 OMPC_MOTION_MODIFIER_iterator)) {
8994 if (
auto *IteratorExpr = dyn_cast<OMPIteratorExpr>(
8995 C->getIteratorModifier()->IgnoreParenImpCasts())) {
8996 const auto *VD =
cast<VarDecl>(IteratorExpr->getIteratorDecl(0));
9001 const auto *EI =
C->getVarRefs().begin();
9002 for (
const auto L :
C->component_lists()) {
9003 InfoGen(std::get<0>(L), Kind, std::get<1>(L), OMPC_MAP_from, {},
9004 C->getMotionModifiers(),
9005 false,
C->isImplicit(), std::get<2>(L),
9018 MapCombinedInfoTy UseDeviceDataCombinedInfo;
9020 auto &&UseDeviceDataCombinedInfoGen =
9021 [&UseDeviceDataCombinedInfo](
const ValueDecl *VD, llvm::Value *
Ptr,
9022 CodeGenFunction &CGF,
bool IsDevAddr,
9023 bool HasUdpFbNullify =
false) {
9024 UseDeviceDataCombinedInfo.Exprs.push_back(VD);
9025 UseDeviceDataCombinedInfo.BasePointers.emplace_back(Ptr);
9026 UseDeviceDataCombinedInfo.DevicePtrDecls.emplace_back(VD);
9027 UseDeviceDataCombinedInfo.DevicePointers.emplace_back(
9028 IsDevAddr ? DeviceInfoTy::Address : DeviceInfoTy::Pointer);
9034 UseDeviceDataCombinedInfo.Pointers.push_back(Ptr);
9035 UseDeviceDataCombinedInfo.Sizes.push_back(
9036 llvm::Constant::getNullValue(CGF.Int64Ty));
9037 OpenMPOffloadMappingFlags Flags =
9038 OpenMPOffloadMappingFlags::OMP_MAP_RETURN_PARAM;
9039 if (HasUdpFbNullify)
9040 Flags |= OpenMPOffloadMappingFlags::OMP_MAP_FB_NULLIFY;
9041 UseDeviceDataCombinedInfo.Types.push_back(Flags);
9042 UseDeviceDataCombinedInfo.HasAttachPtr.push_back(
false);
9043 UseDeviceDataCombinedInfo.Mappers.push_back(
nullptr);
9047 [&UseDeviceDataCombinedInfoGen](
9048 CodeGenFunction &CGF,
const Expr *IE,
const ValueDecl *VD,
9051 bool IsDevAddr,
bool IEIsAttachPtrForDevAddr =
false,
9052 bool HasUdpFbNullify =
false) {
9056 if (IsDevAddr && !IEIsAttachPtrForDevAddr) {
9057 if (IE->isGLValue())
9064 bool TreatDevAddrAsDevPtr = IEIsAttachPtrForDevAddr;
9071 UseDeviceDataCombinedInfoGen(VD, Ptr, CGF, IsDevAddr &&
9072 !TreatDevAddrAsDevPtr,
9076 auto &&IsMapInfoExist =
9077 [&Info,
this](CodeGenFunction &CGF,
const ValueDecl *VD,
const Expr *IE,
9078 const Expr *DesiredAttachPtrExpr,
bool IsDevAddr,
9079 bool HasUdpFbNullify =
false) ->
bool {
9087 if (It != Info.end()) {
9089 for (
auto &
Data : It->second) {
9090 MapInfo *CI =
nullptr;
9094 auto *It = llvm::find_if(
Data, [&](
const MapInfo &MI) {
9095 if (MI.Components.back().getAssociatedDeclaration() != VD)
9098 const Expr *MapAttachPtr = getAttachPtrExpr(MI.Components);
9099 bool Match = AttachPtrComparator.areEqual(MapAttachPtr,
9100 DesiredAttachPtrExpr);
9104 if (It !=
Data.end())
9109 CI->ForDeviceAddr =
true;
9110 CI->ReturnDevicePointer =
true;
9111 CI->HasUdpFbNullify = HasUdpFbNullify;
9115 auto PrevCI = std::next(CI->Components.rbegin());
9116 const auto *VarD = dyn_cast<VarDecl>(VD);
9117 const Expr *AttachPtrExpr = getAttachPtrExpr(CI->Components);
9118 if (CGF.CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory() ||
9120 !VD->getType().getNonReferenceType()->isPointerType() ||
9121 PrevCI == CI->Components.rend() ||
9123 VarD->hasLocalStorage() ||
9124 (isa_and_nonnull<DeclRefExpr>(AttachPtrExpr) &&
9126 CI->ForDeviceAddr = IsDevAddr;
9127 CI->ReturnDevicePointer =
true;
9128 CI->HasUdpFbNullify = HasUdpFbNullify;
9146 for (
const auto *
Cl : Clauses) {
9147 const auto *
C = dyn_cast<OMPUseDevicePtrClause>(
Cl);
9150 bool HasUdpFbNullify =
9151 C->getFallbackModifier() == OMPC_USE_DEVICE_PTR_FALLBACK_fb_nullify;
9152 for (
const auto L :
C->component_lists()) {
9155 assert(!Components.empty() &&
9156 "Not expecting empty list of components!");
9157 const ValueDecl *VD = Components.back().getAssociatedDeclaration();
9159 const Expr *IE = Components.back().getAssociatedExpression();
9167 const Expr *UDPOperandExpr =
9168 Components.front().getAssociatedExpression();
9169 if (IsMapInfoExist(CGF, VD, IE,
9171 false, HasUdpFbNullify))
9173 MapInfoGen(CGF, IE, VD, Components,
false,
9174 false, HasUdpFbNullify);
9178 llvm::SmallDenseSet<CanonicalDeclPtr<const Decl>, 4> Processed;
9179 for (
const auto *
Cl : Clauses) {
9180 const auto *
C = dyn_cast<OMPUseDeviceAddrClause>(
Cl);
9183 for (
const auto L :
C->component_lists()) {
9186 assert(!std::get<1>(L).empty() &&
9187 "Not expecting empty list of components!");
9188 const ValueDecl *VD = std::get<1>(L).back().getAssociatedDeclaration();
9189 if (!Processed.insert(VD).second)
9210 const Expr *UDAAttachPtrExpr = getAttachPtrExpr(Components);
9211 const Expr *IE = std::get<1>(L).back().getAssociatedExpression();
9212 assert((!UDAAttachPtrExpr || UDAAttachPtrExpr == IE) &&
9213 "use_device_addr operand has an attach-ptr, but does not match "
9214 "last component's expr.");
9215 if (IsMapInfoExist(CGF, VD, IE,
9219 MapInfoGen(CGF, IE, VD, Components,
9221 UDAAttachPtrExpr !=
nullptr);
9225 for (
const auto &
Data : Info) {
9226 MapCombinedInfoTy CurInfo;
9228 const ValueDecl *VD = cast_or_null<ValueDecl>(D);
9235 SmallVector<std::pair<const Expr *, MapInfo>, 16> AttachPtrMapInfoPairs;
9238 for (
const auto &M :
Data.second) {
9239 for (
const MapInfo &L : M) {
9240 assert(!L.Components.empty() &&
9241 "Not expecting declaration with no component lists.");
9243 const Expr *AttachPtrExpr = getAttachPtrExpr(L.Components);
9244 AttachPtrMapInfoPairs.emplace_back(AttachPtrExpr, L);
9249 llvm::stable_sort(AttachPtrMapInfoPairs,
9250 [
this](
const auto &LHS,
const auto &RHS) {
9251 return AttachPtrComparator(LHS.first, RHS.first);
9256 auto *It = AttachPtrMapInfoPairs.begin();
9257 while (It != AttachPtrMapInfoPairs.end()) {
9258 const Expr *AttachPtrExpr = It->first;
9260 SmallVector<MapInfo, 8> GroupLists;
9261 while (It != AttachPtrMapInfoPairs.end() &&
9262 (It->first == AttachPtrExpr ||
9263 AttachPtrComparator.areEqual(It->first, AttachPtrExpr))) {
9264 GroupLists.push_back(It->second);
9267 assert(!GroupLists.empty() &&
"GroupLists should not be empty");
9269 StructRangeInfoTy PartialStruct;
9270 AttachInfoTy AttachInfo;
9271 MapCombinedInfoTy GroupCurInfo;
9273 MapCombinedInfoTy GroupStructBaseCurInfo;
9274 for (
const MapInfo &L : GroupLists) {
9276 unsigned CurrentBasePointersIdx = GroupCurInfo.BasePointers.size();
9277 unsigned StructBasePointersIdx =
9278 GroupStructBaseCurInfo.BasePointers.size();
9280 GroupCurInfo.NonContigInfo.IsNonContiguous =
9281 L.Components.back().isNonContiguous();
9282 generateInfoForComponentList(
9283 L.MapType, L.MapModifiers, L.MotionModifiers, L.Components,
9284 GroupCurInfo, GroupStructBaseCurInfo, PartialStruct, AttachInfo,
9285 false, L.IsImplicit,
9286 true, L.Mapper, L.ForDeviceAddr, VD,
9291 if (L.ReturnDevicePointer) {
9295 assert((CurrentBasePointersIdx < GroupCurInfo.BasePointers.size() ||
9296 StructBasePointersIdx <
9297 GroupStructBaseCurInfo.BasePointers.size()) &&
9298 "Unexpected number of mapped base pointers.");
9301 const ValueDecl *RelevantVD =
9302 L.Components.back().getAssociatedDeclaration();
9303 assert(RelevantVD &&
9304 "No relevant declaration related with device pointer??");
9311 auto SetDevicePointerInfo = [&](MapCombinedInfoTy &Info,
9313 Info.DevicePtrDecls[Idx] = RelevantVD;
9314 Info.DevicePointers[Idx] = L.ForDeviceAddr
9315 ? DeviceInfoTy::Address
9316 : DeviceInfoTy::Pointer;
9318 OpenMPOffloadMappingFlags::OMP_MAP_RETURN_PARAM;
9319 if (L.HasUdpFbNullify)
9321 OpenMPOffloadMappingFlags::OMP_MAP_FB_NULLIFY;
9324 if (StructBasePointersIdx <
9325 GroupStructBaseCurInfo.BasePointers.size())
9326 SetDevicePointerInfo(GroupStructBaseCurInfo,
9327 StructBasePointersIdx);
9329 SetDevicePointerInfo(GroupCurInfo, CurrentBasePointersIdx);
9335 MapCombinedInfoTy GroupUnionCurInfo;
9336 GroupUnionCurInfo.append(GroupStructBaseCurInfo);
9337 GroupUnionCurInfo.append(GroupCurInfo);
9341 if (PartialStruct.Base.isValid()) {
9349 GroupUnionCurInfo.NonContigInfo.Dims.insert(
9350 GroupUnionCurInfo.NonContigInfo.Dims.begin(), 1);
9352 CurInfo, GroupUnionCurInfo.Types, PartialStruct, AttachInfo,
9353 !VD, OMPBuilder, VD,
9354 CombinedInfo.BasePointers.size(),
9360 CurInfo.append(GroupUnionCurInfo);
9361 if (AttachInfo.isValid())
9362 emitAttachEntry(CGF, CurInfo, AttachInfo);
9366 CombinedInfo.append(CurInfo);
9369 CombinedInfo.append(UseDeviceDataCombinedInfo);
9373 MappableExprsHandler(
const OMPExecutableDirective &Dir, CodeGenFunction &CGF)
9374 : CurDir(&Dir), CGF(CGF), AttachPtrComparator(*this) {
9376 for (
const auto *
C : Dir.getClausesOfKind<OMPFirstprivateClause>())
9377 for (
const auto *D :
C->varlist())
9378 FirstPrivateDecls.try_emplace(
9381 for (
const auto *
C : Dir.getClausesOfKind<OMPUsesAllocatorsClause>()) {
9382 for (unsigned I = 0, E = C->getNumberOfAllocators(); I < E; ++I) {
9383 OMPUsesAllocatorsClause::Data D = C->getAllocatorData(I);
9384 if (const auto *DRE = dyn_cast_or_null<DeclRefExpr>(D.AllocatorTraits))
9385 FirstPrivateDecls.try_emplace(cast<VarDecl>(DRE->getDecl()),
9387 else if (const auto *VD = dyn_cast<VarDecl>(
9388 cast<DeclRefExpr>(D.Allocator->IgnoreParenImpCasts())
9390 FirstPrivateDecls.try_emplace(VD, true);
9394 for (
const auto *
C : Dir.getClausesOfKind<OMPDefaultmapClause>())
9395 if (
C->getDefaultmapModifier() == OMPC_DEFAULTMAP_MODIFIER_firstprivate)
9396 DefaultmapFirstprivateKinds.insert(
C->getDefaultmapKind());
9398 for (
const auto *
C : Dir.getClausesOfKind<OMPIsDevicePtrClause>())
9399 for (
auto L :
C->component_lists())
9400 DevPointersMap[std::get<0>(L)].push_back(std::get<1>(L));
9402 for (
const auto *
C : Dir.getClausesOfKind<OMPHasDeviceAddrClause>())
9403 for (
auto L :
C->component_lists())
9404 HasDevAddrsMap[std::get<0>(L)].push_back(std::get<1>(L));
9406 for (
const auto *
C : Dir.getClausesOfKind<OMPMapClause>()) {
9407 if (C->getMapType() != OMPC_MAP_to)
9409 for (auto L : C->component_lists()) {
9410 const ValueDecl *VD = std::get<0>(L);
9411 const auto *RD = VD ? VD->getType()
9413 .getNonReferenceType()
9414 ->getAsCXXRecordDecl()
9416 if (RD && RD->isLambda())
9417 LambdasMap.try_emplace(std::get<0>(L), C);
9421 auto CollectAttachPtrExprsForClauseComponents = [
this](
const auto *
C) {
9422 for (
auto L :
C->component_lists()) {
9425 if (!Components.empty())
9426 collectAttachPtrExprInfo(Components, CurDir);
9432 for (
const auto *
C : Dir.getClausesOfKind<OMPMapClause>())
9433 CollectAttachPtrExprsForClauseComponents(
C);
9434 for (
const auto *
C : Dir.getClausesOfKind<OMPToClause>())
9435 CollectAttachPtrExprsForClauseComponents(
C);
9436 for (
const auto *
C : Dir.getClausesOfKind<OMPFromClause>())
9437 CollectAttachPtrExprsForClauseComponents(
C);
9438 for (
const auto *
C : Dir.getClausesOfKind<OMPUseDevicePtrClause>())
9439 CollectAttachPtrExprsForClauseComponents(
C);
9440 for (
const auto *
C : Dir.getClausesOfKind<OMPUseDeviceAddrClause>())
9441 CollectAttachPtrExprsForClauseComponents(
C);
9442 for (
const auto *
C : Dir.getClausesOfKind<OMPIsDevicePtrClause>())
9443 CollectAttachPtrExprsForClauseComponents(
C);
9444 for (
const auto *
C : Dir.getClausesOfKind<OMPHasDeviceAddrClause>())
9445 CollectAttachPtrExprsForClauseComponents(
C);
9449 MappableExprsHandler(
const OMPDeclareMapperDecl &Dir,
CodeGenFunction &CGF)
9450 : CurDir(&Dir), CGF(CGF), AttachPtrComparator(*this) {
9451 auto CollectAttachPtrExprsForClauseComponents = [
this](
const auto *
C) {
9452 for (
auto L :
C->component_lists()) {
9455 if (!Components.empty())
9456 collectAttachPtrExprInfo(Components, CurDir);
9464 if (const auto *C = dyn_cast<OMPMapClause>(Cl))
9465 CollectAttachPtrExprsForClauseComponents(C);
9466 else if (const auto *C = dyn_cast<OMPToClause>(Cl))
9467 CollectAttachPtrExprsForClauseComponents(C);
9468 else if (const auto *C = dyn_cast<OMPFromClause>(Cl))
9469 CollectAttachPtrExprsForClauseComponents(C);
9481 void emitCombinedEntry(MapCombinedInfoTy &CombinedInfo,
9482 MapFlagsArrayTy &CurTypes,
9483 const StructRangeInfoTy &PartialStruct,
9484 AttachInfoTy &AttachInfo,
bool IsMapThis,
9485 llvm::OpenMPIRBuilder &OMPBuilder,
const ValueDecl *VD,
9486 unsigned OffsetForMemberOfFlag,
9487 bool NotTargetParams)
const {
9488 if (CurTypes.size() == 1 &&
9489 ((CurTypes.back() & OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF) !=
9490 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF) &&
9491 !PartialStruct.IsArraySection)
9493 Address LBAddr = PartialStruct.LowestElem.second;
9494 Address HBAddr = PartialStruct.HighestElem.second;
9495 if (PartialStruct.HasCompleteRecord) {
9496 LBAddr = PartialStruct.LB;
9497 HBAddr = PartialStruct.LB;
9499 CombinedInfo.Exprs.push_back(VD);
9501 CombinedInfo.BasePointers.push_back(PartialStruct.Base.emitRawPointer(CGF));
9502 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
9503 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
9506 const CXXMethodDecl *MD =
9508 const CXXRecordDecl *RD = MD ? MD->
getParent() :
nullptr;
9509 bool HasBaseClass = RD && IsMapThis ? RD->
getNumBases() > 0 :
false;
9519 CombinedInfo.Pointers.push_back(PartialStruct.Base.emitRawPointer(CGF));
9524 CombinedInfo.Sizes.push_back(Size);
9526 CombinedInfo.Pointers.push_back(LB);
9529 llvm::Value *HAddr = CGF.
Builder.CreateConstGEP1_32(
9533 llvm::Value *Diff = CGF.
Builder.CreatePtrDiff(CHAddr, CLAddr);
9536 CombinedInfo.Sizes.push_back(Size);
9538 CombinedInfo.Mappers.push_back(
nullptr);
9540 CombinedInfo.Types.push_back(
9541 NotTargetParams ? OpenMPOffloadMappingFlags::OMP_MAP_NONE
9542 : !PartialStruct.PreliminaryMapData.BasePointers.empty()
9543 ? OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ
9544 : OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM);
9552 CombinedInfo.HasAttachPtr.push_back(AttachInfo.isValid());
9555 if (CurTypes.end() !=
9556 llvm::find_if(CurTypes, [](OpenMPOffloadMappingFlags
Type) {
9557 return static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>>(
9558 Type & OpenMPOffloadMappingFlags::OMP_MAP_PRESENT);
9560 CombinedInfo.Types.back() |= OpenMPOffloadMappingFlags::OMP_MAP_PRESENT;
9562 (*CurTypes.begin()) &= ~OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM;
9569 if (CurTypes.end() !=
9570 llvm::find_if(CurTypes, [](OpenMPOffloadMappingFlags
Type) {
9571 return static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>>(
9572 Type & OpenMPOffloadMappingFlags::OMP_MAP_OMPX_HOLD);
9574 CombinedInfo.Types.back() |= OpenMPOffloadMappingFlags::OMP_MAP_OMPX_HOLD;
9575 for (
auto &M : CurTypes)
9576 M |= OpenMPOffloadMappingFlags::OMP_MAP_OMPX_HOLD;
9583 OpenMPOffloadMappingFlags MemberOfFlag = OMPBuilder.getMemberOfFlag(
9584 OffsetForMemberOfFlag + CombinedInfo.BasePointers.size() - 1);
9585 for (
auto &M : CurTypes)
9586 OMPBuilder.setCorrectMemberOfFlag(M, MemberOfFlag);
9603 if (AttachInfo.isValid())
9604 AttachInfo.AttachPteeAddr = LBAddr;
9612 void generateAllInfo(
9613 MapCombinedInfoTy &CombinedInfo, llvm::OpenMPIRBuilder &OMPBuilder,
9614 const llvm::DenseSet<CanonicalDeclPtr<const Decl>> &SkipVarSet =
9615 llvm::DenseSet<CanonicalDeclPtr<const Decl>>())
const {
9617 "Expect a executable directive");
9619 generateAllInfoForClauses(CurExecDir->clauses(), CombinedInfo, OMPBuilder,
9626 void generateAllInfoForMapper(MapCombinedInfoTy &CombinedInfo,
9627 llvm::OpenMPIRBuilder &OMPBuilder)
const {
9629 "Expect a declare mapper directive");
9631 generateAllInfoForClauses(CurMapperDir->clauses(), CombinedInfo,
9636 void generateInfoForLambdaCaptures(
9637 const ValueDecl *VD, llvm::Value *Arg, MapCombinedInfoTy &CombinedInfo,
9638 llvm::DenseMap<llvm::Value *, llvm::Value *> &LambdaPointers)
const {
9646 llvm::DenseMap<const ValueDecl *, FieldDecl *> Captures;
9647 FieldDecl *ThisCapture =
nullptr;
9653 LambdaPointers.try_emplace(ThisLVal.getPointer(CGF),
9654 VDLVal.getPointer(CGF));
9655 CombinedInfo.Exprs.push_back(VD);
9656 CombinedInfo.BasePointers.push_back(ThisLVal.getPointer(CGF));
9657 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
9658 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
9659 CombinedInfo.Pointers.push_back(ThisLValVal.getPointer(CGF));
9660 CombinedInfo.Sizes.push_back(
9663 CombinedInfo.Types.push_back(
9664 OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ |
9665 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL |
9666 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF |
9667 OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT);
9668 CombinedInfo.HasAttachPtr.push_back(
false);
9669 CombinedInfo.Mappers.push_back(
nullptr);
9671 for (
const LambdaCapture &LC : RD->
captures()) {
9672 if (!LC.capturesVariable())
9677 auto It = Captures.find(VD);
9678 assert(It != Captures.end() &&
"Found lambda capture without field.");
9682 LambdaPointers.try_emplace(VarLVal.getPointer(CGF),
9683 VDLVal.getPointer(CGF));
9684 CombinedInfo.Exprs.push_back(VD);
9685 CombinedInfo.BasePointers.push_back(VarLVal.getPointer(CGF));
9686 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
9687 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
9688 CombinedInfo.Pointers.push_back(VarLValVal.getPointer(CGF));
9689 CombinedInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
9695 LambdaPointers.try_emplace(VarLVal.getPointer(CGF),
9696 VDLVal.getPointer(CGF));
9697 CombinedInfo.Exprs.push_back(VD);
9698 CombinedInfo.BasePointers.push_back(VarLVal.getPointer(CGF));
9699 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
9700 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
9701 CombinedInfo.Pointers.push_back(VarRVal.
getScalarVal());
9702 CombinedInfo.Sizes.push_back(llvm::ConstantInt::get(CGF.
Int64Ty, 0));
9704 CombinedInfo.Types.push_back(
9705 OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ |
9706 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL |
9707 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF |
9708 OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT);
9709 CombinedInfo.HasAttachPtr.push_back(
false);
9710 CombinedInfo.Mappers.push_back(
nullptr);
9715 void adjustMemberOfForLambdaCaptures(
9716 llvm::OpenMPIRBuilder &OMPBuilder,
9717 const llvm::DenseMap<llvm::Value *, llvm::Value *> &LambdaPointers,
9718 MapBaseValuesArrayTy &BasePointers, MapValuesArrayTy &Pointers,
9719 MapFlagsArrayTy &Types)
const {
9720 for (
unsigned I = 0, E = Types.size(); I < E; ++I) {
9722 if (Types[I] != (OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ |
9723 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL |
9724 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF |
9725 OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT))
9727 llvm::Value *BasePtr = LambdaPointers.lookup(BasePointers[I]);
9728 assert(BasePtr &&
"Unable to find base lambda address.");
9730 for (
unsigned J = I; J > 0; --J) {
9731 unsigned Idx = J - 1;
9732 if (Pointers[Idx] != BasePtr)
9737 assert(TgtIdx != -1 &&
"Unable to find parent lambda.");
9741 OpenMPOffloadMappingFlags MemberOfFlag =
9742 OMPBuilder.getMemberOfFlag(TgtIdx);
9743 OMPBuilder.setCorrectMemberOfFlag(Types[I], MemberOfFlag);
9749 void populateComponentListsForNonLambdaCaptureFromClauses(
9750 const ValueDecl *VD, MapDataArrayTy &DeclComponentLists,
9752 SmallVector<OMPClauseMappableExprCommon::MappableComponent, 8>>
9753 &StorageForImplicitlyAddedComponentLists)
const {
9754 if (VD && LambdasMap.count(VD))
9760 auto It = DevPointersMap.find(VD);
9761 if (It != DevPointersMap.end())
9762 for (
const auto &MCL : It->second)
9763 DeclComponentLists.emplace_back(MCL, OMPC_MAP_to,
Unknown,
9766 auto I = HasDevAddrsMap.find(VD);
9767 if (I != HasDevAddrsMap.end())
9768 for (
const auto &MCL : I->second)
9769 DeclComponentLists.emplace_back(MCL, OMPC_MAP_tofrom,
Unknown,
9773 "Expect a executable directive");
9775 for (
const auto *
C : CurExecDir->getClausesOfKind<OMPMapClause>()) {
9776 const auto *EI =
C->getVarRefs().begin();
9777 for (
const auto L :
C->decl_component_lists(VD)) {
9778 const ValueDecl *VDecl, *Mapper;
9780 const Expr *E = (
C->getMapLoc().isValid()) ? *EI :
nullptr;
9782 std::tie(VDecl, Components, Mapper) = L;
9783 assert(VDecl == VD &&
"We got information for the wrong declaration??");
9784 assert(!Components.empty() &&
9785 "Not expecting declaration with no component lists.");
9786 DeclComponentLists.emplace_back(Components,
C->getMapType(),
9787 C->getMapTypeModifiers(),
9788 C->isImplicit(), Mapper, E);
9797 addImplicitMapForAttachPtrBaseIfMemberOfCapturedVD(
9798 VD, DeclComponentLists, StorageForImplicitlyAddedComponentLists);
9800 llvm::stable_sort(DeclComponentLists, [](
const MapData &LHS,
9801 const MapData &RHS) {
9802 ArrayRef<OpenMPMapModifierKind> MapModifiers = std::get<2>(LHS);
9805 llvm::is_contained(MapModifiers, clang::OMPC_MAP_MODIFIER_present);
9806 bool HasAllocs = MapType == OMPC_MAP_alloc;
9807 MapModifiers = std::get<2>(RHS);
9808 MapType = std::get<1>(LHS);
9810 llvm::is_contained(MapModifiers, clang::OMPC_MAP_MODIFIER_present);
9811 bool HasAllocsR = MapType == OMPC_MAP_alloc;
9812 return (HasPresent && !HasPresentR) || (HasAllocs && !HasAllocsR);
9848 void addImplicitMapForAttachPtrBaseIfMemberOfCapturedVD(
9849 const ValueDecl *CapturedVD, MapDataArrayTy &DeclComponentLists,
9851 SmallVector<OMPClauseMappableExprCommon::MappableComponent, 8>>
9852 &ComponentVectorStorage)
const {
9853 bool IsThisCapture = CapturedVD ==
nullptr;
9855 for (
const auto &ComponentsAndAttachPtr : AttachPtrExprMap) {
9857 ComponentsWithAttachPtr = ComponentsAndAttachPtr.first;
9858 const Expr *AttachPtrExpr = ComponentsAndAttachPtr.second;
9862 const auto *ME = dyn_cast<MemberExpr>(AttachPtrExpr);
9866 const Expr *
Base = ME->getBase()->IgnoreParenImpCasts();
9887 bool FoundExistingMap =
false;
9888 for (
const MapData &ExistingL : DeclComponentLists) {
9890 ExistingComponents = std::get<0>(ExistingL);
9892 if (ExistingComponents.empty())
9896 const auto &FirstComponent = ExistingComponents.front();
9897 const Expr *FirstExpr = FirstComponent.getAssociatedExpression();
9903 if (AttachPtrComparator.areEqual(FirstExpr, AttachPtrExpr)) {
9904 FoundExistingMap =
true;
9909 if (IsThisCapture) {
9910 if (
const auto *OASE = dyn_cast<ArraySectionExpr>(FirstExpr)) {
9912 FoundExistingMap =
true;
9921 if (
const auto *DRE = dyn_cast<DeclRefExpr>(FirstExpr)) {
9922 if (DRE->getDecl() == CapturedVD) {
9923 FoundExistingMap =
true;
9929 if (FoundExistingMap)
9935 ComponentVectorStorage.emplace_back();
9936 auto &AttachPtrComponents = ComponentVectorStorage.back();
9939 bool SeenAttachPtrComponent =
false;
9945 for (
size_t i = 0; i < ComponentsWithAttachPtr.size(); ++i) {
9946 const auto &Component = ComponentsWithAttachPtr[i];
9947 const Expr *ComponentExpr = Component.getAssociatedExpression();
9949 if (!SeenAttachPtrComponent && ComponentExpr != AttachPtrExpr)
9951 SeenAttachPtrComponent =
true;
9953 AttachPtrComponents.emplace_back(Component.getAssociatedExpression(),
9954 Component.getAssociatedDeclaration(),
9955 Component.isNonContiguous());
9957 assert(!AttachPtrComponents.empty() &&
9958 "Could not populate component-lists for mapping attach-ptr");
9960 DeclComponentLists.emplace_back(
9961 AttachPtrComponents, OMPC_MAP_tofrom,
Unknown,
9962 true,
nullptr, AttachPtrExpr);
9969 void generateInfoForCaptureFromClauseInfo(
9970 const MapDataArrayTy &DeclComponentListsFromClauses,
9971 const CapturedStmt::Capture *Cap, llvm::Value *Arg,
9972 MapCombinedInfoTy &CurCaptureVarInfo, llvm::OpenMPIRBuilder &OMPBuilder,
9973 unsigned OffsetForMemberOfFlag)
const {
9975 "Not expecting to generate map info for a variable array type!");
9984 if (LambdasMap.count(VD))
9990 if (VD && (DevPointersMap.count(VD) || HasDevAddrsMap.count(VD))) {
9991 CurCaptureVarInfo.Exprs.push_back(VD);
9992 CurCaptureVarInfo.BasePointers.emplace_back(Arg);
9993 CurCaptureVarInfo.DevicePtrDecls.emplace_back(VD);
9994 CurCaptureVarInfo.DevicePointers.emplace_back(DeviceInfoTy::Pointer);
9995 CurCaptureVarInfo.Pointers.push_back(Arg);
9996 CurCaptureVarInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
9999 CurCaptureVarInfo.Types.push_back(
10000 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL |
10001 OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM);
10002 CurCaptureVarInfo.HasAttachPtr.push_back(
false);
10003 CurCaptureVarInfo.Mappers.push_back(
nullptr);
10007 auto GenerateInfoForComponentLists =
10008 [&](ArrayRef<MapData> DeclComponentListsFromClauses,
10009 bool IsEligibleForTargetParamFlag) {
10010 MapCombinedInfoTy CurInfoForComponentLists;
10011 StructRangeInfoTy PartialStruct;
10012 AttachInfoTy AttachInfo;
10014 if (DeclComponentListsFromClauses.empty())
10017 generateInfoForCaptureFromComponentLists(
10018 VD, DeclComponentListsFromClauses, CurInfoForComponentLists,
10019 PartialStruct, AttachInfo, IsEligibleForTargetParamFlag);
10024 if (PartialStruct.Base.isValid()) {
10025 CurCaptureVarInfo.append(PartialStruct.PreliminaryMapData);
10027 CurCaptureVarInfo, CurInfoForComponentLists.Types,
10028 PartialStruct, AttachInfo, Cap->
capturesThis(), OMPBuilder,
10029 nullptr, OffsetForMemberOfFlag,
10030 !IsEligibleForTargetParamFlag);
10035 CurCaptureVarInfo.append(CurInfoForComponentLists);
10036 if (AttachInfo.isValid())
10037 emitAttachEntry(CGF, CurCaptureVarInfo, AttachInfo);
10061 SmallVector<std::pair<const Expr *, MapData>, 16> AttachPtrMapDataPairs;
10063 for (
const MapData &L : DeclComponentListsFromClauses) {
10066 const Expr *AttachPtrExpr = getAttachPtrExpr(Components);
10067 AttachPtrMapDataPairs.emplace_back(AttachPtrExpr, L);
10071 llvm::stable_sort(AttachPtrMapDataPairs,
10072 [
this](
const auto &LHS,
const auto &RHS) {
10073 return AttachPtrComparator(LHS.first, RHS.first);
10076 bool NoDefaultMappingDoneForVD = CurCaptureVarInfo.BasePointers.empty();
10077 bool IsFirstGroup =
true;
10081 auto *It = AttachPtrMapDataPairs.begin();
10082 while (It != AttachPtrMapDataPairs.end()) {
10083 const Expr *AttachPtrExpr = It->first;
10085 MapDataArrayTy GroupLists;
10086 while (It != AttachPtrMapDataPairs.end() &&
10087 (It->first == AttachPtrExpr ||
10088 AttachPtrComparator.areEqual(It->first, AttachPtrExpr))) {
10089 GroupLists.push_back(It->second);
10092 assert(!GroupLists.empty() &&
"GroupLists should not be empty");
10097 bool IsEligibleForTargetParamFlag =
10098 IsFirstGroup && NoDefaultMappingDoneForVD;
10100 GenerateInfoForComponentLists(GroupLists, IsEligibleForTargetParamFlag);
10101 IsFirstGroup =
false;
10108 void generateInfoForCaptureFromComponentLists(
10109 const ValueDecl *VD, ArrayRef<MapData> DeclComponentLists,
10110 MapCombinedInfoTy &CurComponentListInfo, StructRangeInfoTy &PartialStruct,
10111 AttachInfoTy &AttachInfo,
bool IsListEligibleForTargetParamFlag)
const {
10113 llvm::SmallDenseMap<
10120 for (
const MapData &L : DeclComponentLists) {
10123 ArrayRef<OpenMPMapModifierKind> MapModifiers;
10125 const ValueDecl *Mapper;
10126 const Expr *VarRef;
10127 std::tie(Components, MapType, MapModifiers, IsImplicit, Mapper, VarRef) =
10130 for (
const MapData &L1 : ArrayRef(DeclComponentLists).slice(Count)) {
10132 std::tie(Components1, MapType, MapModifiers, IsImplicit, Mapper,
10134 auto CI = Components.rbegin();
10135 auto CE = Components.rend();
10136 auto SI = Components1.rbegin();
10137 auto SE = Components1.rend();
10138 for (; CI != CE && SI != SE; ++CI, ++SI) {
10139 if (CI->getAssociatedExpression()->getStmtClass() !=
10140 SI->getAssociatedExpression()->getStmtClass())
10143 if (CI->getAssociatedDeclaration() != SI->getAssociatedDeclaration())
10148 if (CI == CE || SI == SE) {
10150 if (CI == CE && SI == SE)
10152 const auto It = (SI == SE) ? CI : SI;
10159 (std::prev(It)->getAssociatedDeclaration() &&
10161 ->getAssociatedDeclaration()
10163 ->isPointerType()) ||
10164 (It->getAssociatedDeclaration() &&
10165 It->getAssociatedDeclaration()->getType()->isPointerType() &&
10166 std::next(It) != CE && std::next(It) != SE))
10168 const MapData &BaseData = CI == CE ? L : L1;
10170 SI == SE ? Components : Components1;
10171 OverlappedData[&BaseData].push_back(SubData);
10176 llvm::SmallVector<const FieldDecl *, 4> Layout;
10177 if (!OverlappedData.empty()) {
10180 while (BaseType != OrigType) {
10186 getPlainLayout(CRD, Layout,
false);
10192 for (
auto &Pair : OverlappedData) {
10199 auto CI = First.rbegin();
10200 auto CE = First.rend();
10201 auto SI = Second.rbegin();
10202 auto SE = Second.rend();
10203 for (; CI != CE && SI != SE; ++CI, ++SI) {
10204 if (CI->getAssociatedExpression()->getStmtClass() !=
10205 SI->getAssociatedExpression()->getStmtClass())
10208 if (CI->getAssociatedDeclaration() !=
10209 SI->getAssociatedDeclaration())
10214 if (CI == CE && SI == SE)
10218 if (CI == CE || SI == SE)
10223 if (FD1->getParent() == FD2->getParent())
10224 return FD1->getFieldIndex() < FD2->getFieldIndex();
10226 llvm::find_if(Layout, [FD1, FD2](
const FieldDecl *FD) {
10227 return FD == FD1 || FD == FD2;
10235 bool AddTargetParamFlag = IsListEligibleForTargetParamFlag;
10236 MapCombinedInfoTy StructBaseCombinedInfo;
10237 for (
const auto &Pair : OverlappedData) {
10238 const MapData &L = *Pair.getFirst();
10241 ArrayRef<OpenMPMapModifierKind> MapModifiers;
10243 const ValueDecl *Mapper;
10244 const Expr *VarRef;
10245 std::tie(Components, MapType, MapModifiers, IsImplicit, Mapper, VarRef) =
10247 ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef>
10248 OverlappedComponents = Pair.getSecond();
10249 generateInfoForComponentList(
10250 MapType, MapModifiers, {}, Components, CurComponentListInfo,
10251 StructBaseCombinedInfo, PartialStruct, AttachInfo, AddTargetParamFlag,
10252 IsImplicit,
false, Mapper,
10253 false, VD, VarRef, OverlappedComponents);
10254 AddTargetParamFlag =
false;
10257 for (
const MapData &L : DeclComponentLists) {
10260 ArrayRef<OpenMPMapModifierKind> MapModifiers;
10262 const ValueDecl *Mapper;
10263 const Expr *VarRef;
10264 std::tie(Components, MapType, MapModifiers, IsImplicit, Mapper, VarRef) =
10266 auto It = OverlappedData.find(&L);
10267 if (It == OverlappedData.end())
10268 generateInfoForComponentList(
10269 MapType, MapModifiers, {}, Components, CurComponentListInfo,
10270 StructBaseCombinedInfo, PartialStruct, AttachInfo,
10271 AddTargetParamFlag, IsImplicit,
false,
10272 Mapper,
false, VD, VarRef,
10274 AddTargetParamFlag =
false;
10280 bool isEffectivelyFirstprivate(
const VarDecl *VD, QualType
Type)
const {
10282 auto I = FirstPrivateDecls.find(VD);
10283 if (I != FirstPrivateDecls.end() && !I->getSecond())
10287 if (DefaultmapFirstprivateKinds.count(OMPC_DEFAULTMAP_scalar)) {
10288 if (
Type->isScalarType())
10293 if (DefaultmapFirstprivateKinds.count(OMPC_DEFAULTMAP_pointer)) {
10294 if (
Type->isAnyPointerType())
10299 if (DefaultmapFirstprivateKinds.count(OMPC_DEFAULTMAP_aggregate)) {
10300 if (
Type->isAggregateType())
10305 return DefaultmapFirstprivateKinds.count(OMPC_DEFAULTMAP_all);
10310 void generateDefaultMapInfo(
const CapturedStmt::Capture &CI,
10311 const FieldDecl &RI, llvm::Value *CV,
10312 MapCombinedInfoTy &CombinedInfo)
const {
10313 bool IsImplicit =
true;
10316 CombinedInfo.Exprs.push_back(
nullptr);
10317 CombinedInfo.BasePointers.push_back(CV);
10318 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
10319 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
10320 CombinedInfo.Pointers.push_back(CV);
10322 CombinedInfo.Sizes.push_back(
10326 CombinedInfo.Types.push_back(OpenMPOffloadMappingFlags::OMP_MAP_TO |
10327 OpenMPOffloadMappingFlags::OMP_MAP_FROM);
10331 CombinedInfo.BasePointers.push_back(CV);
10332 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
10333 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
10334 CombinedInfo.Pointers.push_back(CV);
10335 bool IsFirstprivate =
10341 CombinedInfo.Types.push_back(
10342 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL);
10343 CombinedInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
10345 }
else if (IsFirstprivate) {
10348 CombinedInfo.Types.push_back(
10349 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL);
10351 CombinedInfo.Sizes.push_back(llvm::Constant::getNullValue(CGF.
Int64Ty));
10355 CombinedInfo.Types.push_back(OpenMPOffloadMappingFlags::OMP_MAP_NONE);
10356 CombinedInfo.Sizes.push_back(llvm::Constant::getNullValue(CGF.
Int64Ty));
10358 auto I = FirstPrivateDecls.find(VD);
10359 if (I != FirstPrivateDecls.end())
10360 IsImplicit = I->getSecond();
10366 bool IsFirstprivate = isEffectivelyFirstprivate(VD, ElementType);
10368 CombinedInfo.BasePointers.push_back(CV);
10369 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
10370 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
10373 if (IsFirstprivate && ElementType->isAnyPointerType()) {
10375 CombinedInfo.Pointers.push_back(CV);
10377 CombinedInfo.Sizes.push_back(llvm::Constant::getNullValue(CGF.
Int64Ty));
10378 CombinedInfo.Types.push_back(
10379 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL);
10381 CombinedInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
10386 CombinedInfo.Types.push_back(getMapModifiersForPrivateClauses(CI));
10387 CombinedInfo.Pointers.push_back(CV);
10389 auto I = FirstPrivateDecls.find(VD);
10390 if (I != FirstPrivateDecls.end())
10391 IsImplicit = I->getSecond();
10394 CombinedInfo.Types.back() |=
10395 OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM;
10399 CombinedInfo.Types.back() |= OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT;
10401 CombinedInfo.HasAttachPtr.push_back(
false);
10403 CombinedInfo.Mappers.push_back(
nullptr);
10415 dyn_cast<MemberExpr>(OASE->getBase()->IgnoreParenImpCasts()))
10416 return ME->getMemberDecl();
10422static llvm::Constant *
10424 MappableExprsHandler::MappingExprInfo &MapExprs) {
10427 if (!MapExprs.getMapDecl() && !MapExprs.getMapExpr())
10428 return OMPBuilder.getOrCreateDefaultSrcLocStr(SrcLocStrSize);
10431 if (!MapExprs.getMapDecl() && MapExprs.getMapExpr()) {
10435 Loc = MapExprs.getMapExpr()->getExprLoc();
10437 Loc = MapExprs.getMapDecl()->getLocation();
10440 std::string ExprName;
10441 if (MapExprs.getMapExpr()) {
10443 llvm::raw_string_ostream OS(ExprName);
10444 MapExprs.getMapExpr()->printPretty(OS,
nullptr, P);
10446 ExprName = MapExprs.getMapDecl()->getNameAsString();
10455 return OMPBuilder.getOrCreateSrcLocStr(
FileName, ExprName, PLoc.
getLine(),
10462 CodeGenFunction &CGF, MappableExprsHandler::MapCombinedInfoTy &CombinedInfo,
10464 bool IsNonContiguous =
false,
bool ForEndCall =
false) {
10467 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
10470 InsertPointTy CodeGenIP(CGF.
Builder.GetInsertBlock(),
10471 CGF.
Builder.GetInsertPoint());
10473 auto DeviceAddrCB = [&](
unsigned int I, llvm::Value *NewDecl) {
10474 if (
const ValueDecl *DevVD = CombinedInfo.DevicePtrDecls[I]) {
10479 auto CustomMapperCB = [&](
unsigned int I) {
10480 llvm::Function *MFunc =
nullptr;
10481 if (CombinedInfo.Mappers[I]) {
10482 Info.HasMapper =
true;
10488 cantFail(OMPBuilder.emitOffloadingArraysAndArgs(
10489 AllocaIP, CodeGenIP, Info, Info.RTArgs, CombinedInfo, CustomMapperCB,
10490 IsNonContiguous, ForEndCall, DeviceAddrCB));
10494static const OMPExecutableDirective *
10496 const auto *CS = D.getInnermostCapturedStmt();
10499 const Stmt *ChildStmt =
10502 if (
const auto *NestedDir =
10503 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) {
10505 switch (D.getDirectiveKind()) {
10511 if (DKind == OMPD_teams) {
10512 Body = NestedDir->getInnermostCapturedStmt()->IgnoreContainers(
10517 if (
const auto *NND =
10518 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) {
10519 DKind = NND->getDirectiveKind();
10525 case OMPD_target_teams:
10529 case OMPD_target_parallel:
10530 case OMPD_target_simd:
10531 case OMPD_target_parallel_for:
10532 case OMPD_target_parallel_for_simd:
10534 case OMPD_target_teams_distribute:
10535 case OMPD_target_teams_distribute_simd:
10536 case OMPD_target_teams_distribute_parallel_for:
10537 case OMPD_target_teams_distribute_parallel_for_simd:
10538 case OMPD_parallel:
10540 case OMPD_parallel_for:
10541 case OMPD_parallel_master:
10542 case OMPD_parallel_sections:
10543 case OMPD_for_simd:
10544 case OMPD_parallel_for_simd:
10546 case OMPD_cancellation_point:
10547 case OMPD_ordered_standalone:
10548 case OMPD_ordered_blockassoc:
10549 case OMPD_threadprivate:
10550 case OMPD_allocate:
10555 case OMPD_sections:
10559 case OMPD_critical:
10560 case OMPD_taskyield:
10562 case OMPD_taskwait:
10563 case OMPD_taskgroup:
10569 case OMPD_target_data:
10570 case OMPD_target_exit_data:
10571 case OMPD_target_enter_data:
10572 case OMPD_distribute:
10573 case OMPD_distribute_simd:
10574 case OMPD_distribute_parallel_for:
10575 case OMPD_distribute_parallel_for_simd:
10576 case OMPD_teams_distribute:
10577 case OMPD_teams_distribute_simd:
10578 case OMPD_teams_distribute_parallel_for:
10579 case OMPD_teams_distribute_parallel_for_simd:
10580 case OMPD_target_update:
10581 case OMPD_declare_simd:
10582 case OMPD_declare_variant:
10583 case OMPD_begin_declare_variant:
10584 case OMPD_end_declare_variant:
10585 case OMPD_declare_target:
10586 case OMPD_end_declare_target:
10587 case OMPD_declare_reduction:
10588 case OMPD_declare_mapper:
10589 case OMPD_taskloop:
10590 case OMPD_taskloop_simd:
10591 case OMPD_master_taskloop:
10592 case OMPD_master_taskloop_simd:
10593 case OMPD_parallel_master_taskloop:
10594 case OMPD_parallel_master_taskloop_simd:
10595 case OMPD_requires:
10596 case OMPD_metadirective:
10599 llvm_unreachable(
"Unexpected directive.");
10659 if (
UDMMap.count(D) > 0)
10663 auto *MapperVarDecl =
10665 CharUnits ElementSize =
C.getTypeSizeInChars(Ty);
10666 llvm::Type *ElemTy =
CGM.getTypes().ConvertTypeForMem(Ty);
10669 MappableExprsHandler::MapCombinedInfoTy CombinedInfo;
10670 auto PrivatizeAndGenMapInfoCB =
10671 [&](llvm::OpenMPIRBuilder::InsertPointTy CodeGenIP, llvm::Value *PtrPHI,
10672 llvm::Value *BeginArg) -> llvm::OpenMPIRBuilder::MapInfosTy & {
10673 MapperCGF.
Builder.restoreIP(CodeGenIP);
10683 Scope.addPrivate(MapperVarDecl, PtrCurrent);
10684 (void)
Scope.Privatize();
10687 MappableExprsHandler MEHandler(*D, MapperCGF);
10688 MEHandler.generateAllInfoForMapper(CombinedInfo,
OMPBuilder);
10690 auto FillInfoMap = [&](MappableExprsHandler::MappingExprInfo &MapExpr) {
10693 if (
CGM.getCodeGenOpts().getDebugInfo() !=
10694 llvm::codegenoptions::NoDebugInfo) {
10695 CombinedInfo.Names.resize(CombinedInfo.Exprs.size());
10696 llvm::transform(CombinedInfo.Exprs, CombinedInfo.Names.begin(),
10700 return CombinedInfo;
10703 auto CustomMapperCB = [&](
unsigned I) {
10704 llvm::Function *MapperFunc =
nullptr;
10705 if (CombinedInfo.Mappers[I]) {
10709 assert(MapperFunc &&
"Expect a valid mapper function is available.");
10715 llvm::raw_svector_ostream Out(TyStr);
10716 CGM.getCXXABI().getMangleContext().mangleCanonicalTypeName(Ty, Out);
10717 std::string Name =
getName({
"omp_mapper", TyStr, D->
getName()});
10723 bool PropagatePresentToPointee =
CGM.getLangOpts().OpenMP >= 60;
10724 llvm::Function *NewFn = cantFail(
OMPBuilder.emitUserDefinedMapper(
10725 PrivatizeAndGenMapInfoCB, ElemTy, Name, CustomMapperCB,
10726 false, PropagatePresentToPointee));
10727 UDMMap.try_emplace(D, NewFn);
10734 auto I =
UDMMap.find(D);
10738 return UDMMap.lookup(D);
10751 Kind != OMPD_target_teams_loop)
10754 return llvm::ConstantInt::get(CGF.
Int64Ty, 0);
10757 if (llvm::Value *NumIterations = SizeEmitter(CGF, *LD))
10758 return NumIterations;
10759 return llvm::ConstantInt::get(CGF.
Int64Ty, 0);
10768 if (OffloadingMandatory) {
10769 CGF.
Builder.CreateUnreachable();
10771 if (RequiresOuterTask) {
10772 CapturedVars.clear();
10776 CapturedVars.end());
10777 Args.push_back(llvm::Constant::getNullValue(CGF.
Builder.getPtrTy()));
10784 llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier>
Device,
10787 llvm::Value *DeviceID;
10788 if (
Device.getPointer()) {
10790 Device.getInt() == OMPC_DEVICE_device_num) &&
10791 "Expected device_num modifier.");
10796 DeviceID = CGF.
Builder.getInt64(OMP_DEVICEID_UNDEF);
10801static std::pair<llvm::Value *, OMPDynGroupprivateFallbackType>
10803 llvm::Value *DynGP = CGF.
Builder.getInt32(0);
10804 auto DynGPFallback = OMPDynGroupprivateFallbackType::Abort;
10808 llvm::Value *DynGPVal =
10812 auto FallbackModifier = DynGPClause->getDynGroupprivateFallbackModifier();
10813 switch (FallbackModifier) {
10814 case OMPC_DYN_GROUPPRIVATE_FALLBACK_abort:
10815 DynGPFallback = OMPDynGroupprivateFallbackType::Abort;
10817 case OMPC_DYN_GROUPPRIVATE_FALLBACK_null:
10818 DynGPFallback = OMPDynGroupprivateFallbackType::Null;
10820 case OMPC_DYN_GROUPPRIVATE_FALLBACK_default_mem:
10823 DynGPFallback = OMPDynGroupprivateFallbackType::DefaultMem;
10826 llvm_unreachable(
"Unknown fallback modifier for OpenMP dyn_groupprivate");
10828 }
else if (
auto *OMPXDynCGClause =
10831 llvm::Value *DynCGMemVal = CGF.
EmitScalarExpr(OMPXDynCGClause->getSize(),
10836 return {DynGP, DynGPFallback};
10842 llvm::OpenMPIRBuilder &OMPBuilder,
10844 MappableExprsHandler::MapCombinedInfoTy &CombinedInfo) {
10846 llvm::DenseMap<llvm::Value *, llvm::Value *> LambdaPointers;
10848 auto *CV = CapturedVars.begin();
10851 CI != CE; ++CI, ++RI, ++CV) {
10852 MappableExprsHandler::MapCombinedInfoTy CurInfo;
10857 CurInfo.Exprs.push_back(
nullptr);
10858 CurInfo.BasePointers.push_back(*CV);
10859 CurInfo.DevicePtrDecls.push_back(
nullptr);
10860 CurInfo.DevicePointers.push_back(
10861 MappableExprsHandler::DeviceInfoTy::None);
10862 CurInfo.Pointers.push_back(*CV);
10863 CurInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
10866 CurInfo.Types.push_back(OpenMPOffloadMappingFlags::OMP_MAP_LITERAL |
10867 OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM |
10868 OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT);
10869 CurInfo.HasAttachPtr.push_back(
false);
10870 CurInfo.Mappers.push_back(
nullptr);
10875 bool HasEntryWithCVAsAttachPtr =
false;
10877 HasEntryWithCVAsAttachPtr =
10878 MEHandler.hasAttachEntryForCapturedVar(CapturedVD);
10881 MappableExprsHandler::MapDataArrayTy DeclComponentLists;
10884 StorageForImplicitlyAddedComponentLists;
10885 MEHandler.populateComponentListsForNonLambdaCaptureFromClauses(
10886 CapturedVD, DeclComponentLists,
10887 StorageForImplicitlyAddedComponentLists);
10898 bool HasEntryWithoutAttachPtr =
10899 llvm::any_of(DeclComponentLists, [&](
const auto &MapData) {
10901 Components = std::get<0>(MapData);
10902 return !MEHandler.getAttachPtrExpr(Components);
10907 if (DeclComponentLists.empty() ||
10908 (!HasEntryWithCVAsAttachPtr && !HasEntryWithoutAttachPtr))
10909 MEHandler.generateDefaultMapInfo(*CI, **RI, *CV, CurInfo);
10913 MEHandler.generateInfoForCaptureFromClauseInfo(
10914 DeclComponentLists, CI, *CV, CurInfo, OMPBuilder,
10915 CombinedInfo.BasePointers.size());
10920 MappedVarSet.insert(
nullptr);
10925 MEHandler.generateInfoForLambdaCaptures(CI->
getCapturedVar(), *CV,
10926 CurInfo, LambdaPointers);
10929 assert(!CurInfo.BasePointers.empty() &&
10930 "Non-existing map pointer for capture!");
10931 assert(CurInfo.BasePointers.size() == CurInfo.Pointers.size() &&
10932 CurInfo.BasePointers.size() == CurInfo.Sizes.size() &&
10933 CurInfo.BasePointers.size() == CurInfo.Types.size() &&
10934 CurInfo.BasePointers.size() == CurInfo.Mappers.size() &&
10935 "Inconsistent map information sizes!");
10938 CombinedInfo.append(CurInfo);
10941 MEHandler.adjustMemberOfForLambdaCaptures(
10942 OMPBuilder, LambdaPointers, CombinedInfo.BasePointers,
10943 CombinedInfo.Pointers, CombinedInfo.Types);
10947 MappableExprsHandler::MapCombinedInfoTy &CombinedInfo,
10948 llvm::OpenMPIRBuilder &OMPBuilder,
10955 MEHandler.generateAllInfo(CombinedInfo, OMPBuilder, SkippedVarSet);
10957 auto FillInfoMap = [&](MappableExprsHandler::MappingExprInfo &MapExpr) {
10961 llvm::codegenoptions::NoDebugInfo) {
10962 CombinedInfo.Names.resize(CombinedInfo.Exprs.size());
10963 llvm::transform(CombinedInfo.Exprs, CombinedInfo.Names.begin(),
10971 llvm::OpenMPIRBuilder &OMPBuilder,
10972 MappableExprsHandler::MapCombinedInfoTy &CombinedInfo) {
10974 MappableExprsHandler MEHandler(D, CGF);
10975 llvm::DenseSet<CanonicalDeclPtr<const Decl>> MappedVarSet;
10978 MappedVarSet, CombinedInfo);
10979 genMapInfo(MEHandler, CGF, CombinedInfo, OMPBuilder, MappedVarSet);
10982template <
typename ClauseTy>
10987 const auto *
C = D.getSingleClause<ClauseTy>();
10988 assert(!
C->varlist_empty() &&
10989 "ompx_bare requires explicit num_teams and thread_limit");
10991 for (
auto *E :
C->varlist()) {
11003 llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier>
Device,
11005 llvm::Value *&MapTypesArray, llvm::Value *&MapNamesArray,
11010 llvm::OpenMPIRBuilder &OMPBuilder = OMPRuntime->
getOMPBuilder();
11013 MappableExprsHandler::MapCombinedInfoTy CombinedInfo;
11015 genMapInfo(D, CGF, CS, CapturedVars, OMPBuilder, CombinedInfo);
11018 using OpenMPOffloadMappingFlags = llvm::omp::OpenMPOffloadMappingFlags;
11019 auto *NullPtr = llvm::Constant::getNullValue(CGF.
Builder.getPtrTy());
11020 CombinedInfo.BasePointers.push_back(NullPtr);
11021 CombinedInfo.Pointers.push_back(NullPtr);
11022 CombinedInfo.DevicePointers.push_back(
11023 llvm::OpenMPIRBuilder::DeviceInfoTy::None);
11024 CombinedInfo.Sizes.push_back(CGF.
Builder.getInt64(0));
11025 CombinedInfo.Types.push_back(OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM |
11026 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL);
11027 CombinedInfo.HasAttachPtr.push_back(
false);
11028 if (!CombinedInfo.Names.empty())
11029 CombinedInfo.Names.push_back(NullPtr);
11030 CombinedInfo.Exprs.push_back(
nullptr);
11031 CombinedInfo.Mappers.push_back(
nullptr);
11032 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
11046 MapTypesArray = Info.RTArgs.MapTypesArray;
11047 MapNamesArray = Info.RTArgs.MapNamesArray;
11049 auto &&ThenGen = [&OMPRuntime, OutlinedFn, &D, &CapturedVars,
11050 RequiresOuterTask, &CS, OffloadingMandatory,
Device,
11051 OutlinedFnID, &InputInfo, &MapTypesArray, &MapNamesArray,
11053 bool IsReverseOffloading =
Device.getInt() == OMPC_DEVICE_ancestor;
11055 if (IsReverseOffloading) {
11061 RequiresOuterTask, CS, OffloadingMandatory, CGF);
11065 bool HasNoWait = D.hasClausesOfKind<OMPNowaitClause>();
11066 unsigned NumTargetItems = InputInfo.NumberOfTargetItems;
11068 llvm::Value *BasePointersArray =
11069 InputInfo.BasePointersArray.emitRawPointer(CGF);
11070 llvm::Value *PointersArray = InputInfo.PointersArray.emitRawPointer(CGF);
11071 llvm::Value *SizesArray = InputInfo.SizesArray.emitRawPointer(CGF);
11072 llvm::Value *MappersArray = InputInfo.MappersArray.emitRawPointer(CGF);
11074 auto &&EmitTargetCallFallbackCB =
11075 [&OMPRuntime, OutlinedFn, &D, &CapturedVars, RequiresOuterTask, &CS,
11076 OffloadingMandatory, &CGF](llvm::OpenMPIRBuilder::InsertPointTy IP)
11077 -> llvm::OpenMPIRBuilder::InsertPointTy {
11080 RequiresOuterTask, CS, OffloadingMandatory, CGF);
11093 NumThreads.push_back(
11099 llvm::Value *NumIterations =
11102 llvm::OpenMPIRBuilder::InsertPointTy AllocaIP(
11105 llvm::OpenMPIRBuilder::TargetDataRTArgs RTArgs(
11106 BasePointersArray, PointersArray, SizesArray, MapTypesArray,
11107 nullptr , MappersArray, MapNamesArray);
11109 llvm::OpenMPIRBuilder::TargetKernelArgs Args(
11110 NumTargetItems, RTArgs, NumIterations, NumTeams, NumThreads,
11111 DynCGroupMem, HasNoWait, IsBare,
11112 IsBare, DynCGroupMemFallback);
11114 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
11116 CGF.
Builder, OutlinedFnID, EmitTargetCallFallbackCB, Args, DeviceID,
11118 CGF.
Builder.restoreIP(AfterIP);
11121 if (RequiresOuterTask)
11136 [&OMPRuntime, OutlinedFn, &D, &CapturedVars, RequiresOuterTask, &CS,
11139 RequiresOuterTask, CS, OffloadingMandatory, CGF);
11142 if (RequiresOuterTask) {
11152 llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID,
const Expr *IfCond,
11153 llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier>
Device,
11160 const bool OffloadingMandatory = !
CGM.getLangOpts().OpenMPIsTargetDevice &&
11161 CGM.getLangOpts().OpenMPOffloadMandatory;
11163 assert((OffloadingMandatory || OutlinedFn) &&
"Invalid outlined function!");
11165 const bool RequiresOuterTask =
11167 D.hasClausesOfKind<OMPNowaitClause>() ||
11168 D.hasClausesOfKind<OMPInReductionClause>() ||
11169 (
CGM.getLangOpts().OpenMP >= 51 &&
11173 const CapturedStmt &CS = *D.getCapturedStmt(OMPD_target);
11181 llvm::Value *MapTypesArray =
nullptr;
11182 llvm::Value *MapNamesArray =
nullptr;
11184 auto &&TargetThenGen = [
this, OutlinedFn, &D, &CapturedVars,
11185 RequiresOuterTask, &CS, OffloadingMandatory,
Device,
11186 OutlinedFnID, &InputInfo, &MapTypesArray,
11190 RequiresOuterTask, CS, OffloadingMandatory,
11191 Device, OutlinedFnID, InputInfo, MapTypesArray,
11192 MapNamesArray, SizeEmitter, CGF,
CGM);
11195 auto &&TargetElseGen =
11196 [
this, OutlinedFn, &D, &CapturedVars, RequiresOuterTask, &CS,
11199 CS, OffloadingMandatory, CGF);
11206 if (OutlinedFnID) {
11208 emitIfClause(CGF, IfCond, TargetThenGen, TargetElseGen);
11220 StringRef ParentName) {
11227 if (
auto *E = dyn_cast<OMPExecutableDirective>(S);
11236 bool RequiresDeviceCodegen =
11241 if (RequiresDeviceCodegen) {
11249 if (!
OMPBuilder.OffloadInfoManager.hasTargetRegionEntryInfo(EntryInfo))
11252 switch (E.getDirectiveKind()) {
11257 case OMPD_target_parallel:
11261 case OMPD_target_teams:
11265 case OMPD_target_teams_distribute:
11269 case OMPD_target_teams_distribute_simd:
11273 case OMPD_target_parallel_for:
11277 case OMPD_target_parallel_for_simd:
11281 case OMPD_target_simd:
11285 case OMPD_target_teams_distribute_parallel_for:
11290 case OMPD_target_teams_distribute_parallel_for_simd:
11296 case OMPD_target_teams_loop:
11300 case OMPD_target_parallel_loop:
11304 case OMPD_parallel:
11306 case OMPD_parallel_for:
11307 case OMPD_parallel_master:
11308 case OMPD_parallel_sections:
11309 case OMPD_for_simd:
11310 case OMPD_parallel_for_simd:
11312 case OMPD_cancellation_point:
11313 case OMPD_ordered_standalone:
11314 case OMPD_ordered_blockassoc:
11315 case OMPD_threadprivate:
11316 case OMPD_allocate:
11321 case OMPD_sections:
11325 case OMPD_critical:
11326 case OMPD_taskyield:
11328 case OMPD_taskwait:
11329 case OMPD_taskgroup:
11335 case OMPD_target_data:
11336 case OMPD_target_exit_data:
11337 case OMPD_target_enter_data:
11338 case OMPD_distribute:
11339 case OMPD_distribute_simd:
11340 case OMPD_distribute_parallel_for:
11341 case OMPD_distribute_parallel_for_simd:
11342 case OMPD_teams_distribute:
11343 case OMPD_teams_distribute_simd:
11344 case OMPD_teams_distribute_parallel_for:
11345 case OMPD_teams_distribute_parallel_for_simd:
11346 case OMPD_target_update:
11347 case OMPD_declare_simd:
11348 case OMPD_declare_variant:
11349 case OMPD_begin_declare_variant:
11350 case OMPD_end_declare_variant:
11351 case OMPD_declare_target:
11352 case OMPD_end_declare_target:
11353 case OMPD_declare_reduction:
11354 case OMPD_declare_mapper:
11355 case OMPD_taskloop:
11356 case OMPD_taskloop_simd:
11357 case OMPD_master_taskloop:
11358 case OMPD_master_taskloop_simd:
11359 case OMPD_parallel_master_taskloop:
11360 case OMPD_parallel_master_taskloop_simd:
11361 case OMPD_requires:
11362 case OMPD_metadirective:
11365 llvm_unreachable(
"Unknown target directive for OpenMP device codegen.");
11370 if (
const auto *E = dyn_cast<OMPExecutableDirective>(S)) {
11371 if (!E->hasAssociatedStmt() || !E->getAssociatedStmt())
11379 if (
const auto *L = dyn_cast<LambdaExpr>(S))
11388 std::optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
11389 OMPDeclareTargetDeclAttr::getDeviceType(VD);
11393 if (!IsDevice && DevTy == OMPDeclareTargetDeclAttr::DT_NoHost)
11396 if (IsDevice && DevTy == OMPDeclareTargetDeclAttr::DT_Host)
11404 if (!
CGM.getLangOpts().OpenMPIsTargetDevice) {
11405 if (
const auto *FD = dyn_cast<FunctionDecl>(GD.
getDecl()))
11407 CGM.getLangOpts().OpenMPIsTargetDevice))
11414 if (
const auto *FD = dyn_cast<FunctionDecl>(VD)) {
11415 StringRef Name =
CGM.getMangledName(GD);
11418 CGM.getLangOpts().OpenMPIsTargetDevice))
11423 return !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD) &&
11429 CGM.getLangOpts().OpenMPIsTargetDevice))
11432 if (!
CGM.getLangOpts().OpenMPIsTargetDevice)
11441 StringRef ParentName =
11446 StringRef ParentName =
11453 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
11454 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(
11456 if (!Res || *Res == OMPDeclareTargetDeclAttr::MT_Link ||
11457 ((*Res == OMPDeclareTargetDeclAttr::MT_To ||
11458 *Res == OMPDeclareTargetDeclAttr::MT_Enter) &&
11467 llvm::Constant *
Addr) {
11468 if (
CGM.getLangOpts().OMPTargetTriples.empty() &&
11469 !
CGM.getLangOpts().OpenMPIsTargetDevice)
11472 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
11473 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
11477 if (Res && *Res != OMPDeclareTargetDeclAttr::MT_Link &&
11483 if (Res && *Res == OMPDeclareTargetDeclAttr::MT_Local)
11487 if (
CGM.getLangOpts().OpenMPIsTargetDevice) {
11490 StringRef VarName =
CGM.getMangledName(VD);
11496 auto AddrOfGlobal = [&VD,
this]() {
return CGM.GetAddrOfGlobal(VD); };
11497 auto LinkageForVariable = [&VD,
this]() {
11498 return CGM.getLLVMLinkageVarDefinition(VD);
11501 std::vector<llvm::GlobalVariable *> GeneratedRefs;
11508 CGM.getMangledName(VD), GeneratedRefs,
CGM.getLangOpts().OpenMPSimd,
11509 CGM.getLangOpts().OMPTargetTriples, AddrOfGlobal, LinkageForVariable,
11510 CGM.getTypes().ConvertTypeForMem(
11511 CGM.getContext().getPointerType(VD->
getType())),
11514 for (
auto *ref : GeneratedRefs)
11515 CGM.addCompilerUsedGlobal(ref);
11528 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
11529 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
11533 if (*Res == OMPDeclareTargetDeclAttr::MT_Local ||
11534 ((*Res == OMPDeclareTargetDeclAttr::MT_To ||
11535 *Res == OMPDeclareTargetDeclAttr::MT_Enter) &&
11537 CGM.EmitGlobal(VD);
11539 assert((*Res == OMPDeclareTargetDeclAttr::MT_Link ||
11540 ((*Res == OMPDeclareTargetDeclAttr::MT_To ||
11541 *Res == OMPDeclareTargetDeclAttr::MT_Enter ||
11542 *Res == OMPDeclareTargetDeclAttr::MT_Local) &&
11544 "Expected link clause or to clause with unified memory.");
11545 (void)
CGM.getOpenMPRuntime().getAddrOfDeclareTargetVar(VD);
11553 " Expected target-based directive.");
11558 if (Clause->getClauseKind() == OMPC_unified_shared_memory) {
11560 OMPBuilder.Config.setHasRequiresUnifiedSharedMemory(
true);
11561 }
else if (
const auto *AC =
11562 dyn_cast<OMPAtomicDefaultMemOrderClause>(Clause)) {
11563 switch (AC->getAtomicDefaultMemOrderKind()) {
11564 case OMPC_ATOMIC_DEFAULT_MEM_ORDER_acq_rel:
11567 case OMPC_ATOMIC_DEFAULT_MEM_ORDER_seq_cst:
11570 case OMPC_ATOMIC_DEFAULT_MEM_ORDER_relaxed:
11586 if (!VD || !VD->
hasAttr<OMPAllocateDeclAttr>())
11588 const auto *A = VD->
getAttr<OMPAllocateDeclAttr>();
11589 switch(A->getAllocatorType()) {
11590 case OMPAllocateDeclAttr::OMPNullMemAlloc:
11591 case OMPAllocateDeclAttr::OMPDefaultMemAlloc:
11593 case OMPAllocateDeclAttr::OMPLargeCapMemAlloc:
11594 case OMPAllocateDeclAttr::OMPCGroupMemAlloc:
11595 case OMPAllocateDeclAttr::OMPHighBWMemAlloc:
11596 case OMPAllocateDeclAttr::OMPLowLatMemAlloc:
11597 case OMPAllocateDeclAttr::OMPThreadMemAlloc:
11598 case OMPAllocateDeclAttr::OMPConstMemAlloc:
11599 case OMPAllocateDeclAttr::OMPPTeamMemAlloc:
11602 case OMPAllocateDeclAttr::OMPUserDefinedMemAlloc:
11603 llvm_unreachable(
"Expected predefined allocator for the variables with the "
11604 "static storage.");
11616 if (CGM.getLangOpts().OpenMPIsTargetDevice) {
11617 SavedShouldMarkAsGlobal = CGM.getOpenMPRuntime().ShouldMarkAsGlobal;
11618 CGM.getOpenMPRuntime().ShouldMarkAsGlobal = false;
11623 if (CGM.getLangOpts().OpenMPIsTargetDevice)
11624 CGM.getOpenMPRuntime().ShouldMarkAsGlobal = SavedShouldMarkAsGlobal;
11634 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(D)) {
11636 if (
auto *F = dyn_cast_or_null<llvm::Function>(
11637 CGM.GetGlobalValue(
CGM.getMangledName(GD))))
11638 return !F->isDeclaration();
11650 llvm::Function *OutlinedFn,
11659 llvm::Value *Args[] = {
11661 CGF.
Builder.getInt32(CapturedVars.size()),
11664 RealArgs.append(std::begin(Args), std::end(Args));
11665 RealArgs.append(CapturedVars.begin(), CapturedVars.end());
11667 llvm::FunctionCallee RTLFn =
OMPBuilder.getOrCreateRuntimeFunction(
11668 CGM.getModule(), OMPRTL___kmpc_fork_teams);
11673 const Expr *NumTeams,
11674 const Expr *ThreadLimit,
11681 llvm::Value *NumTeamsVal =
11687 llvm::Value *ThreadLimitVal =
11694 llvm::Value *PushNumTeamsArgs[] = {RTLoc,
getThreadID(CGF, Loc), NumTeamsVal,
11697 CGM.getModule(), OMPRTL___kmpc_push_num_teams),
11702 const Expr *ThreadLimit,
11705 llvm::Value *ThreadLimitVal =
11712 llvm::Value *ThreadLimitArgs[] = {RTLoc,
getThreadID(CGF, Loc),
11715 CGM.getModule(), OMPRTL___kmpc_set_thread_limit),
11730 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
11732 llvm::Value *IfCondVal =
nullptr;
11737 llvm::Value *DeviceID =
nullptr;
11742 DeviceID = CGF.
Builder.getInt64(OMP_DEVICEID_UNDEF);
11746 MappableExprsHandler::MapCombinedInfoTy CombinedInfo;
11747 auto GenMapInfoCB =
11748 [&](InsertPointTy CodeGenIP) -> llvm::OpenMPIRBuilder::MapInfosTy & {
11749 CGF.
Builder.restoreIP(CodeGenIP);
11751 MappableExprsHandler MEHandler(D, CGF);
11752 MEHandler.generateAllInfo(CombinedInfo,
OMPBuilder);
11754 auto FillInfoMap = [&](MappableExprsHandler::MappingExprInfo &MapExpr) {
11757 if (
CGM.getCodeGenOpts().getDebugInfo() !=
11758 llvm::codegenoptions::NoDebugInfo) {
11759 CombinedInfo.Names.resize(CombinedInfo.Exprs.size());
11760 llvm::transform(CombinedInfo.Exprs, CombinedInfo.Names.begin(),
11764 return CombinedInfo;
11766 using BodyGenTy = llvm::OpenMPIRBuilder::BodyGenTy;
11767 auto BodyCB = [&](InsertPointTy CodeGenIP, BodyGenTy BodyGenType) {
11768 CGF.
Builder.restoreIP(CodeGenIP);
11769 switch (BodyGenType) {
11770 case BodyGenTy::Priv:
11774 case BodyGenTy::DupNoPriv:
11776 CodeGen.setAction(NoPrivAction);
11780 case BodyGenTy::NoPriv:
11782 CodeGen.setAction(NoPrivAction);
11787 return InsertPointTy(CGF.
Builder.GetInsertBlock(),
11788 CGF.
Builder.GetInsertPoint());
11791 auto DeviceAddrCB = [&](
unsigned int I, llvm::Value *NewDecl) {
11792 if (
const ValueDecl *DevVD = CombinedInfo.DevicePtrDecls[I]) {
11797 auto CustomMapperCB = [&](
unsigned int I) {
11798 llvm::Function *MFunc =
nullptr;
11799 if (CombinedInfo.Mappers[I]) {
11800 Info.HasMapper =
true;
11812 InsertPointTy CodeGenIP(CGF.
Builder.GetInsertBlock(),
11813 CGF.
Builder.GetInsertPoint());
11814 llvm::OpenMPIRBuilder::LocationDescription OmpLoc(CGF.
Builder);
11815 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
11817 OmpLoc, AllocaIP, CodeGenIP, {}, DeviceID,
11818 IfCondVal, Info, GenMapInfoCB, CustomMapperCB,
11819 nullptr, BodyCB, DeviceAddrCB, RTLoc));
11820 CGF.
Builder.restoreIP(AfterIP);
11832 "Expecting either target enter, exit data, or update directives.");
11835 llvm::Value *MapTypesArray =
nullptr;
11836 llvm::Value *MapNamesArray =
nullptr;
11838 auto &&ThenGen = [
this, &D,
Device, &InputInfo, &MapTypesArray,
11841 llvm::Value *DeviceID =
nullptr;
11846 DeviceID = CGF.
Builder.getInt64(OMP_DEVICEID_UNDEF);
11850 llvm::Constant *PointerNum =
11857 {RTLoc, DeviceID, PointerNum,
11865 const bool HasNowait = D.hasClausesOfKind<OMPNowaitClause>();
11866 RuntimeFunction RTLFn;
11867 switch (D.getDirectiveKind()) {
11868 case OMPD_target_enter_data:
11869 RTLFn = HasNowait ? OMPRTL___tgt_target_data_begin_nowait_mapper
11870 : OMPRTL___tgt_target_data_begin_mapper;
11872 case OMPD_target_exit_data:
11873 RTLFn = HasNowait ? OMPRTL___tgt_target_data_end_nowait_mapper
11874 : OMPRTL___tgt_target_data_end_mapper;
11876 case OMPD_target_update:
11877 RTLFn = HasNowait ? OMPRTL___tgt_target_data_update_nowait_mapper
11878 : OMPRTL___tgt_target_data_update_mapper;
11880 case OMPD_parallel:
11882 case OMPD_parallel_for:
11883 case OMPD_parallel_master:
11884 case OMPD_parallel_sections:
11885 case OMPD_for_simd:
11886 case OMPD_parallel_for_simd:
11888 case OMPD_cancellation_point:
11889 case OMPD_ordered_standalone:
11890 case OMPD_ordered_blockassoc:
11891 case OMPD_threadprivate:
11892 case OMPD_allocate:
11897 case OMPD_sections:
11901 case OMPD_critical:
11902 case OMPD_taskyield:
11904 case OMPD_taskwait:
11905 case OMPD_taskgroup:
11911 case OMPD_target_data:
11912 case OMPD_distribute:
11913 case OMPD_distribute_simd:
11914 case OMPD_distribute_parallel_for:
11915 case OMPD_distribute_parallel_for_simd:
11916 case OMPD_teams_distribute:
11917 case OMPD_teams_distribute_simd:
11918 case OMPD_teams_distribute_parallel_for:
11919 case OMPD_teams_distribute_parallel_for_simd:
11920 case OMPD_declare_simd:
11921 case OMPD_declare_variant:
11922 case OMPD_begin_declare_variant:
11923 case OMPD_end_declare_variant:
11924 case OMPD_declare_target:
11925 case OMPD_end_declare_target:
11926 case OMPD_declare_reduction:
11927 case OMPD_declare_mapper:
11928 case OMPD_taskloop:
11929 case OMPD_taskloop_simd:
11930 case OMPD_master_taskloop:
11931 case OMPD_master_taskloop_simd:
11932 case OMPD_parallel_master_taskloop:
11933 case OMPD_parallel_master_taskloop_simd:
11935 case OMPD_target_simd:
11936 case OMPD_target_teams_distribute:
11937 case OMPD_target_teams_distribute_simd:
11938 case OMPD_target_teams_distribute_parallel_for:
11939 case OMPD_target_teams_distribute_parallel_for_simd:
11940 case OMPD_target_teams:
11941 case OMPD_target_parallel:
11942 case OMPD_target_parallel_for:
11943 case OMPD_target_parallel_for_simd:
11944 case OMPD_requires:
11945 case OMPD_metadirective:
11948 llvm_unreachable(
"Unexpected standalone target data directive.");
11952 OffloadingArgs.push_back(llvm::Constant::getNullValue(CGF.
Int32Ty));
11953 OffloadingArgs.push_back(llvm::Constant::getNullValue(CGF.
VoidPtrTy));
11954 OffloadingArgs.push_back(llvm::Constant::getNullValue(CGF.
Int32Ty));
11955 OffloadingArgs.push_back(llvm::Constant::getNullValue(CGF.
VoidPtrTy));
11958 OMPBuilder.getOrCreateRuntimeFunction(
CGM.getModule(), RTLFn),
11962 auto &&TargetThenGen = [
this, &ThenGen, &D, &InputInfo, &MapTypesArray,
11966 MappableExprsHandler::MapCombinedInfoTy CombinedInfo;
11968 MappableExprsHandler MEHandler(D, CGF);
11974 D.hasClausesOfKind<OMPNowaitClause>();
11980 CGM.getPointerAlign());
11985 MapTypesArray = Info.RTArgs.MapTypesArray;
11986 MapNamesArray = Info.RTArgs.MapNamesArray;
11987 if (RequiresOuterTask)
12032 unsigned Offset = 0;
12033 if (
const auto *MD = dyn_cast<CXXMethodDecl>(FD)) {
12034 if (ParamAttrs[Offset].Kind ==
12035 llvm::OpenMPIRBuilder::DeclareSimdKindTy::Vector)
12036 CDT =
C.getPointerType(
C.getCanonicalTagType(MD->
getParent()));
12040 for (
unsigned I = 0, E = FD->
getNumParams(); I < E; ++I) {
12041 if (ParamAttrs[I + Offset].Kind ==
12042 llvm::OpenMPIRBuilder::DeclareSimdKindTy::Vector) {
12054 return C.getTypeSize(CDT);
12065 llvm::OpenMPIRBuilder::DeclareSimdKindTy Kind) {
12071 if (Kind == llvm::OpenMPIRBuilder::DeclareSimdKindTy::Uniform)
12074 if (Kind == llvm::OpenMPIRBuilder::DeclareSimdKindTy::LinearUVal ||
12075 Kind == llvm::OpenMPIRBuilder::DeclareSimdKindTy::LinearRef)
12078 if ((Kind == llvm::OpenMPIRBuilder::DeclareSimdKindTy::Linear ||
12079 Kind == llvm::OpenMPIRBuilder::DeclareSimdKindTy::LinearVal) &&
12089 unsigned Size =
C.getTypeSize(QT);
12092 if (Size != 8 && Size != 16 && Size != 32 && Size != 64 && Size != 128)
12113 llvm::OpenMPIRBuilder::DeclareSimdKindTy Kind,
12118 return C.getTypeSize(PTy);
12121 return C.getTypeSize(QT);
12123 return C.getTypeSize(
C.getUIntPtrType());
12129static std::tuple<unsigned, unsigned, bool>
12136 bool OutputBecomesInput =
false;
12141 RetType, llvm::OpenMPIRBuilder::DeclareSimdKindTy::Vector,
C));
12143 OutputBecomesInput =
true;
12145 for (
unsigned I = 0, E = FD->
getNumParams(); I < E; ++I) {
12150 assert(!Sizes.empty() &&
"Unable to determine NDS and WDS.");
12153 assert(llvm::all_of(Sizes,
12154 [](
unsigned Size) {
12155 return Size == 8 || Size == 16 || Size == 32 ||
12156 Size == 64 || Size == 128;
12160 return std::make_tuple(*llvm::min_element(Sizes), *llvm::max_element(Sizes),
12161 OutputBecomesInput);
12164static llvm::OpenMPIRBuilder::DeclareSimdBranch
12167 case OMPDeclareSimdDeclAttr::BS_Undefined:
12168 return llvm::OpenMPIRBuilder::DeclareSimdBranch::Undefined;
12169 case OMPDeclareSimdDeclAttr::BS_Inbranch:
12170 return llvm::OpenMPIRBuilder::DeclareSimdBranch::Inbranch;
12171 case OMPDeclareSimdDeclAttr::BS_Notinbranch:
12172 return llvm::OpenMPIRBuilder::DeclareSimdBranch::Notinbranch;
12174 llvm_unreachable(
"unexpected declare simd branch state");
12179 unsigned UserVLEN,
unsigned WDS,
char ISA) {
12181 if (UserVLEN == 1) {
12188 if (ISA ==
'n' && UserVLEN && !llvm::isPowerOf2_32(UserVLEN)) {
12194 if (ISA ==
's' && UserVLEN != 0 &&
12195 ((UserVLEN * WDS > 2048) || (UserVLEN * WDS % 128 != 0))) {
12204 llvm::Function *Fn) {
12209 llvm::DenseMap<const Decl *, unsigned> ParamPositions;
12211 ParamPositions.try_emplace(FD, 0);
12212 unsigned ParamPos = ParamPositions.size();
12214 ParamPositions.try_emplace(P->getCanonicalDecl(), ParamPos);
12219 ParamPositions.size());
12221 for (
const Expr *E :
Attr->uniforms()) {
12225 Pos = ParamPositions[FD];
12228 ->getCanonicalDecl();
12229 auto It = ParamPositions.find(PVD);
12230 assert(It != ParamPositions.end() &&
"Function parameter not found");
12233 ParamAttrs[Pos].Kind =
12234 llvm::OpenMPIRBuilder::DeclareSimdKindTy::Uniform;
12237 auto *NI =
Attr->alignments_begin();
12238 for (
const Expr *E :
Attr->aligneds()) {
12243 Pos = ParamPositions[FD];
12247 ->getCanonicalDecl();
12248 auto It = ParamPositions.find(PVD);
12249 assert(It != ParamPositions.end() &&
"Function parameter not found");
12251 ParmTy = PVD->getType();
12253 ParamAttrs[Pos].Alignment =
12255 ? (*NI)->EvaluateKnownConstInt(
C)
12256 : llvm::APSInt::getUnsigned(
12257 C.toCharUnitsFromBits(
C.getOpenMPDefaultSimdAlign(ParmTy))
12262 auto *SI =
Attr->steps_begin();
12263 auto *MI =
Attr->modifiers_begin();
12264 for (
const Expr *E :
Attr->linears()) {
12267 bool IsReferenceType =
false;
12270 unsigned PtrRescalingFactor = 1;
12272 Pos = ParamPositions[FD];
12274 PtrRescalingFactor =
CGM.getContext()
12275 .getTypeSizeInChars(P->getPointeeType())
12279 ->getCanonicalDecl();
12280 auto It = ParamPositions.find(PVD);
12281 assert(It != ParamPositions.end() &&
"Function parameter not found");
12283 if (
auto *P = dyn_cast<PointerType>(PVD->getType()))
12284 PtrRescalingFactor =
CGM.getContext()
12285 .getTypeSizeInChars(P->getPointeeType())
12287 else if (PVD->getType()->isReferenceType()) {
12288 IsReferenceType =
true;
12289 PtrRescalingFactor =
12291 .getTypeSizeInChars(PVD->getType().getNonReferenceType())
12295 llvm::OpenMPIRBuilder::DeclareSimdAttrTy &ParamAttr = ParamAttrs[Pos];
12296 if (*MI == OMPC_LINEAR_ref)
12297 ParamAttr.Kind = llvm::OpenMPIRBuilder::DeclareSimdKindTy::LinearRef;
12298 else if (*MI == OMPC_LINEAR_uval)
12299 ParamAttr.Kind = llvm::OpenMPIRBuilder::DeclareSimdKindTy::LinearUVal;
12300 else if (IsReferenceType)
12301 ParamAttr.Kind = llvm::OpenMPIRBuilder::DeclareSimdKindTy::LinearVal;
12303 ParamAttr.Kind = llvm::OpenMPIRBuilder::DeclareSimdKindTy::Linear;
12305 ParamAttr.StrideOrArg = llvm::APSInt::getUnsigned(1);
12309 if (
const auto *DRE =
12311 if (
const auto *StridePVD =
12312 dyn_cast<ParmVarDecl>(DRE->getDecl())) {
12313 ParamAttr.HasVarStride =
true;
12314 auto It = ParamPositions.find(StridePVD->getCanonicalDecl());
12315 assert(It != ParamPositions.end() &&
12316 "Function parameter not found");
12317 ParamAttr.StrideOrArg = llvm::APSInt::getUnsigned(It->second);
12321 ParamAttr.StrideOrArg =
Result.Val.getInt();
12327 if (!ParamAttr.HasVarStride &&
12329 llvm::OpenMPIRBuilder::DeclareSimdKindTy::Linear ||
12331 llvm::OpenMPIRBuilder::DeclareSimdKindTy::LinearRef))
12332 ParamAttr.StrideOrArg = ParamAttr.StrideOrArg * PtrRescalingFactor;
12336 llvm::APSInt VLENVal;
12338 const Expr *VLENExpr =
Attr->getSimdlen();
12343 llvm::OpenMPIRBuilder::DeclareSimdBranch State =
12345 if (
CGM.getTriple().isX86()) {
12347 assert(NumElts &&
"Non-zero simdlen/cdtsize expected");
12348 OMPBuilder.emitX86DeclareSimdFunction(Fn, NumElts, VLENVal, ParamAttrs,
12350 }
else if (
CGM.getTriple().getArch() == llvm::Triple::aarch64) {
12351 unsigned VLEN = VLENVal.getExtValue();
12354 const unsigned NDS = std::get<0>(
Data);
12355 const unsigned WDS = std::get<1>(
Data);
12356 const bool OutputBecomesInput = std::get<2>(
Data);
12357 if (
CGM.getTarget().hasFeature(
"sve")) {
12360 Fn, VLEN, ParamAttrs, State,
's', NDS, OutputBecomesInput);
12361 }
else if (
CGM.getTarget().hasFeature(
"neon")) {
12364 Fn, VLEN, ParamAttrs, State,
'n', NDS, OutputBecomesInput);
12374class DoacrossCleanupTy final :
public EHScopeStack::Cleanup {
12376 static const int DoacrossFinArgs = 2;
12379 llvm::FunctionCallee RTLFn;
12380 llvm::Value *Args[DoacrossFinArgs];
12383 DoacrossCleanupTy(llvm::FunctionCallee RTLFn,
12386 assert(CallArgs.size() == DoacrossFinArgs);
12387 std::copy(CallArgs.begin(), CallArgs.end(), std::begin(Args));
12404 QualType Int64Ty =
C.getIntTypeForBitwidth(64,
true);
12412 RD =
C.buildImplicitRecord(
"kmp_dim");
12420 RD =
KmpDimTy->castAsRecordDecl();
12422 llvm::APInt Size(32, NumIterations.size());
12428 enum { LowerFD = 0, UpperFD, StrideFD };
12430 for (
unsigned I = 0, E = NumIterations.size(); I < E; ++I) {
12435 DimsLVal, *std::next(RD->
field_begin(), UpperFD));
12437 CGF.
EmitScalarExpr(NumIterations[I]), NumIterations[I]->getType(),
12438 Int64Ty, NumIterations[I]->getExprLoc());
12442 DimsLVal, *std::next(RD->
field_begin(), StrideFD));
12449 llvm::Value *Args[] = {
12452 llvm::ConstantInt::getSigned(
CGM.Int32Ty, NumIterations.size()),
12457 llvm::FunctionCallee RTLFn =
OMPBuilder.getOrCreateRuntimeFunction(
12458 CGM.getModule(), OMPRTL___kmpc_doacross_init);
12460 llvm::Value *FiniArgs[DoacrossCleanupTy::DoacrossFinArgs] = {
12462 llvm::FunctionCallee FiniRTLFn =
OMPBuilder.getOrCreateRuntimeFunction(
12463 CGM.getModule(), OMPRTL___kmpc_doacross_fini);
12468template <
typename T>
12470 const T *
C, llvm::Value *ULoc,
12471 llvm::Value *ThreadID) {
12474 llvm::APInt Size(32,
C->getNumLoops());
12478 for (
unsigned I = 0, E =
C->getNumLoops(); I < E; ++I) {
12479 const Expr *CounterVal =
C->getLoopData(I);
12480 assert(CounterVal);
12487 llvm::Value *Args[] = {
12490 llvm::FunctionCallee RTLFn;
12492 OMPDoacrossKind<T> ODK;
12493 if (ODK.isSource(
C)) {
12495 OMPRTL___kmpc_doacross_post);
12497 assert(ODK.isSink(
C) &&
"Expect sink modifier.");
12499 OMPRTL___kmpc_doacross_wait);
12519 llvm::FunctionCallee Callee,
12521 assert(Loc.
isValid() &&
"Outlined function call location must be valid.");
12524 if (
auto *Fn = dyn_cast<llvm::Function>(Callee.getCallee())) {
12525 if (Fn->doesNotThrow()) {
12536 emitCall(CGF, Loc, OutlinedFn, Args);
12540 if (
const auto *FD = dyn_cast<FunctionDecl>(D))
12541 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(FD))
12547 const VarDecl *TargetParam)
const {
12554 const Expr *Allocator) {
12555 llvm::Value *AllocVal;
12565 AllocVal = llvm::Constant::getNullValue(
12575 if (!AllocateAlignment)
12578 return llvm::ConstantInt::get(
CGM.
SizeTy, AllocateAlignment->getQuantity());
12591 auto I = UntiedData.find(VD);
12592 if (I != UntiedData.end()) {
12593 UntiedAddr = I->second.first;
12594 UntiedRealAddr = I->second.second;
12598 if (CVD->
hasAttr<OMPAllocateDeclAttr>()) {
12607 Size = CGF.
Builder.CreateNUWAdd(
12609 Size = CGF.
Builder.CreateUDiv(Size,
CGM.getSize(Align));
12610 Size = CGF.
Builder.CreateNUWMul(Size,
CGM.getSize(Align));
12616 const auto *AA = CVD->
getAttr<OMPAllocateDeclAttr>();
12617 const Expr *Allocator = AA->getAllocator();
12621 Args.push_back(ThreadID);
12623 Args.push_back(Alignment);
12624 Args.push_back(Size);
12625 Args.push_back(AllocVal);
12626 llvm::omp::RuntimeFunction FnID =
12627 Alignment ? OMPRTL___kmpc_aligned_alloc : OMPRTL___kmpc_alloc;
12629 OMPBuilder.getOrCreateRuntimeFunction(
CGM.getModule(), FnID), Args,
12631 llvm::FunctionCallee FiniRTLFn =
OMPBuilder.getOrCreateRuntimeFunction(
12632 CGM.getModule(), OMPRTL___kmpc_free);
12640 class OMPAllocateCleanupTy final :
public EHScopeStack::Cleanup {
12641 llvm::FunctionCallee RTLFn;
12644 const Expr *AllocExpr;
12647 OMPAllocateCleanupTy(llvm::FunctionCallee RTLFn,
12649 const Expr *AllocExpr)
12650 : RTLFn(RTLFn), LocEncoding(LocEncoding),
Addr(
Addr),
12651 AllocExpr(AllocExpr) {}
12655 llvm::Value *Args[3];
12661 Args[2] = AllocVal;
12669 CGF.
EHStack.pushCleanup<OMPAllocateCleanupTy>(
12671 VDAddr, Allocator);
12672 if (UntiedRealAddr.
isValid())
12675 Region->emitUntiedSwitch(CGF);
12692 assert(CGM.getLangOpts().OpenMP &&
"Not in OpenMP mode.");
12696 CGM.getOpenMPRuntime().NontemporalDeclsStack.emplace_back();
12698 for (
const Stmt *Ref :
C->private_refs()) {
12699 const auto *SimpleRefExpr =
cast<Expr>(Ref)->IgnoreParenImpCasts();
12701 if (
const auto *DRE = dyn_cast<DeclRefExpr>(SimpleRefExpr)) {
12702 VD = DRE->getDecl();
12705 assert((ME->isImplicitCXXThis() ||
12707 "Expected member of current class.");
12708 VD = ME->getMemberDecl();
12718 CGM.getOpenMPRuntime().NontemporalDeclsStack.pop_back();
12724 std::pair<Address, Address>> &LocalVars)
12725 : CGM(CGF.CGM), NeedToPush(!LocalVars.empty()) {
12729 CGF.
CurFn, CGM.getOpenMPRuntime().UntiedLocalVarsStack.size());
12730 CGM.getOpenMPRuntime().UntiedLocalVarsStack.push_back(LocalVars);
12736 CGM.getOpenMPRuntime().UntiedLocalVarsStack.pop_back();
12740 assert(
CGM.getLangOpts().OpenMP &&
"Not in OpenMP mode.");
12742 return llvm::any_of(
12743 CGM.getOpenMPRuntime().NontemporalDeclsStack,
12747void CGOpenMPRuntime::LastprivateConditionalRAII::tryToDisableInnerAnalysis(
12751 llvm::DenseSet<CanonicalDeclPtr<const Decl>> NeedToCheckForLPCs;
12757 const CapturedStmt *CS = S.getCapturedStmt(CaptureRegions.front());
12764 for (
const auto *
C : S.getClausesOfKind<OMPPrivateClause>()) {
12765 for (
const Expr *Ref :
C->varlist()) {
12766 if (!Ref->getType()->isScalarType())
12768 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
12771 NeedToCheckForLPCs.insert(DRE->getDecl());
12774 for (
const auto *
C : S.getClausesOfKind<OMPFirstprivateClause>()) {
12775 for (
const Expr *Ref :
C->varlist()) {
12776 if (!Ref->getType()->isScalarType())
12778 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
12781 NeedToCheckForLPCs.insert(DRE->getDecl());
12784 for (
const auto *
C : S.getClausesOfKind<OMPLastprivateClause>()) {
12785 for (
const Expr *Ref :
C->varlist()) {
12786 if (!Ref->getType()->isScalarType())
12788 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
12791 NeedToCheckForLPCs.insert(DRE->getDecl());
12794 for (
const auto *
C : S.getClausesOfKind<OMPReductionClause>()) {
12795 for (
const Expr *Ref :
C->varlist()) {
12796 if (!Ref->getType()->isScalarType())
12798 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
12801 NeedToCheckForLPCs.insert(DRE->getDecl());
12804 for (
const auto *
C : S.getClausesOfKind<OMPLinearClause>()) {
12805 for (
const Expr *Ref :
C->varlist()) {
12806 if (!Ref->getType()->isScalarType())
12808 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
12811 NeedToCheckForLPCs.insert(DRE->getDecl());
12814 for (
const Decl *VD : NeedToCheckForLPCs) {
12816 llvm::reverse(
CGM.getOpenMPRuntime().LastprivateConditionalStack)) {
12817 if (
Data.DeclToUniqueName.count(VD) > 0) {
12818 if (!
Data.Disabled)
12819 NeedToAddForLPCsAsDisabled.insert(VD);
12826CGOpenMPRuntime::LastprivateConditionalRAII::LastprivateConditionalRAII(
12829 Action((CGM.getLangOpts().OpenMP >= 50 &&
12830 llvm::any_of(S.getClausesOfKind<OMPLastprivateClause>(),
12831 [](const OMPLastprivateClause *
C) {
12832 return C->getKind() ==
12833 OMPC_LASTPRIVATE_conditional;
12835 ? ActionToDo::PushAsLastprivateConditional
12836 : ActionToDo::DoNotPush) {
12837 assert(
CGM.getLangOpts().OpenMP &&
"Not in OpenMP mode.");
12838 if (
CGM.getLangOpts().OpenMP < 50 || Action == ActionToDo::DoNotPush)
12840 assert(Action == ActionToDo::PushAsLastprivateConditional &&
12841 "Expected a push action.");
12843 CGM.getOpenMPRuntime().LastprivateConditionalStack.emplace_back();
12844 for (
const auto *
C : S.getClausesOfKind<OMPLastprivateClause>()) {
12845 if (
C->getKind() != OMPC_LASTPRIVATE_conditional)
12848 for (
const Expr *Ref :
C->varlist()) {
12849 Data.DeclToUniqueName.insert(std::make_pair(
12854 Data.IVLVal = IVLVal;
12858CGOpenMPRuntime::LastprivateConditionalRAII::LastprivateConditionalRAII(
12860 :
CGM(CGF.
CGM), Action(ActionToDo::DoNotPush) {
12864 llvm::DenseSet<CanonicalDeclPtr<const Decl>> NeedToAddForLPCsAsDisabled;
12865 tryToDisableInnerAnalysis(S, NeedToAddForLPCsAsDisabled);
12866 if (!NeedToAddForLPCsAsDisabled.empty()) {
12867 Action = ActionToDo::DisableLastprivateConditional;
12868 LastprivateConditionalData &
Data =
12870 for (
const Decl *VD : NeedToAddForLPCsAsDisabled)
12871 Data.DeclToUniqueName.try_emplace(VD);
12873 Data.Disabled =
true;
12877CGOpenMPRuntime::LastprivateConditionalRAII
12880 return LastprivateConditionalRAII(CGF, S);
12884 if (CGM.getLangOpts().OpenMP < 50)
12886 if (Action == ActionToDo::DisableLastprivateConditional) {
12887 assert(CGM.getOpenMPRuntime().LastprivateConditionalStack.back().Disabled &&
12888 "Expected list of disabled private vars.");
12889 CGM.getOpenMPRuntime().LastprivateConditionalStack.pop_back();
12891 if (Action == ActionToDo::PushAsLastprivateConditional) {
12893 !CGM.getOpenMPRuntime().LastprivateConditionalStack.back().Disabled &&
12894 "Expected list of lastprivate conditional vars.");
12895 CGM.getOpenMPRuntime().LastprivateConditionalStack.pop_back();
12907 auto VI = I->getSecond().find(VD);
12908 if (VI == I->getSecond().end()) {
12909 RecordDecl *RD =
C.buildImplicitRecord(
"lasprivate.conditional");
12914 NewType =
C.getCanonicalTagType(RD);
12917 I->getSecond().try_emplace(VD, NewType, VDField, FiredField, BaseLVal);
12919 NewType = std::get<0>(VI->getSecond());
12920 VDField = std::get<1>(VI->getSecond());
12921 FiredField = std::get<2>(VI->getSecond());
12922 BaseLVal = std::get<3>(VI->getSecond());
12934class LastprivateConditionalRefChecker final
12937 const Expr *FoundE =
nullptr;
12938 const Decl *FoundD =
nullptr;
12939 StringRef UniqueDeclName;
12941 llvm::Function *FoundFn =
nullptr;
12947 llvm::reverse(LPM)) {
12948 auto It = D.DeclToUniqueName.find(E->
getDecl());
12949 if (It == D.DeclToUniqueName.end())
12955 UniqueDeclName = It->second;
12960 return FoundE == E;
12966 llvm::reverse(LPM)) {
12968 if (It == D.DeclToUniqueName.end())
12974 UniqueDeclName = It->second;
12979 return FoundE == E;
12981 bool VisitStmt(
const Stmt *S) {
12982 for (
const Stmt *Child : S->
children()) {
12985 if (
const auto *E = dyn_cast<Expr>(Child))
12993 explicit LastprivateConditionalRefChecker(
12994 ArrayRef<CGOpenMPRuntime::LastprivateConditionalData> LPM)
12996 std::tuple<const Expr *, const Decl *, StringRef, LValue, llvm::Function *>
12997 getFoundData()
const {
12998 return std::make_tuple(FoundE, FoundD, UniqueDeclName, IVLVal, FoundFn);
13005 StringRef UniqueDeclName,
13011 llvm::Constant *LastIV =
OMPBuilder.getOrCreateInternalVariable(
13012 LLIVTy,
getName({UniqueDeclName,
"iv"}));
13020 llvm::GlobalVariable *
Last =
OMPBuilder.getOrCreateInternalVariable(
13036 auto &&
CodeGen = [&LastIVLVal, &IVLVal, IVVal, &LVal, &LastLVal,
13042 llvm::Value *CmpRes;
13044 CmpRes = CGF.
Builder.CreateICmpSLE(LastIVVal, IVVal);
13047 "Loop iteration variable must be integer.");
13048 CmpRes = CGF.
Builder.CreateICmpULE(LastIVVal, IVVal);
13052 CGF.
Builder.CreateCondBr(CmpRes, ThenBB, ExitBB);
13073 "Aggregates are not supported in lastprivate conditional.");
13082 if (
CGM.getLangOpts().OpenMPSimd) {
13096 if (!Checker.Visit(LHS))
13098 const Expr *FoundE;
13099 const Decl *FoundD;
13100 StringRef UniqueDeclName;
13102 llvm::Function *FoundFn;
13103 std::tie(FoundE, FoundD, UniqueDeclName, IVLVal, FoundFn) =
13104 Checker.getFoundData();
13105 if (FoundFn != CGF.
CurFn) {
13110 "Lastprivate conditional is not found in outer region.");
13111 QualType StructTy = std::get<0>(It->getSecond());
13112 const FieldDecl* FiredDecl = std::get<2>(It->getSecond());
13123 FiredLVal, llvm::AtomicOrdering::Unordered,
13141 auto It = llvm::find_if(
13143 if (It == Range.end() || It->Fn != CGF.
CurFn)
13147 "Lastprivates must be registered already.");
13150 const CapturedStmt *CS = D.getCapturedStmt(CaptureRegions.back());
13151 for (
const auto &Pair : It->DeclToUniqueName) {
13152 const auto *VD =
cast<VarDecl>(Pair.first->getCanonicalDecl());
13155 auto I = LPCI->getSecond().find(Pair.first);
13156 assert(I != LPCI->getSecond().end() &&
13157 "Lastprivate must be rehistered already.");
13159 LValue BaseLVal = std::get<3>(I->getSecond());
13163 llvm::Value *
Cmp = CGF.
Builder.CreateIsNotNull(Res);
13167 CGF.
Builder.CreateCondBr(
Cmp, ThenBB, DoneBB);
13192 "Unknown lastprivate conditional variable.");
13193 StringRef UniqueName = It->second;
13194 llvm::GlobalVariable *GV =
CGM.getModule().getNamedGlobal(UniqueName);
13208 llvm_unreachable(
"Not supported in SIMD-only mode");
13215 llvm_unreachable(
"Not supported in SIMD-only mode");
13222 bool Tied,
unsigned &NumberOfParts) {
13223 llvm_unreachable(
"Not supported in SIMD-only mode");
13231 llvm_unreachable(
"Not supported in SIMD-only mode");
13237 const Expr *Hint) {
13238 llvm_unreachable(
"Not supported in SIMD-only mode");
13244 llvm_unreachable(
"Not supported in SIMD-only mode");
13250 const Expr *Filter) {
13251 llvm_unreachable(
"Not supported in SIMD-only mode");
13256 llvm_unreachable(
"Not supported in SIMD-only mode");
13262 llvm_unreachable(
"Not supported in SIMD-only mode");
13270 llvm_unreachable(
"Not supported in SIMD-only mode");
13277 llvm_unreachable(
"Not supported in SIMD-only mode");
13284 bool ForceSimpleCall) {
13285 llvm_unreachable(
"Not supported in SIMD-only mode");
13292 llvm_unreachable(
"Not supported in SIMD-only mode");
13297 llvm_unreachable(
"Not supported in SIMD-only mode");
13303 llvm_unreachable(
"Not supported in SIMD-only mode");
13309 llvm_unreachable(
"Not supported in SIMD-only mode");
13316 llvm_unreachable(
"Not supported in SIMD-only mode");
13322 llvm_unreachable(
"Not supported in SIMD-only mode");
13327 unsigned IVSize,
bool IVSigned,
13330 llvm_unreachable(
"Not supported in SIMD-only mode");
13338 llvm_unreachable(
"Not supported in SIMD-only mode");
13342 ProcBindKind ProcBind,
13344 llvm_unreachable(
"Not supported in SIMD-only mode");
13351 llvm_unreachable(
"Not supported in SIMD-only mode");
13357 llvm_unreachable(
"Not supported in SIMD-only mode");
13362 llvm_unreachable(
"Not supported in SIMD-only mode");
13368 llvm::AtomicOrdering AO) {
13369 llvm_unreachable(
"Not supported in SIMD-only mode");
13374 llvm::Function *TaskFunction,
13376 const Expr *IfCond,
13378 llvm_unreachable(
"Not supported in SIMD-only mode");
13385 llvm_unreachable(
"Not supported in SIMD-only mode");
13392 assert(Options.
SimpleReduction &&
"Only simple reduction is expected.");
13394 ReductionOps, Options);
13400 llvm_unreachable(
"Not supported in SIMD-only mode");
13405 bool IsWorksharingReduction) {
13406 llvm_unreachable(
"Not supported in SIMD-only mode");
13413 llvm_unreachable(
"Not supported in SIMD-only mode");
13418 llvm::Value *ReductionsPtr,
13420 llvm_unreachable(
"Not supported in SIMD-only mode");
13426 llvm_unreachable(
"Not supported in SIMD-only mode");
13432 llvm_unreachable(
"Not supported in SIMD-only mode");
13438 llvm_unreachable(
"Not supported in SIMD-only mode");
13443 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
13445 llvm_unreachable(
"Not supported in SIMD-only mode");
13450 llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID,
const Expr *IfCond,
13451 llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier>
Device,
13455 llvm_unreachable(
"Not supported in SIMD-only mode");
13459 llvm_unreachable(
"Not supported in SIMD-only mode");
13463 llvm_unreachable(
"Not supported in SIMD-only mode");
13473 llvm::Function *OutlinedFn,
13475 llvm_unreachable(
"Not supported in SIMD-only mode");
13479 const Expr *NumTeams,
13480 const Expr *ThreadLimit,
13482 llvm_unreachable(
"Not supported in SIMD-only mode");
13489 llvm_unreachable(
"Not supported in SIMD-only mode");
13495 llvm_unreachable(
"Not supported in SIMD-only mode");
13501 llvm_unreachable(
"Not supported in SIMD-only mode");
13506 llvm_unreachable(
"Not supported in SIMD-only mode");
13511 llvm_unreachable(
"Not supported in SIMD-only mode");
13516 const VarDecl *NativeParam)
const {
13517 llvm_unreachable(
"Not supported in SIMD-only mode");
13523 const VarDecl *TargetParam)
const {
13524 llvm_unreachable(
"Not supported in SIMD-only mode");
static llvm::Value * emitCopyprivateCopyFunction(CodeGenModule &CGM, llvm::Type *ArgsElemType, ArrayRef< const Expr * > CopyprivateVars, ArrayRef< const Expr * > DestExprs, ArrayRef< const Expr * > SrcExprs, ArrayRef< const Expr * > AssignmentOps, SourceLocation Loc)
static StringRef getIdentStringFromSourceLocation(CodeGenFunction &CGF, SourceLocation Loc, SmallString< 128 > &Buffer)
static void emitOffloadingArraysAndArgs(CodeGenFunction &CGF, MappableExprsHandler::MapCombinedInfoTy &CombinedInfo, CGOpenMPRuntime::TargetDataInfo &Info, llvm::OpenMPIRBuilder &OMPBuilder, bool IsNonContiguous=false, bool ForEndCall=false)
Emit the arrays used to pass the captures and map information to the offloading runtime library.
static RecordDecl * createKmpTaskTWithPrivatesRecordDecl(CodeGenModule &CGM, QualType KmpTaskTQTy, ArrayRef< PrivateDataTy > Privates)
static void emitInitWithReductionInitializer(CodeGenFunction &CGF, const OMPDeclareReductionDecl *DRD, const Expr *InitOp, Address Private, Address Original, QualType Ty)
static Address castToBase(CodeGenFunction &CGF, QualType BaseTy, QualType ElTy, Address OriginalBaseAddress, llvm::Value *Addr)
static void emitPrivatesInit(CodeGenFunction &CGF, const OMPExecutableDirective &D, Address KmpTaskSharedsPtr, LValue TDBase, const RecordDecl *KmpTaskTWithPrivatesQTyRD, QualType SharedsTy, QualType SharedsPtrTy, const OMPTaskDataTy &Data, ArrayRef< PrivateDataTy > Privates, bool ForDup)
Emit initialization for private variables in task-based directives.
static void emitClauseForBareTargetDirective(CodeGenFunction &CGF, const OMPExecutableDirective &D, llvm::SmallVectorImpl< llvm::Value * > &Values)
static llvm::Value * emitDestructorsFunction(CodeGenModule &CGM, SourceLocation Loc, QualType KmpInt32Ty, QualType KmpTaskTWithPrivatesPtrQTy, QualType KmpTaskTWithPrivatesQTy)
static void EmitOMPAggregateReduction(CodeGenFunction &CGF, QualType Type, const VarDecl *LHSVar, const VarDecl *RHSVar, const llvm::function_ref< void(CodeGenFunction &CGF, const Expr *, const Expr *, const Expr *)> &RedOpGen, const Expr *XExpr=nullptr, const Expr *EExpr=nullptr, const Expr *UpExpr=nullptr)
Emit reduction operation for each element of array (required for array sections) LHS op = RHS.
static void emitTargetCallFallback(CGOpenMPRuntime *OMPRuntime, llvm::Function *OutlinedFn, const OMPExecutableDirective &D, llvm::SmallVectorImpl< llvm::Value * > &CapturedVars, bool RequiresOuterTask, const CapturedStmt &CS, bool OffloadingMandatory, CodeGenFunction &CGF)
static llvm::Value * emitReduceInitFunction(CodeGenModule &CGM, SourceLocation Loc, ReductionCodeGen &RCG, unsigned N)
Emits reduction initializer function:
static RTCancelKind getCancellationKind(OpenMPDirectiveKind CancelRegion)
static void emitDependData(CodeGenFunction &CGF, QualType &KmpDependInfoTy, llvm::PointerUnion< unsigned *, LValue * > Pos, const OMPTaskDataTy::DependData &Data, Address DependenciesArray)
static llvm::Value * emitTaskPrivateMappingFunction(CodeGenModule &CGM, SourceLocation Loc, const OMPTaskDataTy &Data, QualType PrivatesQTy, ArrayRef< PrivateDataTy > Privates)
Emit a privates mapping function for correct handling of private and firstprivate variables.
static llvm::Value * emitReduceCombFunction(CodeGenModule &CGM, SourceLocation Loc, ReductionCodeGen &RCG, unsigned N, const Expr *ReductionOp, const Expr *LHS, const Expr *RHS, const Expr *PrivateRef)
Emits reduction combiner function:
static RecordDecl * createPrivatesRecordDecl(CodeGenModule &CGM, ArrayRef< PrivateDataTy > Privates)
static llvm::Value * getAllocatorVal(CodeGenFunction &CGF, const Expr *Allocator)
Return allocator value from expression, or return a null allocator (default when no allocator specifi...
static llvm::Function * emitProxyTaskFunction(CodeGenModule &CGM, SourceLocation Loc, OpenMPDirectiveKind Kind, QualType KmpInt32Ty, QualType KmpTaskTWithPrivatesPtrQTy, QualType KmpTaskTWithPrivatesQTy, QualType KmpTaskTQTy, QualType SharedsPtrTy, llvm::Function *TaskFunction, llvm::Value *TaskPrivatesMap)
Emit a proxy function which accepts kmp_task_t as the second argument.
static bool isAllocatableDecl(const VarDecl *VD)
static llvm::Value * getAlignmentValue(CodeGenModule &CGM, const VarDecl *VD)
Return the alignment from an allocate directive if present.
static void emitTargetCallKernelLaunch(CGOpenMPRuntime *OMPRuntime, llvm::Function *OutlinedFn, const OMPExecutableDirective &D, llvm::SmallVectorImpl< llvm::Value * > &CapturedVars, bool RequiresOuterTask, const CapturedStmt &CS, bool OffloadingMandatory, llvm::PointerIntPair< const Expr *, 2, OpenMPDeviceClauseModifier > Device, llvm::Value *OutlinedFnID, CodeGenFunction::OMPTargetDataInfo &InputInfo, llvm::Value *&MapTypesArray, llvm::Value *&MapNamesArray, llvm::function_ref< llvm::Value *(CodeGenFunction &CGF, const OMPLoopDirective &D)> SizeEmitter, CodeGenFunction &CGF, CodeGenModule &CGM)
static const OMPExecutableDirective * getNestedDistributeDirective(ASTContext &Ctx, const OMPExecutableDirective &D)
Check for inner distribute directive.
static std::pair< llvm::Value *, llvm::Value * > getPointerAndSize(CodeGenFunction &CGF, const Expr *E)
static const VarDecl * getBaseDecl(const Expr *Ref, const DeclRefExpr *&DE)
static bool getAArch64MTV(QualType QT, llvm::OpenMPIRBuilder::DeclareSimdKindTy Kind)
Maps To Vector (MTV), as defined in 4.1.1 of the AAVFABI (2021Q1).
static bool isTrivial(ASTContext &Ctx, const Expr *E)
Checks if the expression is constant or does not have non-trivial function calls.
static OpenMPSchedType getRuntimeSchedule(OpenMPScheduleClauseKind ScheduleKind, bool Chunked, bool Ordered)
Map the OpenMP loop schedule to the runtime enumeration.
static void getNumThreads(CodeGenFunction &CGF, const CapturedStmt *CS, const Expr **E, int32_t &UpperBound, bool UpperBoundOnly, llvm::Value **CondVal)
Check for a num threads constant value (stored in DefaultVal), or expression (stored in E).
static llvm::Value * emitDeviceID(llvm::PointerIntPair< const Expr *, 2, OpenMPDeviceClauseModifier > Device, CodeGenFunction &CGF)
static const OMPDeclareReductionDecl * getReductionInit(const Expr *ReductionOp)
Check if the combiner is a call to UDR combiner and if it is so return the UDR decl used for reductio...
static bool checkInitIsRequired(CodeGenFunction &CGF, ArrayRef< PrivateDataTy > Privates)
Check if duplication function is required for taskloops.
static bool validateAArch64Simdlen(CodeGenModule &CGM, SourceLocation SLoc, unsigned UserVLEN, unsigned WDS, char ISA)
static bool checkDestructorsRequired(const RecordDecl *KmpTaskTWithPrivatesQTyRD, ArrayRef< PrivateDataTy > Privates)
Checks if destructor function is required to be generated.
static llvm::TargetRegionEntryInfo getEntryInfoFromPresumedLoc(CodeGenModule &CGM, llvm::OpenMPIRBuilder &OMPBuilder, SourceLocation BeginLoc, llvm::StringRef ParentName="")
static void genMapInfo(MappableExprsHandler &MEHandler, CodeGenFunction &CGF, MappableExprsHandler::MapCombinedInfoTy &CombinedInfo, llvm::OpenMPIRBuilder &OMPBuilder, const llvm::DenseSet< CanonicalDeclPtr< const Decl > > &SkippedVarSet=llvm::DenseSet< CanonicalDeclPtr< const Decl > >())
static unsigned getAArch64LS(QualType QT, llvm::OpenMPIRBuilder::DeclareSimdKindTy Kind, ASTContext &C)
Computes the lane size (LS) of a return type or of an input parameter, as defined by LS(P) in 3....
static llvm::OpenMPIRBuilder::DeclareSimdBranch convertDeclareSimdBranch(OMPDeclareSimdDeclAttr::BranchStateTy State)
static void emitForStaticInitCall(CodeGenFunction &CGF, llvm::Value *UpdateLocation, llvm::Value *ThreadId, llvm::FunctionCallee ForStaticInitFunction, OpenMPSchedType Schedule, OpenMPScheduleClauseModifier M1, OpenMPScheduleClauseModifier M2, const CGOpenMPRuntime::StaticRTInput &Values)
static LValue loadToBegin(CodeGenFunction &CGF, QualType BaseTy, QualType ElTy, LValue BaseLV)
static void getKmpAffinityType(ASTContext &C, QualType &KmpTaskAffinityInfoTy)
Builds kmp_depend_info, if it is not built yet, and builds flags type.
static llvm::Constant * emitMappingInformation(CodeGenFunction &CGF, llvm::OpenMPIRBuilder &OMPBuilder, MappableExprsHandler::MappingExprInfo &MapExprs)
Emit a string constant containing the names of the values mapped to the offloading runtime library.
static void getDependTypes(ASTContext &C, QualType &KmpDependInfoTy, QualType &FlagsTy)
Builds kmp_depend_info, if it is not built yet, and builds flags type.
static llvm::Value * emitTaskDupFunction(CodeGenModule &CGM, SourceLocation Loc, const OMPExecutableDirective &D, QualType KmpTaskTWithPrivatesPtrQTy, const RecordDecl *KmpTaskTWithPrivatesQTyRD, const RecordDecl *KmpTaskTQTyRD, QualType SharedsTy, QualType SharedsPtrTy, const OMPTaskDataTy &Data, ArrayRef< PrivateDataTy > Privates, bool WithLastIter)
Emit task_dup function (for initialization of private/firstprivate/lastprivate vars and last_iter fla...
static std::pair< llvm::Value *, OMPDynGroupprivateFallbackType > emitDynCGroupMem(const OMPExecutableDirective &D, CodeGenFunction &CGF)
static llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseKind convertDeviceClause(const VarDecl *VD)
static llvm::Value * emitReduceFiniFunction(CodeGenModule &CGM, SourceLocation Loc, ReductionCodeGen &RCG, unsigned N)
Emits reduction finalizer function:
static void EmitOMPAggregateInit(CodeGenFunction &CGF, Address DestAddr, QualType Type, bool EmitDeclareReductionInit, const Expr *Init, const OMPDeclareReductionDecl *DRD, Address SrcAddr=Address::invalid())
Emit initialization of arrays of complex types.
static bool getAArch64PBV(QualType QT, ASTContext &C)
Pass By Value (PBV), as defined in 3.1.2 of the AAVFABI.
static void EmitDoacrossOrdered(CodeGenFunction &CGF, CodeGenModule &CGM, const T *C, llvm::Value *ULoc, llvm::Value *ThreadID)
static RTLDependenceKindTy translateDependencyKind(OpenMPDependClauseKind K)
Translates internal dependency kind into the runtime kind.
static void emitTargetCallElse(CGOpenMPRuntime *OMPRuntime, llvm::Function *OutlinedFn, const OMPExecutableDirective &D, llvm::SmallVectorImpl< llvm::Value * > &CapturedVars, bool RequiresOuterTask, const CapturedStmt &CS, bool OffloadingMandatory, CodeGenFunction &CGF)
static llvm::Function * emitCombinerOrInitializer(CodeGenModule &CGM, QualType Ty, const Expr *CombinerInitializer, const VarDecl *In, const VarDecl *Out, bool IsCombiner)
static void emitReductionCombiner(CodeGenFunction &CGF, const Expr *ReductionOp)
Emit reduction combiner.
static std::tuple< unsigned, unsigned, bool > getNDSWDS(const FunctionDecl *FD, ArrayRef< llvm::OpenMPIRBuilder::DeclareSimdAttrTy > ParamAttrs)
static std::string generateUniqueName(CodeGenModule &CGM, llvm::StringRef Prefix, const Expr *Ref)
static llvm::Function * emitParallelOrTeamsOutlinedFunction(CodeGenModule &CGM, const OMPExecutableDirective &D, const CapturedStmt *CS, const VarDecl *ThreadIDVar, OpenMPDirectiveKind InnermostKind, const StringRef OutlinedHelperName, const RegionCodeGenTy &CodeGen)
static Address emitAddrOfVarFromArray(CodeGenFunction &CGF, Address Array, unsigned Index, const VarDecl *Var)
Given an array of pointers to variables, project the address of a given variable.
static void mergeThreadCountUpperBound(int32_t &UpperBound, int32_t Val)
Merge the thread count upper bound Val into UpperBound.
static FieldDecl * addFieldToRecordDecl(ASTContext &C, DeclContext *DC, QualType FieldTy)
static unsigned evaluateCDTSize(const FunctionDecl *FD, ArrayRef< llvm::OpenMPIRBuilder::DeclareSimdAttrTy > ParamAttrs)
static ValueDecl * getDeclFromThisExpr(const Expr *E)
static void genMapInfoForCaptures(MappableExprsHandler &MEHandler, CodeGenFunction &CGF, const CapturedStmt &CS, llvm::SmallVectorImpl< llvm::Value * > &CapturedVars, llvm::OpenMPIRBuilder &OMPBuilder, llvm::DenseSet< CanonicalDeclPtr< const Decl > > &MappedVarSet, MappableExprsHandler::MapCombinedInfoTy &CombinedInfo)
static RecordDecl * createKmpTaskTRecordDecl(CodeGenModule &CGM, OpenMPDirectiveKind Kind, QualType KmpInt32Ty, QualType KmpRoutineEntryPointerQTy)
static int addMonoNonMonoModifier(CodeGenModule &CGM, OpenMPSchedType Schedule, OpenMPScheduleClauseModifier M1, OpenMPScheduleClauseModifier M2)
static mlir::omp::DeclareTargetCaptureClause convertCaptureClause(OMPDeclareTargetDeclAttr::MapTypeTy mapTy)
static bool isAssumedToBeNotEmitted(const ValueDecl *vd, bool isDevice)
Returns true if the declaration should be skipped based on its device_type attribute and the current ...
@ LLVM_MARK_AS_BITMASK_ENUM
Result
Implement __builtin_bit_cast and related operations.
This file defines OpenMP AST classes for clauses.
Defines some OpenMP-specific enums and functions.
Defines the SourceManager interface.
This file defines OpenMP AST classes for executable directives and clauses.
__DEVICE__ int max(int __a, int __b)
This represents clause 'affinity' in the 'pragma omp task'-based directives.
ValueDecl * getAssociatedDeclaration() const
Expr * getAssociatedExpression() const
static std::pair< const Expr *, std::optional< size_t > > findAttachPtrExpr(MappableExprComponentListRef Components, OpenMPDirectiveKind CurDirKind)
Find the attach pointer expression from a list of mappable expression components.
static QualType getComponentExprElementType(const Expr *Exp)
Get the type of an element of a ComponentList Expr Exp.
ArrayRef< MappableComponent > MappableExprComponentListRef
This represents implicit clause 'depend' for the 'pragma omp task' directive.
This represents 'detach' clause in the 'pragma omp task' directive.
This represents 'device' clause in the 'pragma omp ...' directive.
This represents the 'doacross' clause for the 'pragma omp ordered' directive.
This represents 'dyn_groupprivate' clause in 'pragma omp target ...' and 'pragma omp teams ....
This is a common base class for loop directives ('omp simd', 'omp for', 'omp for simd' etc....
Expr * getLowerBoundVariable() const
Expr * getUpperBoundVariable() const
Expr * getStrideVariable() const
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)
void emitUpdateDependObjectsClause(CodeGenFunction &CGF, LValue DepobjLVal, OpenMPDependClauseKind NewDepKind, SourceLocation Loc)
Updates the dependency kind in the specified depobj object.
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.
virtual void emitLastprivateConditionalFinalUpdate(CodeGenFunction &CGF, LValue PrivLVal, const VarDecl *VD, SourceLocation Loc)
Gets the address of the global copy used for lastprivate conditional update, if any.
llvm::MapVector< CanonicalDeclPtr< const VarDecl >, std::pair< Address, Address > > UntiedLocalVarsAddressesMap
virtual void emitErrorCall(CodeGenFunction &CGF, SourceLocation Loc, Expr *ME, bool IsFatal)
Emit __kmpc_error call for error directive extern void __kmpc_error(ident_t *loc, int severity,...
void clearLocThreadIdInsertPt(CodeGenFunction &CGF)
virtual void emitTaskyieldCall(CodeGenFunction &CGF, SourceLocation Loc)
Emits code for a taskyield directive.
std::string getName(ArrayRef< StringRef > Parts) const
Get the platform-specific name separator.
QualType KmpRoutineEntryPtrQTy
void computeMinAndMaxThreadsAndTeams(const OMPExecutableDirective &D, CodeGenFunction &CGF, llvm::OpenMPIRBuilder::TargetKernelDefaultAttrs &Attrs)
Helper to determine the min/max number of threads/teams for D.
virtual void emitFlush(CodeGenFunction &CGF, ArrayRef< const Expr * > Vars, SourceLocation Loc, llvm::AtomicOrdering AO)
Emit flush of the variables specified in 'omp flush' directive.
virtual void emitTaskwaitCall(CodeGenFunction &CGF, SourceLocation Loc, const OMPTaskDataTy &Data)
Emit code for 'taskwait' directive.
virtual void emitProcBindClause(CodeGenFunction &CGF, llvm::omp::ProcBindKind ProcBind, SourceLocation Loc)
Emit call to void __kmpc_push_proc_bind(ident_t *loc, kmp_int32global_tid, int proc_bind) to generate...
void emitLastprivateConditionalUpdate(CodeGenFunction &CGF, LValue IVLVal, StringRef UniqueDeclName, LValue LVal, SourceLocation Loc)
Emit update for lastprivate conditional data.
virtual void emitTaskLoopCall(CodeGenFunction &CGF, SourceLocation Loc, const OMPLoopDirective &D, llvm::Function *TaskFunction, QualType SharedsTy, Address Shareds, const Expr *IfCond, const OMPTaskDataTy &Data)
Emit task region for the taskloop directive.
virtual void emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind Kind, bool EmitChecks=true, bool ForceSimpleCall=false)
Emit an implicit/explicit barrier for OpenMP threads.
static unsigned getDefaultFlagsForBarriers(OpenMPDirectiveKind Kind)
Returns default flags for the barriers depending on the directive, for which this barier is going to ...
virtual bool emitTargetFunctions(GlobalDecl GD)
Emit the target regions enclosed in GD function definition or the function itself in case it is a val...
TaskResultTy emitTaskInit(CodeGenFunction &CGF, SourceLocation Loc, const OMPExecutableDirective &D, llvm::Function *TaskFunction, QualType SharedsTy, Address Shareds, const OMPTaskDataTy &Data)
Emit task region for the task directive.
llvm::Value * emitTargetNumIterationsCall(CodeGenFunction &CGF, const OMPExecutableDirective &D, llvm::function_ref< llvm::Value *(CodeGenFunction &CGF, const OMPLoopDirective &D)> SizeEmitter)
Return the trip count of loops associated with constructs / 'target teams distribute' and 'teams dist...
llvm::StringMap< llvm::AssertingVH< llvm::GlobalVariable >, llvm::BumpPtrAllocator > InternalVars
An ordered map of auto-generated variables to their unique names.
virtual void emitDistributeStaticInit(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDistScheduleClauseKind SchedKind, const StaticRTInput &Values)
llvm::SmallVector< UntiedLocalVarsAddressesMap, 4 > UntiedLocalVarsStack
virtual void emitForStaticFinish(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind DKind)
Call the appropriate runtime routine to notify that we finished all the work with current loop.
virtual void emitThreadLimitClause(CodeGenFunction &CGF, const Expr *ThreadLimit, SourceLocation Loc)
Emits call to void __kmpc_set_thread_limit(ident_t *loc, kmp_int32global_tid, kmp_int32 thread_limit)...
void emitIfClause(CodeGenFunction &CGF, const Expr *Cond, const RegionCodeGenTy &ThenGen, const RegionCodeGenTy &ElseGen)
Emits code for OpenMP 'if' clause using specified CodeGen function.
Address emitDepobjDependClause(CodeGenFunction &CGF, const OMPTaskDataTy::DependData &Dependencies, SourceLocation Loc)
Emits list of dependecies based on the provided data (array of dependence/expression pairs) for depob...
bool isNontemporalDecl(const ValueDecl *VD) const
Checks if the VD variable is marked as nontemporal declaration in current context.
virtual llvm::Function * emitParallelOutlinedFunction(CodeGenFunction &CGF, const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen)
Emits outlined function for the specified OpenMP parallel directive D.
const Expr * getNumThreadsExprForTargetDirective(CodeGenFunction &CGF, const OMPExecutableDirective &D, int32_t &UpperBound, bool UpperBoundOnly, llvm::Value **CondExpr=nullptr, const Expr **ThreadLimitExpr=nullptr)
Check for a number of threads upper bound constant value (stored in UpperBound), or expression (retur...
virtual void registerVTableOffloadEntry(llvm::GlobalVariable *VTable, const VarDecl *VD)
Register VTable to OpenMP offload entry.
virtual llvm::Value * emitSeverityClause(OpenMPSeverityClauseKind Severity, SourceLocation Loc)
llvm::SmallVector< LastprivateConditionalData, 4 > LastprivateConditionalStack
Stack for list of addresses of declarations in current context marked as lastprivate conditional.
virtual void emitForStaticInit(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind DKind, const OpenMPScheduleTy &ScheduleKind, const StaticRTInput &Values)
Call the appropriate runtime routine to initialize it before start of loop.
virtual void emitDeclareSimdFunction(const FunctionDecl *FD, llvm::Function *Fn)
Marks function Fn with properly mangled versions of vector functions.
llvm::AtomicOrdering getDefaultMemoryOrdering() const
Gets default memory ordering as specified in requires directive.
virtual bool isStaticNonchunked(OpenMPScheduleClauseKind ScheduleKind, bool Chunked) const
Check if the specified ScheduleKind is static non-chunked.
virtual void emitAndRegisterVTable(CodeGenModule &CGM, CXXRecordDecl *CXXRecord, const VarDecl *VD)
Emit and register VTable for the C++ class in OpenMP offload entry.
llvm::Value * getCriticalRegionLock(StringRef CriticalName)
Returns corresponding lock object for the specified critical region name.
virtual void emitCancelCall(CodeGenFunction &CGF, SourceLocation Loc, const Expr *IfCond, OpenMPDirectiveKind CancelRegion)
Emit code for 'cancel' construct.
QualType SavedKmpTaskTQTy
Saved kmp_task_t for task directive.
virtual void emitMasterRegion(CodeGenFunction &CGF, const RegionCodeGenTy &MasterOpGen, SourceLocation Loc)
Emits a master region.
virtual llvm::Function * emitTaskOutlinedFunction(const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, const VarDecl *PartIDVar, const VarDecl *TaskTVar, OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen, bool Tied, unsigned &NumberOfParts)
Emits outlined function for the OpenMP task directive D.
llvm::DenseMap< llvm::Function *, unsigned > FunctionToUntiedTaskStackMap
Maps function to the position of the untied task locals stack.
void emitDestroyClause(CodeGenFunction &CGF, LValue DepobjLVal, SourceLocation Loc)
Emits the code to destroy the dependency object provided in depobj directive.
virtual void emitTaskReductionFixups(CodeGenFunction &CGF, SourceLocation Loc, ReductionCodeGen &RCG, unsigned N)
Required to resolve existing problems in the runtime.
llvm::ArrayType * KmpCriticalNameTy
Type kmp_critical_name, originally defined as typedef kmp_int32 kmp_critical_name[8];.
virtual void emitDoacrossOrdered(CodeGenFunction &CGF, const OMPDependClause *C)
Emit code for doacross ordered directive with 'depend' clause.
llvm::DenseMap< const OMPDeclareMapperDecl *, llvm::Function * > UDMMap
Map from the user-defined mapper declaration to its corresponding functions.
virtual void checkAndEmitLastprivateConditional(CodeGenFunction &CGF, const Expr *LHS)
Checks if the provided LVal is lastprivate conditional and emits the code to update the value of the ...
std::pair< llvm::Value *, LValue > getDepobjElements(CodeGenFunction &CGF, LValue DepobjLVal, SourceLocation Loc)
Returns the number of the elements and the address of the depobj dependency array.
llvm::SmallDenseSet< const VarDecl * > DeferredGlobalVariables
List of variables that can become declare target implicitly and, thus, must be emitted.
void emitUsesAllocatorsInit(CodeGenFunction &CGF, const Expr *Allocator, const Expr *AllocatorTraits)
Initializes user defined allocators specified in the uses_allocators clauses.
virtual void registerVTable(const OMPExecutableDirective &D)
Emit code for registering vtable by scanning through map clause in OpenMP target region.
llvm::Type * KmpRoutineEntryPtrTy
Type typedef kmp_int32 (* kmp_routine_entry_t)(kmp_int32, void *);.
llvm::Type * getIdentTyPointerTy()
Returns pointer to ident_t type.
void emitSingleReductionCombiner(CodeGenFunction &CGF, const Expr *ReductionOp, const Expr *PrivateRef, const DeclRefExpr *LHS, const DeclRefExpr *RHS)
Emits single reduction combiner.
llvm::OpenMPIRBuilder & getOMPBuilder()
virtual void emitTargetOutlinedFunction(const OMPExecutableDirective &D, StringRef ParentName, llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID, bool IsOffloadEntry, const RegionCodeGenTy &CodeGen)
Emit outilined function for 'target' directive.
virtual void emitCriticalRegion(CodeGenFunction &CGF, StringRef CriticalName, const RegionCodeGenTy &CriticalOpGen, SourceLocation Loc, const Expr *Hint=nullptr)
Emits a critical region.
virtual void emitForOrderedIterationEnd(CodeGenFunction &CGF, SourceLocation Loc, unsigned IVSize, bool IVSigned)
Call the appropriate runtime routine to notify that we finished iteration of the ordered loop with th...
virtual void emitOutlinedFunctionCall(CodeGenFunction &CGF, SourceLocation Loc, llvm::FunctionCallee OutlinedFn, ArrayRef< llvm::Value * > Args={}) const
Emits call of the outlined function with the provided arguments, translating these arguments to corre...
llvm::Value * emitNumThreadsForTargetDirective(CodeGenFunction &CGF, const OMPExecutableDirective &D)
Emit an expression that denotes the number of threads a target region shall use.
void emitThreadPrivateVarInit(CodeGenFunction &CGF, Address VDAddr, llvm::Value *Ctor, llvm::Value *CopyCtor, llvm::Value *Dtor, SourceLocation Loc)
Emits initialization code for the threadprivate variables.
virtual void emitUserDefinedReduction(CodeGenFunction *CGF, const OMPDeclareReductionDecl *D)
Emit code for the specified user defined reduction construct.
virtual void checkAndEmitSharedLastprivateConditional(CodeGenFunction &CGF, const OMPExecutableDirective &D, const llvm::DenseSet< CanonicalDeclPtr< const VarDecl > > &IgnoredDecls)
Checks if the lastprivate conditional was updated in inner region and writes the value.
QualType KmpDimTy
struct kmp_dim { // loop bounds info casted to kmp_int64 kmp_int64 lo; // lower kmp_int64 up; // uppe...
virtual void emitInlinedDirective(CodeGenFunction &CGF, OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen, bool HasCancel=false)
Emit code for the directive that does not require outlining.
virtual void registerTargetGlobalVariable(const VarDecl *VD, llvm::Constant *Addr)
Checks if the provided global decl GD is a declare target variable and registers it when emitting cod...
virtual void emitFunctionProlog(CodeGenFunction &CGF, const Decl *D)
Emits OpenMP-specific function prolog.
void emitKmpRoutineEntryT(QualType KmpInt32Ty)
Build type kmp_routine_entry_t (if not built yet).
virtual bool isStaticChunked(OpenMPScheduleClauseKind ScheduleKind, bool Chunked) const
Check if the specified ScheduleKind is static chunked.
virtual void emitTargetCall(CodeGenFunction &CGF, const OMPExecutableDirective &D, llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID, const Expr *IfCond, llvm::PointerIntPair< const Expr *, 2, OpenMPDeviceClauseModifier > Device, llvm::function_ref< llvm::Value *(CodeGenFunction &CGF, const OMPLoopDirective &D)> SizeEmitter)
Emit the target offloading code associated with D.
virtual bool hasAllocateAttributeForGlobalVar(const VarDecl *VD, LangAS &AS)
Checks if the variable has associated OMPAllocateDeclAttr attribute with the predefined allocator and...
llvm::AtomicOrdering RequiresAtomicOrdering
Atomic ordering from the omp requires directive.
virtual void emitReduction(CodeGenFunction &CGF, SourceLocation Loc, ArrayRef< const Expr * > Privates, ArrayRef< const Expr * > LHSExprs, ArrayRef< const Expr * > RHSExprs, ArrayRef< const Expr * > ReductionOps, ReductionOptionsTy Options)
Emit a code for reduction clause.
std::pair< llvm::Value *, Address > emitDependClause(CodeGenFunction &CGF, ArrayRef< OMPTaskDataTy::DependData > Dependencies, SourceLocation Loc)
Emits list of dependecies based on the provided data (array of dependence/expression pairs).
llvm::StringMap< llvm::WeakTrackingVH > EmittedNonTargetVariables
List of the global variables with their addresses that should not be emitted for the target.
virtual bool isDynamic(OpenMPScheduleClauseKind ScheduleKind) const
Check if the specified ScheduleKind is dynamic.
Address emitLastprivateConditionalInit(CodeGenFunction &CGF, const VarDecl *VD)
Create specialized alloca to handle lastprivate conditionals.
virtual void emitOrderedRegion(CodeGenFunction &CGF, const RegionCodeGenTy &OrderedOpGen, SourceLocation Loc, bool IsThreads)
Emit an ordered region.
virtual Address getAddressOfLocalVariable(CodeGenFunction &CGF, const VarDecl *VD)
Gets the OpenMP-specific address of the local variable.
virtual void emitTaskReductionFini(CodeGenFunction &CGF, SourceLocation Loc, bool IsWorksharingReduction)
Emits the following code for reduction clause with task modifier:
virtual void emitMaskedRegion(CodeGenFunction &CGF, const RegionCodeGenTy &MaskedOpGen, SourceLocation Loc, const Expr *Filter=nullptr)
Emits a masked region.
QualType KmpDependInfoTy
Type typedef struct kmp_depend_info { kmp_intptr_t base_addr; size_t len; struct { bool in:1; bool ou...
llvm::Function * emitReductionFunction(StringRef ReducerName, SourceLocation Loc, llvm::Type *ArgsElemType, ArrayRef< const Expr * > Privates, ArrayRef< const Expr * > LHSExprs, ArrayRef< const Expr * > RHSExprs, ArrayRef< const Expr * > ReductionOps)
Emits reduction function.
virtual void emitForDispatchInit(CodeGenFunction &CGF, SourceLocation Loc, const OpenMPScheduleTy &ScheduleKind, unsigned IVSize, bool IVSigned, bool Ordered, const DispatchRTInput &DispatchValues)
Call the appropriate runtime routine to initialize it before start of loop.
Address getTaskReductionItem(CodeGenFunction &CGF, SourceLocation Loc, llvm::Value *ReductionsPtr, LValue SharedLVal) override
Get the address of void * type of the privatue copy of the reduction item specified by the SharedLVal...
void emitCriticalRegion(CodeGenFunction &CGF, StringRef CriticalName, const RegionCodeGenTy &CriticalOpGen, SourceLocation Loc, const Expr *Hint=nullptr) override
Emits a critical region.
void emitDistributeStaticInit(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDistScheduleClauseKind SchedKind, const StaticRTInput &Values) override
void emitForStaticInit(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind DKind, const OpenMPScheduleTy &ScheduleKind, const StaticRTInput &Values) override
Call the appropriate runtime routine to initialize it before start of loop.
bool emitTargetGlobalVariable(GlobalDecl GD) override
Emit the global variable if it is a valid device global variable.
llvm::Value * emitForNext(CodeGenFunction &CGF, SourceLocation Loc, unsigned IVSize, bool IVSigned, Address IL, Address LB, Address UB, Address ST) override
Call __kmpc_dispatch_next( ident_t *loc, kmp_int32 tid, kmp_int32 *p_lastiter, kmp_int[32|64] *p_lowe...
llvm::Function * emitThreadPrivateVarDefinition(const VarDecl *VD, Address VDAddr, SourceLocation Loc, bool PerformInit, CodeGenFunction *CGF=nullptr) override
Emit a code for initialization of threadprivate variable.
void emitTargetDataStandAloneCall(CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, const Expr *Device) override
Emit the data mapping/movement code associated with the directive D that should be of the form 'targe...
llvm::Function * emitTeamsOutlinedFunction(CodeGenFunction &CGF, const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) override
Emits outlined function for the specified OpenMP teams directive D.
void emitParallelCall(CodeGenFunction &CGF, SourceLocation Loc, llvm::Function *OutlinedFn, ArrayRef< llvm::Value * > CapturedVars, const Expr *IfCond, llvm::Value *NumThreads, OpenMPNumThreadsClauseModifier NumThreadsModifier=OMPC_NUMTHREADS_unknown, OpenMPSeverityClauseKind Severity=OMPC_SEVERITY_fatal, const Expr *Message=nullptr) override
Emits code for parallel or serial call of the OutlinedFn with variables captured in a record which ad...
void emitReduction(CodeGenFunction &CGF, SourceLocation Loc, ArrayRef< const Expr * > Privates, ArrayRef< const Expr * > LHSExprs, ArrayRef< const Expr * > RHSExprs, ArrayRef< const Expr * > ReductionOps, ReductionOptionsTy Options) override
Emit a code for reduction clause.
void emitFlush(CodeGenFunction &CGF, ArrayRef< const Expr * > Vars, SourceLocation Loc, llvm::AtomicOrdering AO) override
Emit flush of the variables specified in 'omp flush' directive.
void emitDoacrossOrdered(CodeGenFunction &CGF, const OMPDependClause *C) override
Emit code for doacross ordered directive with 'depend' clause.
void emitTaskyieldCall(CodeGenFunction &CGF, SourceLocation Loc) override
Emits a masked region.
Address getAddrOfArtificialThreadPrivate(CodeGenFunction &CGF, QualType VarType, StringRef Name) override
Creates artificial threadprivate variable with name Name and type VarType.
Address getAddrOfThreadPrivate(CodeGenFunction &CGF, const VarDecl *VD, Address VDAddr, SourceLocation Loc) override
Returns address of the threadprivate variable for the current thread.
void emitSingleRegion(CodeGenFunction &CGF, const RegionCodeGenTy &SingleOpGen, SourceLocation Loc, ArrayRef< const Expr * > CopyprivateVars, ArrayRef< const Expr * > DestExprs, ArrayRef< const Expr * > SrcExprs, ArrayRef< const Expr * > AssignmentOps) override
Emits a single region.
void emitTaskReductionFixups(CodeGenFunction &CGF, SourceLocation Loc, ReductionCodeGen &RCG, unsigned N) override
Required to resolve existing problems in the runtime.
llvm::Function * emitParallelOutlinedFunction(CodeGenFunction &CGF, const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) override
Emits outlined function for the specified OpenMP parallel directive D.
void emitCancellationPointCall(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind CancelRegion) override
Emit code for 'cancellation point' construct.
void emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind Kind, bool EmitChecks=true, bool ForceSimpleCall=false) override
Emit an implicit/explicit barrier for OpenMP threads.
Address getParameterAddress(CodeGenFunction &CGF, const VarDecl *NativeParam, const VarDecl *TargetParam) const override
Gets the address of the native argument basing on the address of the target-specific parameter.
void emitTeamsCall(CodeGenFunction &CGF, const OMPExecutableDirective &D, SourceLocation Loc, llvm::Function *OutlinedFn, ArrayRef< llvm::Value * > CapturedVars) override
Emits code for teams call of the OutlinedFn with variables captured in a record which address is stor...
void emitForOrderedIterationEnd(CodeGenFunction &CGF, SourceLocation Loc, unsigned IVSize, bool IVSigned) override
Call the appropriate runtime routine to notify that we finished iteration of the ordered loop with th...
bool emitTargetGlobal(GlobalDecl GD) override
Emit the global GD if it is meaningful for the target.
void emitTaskReductionFini(CodeGenFunction &CGF, SourceLocation Loc, bool IsWorksharingReduction) override
Emits the following code for reduction clause with task modifier:
void emitOrderedRegion(CodeGenFunction &CGF, const RegionCodeGenTy &OrderedOpGen, SourceLocation Loc, bool IsThreads) override
Emit an ordered region.
void emitForStaticFinish(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind DKind) override
Call the appropriate runtime routine to notify that we finished all the work with current loop.
llvm::Value * emitTaskReductionInit(CodeGenFunction &CGF, SourceLocation Loc, ArrayRef< const Expr * > LHSExprs, ArrayRef< const Expr * > RHSExprs, const OMPTaskDataTy &Data) override
Emit a code for initialization of task reduction clause.
void emitProcBindClause(CodeGenFunction &CGF, llvm::omp::ProcBindKind ProcBind, SourceLocation Loc) override
Emit call to void __kmpc_push_proc_bind(ident_t *loc, kmp_int32global_tid, int proc_bind) to generate...
void emitTargetOutlinedFunction(const OMPExecutableDirective &D, StringRef ParentName, llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID, bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) override
Emit outilined function for 'target' directive.
void emitMasterRegion(CodeGenFunction &CGF, const RegionCodeGenTy &MasterOpGen, SourceLocation Loc) override
Emits a master region.
void emitNumTeamsClause(CodeGenFunction &CGF, const Expr *NumTeams, const Expr *ThreadLimit, SourceLocation Loc) override
Emits call to void __kmpc_push_num_teams(ident_t *loc, kmp_int32global_tid, kmp_int32 num_teams,...
void emitForDispatchDeinit(CodeGenFunction &CGF, SourceLocation Loc) override
This is used for non static scheduled types and when the ordered clause is present on the loop constr...
const VarDecl * translateParameter(const FieldDecl *FD, const VarDecl *NativeParam) const override
Translates the native parameter of outlined function if this is required for target.
void emitNumThreadsClause(CodeGenFunction &CGF, llvm::Value *NumThreads, SourceLocation Loc, OpenMPNumThreadsClauseModifier Modifier=OMPC_NUMTHREADS_unknown, OpenMPSeverityClauseKind Severity=OMPC_SEVERITY_fatal, SourceLocation SeverityLoc=SourceLocation(), const Expr *Message=nullptr, SourceLocation MessageLoc=SourceLocation()) override
Emits call to void __kmpc_push_num_threads(ident_t *loc, kmp_int32global_tid, kmp_int32 num_threads) ...
void emitMaskedRegion(CodeGenFunction &CGF, const RegionCodeGenTy &MaskedOpGen, SourceLocation Loc, const Expr *Filter=nullptr) override
Emits a masked region.
void emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc, const OMPExecutableDirective &D, llvm::Function *TaskFunction, QualType SharedsTy, Address Shareds, const Expr *IfCond, const OMPTaskDataTy &Data) override
Emit task region for the task directive.
void emitTargetCall(CodeGenFunction &CGF, const OMPExecutableDirective &D, llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID, const Expr *IfCond, llvm::PointerIntPair< const Expr *, 2, OpenMPDeviceClauseModifier > Device, llvm::function_ref< llvm::Value *(CodeGenFunction &CGF, const OMPLoopDirective &D)> SizeEmitter) override
Emit the target offloading code associated with D.
bool emitTargetFunctions(GlobalDecl GD) override
Emit the target regions enclosed in GD function definition or the function itself in case it is a val...
void emitDoacrossInit(CodeGenFunction &CGF, const OMPLoopDirective &D, ArrayRef< Expr * > NumIterations) override
Emit initialization for doacross loop nesting support.
void emitCancelCall(CodeGenFunction &CGF, SourceLocation Loc, const Expr *IfCond, OpenMPDirectiveKind CancelRegion) override
Emit code for 'cancel' construct.
void emitTaskwaitCall(CodeGenFunction &CGF, SourceLocation Loc, const OMPTaskDataTy &Data) override
Emit code for 'taskwait' directive.
void emitTaskgroupRegion(CodeGenFunction &CGF, const RegionCodeGenTy &TaskgroupOpGen, SourceLocation Loc) override
Emit a taskgroup region.
void emitTargetDataCalls(CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, const Expr *Device, const RegionCodeGenTy &CodeGen, CGOpenMPRuntime::TargetDataInfo &Info) override
Emit the target data mapping code associated with D.
void emitForDispatchInit(CodeGenFunction &CGF, SourceLocation Loc, const OpenMPScheduleTy &ScheduleKind, unsigned IVSize, bool IVSigned, bool Ordered, const DispatchRTInput &DispatchValues) override
This is used for non static scheduled types and when the ordered clause is present on the loop constr...
llvm::Function * emitTaskOutlinedFunction(const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, const VarDecl *PartIDVar, const VarDecl *TaskTVar, OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen, bool Tied, unsigned &NumberOfParts) override
Emits outlined function for the OpenMP task directive D.
void emitTaskLoopCall(CodeGenFunction &CGF, SourceLocation Loc, const OMPLoopDirective &D, llvm::Function *TaskFunction, QualType SharedsTy, Address Shareds, const Expr *IfCond, const OMPTaskDataTy &Data) override
Emit task region for the taskloop directive.
unsigned getNonVirtualBaseLLVMFieldNo(const CXXRecordDecl *RD) const
llvm::StructType * getLLVMType() const
Return the "complete object" LLVM type associated with this record.
llvm::StructType * getBaseSubobjectLLVMType() const
Return the "base subobject" LLVM type associated with this record.
unsigned getLLVMFieldNo(const FieldDecl *FD) const
Return llvm::StructType element number that corresponds to the field FD.
unsigned getVirtualBaseIndex(const CXXRecordDecl *base) const
Return the LLVM field index corresponding to the given virtual base.
API for captured statement code generation.
virtual void EmitBody(CodeGenFunction &CGF, const Stmt *S)
Emit the captured statement body.
virtual const FieldDecl * lookup(const VarDecl *VD) const
Lookup the captured field decl for a variable.
RAII for correct setting/restoring of CapturedStmtInfo.
The scope used to remap some variables as private in the OpenMP loop body (or other captured region e...
bool Privatize()
Privatizes local variables previously registered as private.
bool addPrivate(const VarDecl *LocalVD, Address Addr)
Registers LocalVD variable as a private with Addr as the address of the corresponding private variabl...
An RAII object to set (and then clear) a mapping for an OpaqueValueExpr.
Enters a new scope for capturing cleanups, all of which will be executed once the scope is exited.
CodeGenFunction - This class organizes the per-function state that is used while generating LLVM code...
LValue EmitLoadOfReferenceLValue(LValue RefLVal)
void EmitBranchOnBoolExpr(const Expr *Cond, llvm::BasicBlock *TrueBlock, llvm::BasicBlock *FalseBlock, uint64_t TrueCount, Stmt::Likelihood LH=Stmt::LH_None, const Expr *ConditionalOp=nullptr, const VarDecl *ConditionalDecl=nullptr)
EmitBranchOnBoolExpr - Emit a branch on a boolean condition (e.g.
void emitDestroy(Address addr, QualType type, Destroyer *destroyer, bool useEHCleanupForArray)
emitDestroy - Immediately perform the destruction of the given object.
JumpDest getJumpDestInCurrentScope(llvm::BasicBlock *Target)
The given basic block lies in the current EH scope, but may be a target of a potentially scope-crossi...
static void EmitOMPTargetParallelDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetParallelDirective &S)
void EmitNullInitialization(Address DestPtr, QualType Ty)
EmitNullInitialization - Generate code to set a value of the given type to null, If the type contains...
Address LoadCXXThisAddress()
CGCapturedStmtInfo * CapturedStmtInfo
ComplexPairTy EmitLoadOfComplex(LValue src, SourceLocation loc)
EmitLoadOfComplex - Load a complex number from the specified l-value.
static void EmitOMPTargetDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetDirective &S)
Emit device code for the target directive.
static void EmitOMPTargetTeamsDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsDirective &S)
Emit device code for the target teams directive.
static void EmitOMPTargetTeamsDistributeDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsDistributeDirective &S)
Emit device code for the target teams distribute directive.
llvm::Function * GenerateOpenMPCapturedStmtFunctionAggregate(const CapturedStmt &S, const OMPExecutableDirective &D)
llvm::BasicBlock * createBasicBlock(const Twine &name="", llvm::Function *parent=nullptr, llvm::BasicBlock *before=nullptr)
createBasicBlock - Create an LLVM basic block.
const LangOptions & getLangOpts() const
AutoVarEmission EmitAutoVarAlloca(const VarDecl &var)
EmitAutoVarAlloca - Emit the alloca and debug information for a local variable.
void pushDestroy(QualType::DestructionKind dtorKind, Address addr, QualType type)
pushDestroy - Push the standard destructor for the given type as at least a normal cleanup.
Address EmitLoadOfPointer(Address Ptr, const PointerType *PtrTy, LValueBaseInfo *BaseInfo=nullptr, TBAAAccessInfo *TBAAInfo=nullptr)
Load a pointer with type PtrTy stored at address Ptr.
void EmitBranchThroughCleanup(JumpDest Dest)
EmitBranchThroughCleanup - Emit a branch from the current insert block through the normal cleanup han...
const Decl * CurCodeDecl
CurCodeDecl - This is the inner-most code context, which includes blocks.
Destroyer * getDestroyer(QualType::DestructionKind destructionKind)
llvm::AssertingVH< llvm::Instruction > AllocaInsertPt
AllocaInsertPoint - This is an instruction in the entry block before which we prefer to insert alloca...
void EmitAggregateAssign(LValue Dest, LValue Src, QualType EltTy)
Emit an aggregate assignment.
JumpDest ReturnBlock
ReturnBlock - Unified return block.
void EmitAggregateCopy(LValue Dest, LValue Src, QualType EltTy, AggValueSlot::Overlap_t MayOverlap, bool isVolatile=false)
EmitAggregateCopy - Emit an aggregate copy.
LValue EmitLValueForField(LValue Base, const FieldDecl *Field, bool IsInBounds=true)
RawAddress CreateDefaultAlignTempAlloca(llvm::Type *Ty, const Twine &Name="tmp")
CreateDefaultAlignedTempAlloca - This creates an alloca with the default ABI alignment of the given L...
void GenerateOpenMPCapturedVars(const CapturedStmt &S, SmallVectorImpl< llvm::Value * > &CapturedVars)
void EmitIgnoredExpr(const Expr *E)
EmitIgnoredExpr - Emit an expression in a context which ignores the result.
RValue EmitLoadOfLValue(LValue V, SourceLocation Loc)
EmitLoadOfLValue - Given an expression that represents a value lvalue, this method emits the address ...
LValue EmitArraySectionExpr(const ArraySectionExpr *E, bool IsLowerBound=true)
LValue EmitOMPSharedLValue(const Expr *E)
Emits the lvalue for the expression with possibly captured variable.
void StartFunction(GlobalDecl GD, QualType RetTy, llvm::Function *Fn, const CGFunctionInfo &FnInfo, const FunctionArgList &Args, SourceLocation Loc=SourceLocation(), SourceLocation StartLoc=SourceLocation())
Emit code for the start of a function.
void EmitOMPCopy(QualType OriginalType, Address DestAddr, Address SrcAddr, const VarDecl *DestVD, const VarDecl *SrcVD, const Expr *Copy)
Emit proper copying of data from one variable to another.
llvm::Value * EvaluateExprAsBool(const Expr *E)
EvaluateExprAsBool - Perform the usual unary conversions on the specified expression and compare the ...
JumpDest getOMPCancelDestination(OpenMPDirectiveKind Kind)
llvm::Value * emitArrayLength(const ArrayType *arrayType, QualType &baseType, Address &addr)
emitArrayLength - Compute the length of an array, even if it's a VLA, and drill down to the base elem...
void EmitOMPAggregateAssign(Address DestAddr, Address SrcAddr, QualType OriginalType, const llvm::function_ref< void(Address, Address)> CopyGen)
Perform element by element copying of arrays with type OriginalType from SrcAddr to DestAddr using co...
bool HaveInsertPoint() const
HaveInsertPoint - True if an insertion point is defined.
CGDebugInfo * getDebugInfo()
llvm::Value * getTypeSize(QualType Ty)
Returns calculated size of the specified type.
LValue MakeRawAddrLValue(llvm::Value *V, QualType T, CharUnits Alignment, AlignmentSource Source=AlignmentSource::Type)
Same as MakeAddrLValue above except that the pointer is known to be unsigned.
LValue EmitLValueForFieldInitialization(LValue Base, const FieldDecl *Field)
EmitLValueForFieldInitialization - Like EmitLValueForField, except that if the Field is a reference,...
RawAddress CreateMemTempWithoutCast(QualType T, const Twine &Name="tmp")
CreateMemTemp - Create a temporary memory object of the given type, with appropriate alignmen without...
VlaSizePair getVLASize(const VariableArrayType *vla)
Returns an LLVM value that corresponds to the size, in non-variably-sized elements,...
llvm::CallInst * EmitNounwindRuntimeCall(llvm::FunctionCallee callee, const Twine &name="")
ASTContext & getContext() const
llvm::Value * EmitLoadOfScalar(Address Addr, bool Volatile, QualType Ty, SourceLocation Loc, AlignmentSource Source=AlignmentSource::Type, bool isNontemporal=false)
EmitLoadOfScalar - Load a scalar value from an address, taking care to appropriately convert from the...
void EmitStoreOfComplex(ComplexPairTy V, LValue dest, bool isInit)
EmitStoreOfComplex - Store a complex number into the specified l-value.
const Decl * CurFuncDecl
CurFuncDecl - Holds the Decl for the current outermost non-closure context.
void EmitAutoVarCleanups(const AutoVarEmission &emission)
void EmitStoreThroughLValue(RValue Src, LValue Dst, bool isInit=false)
EmitStoreThroughLValue - Store the specified rvalue into the specified lvalue, where both are guarant...
LValue EmitLoadOfPointerLValue(Address Ptr, const PointerType *PtrTy)
void EmitAnyExprToMem(const Expr *E, Address Location, Qualifiers Quals, bool IsInitializer)
EmitAnyExprToMem - Emits the code necessary to evaluate an arbitrary expression into the given memory...
bool needsEHCleanup(QualType::DestructionKind kind)
Determines whether an EH cleanup is required to destroy a type with the given destruction kind.
llvm::DenseMap< const ValueDecl *, FieldDecl * > LambdaCaptureFields
llvm::CallInst * EmitRuntimeCall(llvm::FunctionCallee callee, const Twine &name="")
llvm::Type * ConvertTypeForMem(QualType T)
static void EmitOMPTargetTeamsDistributeParallelForDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsDistributeParallelForDirective &S)
static void EmitOMPTargetParallelForSimdDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetParallelForSimdDirective &S)
Emit device code for the target parallel for simd directive.
CodeGenTypes & getTypes() const
static TypeEvaluationKind getEvaluationKind(QualType T)
getEvaluationKind - Return the TypeEvaluationKind of QualType T.
void EmitOMPTargetTaskBasedDirective(const OMPExecutableDirective &S, const RegionCodeGenTy &BodyGen, OMPTargetDataInfo &InputInfo)
Address EmitPointerWithAlignment(const Expr *Addr, LValueBaseInfo *BaseInfo=nullptr, TBAAAccessInfo *TBAAInfo=nullptr, KnownNonNull_t IsKnownNonNull=NotKnownNonNull)
EmitPointerWithAlignment - Given an expression with a pointer type, emit the value and compute our be...
static void EmitOMPTargetTeamsDistributeParallelForSimdDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsDistributeParallelForSimdDirective &S)
Emit device code for the target teams distribute parallel for simd directive.
void EmitBranch(llvm::BasicBlock *Block)
EmitBranch - Emit a branch to the specified basic block from the current insert block,...
llvm::Function * GenerateOpenMPCapturedStmtFunction(const CapturedStmt &S, const OMPExecutableDirective &D)
RawAddress CreateMemTemp(QualType T, const Twine &Name="tmp", RawAddress *Alloca=nullptr)
CreateMemTemp - Create a temporary memory object of the given type, with appropriate alignmen and cas...
void EmitVarDecl(const VarDecl &D)
EmitVarDecl - Emit a local variable declaration.
llvm::Value * EmitCheckedInBoundsGEP(llvm::Type *ElemTy, llvm::Value *Ptr, ArrayRef< llvm::Value * > IdxList, bool SignedIndices, bool IsSubtraction, SourceLocation Loc, const Twine &Name="")
Same as IRBuilder::CreateInBoundsGEP, but additionally emits a check to detect undefined behavior whe...
static void EmitOMPTargetParallelGenericLoopDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetParallelGenericLoopDirective &S)
Emit device code for the target parallel loop directive.
llvm::Value * EmitScalarExpr(const Expr *E, bool IgnoreResultAssign=false)
EmitScalarExpr - Emit the computation of the specified expression of LLVM scalar type,...
static bool IsWrappedCXXThis(const Expr *E)
Check if E is a C++ "this" pointer wrapped in value-preserving casts.
LValue MakeAddrLValue(Address Addr, QualType T, AlignmentSource Source=AlignmentSource::Type)
void FinishFunction(SourceLocation EndLoc=SourceLocation())
FinishFunction - Complete IR generation of the current function.
void EmitAtomicStore(RValue rvalue, LValue lvalue, bool isInit)
static void EmitOMPTargetSimdDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetSimdDirective &S)
Emit device code for the target simd directive.
static void EmitOMPTargetParallelForDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetParallelForDirective &S)
Emit device code for the target parallel for directive.
Address GetAddrOfLocalVar(const VarDecl *VD)
GetAddrOfLocalVar - Return the address of a local variable.
bool ConstantFoldsToSimpleInteger(const Expr *Cond, bool &Result, bool AllowLabels=false)
ConstantFoldsToSimpleInteger - If the specified expression does not fold to a constant,...
static void EmitOMPTargetTeamsGenericLoopDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsGenericLoopDirective &S)
Emit device code for the target teams loop directive.
LValue EmitMemberExpr(const MemberExpr *E)
std::pair< llvm::Value *, llvm::Value * > ComplexPairTy
Address ReturnValue
ReturnValue - The temporary alloca to hold the return value.
LValue EmitLValue(const Expr *E, KnownNonNull_t IsKnownNonNull=NotKnownNonNull)
EmitLValue - Emit code to compute a designator that specifies the location of the expression.
void incrementProfileCounter(const Stmt *S, llvm::Value *StepV=nullptr)
Increment the profiler's counter for the given statement by StepV.
static void EmitOMPTargetTeamsDistributeSimdDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsDistributeSimdDirective &S)
Emit device code for the target teams distribute simd directive.
llvm::Value * EmitScalarConversion(llvm::Value *Src, QualType SrcTy, QualType DstTy, SourceLocation Loc)
Emit a conversion from the specified type to the specified destination type, both of which are LLVM s...
void EmitVariablyModifiedType(QualType Ty)
EmitVLASize - Capture all the sizes for the VLA expressions in the given variably-modified type and s...
bool isTrivialInitializer(const Expr *Init)
Determine whether the given initializer is trivial in the sense that it requires no code to be genera...
void EmitStoreOfScalar(llvm::Value *Value, Address Addr, bool Volatile, QualType Ty, AlignmentSource Source=AlignmentSource::Type, bool isInit=false, bool isNontemporal=false)
EmitStoreOfScalar - Store a scalar value to an address, taking care to appropriately convert from the...
void EmitBlock(llvm::BasicBlock *BB, bool IsFinished=false)
EmitBlock - Emit the given block.
void EmitExprAsInit(const Expr *init, const ValueDecl *D, LValue lvalue, bool capturedByInit)
EmitExprAsInit - Emits the code necessary to initialize a location in memory with the given initializ...
LValue MakeNaturalAlignRawAddrLValue(llvm::Value *V, QualType T)
This class organizes the cross-function state that is used while generating LLVM code.
void SetInternalFunctionAttributes(GlobalDecl GD, llvm::Function *F, const CGFunctionInfo &FI)
Set the attributes on the LLVM function for the given decl and function info.
llvm::Module & getModule() const
const IntrusiveRefCntPtr< llvm::vfs::FileSystem > & getFileSystem() const
DiagnosticsEngine & getDiags() const
const LangOptions & getLangOpts() const
CharUnits getNaturalTypeAlignment(QualType T, LValueBaseInfo *BaseInfo=nullptr, TBAAAccessInfo *TBAAInfo=nullptr, bool forPointeeType=false)
CodeGenTypes & getTypes()
const llvm::DataLayout & getDataLayout() const
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...
bool HasSideEffects(const ASTContext &Ctx, bool IncludePossibleEffects=true) const
HasSideEffects - This routine returns true for all those expressions which have any effect other than...
std::optional< llvm::APSInt > getIntegerConstantExpr(const ASTContext &Ctx, bool AllowRelaxedEval=false) const
isIntegerConstantExpr - Return the value if this expression is a valid integer constant expression.
bool EvaluateAsBooleanCondition(bool &Result, const ASTContext &Ctx, bool InConstantContext=false) const
EvaluateAsBooleanCondition - Return true if this is a constant which we can fold and convert to a boo...
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
static bool isSameComparisonOperand(const Expr *E1, const Expr *E2)
Checks that the two Expr's will refer to the same value as a comparison operand.
bool hasNonTrivialCall(const ASTContext &Ctx) const
Determine whether this expression involves a call to any function that is not trivial.
Represents a member of a struct/union/class.
unsigned getFieldIndex() const
Returns the index of this field within its record, as appropriate for passing to ASTRecordLayout::get...
const RecordDecl * getParent() const
Returns the parent of this field declaration, which is the struct in which this field is defined.
static FieldDecl * Create(const ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, const IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, Expr *BW, bool Mutable, InClassInitStyle InitStyle)
Represents a function declaration or definition.
const ParmVarDecl * getParamDecl(unsigned i) const
QualType getReturnType() const
ArrayRef< ParmVarDecl * > parameters() const
FunctionDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
FunctionDecl * getMostRecentDecl()
Returns the most recent (re)declaration of this declaration.
unsigned getNumParams() const
Return the number of parameters this function must have based on its FunctionType.
FunctionDecl * getPreviousDecl()
Return the previous declaration of this declaration or NULL if this is the first declaration.
GlobalDecl - represents a global declaration.
const Decl * getDecl() const
static ImplicitParamDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation IdLoc, const IdentifierInfo *Id, QualType T, ImplicitParamKind ParamKind)
Create implicit parameter.
static IntegerLiteral * Create(const ASTContext &C, const llvm::APInt &V, QualType type, SourceLocation l)
Returns a new integer literal with value 'V' and type 'type'.
An lvalue reference type, per C++11 [dcl.ref].
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
ValueDecl * getMemberDecl() const
Retrieve the member declaration to which this expression refers.
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
bool isExternallyVisible() const
const Stmt * getPreInitStmt() const
Get pre-initialization statement for the clause.
This is a basic class for representing single OpenMP clause.
ArrayRef< OMPClause * > clauses() const
This represents 'pragma omp declare mapper ...' directive.
Expr * getMapperVarRef()
Get the variable declared in the mapper.
This represents 'pragma omp declare reduction ...' directive.
Expr * getInitializer()
Get initializer expression (if specified) of the declare reduction construct.
Expr * getInitPriv()
Get Priv variable of the initializer.
Expr * getCombinerOut()
Get Out variable of the combiner.
Expr * getCombinerIn()
Get In variable of the combiner.
Expr * getCombiner()
Get combiner expression of the declare reduction construct.
Expr * getInitOrig()
Get Orig variable of the initializer.
OMPDeclareReductionInitKind getInitializerKind() const
Get initializer kind.
This represents 'if' clause in the 'pragma omp ...' directive.
Expr * getCondition() const
Returns condition.
OMPIteratorHelperData & getHelper(unsigned I)
Fetches helper data for the specified iteration space.
unsigned numOfIterators() const
Returns number of iterator definitions.
This represents 'num_threads' clause in the 'pragma omp ...' directive.
This represents 'pragma omp requires...' directive.
clauselist_range clauselists()
This represents 'threadset' clause in the 'pragma omp task ...' directive.
OpaqueValueExpr - An expression referring to an opaque object of a fixed type and value class.
Represents a parameter to a function.
PointerType - C99 6.7.5.1 - Pointer Declarators.
Represents an unpacked "presumed" location which can be presented to the user.
unsigned getColumn() const
Return the presumed column number of this location.
const char * getFilename() const
Return the presumed filename of this location.
unsigned getLine() const
Return the presumed line number of this location.
A (possibly-)qualified type.
void addRestrict()
Add the restrict qualifier to this QualType.
QualType withRestrict() const
bool isNull() const
Return true if this QualType doesn't point to a type yet.
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
Qualifiers getQualifiers() const
Retrieve the set of qualifiers applied to this type.
QualType getNonReferenceType() const
If Type is a reference type (e.g., const int&), returns the type that the reference refers to ("const...
QualType getCanonicalType() const
DestructionKind isDestructedType() const
Returns a nonzero value if objects of this type require non-trivial work to clean up after.
Represents a struct/union/class.
field_iterator field_end() const
field_range fields() const
virtual void completeDefinition()
Note that the definition of this type is now complete.
field_iterator field_begin() const
Scope - A scope is a transient data structure that is used while parsing the program.
Encodes a location in the source.
static SourceLocation getFromRawEncoding(UIntTy Encoding)
Turn a raw encoding of a SourceLocation object into a real SourceLocation.
bool isValid() const
Return true if this is a valid SourceLocation object.
UIntTy getRawEncoding() const
When a SourceLocation itself cannot be used, this returns an (opaque) 32-bit integer encoding for it.
This class handles loading and caching of source files into memory.
PresumedLoc getPresumedLoc(SourceLocation Loc, bool UseLineDirectives=true) const
Returns the "presumed" location of a SourceLocation specifies.
Stmt - This represents one statement.
StmtClass getStmtClass() const
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Stmt * IgnoreContainers(bool IgnoreCaptured=false)
Skip no-op (attributed, compound) container stmts and skip captured stmt at the top,...
SourceLocation getBeginLoc() const LLVM_READONLY
void startDefinition()
Starts the definition of this tag declaration.
The base class of the type hierarchy.
const Type * getPointeeOrArrayElementType() const
If this is a pointer type, return the pointee type.
bool isSignedIntegerType() const
Return true if this is an integer type that is signed, according to C99 6.2.5p4 [char,...
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
RecordDecl * getAsRecordDecl() const
Retrieves the RecordDecl this type refers to.
bool isPointerType() const
CanQualType getCanonicalTypeUnqualified() const
bool isIntegerType() const
isIntegerType() does not include complex integers (a GCC extension).
const T * castAs() const
Member-template castAs<specific type>.
bool isReferenceType() const
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
bool isLValueReferenceType() const
bool isAggregateType() const
Determines whether the type is a C++ aggregate type or C aggregate or union type.
RecordDecl * castAsRecordDecl() const
QualType getCanonicalTypeInternal() const
const Type * getBaseElementTypeUnsafe() const
Get the base element type of this type, potentially discarding type qualifiers.
bool isVariablyModifiedType() const
Whether this type is a variably-modified type (C99 6.7.5).
const ArrayType * getAsArrayTypeUnsafe() const
A variant of getAs<> for array types which silently discards qualifiers from the outermost type.
bool isFloatingType() const
bool isUnsignedIntegerType() const
Return true if this is an integer type that is unsigned, according to C99 6.2.5p6 [which returns true...
bool isAnyPointerType() const
const T * getAs() const
Member-template getAs<specific type>'.
bool isRecordType() const
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Represents a variable declaration or definition.
VarDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
VarDecl * getDefinition(ASTContext &)
Get the real (not just tentative) definition for this declaration.
const Expr * getInit() const
bool hasExternalStorage() const
Returns true if a variable has extern or private_extern storage.
@ DeclarationOnly
This declaration is only a declaration.
DefinitionKind hasDefinition(ASTContext &) const
Check whether this variable is defined in this translation unit.
bool isLocalVarDeclOrParm() const
Similar to isLocalVarDecl but also includes parameters.
const Expr * getAnyInitializer() const
Get the initializer for this variable, no matter which declaration it is attached to.
Represents a C array with a specified size that is not an integer-constant-expression.
Expr * getSizeExpr() const
specific_attr_iterator - Iterates over a subrange of an AttrVec, only providing attributes that are o...
bool isEmptyRecordForLayout(const ASTContext &Context, QualType T)
isEmptyRecordForLayout - Return true iff a structure contains only empty base classes (per isEmptyRec...
@ Type
The l-value was considered opaque, so the alignment was determined from a type.
@ Decl
The l-value was an access to a declared entity or something equivalently strong, like the address of ...
bool isEmptyFieldForLayout(const ASTContext &Context, const FieldDecl *FD)
isEmptyFieldForLayout - Return true iff the field is "empty", that is, either a zero-width bit-field ...
ComparisonResult
Indicates the result of a tentative comparison.
@ Address
A pointer to a ValueDecl.
Top level wrappers for InstallAPI frontend operations.
bool isOpenMPWorksharingDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a worksharing directive.
CanQual< Type > CanQualType
Represents a canonical, potentially-qualified type.
bool needsTaskBasedThreadLimit(OpenMPDirectiveKind DKind)
Checks if the specified target directive, combined or not, needs task based thread_limit.
@ Match
This is not an overload because the signature exactly matches an existing declaration.
@ Ctor_Complete
Complete object ctor.
Privates[]
This class represents the 'transparent' clause in the 'pragma omp task' directive.
bool isa(CodeGen::Address addr)
if(T->getSizeExpr()) TRY_TO(TraverseStmt(const_cast< Expr * >(T -> getSizeExpr())))
bool isOpenMPTargetDataManagementDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a target data offload directive.
static bool classof(const OMPClause *T)
@ Conditional
A conditional (?:) operator.
@ ICIS_NoInit
No in-class initializer.
bool isOpenMPDistributeDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a distribute directive.
@ LCK_ByRef
Capturing by reference.
LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE()
@ Private
'private' clause, allowed on 'parallel', 'serial', 'loop', 'parallel loop', and 'serial loop' constru...
@ Reduction
'reduction' clause, allowed on Parallel, Serial, Loop, and the combined constructs.
@ Present
'present' clause, allowed on Compute and Combined constructs, plus 'data' and 'declare'.
OpenMPScheduleClauseModifier
OpenMP modifiers for 'schedule' clause.
@ OMPC_SCHEDULE_MODIFIER_last
@ OMPC_SCHEDULE_MODIFIER_unknown
nullptr
This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...
bool isOpenMPParallelDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a parallel-kind directive.
OpenMPDistScheduleClauseKind
OpenMP attributes for 'dist_schedule' clause.
bool isOpenMPTaskingDirective(OpenMPDirectiveKind Kind)
Checks if the specified directive kind is one of tasking directives - task, taskloop,...
bool isOpenMPTargetExecutionDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a target code offload directive.
@ OMPC_DYN_GROUPPRIVATE_FALLBACK_unknown
@ Result
The result type of a method or function.
bool isOpenMPTeamsDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a teams-kind directive.
const FunctionProtoType * T
OpenMPDependClauseKind
OpenMP attributes for 'depend' clause.
@ Dtor_Complete
Complete object dtor.
@ Union
The "union" keyword.
bool isOpenMPTargetMapEnteringDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a map-entering target directive.
@ Type
The name was classified as a type.
bool isOpenMPLoopDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a directive with an associated loop construct.
OpenMPSeverityClauseKind
OpenMP attributes for 'severity' clause.
LangAS
Defines the address space values used by the address space qualifier of QualType.
llvm::omp::Directive OpenMPDirectiveKind
OpenMP directives.
bool isOpenMPSimdDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a simd directive.
@ VK_PRValue
A pr-value expression (in the C++11 taxonomy) produces a temporary value.
@ VK_LValue
An l-value expression is a reference to an object with independent storage.
for(const auto &A :T->param_types())
void getOpenMPCaptureRegions(llvm::SmallVectorImpl< OpenMPDirectiveKind > &CaptureRegions, OpenMPDirectiveKind DKind)
Return the captured regions of an OpenMP directive.
OpenMPNumThreadsClauseModifier
@ OMPC_ATOMIC_DEFAULT_MEM_ORDER_unknown
U cast(CodeGen::Address addr)
OpenMPMapModifierKind
OpenMP modifier kind for 'map' clause.
@ OMPC_MAP_MODIFIER_unknown
@ Other
Other implicit parameter.
OpenMPScheduleClauseKind
OpenMP attributes for 'schedule' clause.
bool isOpenMPTaskLoopDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a taskloop directive.
OpenMPThreadsetKind
OpenMP modifiers for 'threadset' clause.
OpenMPMapClauseKind
OpenMP mapping kind for 'map' clause.
Diagnostic wrappers for TextAPI types for error reporting.
__packed_splat4 __packed_splat2 __packed_splat8 __packed_splat4 int32_t
__packed_splat4 __packed_splat2 __packed_splat8 __packed_splat4 __packed_splat2 __packed_splat4 __packed_splat2 __packed_splat8 __packed_splat4 uint32_t
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.
bool UseFusedDistChunkSchedule
Request the fused distr_static_chunk + static_chunkone runtime schedule in for_static_init.
OpenMPScheduleClauseModifier M2
OpenMPScheduleClauseModifier M1
OpenMPScheduleClauseKind Schedule
Describes how types, statements, expressions, and declarations should be printed.