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 == IP.getNodeParent()->end() &&
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 if (
auto *BD = dyn_cast<BindingDecl>(DRE->getDecl()))
1903 }
else if (
auto *MRE = dyn_cast<MemberExpr>(E)) {
1904 if (
auto *BaseDRE = dyn_cast<DeclRefExpr>(MRE->getBase())) {
1905 if (
auto *BaseVD = dyn_cast<VarDecl>(BaseDRE->getDecl()))
1909 return std::pair<CXXRecordDecl *, const VarDecl *>(
CXXRecord, VD);
1913 for (
const auto *E :
C->varlist()) {
1914 auto DeclPair = GetVTableDecl(E);
1916 if (DeclPair.second)
1925 std::string Suffix =
getName({
"artificial",
""});
1927 llvm::GlobalVariable *GAddr =
OMPBuilder.getOrCreateInternalVariable(
1928 VarLVType, Twine(Name).concat(Suffix).str());
1929 if (
CGM.getLangOpts().OpenMP &&
CGM.getLangOpts().OpenMPUseTLS &&
1930 CGM.getTarget().isTLSSupported()) {
1931 GAddr->setThreadLocal(
true);
1932 return Address(GAddr, GAddr->getValueType(),
1933 CGM.getContext().getTypeAlignInChars(VarType));
1935 std::string CacheSuffix =
getName({
"cache",
""});
1936 llvm::Value *Args[] = {
1944 Twine(Name).concat(Suffix).concat(CacheSuffix).str())};
1949 CGM.getModule(), OMPRTL___kmpc_threadprivate_cached),
1952 VarLVType,
CGM.getContext().getTypeAlignInChars(VarType));
2002 auto &M =
CGM.getModule();
2003 auto &&ThenGen = [&M, OutlinedFn, CapturedVars, RTLoc,
2006 llvm::Value *Args[] = {
2008 CGF.
Builder.getInt32(CapturedVars.size()),
2011 RealArgs.append(std::begin(Args), std::end(Args));
2012 RealArgs.append(CapturedVars.begin(), CapturedVars.end());
2014 llvm::FunctionCallee RTLFn =
2015 OMPBuilder.getOrCreateRuntimeFunction(M, OMPRTL___kmpc_fork_call);
2018 auto &&ElseGen = [&M, OutlinedFn, CapturedVars, RTLoc, Loc,
2024 llvm::Value *Args[] = {RTLoc, ThreadID};
2026 M, OMPRTL___kmpc_serialized_parallel),
2033 ".bound.zero.addr");
2038 OutlinedFnArgs.push_back(ZeroAddrBound.
getPointer());
2039 OutlinedFnArgs.append(CapturedVars.begin(), CapturedVars.end());
2047 OutlinedFn->removeFnAttr(llvm::Attribute::AlwaysInline);
2048 OutlinedFn->addFnAttr(llvm::Attribute::NoInline);
2054 M, OMPRTL___kmpc_end_serialized_parallel),
2073 if (
auto *OMPRegionInfo =
2075 if (OMPRegionInfo->getThreadIDVariable())
2076 return OMPRegionInfo->getThreadIDVariableLValue(CGF).getAddress();
2086 return ThreadIDTemp;
2090 std::string Prefix = Twine(
"gomp_critical_user_", CriticalName).str();
2091 std::string Name =
getName({Prefix,
"var"});
2092 llvm::GlobalVariable *GV =
2094 CGM.setDSOLocal(GV);
2101 llvm::FunctionCallee EnterCallee;
2103 llvm::FunctionCallee ExitCallee;
2106 llvm::BasicBlock *ContBlock =
nullptr;
2109 CommonActionTy(llvm::FunctionCallee EnterCallee,
2111 llvm::FunctionCallee ExitCallee,
2113 : EnterCallee(EnterCallee), EnterArgs(EnterArgs), ExitCallee(ExitCallee),
2118 llvm::Value *CallBool = CGF.
Builder.CreateIsNotNull(EnterRes);
2122 CGF.
Builder.CreateCondBr(CallBool, ThenBlock, ContBlock);
2126 void Done(CodeGenFunction &CGF) {
2131 void Exit(CodeGenFunction &CGF)
override {
2138 StringRef CriticalName,
2147 llvm::FunctionCallee RuntimeFcn =
OMPBuilder.getOrCreateRuntimeFunction(
2149 Hint ? OMPRTL___kmpc_critical_with_hint : OMPRTL___kmpc_critical);
2151 unsigned LockVarArgIdx = 2;
2153 RuntimeFcn.getFunctionType()
2154 ->getParamType(LockVarArgIdx)
2155 ->getPointerAddressSpace())
2157 LockVar, RuntimeFcn.getFunctionType()->getParamType(LockVarArgIdx));
2163 EnterArgs.push_back(CGF.
Builder.CreateIntCast(
2166 CommonActionTy Action(RuntimeFcn, EnterArgs,
2168 CGM.getModule(), OMPRTL___kmpc_end_critical),
2185 CommonActionTy Action(
OMPBuilder.getOrCreateRuntimeFunction(
2186 CGM.getModule(), OMPRTL___kmpc_master),
2189 CGM.getModule(), OMPRTL___kmpc_end_master),
2207 llvm::Value *FilterVal = Filter
2209 : llvm::ConstantInt::get(
CGM.Int32Ty, 0);
2214 CommonActionTy Action(
OMPBuilder.getOrCreateRuntimeFunction(
2215 CGM.getModule(), OMPRTL___kmpc_masked),
2218 CGM.getModule(), OMPRTL___kmpc_end_masked),
2234 llvm::Value *Args[] = {
2236 llvm::ConstantInt::get(
CGM.IntTy, 0,
true)};
2238 CGM.getModule(), OMPRTL___kmpc_omp_taskyield),
2242 if (
auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.
CapturedStmtInfo))
2243 Region->emitUntiedSwitch(CGF);
2256 CommonActionTy Action(
OMPBuilder.getOrCreateRuntimeFunction(
2257 CGM.getModule(), OMPRTL___kmpc_taskgroup),
2260 CGM.getModule(), OMPRTL___kmpc_end_taskgroup),
2269 unsigned Index,
const VarDecl *Var) {
2298 llvm::GlobalValue::InternalLinkage, Name,
2302 Fn->addFnAttr(
"sample-profile-suffix-elision-policy",
"selected");
2303 Fn->setDoesNotRecurse();
2320 for (
unsigned I = 0, E = AssignmentOps.size(); I < E; ++I) {
2321 const auto *DestVar =
2325 const auto *SrcVar =
2331 CGF.
EmitOMPCopy(
Type, DestAddr, SrcAddr, DestVar, SrcVar, AssignmentOps[I]);
2346 assert(CopyprivateVars.size() == SrcExprs.size() &&
2347 CopyprivateVars.size() == DstExprs.size() &&
2348 CopyprivateVars.size() == AssignmentOps.size());
2360 if (!CopyprivateVars.empty()) {
2363 C.getIntTypeForBitwidth(32, 1);
2369 CommonActionTy Action(
OMPBuilder.getOrCreateRuntimeFunction(
2370 CGM.getModule(), OMPRTL___kmpc_single),
2373 CGM.getModule(), OMPRTL___kmpc_end_single),
2386 llvm::APInt ArraySize(32, CopyprivateVars.size());
2387 QualType CopyprivateArrayTy =
C.getConstantArrayType(
2392 CopyprivateArrayTy,
".omp.copyprivate.cpr_list");
2393 for (
unsigned I = 0, E = CopyprivateVars.size(); I < E; ++I) {
2405 SrcExprs, DstExprs, AssignmentOps, Loc);
2406 llvm::Value *BufSize = CGF.
getTypeSize(CopyprivateArrayTy);
2410 llvm::Value *Args[] = {
2414 CL.emitRawPointer(CGF),
2419 CGM.getModule(), OMPRTL___kmpc_copyprivate),
2435 CommonActionTy Action(
OMPBuilder.getOrCreateRuntimeFunction(
2436 CGM.getModule(), OMPRTL___kmpc_ordered),
2439 CGM.getModule(), OMPRTL___kmpc_end_ordered),
2450 if (Kind == OMPD_for)
2451 Flags = OMP_IDENT_BARRIER_IMPL_FOR;
2452 else if (Kind == OMPD_sections)
2453 Flags = OMP_IDENT_BARRIER_IMPL_SECTIONS;
2454 else if (Kind == OMPD_single)
2455 Flags = OMP_IDENT_BARRIER_IMPL_SINGLE;
2456 else if (Kind == OMPD_barrier)
2457 Flags = OMP_IDENT_BARRIER_EXPL;
2459 Flags = OMP_IDENT_BARRIER_IMPL;
2469 S.getClausesOfKind<OMPOrderedClause>(),
2470 [](
const OMPOrderedClause *
C) { return C->getNumForLoops(); })) {
2471 ScheduleKind = OMPC_SCHEDULE_static;
2473 llvm::APInt ChunkSize(32, 1);
2483 bool ForceSimpleCall) {
2485 auto *OMPRegionInfo =
2488 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
2491 CGF.
Builder.restoreIP(AfterIP);
2504 if (OMPRegionInfo) {
2505 if (!ForceSimpleCall && OMPRegionInfo->hasCancel()) {
2508 OMPRTL___kmpc_cancel_barrier),
2517 CGF.
Builder.CreateCondBr(
Cmp, ExitBB, ContBB);
2529 CGM.getModule(), OMPRTL___kmpc_barrier),
2534 Expr *ME,
bool IsFatal) {
2536 : llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
2539 llvm::Value *Args[] = {
2541 llvm::ConstantInt::get(
CGM.Int32Ty, IsFatal ? 2 : 1),
2542 CGF.
Builder.CreatePointerCast(MVL,
CGM.Int8PtrTy)};
2544 CGM.getModule(), OMPRTL___kmpc_error),
2550 bool Chunked,
bool Ordered) {
2551 switch (ScheduleKind) {
2552 case OMPC_SCHEDULE_static:
2553 return Chunked ? (Ordered ? OMP_ord_static_chunked : OMP_sch_static_chunked)
2554 : (Ordered ? OMP_ord_static : OMP_sch_static);
2555 case OMPC_SCHEDULE_dynamic:
2556 return Ordered ? OMP_ord_dynamic_chunked : OMP_sch_dynamic_chunked;
2557 case OMPC_SCHEDULE_guided:
2558 return Ordered ? OMP_ord_guided_chunked : OMP_sch_guided_chunked;
2559 case OMPC_SCHEDULE_runtime:
2560 return Ordered ? OMP_ord_runtime : OMP_sch_runtime;
2561 case OMPC_SCHEDULE_auto:
2562 return Ordered ? OMP_ord_auto : OMP_sch_auto;
2564 assert(!Chunked &&
"chunk was specified but schedule kind not known");
2565 return Ordered ? OMP_ord_static : OMP_sch_static;
2567 llvm_unreachable(
"Unexpected runtime schedule");
2571static OpenMPSchedType
2574 return Chunked ? OMP_dist_sch_static_chunked : OMP_dist_sch_static;
2578 bool Chunked)
const {
2579 OpenMPSchedType Schedule =
2581 return Schedule == OMP_sch_static;
2587 return Schedule == OMP_dist_sch_static;
2591 bool Chunked)
const {
2592 OpenMPSchedType Schedule =
2594 return Schedule == OMP_sch_static_chunked;
2600 return Schedule == OMP_dist_sch_static_chunked;
2604 OpenMPSchedType Schedule =
2606 assert(Schedule != OMP_sch_static_chunked &&
"cannot be chunked here");
2607 return Schedule != OMP_sch_static;
2615 case OMPC_SCHEDULE_MODIFIER_monotonic:
2616 Modifier = OMP_sch_modifier_monotonic;
2618 case OMPC_SCHEDULE_MODIFIER_nonmonotonic:
2619 Modifier = OMP_sch_modifier_nonmonotonic;
2621 case OMPC_SCHEDULE_MODIFIER_simd:
2622 if (Schedule == OMP_sch_static_chunked)
2623 Schedule = OMP_sch_static_balanced_chunked;
2630 case OMPC_SCHEDULE_MODIFIER_monotonic:
2631 Modifier = OMP_sch_modifier_monotonic;
2633 case OMPC_SCHEDULE_MODIFIER_nonmonotonic:
2634 Modifier = OMP_sch_modifier_nonmonotonic;
2636 case OMPC_SCHEDULE_MODIFIER_simd:
2637 if (Schedule == OMP_sch_static_chunked)
2638 Schedule = OMP_sch_static_balanced_chunked;
2650 if (CGM.
getLangOpts().OpenMP >= 50 && Modifier == 0) {
2651 if (!(Schedule == OMP_sch_static_chunked || Schedule == OMP_sch_static ||
2652 Schedule == OMP_sch_static_balanced_chunked ||
2653 Schedule == OMP_ord_static_chunked || Schedule == OMP_ord_static ||
2654 Schedule == OMP_dist_sch_static_chunked ||
2655 Schedule == OMP_dist_sch_static ||
2656 Schedule == OMP_dist_sch_static_chunked_sch_static_chunkone))
2657 Modifier = OMP_sch_modifier_nonmonotonic;
2659 return Schedule | Modifier;
2669 ScheduleKind.
Schedule, DispatchValues.
Chunk !=
nullptr, Ordered);
2671 (Schedule != OMP_sch_static && Schedule != OMP_sch_static_chunked &&
2672 Schedule != OMP_ord_static && Schedule != OMP_ord_static_chunked &&
2673 Schedule != OMP_sch_static_balanced_chunked));
2680 llvm::Value *Chunk = DispatchValues.
Chunk ? DispatchValues.
Chunk
2681 : CGF.
Builder.getIntN(IVSize, 1);
2682 llvm::Value *Args[] = {
2686 CGM, Schedule, ScheduleKind.
M1, ScheduleKind.
M2)),
2689 CGF.
Builder.getIntN(IVSize, 1),
2706 CodeGenFunction &CGF, llvm::Value *UpdateLocation, llvm::Value *ThreadId,
2707 llvm::FunctionCallee ForStaticInitFunction, OpenMPSchedType Schedule,
2714 assert(Schedule == OMP_sch_static || Schedule == OMP_sch_static_chunked ||
2715 Schedule == OMP_sch_static_balanced_chunked ||
2716 Schedule == OMP_ord_static || Schedule == OMP_ord_static_chunked ||
2717 Schedule == OMP_dist_sch_static ||
2718 Schedule == OMP_dist_sch_static_chunked ||
2719 Schedule == OMP_dist_sch_static_chunked_sch_static_chunkone);
2726 llvm::Value *Chunk = Values.
Chunk;
2727 if (Chunk ==
nullptr) {
2728 assert((Schedule == OMP_sch_static || Schedule == OMP_ord_static ||
2729 Schedule == OMP_dist_sch_static) &&
2730 "expected static non-chunked schedule");
2734 assert((Schedule == OMP_sch_static_chunked ||
2735 Schedule == OMP_sch_static_balanced_chunked ||
2736 Schedule == OMP_ord_static_chunked ||
2737 Schedule == OMP_dist_sch_static_chunked ||
2738 Schedule == OMP_dist_sch_static_chunked_sch_static_chunkone) &&
2739 "expected static chunked schedule");
2741 llvm::Value *Args[] = {
2761 OpenMPSchedType ScheduleNum =
2763 ? OMP_dist_sch_static_chunked_sch_static_chunkone
2767 "Expected loop-based or sections-based directive.");
2770 ? OMP_IDENT_WORK_LOOP
2771 : OMP_IDENT_WORK_SECTIONS);
2773 llvm::FunctionCallee StaticInitFunction =
2778 ScheduleNum, ScheduleKind.
M1, ScheduleKind.
M2, Values);
2785 OpenMPSchedType ScheduleNum =
2787 llvm::Value *UpdatedLocation =
2790 llvm::FunctionCallee StaticInitFunction;
2791 bool isGPUDistribute =
2792 CGM.getLangOpts().OpenMPIsTargetDevice &&
CGM.getTriple().isGPU();
2793 StaticInitFunction =
OMPBuilder.createForStaticInitFunction(
2804 assert((DKind == OMPD_distribute || DKind == OMPD_for ||
2805 DKind == OMPD_sections) &&
2806 "Expected distribute, for, or sections directive kind");
2810 llvm::Value *Args[] = {
2813 (DKind == OMPD_target_teams_loop)
2814 ? OMP_IDENT_WORK_DISTRIBUTE
2816 ? OMP_IDENT_WORK_LOOP
2817 : OMP_IDENT_WORK_SECTIONS),
2821 CGM.getLangOpts().OpenMPIsTargetDevice &&
CGM.getTriple().isGPU())
2824 CGM.getModule(), OMPRTL___kmpc_distribute_static_fini),
2828 CGM.getModule(), OMPRTL___kmpc_for_static_fini),
2853 llvm::Value *Args[] = {
2861 OMPBuilder.createDispatchNextFunction(IVSize, IVSigned), Args);
2868 const Expr *Message,
2871 return llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
2880 return llvm::ConstantInt::get(
CGM.Int32Ty,
2881 Severity == OMPC_SEVERITY_warning ? 1 : 2);
2897 RuntimeFunction FnID = OMPRTL___kmpc_push_num_threads;
2898 if (Modifier == OMPC_NUMTHREADS_strict) {
2899 FnID = OMPRTL___kmpc_push_num_threads_strict;
2904 OMPBuilder.getOrCreateRuntimeFunction(
CGM.getModule(), FnID), Args);
2908 ProcBindKind ProcBind,
2912 assert(ProcBind != OMP_PROC_BIND_unknown &&
"Unsupported proc_bind value.");
2914 llvm::Value *Args[] = {
2916 llvm::ConstantInt::get(
CGM.IntTy,
unsigned(ProcBind),
true)};
2918 CGM.getModule(), OMPRTL___kmpc_push_proc_bind),
2931 CGM.getModule(), OMPRTL___kmpc_flush),
2938enum KmpTaskTFields {
2965 if (
CGM.getLangOpts().OpenMPSimd ||
OMPBuilder.OffloadInfoManager.empty())
2968 llvm::OpenMPIRBuilder::EmitMetadataErrorReportFunctionTy &&ErrorReportFn =
2969 [
this](llvm::OpenMPIRBuilder::EmitMetadataErrorKind Kind,
2970 const llvm::TargetRegionEntryInfo &EntryInfo) ->
void {
2972 if (Kind != llvm::OpenMPIRBuilder::EMIT_MD_GLOBAL_VAR_LINK_ERROR) {
2973 for (
auto I =
CGM.getContext().getSourceManager().fileinfo_begin(),
2974 E =
CGM.getContext().getSourceManager().fileinfo_end();
2976 if (I->getFirst().getUniqueID().getDevice() == EntryInfo.DeviceID &&
2977 I->getFirst().getUniqueID().getFile() == EntryInfo.FileID) {
2978 Loc =
CGM.getContext().getSourceManager().translateFileLineCol(
2979 I->getFirst(), EntryInfo.Line, 1);
2985 case llvm::OpenMPIRBuilder::EMIT_MD_TARGET_REGION_ERROR: {
2986 CGM.getDiags().Report(Loc,
2987 diag::err_target_region_offloading_entry_incorrect)
2988 << EntryInfo.ParentName;
2990 case llvm::OpenMPIRBuilder::EMIT_MD_DECLARE_TARGET_ERROR: {
2991 CGM.getDiags().Report(
2992 Loc, diag::err_target_var_offloading_entry_incorrect_with_parent)
2993 << EntryInfo.ParentName;
2995 case llvm::OpenMPIRBuilder::EMIT_MD_GLOBAL_VAR_LINK_ERROR: {
2996 CGM.getDiags().Report(diag::err_target_var_offloading_entry_incorrect);
2998 case llvm::OpenMPIRBuilder::EMIT_MD_GLOBAL_VAR_INDIRECT_ERROR: {
2999 unsigned DiagID =
CGM.getDiags().getCustomDiagID(
3001 "target variable is incorrect: the "
3002 "address is invalid.");
3003 CGM.getDiags().Report(DiagID);
3008 OMPBuilder.createOffloadEntriesAndInfoMetadata(ErrorReportFn);
3015 QualType KmpRoutineEntryTyArgs[] = {KmpInt32Ty,
C.VoidPtrTy};
3018 C.getFunctionType(KmpInt32Ty, KmpRoutineEntryTyArgs, EPI));
3024struct PrivateHelpersTy {
3025 PrivateHelpersTy(
const Expr *OriginalRef,
const VarDecl *Original,
3027 : OriginalRef(OriginalRef), Original(Original), PrivateCopy(PrivateCopy),
3028 PrivateElemInit(PrivateElemInit) {}
3029 PrivateHelpersTy(
const VarDecl *Original) : Original(Original) {}
3030 const Expr *OriginalRef =
nullptr;
3031 const VarDecl *Original =
nullptr;
3032 const VarDecl *PrivateCopy =
nullptr;
3033 const VarDecl *PrivateElemInit =
nullptr;
3034 bool isLocalPrivate()
const {
3035 return !OriginalRef && !PrivateCopy && !PrivateElemInit;
3038typedef std::pair<CharUnits , PrivateHelpersTy> PrivateDataTy;
3044 if (
const auto *BD = dyn_cast<BindingDecl>(
Decl))
3051 if (!CVD->
hasAttr<OMPAllocateDeclAttr>())
3053 const auto *AA = CVD->
getAttr<OMPAllocateDeclAttr>();
3055 return !(AA->getAllocatorType() == OMPAllocateDeclAttr::OMPDefaultMemAlloc &&
3056 !AA->getAllocator());
3066 RecordDecl *RD =
C.buildImplicitRecord(
".kmp_privates.t");
3068 for (
const auto &Pair :
Privates) {
3069 const VarDecl *VD = Pair.second.Original;
3070 const VarDecl *PrivateCopy = Pair.second.PrivateCopy;
3076 Pair.second.OriginalRef &&
3084 if (Pair.second.isLocalPrivate()) {
3107 QualType KmpRoutineEntryPointerQTy) {
3127 CanQualType KmpCmplrdataTy =
C.getCanonicalTagType(UD);
3128 RecordDecl *RD =
C.buildImplicitRecord(
"kmp_task_t");
3158 RecordDecl *RD =
C.buildImplicitRecord(
"kmp_task_t_with_privates");
3178static llvm::Function *
3181 QualType KmpTaskTWithPrivatesPtrQTy,
3183 QualType SharedsPtrTy, llvm::Function *TaskFunction,
3184 llvm::Value *TaskPrivatesMap) {
3190 C,
nullptr, Loc,
nullptr,
3193 const auto &TaskEntryFnInfo =
3195 llvm::FunctionType *TaskEntryTy =
3198 auto *TaskEntry = llvm::Function::Create(
3199 TaskEntryTy, llvm::GlobalValue::InternalLinkage, Name, &CGM.
getModule());
3202 TaskEntry->addFnAttr(
"sample-profile-suffix-elision-policy",
"selected");
3203 TaskEntry->setDoesNotRecurse();
3218 const auto *KmpTaskTWithPrivatesQTyRD =
3223 auto PartIdFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTPartId);
3225 llvm::Value *PartidParam = PartIdLVal.getPointer(CGF);
3227 auto SharedsFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTShareds);
3233 auto PrivatesFI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin(), 1);
3234 llvm::Value *PrivatesParam;
3235 if (PrivatesFI != KmpTaskTWithPrivatesQTyRD->field_end()) {
3238 PrivatesLVal.getPointer(CGF), CGF.
VoidPtrTy);
3240 PrivatesParam = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
3243 llvm::Value *CommonArgs[] = {
3244 GtidParam, PartidParam, PrivatesParam, TaskPrivatesMap,
3250 std::end(CommonArgs));
3252 auto LBFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound);
3255 auto UBFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound);
3258 auto StFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTStride);
3261 auto LIFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLastIter);
3264 auto RFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTReductions);
3267 CallArgs.push_back(LBParam);
3268 CallArgs.push_back(UBParam);
3269 CallArgs.push_back(StParam);
3270 CallArgs.push_back(LIParam);
3271 CallArgs.push_back(RParam);
3273 CallArgs.push_back(SharedsParam);
3286 QualType KmpTaskTWithPrivatesPtrQTy,
3287 QualType KmpTaskTWithPrivatesQTy) {
3293 C,
nullptr, Loc,
nullptr,
3296 const auto &DestructorFnInfo =
3298 llvm::FunctionType *DestructorFnTy =
3302 auto *DestructorFn =
3303 llvm::Function::Create(DestructorFnTy, llvm::GlobalValue::InternalLinkage,
3308 DestructorFn->addFnAttr(
"sample-profile-suffix-elision-policy",
"selected");
3309 DestructorFn->setDoesNotRecurse();
3317 const auto *KmpTaskTWithPrivatesQTyRD =
3319 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin());
3321 for (
const auto *Field : FI->getType()->castAsRecordDecl()->fields()) {
3323 Field->getType().isDestructedType()) {
3325 CGF.
pushDestroy(DtorKind, FieldLValue.getAddress(), Field->getType());
3329 return DestructorFn;
3349 C,
nullptr, Loc,
nullptr,
3350 C.getPointerType(PrivatesQTy).withConst().withRestrict(),
3352 Args.push_back(TaskPrivatesArg);
3353 llvm::SmallDenseMap<CanonicalDeclPtr<const VarDecl>,
unsigned> PrivateVarsPos;
3355 llvm::SmallDenseMap<const BindingDecl *, unsigned> BindingDeclPos;
3356 unsigned Counter = 1;
3357 for (
const Expr *E :
Data.PrivateVars) {
3359 C,
nullptr, Loc,
nullptr,
3360 C.getPointerType(
C.getPointerType(E->
getType()))
3365 if (
const auto *BD = dyn_cast<BindingDecl>(VD))
3371 for (
const Expr *E :
Data.FirstprivateVars) {
3373 C,
nullptr, Loc,
nullptr,
3374 C.getPointerType(
C.getPointerType(E->
getType()))
3379 if (
const auto *BD = dyn_cast<BindingDecl>(VD))
3385 for (
const Expr *E :
Data.LastprivateVars) {
3387 C,
nullptr, Loc,
nullptr,
3388 C.getPointerType(
C.getPointerType(E->
getType()))
3393 if (
const auto *BD = dyn_cast<BindingDecl>(VD))
3402 Ty =
C.getPointerType(Ty);
3404 Ty =
C.getPointerType(Ty);
3406 C,
nullptr, Loc,
nullptr,
3407 C.getPointerType(
C.getPointerType(Ty)).withConst().withRestrict(),
3409 PrivateVarsPos[VD] = Counter;
3412 const auto &TaskPrivatesMapFnInfo =
3414 llvm::FunctionType *TaskPrivatesMapTy =
3418 auto *TaskPrivatesMap = llvm::Function::Create(
3419 TaskPrivatesMapTy, llvm::GlobalValue::InternalLinkage, Name,
3422 TaskPrivatesMapFnInfo);
3424 TaskPrivatesMap->addFnAttr(
"sample-profile-suffix-elision-policy",
3427 TaskPrivatesMap->removeFnAttr(llvm::Attribute::NoInline);
3428 TaskPrivatesMap->removeFnAttr(llvm::Attribute::OptimizeNone);
3429 TaskPrivatesMap->addFnAttr(llvm::Attribute::AlwaysInline);
3433 TaskPrivatesMapFnInfo, Args, Loc, Loc);
3441 for (
const FieldDecl *Field : PrivatesQTyRD->fields()) {
3445 if (
Privates[Counter].second.OriginalRef) {
3449 LookupVD =
Privates[Counter].second.Original;
3457 if (
const auto *BD = dyn_cast<BindingDecl>(LookupVD)) {
3460 assert(Position &&
"binding not in privates mapping");
3464 const VarDecl *VD = Args[Position];
3468 RefLVal.getAddress(), RefLVal.getType()->castAs<
PointerType>());
3473 return TaskPrivatesMap;
3479 Address KmpTaskSharedsPtr, LValue TDBase,
3485 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->
field_begin());
3499 if ((!IsTargetTask && !
Data.FirstprivateVars.empty() && ForDup) ||
3500 (IsTargetTask && KmpTaskSharedsPtr.
isValid())) {
3507 FI = FI->getType()->castAsRecordDecl()->field_begin();
3508 for (
const PrivateDataTy &Pair :
Privates) {
3510 if (Pair.second.isLocalPrivate()) {
3514 const VarDecl *VD = Pair.second.PrivateCopy;
3519 if (
const VarDecl *Elem = Pair.second.PrivateElemInit) {
3520 const VarDecl *OriginalVD = Pair.second.Original;
3523 LValue SharedRefLValue;
3526 if (IsTargetTask && !SharedField) {
3530 ->getNumParams() == 0 &&
3533 ->getDeclContext()) &&
3534 "Expected artificial target data variable.");
3537 }
else if (ForDup) {
3541 if (Pair.second.OriginalRef) {
3542 if (
const auto *DRE =
3543 dyn_cast<DeclRefExpr>(Pair.second.OriginalRef)) {
3544 if (
const auto *BD = dyn_cast<BindingDecl>(DRE->getDecl())) {
3552 It->second = SharedRefLValue.getAddress();
3555 SharedRefLValue = CGF.
EmitLValue(BD->getBinding());
3558 RestoreIt->second = Saved;
3566 Pair.second.OriginalRef &&
3570 SharedRefLValue.getAddress().withAlignment(
3571 IsBinding ?
C.toCharUnitsFromBits(
3572 C.getTypeAlign(SharedRefLValue.getType()))
3573 :
C.getDeclAlign(OriginalVD)),
3575 SharedRefLValue.getTBAAInfo());
3577 Pair.second.Original->getCanonicalDecl()) > 0 ||
3579 SharedRefLValue = CGF.
EmitLValue(Pair.second.OriginalRef);
3582 InlinedOpenMPRegionRAII Region(
3585 SharedRefLValue = CGF.
EmitLValue(Pair.second.OriginalRef);
3596 PrivateLValue.getAddress(), SharedRefLValue.getAddress(),
Type,
3597 [&CGF, Elem,
Init, &CapturesInfo](
Address DestElement,
3600 CodeGenFunction::OMPPrivateScope InitScope(CGF);
3601 InitScope.addPrivate(Elem, SrcElement);
3602 (void)InitScope.Privatize();
3604 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(
3605 CGF, &CapturesInfo);
3606 CGF.EmitAnyExprToMem(Init, DestElement,
3607 Init->getType().getQualifiers(),
3613 InitScope.addPrivate(Elem, SharedRefLValue.getAddress());
3614 (void)InitScope.Privatize();
3622 }
else if (
const VarDecl *OriginalVD = Pair.second.Original) {
3627 if (Pair.second.OriginalRef) {
3628 if (
const auto *DRE = dyn_cast<DeclRefExpr>(Pair.second.OriginalRef)) {
3629 BD = dyn_cast<BindingDecl>(DRE->getDecl());
3639 auto EmitBindingWithTempMap = [&CGF](
const BindingDecl *BD,
3646 It->second = DDAddr;
3655 RestoreIt->second = Saved;
3663 LValue SharedRefLValue;
3667 EmitBindingWithTempMap(BD, SharedRefLValue.getAddress());
3669 SharedRefLValue.getAddress().withAlignment(
3670 C.getDeclAlign(OriginalVD)),
3672 SharedRefLValue.getTBAAInfo());
3676 InlinedOpenMPRegionRAII Region(
3683 SharedRefLValue = EmitBindingWithTempMap(BD, DDAddr);
3696 bool InitRequired =
false;
3697 for (
const PrivateDataTy &Pair :
Privates) {
3698 if (Pair.second.isLocalPrivate())
3700 const VarDecl *VD = Pair.second.PrivateCopy;
3702 InitRequired = InitRequired || (isa_and_nonnull<CXXConstructExpr>(
Init) &&
3707 return InitRequired;
3724 QualType KmpTaskTWithPrivatesPtrQTy,
3731 C,
nullptr, Loc,
nullptr, KmpTaskTWithPrivatesPtrQTy,
3734 C,
nullptr, Loc,
nullptr, KmpTaskTWithPrivatesPtrQTy,
3740 const auto &TaskDupFnInfo =
3744 auto *TaskDup = llvm::Function::Create(
3745 TaskDupTy, llvm::GlobalValue::InternalLinkage, Name, &CGM.
getModule());
3748 TaskDup->addFnAttr(
"sample-profile-suffix-elision-policy",
"selected");
3749 TaskDup->setDoesNotRecurse();
3759 auto LIFI = std::next(KmpTaskTQTyRD->
field_begin(), KmpTaskTLastIter);
3761 TDBase, *KmpTaskTWithPrivatesQTyRD->
field_begin());
3771 if (!
Data.FirstprivateVars.empty()) {
3776 TDBase, *KmpTaskTWithPrivatesQTyRD->
field_begin());
3784 emitPrivatesInit(CGF, D, KmpTaskSharedsPtr, TDBase, KmpTaskTWithPrivatesQTyRD,
3795 for (
const PrivateDataTy &P :
Privates) {
3796 if (P.second.isLocalPrivate())
3798 QualType Ty = P.second.Original->getType().getNonReferenceType();
3807class OMPIteratorGeneratorScope final
3809 CodeGenFunction &CGF;
3810 const OMPIteratorExpr *E =
nullptr;
3811 SmallVector<CodeGenFunction::JumpDest, 4> ContDests;
3812 SmallVector<CodeGenFunction::JumpDest, 4> ExitDests;
3813 OMPIteratorGeneratorScope() =
delete;
3814 OMPIteratorGeneratorScope(OMPIteratorGeneratorScope &) =
delete;
3817 OMPIteratorGeneratorScope(CodeGenFunction &CGF,
const OMPIteratorExpr *E)
3818 : CodeGenFunction::OMPPrivateScope(CGF), CGF(CGF), E(E) {
3821 SmallVector<llvm::Value *, 4> Uppers;
3823 Uppers.push_back(CGF.EmitScalarExpr(E->getHelper(I).Upper));
3824 const auto *VD = cast<VarDecl>(E->getIteratorDecl(I));
3825 addPrivate(VD, CGF.CreateMemTemp(VD->getType(), VD->getName()));
3826 const OMPIteratorHelperData &HelperData = E->getHelper(I);
3828 HelperData.CounterVD,
3829 CGF.CreateMemTemp(HelperData.CounterVD->getType(),
"counter.addr"));
3834 const OMPIteratorHelperData &HelperData = E->getHelper(I);
3836 CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(HelperData.CounterVD),
3837 HelperData.CounterVD->getType());
3839 CGF.EmitStoreOfScalar(
3840 llvm::ConstantInt::get(CLVal.getAddress().getElementType(), 0),
3842 CodeGenFunction::JumpDest &ContDest =
3843 ContDests.emplace_back(CGF.getJumpDestInCurrentScope(
"iter.cont"));
3844 CodeGenFunction::JumpDest &ExitDest =
3845 ExitDests.emplace_back(CGF.getJumpDestInCurrentScope(
"iter.exit"));
3847 llvm::Value *N = Uppers[I];
3850 CGF.EmitBlock(ContDest.getBlock());
3852 CGF.EmitLoadOfScalar(CLVal, HelperData.CounterVD->getLocation());
3854 HelperData.CounterVD->getType()->isSignedIntegerOrEnumerationType()
3855 ? CGF.Builder.CreateICmpSLT(CVal, N)
3856 : CGF.Builder.CreateICmpULT(CVal, N);
3857 llvm::BasicBlock *BodyBB = CGF.createBasicBlock(
"iter.body");
3858 CGF.Builder.CreateCondBr(Cmp, BodyBB, ExitDest.getBlock());
3860 CGF.EmitBlock(BodyBB);
3862 CGF.EmitIgnoredExpr(HelperData.Update);
3865 ~OMPIteratorGeneratorScope() {
3870 const OMPIteratorHelperData &HelperData = E->
getHelper(I - 1);
3875 CGF.
EmitBlock(ExitDests[I - 1].getBlock(), I == 1);
3881static std::pair<llvm::Value *, llvm::Value *>
3883 const auto *OASE = dyn_cast<OMPArrayShapingExpr>(E);
3886 const Expr *
Base = OASE->getBase();
3891 llvm::Value *SizeVal;
3894 SizeVal = CGF.
getTypeSize(OASE->getBase()->getType()->getPointeeType());
3895 for (
const Expr *SE : OASE->getDimensions()) {
3899 SizeVal = CGF.
Builder.CreateNUWMul(SizeVal, Sz);
3901 }
else if (
const auto *ASE =
3904 Address UpAddrAddress = UpAddrLVal.getAddress();
3905 llvm::Value *UpAddr = CGF.
Builder.CreateConstGEP1_32(
3908 SizeVal = CGF.
Builder.CreatePtrDiff(UpAddr,
Addr,
"",
true);
3912 return std::make_pair(
Addr, SizeVal);
3917 QualType FlagsTy =
C.getIntTypeForBitwidth(32,
false);
3918 if (KmpTaskAffinityInfoTy.
isNull()) {
3920 C.buildImplicitRecord(
"kmp_task_affinity_info_t");
3926 KmpTaskAffinityInfoTy =
C.getCanonicalTagType(KmpAffinityInfoRD);
3933 llvm::Function *TaskFunction,
QualType SharedsTy,
3938 const auto *I =
Data.PrivateCopies.begin();
3939 for (
const Expr *E :
Data.PrivateVars) {
3943 Privates.emplace_back(
C.getDeclAlign(VD),
3944 PrivateHelpersTy(E, VD, CopyVD,
3948 I =
Data.FirstprivateCopies.begin();
3949 const auto *IElemInitRef =
Data.FirstprivateInits.begin();
3950 for (
const Expr *E :
Data.FirstprivateVars) {
3954 const auto *InitVD =
3956 Privates.emplace_back(
C.getDeclAlign(VD),
3957 PrivateHelpersTy(E, VD, CopyVD, InitVD));
3961 I =
Data.LastprivateCopies.begin();
3962 for (
const Expr *E :
Data.LastprivateVars) {
3966 Privates.emplace_back(
C.getDeclAlign(VD),
3967 PrivateHelpersTy(E, VD, CopyVD,
3973 Privates.emplace_back(
CGM.getPointerAlign(), PrivateHelpersTy(VD));
3975 Privates.emplace_back(
C.getDeclAlign(VD), PrivateHelpersTy(VD));
3978 [](
const PrivateDataTy &L,
const PrivateDataTy &R) {
3979 return L.first > R.first;
3981 QualType KmpInt32Ty =
C.getIntTypeForBitwidth(32, 1);
3992 assert((D.getDirectiveKind() == OMPD_task ||
3995 "Expected taskloop, task or target directive");
4002 const auto *KmpTaskTQTyRD =
KmpTaskTQTy->castAsRecordDecl();
4004 const RecordDecl *KmpTaskTWithPrivatesQTyRD =
4007 C.getCanonicalTagType(KmpTaskTWithPrivatesQTyRD);
4008 QualType KmpTaskTWithPrivatesPtrQTy =
4009 C.getPointerType(KmpTaskTWithPrivatesQTy);
4010 llvm::Type *KmpTaskTWithPrivatesPtrTy = CGF.
Builder.getPtrTy(0);
4011 llvm::Value *KmpTaskTWithPrivatesTySize =
4013 QualType SharedsPtrTy =
C.getPointerType(SharedsTy);
4016 llvm::Value *TaskPrivatesMap =
nullptr;
4017 llvm::Type *TaskPrivatesMapTy =
4018 std::next(TaskFunction->arg_begin(), 3)->getType();
4020 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->
field_begin());
4024 TaskPrivatesMap, TaskPrivatesMapTy);
4026 TaskPrivatesMap = llvm::ConstantPointerNull::get(
4032 CGM, Loc, D.getDirectiveKind(), KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy,
4033 KmpTaskTWithPrivatesQTy,
KmpTaskTQTy, SharedsPtrTy, TaskFunction,
4045 DestructorsFlag = 0x8,
4046 PriorityFlag = 0x20,
4047 DetachableFlag = 0x40,
4048 FreeAgentFlag = 0x80,
4049 TransparentFlag = 0x100,
4051 unsigned Flags =
Data.Tied ? TiedFlag : 0;
4052 bool NeedsCleanup =
false;
4057 Flags = Flags | DestructorsFlag;
4061 if (Kind == OMPC_THREADSET_omp_pool)
4062 Flags = Flags | FreeAgentFlag;
4064 if (D.getSingleClause<OMPTransparentClause>())
4065 Flags |= TransparentFlag;
4067 if (
Data.Priority.getInt())
4068 Flags = Flags | PriorityFlag;
4070 Flags = Flags | DetachableFlag;
4071 llvm::Value *TaskFlags =
4072 Data.Final.getPointer()
4073 ? CGF.
Builder.CreateSelect(
Data.Final.getPointer(),
4074 CGF.
Builder.getInt32(FinalFlag),
4076 : CGF.
Builder.getInt32(
Data.Final.getInt() ? FinalFlag : 0);
4077 TaskFlags = CGF.
Builder.CreateOr(TaskFlags, CGF.
Builder.getInt32(Flags));
4078 llvm::Value *SharedsSize =
CGM.getSize(
C.getTypeSizeInChars(SharedsTy));
4080 getThreadID(CGF, Loc), TaskFlags, KmpTaskTWithPrivatesTySize,
4083 llvm::Value *NewTask;
4084 if (D.hasClausesOfKind<OMPNowaitClause>()) {
4090 llvm::Value *DeviceID;
4095 DeviceID = CGF.
Builder.getInt64(OMP_DEVICEID_UNDEF);
4096 AllocArgs.push_back(DeviceID);
4099 CGM.getModule(), OMPRTL___kmpc_omp_target_task_alloc),
4104 CGM.getModule(), OMPRTL___kmpc_omp_task_alloc),
4117 llvm::Value *Tid =
getThreadID(CGF, DC->getBeginLoc());
4118 Tid = CGF.
Builder.CreateIntCast(Tid, CGF.
IntTy,
false);
4121 CGM.getModule(), OMPRTL___kmpc_task_allow_completion_event),
4122 {Loc, Tid, NewTask});
4133 llvm::Value *NumOfElements =
nullptr;
4134 unsigned NumAffinities = 0;
4136 if (
const Expr *Modifier =
C->getModifier()) {
4138 for (
unsigned I = 0, E = IE->numOfIterators(); I < E; ++I) {
4142 NumOfElements ? CGF.
Builder.CreateNUWMul(NumOfElements, Sz) : Sz;
4145 NumAffinities +=
C->varlist_size();
4150 enum RTLAffinityInfoFieldsTy { BaseAddr, Len, Flags };
4152 QualType KmpTaskAffinityInfoArrayTy;
4153 if (NumOfElements) {
4154 NumOfElements = CGF.
Builder.CreateNUWAdd(
4155 llvm::ConstantInt::get(CGF.
SizeTy, NumAffinities), NumOfElements);
4158 C.getIntTypeForBitwidth(
C.getTypeSize(
C.getSizeType()), 0),
4162 KmpTaskAffinityInfoArrayTy =
C.getVariableArrayType(
4170 NumOfElements = CGF.
Builder.CreateIntCast(NumOfElements, CGF.
Int32Ty,
4173 KmpTaskAffinityInfoArrayTy =
C.getConstantArrayType(
4175 llvm::APInt(
C.getTypeSize(
C.getSizeType()), NumAffinities),
nullptr,
4180 NumOfElements = llvm::ConstantInt::get(
CGM.Int32Ty, NumAffinities,
4187 bool HasIterator =
false;
4189 if (
C->getModifier()) {
4193 for (
const Expr *E :
C->varlist()) {
4202 Base, *std::next(KmpAffinityInfoRD->field_begin(), BaseAddr));
4207 Base, *std::next(KmpAffinityInfoRD->field_begin(), Len));
4221 const Expr *Modifier =
C->getModifier();
4224 OMPIteratorGeneratorScope IteratorScope(
4226 for (
const Expr *E :
C->varlist()) {
4236 Base, *std::next(KmpAffinityInfoRD->field_begin(), BaseAddr));
4241 Base, *std::next(KmpAffinityInfoRD->field_begin(), Len));
4243 Idx = CGF.
Builder.CreateNUWAdd(
4244 Idx, llvm::ConstantInt::get(Idx->getType(), 1));
4259 CGM.getModule(), OMPRTL___kmpc_omp_reg_task_with_affinity),
4260 {LocRef, GTid, NewTask, NumOfElements, AffinListPtr});
4262 llvm::Value *NewTaskNewTaskTTy =
4264 NewTask, KmpTaskTWithPrivatesPtrTy);
4266 KmpTaskTWithPrivatesQTy);
4277 *std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTShareds)),
4279 CGF.
Int8Ty,
CGM.getNaturalTypeAlignment(SharedsTy));
4293 CGM, Loc, D, KmpTaskTWithPrivatesPtrQTy, KmpTaskTWithPrivatesQTyRD,
4294 KmpTaskTQTyRD, SharedsTy, SharedsPtrTy,
Data,
Privates,
4295 !
Data.LastprivateVars.empty());
4299 enum { Priority = 0, Destructors = 1 };
4301 auto FI = std::next(KmpTaskTQTyRD->field_begin(), Data1);
4302 const auto *KmpCmplrdataUD = (*FI)->getType()->castAsRecordDecl();
4303 assert(KmpCmplrdataUD->isUnion());
4306 CGM, Loc, KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy,
4307 KmpTaskTWithPrivatesQTy);
4310 Data1LV, *std::next(KmpCmplrdataUD->field_begin(), Destructors));
4316 if (
Data.Priority.getInt()) {
4318 TDBase, *std::next(KmpTaskTQTyRD->field_begin(), Data2));
4320 Data2LV, *std::next(KmpCmplrdataUD->field_begin(), Priority));
4323 Result.NewTask = NewTask;
4324 Result.TaskEntry = TaskEntry;
4325 Result.NewTaskNewTaskTTy = NewTaskNewTaskTTy;
4327 Result.KmpTaskTQTyRD = KmpTaskTQTyRD;
4333 RTLDependenceKindTy DepKind;
4335 case OMPC_DEPEND_in:
4336 DepKind = RTLDependenceKindTy::DepIn;
4339 case OMPC_DEPEND_out:
4340 case OMPC_DEPEND_inout:
4341 DepKind = RTLDependenceKindTy::DepInOut;
4343 case OMPC_DEPEND_mutexinoutset:
4344 DepKind = RTLDependenceKindTy::DepMutexInOutSet;
4346 case OMPC_DEPEND_inoutset:
4347 DepKind = RTLDependenceKindTy::DepInOutSet;
4349 case OMPC_DEPEND_outallmemory:
4350 DepKind = RTLDependenceKindTy::DepOmpAllMem;
4352 case OMPC_DEPEND_source:
4353 case OMPC_DEPEND_sink:
4354 case OMPC_DEPEND_depobj:
4355 case OMPC_DEPEND_inoutallmemory:
4357 llvm_unreachable(
"Unknown task dependence type");
4365 FlagsTy =
C.getIntTypeForBitwidth(
C.getTypeSize(
C.BoolTy),
false);
4366 if (KmpDependInfoTy.
isNull()) {
4367 RecordDecl *KmpDependInfoRD =
C.buildImplicitRecord(
"kmp_depend_info");
4373 KmpDependInfoTy =
C.getCanonicalTagType(KmpDependInfoRD);
4377std::pair<llvm::Value *, LValue>
4390 CGF,
Base.getAddress(),
4391 llvm::ConstantInt::get(CGF.
IntPtrTy, -1,
true));
4397 *std::next(KmpDependInfoRD->field_begin(),
4398 static_cast<unsigned int>(RTLDependInfoFields::BaseAddr)));
4400 return std::make_pair(NumDeps,
Base);
4404 llvm::PointerUnion<unsigned *, LValue *> Pos,
4414 OMPIteratorGeneratorScope IteratorScope(
4415 CGF, cast_or_null<OMPIteratorExpr>(
4416 Data.IteratorExpr ?
Data.IteratorExpr->IgnoreParenImpCasts()
4418 for (
const Expr *E :
Data.DepExprs) {
4428 Size = llvm::ConstantInt::get(CGF.
SizeTy, 0);
4431 if (
unsigned *P = dyn_cast<unsigned *>(Pos)) {
4435 assert(E &&
"Expected a non-null expression");
4444 *std::next(KmpDependInfoRD->field_begin(),
4445 static_cast<unsigned int>(RTLDependInfoFields::BaseAddr)));
4449 Base, *std::next(KmpDependInfoRD->field_begin(),
4450 static_cast<unsigned int>(RTLDependInfoFields::Len)));
4456 *std::next(KmpDependInfoRD->field_begin(),
4457 static_cast<unsigned int>(RTLDependInfoFields::Flags)));
4459 llvm::ConstantInt::get(LLVMFlagsTy,
static_cast<unsigned int>(DepKind)),
4461 if (
unsigned *P = dyn_cast<unsigned *>(Pos)) {
4466 Idx = CGF.
Builder.CreateNUWAdd(Idx,
4467 llvm::ConstantInt::get(Idx->getType(), 1));
4476 assert(
Data.DepKind == OMPC_DEPEND_depobj &&
4477 "Expected depobj dependency kind.");
4482 OMPIteratorGeneratorScope IteratorScope(
4483 CGF, cast_or_null<OMPIteratorExpr>(
4484 Data.IteratorExpr ?
Data.IteratorExpr->IgnoreParenImpCasts()
4486 for (
const Expr *E :
Data.DepExprs) {
4487 llvm::Value *NumDeps;
4490 std::tie(NumDeps,
Base) =
4494 C.getUIntPtrType());
4498 llvm::Value *Add = CGF.
Builder.CreateNUWAdd(PrevVal, NumDeps);
4500 SizeLVals.push_back(NumLVal);
4503 for (
unsigned I = 0, E = SizeLVals.size(); I < E; ++I) {
4506 Sizes.push_back(Size);
4516 assert(
Data.DepKind == OMPC_DEPEND_depobj &&
4517 "Expected depobj dependency kind.");
4520 OMPIteratorGeneratorScope IteratorScope(
4521 CGF, cast_or_null<OMPIteratorExpr>(
4522 Data.IteratorExpr ?
Data.IteratorExpr->IgnoreParenImpCasts()
4524 for (
const Expr *E :
Data.DepExprs) {
4525 llvm::Value *NumDeps;
4528 std::tie(NumDeps,
Base) =
4532 llvm::Value *Size = CGF.
Builder.CreateNUWMul(
4541 llvm::Value *Add = CGF.
Builder.CreateNUWAdd(Pos, NumDeps);
4557 llvm::Value *NumOfElements =
nullptr;
4558 unsigned NumDependencies = std::accumulate(
4559 Dependencies.begin(), Dependencies.end(), 0,
4561 return D.DepKind == OMPC_DEPEND_depobj
4563 : (V + (D.IteratorExpr ? 0 : D.DepExprs.size()));
4567 bool HasDepobjDeps =
false;
4568 bool HasRegularWithIterators =
false;
4569 llvm::Value *NumOfDepobjElements = llvm::ConstantInt::get(CGF.
IntPtrTy, 0);
4570 llvm::Value *NumOfRegularWithIterators =
4571 llvm::ConstantInt::get(CGF.
IntPtrTy, 0);
4575 if (D.
DepKind == OMPC_DEPEND_depobj) {
4578 for (llvm::Value *Size : Sizes) {
4579 NumOfDepobjElements =
4580 CGF.
Builder.CreateNUWAdd(NumOfDepobjElements, Size);
4582 HasDepobjDeps =
true;
4587 if (
const auto *IE = cast_or_null<OMPIteratorExpr>(D.
IteratorExpr)) {
4588 llvm::Value *ClauseIteratorSpace =
4589 llvm::ConstantInt::get(CGF.
IntPtrTy, 1);
4593 ClauseIteratorSpace = CGF.
Builder.CreateNUWMul(Sz, ClauseIteratorSpace);
4595 llvm::Value *NumClauseDeps = CGF.
Builder.CreateNUWMul(
4596 ClauseIteratorSpace,
4598 NumOfRegularWithIterators =
4599 CGF.
Builder.CreateNUWAdd(NumOfRegularWithIterators, NumClauseDeps);
4600 HasRegularWithIterators =
true;
4606 if (HasDepobjDeps || HasRegularWithIterators) {
4607 NumOfElements = llvm::ConstantInt::get(
CGM.IntPtrTy, NumDependencies,
4609 if (HasDepobjDeps) {
4611 CGF.
Builder.CreateNUWAdd(NumOfDepobjElements, NumOfElements);
4613 if (HasRegularWithIterators) {
4615 CGF.
Builder.CreateNUWAdd(NumOfRegularWithIterators, NumOfElements);
4618 Loc,
C.getIntTypeForBitwidth(64, 0),
4622 KmpDependInfoArrayTy =
4631 NumOfElements = CGF.
Builder.CreateIntCast(NumOfElements, CGF.
Int32Ty,
4634 KmpDependInfoArrayTy =
C.getConstantArrayType(
4640 NumOfElements = llvm::ConstantInt::get(
CGM.Int32Ty, NumDependencies,
4645 if (Dep.DepKind == OMPC_DEPEND_depobj || Dep.IteratorExpr)
4655 if (Dep.DepKind == OMPC_DEPEND_depobj || !Dep.IteratorExpr)
4660 if (HasDepobjDeps) {
4662 if (Dep.DepKind != OMPC_DEPEND_depobj)
4669 return std::make_pair(NumOfElements, DependenciesArray);
4680 unsigned NumDependencies = Dependencies.
DepExprs.size();
4690 llvm::Value *NumDepsVal;
4692 if (
const auto *IE =
4693 cast_or_null<OMPIteratorExpr>(Dependencies.
IteratorExpr)) {
4694 NumDepsVal = llvm::ConstantInt::get(CGF.
SizeTy, 1);
4698 NumDepsVal = CGF.
Builder.CreateNUWMul(NumDepsVal, Sz);
4700 Size = CGF.
Builder.CreateNUWAdd(llvm::ConstantInt::get(CGF.
SizeTy, 1),
4704 llvm::Value *RecSize =
CGM.getSize(SizeInBytes);
4705 Size = CGF.
Builder.CreateNUWMul(Size, RecSize);
4709 QualType KmpDependInfoArrayTy =
C.getConstantArrayType(
4712 CharUnits Sz =
C.getTypeSizeInChars(KmpDependInfoArrayTy);
4714 NumDepsVal = llvm::ConstantInt::get(CGF.
IntPtrTy, NumDependencies);
4719 llvm::Value *Allocator = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
4720 llvm::Value *Args[] = {ThreadID, Size, Allocator};
4724 CGM.getModule(), OMPRTL___kmpc_alloc),
4725 Args,
".dep.arr.addr");
4729 DependenciesArray =
Address(
Addr, KmpDependInfoLlvmTy, Align);
4735 *std::next(KmpDependInfoRD->field_begin(),
4736 static_cast<unsigned int>(RTLDependInfoFields::BaseAddr)));
4738 llvm::PointerUnion<unsigned *, LValue *> Pos;
4755 return DependenciesArray;
4770 Addr.getElementType(),
Addr.emitRawPointer(CGF),
4771 llvm::ConstantInt::get(CGF.
IntPtrTy, -1,
true));
4776 llvm::Value *Allocator = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
4777 llvm::Value *Args[] = {ThreadID, DepObjAddr, Allocator};
4781 CGM.getModule(), OMPRTL___kmpc_free),
4793 llvm::Value *NumDeps;
4804 llvm::BasicBlock *EntryBB = CGF.
Builder.GetInsertBlock();
4806 llvm::PHINode *ElementPHI =
4811 Base.getTBAAInfo());
4815 Base, *std::next(KmpDependInfoRD->field_begin(),
4816 static_cast<unsigned int>(RTLDependInfoFields::Flags)));
4818 llvm::ConstantInt::get(LLVMFlagsTy,
static_cast<unsigned int>(DepKind)),
4822 llvm::Value *ElementNext =
4825 ElementPHI->addIncoming(ElementNext, CGF.
Builder.GetInsertBlock());
4826 llvm::Value *IsEmpty =
4827 CGF.
Builder.CreateICmpEQ(ElementNext, End,
"omp.isempty");
4828 CGF.
Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
4835 llvm::Function *TaskFunction,
4844 llvm::Value *NewTask =
Result.NewTask;
4845 llvm::Function *TaskEntry =
Result.TaskEntry;
4846 llvm::Value *NewTaskNewTaskTTy =
Result.NewTaskNewTaskTTy;
4851 llvm::Value *NumOfElements;
4852 std::tie(NumOfElements, DependenciesArray) =
4863 llvm::Value *TaskArgs[] = { UpLoc, ThreadID, NewTask };
4864 llvm::Value *DepTaskArgs[7];
4865 if (!
Data.Dependences.empty()) {
4866 DepTaskArgs[0] = UpLoc;
4867 DepTaskArgs[1] = ThreadID;
4868 DepTaskArgs[2] = NewTask;
4869 DepTaskArgs[3] = NumOfElements;
4871 DepTaskArgs[5] = CGF.
Builder.getInt32(0);
4872 DepTaskArgs[6] = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
4874 auto &&ThenCodeGen = [
this, &
Data, TDBase, KmpTaskTQTyRD, &TaskArgs,
4877 auto PartIdFI = std::next(KmpTaskTQTyRD->
field_begin(), KmpTaskTPartId);
4881 if (!
Data.Dependences.empty()) {
4884 CGM.getModule(), OMPRTL___kmpc_omp_task_with_deps),
4888 CGM.getModule(), OMPRTL___kmpc_omp_task),
4894 Region->emitUntiedSwitch(CGF);
4897 llvm::Value *DepWaitTaskArgs[7];
4898 if (!
Data.Dependences.empty()) {
4899 DepWaitTaskArgs[0] = UpLoc;
4900 DepWaitTaskArgs[1] = ThreadID;
4901 DepWaitTaskArgs[2] = NumOfElements;
4903 DepWaitTaskArgs[4] = CGF.
Builder.getInt32(0);
4904 DepWaitTaskArgs[5] = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
4905 DepWaitTaskArgs[6] =
4906 llvm::ConstantInt::get(CGF.
Int32Ty,
Data.HasNowaitClause);
4908 auto &M =
CGM.getModule();
4909 auto &&ElseCodeGen = [
this, &M, &TaskArgs, ThreadID, NewTaskNewTaskTTy,
4910 TaskEntry, &
Data, &DepWaitTaskArgs,
4917 if (!
Data.Dependences.empty())
4919 M, OMPRTL___kmpc_omp_taskwait_deps_51),
4922 auto &&
CodeGen = [TaskEntry, ThreadID, NewTaskNewTaskTTy,
4925 llvm::Value *OutlinedFnArgs[] = {ThreadID, NewTaskNewTaskTTy};
4926 CGF.CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, Loc, TaskEntry,
4935 CommonActionTy Action(
OMPBuilder.getOrCreateRuntimeFunction(
4936 M, OMPRTL___kmpc_omp_task_begin_if0),
4939 M, OMPRTL___kmpc_omp_task_complete_if0),
4955 llvm::Function *TaskFunction,
4975 IfVal = llvm::ConstantInt::getSigned(CGF.
IntTy, 1);
4980 *std::next(
Result.KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound));
4987 *std::next(
Result.KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound));
4994 *std::next(
Result.KmpTaskTQTyRD->field_begin(), KmpTaskTStride));
5002 *std::next(
Result.KmpTaskTQTyRD->field_begin(), KmpTaskTReductions));
5003 if (
Data.Reductions) {
5009 enum { NoSchedule = 0, Grainsize = 1, NumTasks = 2 };
5018 llvm::ConstantInt::getSigned(
5020 llvm::ConstantInt::getSigned(
5022 ?
Data.Schedule.getInt() ? NumTasks : Grainsize
5024 Data.Schedule.getPointer()
5027 : llvm::ConstantInt::get(CGF.
Int64Ty, 0)};
5028 if (
Data.HasModifier)
5029 TaskArgs.push_back(llvm::ConstantInt::get(CGF.
Int32Ty, 1));
5031 TaskArgs.push_back(
Result.TaskDupFn
5034 : llvm::ConstantPointerNull::get(CGF.
VoidPtrTy));
5036 CGM.getModule(),
Data.HasModifier
5037 ? OMPRTL___kmpc_taskloop_5
5038 : OMPRTL___kmpc_taskloop),
5055 const Expr *,
const Expr *)> &RedOpGen,
5056 const Expr *XExpr =
nullptr,
const Expr *EExpr =
nullptr,
5057 const Expr *UpExpr =
nullptr) {
5065 llvm::Value *NumElements = CGF.
emitArrayLength(ArrayTy, ElementTy, LHSAddr);
5070 llvm::Value *LHSEnd =
5075 llvm::Value *IsEmpty =
5076 CGF.
Builder.CreateICmpEQ(LHSBegin, LHSEnd,
"omp.arraycpy.isempty");
5077 CGF.
Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
5080 llvm::BasicBlock *EntryBB = CGF.
Builder.GetInsertBlock();
5085 llvm::PHINode *RHSElementPHI = CGF.
Builder.CreatePHI(
5086 RHSBegin->getType(), 2,
"omp.arraycpy.srcElementPast");
5087 RHSElementPHI->addIncoming(RHSBegin, EntryBB);
5092 llvm::PHINode *LHSElementPHI = CGF.
Builder.CreatePHI(
5093 LHSBegin->getType(), 2,
"omp.arraycpy.destElementPast");
5094 LHSElementPHI->addIncoming(LHSBegin, EntryBB);
5101 Scope.addPrivate(LHSVar, LHSElementCurrent);
5102 Scope.addPrivate(RHSVar, RHSElementCurrent);
5104 RedOpGen(CGF, XExpr, EExpr, UpExpr);
5105 Scope.ForceCleanup();
5108 llvm::Value *LHSElementNext = CGF.
Builder.CreateConstGEP1_32(
5110 "omp.arraycpy.dest.element");
5111 llvm::Value *RHSElementNext = CGF.
Builder.CreateConstGEP1_32(
5113 "omp.arraycpy.src.element");
5116 CGF.
Builder.CreateICmpEQ(LHSElementNext, LHSEnd,
"omp.arraycpy.done");
5117 CGF.
Builder.CreateCondBr(Done, DoneBB, BodyBB);
5118 LHSElementPHI->addIncoming(LHSElementNext, CGF.
Builder.GetInsertBlock());
5119 RHSElementPHI->addIncoming(RHSElementNext, CGF.
Builder.GetInsertBlock());
5129 const Expr *ReductionOp) {
5130 if (
const auto *CE = dyn_cast<CallExpr>(ReductionOp))
5131 if (
const auto *OVE = dyn_cast<OpaqueValueExpr>(CE->getCallee()))
5132 if (
const auto *DRE =
5133 dyn_cast<DeclRefExpr>(OVE->getSourceExpr()->IgnoreImpCasts()))
5134 if (
const auto *DRD =
5135 dyn_cast<OMPDeclareReductionDecl>(DRE->getDecl())) {
5136 std::pair<llvm::Function *, llvm::Function *>
Reduction =
5147 StringRef ReducerName,
SourceLocation Loc, llvm::Type *ArgsElemType,
5161 CGM.getTypes().arrangeBuiltinFunctionDeclaration(
C.VoidTy, Args);
5163 auto *Fn = llvm::Function::Create(
CGM.getTypes().GetFunctionType(CGFI),
5164 llvm::GlobalValue::InternalLinkage, Name,
5167 if (!
CGM.getCodeGenOpts().SampleProfileFile.empty())
5168 Fn->addFnAttr(
"sample-profile-suffix-elision-policy",
"selected");
5169 Fn->setDoesNotRecurse();
5188 const auto *IPriv =
Privates.begin();
5190 for (
unsigned I = 0, E = ReductionOps.size(); I < E; ++I, ++IPriv, ++Idx) {
5191 const auto *RHSVar =
5194 const auto *LHSVar =
5197 QualType PrivTy = (*IPriv)->getType();
5213 const auto *ILHS = LHSExprs.begin();
5214 const auto *IRHS = RHSExprs.begin();
5215 for (
const Expr *E : ReductionOps) {
5216 if ((*IPriv)->getType()->isArrayType()) {
5221 CGF, (*IPriv)->getType(), LHSVar, RHSVar,
5223 emitReductionCombiner(CGF, E);
5233 Scope.ForceCleanup();
5239 const Expr *ReductionOp,
5240 const Expr *PrivateRef,
5248 CGF, PrivateRef->
getType(), LHSVar, RHSVar,
5250 emitReductionCombiner(CGF, ReductionOp);
5259 llvm::StringRef Prefix,
const Expr *Ref);
5263 const Expr *LHSExprs,
const Expr *RHSExprs,
const Expr *ReductionOps) {
5290 std::string ReductionVarNameStr;
5291 if (
const auto *DRE = dyn_cast<DeclRefExpr>(
Privates->IgnoreParenCasts()))
5292 ReductionVarNameStr =
5295 ReductionVarNameStr =
"unnamed_priv_var";
5298 std::string SharedName =
5299 CGM.getOpenMPRuntime().getName({
"internal_pivate_", ReductionVarNameStr});
5300 llvm::GlobalVariable *SharedVar =
OMPBuilder.getOrCreateInternalVariable(
5301 LLVMType,
".omp.reduction." + SharedName);
5303 SharedVar->setAlignment(
5311 llvm::Value *BarrierArgs[] = {BarrierLoc, ThreadId};
5316 llvm::Value *IsWorker = CGF.
Builder.CreateICmpEQ(
5317 ThreadId, llvm::ConstantInt::get(ThreadId->getType(), 0));
5318 CGF.
Builder.CreateCondBr(IsWorker, InitBB, InitEndBB);
5322 auto EmitSharedInit = [&]() {
5325 std::pair<llvm::Function *, llvm::Function *> FnPair =
5327 llvm::Function *InitializerFn = FnPair.second;
5328 if (InitializerFn) {
5329 if (
const auto *CE =
5330 dyn_cast<CallExpr>(UDRInitExpr->IgnoreParenImpCasts())) {
5337 LocalScope.addPrivate(OutVD, SharedResult);
5339 (void)LocalScope.Privatize();
5340 if (
const auto *OVE = dyn_cast<OpaqueValueExpr>(
5341 CE->getCallee()->IgnoreParenImpCasts())) {
5367 if (
const auto *DRE = dyn_cast<DeclRefExpr>(
Privates)) {
5368 if (
const auto *VD = dyn_cast<VarDecl>(DRE->getDecl())) {
5379 CGF.
Builder.CreateBr(InitEndBB);
5383 CGM.getModule(), OMPRTL___kmpc_barrier),
5386 const Expr *ReductionOp = ReductionOps;
5391 auto EmitCriticalReduction = [&](
auto ReductionGen) {
5392 std::string CriticalName =
getName({
"reduction_critical"});
5400 std::pair<llvm::Function *, llvm::Function *> FnPair =
5403 if (
const auto *CE = dyn_cast<CallExpr>(ReductionOp)) {
5415 (void)LocalScope.Privatize();
5420 EmitCriticalReduction(ReductionGen);
5425 if (
const auto *Cleanup = dyn_cast<ExprWithCleanups>(ReductionClauseExpr))
5428 const Expr *AssignRHS =
nullptr;
5429 if (
const auto *BinOp = dyn_cast<BinaryOperator>(ReductionClauseExpr)) {
5430 if (BinOp->getOpcode() == BO_Assign)
5431 AssignRHS = BinOp->getRHS();
5432 }
else if (
const auto *OpCall =
5433 dyn_cast<CXXOperatorCallExpr>(ReductionClauseExpr)) {
5434 if (OpCall->getOperator() == OO_Equal)
5435 AssignRHS = OpCall->getArg(1);
5439 "Private Variable Reduction : Invalid ReductionOp expression");
5444 const auto *OmpOutDRE =
5446 const auto *OmpInDRE =
5449 OmpOutDRE && OmpInDRE &&
5450 "Private Variable Reduction : LHSExpr/RHSExpr must be DeclRefExprs");
5454 LocalScope.addPrivate(OmpOutVD, SharedLV.
getAddress());
5455 LocalScope.addPrivate(OmpInVD, LHSLV.
getAddress());
5456 (void)LocalScope.Privatize();
5460 EmitCriticalReduction(ReductionGen);
5464 CGM.getModule(), OMPRTL___kmpc_barrier),
5470 llvm::Value *FinalResultVal =
nullptr;
5474 FinalResultAddr = SharedResult;
5488 CGM.getModule(), OMPRTL___kmpc_barrier),
5499 EmitCriticalReduction(OriginalListCombiner);
5551 if (SimpleReduction) {
5553 const auto *IPriv = OrgPrivates.begin();
5554 const auto *ILHS = OrgLHSExprs.begin();
5555 const auto *IRHS = OrgRHSExprs.begin();
5556 for (
const Expr *E : OrgReductionOps) {
5569 FilteredRHSExprs, FilteredReductionOps;
5570 for (
unsigned I : llvm::seq<unsigned>(
5571 std::min(OrgReductionOps.size(), OrgLHSExprs.size()))) {
5573 FilteredPrivates.emplace_back(OrgPrivates[I]);
5574 FilteredLHSExprs.emplace_back(OrgLHSExprs[I]);
5575 FilteredRHSExprs.emplace_back(OrgRHSExprs[I]);
5576 FilteredReductionOps.emplace_back(OrgReductionOps[I]);
5588 auto Size = RHSExprs.size();
5594 llvm::APInt ArraySize(32, Size);
5595 QualType ReductionArrayTy =
C.getConstantArrayType(
5599 CGF.
CreateMemTemp(ReductionArrayTy,
".omp.reduction.red_list");
5600 const auto *IPriv =
Privates.begin();
5602 for (
unsigned I = 0, E = RHSExprs.size(); I < E; ++I, ++IPriv, ++Idx) {
5608 if ((*IPriv)->getType()->isVariablyModifiedType()) {
5612 llvm::Value *Size = CGF.
Builder.CreateIntCast(
5625 Privates, LHSExprs, RHSExprs, ReductionOps);
5628 std::string Name =
getName({
"reduction"});
5635 llvm::Value *ReductionArrayTySize = CGF.
getTypeSize(ReductionArrayTy);
5638 llvm::Value *Args[] = {
5641 CGF.
Builder.getInt32(RHSExprs.size()),
5642 ReductionArrayTySize,
5650 WithNowait ? OMPRTL___kmpc_reduce_nowait : OMPRTL___kmpc_reduce),
5654 llvm::BasicBlock *DefaultBB = CGF.
createBasicBlock(
".omp.reduction.default");
5655 llvm::SwitchInst *SwInst =
5656 CGF.
Builder.CreateSwitch(Res, DefaultBB, 2);
5665 SwInst->addCase(CGF.
Builder.getInt32(1), Case1BB);
5669 llvm::Value *EndArgs[] = {
5677 const auto *IPriv =
Privates.begin();
5678 const auto *ILHS = LHSExprs.begin();
5679 const auto *IRHS = RHSExprs.begin();
5680 for (
const Expr *E : ReductionOps) {
5689 CommonActionTy Action(
5692 CGM.getModule(), WithNowait ? OMPRTL___kmpc_end_reduce_nowait
5693 : OMPRTL___kmpc_end_reduce),
5706 SwInst->addCase(CGF.
Builder.getInt32(2), Case2BB);
5709 auto &&AtomicCodeGen = [Loc,
Privates, LHSExprs, RHSExprs, ReductionOps](
5711 const auto *ILHS = LHSExprs.begin();
5712 const auto *IRHS = RHSExprs.begin();
5713 const auto *IPriv =
Privates.begin();
5714 for (
const Expr *E : ReductionOps) {
5715 const Expr *XExpr =
nullptr;
5716 const Expr *EExpr =
nullptr;
5717 const Expr *UpExpr =
nullptr;
5719 if (
const auto *BO = dyn_cast<BinaryOperator>(E)) {
5720 if (BO->getOpcode() == BO_Assign) {
5721 XExpr = BO->getLHS();
5722 UpExpr = BO->getRHS();
5726 const Expr *RHSExpr = UpExpr;
5729 if (
const auto *ACO = dyn_cast<AbstractConditionalOperator>(
5733 RHSExpr = ACO->getCond();
5735 if (
const auto *BORHS =
5737 EExpr = BORHS->getRHS();
5738 BO = BORHS->getOpcode();
5743 auto &&AtomicRedGen = [BO, VD,
5745 const Expr *EExpr,
const Expr *UpExpr) {
5746 LValue X = CGF.EmitLValue(XExpr);
5749 E = CGF.EmitAnyExpr(EExpr);
5750 CGF.EmitOMPAtomicSimpleUpdateExpr(
5752 llvm::AtomicOrdering::Monotonic, Loc,
5753 [&CGF, UpExpr, VD, Loc](
RValue XRValue) {
5755 Address LHSTemp = CGF.CreateMemTemp(VD->getType());
5756 CGF.emitOMPSimpleStore(
5757 CGF.MakeAddrLValue(LHSTemp, VD->
getType()), XRValue,
5758 VD->getType().getNonReferenceType(), Loc);
5761 return CGF.EmitAnyExpr(UpExpr);
5764 if ((*IPriv)->getType()->isArrayType()) {
5766 const auto *RHSVar =
5769 AtomicRedGen, XExpr, EExpr, UpExpr);
5772 AtomicRedGen(CGF, XExpr, EExpr, UpExpr);
5779 std::string Name = RT.
getName({
"atomic_reduction"});
5788 if ((*IPriv)->getType()->isArrayType()) {
5789 const auto *LHSVar =
5791 const auto *RHSVar =
5796 CritRedGen(CGF,
nullptr,
nullptr,
nullptr);
5807 llvm::Value *EndArgs[] = {
5812 CommonActionTy Action(
nullptr, {},
5814 CGM.getModule(), OMPRTL___kmpc_end_reduce),
5824 assert(OrgLHSExprs.size() == OrgPrivates.size() &&
5825 "PrivateVarReduction: Privates size mismatch");
5826 assert(OrgLHSExprs.size() == OrgReductionOps.size() &&
5827 "PrivateVarReduction: ReductionOps size mismatch");
5828 for (
unsigned I : llvm::seq<unsigned>(
5829 std::min(OrgReductionOps.size(), OrgLHSExprs.size()))) {
5832 OrgRHSExprs[I], OrgReductionOps[I]);
5841 llvm::raw_svector_ostream Out(Buffer);
5846 if (
const auto *BD = dyn_cast<BindingDecl>(DRE->getDecl())) {
5856 Out << Prefix << Name <<
"_"
5858 return std::string(Out.str());
5882 Args.emplace_back(Param);
5883 Args.emplace_back(ParamOrig);
5884 const auto &FnInfo =
5888 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
5892 Fn->addFnAttr(
"sample-profile-suffix-elision-policy",
"selected");
5893 Fn->setDoesNotRecurse();
5900 llvm::Value *Size =
nullptr;
5943 const Expr *ReductionOp,
5945 const Expr *PrivateRef) {
5956 Args.emplace_back(ParamInOut);
5957 Args.emplace_back(ParamIn);
5958 const auto &FnInfo =
5962 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
5966 Fn->addFnAttr(
"sample-profile-suffix-elision-policy",
"selected");
5967 Fn->setDoesNotRecurse();
5970 llvm::Value *Size =
nullptr;
5991 C.getPointerType(LHSVD->getType())->castAs<
PointerType>()));
5998 C.getPointerType(RHSVD->getType())->castAs<
PointerType>()));
6028 Args.emplace_back(Param);
6029 const auto &FnInfo =
6033 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
6037 Fn->addFnAttr(
"sample-profile-suffix-elision-policy",
"selected");
6038 Fn->setDoesNotRecurse();
6043 llvm::Value *Size =
nullptr;
6078 RecordDecl *RD =
C.buildImplicitRecord(
"kmp_taskred_input_t");
6087 C, RD,
C.getIntTypeForBitwidth(32,
false));
6090 unsigned Size =
Data.ReductionVars.size();
6091 llvm::APInt ArraySize(64, Size);
6093 C.getConstantArrayType(RDType, ArraySize,
nullptr,
6098 Data.ReductionCopies,
Data.ReductionOps);
6099 for (
unsigned Cnt = 0; Cnt < Size; ++Cnt) {
6101 llvm::Value *Idxs[] = {llvm::ConstantInt::get(
CGM.SizeTy, 0),
6102 llvm::ConstantInt::get(
CGM.SizeTy, Cnt)};
6118 llvm::Value *SizeValInChars;
6119 llvm::Value *SizeVal;
6120 std::tie(SizeValInChars, SizeVal) = RCG.
getSizes(Cnt);
6126 bool DelayedCreation = !!SizeVal;
6127 SizeValInChars = CGF.
Builder.CreateIntCast(SizeValInChars,
CGM.SizeTy,
6138 llvm::Value *FiniAddr =
6139 Fini ? Fini : llvm::ConstantPointerNull::get(
CGM.VoidPtrTy);
6144 CGM, Loc, RCG, Cnt,
Data.ReductionOps[Cnt], LHSExprs[Cnt],
6145 RHSExprs[Cnt],
Data.ReductionCopies[Cnt]);
6149 if (DelayedCreation) {
6151 llvm::ConstantInt::get(
CGM.Int32Ty, 1,
true),
6156 if (
Data.IsReductionWithTaskMod) {
6162 llvm::Value *Args[] = {
6164 llvm::ConstantInt::get(
CGM.IntTy,
Data.IsWorksharingReduction ? 1 : 0,
6166 llvm::ConstantInt::get(
CGM.IntTy, Size,
true),
6171 CGM.getModule(), OMPRTL___kmpc_taskred_modifier_init),
6175 llvm::Value *Args[] = {
6178 llvm::ConstantInt::get(
CGM.IntTy, Size,
true),
6182 CGM.getModule(), OMPRTL___kmpc_taskred_init),
6188 bool IsWorksharingReduction) {
6194 llvm::Value *Args[] = {IdentTLoc, GTid,
6195 llvm::ConstantInt::get(
CGM.IntTy,
6196 IsWorksharingReduction ? 1 : 0,
6200 CGM.getModule(), OMPRTL___kmpc_task_reduction_modifier_fini),
6212 llvm::Value *SizeVal = CGF.
Builder.CreateIntCast(Sizes.second,
CGM.SizeTy,
6215 CGF,
CGM.getContext().getSizeType(),
6223 llvm::Value *ReductionsPtr,
6236 CGM.getModule(), OMPRTL___kmpc_task_reduction_get_th_data),
6252 auto &M =
CGM.getModule();
6254 llvm::Value *NumOfElements;
6255 std::tie(NumOfElements, DependenciesArray) =
6257 if (!
Data.Dependences.empty()) {
6258 llvm::Value *DepWaitTaskArgs[7];
6259 DepWaitTaskArgs[0] = UpLoc;
6260 DepWaitTaskArgs[1] = ThreadID;
6261 DepWaitTaskArgs[2] = NumOfElements;
6263 DepWaitTaskArgs[4] = CGF.
Builder.getInt32(0);
6264 DepWaitTaskArgs[5] = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
6265 DepWaitTaskArgs[6] =
6266 llvm::ConstantInt::get(CGF.
Int32Ty,
Data.HasNowaitClause);
6275 M, OMPRTL___kmpc_omp_taskwait_deps_51),
6282 llvm::Value *Args[] = {UpLoc, ThreadID};
6285 OMPBuilder.getOrCreateRuntimeFunction(M, OMPRTL___kmpc_omp_taskwait),
6290 if (
auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.
CapturedStmtInfo))
6291 Region->emitUntiedSwitch(CGF);
6300 InlinedOpenMPRegionRAII Region(CGF,
CodeGen, InnerKind, HasCancel,
6301 InnerKind != OMPD_critical &&
6302 InnerKind != OMPD_master &&
6303 InnerKind != OMPD_masked);
6318 RTCancelKind CancelKind = CancelNoreq;
6319 if (CancelRegion == OMPD_parallel)
6320 CancelKind = CancelParallel;
6321 else if (CancelRegion == OMPD_for)
6322 CancelKind = CancelLoop;
6323 else if (CancelRegion == OMPD_sections)
6324 CancelKind = CancelSections;
6326 assert(CancelRegion == OMPD_taskgroup);
6327 CancelKind = CancelTaskgroup;
6339 if (
auto *OMPRegionInfo =
6343 if (CancelRegion == OMPD_taskgroup || OMPRegionInfo->hasCancel()) {
6344 llvm::Value *Args[] = {
6350 CGM.getModule(), OMPRTL___kmpc_cancellationpoint),
6359 CGF.
Builder.CreateCondBr(
Cmp, ExitBB, ContBB);
6361 if (CancelRegion == OMPD_parallel)
6379 auto &M =
CGM.getModule();
6380 if (
auto *OMPRegionInfo =
6382 auto &&ThenGen = [
this, &M, Loc, CancelRegion,
6385 llvm::Value *Args[] = {
6389 llvm::Value *
Result = CGF.EmitRuntimeCall(
6390 OMPBuilder.getOrCreateRuntimeFunction(M, OMPRTL___kmpc_cancel), Args);
6395 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(
".cancel.exit");
6396 llvm::BasicBlock *ContBB = CGF.createBasicBlock(
".cancel.continue");
6397 llvm::Value *
Cmp = CGF.Builder.CreateIsNotNull(
Result);
6398 CGF.Builder.CreateCondBr(
Cmp, ExitBB, ContBB);
6399 CGF.EmitBlock(ExitBB);
6400 if (CancelRegion == OMPD_parallel)
6404 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind());
6405 CGF.EmitBranchThroughCleanup(CancelDest);
6406 CGF.EmitBlock(ContBB,
true);
6423 bool IsOffloadEntry;
6426 OMPUsesAllocatorsActionTy(
6427 ArrayRef<std::pair<const Expr *, const Expr *>> Allocators,
6429 : Allocators(Allocators), D(D), IsOffloadEntry(IsOffloadEntry) {}
6433 for (
const auto &AllocatorData : Allocators) {
6435 CGF, AllocatorData.first, AllocatorData.second);
6444 void Exit(CodeGenFunction &CGF)
override {
6447 for (
const auto &AllocatorData : Allocators) {
6449 AllocatorData.first);
6457 llvm::OpenMPIRBuilder::TargetKernelDefaultAttrs Attrs;
6458 Attrs.ExecFlags = llvm::omp::OMPTgtExecModeFlags::OMP_TGT_EXEC_MODE_GENERIC;
6465 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
6467 assert(!ParentName.empty() &&
"Invalid target entry parent name!");
6471 for (
unsigned I = 0, E =
C->getNumberOfAllocators(); I < E; ++I) {
6478 OMPUsesAllocatorsActionTy UsesAllocatorAction(Allocators, D, IsOffloadEntry);
6479 CodeGen.setAction(UsesAllocatorAction);
6485 const Expr *Allocator,
6486 const Expr *AllocatorTraits) {
6488 ThreadId = CGF.
Builder.CreateIntCast(ThreadId, CGF.
IntTy,
true);
6490 llvm::Value *MemSpaceHandle = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
6491 llvm::Value *NumTraits = llvm::ConstantInt::get(
6495 .getLimitedValue());
6502 llvm::Value *Traits =
Addr.emitRawPointer(CGF);
6504 llvm::Value *AllocatorVal =
6506 CGM.getModule(), OMPRTL___kmpc_init_allocator),
6507 {ThreadId, MemSpaceHandle, NumTraits, Traits});
6519 const Expr *Allocator) {
6521 ThreadId = CGF.
Builder.CreateIntCast(ThreadId, CGF.
IntTy,
true);
6523 llvm::Value *AllocatorVal =
6530 OMPRTL___kmpc_destroy_allocator),
6531 {ThreadId, AllocatorVal});
6536 llvm::OpenMPIRBuilder::TargetKernelDefaultAttrs &Attrs) {
6537 assert(Attrs.MaxTeams.size() == 1 && Attrs.MaxThreads.size() == 1 &&
6538 "invalid default attrs structure");
6539 int32_t &MaxTeamsVal = Attrs.MaxTeams.front();
6540 int32_t &MaxThreadsVal = Attrs.MaxThreads.front();
6548 for (
auto *A :
C->getAttrs()) {
6549 int32_t AttrMinThreadsVal = 1, AttrMaxThreadsVal = -1;
6550 int32_t AttrMinBlocksVal = 1, AttrMaxBlocksVal = -1;
6551 if (
auto *
Attr = dyn_cast<CUDALaunchBoundsAttr>(A))
6552 CGM.handleCUDALaunchBoundsAttr(
nullptr,
Attr, &AttrMaxThreadsVal,
6553 &AttrMinBlocksVal, &AttrMaxBlocksVal);
6554 else if (
auto *
Attr = dyn_cast<AMDGPUFlatWorkGroupSizeAttr>(A))
6555 CGM.handleAMDGPUFlatWorkGroupSizeAttr(
6556 nullptr,
Attr,
nullptr, &AttrMinThreadsVal,
6557 &AttrMaxThreadsVal);
6561 Attrs.MinThreads.front() =
6562 std::max(Attrs.MinThreads.front(), AttrMinThreadsVal);
6563 if (AttrMaxThreadsVal > 0)
6564 MaxThreadsVal = MaxThreadsVal > 0
6565 ? std::min(MaxThreadsVal, AttrMaxThreadsVal)
6566 : AttrMaxThreadsVal;
6567 Attrs.MinTeams.front() =
6568 std::max(Attrs.MinTeams.front(), AttrMinBlocksVal);
6569 if (AttrMaxBlocksVal > 0)
6570 MaxTeamsVal = MaxTeamsVal > 0 ? std::min(MaxTeamsVal, AttrMaxBlocksVal)
6578 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
6581 llvm::TargetRegionEntryInfo EntryInfo =
6585 llvm::OpenMPIRBuilder::FunctionGenCallback &&GenerateOutlinedFunction =
6586 [&CGF, &D, &
CodeGen,
this](StringRef EntryFnName) {
6587 const CapturedStmt &CS = *D.getCapturedStmt(OMPD_target);
6589 CGOpenMPTargetRegionInfo CGInfo(CS,
CodeGen, EntryFnName);
6591 if (
CGM.getLangOpts().OpenMPIsTargetDevice && !
isGPU())
6596 cantFail(
OMPBuilder.emitTargetRegionFunction(
6597 EntryInfo, GenerateOutlinedFunction, IsOffloadEntry, OutlinedFn,
6605 OutlinedFn->setDoesNotRecurse();
6607 CGM.getTargetCodeGenInfo().setTargetAttributes(
nullptr, OutlinedFn,
CGM);
6610 for (
auto *A :
C->getAttrs()) {
6611 if (
auto *
Attr = dyn_cast<AMDGPUWavesPerEUAttr>(A))
6612 CGM.handleAMDGPUWavesPerEUAttr(OutlinedFn,
Attr);
6631 while (
const auto *
C = dyn_cast_or_null<CompoundStmt>(Child)) {
6633 for (
const Stmt *S :
C->body()) {
6634 if (
const auto *E = dyn_cast<Expr>(S)) {
6643 if (
const auto *DS = dyn_cast<DeclStmt>(S)) {
6644 if (llvm::all_of(DS->decls(), [](
const Decl *D) {
6645 if (isa<EmptyDecl>(D) || isa<DeclContext>(D) ||
6646 isa<TypeDecl>(D) || isa<PragmaCommentDecl>(D) ||
6647 isa<PragmaDetectMismatchDecl>(D) || isa<UsingDecl>(D) ||
6648 isa<UsingDirectiveDecl>(D) ||
6649 isa<OMPDeclareReductionDecl>(D) ||
6650 isa<OMPThreadPrivateDecl>(D) || isa<OMPAllocateDecl>(D))
6652 const auto *VD = dyn_cast<VarDecl>(D);
6655 return VD->hasGlobalStorage() || !VD->isUsed();
6665 Child = Child->IgnoreContainers();
6672 int32_t &MaxTeamsVal) {
6676 "Expected target-based executable directive.");
6677 switch (DirectiveKind) {
6679 const auto *CS = D.getInnermostCapturedStmt();
6682 const Stmt *ChildStmt =
6684 if (
const auto *NestedDir =
6685 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) {
6694 MinTeamsVal = MaxTeamsVal =
Constant->getExtValue();
6697 MinTeamsVal = MaxTeamsVal = 0;
6700 MinTeamsVal = MaxTeamsVal = 1;
6704 MinTeamsVal = MaxTeamsVal = -1;
6707 case OMPD_target_teams_loop:
6708 case OMPD_target_teams:
6709 case OMPD_target_teams_distribute:
6710 case OMPD_target_teams_distribute_simd:
6711 case OMPD_target_teams_distribute_parallel_for:
6712 case OMPD_target_teams_distribute_parallel_for_simd: {
6714 const Expr *NumTeams =
6718 MinTeamsVal = MaxTeamsVal =
Constant->getExtValue();
6721 MinTeamsVal = MaxTeamsVal = 0;
6724 case OMPD_target_parallel:
6725 case OMPD_target_parallel_for:
6726 case OMPD_target_parallel_for_simd:
6727 case OMPD_target_parallel_loop:
6728 case OMPD_target_simd:
6729 MinTeamsVal = MaxTeamsVal = 1;
6733 case OMPD_parallel_for:
6734 case OMPD_parallel_loop:
6735 case OMPD_parallel_master:
6736 case OMPD_parallel_sections:
6738 case OMPD_parallel_for_simd:
6740 case OMPD_cancellation_point:
6741 case OMPD_ordered_standalone:
6742 case OMPD_ordered_blockassoc:
6743 case OMPD_threadprivate:
6754 case OMPD_taskyield:
6757 case OMPD_taskgroup:
6763 case OMPD_target_data:
6764 case OMPD_target_exit_data:
6765 case OMPD_target_enter_data:
6766 case OMPD_distribute:
6767 case OMPD_distribute_simd:
6768 case OMPD_distribute_parallel_for:
6769 case OMPD_distribute_parallel_for_simd:
6770 case OMPD_teams_distribute:
6771 case OMPD_teams_distribute_simd:
6772 case OMPD_teams_distribute_parallel_for:
6773 case OMPD_teams_distribute_parallel_for_simd:
6774 case OMPD_target_update:
6775 case OMPD_declare_simd:
6776 case OMPD_declare_variant:
6777 case OMPD_begin_declare_variant:
6778 case OMPD_end_declare_variant:
6779 case OMPD_declare_target:
6780 case OMPD_end_declare_target:
6781 case OMPD_declare_reduction:
6782 case OMPD_declare_mapper:
6784 case OMPD_taskloop_simd:
6785 case OMPD_master_taskloop:
6786 case OMPD_master_taskloop_simd:
6787 case OMPD_parallel_master_taskloop:
6788 case OMPD_parallel_master_taskloop_simd:
6790 case OMPD_metadirective:
6796 llvm_unreachable(
"Unexpected directive kind.");
6802 "Clauses associated with the teams directive expected to be emitted "
6803 "only for the host!");
6805 int32_t MinNT = -1, MaxNT = -1;
6806 const Expr *NumTeams =
6808 if (NumTeams !=
nullptr) {
6811 switch (DirectiveKind) {
6813 const auto *CS = D.getInnermostCapturedStmt();
6814 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6818 return Bld.CreateIntCast(NumTeamsVal, CGF.
Int32Ty,
6821 case OMPD_target_teams:
6822 case OMPD_target_teams_distribute:
6823 case OMPD_target_teams_distribute_simd:
6824 case OMPD_target_teams_distribute_parallel_for:
6825 case OMPD_target_teams_distribute_parallel_for_simd: {
6829 return Bld.CreateIntCast(NumTeamsVal, CGF.
Int32Ty,
6837 assert(MinNT == MaxNT &&
"Num threads ranges require handling here.");
6838 return llvm::ConstantInt::getSigned(CGF.
Int32Ty, MinNT);
6852 UpperBound = UpperBound > 0 ? std::min(UpperBound, Val) : Val;
6861 bool UpperBoundOnly, llvm::Value **CondVal) {
6864 const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child);
6871 if (CondVal && Dir->hasClausesOfKind<
OMPIfClause>()) {
6872 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6875 for (
const auto *
C : Dir->getClausesOfKind<
OMPIfClause>()) {
6876 if (
C->getNameModifier() == OMPD_unknown ||
6877 C->getNameModifier() == OMPD_parallel) {
6892 if (
const auto *PreInit =
6894 for (
const auto *I : PreInit->decls()) {
6895 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
6911 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6913 const auto *NumThreadsClause =
6915 const Expr *NTExpr = NumThreadsClause->getNumThreads().front();
6916 if (NTExpr->isIntegerConstantExpr(CGF.
getContext()))
6922 if (UpperBound == -1)
6927 if (
const auto *PreInit =
6928 cast_or_null<DeclStmt>(NumThreadsClause->getPreInitStmt())) {
6929 for (
const auto *I : PreInit->decls()) {
6930 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
6949 bool UpperBoundOnly, llvm::Value **CondVal,
const Expr **ThreadLimitExpr) {
6950 assert((!CGF.
getLangOpts().OpenMPIsTargetDevice || UpperBoundOnly) &&
6951 "Clauses associated with the teams directive expected to be emitted "
6952 "only for the host!");
6955 "Expected target-based executable directive.");
6957 const Expr *NT =
nullptr;
6958 const Expr **NTPtr = UpperBoundOnly ?
nullptr : &NT;
6960 auto CheckForConstExpr = [&](
const Expr *E,
const Expr **EPtr) {
6964 UpperBound,
static_cast<int32_t
>(
Constant->getZExtValue()));
6968 if (UpperBound == -1)
6974 auto ReturnSequential = [&]() {
6979 switch (DirectiveKind) {
6982 getNumThreads(CGF, CS, NTPtr, UpperBound, UpperBoundOnly, CondVal);
6988 if (
const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) {
6990 ThreadLimitClause = TLC;
6991 if (ThreadLimitExpr) {
6992 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6996 ThreadLimitClause->getThreadLimit().front()->getSourceRange());
6997 if (
const auto *PreInit =
6998 cast_or_null<DeclStmt>(ThreadLimitClause->getPreInitStmt())) {
6999 for (
const auto *I : PreInit->decls()) {
7000 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
7012 if (ThreadLimitClause)
7013 CheckForConstExpr(ThreadLimitClause->getThreadLimit().front(),
7015 if (
const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) {
7018 CS = Dir->getInnermostCapturedStmt();
7032 Dir = dyn_cast_or_null<OMPExecutableDirective>(Child);
7035 CS = Dir->getInnermostCapturedStmt();
7036 getNumThreads(CGF, CS, NTPtr, UpperBound, UpperBoundOnly, CondVal);
7038 return ReturnSequential();
7042 case OMPD_target_teams: {
7046 CheckForConstExpr(ThreadLimitClause->getThreadLimit().front(),
7050 getNumThreads(CGF, CS, NTPtr, UpperBound, UpperBoundOnly, CondVal);
7053 if (
const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) {
7054 if (Dir->getDirectiveKind() == OMPD_distribute) {
7055 CS = Dir->getInnermostCapturedStmt();
7056 getNumThreads(CGF, CS, NTPtr, UpperBound, UpperBoundOnly, CondVal);
7061 case OMPD_target_teams_distribute:
7065 CheckForConstExpr(ThreadLimitClause->getThreadLimit().front(),
7068 getNumThreads(CGF, D.getInnermostCapturedStmt(), NTPtr, UpperBound,
7069 UpperBoundOnly, CondVal);
7071 case OMPD_target_teams_loop:
7072 case OMPD_target_parallel_loop:
7073 case OMPD_target_parallel:
7074 case OMPD_target_parallel_for:
7075 case OMPD_target_parallel_for_simd:
7076 case OMPD_target_teams_distribute_parallel_for:
7077 case OMPD_target_teams_distribute_parallel_for_simd: {
7078 if (CondVal && D.hasClausesOfKind<
OMPIfClause>()) {
7080 for (
const auto *
C : D.getClausesOfKind<
OMPIfClause>()) {
7081 if (
C->getNameModifier() == OMPD_unknown ||
7082 C->getNameModifier() == OMPD_parallel) {
7092 return ReturnSequential();
7102 CheckForConstExpr(ThreadLimitClause->getThreadLimit().front(),
7108 CheckForConstExpr(NumThreadsClause->getNumThreads().front(),
nullptr);
7109 return NumThreadsClause->getNumThreads().front();
7113 case OMPD_target_teams_distribute_simd:
7114 case OMPD_target_simd:
7115 return ReturnSequential();
7119 llvm_unreachable(
"Unsupported directive kind.");
7124 llvm::Value *NumThreadsVal =
nullptr;
7125 llvm::Value *CondVal =
nullptr;
7126 llvm::Value *ThreadLimitVal =
nullptr;
7127 const Expr *ThreadLimitExpr =
nullptr;
7128 int32_t UpperBound = -1;
7131 CGF, D, UpperBound,
false, &CondVal,
7135 if (ThreadLimitExpr) {
7138 ThreadLimitVal = CGF.
Builder.CreateIntCast(ThreadLimitVal, CGF.
Int32Ty,
7143 if (UpperBound == 1) {
7144 NumThreadsVal = CGF.
Builder.getInt32(UpperBound);
7147 NumThreadsVal = CGF.
Builder.CreateIntCast(NumThreadsVal, CGF.
Int32Ty,
7149 }
else if (ThreadLimitVal) {
7152 NumThreadsVal = ThreadLimitVal;
7153 ThreadLimitVal =
nullptr;
7156 assert(!ThreadLimitVal &&
"Default not applicable with thread limit value");
7157 NumThreadsVal = CGF.
Builder.getInt32(0);
7164 NumThreadsVal = CGF.
Builder.CreateSelect(CondVal, NumThreadsVal,
7170 if (ThreadLimitVal) {
7171 NumThreadsVal = CGF.
Builder.CreateSelect(
7172 CGF.
Builder.CreateICmpULT(ThreadLimitVal, NumThreadsVal),
7173 ThreadLimitVal, NumThreadsVal);
7176 return NumThreadsVal;
7186class MappableExprsHandler {
7192 struct AttachPtrExprComparator {
7193 const MappableExprsHandler &Handler;
7195 mutable llvm::DenseMap<std::pair<const Expr *, const Expr *>,
bool>
7196 CachedEqualityComparisons;
7198 AttachPtrExprComparator(
const MappableExprsHandler &H) : Handler(H) {}
7199 AttachPtrExprComparator() =
delete;
7202 bool operator()(
const Expr *LHS,
const Expr *RHS)
const {
7207 const auto ItLHS = Handler.AttachPtrComponentDepthMap.find(LHS);
7208 const auto ItRHS = Handler.AttachPtrComponentDepthMap.find(RHS);
7210 std::optional<size_t> DepthLHS =
7211 (ItLHS != Handler.AttachPtrComponentDepthMap.end()) ? ItLHS->second
7213 std::optional<size_t> DepthRHS =
7214 (ItRHS != Handler.AttachPtrComponentDepthMap.end()) ? ItRHS->second
7218 if (!DepthLHS.has_value() && !DepthRHS.has_value()) {
7220 if (areEqual(LHS, RHS))
7223 return wasComputedBefore(LHS, RHS);
7225 if (!DepthLHS.has_value())
7227 if (!DepthRHS.has_value())
7231 if (DepthLHS.value() != DepthRHS.value())
7232 return DepthLHS.value() < DepthRHS.value();
7235 if (areEqual(LHS, RHS))
7238 return wasComputedBefore(LHS, RHS);
7244 bool areEqual(
const Expr *LHS,
const Expr *RHS)
const {
7246 const auto CachedResultIt = CachedEqualityComparisons.find({LHS, RHS});
7247 if (CachedResultIt != CachedEqualityComparisons.end())
7248 return CachedResultIt->second;
7262 bool wasComputedBefore(
const Expr *LHS,
const Expr *RHS)
const {
7263 const size_t &OrderLHS = Handler.AttachPtrComputationOrderMap.at(LHS);
7264 const size_t &OrderRHS = Handler.AttachPtrComputationOrderMap.at(RHS);
7266 return OrderLHS < OrderRHS;
7275 bool areSemanticallyEqual(
const Expr *LHS,
const Expr *RHS)
const {
7297 if (
const auto *LD = dyn_cast<DeclRefExpr>(LHS)) {
7298 const auto *RD = dyn_cast<DeclRefExpr>(RHS);
7301 return LD->getDecl()->getCanonicalDecl() ==
7302 RD->getDecl()->getCanonicalDecl();
7306 if (
const auto *LA = dyn_cast<ArraySubscriptExpr>(LHS)) {
7307 const auto *RA = dyn_cast<ArraySubscriptExpr>(RHS);
7310 return areSemanticallyEqual(LA->getBase(), RA->getBase()) &&
7311 areSemanticallyEqual(LA->getIdx(), RA->getIdx());
7315 if (
const auto *LM = dyn_cast<MemberExpr>(LHS)) {
7316 const auto *RM = dyn_cast<MemberExpr>(RHS);
7319 if (LM->getMemberDecl()->getCanonicalDecl() !=
7320 RM->getMemberDecl()->getCanonicalDecl())
7322 return areSemanticallyEqual(LM->getBase(), RM->getBase());
7326 if (
const auto *LU = dyn_cast<UnaryOperator>(LHS)) {
7327 const auto *RU = dyn_cast<UnaryOperator>(RHS);
7330 if (LU->getOpcode() != RU->getOpcode())
7332 return areSemanticallyEqual(LU->getSubExpr(), RU->getSubExpr());
7336 if (
const auto *LB = dyn_cast<BinaryOperator>(LHS)) {
7337 const auto *RB = dyn_cast<BinaryOperator>(RHS);
7340 if (LB->getOpcode() != RB->getOpcode())
7342 return areSemanticallyEqual(LB->getLHS(), RB->getLHS()) &&
7343 areSemanticallyEqual(LB->getRHS(), RB->getRHS());
7349 if (
const auto *LAS = dyn_cast<ArraySectionExpr>(LHS)) {
7350 const auto *RAS = dyn_cast<ArraySectionExpr>(RHS);
7353 return areSemanticallyEqual(LAS->getBase(), RAS->getBase()) &&
7354 areSemanticallyEqual(LAS->getLowerBound(),
7355 RAS->getLowerBound()) &&
7356 areSemanticallyEqual(LAS->getLength(), RAS->getLength());
7360 if (
const auto *LC = dyn_cast<CastExpr>(LHS)) {
7361 const auto *RC = dyn_cast<CastExpr>(RHS);
7364 if (LC->getCastKind() != RC->getCastKind())
7366 return areSemanticallyEqual(LC->getSubExpr(), RC->getSubExpr());
7374 if (
const auto *LI = dyn_cast<IntegerLiteral>(LHS)) {
7375 const auto *RI = dyn_cast<IntegerLiteral>(RHS);
7378 return LI->getValue() == RI->getValue();
7382 if (
const auto *LC = dyn_cast<CharacterLiteral>(LHS)) {
7383 const auto *RC = dyn_cast<CharacterLiteral>(RHS);
7386 return LC->getValue() == RC->getValue();
7390 if (
const auto *LF = dyn_cast<FloatingLiteral>(LHS)) {
7391 const auto *RF = dyn_cast<FloatingLiteral>(RHS);
7395 return LF->getValue().bitwiseIsEqual(RF->getValue());
7399 if (
const auto *LS = dyn_cast<StringLiteral>(LHS)) {
7400 const auto *RS = dyn_cast<StringLiteral>(RHS);
7403 return LS->getString() == RS->getString();
7411 if (
const auto *LB = dyn_cast<CXXBoolLiteralExpr>(LHS)) {
7412 const auto *RB = dyn_cast<CXXBoolLiteralExpr>(RHS);
7415 return LB->getValue() == RB->getValue();
7424 static unsigned getFlagMemberOffset() {
7425 unsigned Offset = 0;
7426 for (uint64_t Remain =
7427 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
7428 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF);
7429 !(Remain & 1); Remain = Remain >> 1)
7436 class MappingExprInfo {
7438 const ValueDecl *MapDecl =
nullptr;
7441 const Expr *MapExpr =
nullptr;
7444 MappingExprInfo(
const ValueDecl *MapDecl,
const Expr *MapExpr =
nullptr)
7445 : MapDecl(MapDecl), MapExpr(MapExpr) {}
7447 const ValueDecl *getMapDecl()
const {
return MapDecl; }
7448 const Expr *getMapExpr()
const {
return MapExpr; }
7451 using DeviceInfoTy = llvm::OpenMPIRBuilder::DeviceInfoTy;
7452 using MapBaseValuesArrayTy = llvm::OpenMPIRBuilder::MapValuesArrayTy;
7453 using MapValuesArrayTy = llvm::OpenMPIRBuilder::MapValuesArrayTy;
7454 using MapFlagsArrayTy = llvm::OpenMPIRBuilder::MapFlagsArrayTy;
7455 using MapDimArrayTy = llvm::OpenMPIRBuilder::MapDimArrayTy;
7456 using MapNonContiguousArrayTy =
7457 llvm::OpenMPIRBuilder::MapNonContiguousArrayTy;
7458 using MapExprsArrayTy = SmallVector<MappingExprInfo, 4>;
7459 using MapValueDeclsArrayTy = SmallVector<const ValueDecl *, 4>;
7463 bool ,
const ValueDecl *,
const Expr *>;
7464 using MapDataArrayTy = SmallVector<MapData, 4>;
7469 struct MapCombinedInfoTy : llvm::OpenMPIRBuilder::MapInfosTy {
7470 MapExprsArrayTy Exprs;
7471 MapValueDeclsArrayTy Mappers;
7472 MapValueDeclsArrayTy DevicePtrDecls;
7475 void append(MapCombinedInfoTy &CurInfo) {
7476 Exprs.append(CurInfo.Exprs.begin(), CurInfo.Exprs.end());
7477 DevicePtrDecls.append(CurInfo.DevicePtrDecls.begin(),
7478 CurInfo.DevicePtrDecls.end());
7479 Mappers.append(CurInfo.Mappers.begin(), CurInfo.Mappers.end());
7480 llvm::OpenMPIRBuilder::MapInfosTy::append(CurInfo);
7488 struct StructRangeInfoTy {
7489 MapCombinedInfoTy PreliminaryMapData;
7490 std::pair<
unsigned ,
Address > LowestElem = {
7492 std::pair<
unsigned ,
Address > HighestElem = {
7496 bool IsArraySection =
false;
7497 bool HasCompleteRecord =
false;
7502 struct AttachInfoTy {
7505 const ValueDecl *AttachPtrDecl =
nullptr;
7506 const Expr *AttachMapExpr =
nullptr;
7508 bool isValid()
const {
7515 bool hasAttachEntryForCapturedVar(
const ValueDecl *VD)
const {
7516 for (
const auto &AttachEntry : AttachPtrExprMap) {
7517 if (AttachEntry.second) {
7520 if (
const auto *DRE = dyn_cast<DeclRefExpr>(AttachEntry.second))
7521 if (DRE->getDecl() == VD)
7529 const Expr *getAttachPtrExpr(
7532 const auto It = AttachPtrExprMap.find(Components);
7533 if (It != AttachPtrExprMap.end())
7544 ArrayRef<OpenMPMapModifierKind> MapModifiers;
7545 ArrayRef<OpenMPMotionModifierKind> MotionModifiers;
7546 bool ReturnDevicePointer =
false;
7547 bool IsImplicit =
false;
7548 const ValueDecl *Mapper =
nullptr;
7549 const Expr *VarRef =
nullptr;
7550 bool ForDeviceAddr =
false;
7551 bool HasUdpFbNullify =
false;
7553 MapInfo() =
default;
7557 ArrayRef<OpenMPMapModifierKind> MapModifiers,
7558 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
7559 bool ReturnDevicePointer,
bool IsImplicit,
7560 const ValueDecl *Mapper =
nullptr,
const Expr *VarRef =
nullptr,
7561 bool ForDeviceAddr =
false,
bool HasUdpFbNullify =
false)
7562 : Components(Components), MapType(MapType), MapModifiers(MapModifiers),
7563 MotionModifiers(MotionModifiers),
7564 ReturnDevicePointer(ReturnDevicePointer), IsImplicit(IsImplicit),
7565 Mapper(Mapper), VarRef(VarRef), ForDeviceAddr(ForDeviceAddr),
7566 HasUdpFbNullify(HasUdpFbNullify) {}
7571 llvm::PointerUnion<
const OMPExecutableDirective *,
7572 const OMPDeclareMapperDecl *>
7576 CodeGenFunction &CGF;
7581 llvm::DenseMap<CanonicalDeclPtr<const VarDecl>,
bool> FirstPrivateDecls;
7584 llvm::SmallSet<OpenMPDefaultmapClauseKind, 4> DefaultmapFirstprivateKinds;
7590 SmallVector<OMPClauseMappableExprCommon::MappableExprComponentListRef, 4>>
7597 SmallVector<OMPClauseMappableExprCommon::MappableExprComponentListRef, 4>>
7601 llvm::DenseMap<const ValueDecl *, const OMPMapClause *> LambdasMap;
7616 llvm::DenseMap<const Expr *, std::optional<size_t>>
7617 AttachPtrComponentDepthMap = {{
nullptr, std::nullopt}};
7621 llvm::DenseMap<const Expr *, size_t> AttachPtrComputationOrderMap = {
7626 AttachPtrExprComparator AttachPtrComparator;
7628 llvm::Value *getExprTypeSize(
const Expr *E)
const {
7632 if (
const auto *OAE = dyn_cast<OMPArrayShapingExpr>(E)) {
7634 CGF.
getTypeSize(OAE->getBase()->getType()->getPointeeType());
7635 for (
const Expr *SE : OAE->getDimensions()) {
7646 if (
const auto *RefTy =
ExprTy->getAs<ReferenceType>())
7647 ExprTy = RefTy->getPointeeType().getCanonicalType();
7652 if (
const auto *OAE = dyn_cast<ArraySectionExpr>(E)) {
7654 OAE->getBase()->IgnoreParenImpCasts())
7660 if (!OAE->getLength() && OAE->getColonLocFirst().isValid() &&
7661 !OAE->getLowerBound())
7664 llvm::Value *ElemSize;
7665 if (
const auto *PTy = BaseTy->
getAs<PointerType>()) {
7666 ElemSize = CGF.
getTypeSize(PTy->getPointeeType().getCanonicalType());
7669 assert(ATy &&
"Expecting array type if not a pointer type.");
7670 ElemSize = CGF.
getTypeSize(ATy->getElementType().getCanonicalType());
7675 if (!OAE->getLength() && OAE->getColonLocFirst().isInvalid())
7678 if (
const Expr *LenExpr = OAE->getLength()) {
7682 LenExpr->getExprLoc());
7683 return CGF.
Builder.CreateNUWMul(LengthVal, ElemSize);
7685 assert(!OAE->getLength() && OAE->getColonLocFirst().isValid() &&
7686 OAE->getLowerBound() &&
"expected array_section[lb:].");
7692 OAE->getLowerBound()->getExprLoc());
7693 LBVal = CGF.
Builder.CreateNUWMul(LBVal, ElemSize);
7694 llvm::Value *
Cmp = CGF.
Builder.CreateICmpUGT(LengthVal, LBVal);
7695 llvm::Value *TrueVal = CGF.
Builder.CreateNUWSub(LengthVal, LBVal);
7696 LengthVal = CGF.
Builder.CreateSelect(
7697 Cmp, TrueVal, llvm::ConstantInt::get(CGF.
SizeTy, 0));
7707 OpenMPOffloadMappingFlags getMapTypeBits(
7709 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
bool IsImplicit,
7710 bool AddPtrFlag,
bool AddIsTargetParamFlag,
bool IsNonContiguous)
const {
7711 OpenMPOffloadMappingFlags Bits =
7712 IsImplicit ? OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT
7713 : OpenMPOffloadMappingFlags::OMP_MAP_NONE;
7715 case OMPC_MAP_alloc:
7716 case OMPC_MAP_release:
7723 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_TO;
7726 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_FROM;
7728 case OMPC_MAP_tofrom:
7729 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_TO |
7730 OpenMPOffloadMappingFlags::OMP_MAP_FROM;
7732 case OMPC_MAP_delete:
7733 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_DELETE;
7736 llvm_unreachable(
"Unexpected map type!");
7739 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ;
7740 if (AddIsTargetParamFlag)
7741 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM;
7742 if (llvm::is_contained(MapModifiers, OMPC_MAP_MODIFIER_always))
7743 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_ALWAYS;
7744 if (llvm::is_contained(MapModifiers, OMPC_MAP_MODIFIER_close))
7745 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_CLOSE;
7746 if (llvm::is_contained(MapModifiers, OMPC_MAP_MODIFIER_present) ||
7747 llvm::is_contained(MotionModifiers, OMPC_MOTION_MODIFIER_present))
7748 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_PRESENT;
7749 if (llvm::is_contained(MapModifiers, OMPC_MAP_MODIFIER_ompx_hold))
7750 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_OMPX_HOLD;
7751 if (IsNonContiguous)
7752 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_NON_CONTIG;
7758 bool isFinalArraySectionExpression(
const Expr *E)
const {
7759 const auto *OASE = dyn_cast<ArraySectionExpr>(E);
7766 if (OASE->getColonLocFirst().isInvalid())
7769 const Expr *Length = OASE->getLength();
7776 OASE->getBase()->IgnoreParenImpCasts())
7778 if (
const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.
getTypePtr()))
7779 return ATy->getSExtSize() != 1;
7791 llvm::APSInt ConstLength =
Result.Val.getInt();
7792 return ConstLength.getSExtValue() != 1;
7799 void emitAttachEntry(CodeGenFunction &CGF, MapCombinedInfoTy &CombinedInfo,
7800 const AttachInfoTy &AttachInfo)
const {
7801 assert(AttachInfo.isValid() &&
7802 "Expected valid attach pointer/pointee information!");
7806 llvm::Value *PointerSize = CGF.
Builder.CreateIntCast(
7807 llvm::ConstantInt::get(
7813 CombinedInfo.Exprs.emplace_back(AttachInfo.AttachPtrDecl,
7814 AttachInfo.AttachMapExpr);
7815 CombinedInfo.BasePointers.push_back(
7816 AttachInfo.AttachPtrAddr.emitRawPointer(CGF));
7817 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
7818 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
7819 CombinedInfo.Pointers.push_back(
7820 AttachInfo.AttachPteeAddr.emitRawPointer(CGF));
7821 CombinedInfo.Sizes.push_back(PointerSize);
7822 CombinedInfo.Types.push_back(OpenMPOffloadMappingFlags::OMP_MAP_ATTACH);
7824 CombinedInfo.HasAttachPtr.push_back(
false);
7825 CombinedInfo.Mappers.push_back(
nullptr);
7826 CombinedInfo.NonContigInfo.Dims.push_back(1);
7833 class CopyOverlappedEntryGaps {
7834 CodeGenFunction &CGF;
7835 MapCombinedInfoTy &CombinedInfo;
7836 OpenMPOffloadMappingFlags Flags = OpenMPOffloadMappingFlags::OMP_MAP_NONE;
7837 const ValueDecl *MapDecl =
nullptr;
7838 const Expr *MapExpr =
nullptr;
7840 bool IsNonContiguous =
false;
7844 const RecordDecl *LastParent =
nullptr;
7846 unsigned LastIndex = -1u;
7850 CopyOverlappedEntryGaps(CodeGenFunction &CGF,
7851 MapCombinedInfoTy &CombinedInfo,
7852 OpenMPOffloadMappingFlags Flags,
7853 const ValueDecl *MapDecl,
const Expr *MapExpr,
7854 Address BP, Address LB,
bool IsNonContiguous,
7856 : CGF(CGF), CombinedInfo(CombinedInfo), Flags(Flags), MapDecl(MapDecl),
7857 MapExpr(MapExpr), BP(BP), IsNonContiguous(IsNonContiguous),
7858 DimSize(DimSize), LB(LB) {}
7861 const OMPClauseMappableExprCommon::MappableComponent &MC,
7862 const FieldDecl *FD,
7863 llvm::function_ref<LValue(CodeGenFunction &,
const MemberExpr *)>
7864 EmitMemberExprBase) {
7874 LValue BaseLVal = EmitMemberExprBase(CGF, ME);
7886 copyUntilField(FD, ComponentLB);
7889 if (((int64_t)FieldOffset - (int64_t)Cursor) > 0)
7890 copyUntilField(FD, ComponentLB);
7892 Cursor = FieldOffset + FieldSize;
7897 void copyUntilField(
const FieldDecl *FD, Address ComponentLB) {
7900 llvm::Value *
Size = CGF.
Builder.CreatePtrDiff(ComponentLBPtr, LBPtr);
7901 copySizedChunk(LBPtr, Size);
7904 void copyUntilEnd(Address HB) {
7906 const ASTRecordLayout &RL =
7914 copySizedChunk(LBPtr, Size);
7917 void copySizedChunk(llvm::Value *Base, llvm::Value *Size) {
7918 CombinedInfo.Exprs.emplace_back(MapDecl, MapExpr);
7920 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
7921 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
7922 CombinedInfo.Pointers.push_back(Base);
7923 CombinedInfo.Sizes.push_back(
7925 CombinedInfo.Types.push_back(Flags);
7926 CombinedInfo.HasAttachPtr.push_back(
false);
7927 CombinedInfo.Mappers.push_back(
nullptr);
7928 CombinedInfo.NonContigInfo.Dims.push_back(IsNonContiguous ? DimSize : 1);
7937 void generateInfoForComponentList(
7939 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
7941 MapCombinedInfoTy &CombinedInfo,
7942 MapCombinedInfoTy &StructBaseCombinedInfo,
7943 StructRangeInfoTy &PartialStruct, AttachInfoTy &AttachInfo,
7944 bool IsFirstComponentList,
bool IsImplicit,
7945 bool GenerateAllInfoForClauses,
const ValueDecl *Mapper =
nullptr,
7946 bool ForDeviceAddr =
false,
const ValueDecl *BaseDecl =
nullptr,
7947 const Expr *MapExpr =
nullptr,
7948 ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef>
7949 OverlappedElements = {})
const {
8167 bool IsCaptureFirstInfo = IsFirstComponentList;
8171 bool RequiresReference =
false;
8174 auto CI = Components.rbegin();
8175 auto CE = Components.rend();
8180 bool IsExpressionFirstInfo =
true;
8181 bool FirstPointerInComplexData =
false;
8184 const Expr *AssocExpr = I->getAssociatedExpression();
8185 const auto *AE = dyn_cast<ArraySubscriptExpr>(AssocExpr);
8186 const auto *OASE = dyn_cast<ArraySectionExpr>(AssocExpr);
8187 const auto *OAShE = dyn_cast<OMPArrayShapingExpr>(AssocExpr);
8190 const Expr *AttachPtrExpr = getAttachPtrExpr(Components);
8191 auto [AttachPtrAddr, AttachPteeBaseAddr] =
8192 getAttachPtrAddrAndPteeBaseAddr(AttachPtrExpr, CGF);
8194 bool HasAttachPtr = AttachPtrExpr !=
nullptr;
8195 bool FirstComponentIsForAttachPtr = AssocExpr == AttachPtrExpr;
8196 bool SeenAttachPtr = FirstComponentIsForAttachPtr;
8198 if (FirstComponentIsForAttachPtr) {
8206 }
else if ((AE &&
isa<CXXThisExpr>(AE->getBase()->IgnoreParenImpCasts())) ||
8220 if (
const auto *VD =
8221 dyn_cast_or_null<VarDecl>(I->getAssociatedDeclaration())) {
8222 if (std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
8223 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD)) {
8224 if ((*Res == OMPDeclareTargetDeclAttr::MT_Link) ||
8225 ((*Res == OMPDeclareTargetDeclAttr::MT_To ||
8226 *Res == OMPDeclareTargetDeclAttr::MT_Enter) &&
8228 RequiresReference =
true;
8238 I->getAssociatedDeclaration()->
getType().getNonReferenceType();
8243 const auto *VD = dyn_cast<VarDecl>(I->getAssociatedDeclaration());
8245 !VD || VD->hasLocalStorage() || HasAttachPtr)
8248 FirstPointerInComplexData =
true;
8267 bool ShouldBeMemberOf =
false;
8276 const MemberExpr *EncounteredME =
nullptr;
8288 bool IsNonContiguous =
8289 CombinedInfo.NonContigInfo.IsNonContiguous ||
8290 any_of(Components, [&](
const auto &Component) {
8292 dyn_cast<ArraySectionExpr>(Component.getAssociatedExpression());
8296 const Expr *StrideExpr = OASE->getStride();
8301 "Stride expression must be of integer type");
8314 bool IsPrevMemberReference =
false;
8316 bool IsPartialMapped =
8317 !PartialStruct.PreliminaryMapData.BasePointers.empty();
8324 bool IsMappingWholeStruct =
true;
8325 if (!GenerateAllInfoForClauses) {
8326 IsMappingWholeStruct =
false;
8328 for (
auto TempI = I; TempI != CE; ++TempI) {
8329 const MemberExpr *PossibleME =
8330 dyn_cast<MemberExpr>(TempI->getAssociatedExpression());
8332 IsMappingWholeStruct =
false;
8338 bool SeenFirstNonBinOpExprAfterAttachPtr =
false;
8339 for (; I != CE; ++I) {
8342 if (HasAttachPtr && !SeenAttachPtr) {
8343 SeenAttachPtr = I->getAssociatedExpression() == AttachPtrExpr;
8350 if (HasAttachPtr && !SeenFirstNonBinOpExprAfterAttachPtr) {
8351 const auto *BO = dyn_cast<BinaryOperator>(I->getAssociatedExpression());
8356 SeenFirstNonBinOpExprAfterAttachPtr =
true;
8357 BP = AttachPteeBaseAddr;
8361 if (!EncounteredME) {
8362 EncounteredME = dyn_cast<MemberExpr>(I->getAssociatedExpression());
8365 if (EncounteredME) {
8366 ShouldBeMemberOf =
true;
8369 if (FirstPointerInComplexData) {
8370 QualType Ty = std::prev(I)
8371 ->getAssociatedDeclaration()
8373 .getNonReferenceType();
8375 FirstPointerInComplexData =
false;
8380 auto Next = std::next(I);
8390 bool IsFinalArraySection =
8392 isFinalArraySectionExpression(I->getAssociatedExpression());
8396 const ValueDecl *MapDecl = (I->getAssociatedDeclaration())
8397 ? I->getAssociatedDeclaration()
8399 MapExpr = (I->getAssociatedExpression()) ? I->getAssociatedExpression()
8406 dyn_cast<ArraySectionExpr>(I->getAssociatedExpression());
8408 dyn_cast<OMPArrayShapingExpr>(I->getAssociatedExpression());
8409 const auto *UO = dyn_cast<UnaryOperator>(I->getAssociatedExpression());
8410 const auto *BO = dyn_cast<BinaryOperator>(I->getAssociatedExpression());
8416 I->getAssociatedExpression()->getType()->isAnyPointerType();
8417 bool IsMemberReference =
isa<MemberExpr>(I->getAssociatedExpression()) &&
8420 bool IsNonDerefPointer = IsPointer &&
8421 !(UO && UO->getOpcode() != UO_Deref) && !BO &&
8427 if (
Next == CE || IsMemberReference || IsNonDerefPointer ||
8428 IsFinalArraySection) {
8431 assert((
Next == CE ||
8438 "Unexpected expression");
8442 auto &&EmitMemberExprBase = [](CodeGenFunction &CGF,
8443 const MemberExpr *E) {
8444 const Expr *BaseExpr = E->getBase();
8449 LValueBaseInfo BaseInfo;
8450 TBAAAccessInfo TBAAInfo;
8464 OAShE->getBase()->getType()->getPointeeType()),
8466 OAShE->getBase()->getType()));
8467 }
else if (IsMemberReference) {
8469 LValue BaseLVal = EmitMemberExprBase(CGF, ME);
8484 FinalLowestElem = LowestElem;
8489 bool IsMemberPointerOrAddr =
8491 (((IsPointer || ForDeviceAddr) &&
8492 I->getAssociatedExpression() == EncounteredME) ||
8493 (IsPrevMemberReference && !IsPointer) ||
8494 (IsMemberReference &&
Next != CE &&
8495 !
Next->getAssociatedExpression()->getType()->isPointerType()));
8496 if (!OverlappedElements.empty() &&
Next == CE) {
8498 assert(!PartialStruct.Base.isValid() &&
"The base element is set.");
8499 assert(!IsPointer &&
8500 "Unexpected base element with the pointer type.");
8503 PartialStruct.LowestElem = {0, LowestElem};
8505 I->getAssociatedExpression()->getType());
8510 PartialStruct.HighestElem = {
8511 std::numeric_limits<
decltype(
8512 PartialStruct.HighestElem.first)>
::max(),
8514 PartialStruct.Base = BP;
8515 PartialStruct.LB = LB;
8517 PartialStruct.PreliminaryMapData.BasePointers.empty() &&
8518 "Overlapped elements must be used only once for the variable.");
8519 std::swap(PartialStruct.PreliminaryMapData, CombinedInfo);
8521 OpenMPOffloadMappingFlags Flags =
8522 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF |
8523 getMapTypeBits(MapType, MapModifiers, MotionModifiers, IsImplicit,
8525 false, IsNonContiguous);
8526 CopyOverlappedEntryGaps CopyGaps(CGF, CombinedInfo, Flags, MapDecl,
8527 MapExpr, BP, LB, IsNonContiguous,
8531 Component : OverlappedElements) {
8532 for (
const OMPClauseMappableExprCommon::MappableComponent &MC :
8535 if (
const auto *FD = dyn_cast<FieldDecl>(VD)) {
8536 CopyGaps.processField(MC, FD, EmitMemberExprBase);
8541 CopyGaps.copyUntilEnd(HB);
8544 llvm::Value *
Size = getExprTypeSize(I->getAssociatedExpression());
8551 if ((!IsMemberPointerOrAddr && !IsPartialMapped) ||
8553 if (!IsMappingWholeStruct) {
8554 CombinedInfo.Exprs.emplace_back(MapDecl, MapExpr);
8556 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
8557 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
8559 CombinedInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
8561 CombinedInfo.NonContigInfo.Dims.push_back(IsNonContiguous ? DimSize
8564 StructBaseCombinedInfo.Exprs.emplace_back(MapDecl, MapExpr);
8565 StructBaseCombinedInfo.BasePointers.push_back(
8567 StructBaseCombinedInfo.DevicePtrDecls.push_back(
nullptr);
8568 StructBaseCombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
8569 StructBaseCombinedInfo.Pointers.push_back(LB.
emitRawPointer(CGF));
8570 StructBaseCombinedInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
8572 StructBaseCombinedInfo.NonContigInfo.Dims.push_back(
8573 IsNonContiguous ? DimSize : 1);
8577 bool HasMapper = Mapper &&
Next == CE;
8578 if (!IsMappingWholeStruct)
8579 CombinedInfo.Mappers.push_back(HasMapper ? Mapper :
nullptr);
8581 StructBaseCombinedInfo.Mappers.push_back(HasMapper ? Mapper
8588 OpenMPOffloadMappingFlags Flags = getMapTypeBits(
8589 MapType, MapModifiers, MotionModifiers, IsImplicit,
8590 !IsExpressionFirstInfo || RequiresReference ||
8591 FirstPointerInComplexData || IsMemberReference,
8592 IsCaptureFirstInfo && !RequiresReference, IsNonContiguous);
8594 if (!IsExpressionFirstInfo || IsMemberReference) {
8597 if (IsPointer || (IsMemberReference &&
Next != CE))
8598 Flags &= ~(OpenMPOffloadMappingFlags::OMP_MAP_TO |
8599 OpenMPOffloadMappingFlags::OMP_MAP_FROM |
8600 OpenMPOffloadMappingFlags::OMP_MAP_ALWAYS |
8601 OpenMPOffloadMappingFlags::OMP_MAP_DELETE |
8602 OpenMPOffloadMappingFlags::OMP_MAP_CLOSE);
8604 if (ShouldBeMemberOf) {
8607 Flags |= OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF;
8610 ShouldBeMemberOf =
false;
8614 if (!IsMappingWholeStruct) {
8615 CombinedInfo.Types.push_back(Flags);
8617 CombinedInfo.HasAttachPtr.push_back(HasAttachPtr);
8619 StructBaseCombinedInfo.Types.push_back(Flags);
8620 StructBaseCombinedInfo.HasAttachPtr.push_back(HasAttachPtr);
8627 if (EncounteredME) {
8632 if (!PartialStruct.Base.isValid()) {
8633 PartialStruct.LowestElem = {FieldIndex, LowestElem};
8634 if (IsFinalArraySection && OASE) {
8638 PartialStruct.HighestElem = {FieldIndex, HB};
8640 PartialStruct.HighestElem = {FieldIndex, LowestElem};
8642 PartialStruct.Base = BP;
8643 PartialStruct.LB = BP;
8644 }
else if (FieldIndex < PartialStruct.LowestElem.first) {
8645 PartialStruct.LowestElem = {FieldIndex, LowestElem};
8646 }
else if (FieldIndex > PartialStruct.HighestElem.first) {
8647 if (IsFinalArraySection && OASE) {
8651 PartialStruct.HighestElem = {FieldIndex, HB};
8653 PartialStruct.HighestElem = {FieldIndex, LowestElem};
8659 if (IsFinalArraySection || IsNonContiguous)
8660 PartialStruct.IsArraySection =
true;
8663 if (IsFinalArraySection)
8668 BP = IsMemberReference ? LowestElem : LB;
8669 if (!IsPartialMapped)
8670 IsExpressionFirstInfo =
false;
8671 IsCaptureFirstInfo =
false;
8672 FirstPointerInComplexData =
false;
8673 IsPrevMemberReference = IsMemberReference;
8674 }
else if (FirstPointerInComplexData) {
8675 QualType Ty = Components.rbegin()
8676 ->getAssociatedDeclaration()
8678 .getNonReferenceType();
8680 FirstPointerInComplexData =
false;
8686 PartialStruct.HasCompleteRecord =
true;
8689 if (shouldEmitAttachEntry(AttachPtrExpr, BaseDecl, CGF, CurDir)) {
8690 AttachInfo.AttachPtrAddr = AttachPtrAddr;
8691 AttachInfo.AttachPteeAddr = FinalLowestElem;
8692 AttachInfo.AttachPtrDecl = BaseDecl;
8693 AttachInfo.AttachMapExpr = MapExpr;
8696 if (!IsNonContiguous)
8699 const ASTContext &Context = CGF.
getContext();
8703 MapValuesArrayTy CurOffsets = {llvm::ConstantInt::get(CGF.
CGM.
Int64Ty, 0)};
8704 MapValuesArrayTy CurCounts;
8705 MapValuesArrayTy CurStrides = {llvm::ConstantInt::get(CGF.
CGM.
Int64Ty, 1)};
8706 MapValuesArrayTy DimSizes{llvm::ConstantInt::get(CGF.
CGM.
Int64Ty, 1)};
8712 for (
const OMPClauseMappableExprCommon::MappableComponent &Component :
8714 const Expr *AssocExpr = Component.getAssociatedExpression();
8715 const auto *OASE = dyn_cast<ArraySectionExpr>(AssocExpr);
8725 assert((VAT || CAT || &Component == &*Components.begin()) &&
8726 "Should be either ConstantArray or VariableArray if not the "
8730 if (CurCounts.empty()) {
8731 const Type *ElementType =
nullptr;
8733 ElementType = CAT->getElementType().getTypePtr();
8735 ElementType = VAT->getElementType().getTypePtr();
8736 else if (&Component == &*Components.begin()) {
8743 if (
const auto *PtrType = Ty->
getAs<PointerType>())
8744 ElementType = PtrType->getPointeeType().getTypePtr();
8750 "Non-first components should not be raw pointers");
8758 if (&Component != &*Components.begin())
8759 ElementType = ElementType->getPointeeOrArrayElementType();
8762 CurCounts.push_back(
8763 llvm::ConstantInt::get(CGF.
Int64Ty, ElementTypeSize));
8768 if (DimSizes.size() < Components.size() - 1) {
8771 llvm::ConstantInt::get(CGF.
Int64Ty, CAT->getZExtSize()));
8773 DimSizes.push_back(CGF.
Builder.CreateIntCast(
8780 auto *DI = DimSizes.begin() + 1;
8782 llvm::Value *DimProd =
8783 llvm::ConstantInt::get(CGF.
CGM.
Int64Ty, ElementTypeSize);
8792 for (
const OMPClauseMappableExprCommon::MappableComponent &Component :
8794 const Expr *AssocExpr = Component.getAssociatedExpression();
8796 if (
const auto *AE = dyn_cast<ArraySubscriptExpr>(AssocExpr)) {
8797 llvm::Value *Offset = CGF.
Builder.CreateIntCast(
8800 CurOffsets.push_back(Offset);
8801 CurCounts.push_back(llvm::ConstantInt::get(CGF.
Int64Ty, 1));
8802 CurStrides.push_back(CurStrides.back());
8806 const auto *OASE = dyn_cast<ArraySectionExpr>(AssocExpr);
8812 const Expr *OffsetExpr = OASE->getLowerBound();
8813 llvm::Value *Offset =
nullptr;
8816 Offset = llvm::ConstantInt::get(CGF.
Int64Ty, 0);
8824 const Expr *CountExpr = OASE->getLength();
8825 llvm::Value *Count =
nullptr;
8831 if (!OASE->getColonLocFirst().isValid() &&
8832 !OASE->getColonLocSecond().isValid()) {
8833 Count = llvm::ConstantInt::get(CGF.
Int64Ty, 1);
8839 const Expr *StrideExpr = OASE->getStride();
8840 llvm::Value *Stride =
8846 Count = CGF.
Builder.CreateUDiv(
8847 CGF.
Builder.CreateNUWSub(*DI, Offset), Stride);
8849 Count = CGF.
Builder.CreateNUWSub(*DI, Offset);
8855 CurCounts.push_back(Count);
8865 const Expr *StrideExpr = OASE->getStride();
8866 llvm::Value *Stride =
8871 DimProd = CGF.
Builder.CreateNUWMul(DimProd, *(DI - 1));
8873 CurStrides.push_back(CGF.
Builder.CreateNUWMul(DimProd, Stride));
8875 CurStrides.push_back(DimProd);
8877 Offset = CGF.
Builder.CreateNUWMul(DimProd, Offset);
8878 CurOffsets.push_back(Offset);
8880 if (DI != DimSizes.end())
8884 CombinedInfo.NonContigInfo.Offsets.push_back(CurOffsets);
8885 CombinedInfo.NonContigInfo.Counts.push_back(CurCounts);
8886 CombinedInfo.NonContigInfo.Strides.push_back(CurStrides);
8892 OpenMPOffloadMappingFlags
8893 getMapModifiersForPrivateClauses(
const CapturedStmt::Capture &Cap)
const {
8901 return OpenMPOffloadMappingFlags::OMP_MAP_TO |
8902 OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ;
8903 return OpenMPOffloadMappingFlags::OMP_MAP_PRIVATE |
8904 OpenMPOffloadMappingFlags::OMP_MAP_TO;
8907 if (I != LambdasMap.end())
8909 return getMapTypeBits(
8910 I->getSecond()->getMapType(), I->getSecond()->getMapTypeModifiers(),
8911 {}, I->getSecond()->isImplicit(),
8915 return OpenMPOffloadMappingFlags::OMP_MAP_TO |
8916 OpenMPOffloadMappingFlags::OMP_MAP_FROM;
8919 void getPlainLayout(
const CXXRecordDecl *RD,
8920 llvm::SmallVectorImpl<const FieldDecl *> &Layout,
8921 bool AsBase)
const {
8924 llvm::StructType *St =
8927 unsigned NumElements = St->getNumElements();
8929 llvm::PointerUnion<const CXXRecordDecl *, const FieldDecl *>, 4>
8930 RecordLayout(NumElements);
8933 for (
const auto &I : RD->
bases()) {
8937 QualType BaseTy = I.getType();
8948 RecordLayout[FieldIndex] =
Base;
8951 for (
const auto &I : RD->
vbases()) {
8952 QualType BaseTy = I.getType();
8959 if (RecordLayout[FieldIndex])
8961 RecordLayout[FieldIndex] =
Base;
8964 assert(!RD->
isUnion() &&
"Unexpected union.");
8965 for (
const auto *Field : RD->
fields()) {
8968 if (!
Field->isBitField() &&
8971 RecordLayout[FieldIndex] =
Field;
8974 for (
const llvm::PointerUnion<const CXXRecordDecl *, const FieldDecl *>
8975 &
Data : RecordLayout) {
8978 if (
const auto *Base = dyn_cast<const CXXRecordDecl *>(
Data))
8979 getPlainLayout(Base, Layout,
true);
8986 static Address getAttachPtrAddr(
const Expr *PointerExpr,
8987 CodeGenFunction &CGF) {
8988 assert(PointerExpr &&
"Cannot get addr from null attach-ptr expr");
8991 if (
auto *DRE = dyn_cast<DeclRefExpr>(PointerExpr)) {
8994 }
else if (
auto *OASE = dyn_cast<ArraySectionExpr>(PointerExpr)) {
8997 }
else if (
auto *ASE = dyn_cast<ArraySubscriptExpr>(PointerExpr)) {
8999 }
else if (
auto *ME = dyn_cast<MemberExpr>(PointerExpr)) {
9001 }
else if (
auto *UO = dyn_cast<UnaryOperator>(PointerExpr)) {
9002 assert(UO->getOpcode() == UO_Deref &&
9003 "Unexpected unary-operator on attach-ptr-expr");
9006 assert(AttachPtrAddr.
isValid() &&
9007 "Failed to get address for attach pointer expression");
9008 return AttachPtrAddr;
9015 static std::pair<Address, Address>
9016 getAttachPtrAddrAndPteeBaseAddr(
const Expr *AttachPtrExpr,
9017 CodeGenFunction &CGF) {
9022 Address AttachPtrAddr = getAttachPtrAddr(AttachPtrExpr, CGF);
9023 assert(AttachPtrAddr.
isValid() &&
"Invalid attach pointer addr");
9025 QualType AttachPtrType =
9030 AttachPtrAddr, AttachPtrType->
castAs<PointerType>());
9031 assert(AttachPteeBaseAddr.
isValid() &&
"Invalid attach pointee base addr");
9033 return {AttachPtrAddr, AttachPteeBaseAddr};
9039 shouldEmitAttachEntry(
const Expr *PointerExpr,
const ValueDecl *MapBaseDecl,
9040 CodeGenFunction &CGF,
9041 llvm::PointerUnion<
const OMPExecutableDirective *,
9042 const OMPDeclareMapperDecl *>
9052 ->getDirectiveKind());
9061 void collectAttachPtrExprInfo(
9063 llvm::PointerUnion<
const OMPExecutableDirective *,
9064 const OMPDeclareMapperDecl *>
9069 ? OMPD_declare_mapper
9072 const auto &[AttachPtrExpr, Depth] =
9076 AttachPtrComputationOrderMap.try_emplace(
9077 AttachPtrExpr, AttachPtrComputationOrderMap.size());
9078 AttachPtrComponentDepthMap.try_emplace(AttachPtrExpr, Depth);
9079 AttachPtrExprMap.try_emplace(Components, AttachPtrExpr);
9087 void generateAllInfoForClauses(
9088 ArrayRef<const OMPClause *> Clauses, MapCombinedInfoTy &CombinedInfo,
9089 llvm::OpenMPIRBuilder &OMPBuilder,
9090 const llvm::DenseSet<CanonicalDeclPtr<const Decl>> &SkipVarSet =
9091 llvm::DenseSet<CanonicalDeclPtr<const Decl>>())
const {
9096 llvm::MapVector<CanonicalDeclPtr<const Decl>,
9097 SmallVector<SmallVector<MapInfo, 8>, 4>>
9103 [&Info, &SkipVarSet](
9104 const ValueDecl *D, MapKind
Kind,
9107 ArrayRef<OpenMPMapModifierKind> MapModifiers,
9108 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
9109 bool ReturnDevicePointer,
bool IsImplicit,
const ValueDecl *Mapper,
9110 const Expr *VarRef =
nullptr,
bool ForDeviceAddr =
false) {
9111 if (SkipVarSet.contains(D))
9113 auto It = Info.try_emplace(D, Total).first;
9114 It->second[
Kind].emplace_back(
9115 L, MapType, MapModifiers, MotionModifiers, ReturnDevicePointer,
9116 IsImplicit, Mapper, VarRef, ForDeviceAddr);
9119 for (
const auto *
Cl : Clauses) {
9120 const auto *
C = dyn_cast<OMPMapClause>(
Cl);
9124 if (llvm::is_contained(
C->getMapTypeModifiers(),
9125 OMPC_MAP_MODIFIER_present))
9127 else if (
C->getMapType() == OMPC_MAP_alloc)
9129 const auto *EI =
C->getVarRefs().begin();
9130 for (
const auto L :
C->component_lists()) {
9131 const Expr *E = (
C->getMapLoc().isValid()) ? *EI :
nullptr;
9132 InfoGen(std::get<0>(L), Kind, std::get<1>(L),
C->getMapType(),
9133 C->getMapTypeModifiers(), {},
9134 false,
C->isImplicit(), std::get<2>(L),
9139 for (
const auto *
Cl : Clauses) {
9140 const auto *
C = dyn_cast<OMPToClause>(
Cl);
9144 if (llvm::is_contained(
C->getMotionModifiers(),
9145 OMPC_MOTION_MODIFIER_present))
9147 if (llvm::is_contained(
C->getMotionModifiers(),
9148 OMPC_MOTION_MODIFIER_iterator)) {
9149 if (
auto *IteratorExpr = dyn_cast<OMPIteratorExpr>(
9150 C->getIteratorModifier()->IgnoreParenImpCasts())) {
9151 const auto *VD =
cast<VarDecl>(IteratorExpr->getIteratorDecl(0));
9156 const auto *EI =
C->getVarRefs().begin();
9157 for (
const auto L :
C->component_lists()) {
9158 InfoGen(std::get<0>(L), Kind, std::get<1>(L), OMPC_MAP_to, {},
9159 C->getMotionModifiers(),
false,
9160 C->isImplicit(), std::get<2>(L), *EI);
9164 for (
const auto *
Cl : Clauses) {
9165 const auto *
C = dyn_cast<OMPFromClause>(
Cl);
9169 if (llvm::is_contained(
C->getMotionModifiers(),
9170 OMPC_MOTION_MODIFIER_present))
9172 if (llvm::is_contained(
C->getMotionModifiers(),
9173 OMPC_MOTION_MODIFIER_iterator)) {
9174 if (
auto *IteratorExpr = dyn_cast<OMPIteratorExpr>(
9175 C->getIteratorModifier()->IgnoreParenImpCasts())) {
9176 const auto *VD =
cast<VarDecl>(IteratorExpr->getIteratorDecl(0));
9181 const auto *EI =
C->getVarRefs().begin();
9182 for (
const auto L :
C->component_lists()) {
9183 InfoGen(std::get<0>(L), Kind, std::get<1>(L), OMPC_MAP_from, {},
9184 C->getMotionModifiers(),
9185 false,
C->isImplicit(), std::get<2>(L),
9198 MapCombinedInfoTy UseDeviceDataCombinedInfo;
9200 auto &&UseDeviceDataCombinedInfoGen =
9201 [&UseDeviceDataCombinedInfo](
const ValueDecl *VD, llvm::Value *
Ptr,
9202 CodeGenFunction &CGF,
bool IsDevAddr,
9203 bool HasUdpFbNullify =
false) {
9204 UseDeviceDataCombinedInfo.Exprs.push_back(VD);
9205 UseDeviceDataCombinedInfo.BasePointers.emplace_back(Ptr);
9206 UseDeviceDataCombinedInfo.DevicePtrDecls.emplace_back(VD);
9207 UseDeviceDataCombinedInfo.DevicePointers.emplace_back(
9208 IsDevAddr ? DeviceInfoTy::Address : DeviceInfoTy::Pointer);
9214 UseDeviceDataCombinedInfo.Pointers.push_back(Ptr);
9215 UseDeviceDataCombinedInfo.Sizes.push_back(
9216 llvm::Constant::getNullValue(CGF.Int64Ty));
9217 OpenMPOffloadMappingFlags Flags =
9218 OpenMPOffloadMappingFlags::OMP_MAP_RETURN_PARAM;
9219 if (HasUdpFbNullify)
9220 Flags |= OpenMPOffloadMappingFlags::OMP_MAP_FB_NULLIFY;
9221 UseDeviceDataCombinedInfo.Types.push_back(Flags);
9222 UseDeviceDataCombinedInfo.HasAttachPtr.push_back(
false);
9223 UseDeviceDataCombinedInfo.Mappers.push_back(
nullptr);
9227 [&UseDeviceDataCombinedInfoGen](
9228 CodeGenFunction &CGF,
const Expr *IE,
const ValueDecl *VD,
9231 bool IsDevAddr,
bool IEIsAttachPtrForDevAddr =
false,
9232 bool HasUdpFbNullify =
false) {
9236 if (IsDevAddr && !IEIsAttachPtrForDevAddr) {
9237 if (IE->isGLValue())
9244 bool TreatDevAddrAsDevPtr = IEIsAttachPtrForDevAddr;
9251 UseDeviceDataCombinedInfoGen(VD, Ptr, CGF, IsDevAddr &&
9252 !TreatDevAddrAsDevPtr,
9256 auto &&IsMapInfoExist =
9257 [&Info,
this](CodeGenFunction &CGF,
const ValueDecl *VD,
const Expr *IE,
9258 const Expr *DesiredAttachPtrExpr,
bool IsDevAddr,
9259 bool HasUdpFbNullify =
false) ->
bool {
9267 if (It != Info.end()) {
9269 for (
auto &
Data : It->second) {
9270 MapInfo *CI =
nullptr;
9274 auto *It = llvm::find_if(
Data, [&](
const MapInfo &MI) {
9275 if (MI.Components.back().getAssociatedDeclaration() != VD)
9278 const Expr *MapAttachPtr = getAttachPtrExpr(MI.Components);
9279 bool Match = AttachPtrComparator.areEqual(MapAttachPtr,
9280 DesiredAttachPtrExpr);
9284 if (It !=
Data.end())
9289 CI->ForDeviceAddr =
true;
9290 CI->ReturnDevicePointer =
true;
9291 CI->HasUdpFbNullify = HasUdpFbNullify;
9295 auto PrevCI = std::next(CI->Components.rbegin());
9296 const auto *VarD = dyn_cast<VarDecl>(VD);
9297 const Expr *AttachPtrExpr = getAttachPtrExpr(CI->Components);
9298 if (CGF.CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory() ||
9300 !VD->getType().getNonReferenceType()->isPointerType() ||
9301 PrevCI == CI->Components.rend() ||
9303 VarD->hasLocalStorage() ||
9304 (isa_and_nonnull<DeclRefExpr>(AttachPtrExpr) &&
9306 CI->ForDeviceAddr = IsDevAddr;
9307 CI->ReturnDevicePointer =
true;
9308 CI->HasUdpFbNullify = HasUdpFbNullify;
9326 for (
const auto *
Cl : Clauses) {
9327 const auto *
C = dyn_cast<OMPUseDevicePtrClause>(
Cl);
9330 bool HasUdpFbNullify =
9331 C->getFallbackModifier() == OMPC_USE_DEVICE_PTR_FALLBACK_fb_nullify;
9332 for (
const auto L :
C->component_lists()) {
9335 assert(!Components.empty() &&
9336 "Not expecting empty list of components!");
9337 const ValueDecl *VD = Components.back().getAssociatedDeclaration();
9339 const Expr *IE = Components.back().getAssociatedExpression();
9347 const Expr *UDPOperandExpr =
9348 Components.front().getAssociatedExpression();
9349 if (IsMapInfoExist(CGF, VD, IE,
9351 false, HasUdpFbNullify))
9353 MapInfoGen(CGF, IE, VD, Components,
false,
9354 false, HasUdpFbNullify);
9358 llvm::SmallDenseSet<CanonicalDeclPtr<const Decl>, 4> Processed;
9359 for (
const auto *
Cl : Clauses) {
9360 const auto *
C = dyn_cast<OMPUseDeviceAddrClause>(
Cl);
9363 for (
const auto L :
C->component_lists()) {
9366 assert(!std::get<1>(L).empty() &&
9367 "Not expecting empty list of components!");
9368 const ValueDecl *VD = std::get<1>(L).back().getAssociatedDeclaration();
9369 if (!Processed.insert(VD).second)
9390 const Expr *UDAAttachPtrExpr = getAttachPtrExpr(Components);
9391 const Expr *IE = std::get<1>(L).back().getAssociatedExpression();
9392 assert((!UDAAttachPtrExpr || UDAAttachPtrExpr == IE) &&
9393 "use_device_addr operand has an attach-ptr, but does not match "
9394 "last component's expr.");
9395 if (IsMapInfoExist(CGF, VD, IE,
9399 MapInfoGen(CGF, IE, VD, Components,
9401 UDAAttachPtrExpr !=
nullptr);
9405 for (
const auto &
Data : Info) {
9406 MapCombinedInfoTy CurInfo;
9408 const ValueDecl *VD = cast_or_null<ValueDecl>(D);
9415 SmallVector<std::pair<const Expr *, MapInfo>, 16> AttachPtrMapInfoPairs;
9418 for (
const auto &M :
Data.second) {
9419 for (
const MapInfo &L : M) {
9420 assert(!L.Components.empty() &&
9421 "Not expecting declaration with no component lists.");
9423 const Expr *AttachPtrExpr = getAttachPtrExpr(L.Components);
9424 AttachPtrMapInfoPairs.emplace_back(AttachPtrExpr, L);
9429 llvm::stable_sort(AttachPtrMapInfoPairs,
9430 [
this](
const auto &LHS,
const auto &RHS) {
9431 return AttachPtrComparator(LHS.first, RHS.first);
9436 auto *It = AttachPtrMapInfoPairs.begin();
9437 while (It != AttachPtrMapInfoPairs.end()) {
9438 const Expr *AttachPtrExpr = It->first;
9440 SmallVector<MapInfo, 8> GroupLists;
9441 while (It != AttachPtrMapInfoPairs.end() &&
9442 (It->first == AttachPtrExpr ||
9443 AttachPtrComparator.areEqual(It->first, AttachPtrExpr))) {
9444 GroupLists.push_back(It->second);
9447 assert(!GroupLists.empty() &&
"GroupLists should not be empty");
9449 StructRangeInfoTy PartialStruct;
9450 AttachInfoTy AttachInfo;
9451 MapCombinedInfoTy GroupCurInfo;
9453 MapCombinedInfoTy GroupStructBaseCurInfo;
9454 for (
const MapInfo &L : GroupLists) {
9456 unsigned CurrentBasePointersIdx = GroupCurInfo.BasePointers.size();
9457 unsigned StructBasePointersIdx =
9458 GroupStructBaseCurInfo.BasePointers.size();
9460 GroupCurInfo.NonContigInfo.IsNonContiguous =
9461 L.Components.back().isNonContiguous();
9462 generateInfoForComponentList(
9463 L.MapType, L.MapModifiers, L.MotionModifiers, L.Components,
9464 GroupCurInfo, GroupStructBaseCurInfo, PartialStruct, AttachInfo,
9465 false, L.IsImplicit,
9466 true, L.Mapper, L.ForDeviceAddr, VD,
9471 if (L.ReturnDevicePointer) {
9475 assert((CurrentBasePointersIdx < GroupCurInfo.BasePointers.size() ||
9476 StructBasePointersIdx <
9477 GroupStructBaseCurInfo.BasePointers.size()) &&
9478 "Unexpected number of mapped base pointers.");
9481 const ValueDecl *RelevantVD =
9482 L.Components.back().getAssociatedDeclaration();
9483 assert(RelevantVD &&
9484 "No relevant declaration related with device pointer??");
9491 auto SetDevicePointerInfo = [&](MapCombinedInfoTy &Info,
9493 Info.DevicePtrDecls[Idx] = RelevantVD;
9494 Info.DevicePointers[Idx] = L.ForDeviceAddr
9495 ? DeviceInfoTy::Address
9496 : DeviceInfoTy::Pointer;
9498 OpenMPOffloadMappingFlags::OMP_MAP_RETURN_PARAM;
9499 if (L.HasUdpFbNullify)
9501 OpenMPOffloadMappingFlags::OMP_MAP_FB_NULLIFY;
9504 if (StructBasePointersIdx <
9505 GroupStructBaseCurInfo.BasePointers.size())
9506 SetDevicePointerInfo(GroupStructBaseCurInfo,
9507 StructBasePointersIdx);
9509 SetDevicePointerInfo(GroupCurInfo, CurrentBasePointersIdx);
9515 MapCombinedInfoTy GroupUnionCurInfo;
9516 GroupUnionCurInfo.append(GroupStructBaseCurInfo);
9517 GroupUnionCurInfo.append(GroupCurInfo);
9521 if (PartialStruct.Base.isValid()) {
9529 GroupUnionCurInfo.NonContigInfo.Dims.insert(
9530 GroupUnionCurInfo.NonContigInfo.Dims.begin(), 1);
9532 CurInfo, GroupUnionCurInfo.Types, PartialStruct, AttachInfo,
9533 !VD, OMPBuilder, VD,
9534 CombinedInfo.BasePointers.size(),
9540 CurInfo.append(GroupUnionCurInfo);
9541 if (AttachInfo.isValid())
9542 emitAttachEntry(CGF, CurInfo, AttachInfo);
9546 CombinedInfo.append(CurInfo);
9549 CombinedInfo.append(UseDeviceDataCombinedInfo);
9553 MappableExprsHandler(
const OMPExecutableDirective &Dir, CodeGenFunction &CGF)
9554 : CurDir(&Dir), CGF(CGF), AttachPtrComparator(*this) {
9556 for (
const auto *
C : Dir.getClausesOfKind<OMPFirstprivateClause>())
9557 for (
const auto *D :
C->varlist()) {
9558 const ValueDecl *VD = cast<DeclRefExpr>(D)->getDecl();
9559 if (const auto *BD = dyn_cast<BindingDecl>(VD))
9560 VD = cast<VarDecl>(BD->getDecomposedDecl());
9561 FirstPrivateDecls.try_emplace(cast<VarDecl>(VD), C->isImplicit());
9564 for (
const auto *
C : Dir.getClausesOfKind<OMPUsesAllocatorsClause>()) {
9565 for (unsigned I = 0, E = C->getNumberOfAllocators(); I < E; ++I) {
9566 OMPUsesAllocatorsClause::Data D = C->getAllocatorData(I);
9567 if (const auto *DRE = dyn_cast_or_null<DeclRefExpr>(D.AllocatorTraits))
9568 FirstPrivateDecls.try_emplace(cast<VarDecl>(DRE->getDecl()),
9570 else if (const auto *VD = dyn_cast<VarDecl>(
9571 cast<DeclRefExpr>(D.Allocator->IgnoreParenImpCasts())
9573 FirstPrivateDecls.try_emplace(VD, true);
9577 for (
const auto *
C : Dir.getClausesOfKind<OMPDefaultmapClause>())
9578 if (
C->getDefaultmapModifier() == OMPC_DEFAULTMAP_MODIFIER_firstprivate)
9579 DefaultmapFirstprivateKinds.insert(
C->getDefaultmapKind());
9581 for (
const auto *
C : Dir.getClausesOfKind<OMPIsDevicePtrClause>())
9582 for (
auto L :
C->component_lists())
9583 DevPointersMap[std::get<0>(L)].push_back(std::get<1>(L));
9585 for (
const auto *
C : Dir.getClausesOfKind<OMPHasDeviceAddrClause>())
9586 for (
auto L :
C->component_lists())
9587 HasDevAddrsMap[std::get<0>(L)].push_back(std::get<1>(L));
9589 for (
const auto *
C : Dir.getClausesOfKind<OMPMapClause>()) {
9590 if (C->getMapType() != OMPC_MAP_to)
9592 for (auto L : C->component_lists()) {
9593 const ValueDecl *VD = std::get<0>(L);
9594 const auto *RD = VD ? VD->getType()
9596 .getNonReferenceType()
9597 ->getAsCXXRecordDecl()
9599 if (RD && RD->isLambda())
9600 LambdasMap.try_emplace(std::get<0>(L), C);
9604 auto CollectAttachPtrExprsForClauseComponents = [
this](
const auto *
C) {
9605 for (
auto L :
C->component_lists()) {
9608 if (!Components.empty())
9609 collectAttachPtrExprInfo(Components, CurDir);
9615 for (
const auto *
C : Dir.getClausesOfKind<OMPMapClause>())
9616 CollectAttachPtrExprsForClauseComponents(
C);
9617 for (
const auto *
C : Dir.getClausesOfKind<OMPToClause>())
9618 CollectAttachPtrExprsForClauseComponents(
C);
9619 for (
const auto *
C : Dir.getClausesOfKind<OMPFromClause>())
9620 CollectAttachPtrExprsForClauseComponents(
C);
9621 for (
const auto *
C : Dir.getClausesOfKind<OMPUseDevicePtrClause>())
9622 CollectAttachPtrExprsForClauseComponents(
C);
9623 for (
const auto *
C : Dir.getClausesOfKind<OMPUseDeviceAddrClause>())
9624 CollectAttachPtrExprsForClauseComponents(
C);
9625 for (
const auto *
C : Dir.getClausesOfKind<OMPIsDevicePtrClause>())
9626 CollectAttachPtrExprsForClauseComponents(
C);
9627 for (
const auto *
C : Dir.getClausesOfKind<OMPHasDeviceAddrClause>())
9628 CollectAttachPtrExprsForClauseComponents(
C);
9632 MappableExprsHandler(
const OMPDeclareMapperDecl &Dir,
CodeGenFunction &CGF)
9633 : CurDir(&Dir), CGF(CGF), AttachPtrComparator(*this) {
9634 auto CollectAttachPtrExprsForClauseComponents = [
this](
const auto *
C) {
9635 for (
auto L :
C->component_lists()) {
9638 if (!Components.empty())
9639 collectAttachPtrExprInfo(Components, CurDir);
9647 if (const auto *C = dyn_cast<OMPMapClause>(Cl))
9648 CollectAttachPtrExprsForClauseComponents(C);
9649 else if (const auto *C = dyn_cast<OMPToClause>(Cl))
9650 CollectAttachPtrExprsForClauseComponents(C);
9651 else if (const auto *C = dyn_cast<OMPFromClause>(Cl))
9652 CollectAttachPtrExprsForClauseComponents(C);
9664 void emitCombinedEntry(MapCombinedInfoTy &CombinedInfo,
9665 MapFlagsArrayTy &CurTypes,
9666 const StructRangeInfoTy &PartialStruct,
9667 AttachInfoTy &AttachInfo,
bool IsMapThis,
9668 llvm::OpenMPIRBuilder &OMPBuilder,
const ValueDecl *VD,
9669 unsigned OffsetForMemberOfFlag,
9670 bool NotTargetParams)
const {
9671 if (CurTypes.size() == 1 &&
9672 ((CurTypes.back() & OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF) !=
9673 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF) &&
9674 !PartialStruct.IsArraySection)
9676 Address LBAddr = PartialStruct.LowestElem.second;
9677 Address HBAddr = PartialStruct.HighestElem.second;
9678 if (PartialStruct.HasCompleteRecord) {
9679 LBAddr = PartialStruct.LB;
9680 HBAddr = PartialStruct.LB;
9682 CombinedInfo.Exprs.push_back(VD);
9684 CombinedInfo.BasePointers.push_back(PartialStruct.Base.emitRawPointer(CGF));
9685 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
9686 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
9689 const CXXMethodDecl *MD =
9691 const CXXRecordDecl *RD = MD ? MD->
getParent() :
nullptr;
9692 bool HasBaseClass = RD && IsMapThis ? RD->
getNumBases() > 0 :
false;
9702 CombinedInfo.Pointers.push_back(PartialStruct.Base.emitRawPointer(CGF));
9707 CombinedInfo.Sizes.push_back(Size);
9709 CombinedInfo.Pointers.push_back(LB);
9712 llvm::Value *HAddr = CGF.
Builder.CreateConstGEP1_32(
9716 llvm::Value *Diff = CGF.
Builder.CreatePtrDiff(CHAddr, CLAddr);
9719 CombinedInfo.Sizes.push_back(Size);
9721 CombinedInfo.Mappers.push_back(
nullptr);
9723 CombinedInfo.Types.push_back(
9724 NotTargetParams ? OpenMPOffloadMappingFlags::OMP_MAP_NONE
9725 : !PartialStruct.PreliminaryMapData.BasePointers.empty()
9726 ? OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ
9727 : OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM);
9735 CombinedInfo.HasAttachPtr.push_back(AttachInfo.isValid());
9738 if (CurTypes.end() !=
9739 llvm::find_if(CurTypes, [](OpenMPOffloadMappingFlags
Type) {
9740 return static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>>(
9741 Type & OpenMPOffloadMappingFlags::OMP_MAP_PRESENT);
9743 CombinedInfo.Types.back() |= OpenMPOffloadMappingFlags::OMP_MAP_PRESENT;
9745 (*CurTypes.begin()) &= ~OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM;
9752 if (CurTypes.end() !=
9753 llvm::find_if(CurTypes, [](OpenMPOffloadMappingFlags
Type) {
9754 return static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>>(
9755 Type & OpenMPOffloadMappingFlags::OMP_MAP_OMPX_HOLD);
9757 CombinedInfo.Types.back() |= OpenMPOffloadMappingFlags::OMP_MAP_OMPX_HOLD;
9758 for (
auto &M : CurTypes)
9759 M |= OpenMPOffloadMappingFlags::OMP_MAP_OMPX_HOLD;
9766 OpenMPOffloadMappingFlags MemberOfFlag = OMPBuilder.getMemberOfFlag(
9767 OffsetForMemberOfFlag + CombinedInfo.BasePointers.size() - 1);
9768 for (
auto &M : CurTypes)
9769 OMPBuilder.setCorrectMemberOfFlag(M, MemberOfFlag);
9786 if (AttachInfo.isValid())
9787 AttachInfo.AttachPteeAddr = LBAddr;
9795 void generateAllInfo(
9796 MapCombinedInfoTy &CombinedInfo, llvm::OpenMPIRBuilder &OMPBuilder,
9797 const llvm::DenseSet<CanonicalDeclPtr<const Decl>> &SkipVarSet =
9798 llvm::DenseSet<CanonicalDeclPtr<const Decl>>())
const {
9800 "Expect a executable directive");
9802 generateAllInfoForClauses(CurExecDir->clauses(), CombinedInfo, OMPBuilder,
9809 void generateAllInfoForMapper(MapCombinedInfoTy &CombinedInfo,
9810 llvm::OpenMPIRBuilder &OMPBuilder)
const {
9812 "Expect a declare mapper directive");
9814 generateAllInfoForClauses(CurMapperDir->clauses(), CombinedInfo,
9819 void generateInfoForLambdaCaptures(
9820 const ValueDecl *VD, llvm::Value *Arg, MapCombinedInfoTy &CombinedInfo,
9821 llvm::DenseMap<llvm::Value *, llvm::Value *> &LambdaPointers)
const {
9829 llvm::DenseMap<const ValueDecl *, FieldDecl *> Captures;
9830 FieldDecl *ThisCapture =
nullptr;
9836 LambdaPointers.try_emplace(ThisLVal.getPointer(CGF),
9837 VDLVal.getPointer(CGF));
9838 CombinedInfo.Exprs.push_back(VD);
9839 CombinedInfo.BasePointers.push_back(ThisLVal.getPointer(CGF));
9840 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
9841 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
9842 CombinedInfo.Pointers.push_back(ThisLValVal.getPointer(CGF));
9843 CombinedInfo.Sizes.push_back(
9846 CombinedInfo.Types.push_back(
9847 OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ |
9848 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL |
9849 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF |
9850 OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT);
9851 CombinedInfo.HasAttachPtr.push_back(
false);
9852 CombinedInfo.Mappers.push_back(
nullptr);
9854 for (
const LambdaCapture &LC : RD->
captures()) {
9855 if (!LC.capturesVariable())
9860 auto It = Captures.find(VD);
9861 assert(It != Captures.end() &&
"Found lambda capture without field.");
9865 LambdaPointers.try_emplace(VarLVal.getPointer(CGF),
9866 VDLVal.getPointer(CGF));
9867 CombinedInfo.Exprs.push_back(VD);
9868 CombinedInfo.BasePointers.push_back(VarLVal.getPointer(CGF));
9869 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
9870 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
9871 CombinedInfo.Pointers.push_back(VarLValVal.getPointer(CGF));
9872 CombinedInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
9878 LambdaPointers.try_emplace(VarLVal.getPointer(CGF),
9879 VDLVal.getPointer(CGF));
9880 CombinedInfo.Exprs.push_back(VD);
9881 CombinedInfo.BasePointers.push_back(VarLVal.getPointer(CGF));
9882 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
9883 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
9884 CombinedInfo.Pointers.push_back(VarRVal.
getScalarVal());
9885 CombinedInfo.Sizes.push_back(llvm::ConstantInt::get(CGF.
Int64Ty, 0));
9887 CombinedInfo.Types.push_back(
9888 OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ |
9889 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL |
9890 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF |
9891 OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT);
9892 CombinedInfo.HasAttachPtr.push_back(
false);
9893 CombinedInfo.Mappers.push_back(
nullptr);
9898 void adjustMemberOfForLambdaCaptures(
9899 llvm::OpenMPIRBuilder &OMPBuilder,
9900 const llvm::DenseMap<llvm::Value *, llvm::Value *> &LambdaPointers,
9901 MapBaseValuesArrayTy &BasePointers, MapValuesArrayTy &Pointers,
9902 MapFlagsArrayTy &Types)
const {
9903 for (
unsigned I = 0, E = Types.size(); I < E; ++I) {
9905 if (Types[I] != (OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ |
9906 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL |
9907 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF |
9908 OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT))
9910 llvm::Value *BasePtr = LambdaPointers.lookup(BasePointers[I]);
9911 assert(BasePtr &&
"Unable to find base lambda address.");
9913 for (
unsigned J = I; J > 0; --J) {
9914 unsigned Idx = J - 1;
9915 if (Pointers[Idx] != BasePtr)
9920 assert(TgtIdx != -1 &&
"Unable to find parent lambda.");
9924 OpenMPOffloadMappingFlags MemberOfFlag =
9925 OMPBuilder.getMemberOfFlag(TgtIdx);
9926 OMPBuilder.setCorrectMemberOfFlag(Types[I], MemberOfFlag);
9932 void populateComponentListsForNonLambdaCaptureFromClauses(
9933 const ValueDecl *VD, MapDataArrayTy &DeclComponentLists,
9935 SmallVector<OMPClauseMappableExprCommon::MappableComponent, 8>>
9936 &StorageForImplicitlyAddedComponentLists)
const {
9937 if (VD && LambdasMap.count(VD))
9943 auto It = DevPointersMap.find(VD);
9944 if (It != DevPointersMap.end())
9945 for (
const auto &MCL : It->second)
9946 DeclComponentLists.emplace_back(MCL, OMPC_MAP_to,
Unknown,
9949 auto I = HasDevAddrsMap.find(VD);
9950 if (I != HasDevAddrsMap.end())
9951 for (
const auto &MCL : I->second)
9952 DeclComponentLists.emplace_back(MCL, OMPC_MAP_tofrom,
Unknown,
9956 "Expect a executable directive");
9958 for (
const auto *
C : CurExecDir->getClausesOfKind<OMPMapClause>()) {
9959 const auto *EI =
C->getVarRefs().begin();
9960 for (
const auto L :
C->decl_component_lists(VD)) {
9961 const ValueDecl *VDecl, *Mapper;
9963 const Expr *E = (
C->getMapLoc().isValid()) ? *EI :
nullptr;
9965 std::tie(VDecl, Components, Mapper) = L;
9966 assert(VDecl == VD &&
"We got information for the wrong declaration??");
9967 assert(!Components.empty() &&
9968 "Not expecting declaration with no component lists.");
9969 DeclComponentLists.emplace_back(Components,
C->getMapType(),
9970 C->getMapTypeModifiers(),
9971 C->isImplicit(), Mapper, E);
9980 addImplicitMapForAttachPtrBaseIfMemberOfCapturedVD(
9981 VD, DeclComponentLists, StorageForImplicitlyAddedComponentLists);
9983 llvm::stable_sort(DeclComponentLists, [](
const MapData &LHS,
9984 const MapData &RHS) {
9985 ArrayRef<OpenMPMapModifierKind> MapModifiers = std::get<2>(LHS);
9988 llvm::is_contained(MapModifiers, clang::OMPC_MAP_MODIFIER_present);
9989 bool HasAllocs = MapType == OMPC_MAP_alloc;
9990 MapModifiers = std::get<2>(RHS);
9991 MapType = std::get<1>(LHS);
9993 llvm::is_contained(MapModifiers, clang::OMPC_MAP_MODIFIER_present);
9994 bool HasAllocsR = MapType == OMPC_MAP_alloc;
9995 return (HasPresent && !HasPresentR) || (HasAllocs && !HasAllocsR);
10031 void addImplicitMapForAttachPtrBaseIfMemberOfCapturedVD(
10032 const ValueDecl *CapturedVD, MapDataArrayTy &DeclComponentLists,
10034 SmallVector<OMPClauseMappableExprCommon::MappableComponent, 8>>
10035 &ComponentVectorStorage)
const {
10036 bool IsThisCapture = CapturedVD ==
nullptr;
10038 for (
const auto &ComponentsAndAttachPtr : AttachPtrExprMap) {
10040 ComponentsWithAttachPtr = ComponentsAndAttachPtr.first;
10041 const Expr *AttachPtrExpr = ComponentsAndAttachPtr.second;
10042 if (!AttachPtrExpr)
10045 const auto *ME = dyn_cast<MemberExpr>(AttachPtrExpr);
10049 const Expr *
Base = ME->getBase()->IgnoreParenImpCasts();
10070 bool FoundExistingMap =
false;
10071 for (
const MapData &ExistingL : DeclComponentLists) {
10073 ExistingComponents = std::get<0>(ExistingL);
10075 if (ExistingComponents.empty())
10079 const auto &FirstComponent = ExistingComponents.front();
10080 const Expr *FirstExpr = FirstComponent.getAssociatedExpression();
10086 if (AttachPtrComparator.areEqual(FirstExpr, AttachPtrExpr)) {
10087 FoundExistingMap =
true;
10092 if (IsThisCapture) {
10093 if (
const auto *OASE = dyn_cast<ArraySectionExpr>(FirstExpr)) {
10095 FoundExistingMap =
true;
10104 if (
const auto *DRE = dyn_cast<DeclRefExpr>(FirstExpr)) {
10105 if (DRE->getDecl() == CapturedVD) {
10106 FoundExistingMap =
true;
10112 if (FoundExistingMap)
10118 ComponentVectorStorage.emplace_back();
10119 auto &AttachPtrComponents = ComponentVectorStorage.back();
10122 bool SeenAttachPtrComponent =
false;
10128 for (
size_t i = 0; i < ComponentsWithAttachPtr.size(); ++i) {
10129 const auto &Component = ComponentsWithAttachPtr[i];
10130 const Expr *ComponentExpr = Component.getAssociatedExpression();
10132 if (!SeenAttachPtrComponent && ComponentExpr != AttachPtrExpr)
10134 SeenAttachPtrComponent =
true;
10136 AttachPtrComponents.emplace_back(Component.getAssociatedExpression(),
10137 Component.getAssociatedDeclaration(),
10138 Component.isNonContiguous());
10140 assert(!AttachPtrComponents.empty() &&
10141 "Could not populate component-lists for mapping attach-ptr");
10143 DeclComponentLists.emplace_back(
10144 AttachPtrComponents, OMPC_MAP_tofrom,
Unknown,
10145 true,
nullptr, AttachPtrExpr);
10152 void generateInfoForCaptureFromClauseInfo(
10153 const MapDataArrayTy &DeclComponentListsFromClauses,
10154 const CapturedStmt::Capture *Cap, llvm::Value *Arg,
10155 MapCombinedInfoTy &CurCaptureVarInfo, llvm::OpenMPIRBuilder &OMPBuilder,
10156 unsigned OffsetForMemberOfFlag)
const {
10158 "Not expecting to generate map info for a variable array type!");
10167 if (LambdasMap.count(VD))
10173 if (VD && (DevPointersMap.count(VD) || HasDevAddrsMap.count(VD))) {
10174 CurCaptureVarInfo.Exprs.push_back(VD);
10175 CurCaptureVarInfo.BasePointers.emplace_back(Arg);
10176 CurCaptureVarInfo.DevicePtrDecls.emplace_back(VD);
10177 CurCaptureVarInfo.DevicePointers.emplace_back(DeviceInfoTy::Pointer);
10178 CurCaptureVarInfo.Pointers.push_back(Arg);
10179 CurCaptureVarInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
10182 CurCaptureVarInfo.Types.push_back(
10183 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL |
10184 OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM);
10185 CurCaptureVarInfo.HasAttachPtr.push_back(
false);
10186 CurCaptureVarInfo.Mappers.push_back(
nullptr);
10190 auto GenerateInfoForComponentLists =
10191 [&](ArrayRef<MapData> DeclComponentListsFromClauses,
10192 bool IsEligibleForTargetParamFlag) {
10193 MapCombinedInfoTy CurInfoForComponentLists;
10194 StructRangeInfoTy PartialStruct;
10195 AttachInfoTy AttachInfo;
10197 if (DeclComponentListsFromClauses.empty())
10200 generateInfoForCaptureFromComponentLists(
10201 VD, DeclComponentListsFromClauses, CurInfoForComponentLists,
10202 PartialStruct, AttachInfo, IsEligibleForTargetParamFlag);
10207 if (PartialStruct.Base.isValid()) {
10208 CurCaptureVarInfo.append(PartialStruct.PreliminaryMapData);
10210 CurCaptureVarInfo, CurInfoForComponentLists.Types,
10211 PartialStruct, AttachInfo, Cap->
capturesThis(), OMPBuilder,
10212 nullptr, OffsetForMemberOfFlag,
10213 !IsEligibleForTargetParamFlag);
10218 CurCaptureVarInfo.append(CurInfoForComponentLists);
10219 if (AttachInfo.isValid())
10220 emitAttachEntry(CGF, CurCaptureVarInfo, AttachInfo);
10244 SmallVector<std::pair<const Expr *, MapData>, 16> AttachPtrMapDataPairs;
10246 for (
const MapData &L : DeclComponentListsFromClauses) {
10249 const Expr *AttachPtrExpr = getAttachPtrExpr(Components);
10250 AttachPtrMapDataPairs.emplace_back(AttachPtrExpr, L);
10254 llvm::stable_sort(AttachPtrMapDataPairs,
10255 [
this](
const auto &LHS,
const auto &RHS) {
10256 return AttachPtrComparator(LHS.first, RHS.first);
10259 bool NoDefaultMappingDoneForVD = CurCaptureVarInfo.BasePointers.empty();
10260 bool IsFirstGroup =
true;
10264 auto *It = AttachPtrMapDataPairs.begin();
10265 while (It != AttachPtrMapDataPairs.end()) {
10266 const Expr *AttachPtrExpr = It->first;
10268 MapDataArrayTy GroupLists;
10269 while (It != AttachPtrMapDataPairs.end() &&
10270 (It->first == AttachPtrExpr ||
10271 AttachPtrComparator.areEqual(It->first, AttachPtrExpr))) {
10272 GroupLists.push_back(It->second);
10275 assert(!GroupLists.empty() &&
"GroupLists should not be empty");
10280 bool IsEligibleForTargetParamFlag =
10281 IsFirstGroup && NoDefaultMappingDoneForVD;
10283 GenerateInfoForComponentLists(GroupLists, IsEligibleForTargetParamFlag);
10284 IsFirstGroup =
false;
10291 void generateInfoForCaptureFromComponentLists(
10292 const ValueDecl *VD, ArrayRef<MapData> DeclComponentLists,
10293 MapCombinedInfoTy &CurComponentListInfo, StructRangeInfoTy &PartialStruct,
10294 AttachInfoTy &AttachInfo,
bool IsListEligibleForTargetParamFlag)
const {
10296 llvm::SmallDenseMap<
10303 for (
const MapData &L : DeclComponentLists) {
10306 ArrayRef<OpenMPMapModifierKind> MapModifiers;
10308 const ValueDecl *Mapper;
10309 const Expr *VarRef;
10310 std::tie(Components, MapType, MapModifiers, IsImplicit, Mapper, VarRef) =
10313 for (
const MapData &L1 : ArrayRef(DeclComponentLists).slice(Count)) {
10315 std::tie(Components1, MapType, MapModifiers, IsImplicit, Mapper,
10317 auto CI = Components.rbegin();
10318 auto CE = Components.rend();
10319 auto SI = Components1.rbegin();
10320 auto SE = Components1.rend();
10321 for (; CI != CE && SI != SE; ++CI, ++SI) {
10322 if (CI->getAssociatedExpression()->getStmtClass() !=
10323 SI->getAssociatedExpression()->getStmtClass())
10326 if (CI->getAssociatedDeclaration() != SI->getAssociatedDeclaration())
10331 if (CI == CE || SI == SE) {
10333 if (CI == CE && SI == SE)
10335 const auto It = (SI == SE) ? CI : SI;
10342 (std::prev(It)->getAssociatedDeclaration() &&
10344 ->getAssociatedDeclaration()
10346 ->isPointerType()) ||
10347 (It->getAssociatedDeclaration() &&
10348 It->getAssociatedDeclaration()->getType()->isPointerType() &&
10349 std::next(It) != CE && std::next(It) != SE))
10351 const MapData &BaseData = CI == CE ? L : L1;
10353 SI == SE ? Components : Components1;
10354 OverlappedData[&BaseData].push_back(SubData);
10359 llvm::SmallVector<const FieldDecl *, 4> Layout;
10360 if (!OverlappedData.empty()) {
10363 while (BaseType != OrigType) {
10369 getPlainLayout(CRD, Layout,
false);
10375 for (
auto &Pair : OverlappedData) {
10382 auto CI = First.rbegin();
10383 auto CE = First.rend();
10384 auto SI = Second.rbegin();
10385 auto SE = Second.rend();
10386 for (; CI != CE && SI != SE; ++CI, ++SI) {
10387 if (CI->getAssociatedExpression()->getStmtClass() !=
10388 SI->getAssociatedExpression()->getStmtClass())
10391 if (CI->getAssociatedDeclaration() !=
10392 SI->getAssociatedDeclaration())
10397 if (CI == CE && SI == SE)
10401 if (CI == CE || SI == SE)
10406 if (FD1->getParent() == FD2->getParent())
10407 return FD1->getFieldIndex() < FD2->getFieldIndex();
10409 llvm::find_if(Layout, [FD1, FD2](
const FieldDecl *FD) {
10410 return FD == FD1 || FD == FD2;
10418 bool AddTargetParamFlag = IsListEligibleForTargetParamFlag;
10419 MapCombinedInfoTy StructBaseCombinedInfo;
10420 for (
const auto &Pair : OverlappedData) {
10421 const MapData &L = *Pair.getFirst();
10424 ArrayRef<OpenMPMapModifierKind> MapModifiers;
10426 const ValueDecl *Mapper;
10427 const Expr *VarRef;
10428 std::tie(Components, MapType, MapModifiers, IsImplicit, Mapper, VarRef) =
10430 ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef>
10431 OverlappedComponents = Pair.getSecond();
10432 generateInfoForComponentList(
10433 MapType, MapModifiers, {}, Components, CurComponentListInfo,
10434 StructBaseCombinedInfo, PartialStruct, AttachInfo, AddTargetParamFlag,
10435 IsImplicit,
false, Mapper,
10436 false, VD, VarRef, OverlappedComponents);
10437 AddTargetParamFlag =
false;
10440 for (
const MapData &L : DeclComponentLists) {
10443 ArrayRef<OpenMPMapModifierKind> MapModifiers;
10445 const ValueDecl *Mapper;
10446 const Expr *VarRef;
10447 std::tie(Components, MapType, MapModifiers, IsImplicit, Mapper, VarRef) =
10449 auto It = OverlappedData.find(&L);
10450 if (It == OverlappedData.end())
10451 generateInfoForComponentList(
10452 MapType, MapModifiers, {}, Components, CurComponentListInfo,
10453 StructBaseCombinedInfo, PartialStruct, AttachInfo,
10454 AddTargetParamFlag, IsImplicit,
false,
10455 Mapper,
false, VD, VarRef,
10457 AddTargetParamFlag =
false;
10463 bool isEffectivelyFirstprivate(
const VarDecl *VD, QualType
Type)
const {
10465 auto I = FirstPrivateDecls.find(VD);
10466 if (I != FirstPrivateDecls.end() && !I->getSecond())
10470 if (DefaultmapFirstprivateKinds.count(OMPC_DEFAULTMAP_scalar)) {
10471 if (
Type->isScalarType())
10476 if (DefaultmapFirstprivateKinds.count(OMPC_DEFAULTMAP_pointer)) {
10477 if (
Type->isAnyPointerType())
10482 if (DefaultmapFirstprivateKinds.count(OMPC_DEFAULTMAP_aggregate)) {
10483 if (
Type->isAggregateType())
10488 return DefaultmapFirstprivateKinds.count(OMPC_DEFAULTMAP_all);
10493 void generateDefaultMapInfo(
const CapturedStmt::Capture &CI,
10494 const FieldDecl &RI, llvm::Value *CV,
10495 MapCombinedInfoTy &CombinedInfo)
const {
10496 bool IsImplicit =
true;
10499 CombinedInfo.Exprs.push_back(
nullptr);
10500 CombinedInfo.BasePointers.push_back(CV);
10501 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
10502 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
10503 CombinedInfo.Pointers.push_back(CV);
10505 CombinedInfo.Sizes.push_back(
10509 CombinedInfo.Types.push_back(OpenMPOffloadMappingFlags::OMP_MAP_TO |
10510 OpenMPOffloadMappingFlags::OMP_MAP_FROM);
10514 CombinedInfo.BasePointers.push_back(CV);
10515 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
10516 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
10517 CombinedInfo.Pointers.push_back(CV);
10518 bool IsFirstprivate =
10524 CombinedInfo.Types.push_back(
10525 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL);
10526 CombinedInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
10528 }
else if (IsFirstprivate) {
10531 CombinedInfo.Types.push_back(
10532 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL);
10534 CombinedInfo.Sizes.push_back(llvm::Constant::getNullValue(CGF.
Int64Ty));
10538 CombinedInfo.Types.push_back(OpenMPOffloadMappingFlags::OMP_MAP_NONE);
10539 CombinedInfo.Sizes.push_back(llvm::Constant::getNullValue(CGF.
Int64Ty));
10541 auto I = FirstPrivateDecls.find(VD);
10542 if (I != FirstPrivateDecls.end())
10543 IsImplicit = I->getSecond();
10549 bool IsFirstprivate = isEffectivelyFirstprivate(VD, ElementType);
10551 CombinedInfo.BasePointers.push_back(CV);
10552 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
10553 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
10556 if (IsFirstprivate && ElementType->isAnyPointerType()) {
10558 CombinedInfo.Pointers.push_back(CV);
10560 CombinedInfo.Sizes.push_back(llvm::Constant::getNullValue(CGF.
Int64Ty));
10561 CombinedInfo.Types.push_back(
10562 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL);
10564 CombinedInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
10569 CombinedInfo.Types.push_back(getMapModifiersForPrivateClauses(CI));
10570 CombinedInfo.Pointers.push_back(CV);
10572 auto I = FirstPrivateDecls.find(VD);
10573 if (I != FirstPrivateDecls.end())
10574 IsImplicit = I->getSecond();
10577 CombinedInfo.Types.back() |=
10578 OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM;
10582 CombinedInfo.Types.back() |= OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT;
10584 CombinedInfo.HasAttachPtr.push_back(
false);
10586 CombinedInfo.Mappers.push_back(
nullptr);
10598 dyn_cast<MemberExpr>(OASE->getBase()->IgnoreParenImpCasts()))
10599 return ME->getMemberDecl();
10605static llvm::Constant *
10607 MappableExprsHandler::MappingExprInfo &MapExprs) {
10610 if (!MapExprs.getMapDecl() && !MapExprs.getMapExpr())
10611 return OMPBuilder.getOrCreateDefaultSrcLocStr(SrcLocStrSize);
10614 if (!MapExprs.getMapDecl() && MapExprs.getMapExpr()) {
10618 Loc = MapExprs.getMapExpr()->getExprLoc();
10620 Loc = MapExprs.getMapDecl()->getLocation();
10623 std::string ExprName;
10624 if (MapExprs.getMapExpr()) {
10626 llvm::raw_string_ostream OS(ExprName);
10627 MapExprs.getMapExpr()->printPretty(OS,
nullptr, P);
10629 ExprName = MapExprs.getMapDecl()->getNameAsString();
10638 return OMPBuilder.getOrCreateSrcLocStr(
FileName, ExprName, PLoc.
getLine(),
10645 CodeGenFunction &CGF, MappableExprsHandler::MapCombinedInfoTy &CombinedInfo,
10647 bool IsNonContiguous =
false,
bool ForEndCall =
false) {
10650 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
10652 InsertPointTy CodeGenIP(CGF.
Builder.GetInsertPoint());
10654 auto DeviceAddrCB = [&](
unsigned int I, llvm::Value *NewDecl) {
10655 if (
const ValueDecl *DevVD = CombinedInfo.DevicePtrDecls[I]) {
10660 auto CustomMapperCB = [&](
unsigned int I) {
10661 llvm::Function *MFunc =
nullptr;
10662 if (CombinedInfo.Mappers[I]) {
10663 Info.HasMapper =
true;
10669 cantFail(OMPBuilder.emitOffloadingArraysAndArgs(
10670 AllocaIP, CodeGenIP, Info, Info.RTArgs, CombinedInfo, CustomMapperCB,
10671 IsNonContiguous, ForEndCall, DeviceAddrCB));
10675static const OMPExecutableDirective *
10677 const auto *CS = D.getInnermostCapturedStmt();
10680 const Stmt *ChildStmt =
10683 if (
const auto *NestedDir =
10684 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) {
10686 switch (D.getDirectiveKind()) {
10692 if (DKind == OMPD_teams) {
10693 Body = NestedDir->getInnermostCapturedStmt()->IgnoreContainers(
10698 if (
const auto *NND =
10699 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) {
10700 DKind = NND->getDirectiveKind();
10706 case OMPD_target_teams:
10710 case OMPD_target_parallel:
10711 case OMPD_target_simd:
10712 case OMPD_target_parallel_for:
10713 case OMPD_target_parallel_for_simd:
10715 case OMPD_target_teams_distribute:
10716 case OMPD_target_teams_distribute_simd:
10717 case OMPD_target_teams_distribute_parallel_for:
10718 case OMPD_target_teams_distribute_parallel_for_simd:
10719 case OMPD_parallel:
10721 case OMPD_parallel_for:
10722 case OMPD_parallel_master:
10723 case OMPD_parallel_sections:
10724 case OMPD_for_simd:
10725 case OMPD_parallel_for_simd:
10727 case OMPD_cancellation_point:
10728 case OMPD_ordered_standalone:
10729 case OMPD_ordered_blockassoc:
10730 case OMPD_threadprivate:
10731 case OMPD_allocate:
10736 case OMPD_sections:
10740 case OMPD_critical:
10741 case OMPD_taskyield:
10743 case OMPD_taskwait:
10744 case OMPD_taskgroup:
10750 case OMPD_target_data:
10751 case OMPD_target_exit_data:
10752 case OMPD_target_enter_data:
10753 case OMPD_distribute:
10754 case OMPD_distribute_simd:
10755 case OMPD_distribute_parallel_for:
10756 case OMPD_distribute_parallel_for_simd:
10757 case OMPD_teams_distribute:
10758 case OMPD_teams_distribute_simd:
10759 case OMPD_teams_distribute_parallel_for:
10760 case OMPD_teams_distribute_parallel_for_simd:
10761 case OMPD_target_update:
10762 case OMPD_declare_simd:
10763 case OMPD_declare_variant:
10764 case OMPD_begin_declare_variant:
10765 case OMPD_end_declare_variant:
10766 case OMPD_declare_target:
10767 case OMPD_end_declare_target:
10768 case OMPD_declare_reduction:
10769 case OMPD_declare_mapper:
10770 case OMPD_taskloop:
10771 case OMPD_taskloop_simd:
10772 case OMPD_master_taskloop:
10773 case OMPD_master_taskloop_simd:
10774 case OMPD_parallel_master_taskloop:
10775 case OMPD_parallel_master_taskloop_simd:
10776 case OMPD_requires:
10777 case OMPD_metadirective:
10780 llvm_unreachable(
"Unexpected directive.");
10840 if (
UDMMap.count(D) > 0)
10844 auto *MapperVarDecl =
10846 CharUnits ElementSize =
C.getTypeSizeInChars(Ty);
10847 llvm::Type *ElemTy =
CGM.getTypes().ConvertTypeForMem(Ty);
10850 MappableExprsHandler::MapCombinedInfoTy CombinedInfo;
10851 auto PrivatizeAndGenMapInfoCB =
10852 [&](llvm::OpenMPIRBuilder::InsertPointTy CodeGenIP, llvm::Value *PtrPHI,
10853 llvm::Value *BeginArg) -> llvm::OpenMPIRBuilder::MapInfosTy & {
10854 MapperCGF.
Builder.restoreIP(CodeGenIP);
10864 Scope.addPrivate(MapperVarDecl, PtrCurrent);
10865 (void)
Scope.Privatize();
10868 MappableExprsHandler MEHandler(*D, MapperCGF);
10869 MEHandler.generateAllInfoForMapper(CombinedInfo,
OMPBuilder);
10871 auto FillInfoMap = [&](MappableExprsHandler::MappingExprInfo &MapExpr) {
10874 if (
CGM.getCodeGenOpts().getDebugInfo() !=
10875 llvm::codegenoptions::NoDebugInfo) {
10876 CombinedInfo.Names.resize(CombinedInfo.Exprs.size());
10877 llvm::transform(CombinedInfo.Exprs, CombinedInfo.Names.begin(),
10881 return CombinedInfo;
10884 auto CustomMapperCB = [&](
unsigned I) {
10885 llvm::Function *MapperFunc =
nullptr;
10886 if (CombinedInfo.Mappers[I]) {
10890 assert(MapperFunc &&
"Expect a valid mapper function is available.");
10896 llvm::raw_svector_ostream Out(TyStr);
10897 CGM.getCXXABI().getMangleContext().mangleCanonicalTypeName(Ty, Out);
10898 std::string Name =
getName({
"omp_mapper", TyStr, D->
getName()});
10904 bool PropagatePresentToPointee =
CGM.getLangOpts().OpenMP >= 60;
10905 llvm::Function *NewFn = cantFail(
OMPBuilder.emitUserDefinedMapper(
10906 PrivatizeAndGenMapInfoCB, ElemTy, Name, CustomMapperCB,
10907 false, PropagatePresentToPointee));
10908 UDMMap.try_emplace(D, NewFn);
10915 auto I =
UDMMap.find(D);
10919 return UDMMap.lookup(D);
10932 Kind != OMPD_target_teams_loop)
10935 return llvm::ConstantInt::get(CGF.
Int64Ty, 0);
10938 if (llvm::Value *NumIterations = SizeEmitter(CGF, *LD))
10939 return NumIterations;
10940 return llvm::ConstantInt::get(CGF.
Int64Ty, 0);
10949 if (OffloadingMandatory) {
10950 CGF.
Builder.CreateUnreachable();
10952 if (RequiresOuterTask) {
10953 CapturedVars.clear();
10957 CapturedVars.end());
10958 Args.push_back(llvm::Constant::getNullValue(CGF.
Builder.getPtrTy()));
10965 llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier>
Device,
10968 llvm::Value *DeviceID;
10969 if (
Device.getPointer()) {
10971 Device.getInt() == OMPC_DEVICE_device_num) &&
10972 "Expected device_num modifier.");
10977 DeviceID = CGF.
Builder.getInt64(OMP_DEVICEID_UNDEF);
10982static std::pair<llvm::Value *, OMPDynGroupprivateFallbackType>
10984 llvm::Value *DynGP = CGF.
Builder.getInt32(0);
10985 auto DynGPFallback = OMPDynGroupprivateFallbackType::Abort;
10989 llvm::Value *DynGPVal =
10993 auto FallbackModifier = DynGPClause->getDynGroupprivateFallbackModifier();
10994 switch (FallbackModifier) {
10995 case OMPC_DYN_GROUPPRIVATE_FALLBACK_abort:
10996 DynGPFallback = OMPDynGroupprivateFallbackType::Abort;
10998 case OMPC_DYN_GROUPPRIVATE_FALLBACK_null:
10999 DynGPFallback = OMPDynGroupprivateFallbackType::Null;
11001 case OMPC_DYN_GROUPPRIVATE_FALLBACK_default_mem:
11004 DynGPFallback = OMPDynGroupprivateFallbackType::DefaultMem;
11007 llvm_unreachable(
"Unknown fallback modifier for OpenMP dyn_groupprivate");
11009 }
else if (
auto *OMPXDynCGClause =
11012 llvm::Value *DynCGMemVal = CGF.
EmitScalarExpr(OMPXDynCGClause->getSize(),
11017 return {DynGP, DynGPFallback};
11023 llvm::OpenMPIRBuilder &OMPBuilder,
11025 MappableExprsHandler::MapCombinedInfoTy &CombinedInfo) {
11027 llvm::DenseMap<llvm::Value *, llvm::Value *> LambdaPointers;
11029 auto *CV = CapturedVars.begin();
11032 CI != CE; ++CI, ++RI, ++CV) {
11033 MappableExprsHandler::MapCombinedInfoTy CurInfo;
11038 CurInfo.Exprs.push_back(
nullptr);
11039 CurInfo.BasePointers.push_back(*CV);
11040 CurInfo.DevicePtrDecls.push_back(
nullptr);
11041 CurInfo.DevicePointers.push_back(
11042 MappableExprsHandler::DeviceInfoTy::None);
11043 CurInfo.Pointers.push_back(*CV);
11044 CurInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
11047 CurInfo.Types.push_back(OpenMPOffloadMappingFlags::OMP_MAP_LITERAL |
11048 OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM |
11049 OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT);
11050 CurInfo.HasAttachPtr.push_back(
false);
11051 CurInfo.Mappers.push_back(
nullptr);
11056 bool HasEntryWithCVAsAttachPtr =
false;
11058 HasEntryWithCVAsAttachPtr =
11059 MEHandler.hasAttachEntryForCapturedVar(CapturedVD);
11062 MappableExprsHandler::MapDataArrayTy DeclComponentLists;
11065 StorageForImplicitlyAddedComponentLists;
11066 MEHandler.populateComponentListsForNonLambdaCaptureFromClauses(
11067 CapturedVD, DeclComponentLists,
11068 StorageForImplicitlyAddedComponentLists);
11079 bool HasEntryWithoutAttachPtr =
11080 llvm::any_of(DeclComponentLists, [&](
const auto &MapData) {
11082 Components = std::get<0>(MapData);
11083 return !MEHandler.getAttachPtrExpr(Components);
11088 if (DeclComponentLists.empty() ||
11089 (!HasEntryWithCVAsAttachPtr && !HasEntryWithoutAttachPtr))
11090 MEHandler.generateDefaultMapInfo(*CI, **RI, *CV, CurInfo);
11094 MEHandler.generateInfoForCaptureFromClauseInfo(
11095 DeclComponentLists, CI, *CV, CurInfo, OMPBuilder,
11096 CombinedInfo.BasePointers.size());
11101 MappedVarSet.insert(
nullptr);
11106 MEHandler.generateInfoForLambdaCaptures(CI->
getCapturedVar(), *CV,
11107 CurInfo, LambdaPointers);
11110 assert(!CurInfo.BasePointers.empty() &&
11111 "Non-existing map pointer for capture!");
11112 assert(CurInfo.BasePointers.size() == CurInfo.Pointers.size() &&
11113 CurInfo.BasePointers.size() == CurInfo.Sizes.size() &&
11114 CurInfo.BasePointers.size() == CurInfo.Types.size() &&
11115 CurInfo.BasePointers.size() == CurInfo.Mappers.size() &&
11116 "Inconsistent map information sizes!");
11119 CombinedInfo.append(CurInfo);
11122 MEHandler.adjustMemberOfForLambdaCaptures(
11123 OMPBuilder, LambdaPointers, CombinedInfo.BasePointers,
11124 CombinedInfo.Pointers, CombinedInfo.Types);
11128 MappableExprsHandler::MapCombinedInfoTy &CombinedInfo,
11129 llvm::OpenMPIRBuilder &OMPBuilder,
11136 MEHandler.generateAllInfo(CombinedInfo, OMPBuilder, SkippedVarSet);
11138 auto FillInfoMap = [&](MappableExprsHandler::MappingExprInfo &MapExpr) {
11142 llvm::codegenoptions::NoDebugInfo) {
11143 CombinedInfo.Names.resize(CombinedInfo.Exprs.size());
11144 llvm::transform(CombinedInfo.Exprs, CombinedInfo.Names.begin(),
11152 llvm::OpenMPIRBuilder &OMPBuilder,
11153 MappableExprsHandler::MapCombinedInfoTy &CombinedInfo) {
11155 MappableExprsHandler MEHandler(D, CGF);
11156 llvm::DenseSet<CanonicalDeclPtr<const Decl>> MappedVarSet;
11159 MappedVarSet, CombinedInfo);
11160 genMapInfo(MEHandler, CGF, CombinedInfo, OMPBuilder, MappedVarSet);
11163template <
typename ClauseTy>
11168 const auto *
C = D.getSingleClause<ClauseTy>();
11169 assert(!
C->varlist_empty() &&
11170 "ompx_bare requires explicit num_teams and thread_limit");
11172 for (
auto *E :
C->varlist()) {
11184 llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier>
Device,
11186 llvm::Value *&MapTypesArray, llvm::Value *&MapNamesArray,
11191 llvm::OpenMPIRBuilder &OMPBuilder = OMPRuntime->
getOMPBuilder();
11194 MappableExprsHandler::MapCombinedInfoTy CombinedInfo;
11196 genMapInfo(D, CGF, CS, CapturedVars, OMPBuilder, CombinedInfo);
11199 using OpenMPOffloadMappingFlags = llvm::omp::OpenMPOffloadMappingFlags;
11200 auto *NullPtr = llvm::Constant::getNullValue(CGF.
Builder.getPtrTy());
11201 CombinedInfo.BasePointers.push_back(NullPtr);
11202 CombinedInfo.Pointers.push_back(NullPtr);
11203 CombinedInfo.DevicePointers.push_back(
11204 llvm::OpenMPIRBuilder::DeviceInfoTy::None);
11205 CombinedInfo.Sizes.push_back(CGF.
Builder.getInt64(0));
11206 CombinedInfo.Types.push_back(OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM |
11207 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL);
11208 CombinedInfo.HasAttachPtr.push_back(
false);
11209 if (!CombinedInfo.Names.empty())
11210 CombinedInfo.Names.push_back(NullPtr);
11211 CombinedInfo.Exprs.push_back(
nullptr);
11212 CombinedInfo.Mappers.push_back(
nullptr);
11213 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
11227 MapTypesArray = Info.RTArgs.MapTypesArray;
11228 MapNamesArray = Info.RTArgs.MapNamesArray;
11230 auto &&ThenGen = [&OMPRuntime, OutlinedFn, &D, &CapturedVars,
11231 RequiresOuterTask, &CS, OffloadingMandatory,
Device,
11232 OutlinedFnID, &InputInfo, &MapTypesArray, &MapNamesArray,
11234 bool IsReverseOffloading =
Device.getInt() == OMPC_DEVICE_ancestor;
11236 if (IsReverseOffloading) {
11242 RequiresOuterTask, CS, OffloadingMandatory, CGF);
11246 bool HasNoWait = D.hasClausesOfKind<OMPNowaitClause>();
11247 unsigned NumTargetItems = InputInfo.NumberOfTargetItems;
11249 llvm::Value *BasePointersArray =
11250 InputInfo.BasePointersArray.emitRawPointer(CGF);
11251 llvm::Value *PointersArray = InputInfo.PointersArray.emitRawPointer(CGF);
11252 llvm::Value *SizesArray = InputInfo.SizesArray.emitRawPointer(CGF);
11253 llvm::Value *MappersArray = InputInfo.MappersArray.emitRawPointer(CGF);
11255 auto &&EmitTargetCallFallbackCB =
11256 [&OMPRuntime, OutlinedFn, &D, &CapturedVars, RequiresOuterTask, &CS,
11257 OffloadingMandatory, &CGF](llvm::OpenMPIRBuilder::InsertPointTy IP)
11258 -> llvm::OpenMPIRBuilder::InsertPointTy {
11261 RequiresOuterTask, CS, OffloadingMandatory, CGF);
11274 NumThreads.push_back(
11280 llvm::Value *NumIterations =
11283 llvm::OpenMPIRBuilder::InsertPointTy AllocaIP(
11286 llvm::OpenMPIRBuilder::TargetDataRTArgs RTArgs(
11287 BasePointersArray, PointersArray, SizesArray, MapTypesArray,
11288 nullptr , MappersArray, MapNamesArray);
11290 llvm::OpenMPIRBuilder::TargetKernelArgs Args(
11291 NumTargetItems, RTArgs, NumIterations, NumTeams, NumThreads,
11292 DynCGroupMem, HasNoWait, IsBare,
11293 IsBare, DynCGroupMemFallback);
11295 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
11297 CGF.
Builder, OutlinedFnID, EmitTargetCallFallbackCB, Args, DeviceID,
11299 CGF.
Builder.restoreIP(AfterIP);
11302 if (RequiresOuterTask)
11317 [&OMPRuntime, OutlinedFn, &D, &CapturedVars, RequiresOuterTask, &CS,
11320 RequiresOuterTask, CS, OffloadingMandatory, CGF);
11323 if (RequiresOuterTask) {
11333 llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID,
const Expr *IfCond,
11334 llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier>
Device,
11341 const bool OffloadingMandatory = !
CGM.getLangOpts().OpenMPIsTargetDevice &&
11342 CGM.getLangOpts().OpenMPOffloadMandatory;
11344 assert((OffloadingMandatory || OutlinedFn) &&
"Invalid outlined function!");
11346 const bool RequiresOuterTask =
11348 D.hasClausesOfKind<OMPNowaitClause>() ||
11349 D.hasClausesOfKind<OMPInReductionClause>() ||
11350 (
CGM.getLangOpts().OpenMP >= 51 &&
11354 const CapturedStmt &CS = *D.getCapturedStmt(OMPD_target);
11362 llvm::Value *MapTypesArray =
nullptr;
11363 llvm::Value *MapNamesArray =
nullptr;
11365 auto &&TargetThenGen = [
this, OutlinedFn, &D, &CapturedVars,
11366 RequiresOuterTask, &CS, OffloadingMandatory,
Device,
11367 OutlinedFnID, &InputInfo, &MapTypesArray,
11371 RequiresOuterTask, CS, OffloadingMandatory,
11372 Device, OutlinedFnID, InputInfo, MapTypesArray,
11373 MapNamesArray, SizeEmitter, CGF,
CGM);
11376 auto &&TargetElseGen =
11377 [
this, OutlinedFn, &D, &CapturedVars, RequiresOuterTask, &CS,
11380 CS, OffloadingMandatory, CGF);
11387 if (OutlinedFnID) {
11389 emitIfClause(CGF, IfCond, TargetThenGen, TargetElseGen);
11401 StringRef ParentName) {
11408 if (
auto *E = dyn_cast<OMPExecutableDirective>(S);
11417 bool RequiresDeviceCodegen =
11422 if (RequiresDeviceCodegen) {
11430 if (!
OMPBuilder.OffloadInfoManager.hasTargetRegionEntryInfo(EntryInfo))
11433 switch (E.getDirectiveKind()) {
11438 case OMPD_target_parallel:
11442 case OMPD_target_teams:
11446 case OMPD_target_teams_distribute:
11450 case OMPD_target_teams_distribute_simd:
11454 case OMPD_target_parallel_for:
11458 case OMPD_target_parallel_for_simd:
11462 case OMPD_target_simd:
11466 case OMPD_target_teams_distribute_parallel_for:
11471 case OMPD_target_teams_distribute_parallel_for_simd:
11477 case OMPD_target_teams_loop:
11481 case OMPD_target_parallel_loop:
11485 case OMPD_parallel:
11487 case OMPD_parallel_for:
11488 case OMPD_parallel_master:
11489 case OMPD_parallel_sections:
11490 case OMPD_for_simd:
11491 case OMPD_parallel_for_simd:
11493 case OMPD_cancellation_point:
11494 case OMPD_ordered_standalone:
11495 case OMPD_ordered_blockassoc:
11496 case OMPD_threadprivate:
11497 case OMPD_allocate:
11502 case OMPD_sections:
11506 case OMPD_critical:
11507 case OMPD_taskyield:
11509 case OMPD_taskwait:
11510 case OMPD_taskgroup:
11516 case OMPD_target_data:
11517 case OMPD_target_exit_data:
11518 case OMPD_target_enter_data:
11519 case OMPD_distribute:
11520 case OMPD_distribute_simd:
11521 case OMPD_distribute_parallel_for:
11522 case OMPD_distribute_parallel_for_simd:
11523 case OMPD_teams_distribute:
11524 case OMPD_teams_distribute_simd:
11525 case OMPD_teams_distribute_parallel_for:
11526 case OMPD_teams_distribute_parallel_for_simd:
11527 case OMPD_target_update:
11528 case OMPD_declare_simd:
11529 case OMPD_declare_variant:
11530 case OMPD_begin_declare_variant:
11531 case OMPD_end_declare_variant:
11532 case OMPD_declare_target:
11533 case OMPD_end_declare_target:
11534 case OMPD_declare_reduction:
11535 case OMPD_declare_mapper:
11536 case OMPD_taskloop:
11537 case OMPD_taskloop_simd:
11538 case OMPD_master_taskloop:
11539 case OMPD_master_taskloop_simd:
11540 case OMPD_parallel_master_taskloop:
11541 case OMPD_parallel_master_taskloop_simd:
11542 case OMPD_requires:
11543 case OMPD_metadirective:
11546 llvm_unreachable(
"Unknown target directive for OpenMP device codegen.");
11551 if (
const auto *E = dyn_cast<OMPExecutableDirective>(S)) {
11552 if (!E->hasAssociatedStmt() || !E->getAssociatedStmt())
11560 if (
const auto *L = dyn_cast<LambdaExpr>(S))
11569 std::optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
11570 OMPDeclareTargetDeclAttr::getDeviceType(VD);
11574 if (!IsDevice && DevTy == OMPDeclareTargetDeclAttr::DT_NoHost)
11577 if (IsDevice && DevTy == OMPDeclareTargetDeclAttr::DT_Host)
11585 if (!
CGM.getLangOpts().OpenMPIsTargetDevice) {
11586 if (
const auto *FD = dyn_cast<FunctionDecl>(GD.
getDecl()))
11588 CGM.getLangOpts().OpenMPIsTargetDevice))
11595 if (
const auto *FD = dyn_cast<FunctionDecl>(VD)) {
11596 StringRef Name =
CGM.getMangledName(GD);
11599 CGM.getLangOpts().OpenMPIsTargetDevice))
11604 return !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD) &&
11610 CGM.getLangOpts().OpenMPIsTargetDevice))
11613 if (!
CGM.getLangOpts().OpenMPIsTargetDevice)
11622 StringRef ParentName =
11627 StringRef ParentName =
11634 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
11635 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(
11637 if (!Res || *Res == OMPDeclareTargetDeclAttr::MT_Link ||
11638 ((*Res == OMPDeclareTargetDeclAttr::MT_To ||
11639 *Res == OMPDeclareTargetDeclAttr::MT_Enter) &&
11648 llvm::Constant *
Addr) {
11649 if (
CGM.getLangOpts().OMPTargetTriples.empty() &&
11650 !
CGM.getLangOpts().OpenMPIsTargetDevice)
11653 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
11654 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
11658 if (Res && *Res != OMPDeclareTargetDeclAttr::MT_Link &&
11664 if (Res && *Res == OMPDeclareTargetDeclAttr::MT_Local)
11668 if (
CGM.getLangOpts().OpenMPIsTargetDevice) {
11671 StringRef VarName =
CGM.getMangledName(VD);
11677 auto AddrOfGlobal = [&VD,
this]() {
return CGM.GetAddrOfGlobal(VD); };
11678 auto LinkageForVariable = [&VD,
this]() {
11679 return CGM.getLLVMLinkageVarDefinition(VD);
11682 std::vector<llvm::GlobalVariable *> GeneratedRefs;
11689 CGM.getMangledName(VD), GeneratedRefs,
CGM.getLangOpts().OpenMPSimd,
11690 CGM.getLangOpts().OMPTargetTriples, AddrOfGlobal, LinkageForVariable,
11691 CGM.getTypes().ConvertTypeForMem(
11692 CGM.getContext().getPointerType(VD->
getType())),
11695 for (
auto *ref : GeneratedRefs)
11696 CGM.addCompilerUsedGlobal(ref);
11709 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
11710 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
11714 if (*Res == OMPDeclareTargetDeclAttr::MT_Local ||
11715 ((*Res == OMPDeclareTargetDeclAttr::MT_To ||
11716 *Res == OMPDeclareTargetDeclAttr::MT_Enter) &&
11718 CGM.EmitGlobal(VD);
11720 assert((*Res == OMPDeclareTargetDeclAttr::MT_Link ||
11721 ((*Res == OMPDeclareTargetDeclAttr::MT_To ||
11722 *Res == OMPDeclareTargetDeclAttr::MT_Enter ||
11723 *Res == OMPDeclareTargetDeclAttr::MT_Local) &&
11725 "Expected link clause or to clause with unified memory.");
11726 (void)
CGM.getOpenMPRuntime().getAddrOfDeclareTargetVar(VD);
11734 " Expected target-based directive.");
11739 if (Clause->getClauseKind() == OMPC_unified_shared_memory) {
11741 OMPBuilder.Config.setHasRequiresUnifiedSharedMemory(
true);
11742 }
else if (
const auto *AC =
11743 dyn_cast<OMPAtomicDefaultMemOrderClause>(Clause)) {
11744 switch (AC->getAtomicDefaultMemOrderKind()) {
11745 case OMPC_ATOMIC_DEFAULT_MEM_ORDER_acq_rel:
11748 case OMPC_ATOMIC_DEFAULT_MEM_ORDER_seq_cst:
11751 case OMPC_ATOMIC_DEFAULT_MEM_ORDER_relaxed:
11767 if (!VD || !VD->
hasAttr<OMPAllocateDeclAttr>())
11769 const auto *A = VD->
getAttr<OMPAllocateDeclAttr>();
11770 switch(A->getAllocatorType()) {
11771 case OMPAllocateDeclAttr::OMPNullMemAlloc:
11772 case OMPAllocateDeclAttr::OMPDefaultMemAlloc:
11774 case OMPAllocateDeclAttr::OMPLargeCapMemAlloc:
11775 case OMPAllocateDeclAttr::OMPCGroupMemAlloc:
11776 case OMPAllocateDeclAttr::OMPHighBWMemAlloc:
11777 case OMPAllocateDeclAttr::OMPLowLatMemAlloc:
11778 case OMPAllocateDeclAttr::OMPThreadMemAlloc:
11779 case OMPAllocateDeclAttr::OMPConstMemAlloc:
11780 case OMPAllocateDeclAttr::OMPPTeamMemAlloc:
11783 case OMPAllocateDeclAttr::OMPUserDefinedMemAlloc:
11784 llvm_unreachable(
"Expected predefined allocator for the variables with the "
11785 "static storage.");
11797 if (CGM.getLangOpts().OpenMPIsTargetDevice) {
11798 SavedShouldMarkAsGlobal = CGM.getOpenMPRuntime().ShouldMarkAsGlobal;
11799 CGM.getOpenMPRuntime().ShouldMarkAsGlobal = false;
11804 if (CGM.getLangOpts().OpenMPIsTargetDevice)
11805 CGM.getOpenMPRuntime().ShouldMarkAsGlobal = SavedShouldMarkAsGlobal;
11815 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(D)) {
11817 if (
auto *F = dyn_cast_or_null<llvm::Function>(
11818 CGM.GetGlobalValue(
CGM.getMangledName(GD))))
11819 return !F->isDeclaration();
11831 llvm::Function *OutlinedFn,
11840 llvm::Value *Args[] = {
11842 CGF.
Builder.getInt32(CapturedVars.size()),
11845 RealArgs.append(std::begin(Args), std::end(Args));
11846 RealArgs.append(CapturedVars.begin(), CapturedVars.end());
11848 llvm::FunctionCallee RTLFn =
OMPBuilder.getOrCreateRuntimeFunction(
11849 CGM.getModule(), OMPRTL___kmpc_fork_teams);
11854 const Expr *NumTeams,
11855 const Expr *ThreadLimit,
11862 llvm::Value *NumTeamsVal =
11868 llvm::Value *ThreadLimitVal =
11875 llvm::Value *PushNumTeamsArgs[] = {RTLoc,
getThreadID(CGF, Loc), NumTeamsVal,
11878 CGM.getModule(), OMPRTL___kmpc_push_num_teams),
11883 const Expr *ThreadLimit,
11886 llvm::Value *ThreadLimitVal =
11893 llvm::Value *ThreadLimitArgs[] = {RTLoc,
getThreadID(CGF, Loc),
11896 CGM.getModule(), OMPRTL___kmpc_set_thread_limit),
11911 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
11913 llvm::Value *IfCondVal =
nullptr;
11918 llvm::Value *DeviceID =
nullptr;
11923 DeviceID = CGF.
Builder.getInt64(OMP_DEVICEID_UNDEF);
11927 MappableExprsHandler::MapCombinedInfoTy CombinedInfo;
11928 auto GenMapInfoCB =
11929 [&](InsertPointTy CodeGenIP) -> llvm::OpenMPIRBuilder::MapInfosTy & {
11930 CGF.
Builder.restoreIP(CodeGenIP);
11932 MappableExprsHandler MEHandler(D, CGF);
11933 MEHandler.generateAllInfo(CombinedInfo,
OMPBuilder);
11935 auto FillInfoMap = [&](MappableExprsHandler::MappingExprInfo &MapExpr) {
11938 if (
CGM.getCodeGenOpts().getDebugInfo() !=
11939 llvm::codegenoptions::NoDebugInfo) {
11940 CombinedInfo.Names.resize(CombinedInfo.Exprs.size());
11941 llvm::transform(CombinedInfo.Exprs, CombinedInfo.Names.begin(),
11945 return CombinedInfo;
11947 using BodyGenTy = llvm::OpenMPIRBuilder::BodyGenTy;
11948 auto BodyCB = [&](InsertPointTy CodeGenIP, BodyGenTy BodyGenType) {
11949 CGF.
Builder.restoreIP(CodeGenIP);
11950 switch (BodyGenType) {
11951 case BodyGenTy::Priv:
11955 case BodyGenTy::DupNoPriv:
11957 CodeGen.setAction(NoPrivAction);
11961 case BodyGenTy::NoPriv:
11963 CodeGen.setAction(NoPrivAction);
11968 return InsertPointTy(CGF.
Builder.GetInsertPoint());
11971 auto DeviceAddrCB = [&](
unsigned int I, llvm::Value *NewDecl) {
11972 if (
const ValueDecl *DevVD = CombinedInfo.DevicePtrDecls[I]) {
11977 auto CustomMapperCB = [&](
unsigned int I) {
11978 llvm::Function *MFunc =
nullptr;
11979 if (CombinedInfo.Mappers[I]) {
11980 Info.HasMapper =
true;
11991 InsertPointTy CodeGenIP(CGF.
Builder.GetInsertPoint());
11992 llvm::OpenMPIRBuilder::LocationDescription OmpLoc(CGF.
Builder);
11993 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
11995 OmpLoc, AllocaIP, CodeGenIP, {}, DeviceID,
11996 IfCondVal, Info, GenMapInfoCB, CustomMapperCB,
11997 nullptr, BodyCB, DeviceAddrCB, RTLoc));
11998 CGF.
Builder.restoreIP(AfterIP);
12010 "Expecting either target enter, exit data, or update directives.");
12013 llvm::Value *MapTypesArray =
nullptr;
12014 llvm::Value *MapNamesArray =
nullptr;
12016 auto &&ThenGen = [
this, &D,
Device, &InputInfo, &MapTypesArray,
12019 llvm::Value *DeviceID =
nullptr;
12024 DeviceID = CGF.
Builder.getInt64(OMP_DEVICEID_UNDEF);
12028 llvm::Constant *PointerNum =
12035 {RTLoc, DeviceID, PointerNum,
12043 const bool HasNowait = D.hasClausesOfKind<OMPNowaitClause>();
12044 RuntimeFunction RTLFn;
12045 switch (D.getDirectiveKind()) {
12046 case OMPD_target_enter_data:
12047 RTLFn = HasNowait ? OMPRTL___tgt_target_data_begin_nowait_mapper
12048 : OMPRTL___tgt_target_data_begin_mapper;
12050 case OMPD_target_exit_data:
12051 RTLFn = HasNowait ? OMPRTL___tgt_target_data_end_nowait_mapper
12052 : OMPRTL___tgt_target_data_end_mapper;
12054 case OMPD_target_update:
12055 RTLFn = HasNowait ? OMPRTL___tgt_target_data_update_nowait_mapper
12056 : OMPRTL___tgt_target_data_update_mapper;
12058 case OMPD_parallel:
12060 case OMPD_parallel_for:
12061 case OMPD_parallel_master:
12062 case OMPD_parallel_sections:
12063 case OMPD_for_simd:
12064 case OMPD_parallel_for_simd:
12066 case OMPD_cancellation_point:
12067 case OMPD_ordered_standalone:
12068 case OMPD_ordered_blockassoc:
12069 case OMPD_threadprivate:
12070 case OMPD_allocate:
12075 case OMPD_sections:
12079 case OMPD_critical:
12080 case OMPD_taskyield:
12082 case OMPD_taskwait:
12083 case OMPD_taskgroup:
12089 case OMPD_target_data:
12090 case OMPD_distribute:
12091 case OMPD_distribute_simd:
12092 case OMPD_distribute_parallel_for:
12093 case OMPD_distribute_parallel_for_simd:
12094 case OMPD_teams_distribute:
12095 case OMPD_teams_distribute_simd:
12096 case OMPD_teams_distribute_parallel_for:
12097 case OMPD_teams_distribute_parallel_for_simd:
12098 case OMPD_declare_simd:
12099 case OMPD_declare_variant:
12100 case OMPD_begin_declare_variant:
12101 case OMPD_end_declare_variant:
12102 case OMPD_declare_target:
12103 case OMPD_end_declare_target:
12104 case OMPD_declare_reduction:
12105 case OMPD_declare_mapper:
12106 case OMPD_taskloop:
12107 case OMPD_taskloop_simd:
12108 case OMPD_master_taskloop:
12109 case OMPD_master_taskloop_simd:
12110 case OMPD_parallel_master_taskloop:
12111 case OMPD_parallel_master_taskloop_simd:
12113 case OMPD_target_simd:
12114 case OMPD_target_teams_distribute:
12115 case OMPD_target_teams_distribute_simd:
12116 case OMPD_target_teams_distribute_parallel_for:
12117 case OMPD_target_teams_distribute_parallel_for_simd:
12118 case OMPD_target_teams:
12119 case OMPD_target_parallel:
12120 case OMPD_target_parallel_for:
12121 case OMPD_target_parallel_for_simd:
12122 case OMPD_requires:
12123 case OMPD_metadirective:
12126 llvm_unreachable(
"Unexpected standalone target data directive.");
12130 OffloadingArgs.push_back(llvm::Constant::getNullValue(CGF.
Int32Ty));
12131 OffloadingArgs.push_back(llvm::Constant::getNullValue(CGF.
VoidPtrTy));
12132 OffloadingArgs.push_back(llvm::Constant::getNullValue(CGF.
Int32Ty));
12133 OffloadingArgs.push_back(llvm::Constant::getNullValue(CGF.
VoidPtrTy));
12136 OMPBuilder.getOrCreateRuntimeFunction(
CGM.getModule(), RTLFn),
12140 auto &&TargetThenGen = [
this, &ThenGen, &D, &InputInfo, &MapTypesArray,
12144 MappableExprsHandler::MapCombinedInfoTy CombinedInfo;
12146 MappableExprsHandler MEHandler(D, CGF);
12152 D.hasClausesOfKind<OMPNowaitClause>();
12158 CGM.getPointerAlign());
12163 MapTypesArray = Info.RTArgs.MapTypesArray;
12164 MapNamesArray = Info.RTArgs.MapNamesArray;
12165 if (RequiresOuterTask)
12210 unsigned Offset = 0;
12211 if (
const auto *MD = dyn_cast<CXXMethodDecl>(FD)) {
12212 if (ParamAttrs[Offset].Kind ==
12213 llvm::OpenMPIRBuilder::DeclareSimdKindTy::Vector)
12214 CDT =
C.getPointerType(
C.getCanonicalTagType(MD->
getParent()));
12218 for (
unsigned I = 0, E = FD->
getNumParams(); I < E; ++I) {
12219 if (ParamAttrs[I + Offset].Kind ==
12220 llvm::OpenMPIRBuilder::DeclareSimdKindTy::Vector) {
12232 return C.getTypeSize(CDT);
12243 llvm::OpenMPIRBuilder::DeclareSimdKindTy Kind) {
12249 if (Kind == llvm::OpenMPIRBuilder::DeclareSimdKindTy::Uniform)
12252 if (Kind == llvm::OpenMPIRBuilder::DeclareSimdKindTy::LinearUVal ||
12253 Kind == llvm::OpenMPIRBuilder::DeclareSimdKindTy::LinearRef)
12256 if ((Kind == llvm::OpenMPIRBuilder::DeclareSimdKindTy::Linear ||
12257 Kind == llvm::OpenMPIRBuilder::DeclareSimdKindTy::LinearVal) &&
12267 unsigned Size =
C.getTypeSize(QT);
12270 if (Size != 8 && Size != 16 && Size != 32 && Size != 64 && Size != 128)
12291 llvm::OpenMPIRBuilder::DeclareSimdKindTy Kind,
12296 return C.getTypeSize(PTy);
12299 return C.getTypeSize(QT);
12301 return C.getTypeSize(
C.getUIntPtrType());
12307static std::tuple<unsigned, unsigned, bool>
12314 bool OutputBecomesInput =
false;
12319 RetType, llvm::OpenMPIRBuilder::DeclareSimdKindTy::Vector,
C));
12321 OutputBecomesInput =
true;
12323 for (
unsigned I = 0, E = FD->
getNumParams(); I < E; ++I) {
12328 assert(!Sizes.empty() &&
"Unable to determine NDS and WDS.");
12331 assert(llvm::all_of(Sizes,
12332 [](
unsigned Size) {
12333 return Size == 8 || Size == 16 || Size == 32 ||
12334 Size == 64 || Size == 128;
12338 return std::make_tuple(*llvm::min_element(Sizes), *llvm::max_element(Sizes),
12339 OutputBecomesInput);
12342static llvm::OpenMPIRBuilder::DeclareSimdBranch
12345 case OMPDeclareSimdDeclAttr::BS_Undefined:
12346 return llvm::OpenMPIRBuilder::DeclareSimdBranch::Undefined;
12347 case OMPDeclareSimdDeclAttr::BS_Inbranch:
12348 return llvm::OpenMPIRBuilder::DeclareSimdBranch::Inbranch;
12349 case OMPDeclareSimdDeclAttr::BS_Notinbranch:
12350 return llvm::OpenMPIRBuilder::DeclareSimdBranch::Notinbranch;
12352 llvm_unreachable(
"unexpected declare simd branch state");
12357 unsigned UserVLEN,
unsigned WDS,
char ISA) {
12359 if (UserVLEN == 1) {
12366 if (ISA ==
'n' && UserVLEN && !llvm::isPowerOf2_32(UserVLEN)) {
12372 if (ISA ==
's' && UserVLEN != 0 &&
12373 ((UserVLEN * WDS > 2048) || (UserVLEN * WDS % 128 != 0))) {
12382 llvm::Function *Fn) {
12387 llvm::DenseMap<const Decl *, unsigned> ParamPositions;
12389 ParamPositions.try_emplace(FD, 0);
12390 unsigned ParamPos = ParamPositions.size();
12392 ParamPositions.try_emplace(P->getCanonicalDecl(), ParamPos);
12397 ParamPositions.size());
12399 for (
const Expr *E :
Attr->uniforms()) {
12403 Pos = ParamPositions[FD];
12406 ->getCanonicalDecl();
12407 auto It = ParamPositions.find(PVD);
12408 assert(It != ParamPositions.end() &&
"Function parameter not found");
12411 ParamAttrs[Pos].Kind =
12412 llvm::OpenMPIRBuilder::DeclareSimdKindTy::Uniform;
12415 auto *NI =
Attr->alignments_begin();
12416 for (
const Expr *E :
Attr->aligneds()) {
12421 Pos = ParamPositions[FD];
12425 ->getCanonicalDecl();
12426 auto It = ParamPositions.find(PVD);
12427 assert(It != ParamPositions.end() &&
"Function parameter not found");
12429 ParmTy = PVD->getType();
12431 ParamAttrs[Pos].Alignment =
12433 ? (*NI)->EvaluateKnownConstInt(
C)
12434 : llvm::APSInt::getUnsigned(
12435 C.toCharUnitsFromBits(
C.getOpenMPDefaultSimdAlign(ParmTy))
12440 auto *SI =
Attr->steps_begin();
12441 auto *MI =
Attr->modifiers_begin();
12442 for (
const Expr *E :
Attr->linears()) {
12445 bool IsReferenceType =
false;
12448 unsigned PtrRescalingFactor = 1;
12450 Pos = ParamPositions[FD];
12452 PtrRescalingFactor =
CGM.getContext()
12453 .getTypeSizeInChars(P->getPointeeType())
12457 ->getCanonicalDecl();
12458 auto It = ParamPositions.find(PVD);
12459 assert(It != ParamPositions.end() &&
"Function parameter not found");
12461 if (
auto *P = dyn_cast<PointerType>(PVD->getType()))
12462 PtrRescalingFactor =
CGM.getContext()
12463 .getTypeSizeInChars(P->getPointeeType())
12465 else if (PVD->getType()->isReferenceType()) {
12466 IsReferenceType =
true;
12467 PtrRescalingFactor =
12469 .getTypeSizeInChars(PVD->getType().getNonReferenceType())
12473 llvm::OpenMPIRBuilder::DeclareSimdAttrTy &ParamAttr = ParamAttrs[Pos];
12474 if (*MI == OMPC_LINEAR_ref)
12475 ParamAttr.Kind = llvm::OpenMPIRBuilder::DeclareSimdKindTy::LinearRef;
12476 else if (*MI == OMPC_LINEAR_uval)
12477 ParamAttr.Kind = llvm::OpenMPIRBuilder::DeclareSimdKindTy::LinearUVal;
12478 else if (IsReferenceType)
12479 ParamAttr.Kind = llvm::OpenMPIRBuilder::DeclareSimdKindTy::LinearVal;
12481 ParamAttr.Kind = llvm::OpenMPIRBuilder::DeclareSimdKindTy::Linear;
12483 ParamAttr.StrideOrArg = llvm::APSInt::getUnsigned(1);
12487 if (
const auto *DRE =
12489 if (
const auto *StridePVD =
12490 dyn_cast<ParmVarDecl>(DRE->getDecl())) {
12491 ParamAttr.HasVarStride =
true;
12492 auto It = ParamPositions.find(StridePVD->getCanonicalDecl());
12493 assert(It != ParamPositions.end() &&
12494 "Function parameter not found");
12495 ParamAttr.StrideOrArg = llvm::APSInt::getUnsigned(It->second);
12499 ParamAttr.StrideOrArg =
Result.Val.getInt();
12505 if (!ParamAttr.HasVarStride &&
12507 llvm::OpenMPIRBuilder::DeclareSimdKindTy::Linear ||
12509 llvm::OpenMPIRBuilder::DeclareSimdKindTy::LinearRef))
12510 ParamAttr.StrideOrArg = ParamAttr.StrideOrArg * PtrRescalingFactor;
12514 llvm::APSInt VLENVal;
12516 const Expr *VLENExpr =
Attr->getSimdlen();
12521 llvm::OpenMPIRBuilder::DeclareSimdBranch State =
12523 if (
CGM.getTriple().isX86()) {
12525 assert(NumElts &&
"Non-zero simdlen/cdtsize expected");
12526 OMPBuilder.emitX86DeclareSimdFunction(Fn, NumElts, VLENVal, ParamAttrs,
12528 }
else if (
CGM.getTriple().getArch() == llvm::Triple::aarch64) {
12529 unsigned VLEN = VLENVal.getExtValue();
12532 const unsigned NDS = std::get<0>(
Data);
12533 const unsigned WDS = std::get<1>(
Data);
12534 const bool OutputBecomesInput = std::get<2>(
Data);
12535 if (
CGM.getTarget().hasFeature(
"sve")) {
12538 Fn, VLEN, ParamAttrs, State,
's', NDS, OutputBecomesInput);
12539 }
else if (
CGM.getTarget().hasFeature(
"neon")) {
12542 Fn, VLEN, ParamAttrs, State,
'n', NDS, OutputBecomesInput);
12552class DoacrossCleanupTy final :
public EHScopeStack::Cleanup {
12554 static const int DoacrossFinArgs = 2;
12557 llvm::FunctionCallee RTLFn;
12558 llvm::Value *Args[DoacrossFinArgs];
12561 DoacrossCleanupTy(llvm::FunctionCallee RTLFn,
12564 assert(CallArgs.size() == DoacrossFinArgs);
12565 std::copy(CallArgs.begin(), CallArgs.end(), std::begin(Args));
12582 QualType Int64Ty =
C.getIntTypeForBitwidth(64,
true);
12590 RD =
C.buildImplicitRecord(
"kmp_dim");
12598 RD =
KmpDimTy->castAsRecordDecl();
12600 llvm::APInt Size(32, NumIterations.size());
12606 enum { LowerFD = 0, UpperFD, StrideFD };
12608 for (
unsigned I = 0, E = NumIterations.size(); I < E; ++I) {
12613 DimsLVal, *std::next(RD->
field_begin(), UpperFD));
12615 CGF.
EmitScalarExpr(NumIterations[I]), NumIterations[I]->getType(),
12616 Int64Ty, NumIterations[I]->getExprLoc());
12620 DimsLVal, *std::next(RD->
field_begin(), StrideFD));
12627 llvm::Value *Args[] = {
12630 llvm::ConstantInt::getSigned(
CGM.Int32Ty, NumIterations.size()),
12635 llvm::FunctionCallee RTLFn =
OMPBuilder.getOrCreateRuntimeFunction(
12636 CGM.getModule(), OMPRTL___kmpc_doacross_init);
12638 llvm::Value *FiniArgs[DoacrossCleanupTy::DoacrossFinArgs] = {
12640 llvm::FunctionCallee FiniRTLFn =
OMPBuilder.getOrCreateRuntimeFunction(
12641 CGM.getModule(), OMPRTL___kmpc_doacross_fini);
12646template <
typename T>
12648 const T *
C, llvm::Value *ULoc,
12649 llvm::Value *ThreadID) {
12652 llvm::APInt Size(32,
C->getNumLoops());
12656 for (
unsigned I = 0, E =
C->getNumLoops(); I < E; ++I) {
12657 const Expr *CounterVal =
C->getLoopData(I);
12658 assert(CounterVal);
12665 llvm::Value *Args[] = {
12668 llvm::FunctionCallee RTLFn;
12670 OMPDoacrossKind<T> ODK;
12671 if (ODK.isSource(
C)) {
12673 OMPRTL___kmpc_doacross_post);
12675 assert(ODK.isSink(
C) &&
"Expect sink modifier.");
12677 OMPRTL___kmpc_doacross_wait);
12697 llvm::FunctionCallee Callee,
12699 assert(Loc.
isValid() &&
"Outlined function call location must be valid.");
12702 if (
auto *Fn = dyn_cast<llvm::Function>(Callee.getCallee())) {
12703 if (Fn->doesNotThrow()) {
12714 emitCall(CGF, Loc, OutlinedFn, Args);
12718 if (
const auto *FD = dyn_cast<FunctionDecl>(D))
12719 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(FD))
12725 const VarDecl *TargetParam)
const {
12732 const Expr *Allocator) {
12733 llvm::Value *AllocVal;
12743 AllocVal = llvm::Constant::getNullValue(
12753 if (!AllocateAlignment)
12756 return llvm::ConstantInt::get(
CGM.
SizeTy, AllocateAlignment->getQuantity());
12769 auto I = UntiedData.find(VD);
12770 if (I != UntiedData.end()) {
12771 UntiedAddr = I->second.first;
12772 UntiedRealAddr = I->second.second;
12776 if (CVD->
hasAttr<OMPAllocateDeclAttr>()) {
12785 Size = CGF.
Builder.CreateNUWAdd(
12787 Size = CGF.
Builder.CreateUDiv(Size,
CGM.getSize(Align));
12788 Size = CGF.
Builder.CreateNUWMul(Size,
CGM.getSize(Align));
12794 const auto *AA = CVD->
getAttr<OMPAllocateDeclAttr>();
12795 const Expr *Allocator = AA->getAllocator();
12799 Args.push_back(ThreadID);
12801 Args.push_back(Alignment);
12802 Args.push_back(Size);
12803 Args.push_back(AllocVal);
12804 llvm::omp::RuntimeFunction FnID =
12805 Alignment ? OMPRTL___kmpc_aligned_alloc : OMPRTL___kmpc_alloc;
12807 OMPBuilder.getOrCreateRuntimeFunction(
CGM.getModule(), FnID), Args,
12809 llvm::FunctionCallee FiniRTLFn =
OMPBuilder.getOrCreateRuntimeFunction(
12810 CGM.getModule(), OMPRTL___kmpc_free);
12818 class OMPAllocateCleanupTy final :
public EHScopeStack::Cleanup {
12819 llvm::FunctionCallee RTLFn;
12822 const Expr *AllocExpr;
12825 OMPAllocateCleanupTy(llvm::FunctionCallee RTLFn,
12827 const Expr *AllocExpr)
12828 : RTLFn(RTLFn), LocEncoding(LocEncoding),
Addr(
Addr),
12829 AllocExpr(AllocExpr) {}
12833 llvm::Value *Args[3];
12839 Args[2] = AllocVal;
12847 CGF.
EHStack.pushCleanup<OMPAllocateCleanupTy>(
12849 VDAddr, Allocator);
12850 if (UntiedRealAddr.
isValid())
12853 Region->emitUntiedSwitch(CGF);
12870 assert(CGM.getLangOpts().OpenMP &&
"Not in OpenMP mode.");
12874 CGM.getOpenMPRuntime().NontemporalDeclsStack.emplace_back();
12876 for (
const Stmt *Ref :
C->private_refs()) {
12877 const auto *SimpleRefExpr =
cast<Expr>(Ref)->IgnoreParenImpCasts();
12879 if (
const auto *DRE = dyn_cast<DeclRefExpr>(SimpleRefExpr)) {
12880 VD = DRE->getDecl();
12883 assert((ME->isImplicitCXXThis() ||
12885 "Expected member of current class.");
12886 VD = ME->getMemberDecl();
12896 CGM.getOpenMPRuntime().NontemporalDeclsStack.pop_back();
12902 std::pair<Address, Address>> &LocalVars)
12903 : CGM(CGF.CGM), NeedToPush(!LocalVars.empty()) {
12907 CGF.
CurFn, CGM.getOpenMPRuntime().UntiedLocalVarsStack.size());
12908 CGM.getOpenMPRuntime().UntiedLocalVarsStack.push_back(LocalVars);
12914 CGM.getOpenMPRuntime().UntiedLocalVarsStack.pop_back();
12918 assert(
CGM.getLangOpts().OpenMP &&
"Not in OpenMP mode.");
12920 return llvm::any_of(
12921 CGM.getOpenMPRuntime().NontemporalDeclsStack,
12925void CGOpenMPRuntime::LastprivateConditionalRAII::tryToDisableInnerAnalysis(
12929 llvm::DenseSet<CanonicalDeclPtr<const Decl>> NeedToCheckForLPCs;
12935 const CapturedStmt *CS = S.getCapturedStmt(CaptureRegions.front());
12942 for (
const auto *
C : S.getClausesOfKind<OMPPrivateClause>()) {
12943 for (
const Expr *Ref :
C->varlist()) {
12944 if (!Ref->getType()->isScalarType())
12946 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
12949 NeedToCheckForLPCs.insert(DRE->getDecl());
12952 for (
const auto *
C : S.getClausesOfKind<OMPFirstprivateClause>()) {
12953 for (
const Expr *Ref :
C->varlist()) {
12954 if (!Ref->getType()->isScalarType())
12956 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
12959 NeedToCheckForLPCs.insert(DRE->getDecl());
12962 for (
const auto *
C : S.getClausesOfKind<OMPLastprivateClause>()) {
12963 for (
const Expr *Ref :
C->varlist()) {
12964 if (!Ref->getType()->isScalarType())
12966 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
12969 NeedToCheckForLPCs.insert(DRE->getDecl());
12972 for (
const auto *
C : S.getClausesOfKind<OMPReductionClause>()) {
12973 for (
const Expr *Ref :
C->varlist()) {
12974 if (!Ref->getType()->isScalarType())
12976 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
12979 NeedToCheckForLPCs.insert(DRE->getDecl());
12982 for (
const auto *
C : S.getClausesOfKind<OMPLinearClause>()) {
12983 for (
const Expr *Ref :
C->varlist()) {
12984 if (!Ref->getType()->isScalarType())
12986 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
12989 NeedToCheckForLPCs.insert(DRE->getDecl());
12992 for (
const Decl *VD : NeedToCheckForLPCs) {
12994 llvm::reverse(
CGM.getOpenMPRuntime().LastprivateConditionalStack)) {
12995 if (
Data.DeclToUniqueName.count(VD) > 0) {
12996 if (!
Data.Disabled)
12997 NeedToAddForLPCsAsDisabled.insert(VD);
13004CGOpenMPRuntime::LastprivateConditionalRAII::LastprivateConditionalRAII(
13007 Action((CGM.getLangOpts().OpenMP >= 50 &&
13008 llvm::any_of(S.getClausesOfKind<OMPLastprivateClause>(),
13009 [](const OMPLastprivateClause *
C) {
13010 return C->getKind() ==
13011 OMPC_LASTPRIVATE_conditional;
13013 ? ActionToDo::PushAsLastprivateConditional
13014 : ActionToDo::DoNotPush) {
13015 assert(
CGM.getLangOpts().OpenMP &&
"Not in OpenMP mode.");
13016 if (
CGM.getLangOpts().OpenMP < 50 || Action == ActionToDo::DoNotPush)
13018 assert(Action == ActionToDo::PushAsLastprivateConditional &&
13019 "Expected a push action.");
13021 CGM.getOpenMPRuntime().LastprivateConditionalStack.emplace_back();
13022 for (
const auto *
C : S.getClausesOfKind<OMPLastprivateClause>()) {
13023 if (
C->getKind() != OMPC_LASTPRIVATE_conditional)
13026 for (
const Expr *Ref :
C->varlist()) {
13027 Data.DeclToUniqueName.insert(std::make_pair(
13032 Data.IVLVal = IVLVal;
13036CGOpenMPRuntime::LastprivateConditionalRAII::LastprivateConditionalRAII(
13038 :
CGM(CGF.
CGM), Action(ActionToDo::DoNotPush) {
13042 llvm::DenseSet<CanonicalDeclPtr<const Decl>> NeedToAddForLPCsAsDisabled;
13043 tryToDisableInnerAnalysis(S, NeedToAddForLPCsAsDisabled);
13044 if (!NeedToAddForLPCsAsDisabled.empty()) {
13045 Action = ActionToDo::DisableLastprivateConditional;
13046 LastprivateConditionalData &
Data =
13048 for (
const Decl *VD : NeedToAddForLPCsAsDisabled)
13049 Data.DeclToUniqueName.try_emplace(VD);
13051 Data.Disabled =
true;
13055CGOpenMPRuntime::LastprivateConditionalRAII
13058 return LastprivateConditionalRAII(CGF, S);
13062 if (CGM.getLangOpts().OpenMP < 50)
13064 if (Action == ActionToDo::DisableLastprivateConditional) {
13065 assert(CGM.getOpenMPRuntime().LastprivateConditionalStack.back().Disabled &&
13066 "Expected list of disabled private vars.");
13067 CGM.getOpenMPRuntime().LastprivateConditionalStack.pop_back();
13069 if (Action == ActionToDo::PushAsLastprivateConditional) {
13071 !CGM.getOpenMPRuntime().LastprivateConditionalStack.back().Disabled &&
13072 "Expected list of lastprivate conditional vars.");
13073 CGM.getOpenMPRuntime().LastprivateConditionalStack.pop_back();
13085 auto VI = I->getSecond().find(VD);
13086 if (VI == I->getSecond().end()) {
13087 RecordDecl *RD =
C.buildImplicitRecord(
"lasprivate.conditional");
13092 NewType =
C.getCanonicalTagType(RD);
13095 I->getSecond().try_emplace(VD, NewType, VDField, FiredField, BaseLVal);
13097 NewType = std::get<0>(VI->getSecond());
13098 VDField = std::get<1>(VI->getSecond());
13099 FiredField = std::get<2>(VI->getSecond());
13100 BaseLVal = std::get<3>(VI->getSecond());
13112class LastprivateConditionalRefChecker final
13115 const Expr *FoundE =
nullptr;
13116 const Decl *FoundD =
nullptr;
13117 StringRef UniqueDeclName;
13119 llvm::Function *FoundFn =
nullptr;
13125 llvm::reverse(LPM)) {
13126 auto It = D.DeclToUniqueName.find(E->
getDecl());
13127 if (It == D.DeclToUniqueName.end())
13133 UniqueDeclName = It->second;
13138 return FoundE == E;
13144 llvm::reverse(LPM)) {
13146 if (It == D.DeclToUniqueName.end())
13152 UniqueDeclName = It->second;
13157 return FoundE == E;
13159 bool VisitStmt(
const Stmt *S) {
13160 for (
const Stmt *Child : S->
children()) {
13163 if (
const auto *E = dyn_cast<Expr>(Child))
13171 explicit LastprivateConditionalRefChecker(
13172 ArrayRef<CGOpenMPRuntime::LastprivateConditionalData> LPM)
13174 std::tuple<const Expr *, const Decl *, StringRef, LValue, llvm::Function *>
13175 getFoundData()
const {
13176 return std::make_tuple(FoundE, FoundD, UniqueDeclName, IVLVal, FoundFn);
13183 StringRef UniqueDeclName,
13189 llvm::Constant *LastIV =
OMPBuilder.getOrCreateInternalVariable(
13190 LLIVTy,
getName({UniqueDeclName,
"iv"}));
13198 llvm::GlobalVariable *
Last =
OMPBuilder.getOrCreateInternalVariable(
13214 auto &&
CodeGen = [&LastIVLVal, &IVLVal, IVVal, &LVal, &LastLVal,
13220 llvm::Value *CmpRes;
13222 CmpRes = CGF.
Builder.CreateICmpSLE(LastIVVal, IVVal);
13225 "Loop iteration variable must be integer.");
13226 CmpRes = CGF.
Builder.CreateICmpULE(LastIVVal, IVVal);
13230 CGF.
Builder.CreateCondBr(CmpRes, ThenBB, ExitBB);
13251 "Aggregates are not supported in lastprivate conditional.");
13260 if (
CGM.getLangOpts().OpenMPSimd) {
13274 if (!Checker.Visit(LHS))
13276 const Expr *FoundE;
13277 const Decl *FoundD;
13278 StringRef UniqueDeclName;
13280 llvm::Function *FoundFn;
13281 std::tie(FoundE, FoundD, UniqueDeclName, IVLVal, FoundFn) =
13282 Checker.getFoundData();
13283 if (FoundFn != CGF.
CurFn) {
13288 "Lastprivate conditional is not found in outer region.");
13289 QualType StructTy = std::get<0>(It->getSecond());
13290 const FieldDecl* FiredDecl = std::get<2>(It->getSecond());
13301 FiredLVal, llvm::AtomicOrdering::Unordered,
13319 auto It = llvm::find_if(
13321 if (It == Range.end() || It->Fn != CGF.
CurFn)
13325 "Lastprivates must be registered already.");
13328 const CapturedStmt *CS = D.getCapturedStmt(CaptureRegions.back());
13329 for (
const auto &Pair : It->DeclToUniqueName) {
13330 const auto *VD =
cast<VarDecl>(Pair.first->getCanonicalDecl());
13333 auto I = LPCI->getSecond().find(Pair.first);
13334 assert(I != LPCI->getSecond().end() &&
13335 "Lastprivate must be rehistered already.");
13337 LValue BaseLVal = std::get<3>(I->getSecond());
13341 llvm::Value *
Cmp = CGF.
Builder.CreateIsNotNull(Res);
13345 CGF.
Builder.CreateCondBr(
Cmp, ThenBB, DoneBB);
13370 "Unknown lastprivate conditional variable.");
13371 StringRef UniqueName = It->second;
13372 llvm::GlobalVariable *GV =
CGM.getModule().getNamedGlobal(UniqueName);
13386 llvm_unreachable(
"Not supported in SIMD-only mode");
13393 llvm_unreachable(
"Not supported in SIMD-only mode");
13400 bool Tied,
unsigned &NumberOfParts) {
13401 llvm_unreachable(
"Not supported in SIMD-only mode");
13409 llvm_unreachable(
"Not supported in SIMD-only mode");
13415 const Expr *Hint) {
13416 llvm_unreachable(
"Not supported in SIMD-only mode");
13422 llvm_unreachable(
"Not supported in SIMD-only mode");
13428 const Expr *Filter) {
13429 llvm_unreachable(
"Not supported in SIMD-only mode");
13434 llvm_unreachable(
"Not supported in SIMD-only mode");
13440 llvm_unreachable(
"Not supported in SIMD-only mode");
13448 llvm_unreachable(
"Not supported in SIMD-only mode");
13455 llvm_unreachable(
"Not supported in SIMD-only mode");
13462 bool ForceSimpleCall) {
13463 llvm_unreachable(
"Not supported in SIMD-only mode");
13470 llvm_unreachable(
"Not supported in SIMD-only mode");
13475 llvm_unreachable(
"Not supported in SIMD-only mode");
13481 llvm_unreachable(
"Not supported in SIMD-only mode");
13487 llvm_unreachable(
"Not supported in SIMD-only mode");
13494 llvm_unreachable(
"Not supported in SIMD-only mode");
13500 llvm_unreachable(
"Not supported in SIMD-only mode");
13505 unsigned IVSize,
bool IVSigned,
13508 llvm_unreachable(
"Not supported in SIMD-only mode");
13516 llvm_unreachable(
"Not supported in SIMD-only mode");
13520 ProcBindKind ProcBind,
13522 llvm_unreachable(
"Not supported in SIMD-only mode");
13529 llvm_unreachable(
"Not supported in SIMD-only mode");
13535 llvm_unreachable(
"Not supported in SIMD-only mode");
13540 llvm_unreachable(
"Not supported in SIMD-only mode");
13546 llvm::AtomicOrdering AO) {
13547 llvm_unreachable(
"Not supported in SIMD-only mode");
13552 llvm::Function *TaskFunction,
13554 const Expr *IfCond,
13556 llvm_unreachable(
"Not supported in SIMD-only mode");
13563 llvm_unreachable(
"Not supported in SIMD-only mode");
13570 assert(Options.
SimpleReduction &&
"Only simple reduction is expected.");
13572 ReductionOps, Options);
13578 llvm_unreachable(
"Not supported in SIMD-only mode");
13583 bool IsWorksharingReduction) {
13584 llvm_unreachable(
"Not supported in SIMD-only mode");
13591 llvm_unreachable(
"Not supported in SIMD-only mode");
13596 llvm::Value *ReductionsPtr,
13598 llvm_unreachable(
"Not supported in SIMD-only mode");
13604 llvm_unreachable(
"Not supported in SIMD-only mode");
13610 llvm_unreachable(
"Not supported in SIMD-only mode");
13616 llvm_unreachable(
"Not supported in SIMD-only mode");
13621 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
13623 llvm_unreachable(
"Not supported in SIMD-only mode");
13628 llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID,
const Expr *IfCond,
13629 llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier>
Device,
13633 llvm_unreachable(
"Not supported in SIMD-only mode");
13637 llvm_unreachable(
"Not supported in SIMD-only mode");
13641 llvm_unreachable(
"Not supported in SIMD-only mode");
13651 llvm::Function *OutlinedFn,
13653 llvm_unreachable(
"Not supported in SIMD-only mode");
13657 const Expr *NumTeams,
13658 const Expr *ThreadLimit,
13660 llvm_unreachable(
"Not supported in SIMD-only mode");
13667 llvm_unreachable(
"Not supported in SIMD-only mode");
13673 llvm_unreachable(
"Not supported in SIMD-only mode");
13679 llvm_unreachable(
"Not supported in SIMD-only mode");
13684 llvm_unreachable(
"Not supported in SIMD-only mode");
13689 llvm_unreachable(
"Not supported in SIMD-only mode");
13694 const VarDecl *NativeParam)
const {
13695 llvm_unreachable(
"Not supported in SIMD-only mode");
13701 const VarDecl *TargetParam)
const {
13702 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 const VarDecl * getOriginalVarDecl(const ValueDecl *Decl)
For BindingDecls, returns the DecomposedDecl as the original VarDecl.
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.
A binding in a decomposition declaration.
Expr * getBinding() const
Get the expression to which this declaration is bound.
DecompositionDecl * getDecomposedDecl() const
Get the decomposition declaration that this binding represents a decomposition of.
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.
This is an opaque type for sizes expressed in character units.
bool isZero() const
Test whether the quantity equals zero.
CharUnits alignTo(CharUnits Align) const
Returns the next integer (mod 2**64) that is greater than or equal to this quantity and is a multiple...
llvm::Align getAsAlign() const
Returns Quantity as a valid llvm::Align, Beware llvm::Align assumes power of two 8-bit bytes.
QuantityType getQuantity() const
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)
Construct a CharUnits quantity from a raw integer type.
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 emitHostKernelEnvironment(const OMPExecutableDirective &D, CodeGenFunction &CGF)
Emit the '<kernel>_kernel_environment' global for a target region that is compiled for a non-GPU (hos...
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 ValueDecl *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.
void eraseLocalDecl(const Decl *D)
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.
DeclMapTy::iterator localDeclMapEnd()
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)
DeclMapTy::iterator findLocalDecl(const Decl *D)
Accessors for LocalDeclMap.
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 ...
std::pair< DeclMapTy::iterator, bool > insertLocalDecl(const Decl *D, Address Addr)
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...
const clang::Expr * ExprTy
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.
bool isOpenMPLoopDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a directive with an associated loop construct.
OpenMPSeverityClauseKind
OpenMP attributes for 'severity' clause.
LangAS
Defines the address space values used by the address space qualifier of QualType.
llvm::omp::Directive OpenMPDirectiveKind
OpenMP directives.
bool isOpenMPSimdDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a simd directive.
@ VK_PRValue
A pr-value expression (in the C++11 taxonomy) produces a temporary value.
@ VK_LValue
An l-value expression is a reference to an object with independent storage.
for(const auto &A :T->param_types())
void getOpenMPCaptureRegions(llvm::SmallVectorImpl< OpenMPDirectiveKind > &CaptureRegions, OpenMPDirectiveKind DKind)
Return the captured regions of an OpenMP directive.
OpenMPNumThreadsClauseModifier
@ OMPC_ATOMIC_DEFAULT_MEM_ORDER_unknown
U cast(CodeGen::Address addr)
OpenMPMapModifierKind
OpenMP modifier kind for 'map' clause.
@ OMPC_MAP_MODIFIER_unknown
@ Other
Other implicit parameter.
OpenMPScheduleClauseKind
OpenMP attributes for 'schedule' clause.
bool isOpenMPTaskLoopDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a taskloop directive.
OpenMPThreadsetKind
OpenMP modifiers for 'threadset' clause.
OpenMPMapClauseKind
OpenMP mapping kind for 'map' clause.
Diagnostic wrappers for TextAPI types for error reporting.
Data for list of allocators.
Expr * AllocatorTraits
Allocator traits.
Expr * Allocator
Allocator.
Maps the expression for the lastprivate variable to the global copy used to store new value because o...
llvm::SmallVector< bool, 8 > IsPrivateVarReduction
A jump destination is an abstract label, branching to which may require a jump out through normal cle...
llvm::BasicBlock * getBlock() const
unsigned NumberOfTargetItems
Address BasePointersArray
llvm::PointerType * VoidPtrTy
llvm::IntegerType * Int64Ty
llvm::IntegerType * Int8Ty
i8, i16, i32, and i64
llvm::CallingConv::ID getRuntimeCC() const
llvm::IntegerType * SizeTy
llvm::PointerType * VoidPtrPtrTy
llvm::IntegerType * Int32Ty
llvm::IntegerType * IntPtrTy
llvm::IntegerType * IntTy
int
CharUnits getPointerAlign() const
OpenMPDependClauseKind DepKind
const Expr * IteratorExpr
SmallVector< const Expr *, 4 > DepExprs
EvalResult is a struct with detailed info about an evaluated expression.
Extra information about a function prototype.
Expr * CounterUpdate
Updater for the internal counter: ++CounterVD;.
Scheduling data for loop-based OpenMP directives.
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.