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);
586 Callback(CodeGen, CGF, Action);
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::ConstantExpr::getSizeOf(ElemType);
821 if (AsArraySection) {
822 Size = CGF.
Builder.CreatePtrDiff(ElemType,
823 OrigAddresses[N].second.getPointer(CGF),
824 OrigAddresses[N].first.getPointer(CGF));
825 Size = CGF.
Builder.CreateZExtOrTrunc(Size, ElemSizeOf->getType());
826 Size = CGF.
Builder.CreateNUWAdd(
827 Size, llvm::ConstantInt::get(Size->getType(), 1));
828 SizeInChars = CGF.
Builder.CreateNUWMul(Size, ElemSizeOf);
831 CGF.
getTypeSize(OrigAddresses[N].first.getType().getNonReferenceType());
832 Size = CGF.
Builder.CreateExactUDiv(SizeInChars, ElemSizeOf);
834 Sizes.emplace_back(SizeInChars, Size);
847 assert(!Size && !Sizes[N].second &&
848 "Size should be nullptr for non-variably modified reduction "
863 assert(SharedAddresses.size() > N &&
"No variable was generated");
864 const auto *PrivateVD =
870 (void)DefaultInit(CGF);
871 emitAggregateInitialization(CGF, N, PrivateAddr, SharedAddr, DRD);
872 }
else if (DRD && (DRD->
getInitializer() || !PrivateVD->hasInit())) {
873 (void)DefaultInit(CGF);
874 QualType SharedType = SharedAddresses[N].first.getType();
876 PrivateAddr, SharedAddr, SharedType);
877 }
else if (!DefaultInit(CGF) && PrivateVD->hasInit() &&
880 PrivateVD->
getType().getQualifiers(),
898 CGF.
pushDestroy(DTorKind, PrivateAddr, PrivateType);
917 BaseLV.getType(), BaseLV.getBaseInfo(),
951 const VarDecl *OrigVD =
nullptr;
952 if (
const auto *OASE = dyn_cast<ArraySectionExpr>(Ref)) {
953 const Expr *
Base = OASE->getBase()->IgnoreParenImpCasts();
954 while (
const auto *TempOASE = dyn_cast<ArraySectionExpr>(
Base))
955 Base = TempOASE->getBase()->IgnoreParenImpCasts();
956 while (
const auto *TempASE = dyn_cast<ArraySubscriptExpr>(
Base))
957 Base = TempASE->getBase()->IgnoreParenImpCasts();
960 }
else if (
const auto *ASE = dyn_cast<ArraySubscriptExpr>(Ref)) {
961 const Expr *
Base = ASE->getBase()->IgnoreParenImpCasts();
962 while (
const auto *TempASE = dyn_cast<ArraySubscriptExpr>(
Base))
963 Base = TempASE->getBase()->IgnoreParenImpCasts();
974 BaseDecls.emplace_back(OrigVD);
977 loadToBegin(CGF, OrigVD->getType(), SharedAddresses[N].first.getType(),
979 Address SharedAddr = SharedAddresses[N].first.getAddress();
980 llvm::Value *Adjustment = CGF.
Builder.CreatePtrDiff(
983 llvm::Value *PrivatePointer =
989 SharedAddresses[N].first.getType(),
992 BaseDecls.emplace_back(
1006 getThreadIDVariable()->
getType()->castAs<PointerType>());
1024LValue CGOpenMPTaskOutlinedRegionInfo::getThreadIDVariableLValue(
1027 getThreadIDVariable()->
getType(),
1045 llvm::OpenMPIRBuilderConfig Config(
1046 CGM.getLangOpts().OpenMPIsTargetDevice,
isGPU(),
1047 CGM.getLangOpts().OpenMPOffloadMandatory,
1050 Config.setDefaultTargetAS(
1052 Config.setRuntimeCC(
CGM.getRuntimeCC());
1057 CGM.getLangOpts().OpenMPIsTargetDevice
1058 ?
CGM.getLangOpts().OMPHostIRFile
1063 if (
CGM.getLangOpts().OpenMPForceUSM) {
1065 OMPBuilder.Config.setHasRequiresUnifiedSharedMemory(
true);
1073 if (!
Data.getValue().pointsToAliveValue())
1075 auto *GV = dyn_cast<llvm::GlobalVariable>(
Data.getValue());
1078 if (!GV->isDeclaration() || GV->getNumUses() > 0)
1080 GV->eraseFromParent();
1085 return OMPBuilder.createPlatformSpecificName(Parts);
1088static llvm::Function *
1090 const Expr *CombinerInitializer,
const VarDecl *In,
1091 const VarDecl *Out,
bool IsCombiner) {
1094 QualType PtrTy =
C.getPointerType(Ty).withRestrict();
1096 C,
nullptr, Out->getLocation(),
1099 C,
nullptr, In->getLocation(),
1106 {IsCombiner ?
"omp_combiner" :
"omp_initializer",
""});
1107 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
1111 Fn->addFnAttr(
"sample-profile-suffix-elision-policy",
"selected");
1113 Fn->removeFnAttr(llvm::Attribute::NoInline);
1114 Fn->removeFnAttr(llvm::Attribute::OptimizeNone);
1115 Fn->addFnAttr(llvm::Attribute::AlwaysInline);
1121 Out->getLocation());
1131 (void)
Scope.Privatize();
1132 if (!IsCombiner && Out->hasInit() &&
1135 Out->getType().getQualifiers(),
1138 if (CombinerInitializer)
1140 Scope.ForceCleanup();
1169std::pair<llvm::Function *, llvm::Function *>
1181struct PushAndPopStackRAII {
1182 PushAndPopStackRAII(llvm::OpenMPIRBuilder *OMPBuilder,
CodeGenFunction &CGF,
1183 bool HasCancel, llvm::omp::Directive Kind)
1184 : OMPBuilder(OMPBuilder) {
1200 auto FiniCB = [&CGF](llvm::OpenMPIRBuilder::InsertPointTy IP) {
1201 assert(IP.getBlock()->end() == IP.getPoint() &&
1202 "Clang CG should cause non-terminated block!");
1203 CGBuilderTy::InsertPointGuard IPG(CGF.
Builder);
1208 return llvm::Error::success();
1213 llvm::OpenMPIRBuilder::FinalizationInfo FI({FiniCB, Kind, HasCancel});
1214 OMPBuilder->pushFinalizationCB(std::move(FI));
1216 ~PushAndPopStackRAII() {
1218 OMPBuilder->popFinalizationCB();
1220 llvm::OpenMPIRBuilder *OMPBuilder;
1229 "thread id variable must be of type kmp_int32 *");
1231 bool HasCancel =
false;
1232 if (
const auto *OPD = dyn_cast<OMPParallelDirective>(&D))
1233 HasCancel = OPD->hasCancel();
1234 else if (
const auto *OPD = dyn_cast<OMPTargetParallelDirective>(&D))
1235 HasCancel = OPD->hasCancel();
1236 else if (
const auto *OPSD = dyn_cast<OMPParallelSectionsDirective>(&D))
1237 HasCancel = OPSD->hasCancel();
1238 else if (
const auto *OPFD = dyn_cast<OMPParallelForDirective>(&D))
1239 HasCancel = OPFD->hasCancel();
1240 else if (
const auto *OPFD = dyn_cast<OMPTargetParallelForDirective>(&D))
1241 HasCancel = OPFD->hasCancel();
1242 else if (
const auto *OPFD = dyn_cast<OMPDistributeParallelForDirective>(&D))
1243 HasCancel = OPFD->hasCancel();
1244 else if (
const auto *OPFD =
1245 dyn_cast<OMPTeamsDistributeParallelForDirective>(&D))
1246 HasCancel = OPFD->hasCancel();
1247 else if (
const auto *OPFD =
1248 dyn_cast<OMPTargetTeamsDistributeParallelForDirective>(&D))
1249 HasCancel = OPFD->hasCancel();
1254 PushAndPopStackRAII PSR(&OMPBuilder, CGF, HasCancel, InnermostKind);
1255 CGOpenMPOutlinedRegionInfo CGInfo(*CS, ThreadIDVar,
CodeGen, InnermostKind,
1256 HasCancel, OutlinedHelperName);
1262 std::string Suffix =
getName({
"omp_outlined"});
1263 return (Name + Suffix).str();
1271 std::string Suffix =
getName({
"omp",
"reduction",
"reduction_func"});
1272 return (Name + Suffix).str();
1279 const CapturedStmt *CS = D.getCapturedStmt(OMPD_parallel);
1289 const CapturedStmt *CS = D.getCapturedStmt(OMPD_teams);
1299 bool Tied,
unsigned &NumberOfParts) {
1302 llvm::Value *ThreadID =
getThreadID(CGF, D.getBeginLoc());
1304 llvm::Value *TaskArgs[] = {
1306 CGF.EmitLoadOfPointerLValue(CGF.GetAddrOfLocalVar(TaskTVar),
1309 CGF.EmitRuntimeCall(
OMPBuilder.getOrCreateRuntimeFunction(
1310 CGM.getModule(), OMPRTL___kmpc_omp_task),
1313 CGOpenMPTaskOutlinedRegionInfo::UntiedTaskActionTy Action(Tied, PartIDVar,
1317 "thread id variable must be of type kmp_int32 for tasks");
1322 bool HasCancel =
false;
1323 if (
const auto *TD = dyn_cast<OMPTaskDirective>(&D))
1324 HasCancel = TD->hasCancel();
1325 else if (
const auto *TD = dyn_cast<OMPTaskLoopDirective>(&D))
1326 HasCancel = TD->hasCancel();
1327 else if (
const auto *TD = dyn_cast<OMPMasterTaskLoopDirective>(&D))
1328 HasCancel = TD->hasCancel();
1329 else if (
const auto *TD = dyn_cast<OMPParallelMasterTaskLoopDirective>(&D))
1330 HasCancel = TD->hasCancel();
1333 CGOpenMPTaskOutlinedRegionInfo CGInfo(*CS, ThreadIDVar,
CodeGen,
1334 InnermostKind, HasCancel, Action);
1336 llvm::Function *Res = CGF.GenerateCapturedStmtFunction(*CS);
1338 NumberOfParts = Action.getNumberOfParts();
1343 bool AtCurrentPoint) {
1345 assert(!Elem.ServiceInsertPt &&
"Insert point is set already.");
1347 llvm::Value *Undef = llvm::UndefValue::get(CGF.
Int32Ty);
1348 if (AtCurrentPoint) {
1349 Elem.ServiceInsertPt =
new llvm::BitCastInst(Undef, CGF.
Int32Ty,
"svcpt",
1350 CGF.
Builder.GetInsertBlock());
1352 Elem.ServiceInsertPt =
new llvm::BitCastInst(Undef, CGF.
Int32Ty,
"svcpt");
1353 Elem.ServiceInsertPt->insertAfter(CGF.
AllocaInsertPt->getIterator());
1359 if (Elem.ServiceInsertPt) {
1360 llvm::Instruction *Ptr = Elem.ServiceInsertPt;
1361 Elem.ServiceInsertPt =
nullptr;
1362 Ptr->eraseFromParent();
1369 llvm::raw_svector_ostream OS(Buffer);
1378 if (
const auto *FD = dyn_cast_or_null<FunctionDecl>(CGF.
CurFuncDecl))
1379 OS << FD->getQualifiedNameAsString();
1386 unsigned Flags,
bool EmitLoc) {
1387 uint32_t SrcLocStrSize;
1388 llvm::Constant *SrcLocStr;
1389 if ((!EmitLoc &&
CGM.getCodeGenOpts().getDebugInfo() ==
1390 llvm::codegenoptions::NoDebugInfo) ||
1392 SrcLocStr =
OMPBuilder.getOrCreateDefaultSrcLocStr(SrcLocStrSize);
1394 std::string FunctionName;
1396 if (
const auto *FD = dyn_cast_or_null<FunctionDecl>(CGF.
CurFuncDecl))
1397 FunctionName = FD->getQualifiedNameAsString();
1410 SrcLocStr, SrcLocStrSize, llvm::omp::IdentFlag(Flags), Reserved2Flags);
1415 assert(CGF.
CurFn &&
"No function in current CodeGenFunction.");
1418 if (
CGM.getLangOpts().OpenMPIRBuilder) {
1421 uint32_t SrcLocStrSize;
1422 auto *SrcLocStr =
OMPBuilder.getOrCreateSrcLocStr(
1425 OMPBuilder.getOrCreateIdent(SrcLocStr, SrcLocStrSize));
1428 llvm::Value *ThreadID =
nullptr;
1433 ThreadID = I->second.ThreadID;
1434 if (ThreadID !=
nullptr)
1438 if (
auto *OMPRegionInfo =
1440 if (OMPRegionInfo->getThreadIDVariable()) {
1442 LValue LVal = OMPRegionInfo->getThreadIDVariableLValue(CGF);
1446 CGF.
Builder.GetInsertBlock() == TopBlock ||
1451 CGF.
Builder.GetInsertBlock()) {
1455 if (CGF.
Builder.GetInsertBlock() == TopBlock)
1467 if (!Elem.ServiceInsertPt)
1469 CGBuilderTy::InsertPointGuard IPG(CGF.
Builder);
1470 CGF.
Builder.SetInsertPoint(Elem.ServiceInsertPt);
1474 OMPRTL___kmpc_global_thread_num),
1477 Elem.ThreadID =
Call;
1482 assert(CGF.
CurFn &&
"No function in current CodeGenFunction.");
1488 for (
const auto *D : I->second)
1493 for (
const auto *D : I->second)
1505static llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseKind
1507 std::optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
1508 OMPDeclareTargetDeclAttr::getDeviceType(VD);
1510 return llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseNone;
1512 switch ((
int)*DevTy) {
1513 case OMPDeclareTargetDeclAttr::DT_Host:
1514 return llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseHost;
1516 case OMPDeclareTargetDeclAttr::DT_NoHost:
1517 return llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseNoHost;
1519 case OMPDeclareTargetDeclAttr::DT_Any:
1520 return llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseAny;
1523 return llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseNone;
1528static llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryKind
1530 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> MapType =
1531 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
1533 return llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryNone;
1534 switch ((
int)*MapType) {
1535 case OMPDeclareTargetDeclAttr::MapTypeTy::MT_To:
1536 return llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryTo;
1538 case OMPDeclareTargetDeclAttr::MapTypeTy::MT_Enter:
1539 return llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryEnter;
1540 case OMPDeclareTargetDeclAttr::MapTypeTy::MT_Link:
1541 return llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryLink;
1543 case OMPDeclareTargetDeclAttr::MapTypeTy::MT_Local:
1545 llvm_unreachable(
"MT_Local should not reach convertCaptureClause");
1548 return llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryNone;
1557 auto FileInfoCallBack = [&]() {
1567 return OMPBuilder.getTargetEntryUniqueInfo(FileInfoCallBack,
1572 auto AddrOfGlobal = [&VD,
this]() {
return CGM.GetAddrOfGlobal(VD); };
1574 auto LinkageForVariable = [&VD,
this]() {
1575 return CGM.getLLVMLinkageVarDefinition(VD);
1578 std::vector<llvm::GlobalVariable *> GeneratedRefs;
1580 llvm::Type *LlvmPtrTy =
CGM.getTypes().ConvertTypeForMem(
1581 CGM.getContext().getPointerType(VD->
getType()));
1582 llvm::Constant *addr =
OMPBuilder.getAddrOfDeclareTargetVar(
1588 CGM.getMangledName(VD), GeneratedRefs,
CGM.getLangOpts().OpenMPSimd,
1589 CGM.getLangOpts().OMPTargetTriples, LlvmPtrTy, AddrOfGlobal,
1590 LinkageForVariable);
1599 assert(!
CGM.getLangOpts().OpenMPUseTLS ||
1600 !
CGM.getContext().getTargetInfo().isTLSSupported());
1602 std::string Suffix =
getName({
"cache",
""});
1603 return OMPBuilder.getOrCreateInternalVariable(
1604 CGM.Int8PtrPtrTy, Twine(
CGM.getMangledName(VD)).concat(Suffix).str());
1611 if (
CGM.getLangOpts().OpenMPUseTLS &&
1612 CGM.getContext().getTargetInfo().isTLSSupported())
1616 llvm::Value *Args[] = {
1619 CGM.getSize(
CGM.GetTargetTypeStoreSize(VarTy)),
1624 CGM.getModule(), OMPRTL___kmpc_threadprivate_cached),
1636 CGM.getModule(), OMPRTL___kmpc_global_thread_num),
1640 llvm::Value *Args[] = {
1643 Ctor, CopyCtor, Dtor};
1646 CGM.getModule(), OMPRTL___kmpc_threadprivate_register),
1653 if (
CGM.getLangOpts().OpenMPUseTLS &&
1654 CGM.getContext().getTargetInfo().isTLSSupported())
1661 llvm::Value *Ctor =
nullptr, *CopyCtor =
nullptr, *Dtor =
nullptr;
1663 if (
CGM.getLangOpts().CPlusPlus && PerformInit) {
1668 CGM.getContext(),
nullptr, Loc,
1672 const auto &FI =
CGM.getTypes().arrangeBuiltinFunctionDeclaration(
1673 CGM.getContext().VoidPtrTy, Args);
1674 llvm::FunctionType *FTy =
CGM.getTypes().GetFunctionType(FI);
1675 std::string Name =
getName({
"__kmpc_global_ctor_",
""});
1676 llvm::Function *Fn =
1677 CGM.CreateGlobalInitOrCleanUpFunction(FTy, Name, FI, Loc);
1682 CGM.getContext().VoidPtrTy, Dst->getLocation());
1689 CGM.getContext().VoidPtrTy, Dst->getLocation());
1699 CGM.getContext(),
nullptr, Loc,
1703 const auto &FI =
CGM.getTypes().arrangeBuiltinFunctionDeclaration(
1704 CGM.getContext().VoidTy, Args);
1705 llvm::FunctionType *FTy =
CGM.getTypes().GetFunctionType(FI);
1706 std::string Name =
getName({
"__kmpc_global_dtor_",
""});
1707 llvm::Function *Fn =
1708 CGM.CreateGlobalInitOrCleanUpFunction(FTy, Name, FI, Loc);
1716 false,
CGM.getContext().VoidPtrTy, Dst->getLocation());
1731 CopyCtor = llvm::Constant::getNullValue(
CGM.DefaultPtrTy);
1732 if (Ctor ==
nullptr) {
1733 Ctor = llvm::Constant::getNullValue(
CGM.DefaultPtrTy);
1735 if (Dtor ==
nullptr) {
1736 Dtor = llvm::Constant::getNullValue(
CGM.DefaultPtrTy);
1739 auto *InitFunctionTy =
1740 llvm::FunctionType::get(
CGM.VoidTy,
false);
1741 std::string Name =
getName({
"__omp_threadprivate_init_",
""});
1742 llvm::Function *InitFunction =
CGM.CreateGlobalInitOrCleanUpFunction(
1743 InitFunctionTy, Name,
CGM.getTypes().arrangeNullaryFunction());
1747 CGM.getTypes().arrangeNullaryFunction(), ArgList,
1751 return InitFunction;
1759 llvm::GlobalValue *GV) {
1760 std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr =
1761 OMPDeclareTargetDeclAttr::getActiveAttr(FD);
1764 if (!ActiveAttr || !(*ActiveAttr)->getIndirect())
1771 OMPBuilder.OffloadInfoManager.getTargetRegionEntryFnName(Name, EntryInfo);
1777 llvm::GlobalValue *
Addr = GV;
1778 if (
CGM.getLangOpts().OpenMPIsTargetDevice) {
1779 llvm::PointerType *FnPtrTy = llvm::PointerType::get(
1780 CGM.getLLVMContext(),
1781 CGM.getModule().getDataLayout().getProgramAddressSpace());
1782 Addr =
new llvm::GlobalVariable(
1783 CGM.getModule(), FnPtrTy,
1784 true, llvm::GlobalValue::ExternalLinkage, GV, Name,
1785 nullptr, llvm::GlobalValue::NotThreadLocal,
1786 CGM.getModule().getDataLayout().getDefaultGlobalsAddressSpace());
1787 Addr->setVisibility(llvm::GlobalValue::ProtectedVisibility);
1794 OMPBuilder.OffloadInfoManager.registerDeviceGlobalVarEntryInfo(
1795 Name,
Addr,
CGM.GetTargetTypeStoreSize(
CGM.VoidPtrTy).getQuantity(),
1796 llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryIndirect,
1797 llvm::GlobalValue::WeakODRLinkage);
1810 llvm::OpenMPIRBuilder &
OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
1826 llvm::GlobalVariable *
Addr = VTable;
1828 OMPBuilder.OffloadInfoManager.getTargetRegionEntryFnName(AddrName, EntryInfo);
1829 AddrName.append(
"addr");
1831 if (
CGM.getLangOpts().OpenMPIsTargetDevice) {
1832 Addr =
new llvm::GlobalVariable(
1833 CGM.getModule(), VTable->getType(),
1834 true, llvm::GlobalValue::ExternalLinkage, VTable,
1836 nullptr, llvm::GlobalValue::NotThreadLocal,
1837 CGM.getModule().getDataLayout().getDefaultGlobalsAddressSpace());
1838 Addr->setVisibility(llvm::GlobalValue::ProtectedVisibility);
1840 OMPBuilder.OffloadInfoManager.registerDeviceGlobalVarEntryInfo(
1842 CGM.getDataLayout().getTypeAllocSize(VTable->getInitializer()->getType()),
1843 llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryIndirectVTable,
1844 llvm::GlobalValue::WeakODRLinkage);
1853 !
CGM.getOpenMPRuntime().VTableDeclMap.contains(
CXXRecord)) {
1854 auto Res =
CGM.getOpenMPRuntime().VTableDeclMap.try_emplace(
CXXRecord, VD);
1859 assert(VTablesAddr &&
"Expected non-null VTable address");
1861 if (VTablesAddr->hasExternalLinkage())
1862 VTablesAddr->setLinkage(llvm::GlobalValue::WeakODRLinkage);
1863 CGM.getOpenMPRuntime().registerVTableOffloadEntry(VTablesAddr, VD);
1881 auto GetVTableDecl = [](
const Expr *E) {
1892 if (
auto *DRE = dyn_cast<DeclRefExpr>(E)) {
1894 }
else if (
auto *MRE = dyn_cast<MemberExpr>(E)) {
1895 if (
auto *BaseDRE = dyn_cast<DeclRefExpr>(MRE->getBase())) {
1896 if (
auto *BaseVD = dyn_cast<VarDecl>(BaseDRE->getDecl()))
1900 return std::pair<CXXRecordDecl *, const VarDecl *>(
CXXRecord, VD);
1904 for (
const auto *E :
C->varlist()) {
1905 auto DeclPair = GetVTableDecl(E);
1907 if (DeclPair.second)
1916 std::string Suffix =
getName({
"artificial",
""});
1918 llvm::GlobalVariable *GAddr =
OMPBuilder.getOrCreateInternalVariable(
1919 VarLVType, Twine(Name).concat(Suffix).str());
1920 if (
CGM.getLangOpts().OpenMP &&
CGM.getLangOpts().OpenMPUseTLS &&
1921 CGM.getTarget().isTLSSupported()) {
1922 GAddr->setThreadLocal(
true);
1923 return Address(GAddr, GAddr->getValueType(),
1924 CGM.getContext().getTypeAlignInChars(VarType));
1926 std::string CacheSuffix =
getName({
"cache",
""});
1927 llvm::Value *Args[] = {
1935 Twine(Name).concat(Suffix).concat(CacheSuffix).str())};
1940 CGM.getModule(), OMPRTL___kmpc_threadprivate_cached),
1943 VarLVType,
CGM.getContext().getTypeAlignInChars(VarType));
1993 auto &M =
CGM.getModule();
1994 auto &&ThenGen = [&M, OutlinedFn, CapturedVars, RTLoc,
1997 llvm::Value *Args[] = {
1999 CGF.
Builder.getInt32(CapturedVars.size()),
2002 RealArgs.append(std::begin(Args), std::end(Args));
2003 RealArgs.append(CapturedVars.begin(), CapturedVars.end());
2005 llvm::FunctionCallee RTLFn =
2006 OMPBuilder.getOrCreateRuntimeFunction(M, OMPRTL___kmpc_fork_call);
2009 auto &&ElseGen = [&M, OutlinedFn, CapturedVars, RTLoc, Loc,
2015 llvm::Value *Args[] = {RTLoc, ThreadID};
2017 M, OMPRTL___kmpc_serialized_parallel),
2024 ".bound.zero.addr");
2029 OutlinedFnArgs.push_back(ZeroAddrBound.
getPointer());
2030 OutlinedFnArgs.append(CapturedVars.begin(), CapturedVars.end());
2038 OutlinedFn->removeFnAttr(llvm::Attribute::AlwaysInline);
2039 OutlinedFn->addFnAttr(llvm::Attribute::NoInline);
2045 M, OMPRTL___kmpc_end_serialized_parallel),
2064 if (
auto *OMPRegionInfo =
2066 if (OMPRegionInfo->getThreadIDVariable())
2067 return OMPRegionInfo->getThreadIDVariableLValue(CGF).getAddress();
2077 return ThreadIDTemp;
2081 std::string Prefix = Twine(
"gomp_critical_user_", CriticalName).str();
2082 std::string Name =
getName({Prefix,
"var"});
2083 llvm::GlobalVariable *GV =
2085 CGM.setDSOLocal(GV);
2092 llvm::FunctionCallee EnterCallee;
2094 llvm::FunctionCallee ExitCallee;
2097 llvm::BasicBlock *ContBlock =
nullptr;
2100 CommonActionTy(llvm::FunctionCallee EnterCallee,
2102 llvm::FunctionCallee ExitCallee,
2104 : EnterCallee(EnterCallee), EnterArgs(EnterArgs), ExitCallee(ExitCallee),
2109 llvm::Value *CallBool = CGF.
Builder.CreateIsNotNull(EnterRes);
2113 CGF.
Builder.CreateCondBr(CallBool, ThenBlock, ContBlock);
2117 void Done(CodeGenFunction &CGF) {
2122 void Exit(CodeGenFunction &CGF)
override {
2129 StringRef CriticalName,
2138 llvm::FunctionCallee RuntimeFcn =
OMPBuilder.getOrCreateRuntimeFunction(
2140 Hint ? OMPRTL___kmpc_critical_with_hint : OMPRTL___kmpc_critical);
2142 unsigned LockVarArgIdx = 2;
2144 RuntimeFcn.getFunctionType()
2145 ->getParamType(LockVarArgIdx)
2146 ->getPointerAddressSpace())
2148 LockVar, RuntimeFcn.getFunctionType()->getParamType(LockVarArgIdx));
2154 EnterArgs.push_back(CGF.
Builder.CreateIntCast(
2157 CommonActionTy Action(RuntimeFcn, EnterArgs,
2159 CGM.getModule(), OMPRTL___kmpc_end_critical),
2176 CommonActionTy Action(
OMPBuilder.getOrCreateRuntimeFunction(
2177 CGM.getModule(), OMPRTL___kmpc_master),
2180 CGM.getModule(), OMPRTL___kmpc_end_master),
2198 llvm::Value *FilterVal = Filter
2200 : llvm::ConstantInt::get(
CGM.Int32Ty, 0);
2205 CommonActionTy Action(
OMPBuilder.getOrCreateRuntimeFunction(
2206 CGM.getModule(), OMPRTL___kmpc_masked),
2209 CGM.getModule(), OMPRTL___kmpc_end_masked),
2225 llvm::Value *Args[] = {
2227 llvm::ConstantInt::get(
CGM.IntTy, 0,
true)};
2229 CGM.getModule(), OMPRTL___kmpc_omp_taskyield),
2233 if (
auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.
CapturedStmtInfo))
2234 Region->emitUntiedSwitch(CGF);
2247 CommonActionTy Action(
OMPBuilder.getOrCreateRuntimeFunction(
2248 CGM.getModule(), OMPRTL___kmpc_taskgroup),
2251 CGM.getModule(), OMPRTL___kmpc_end_taskgroup),
2260 unsigned Index,
const VarDecl *Var) {
2289 llvm::GlobalValue::InternalLinkage, Name,
2293 Fn->addFnAttr(
"sample-profile-suffix-elision-policy",
"selected");
2294 Fn->setDoesNotRecurse();
2311 for (
unsigned I = 0, E = AssignmentOps.size(); I < E; ++I) {
2312 const auto *DestVar =
2316 const auto *SrcVar =
2322 CGF.
EmitOMPCopy(
Type, DestAddr, SrcAddr, DestVar, SrcVar, AssignmentOps[I]);
2337 assert(CopyprivateVars.size() == SrcExprs.size() &&
2338 CopyprivateVars.size() == DstExprs.size() &&
2339 CopyprivateVars.size() == AssignmentOps.size());
2351 if (!CopyprivateVars.empty()) {
2354 C.getIntTypeForBitwidth(32, 1);
2360 CommonActionTy Action(
OMPBuilder.getOrCreateRuntimeFunction(
2361 CGM.getModule(), OMPRTL___kmpc_single),
2364 CGM.getModule(), OMPRTL___kmpc_end_single),
2377 llvm::APInt ArraySize(32, CopyprivateVars.size());
2378 QualType CopyprivateArrayTy =
C.getConstantArrayType(
2383 CopyprivateArrayTy,
".omp.copyprivate.cpr_list");
2384 for (
unsigned I = 0, E = CopyprivateVars.size(); I < E; ++I) {
2396 SrcExprs, DstExprs, AssignmentOps, Loc);
2397 llvm::Value *BufSize = CGF.
getTypeSize(CopyprivateArrayTy);
2401 llvm::Value *Args[] = {
2405 CL.emitRawPointer(CGF),
2410 CGM.getModule(), OMPRTL___kmpc_copyprivate),
2426 CommonActionTy Action(
OMPBuilder.getOrCreateRuntimeFunction(
2427 CGM.getModule(), OMPRTL___kmpc_ordered),
2430 CGM.getModule(), OMPRTL___kmpc_end_ordered),
2441 if (Kind == OMPD_for)
2442 Flags = OMP_IDENT_BARRIER_IMPL_FOR;
2443 else if (Kind == OMPD_sections)
2444 Flags = OMP_IDENT_BARRIER_IMPL_SECTIONS;
2445 else if (Kind == OMPD_single)
2446 Flags = OMP_IDENT_BARRIER_IMPL_SINGLE;
2447 else if (Kind == OMPD_barrier)
2448 Flags = OMP_IDENT_BARRIER_EXPL;
2450 Flags = OMP_IDENT_BARRIER_IMPL;
2460 S.getClausesOfKind<OMPOrderedClause>(),
2461 [](
const OMPOrderedClause *
C) { return C->getNumForLoops(); })) {
2462 ScheduleKind = OMPC_SCHEDULE_static;
2464 llvm::APInt ChunkSize(32, 1);
2474 bool ForceSimpleCall) {
2476 auto *OMPRegionInfo =
2479 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
2482 CGF.
Builder.restoreIP(AfterIP);
2495 if (OMPRegionInfo) {
2496 if (!ForceSimpleCall && OMPRegionInfo->hasCancel()) {
2499 OMPRTL___kmpc_cancel_barrier),
2508 CGF.
Builder.CreateCondBr(
Cmp, ExitBB, ContBB);
2520 CGM.getModule(), OMPRTL___kmpc_barrier),
2525 Expr *ME,
bool IsFatal) {
2527 : llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
2530 llvm::Value *Args[] = {
2532 llvm::ConstantInt::get(
CGM.Int32Ty, IsFatal ? 2 : 1),
2533 CGF.
Builder.CreatePointerCast(MVL,
CGM.Int8PtrTy)};
2535 CGM.getModule(), OMPRTL___kmpc_error),
2541 bool Chunked,
bool Ordered) {
2542 switch (ScheduleKind) {
2543 case OMPC_SCHEDULE_static:
2544 return Chunked ? (Ordered ? OMP_ord_static_chunked : OMP_sch_static_chunked)
2545 : (Ordered ? OMP_ord_static : OMP_sch_static);
2546 case OMPC_SCHEDULE_dynamic:
2547 return Ordered ? OMP_ord_dynamic_chunked : OMP_sch_dynamic_chunked;
2548 case OMPC_SCHEDULE_guided:
2549 return Ordered ? OMP_ord_guided_chunked : OMP_sch_guided_chunked;
2550 case OMPC_SCHEDULE_runtime:
2551 return Ordered ? OMP_ord_runtime : OMP_sch_runtime;
2552 case OMPC_SCHEDULE_auto:
2553 return Ordered ? OMP_ord_auto : OMP_sch_auto;
2555 assert(!Chunked &&
"chunk was specified but schedule kind not known");
2556 return Ordered ? OMP_ord_static : OMP_sch_static;
2558 llvm_unreachable(
"Unexpected runtime schedule");
2562static OpenMPSchedType
2565 return Chunked ? OMP_dist_sch_static_chunked : OMP_dist_sch_static;
2569 bool Chunked)
const {
2570 OpenMPSchedType Schedule =
2572 return Schedule == OMP_sch_static;
2578 return Schedule == OMP_dist_sch_static;
2582 bool Chunked)
const {
2583 OpenMPSchedType Schedule =
2585 return Schedule == OMP_sch_static_chunked;
2591 return Schedule == OMP_dist_sch_static_chunked;
2595 OpenMPSchedType Schedule =
2597 assert(Schedule != OMP_sch_static_chunked &&
"cannot be chunked here");
2598 return Schedule != OMP_sch_static;
2606 case OMPC_SCHEDULE_MODIFIER_monotonic:
2607 Modifier = OMP_sch_modifier_monotonic;
2609 case OMPC_SCHEDULE_MODIFIER_nonmonotonic:
2610 Modifier = OMP_sch_modifier_nonmonotonic;
2612 case OMPC_SCHEDULE_MODIFIER_simd:
2613 if (Schedule == OMP_sch_static_chunked)
2614 Schedule = OMP_sch_static_balanced_chunked;
2621 case OMPC_SCHEDULE_MODIFIER_monotonic:
2622 Modifier = OMP_sch_modifier_monotonic;
2624 case OMPC_SCHEDULE_MODIFIER_nonmonotonic:
2625 Modifier = OMP_sch_modifier_nonmonotonic;
2627 case OMPC_SCHEDULE_MODIFIER_simd:
2628 if (Schedule == OMP_sch_static_chunked)
2629 Schedule = OMP_sch_static_balanced_chunked;
2641 if (CGM.
getLangOpts().OpenMP >= 50 && Modifier == 0) {
2642 if (!(Schedule == OMP_sch_static_chunked || Schedule == OMP_sch_static ||
2643 Schedule == OMP_sch_static_balanced_chunked ||
2644 Schedule == OMP_ord_static_chunked || Schedule == OMP_ord_static ||
2645 Schedule == OMP_dist_sch_static_chunked ||
2646 Schedule == OMP_dist_sch_static ||
2647 Schedule == OMP_dist_sch_static_chunked_sch_static_chunkone))
2648 Modifier = OMP_sch_modifier_nonmonotonic;
2650 return Schedule | Modifier;
2660 ScheduleKind.
Schedule, DispatchValues.
Chunk !=
nullptr, Ordered);
2662 (Schedule != OMP_sch_static && Schedule != OMP_sch_static_chunked &&
2663 Schedule != OMP_ord_static && Schedule != OMP_ord_static_chunked &&
2664 Schedule != OMP_sch_static_balanced_chunked));
2671 llvm::Value *Chunk = DispatchValues.
Chunk ? DispatchValues.
Chunk
2672 : CGF.
Builder.getIntN(IVSize, 1);
2673 llvm::Value *Args[] = {
2677 CGM, Schedule, ScheduleKind.
M1, ScheduleKind.
M2)),
2680 CGF.
Builder.getIntN(IVSize, 1),
2697 CodeGenFunction &CGF, llvm::Value *UpdateLocation, llvm::Value *ThreadId,
2698 llvm::FunctionCallee ForStaticInitFunction, OpenMPSchedType Schedule,
2705 assert(Schedule == OMP_sch_static || Schedule == OMP_sch_static_chunked ||
2706 Schedule == OMP_sch_static_balanced_chunked ||
2707 Schedule == OMP_ord_static || Schedule == OMP_ord_static_chunked ||
2708 Schedule == OMP_dist_sch_static ||
2709 Schedule == OMP_dist_sch_static_chunked ||
2710 Schedule == OMP_dist_sch_static_chunked_sch_static_chunkone);
2717 llvm::Value *Chunk = Values.
Chunk;
2718 if (Chunk ==
nullptr) {
2719 assert((Schedule == OMP_sch_static || Schedule == OMP_ord_static ||
2720 Schedule == OMP_dist_sch_static) &&
2721 "expected static non-chunked schedule");
2725 assert((Schedule == OMP_sch_static_chunked ||
2726 Schedule == OMP_sch_static_balanced_chunked ||
2727 Schedule == OMP_ord_static_chunked ||
2728 Schedule == OMP_dist_sch_static_chunked ||
2729 Schedule == OMP_dist_sch_static_chunked_sch_static_chunkone) &&
2730 "expected static chunked schedule");
2732 llvm::Value *Args[] = {
2752 OpenMPSchedType ScheduleNum =
2754 ? OMP_dist_sch_static_chunked_sch_static_chunkone
2758 "Expected loop-based or sections-based directive.");
2761 ? OMP_IDENT_WORK_LOOP
2762 : OMP_IDENT_WORK_SECTIONS);
2764 llvm::FunctionCallee StaticInitFunction =
2769 ScheduleNum, ScheduleKind.
M1, ScheduleKind.
M2, Values);
2776 OpenMPSchedType ScheduleNum =
2778 llvm::Value *UpdatedLocation =
2781 llvm::FunctionCallee StaticInitFunction;
2782 bool isGPUDistribute =
2783 CGM.getLangOpts().OpenMPIsTargetDevice &&
CGM.getTriple().isGPU();
2784 StaticInitFunction =
OMPBuilder.createForStaticInitFunction(
2795 assert((DKind == OMPD_distribute || DKind == OMPD_for ||
2796 DKind == OMPD_sections) &&
2797 "Expected distribute, for, or sections directive kind");
2801 llvm::Value *Args[] = {
2804 (DKind == OMPD_target_teams_loop)
2805 ? OMP_IDENT_WORK_DISTRIBUTE
2807 ? OMP_IDENT_WORK_LOOP
2808 : OMP_IDENT_WORK_SECTIONS),
2812 CGM.getLangOpts().OpenMPIsTargetDevice &&
CGM.getTriple().isGPU())
2815 CGM.getModule(), OMPRTL___kmpc_distribute_static_fini),
2819 CGM.getModule(), OMPRTL___kmpc_for_static_fini),
2844 llvm::Value *Args[] = {
2852 OMPBuilder.createDispatchNextFunction(IVSize, IVSigned), Args);
2859 const Expr *Message,
2862 return llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
2871 return llvm::ConstantInt::get(
CGM.Int32Ty,
2872 Severity == OMPC_SEVERITY_warning ? 1 : 2);
2888 RuntimeFunction FnID = OMPRTL___kmpc_push_num_threads;
2889 if (Modifier == OMPC_NUMTHREADS_strict) {
2890 FnID = OMPRTL___kmpc_push_num_threads_strict;
2895 OMPBuilder.getOrCreateRuntimeFunction(
CGM.getModule(), FnID), Args);
2899 ProcBindKind ProcBind,
2903 assert(ProcBind != OMP_PROC_BIND_unknown &&
"Unsupported proc_bind value.");
2905 llvm::Value *Args[] = {
2907 llvm::ConstantInt::get(
CGM.IntTy,
unsigned(ProcBind),
true)};
2909 CGM.getModule(), OMPRTL___kmpc_push_proc_bind),
2922 CGM.getModule(), OMPRTL___kmpc_flush),
2929enum KmpTaskTFields {
2956 if (
CGM.getLangOpts().OpenMPSimd ||
OMPBuilder.OffloadInfoManager.empty())
2959 llvm::OpenMPIRBuilder::EmitMetadataErrorReportFunctionTy &&ErrorReportFn =
2960 [
this](llvm::OpenMPIRBuilder::EmitMetadataErrorKind Kind,
2961 const llvm::TargetRegionEntryInfo &EntryInfo) ->
void {
2963 if (Kind != llvm::OpenMPIRBuilder::EMIT_MD_GLOBAL_VAR_LINK_ERROR) {
2964 for (
auto I =
CGM.getContext().getSourceManager().fileinfo_begin(),
2965 E =
CGM.getContext().getSourceManager().fileinfo_end();
2967 if (I->getFirst().getUniqueID().getDevice() == EntryInfo.DeviceID &&
2968 I->getFirst().getUniqueID().getFile() == EntryInfo.FileID) {
2969 Loc =
CGM.getContext().getSourceManager().translateFileLineCol(
2970 I->getFirst(), EntryInfo.Line, 1);
2976 case llvm::OpenMPIRBuilder::EMIT_MD_TARGET_REGION_ERROR: {
2977 CGM.getDiags().Report(Loc,
2978 diag::err_target_region_offloading_entry_incorrect)
2979 << EntryInfo.ParentName;
2981 case llvm::OpenMPIRBuilder::EMIT_MD_DECLARE_TARGET_ERROR: {
2982 CGM.getDiags().Report(
2983 Loc, diag::err_target_var_offloading_entry_incorrect_with_parent)
2984 << EntryInfo.ParentName;
2986 case llvm::OpenMPIRBuilder::EMIT_MD_GLOBAL_VAR_LINK_ERROR: {
2987 CGM.getDiags().Report(diag::err_target_var_offloading_entry_incorrect);
2989 case llvm::OpenMPIRBuilder::EMIT_MD_GLOBAL_VAR_INDIRECT_ERROR: {
2990 unsigned DiagID =
CGM.getDiags().getCustomDiagID(
2992 "target variable is incorrect: the "
2993 "address is invalid.");
2994 CGM.getDiags().Report(DiagID);
2999 OMPBuilder.createOffloadEntriesAndInfoMetadata(ErrorReportFn);
3006 QualType KmpRoutineEntryTyArgs[] = {KmpInt32Ty,
C.VoidPtrTy};
3009 C.getFunctionType(KmpInt32Ty, KmpRoutineEntryTyArgs, EPI));
3015struct PrivateHelpersTy {
3016 PrivateHelpersTy(
const Expr *OriginalRef,
const VarDecl *Original,
3018 : OriginalRef(OriginalRef), Original(Original), PrivateCopy(PrivateCopy),
3019 PrivateElemInit(PrivateElemInit) {}
3020 PrivateHelpersTy(
const VarDecl *Original) : Original(Original) {}
3021 const Expr *OriginalRef =
nullptr;
3022 const VarDecl *Original =
nullptr;
3023 const VarDecl *PrivateCopy =
nullptr;
3024 const VarDecl *PrivateElemInit =
nullptr;
3025 bool isLocalPrivate()
const {
3026 return !OriginalRef && !PrivateCopy && !PrivateElemInit;
3029typedef std::pair<CharUnits , PrivateHelpersTy> PrivateDataTy;
3034 if (!CVD->
hasAttr<OMPAllocateDeclAttr>())
3036 const auto *AA = CVD->
getAttr<OMPAllocateDeclAttr>();
3038 return !(AA->getAllocatorType() == OMPAllocateDeclAttr::OMPDefaultMemAlloc &&
3039 !AA->getAllocator());
3049 RecordDecl *RD =
C.buildImplicitRecord(
".kmp_privates.t");
3051 for (
const auto &Pair :
Privates) {
3052 const VarDecl *VD = Pair.second.Original;
3056 if (Pair.second.isLocalPrivate()) {
3079 QualType KmpRoutineEntryPointerQTy) {
3099 CanQualType KmpCmplrdataTy =
C.getCanonicalTagType(UD);
3100 RecordDecl *RD =
C.buildImplicitRecord(
"kmp_task_t");
3130 RecordDecl *RD =
C.buildImplicitRecord(
"kmp_task_t_with_privates");
3150static llvm::Function *
3153 QualType KmpTaskTWithPrivatesPtrQTy,
3155 QualType SharedsPtrTy, llvm::Function *TaskFunction,
3156 llvm::Value *TaskPrivatesMap) {
3162 C,
nullptr, Loc,
nullptr,
3165 const auto &TaskEntryFnInfo =
3167 llvm::FunctionType *TaskEntryTy =
3170 auto *TaskEntry = llvm::Function::Create(
3171 TaskEntryTy, llvm::GlobalValue::InternalLinkage, Name, &CGM.
getModule());
3174 TaskEntry->addFnAttr(
"sample-profile-suffix-elision-policy",
"selected");
3175 TaskEntry->setDoesNotRecurse();
3190 const auto *KmpTaskTWithPrivatesQTyRD =
3195 auto PartIdFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTPartId);
3197 llvm::Value *PartidParam = PartIdLVal.getPointer(CGF);
3199 auto SharedsFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTShareds);
3205 auto PrivatesFI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin(), 1);
3206 llvm::Value *PrivatesParam;
3207 if (PrivatesFI != KmpTaskTWithPrivatesQTyRD->field_end()) {
3210 PrivatesLVal.getPointer(CGF), CGF.
VoidPtrTy);
3212 PrivatesParam = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
3215 llvm::Value *CommonArgs[] = {
3216 GtidParam, PartidParam, PrivatesParam, TaskPrivatesMap,
3222 std::end(CommonArgs));
3224 auto LBFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound);
3227 auto UBFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound);
3230 auto StFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTStride);
3233 auto LIFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLastIter);
3236 auto RFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTReductions);
3239 CallArgs.push_back(LBParam);
3240 CallArgs.push_back(UBParam);
3241 CallArgs.push_back(StParam);
3242 CallArgs.push_back(LIParam);
3243 CallArgs.push_back(RParam);
3245 CallArgs.push_back(SharedsParam);
3258 QualType KmpTaskTWithPrivatesPtrQTy,
3259 QualType KmpTaskTWithPrivatesQTy) {
3265 C,
nullptr, Loc,
nullptr,
3268 const auto &DestructorFnInfo =
3270 llvm::FunctionType *DestructorFnTy =
3274 auto *DestructorFn =
3275 llvm::Function::Create(DestructorFnTy, llvm::GlobalValue::InternalLinkage,
3280 DestructorFn->addFnAttr(
"sample-profile-suffix-elision-policy",
"selected");
3281 DestructorFn->setDoesNotRecurse();
3289 const auto *KmpTaskTWithPrivatesQTyRD =
3291 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin());
3293 for (
const auto *Field : FI->getType()->castAsRecordDecl()->fields()) {
3295 Field->getType().isDestructedType()) {
3297 CGF.
pushDestroy(DtorKind, FieldLValue.getAddress(), Field->getType());
3301 return DestructorFn;
3321 C,
nullptr, Loc,
nullptr,
3322 C.getPointerType(PrivatesQTy).withConst().withRestrict(),
3324 Args.push_back(TaskPrivatesArg);
3325 llvm::DenseMap<CanonicalDeclPtr<const VarDecl>,
unsigned> PrivateVarsPos;
3326 unsigned Counter = 1;
3327 for (
const Expr *E :
Data.PrivateVars) {
3329 C,
nullptr, Loc,
nullptr,
3330 C.getPointerType(
C.getPointerType(E->
getType()))
3335 PrivateVarsPos[VD] = Counter;
3338 for (
const Expr *E :
Data.FirstprivateVars) {
3340 C,
nullptr, Loc,
nullptr,
3341 C.getPointerType(
C.getPointerType(E->
getType()))
3346 PrivateVarsPos[VD] = Counter;
3349 for (
const Expr *E :
Data.LastprivateVars) {
3351 C,
nullptr, Loc,
nullptr,
3352 C.getPointerType(
C.getPointerType(E->
getType()))
3357 PrivateVarsPos[VD] = Counter;
3363 Ty =
C.getPointerType(Ty);
3365 Ty =
C.getPointerType(Ty);
3367 C,
nullptr, Loc,
nullptr,
3368 C.getPointerType(
C.getPointerType(Ty)).withConst().withRestrict(),
3370 PrivateVarsPos[VD] = Counter;
3373 const auto &TaskPrivatesMapFnInfo =
3375 llvm::FunctionType *TaskPrivatesMapTy =
3379 auto *TaskPrivatesMap = llvm::Function::Create(
3380 TaskPrivatesMapTy, llvm::GlobalValue::InternalLinkage, Name,
3383 TaskPrivatesMapFnInfo);
3385 TaskPrivatesMap->addFnAttr(
"sample-profile-suffix-elision-policy",
3388 TaskPrivatesMap->removeFnAttr(llvm::Attribute::NoInline);
3389 TaskPrivatesMap->removeFnAttr(llvm::Attribute::OptimizeNone);
3390 TaskPrivatesMap->addFnAttr(llvm::Attribute::AlwaysInline);
3394 TaskPrivatesMapFnInfo, Args, Loc, Loc);
3402 for (
const FieldDecl *Field : PrivatesQTyRD->fields()) {
3404 const VarDecl *VD = Args[PrivateVarsPos[
Privates[Counter].second.Original]];
3408 RefLVal.getAddress(), RefLVal.getType()->castAs<
PointerType>());
3413 return TaskPrivatesMap;
3419 Address KmpTaskSharedsPtr, LValue TDBase,
3425 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->
field_begin());
3439 if ((!IsTargetTask && !
Data.FirstprivateVars.empty() && ForDup) ||
3440 (IsTargetTask && KmpTaskSharedsPtr.
isValid())) {
3447 FI = FI->getType()->castAsRecordDecl()->field_begin();
3448 for (
const PrivateDataTy &Pair :
Privates) {
3450 if (Pair.second.isLocalPrivate()) {
3454 const VarDecl *VD = Pair.second.PrivateCopy;
3459 if (
const VarDecl *Elem = Pair.second.PrivateElemInit) {
3460 const VarDecl *OriginalVD = Pair.second.Original;
3463 LValue SharedRefLValue;
3466 if (IsTargetTask && !SharedField) {
3470 ->getNumParams() == 0 &&
3473 ->getDeclContext()) &&
3474 "Expected artificial target data variable.");
3477 }
else if (ForDup) {
3480 SharedRefLValue.getAddress().withAlignment(
3481 C.getDeclAlign(OriginalVD)),
3483 SharedRefLValue.getTBAAInfo());
3485 Pair.second.Original->getCanonicalDecl()) > 0 ||
3487 SharedRefLValue = CGF.
EmitLValue(Pair.second.OriginalRef);
3490 InlinedOpenMPRegionRAII Region(
3493 SharedRefLValue = CGF.
EmitLValue(Pair.second.OriginalRef);
3504 PrivateLValue.getAddress(), SharedRefLValue.getAddress(),
Type,
3505 [&CGF, Elem,
Init, &CapturesInfo](
Address DestElement,
3508 CodeGenFunction::OMPPrivateScope InitScope(CGF);
3509 InitScope.addPrivate(Elem, SrcElement);
3510 (void)InitScope.Privatize();
3512 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(
3513 CGF, &CapturesInfo);
3514 CGF.EmitAnyExprToMem(Init, DestElement,
3515 Init->getType().getQualifiers(),
3521 InitScope.addPrivate(Elem, SharedRefLValue.getAddress());
3522 (void)InitScope.Privatize();
3538 bool InitRequired =
false;
3539 for (
const PrivateDataTy &Pair :
Privates) {
3540 if (Pair.second.isLocalPrivate())
3542 const VarDecl *VD = Pair.second.PrivateCopy;
3544 InitRequired = InitRequired || (isa_and_nonnull<CXXConstructExpr>(
Init) &&
3549 return InitRequired;
3566 QualType KmpTaskTWithPrivatesPtrQTy,
3573 C,
nullptr, Loc,
nullptr, KmpTaskTWithPrivatesPtrQTy,
3576 C,
nullptr, Loc,
nullptr, KmpTaskTWithPrivatesPtrQTy,
3582 const auto &TaskDupFnInfo =
3586 auto *TaskDup = llvm::Function::Create(
3587 TaskDupTy, llvm::GlobalValue::InternalLinkage, Name, &CGM.
getModule());
3590 TaskDup->addFnAttr(
"sample-profile-suffix-elision-policy",
"selected");
3591 TaskDup->setDoesNotRecurse();
3601 auto LIFI = std::next(KmpTaskTQTyRD->
field_begin(), KmpTaskTLastIter);
3603 TDBase, *KmpTaskTWithPrivatesQTyRD->
field_begin());
3613 if (!
Data.FirstprivateVars.empty()) {
3618 TDBase, *KmpTaskTWithPrivatesQTyRD->
field_begin());
3626 emitPrivatesInit(CGF, D, KmpTaskSharedsPtr, TDBase, KmpTaskTWithPrivatesQTyRD,
3637 for (
const PrivateDataTy &P :
Privates) {
3638 if (P.second.isLocalPrivate())
3640 QualType Ty = P.second.Original->getType().getNonReferenceType();
3649class OMPIteratorGeneratorScope final
3651 CodeGenFunction &CGF;
3652 const OMPIteratorExpr *E =
nullptr;
3653 SmallVector<CodeGenFunction::JumpDest, 4> ContDests;
3654 SmallVector<CodeGenFunction::JumpDest, 4> ExitDests;
3655 OMPIteratorGeneratorScope() =
delete;
3656 OMPIteratorGeneratorScope(OMPIteratorGeneratorScope &) =
delete;
3659 OMPIteratorGeneratorScope(CodeGenFunction &CGF,
const OMPIteratorExpr *E)
3660 : CodeGenFunction::OMPPrivateScope(CGF), CGF(CGF), E(E) {
3663 SmallVector<llvm::Value *, 4> Uppers;
3665 Uppers.push_back(CGF.EmitScalarExpr(E->getHelper(I).Upper));
3666 const auto *VD = cast<VarDecl>(E->getIteratorDecl(I));
3667 addPrivate(VD, CGF.CreateMemTemp(VD->getType(), VD->getName()));
3668 const OMPIteratorHelperData &HelperData = E->getHelper(I);
3670 HelperData.CounterVD,
3671 CGF.CreateMemTemp(HelperData.CounterVD->getType(),
"counter.addr"));
3676 const OMPIteratorHelperData &HelperData = E->getHelper(I);
3678 CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(HelperData.CounterVD),
3679 HelperData.CounterVD->getType());
3681 CGF.EmitStoreOfScalar(
3682 llvm::ConstantInt::get(CLVal.getAddress().getElementType(), 0),
3684 CodeGenFunction::JumpDest &ContDest =
3685 ContDests.emplace_back(CGF.getJumpDestInCurrentScope(
"iter.cont"));
3686 CodeGenFunction::JumpDest &ExitDest =
3687 ExitDests.emplace_back(CGF.getJumpDestInCurrentScope(
"iter.exit"));
3689 llvm::Value *N = Uppers[I];
3692 CGF.EmitBlock(ContDest.getBlock());
3694 CGF.EmitLoadOfScalar(CLVal, HelperData.CounterVD->getLocation());
3696 HelperData.CounterVD->getType()->isSignedIntegerOrEnumerationType()
3697 ? CGF.Builder.CreateICmpSLT(CVal, N)
3698 : CGF.Builder.CreateICmpULT(CVal, N);
3699 llvm::BasicBlock *BodyBB = CGF.createBasicBlock(
"iter.body");
3700 CGF.Builder.CreateCondBr(Cmp, BodyBB, ExitDest.getBlock());
3702 CGF.EmitBlock(BodyBB);
3704 CGF.EmitIgnoredExpr(HelperData.Update);
3707 ~OMPIteratorGeneratorScope() {
3712 const OMPIteratorHelperData &HelperData = E->
getHelper(I - 1);
3717 CGF.
EmitBlock(ExitDests[I - 1].getBlock(), I == 1);
3723static std::pair<llvm::Value *, llvm::Value *>
3725 const auto *OASE = dyn_cast<OMPArrayShapingExpr>(E);
3728 const Expr *
Base = OASE->getBase();
3733 llvm::Value *SizeVal;
3736 SizeVal = CGF.
getTypeSize(OASE->getBase()->getType()->getPointeeType());
3737 for (
const Expr *SE : OASE->getDimensions()) {
3741 SizeVal = CGF.
Builder.CreateNUWMul(SizeVal, Sz);
3743 }
else if (
const auto *ASE =
3746 Address UpAddrAddress = UpAddrLVal.getAddress();
3747 llvm::Value *UpAddr = CGF.
Builder.CreateConstGEP1_32(
3750 SizeVal = CGF.
Builder.CreatePtrDiff(UpAddr,
Addr,
"",
true);
3754 return std::make_pair(
Addr, SizeVal);
3759 QualType FlagsTy =
C.getIntTypeForBitwidth(32,
false);
3760 if (KmpTaskAffinityInfoTy.
isNull()) {
3762 C.buildImplicitRecord(
"kmp_task_affinity_info_t");
3768 KmpTaskAffinityInfoTy =
C.getCanonicalTagType(KmpAffinityInfoRD);
3775 llvm::Function *TaskFunction,
QualType SharedsTy,
3780 const auto *I =
Data.PrivateCopies.begin();
3781 for (
const Expr *E :
Data.PrivateVars) {
3789 I =
Data.FirstprivateCopies.begin();
3790 const auto *IElemInitRef =
Data.FirstprivateInits.begin();
3791 for (
const Expr *E :
Data.FirstprivateVars) {
3801 I =
Data.LastprivateCopies.begin();
3802 for (
const Expr *E :
Data.LastprivateVars) {
3812 Privates.emplace_back(
CGM.getPointerAlign(), PrivateHelpersTy(VD));
3814 Privates.emplace_back(
C.getDeclAlign(VD), PrivateHelpersTy(VD));
3817 [](
const PrivateDataTy &L,
const PrivateDataTy &R) {
3818 return L.first > R.first;
3820 QualType KmpInt32Ty =
C.getIntTypeForBitwidth(32, 1);
3831 assert((D.getDirectiveKind() == OMPD_task ||
3834 "Expected taskloop, task or target directive");
3841 const auto *KmpTaskTQTyRD =
KmpTaskTQTy->castAsRecordDecl();
3843 const RecordDecl *KmpTaskTWithPrivatesQTyRD =
3846 C.getCanonicalTagType(KmpTaskTWithPrivatesQTyRD);
3847 QualType KmpTaskTWithPrivatesPtrQTy =
3848 C.getPointerType(KmpTaskTWithPrivatesQTy);
3849 llvm::Type *KmpTaskTWithPrivatesPtrTy = CGF.
Builder.getPtrTy(0);
3850 llvm::Value *KmpTaskTWithPrivatesTySize =
3852 QualType SharedsPtrTy =
C.getPointerType(SharedsTy);
3855 llvm::Value *TaskPrivatesMap =
nullptr;
3856 llvm::Type *TaskPrivatesMapTy =
3857 std::next(TaskFunction->arg_begin(), 3)->getType();
3859 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->
field_begin());
3863 TaskPrivatesMap, TaskPrivatesMapTy);
3865 TaskPrivatesMap = llvm::ConstantPointerNull::get(
3871 CGM, Loc, D.getDirectiveKind(), KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy,
3872 KmpTaskTWithPrivatesQTy,
KmpTaskTQTy, SharedsPtrTy, TaskFunction,
3884 DestructorsFlag = 0x8,
3885 PriorityFlag = 0x20,
3886 DetachableFlag = 0x40,
3887 FreeAgentFlag = 0x80,
3888 TransparentFlag = 0x100,
3890 unsigned Flags =
Data.Tied ? TiedFlag : 0;
3891 bool NeedsCleanup =
false;
3896 Flags = Flags | DestructorsFlag;
3900 if (Kind == OMPC_THREADSET_omp_pool)
3901 Flags = Flags | FreeAgentFlag;
3903 if (D.getSingleClause<OMPTransparentClause>())
3904 Flags |= TransparentFlag;
3906 if (
Data.Priority.getInt())
3907 Flags = Flags | PriorityFlag;
3909 Flags = Flags | DetachableFlag;
3910 llvm::Value *TaskFlags =
3911 Data.Final.getPointer()
3912 ? CGF.
Builder.CreateSelect(
Data.Final.getPointer(),
3913 CGF.
Builder.getInt32(FinalFlag),
3915 : CGF.
Builder.getInt32(
Data.Final.getInt() ? FinalFlag : 0);
3916 TaskFlags = CGF.
Builder.CreateOr(TaskFlags, CGF.
Builder.getInt32(Flags));
3917 llvm::Value *SharedsSize =
CGM.getSize(
C.getTypeSizeInChars(SharedsTy));
3919 getThreadID(CGF, Loc), TaskFlags, KmpTaskTWithPrivatesTySize,
3922 llvm::Value *NewTask;
3923 if (D.hasClausesOfKind<OMPNowaitClause>()) {
3929 llvm::Value *DeviceID;
3934 DeviceID = CGF.
Builder.getInt64(OMP_DEVICEID_UNDEF);
3935 AllocArgs.push_back(DeviceID);
3938 CGM.getModule(), OMPRTL___kmpc_omp_target_task_alloc),
3943 CGM.getModule(), OMPRTL___kmpc_omp_task_alloc),
3956 llvm::Value *Tid =
getThreadID(CGF, DC->getBeginLoc());
3957 Tid = CGF.
Builder.CreateIntCast(Tid, CGF.
IntTy,
false);
3960 CGM.getModule(), OMPRTL___kmpc_task_allow_completion_event),
3961 {Loc, Tid, NewTask});
3972 llvm::Value *NumOfElements =
nullptr;
3973 unsigned NumAffinities = 0;
3975 if (
const Expr *Modifier =
C->getModifier()) {
3977 for (
unsigned I = 0, E = IE->numOfIterators(); I < E; ++I) {
3981 NumOfElements ? CGF.
Builder.CreateNUWMul(NumOfElements, Sz) : Sz;
3984 NumAffinities +=
C->varlist_size();
3989 enum RTLAffinityInfoFieldsTy { BaseAddr, Len, Flags };
3991 QualType KmpTaskAffinityInfoArrayTy;
3992 if (NumOfElements) {
3993 NumOfElements = CGF.
Builder.CreateNUWAdd(
3994 llvm::ConstantInt::get(CGF.
SizeTy, NumAffinities), NumOfElements);
3997 C.getIntTypeForBitwidth(
C.getTypeSize(
C.getSizeType()), 0),
4001 KmpTaskAffinityInfoArrayTy =
C.getVariableArrayType(
4009 NumOfElements = CGF.
Builder.CreateIntCast(NumOfElements, CGF.
Int32Ty,
4012 KmpTaskAffinityInfoArrayTy =
C.getConstantArrayType(
4014 llvm::APInt(
C.getTypeSize(
C.getSizeType()), NumAffinities),
nullptr,
4019 NumOfElements = llvm::ConstantInt::get(
CGM.Int32Ty, NumAffinities,
4026 bool HasIterator =
false;
4028 if (
C->getModifier()) {
4032 for (
const Expr *E :
C->varlist()) {
4041 Base, *std::next(KmpAffinityInfoRD->field_begin(), BaseAddr));
4046 Base, *std::next(KmpAffinityInfoRD->field_begin(), Len));
4060 const Expr *Modifier =
C->getModifier();
4063 OMPIteratorGeneratorScope IteratorScope(
4065 for (
const Expr *E :
C->varlist()) {
4075 Base, *std::next(KmpAffinityInfoRD->field_begin(), BaseAddr));
4080 Base, *std::next(KmpAffinityInfoRD->field_begin(), Len));
4082 Idx = CGF.
Builder.CreateNUWAdd(
4083 Idx, llvm::ConstantInt::get(Idx->getType(), 1));
4098 CGM.getModule(), OMPRTL___kmpc_omp_reg_task_with_affinity),
4099 {LocRef, GTid, NewTask, NumOfElements, AffinListPtr});
4101 llvm::Value *NewTaskNewTaskTTy =
4103 NewTask, KmpTaskTWithPrivatesPtrTy);
4105 KmpTaskTWithPrivatesQTy);
4116 *std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTShareds)),
4118 CGF.
Int8Ty,
CGM.getNaturalTypeAlignment(SharedsTy));
4132 CGM, Loc, D, KmpTaskTWithPrivatesPtrQTy, KmpTaskTWithPrivatesQTyRD,
4133 KmpTaskTQTyRD, SharedsTy, SharedsPtrTy,
Data,
Privates,
4134 !
Data.LastprivateVars.empty());
4138 enum { Priority = 0, Destructors = 1 };
4140 auto FI = std::next(KmpTaskTQTyRD->field_begin(), Data1);
4141 const auto *KmpCmplrdataUD = (*FI)->getType()->castAsRecordDecl();
4142 assert(KmpCmplrdataUD->isUnion());
4145 CGM, Loc, KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy,
4146 KmpTaskTWithPrivatesQTy);
4149 Data1LV, *std::next(KmpCmplrdataUD->field_begin(), Destructors));
4155 if (
Data.Priority.getInt()) {
4157 TDBase, *std::next(KmpTaskTQTyRD->field_begin(), Data2));
4159 Data2LV, *std::next(KmpCmplrdataUD->field_begin(), Priority));
4162 Result.NewTask = NewTask;
4163 Result.TaskEntry = TaskEntry;
4164 Result.NewTaskNewTaskTTy = NewTaskNewTaskTTy;
4166 Result.KmpTaskTQTyRD = KmpTaskTQTyRD;
4172 RTLDependenceKindTy DepKind;
4174 case OMPC_DEPEND_in:
4175 DepKind = RTLDependenceKindTy::DepIn;
4178 case OMPC_DEPEND_out:
4179 case OMPC_DEPEND_inout:
4180 DepKind = RTLDependenceKindTy::DepInOut;
4182 case OMPC_DEPEND_mutexinoutset:
4183 DepKind = RTLDependenceKindTy::DepMutexInOutSet;
4185 case OMPC_DEPEND_inoutset:
4186 DepKind = RTLDependenceKindTy::DepInOutSet;
4188 case OMPC_DEPEND_outallmemory:
4189 DepKind = RTLDependenceKindTy::DepOmpAllMem;
4191 case OMPC_DEPEND_source:
4192 case OMPC_DEPEND_sink:
4193 case OMPC_DEPEND_depobj:
4194 case OMPC_DEPEND_inoutallmemory:
4196 llvm_unreachable(
"Unknown task dependence type");
4204 FlagsTy =
C.getIntTypeForBitwidth(
C.getTypeSize(
C.BoolTy),
false);
4205 if (KmpDependInfoTy.
isNull()) {
4206 RecordDecl *KmpDependInfoRD =
C.buildImplicitRecord(
"kmp_depend_info");
4212 KmpDependInfoTy =
C.getCanonicalTagType(KmpDependInfoRD);
4216std::pair<llvm::Value *, LValue>
4229 CGF,
Base.getAddress(),
4230 llvm::ConstantInt::get(CGF.
IntPtrTy, -1,
true));
4236 *std::next(KmpDependInfoRD->field_begin(),
4237 static_cast<unsigned int>(RTLDependInfoFields::BaseAddr)));
4239 return std::make_pair(NumDeps,
Base);
4243 llvm::PointerUnion<unsigned *, LValue *> Pos,
4253 OMPIteratorGeneratorScope IteratorScope(
4254 CGF, cast_or_null<OMPIteratorExpr>(
4255 Data.IteratorExpr ?
Data.IteratorExpr->IgnoreParenImpCasts()
4257 for (
const Expr *E :
Data.DepExprs) {
4267 Size = llvm::ConstantInt::get(CGF.
SizeTy, 0);
4270 if (
unsigned *P = dyn_cast<unsigned *>(Pos)) {
4274 assert(E &&
"Expected a non-null expression");
4283 *std::next(KmpDependInfoRD->field_begin(),
4284 static_cast<unsigned int>(RTLDependInfoFields::BaseAddr)));
4288 Base, *std::next(KmpDependInfoRD->field_begin(),
4289 static_cast<unsigned int>(RTLDependInfoFields::Len)));
4295 *std::next(KmpDependInfoRD->field_begin(),
4296 static_cast<unsigned int>(RTLDependInfoFields::Flags)));
4298 llvm::ConstantInt::get(LLVMFlagsTy,
static_cast<unsigned int>(DepKind)),
4300 if (
unsigned *P = dyn_cast<unsigned *>(Pos)) {
4305 Idx = CGF.
Builder.CreateNUWAdd(Idx,
4306 llvm::ConstantInt::get(Idx->getType(), 1));
4315 assert(
Data.DepKind == OMPC_DEPEND_depobj &&
4316 "Expected depobj dependency kind.");
4321 OMPIteratorGeneratorScope IteratorScope(
4322 CGF, cast_or_null<OMPIteratorExpr>(
4323 Data.IteratorExpr ?
Data.IteratorExpr->IgnoreParenImpCasts()
4325 for (
const Expr *E :
Data.DepExprs) {
4326 llvm::Value *NumDeps;
4329 std::tie(NumDeps,
Base) =
4333 C.getUIntPtrType());
4337 llvm::Value *Add = CGF.
Builder.CreateNUWAdd(PrevVal, NumDeps);
4339 SizeLVals.push_back(NumLVal);
4342 for (
unsigned I = 0, E = SizeLVals.size(); I < E; ++I) {
4345 Sizes.push_back(Size);
4355 assert(
Data.DepKind == OMPC_DEPEND_depobj &&
4356 "Expected depobj dependency kind.");
4359 OMPIteratorGeneratorScope IteratorScope(
4360 CGF, cast_or_null<OMPIteratorExpr>(
4361 Data.IteratorExpr ?
Data.IteratorExpr->IgnoreParenImpCasts()
4363 for (
const Expr *E :
Data.DepExprs) {
4364 llvm::Value *NumDeps;
4367 std::tie(NumDeps,
Base) =
4371 llvm::Value *Size = CGF.
Builder.CreateNUWMul(
4380 llvm::Value *Add = CGF.
Builder.CreateNUWAdd(Pos, NumDeps);
4396 llvm::Value *NumOfElements =
nullptr;
4397 unsigned NumDependencies = std::accumulate(
4398 Dependencies.begin(), Dependencies.end(), 0,
4400 return D.DepKind == OMPC_DEPEND_depobj
4402 : (V + (D.IteratorExpr ? 0 : D.DepExprs.size()));
4406 bool HasDepobjDeps =
false;
4407 bool HasRegularWithIterators =
false;
4408 llvm::Value *NumOfDepobjElements = llvm::ConstantInt::get(CGF.
IntPtrTy, 0);
4409 llvm::Value *NumOfRegularWithIterators =
4410 llvm::ConstantInt::get(CGF.
IntPtrTy, 0);
4414 if (D.
DepKind == OMPC_DEPEND_depobj) {
4417 for (llvm::Value *Size : Sizes) {
4418 NumOfDepobjElements =
4419 CGF.
Builder.CreateNUWAdd(NumOfDepobjElements, Size);
4421 HasDepobjDeps =
true;
4426 if (
const auto *IE = cast_or_null<OMPIteratorExpr>(D.
IteratorExpr)) {
4427 llvm::Value *ClauseIteratorSpace =
4428 llvm::ConstantInt::get(CGF.
IntPtrTy, 1);
4432 ClauseIteratorSpace = CGF.
Builder.CreateNUWMul(Sz, ClauseIteratorSpace);
4434 llvm::Value *NumClauseDeps = CGF.
Builder.CreateNUWMul(
4435 ClauseIteratorSpace,
4437 NumOfRegularWithIterators =
4438 CGF.
Builder.CreateNUWAdd(NumOfRegularWithIterators, NumClauseDeps);
4439 HasRegularWithIterators =
true;
4445 if (HasDepobjDeps || HasRegularWithIterators) {
4446 NumOfElements = llvm::ConstantInt::get(
CGM.IntPtrTy, NumDependencies,
4448 if (HasDepobjDeps) {
4450 CGF.
Builder.CreateNUWAdd(NumOfDepobjElements, NumOfElements);
4452 if (HasRegularWithIterators) {
4454 CGF.
Builder.CreateNUWAdd(NumOfRegularWithIterators, NumOfElements);
4457 Loc,
C.getIntTypeForBitwidth(64, 0),
4461 KmpDependInfoArrayTy =
4470 NumOfElements = CGF.
Builder.CreateIntCast(NumOfElements, CGF.
Int32Ty,
4473 KmpDependInfoArrayTy =
C.getConstantArrayType(
4479 NumOfElements = llvm::ConstantInt::get(
CGM.Int32Ty, NumDependencies,
4484 if (Dep.DepKind == OMPC_DEPEND_depobj || Dep.IteratorExpr)
4494 if (Dep.DepKind == OMPC_DEPEND_depobj || !Dep.IteratorExpr)
4499 if (HasDepobjDeps) {
4501 if (Dep.DepKind != OMPC_DEPEND_depobj)
4508 return std::make_pair(NumOfElements, DependenciesArray);
4519 unsigned NumDependencies = Dependencies.
DepExprs.size();
4529 llvm::Value *NumDepsVal;
4531 if (
const auto *IE =
4532 cast_or_null<OMPIteratorExpr>(Dependencies.
IteratorExpr)) {
4533 NumDepsVal = llvm::ConstantInt::get(CGF.
SizeTy, 1);
4537 NumDepsVal = CGF.
Builder.CreateNUWMul(NumDepsVal, Sz);
4539 Size = CGF.
Builder.CreateNUWAdd(llvm::ConstantInt::get(CGF.
SizeTy, 1),
4543 llvm::Value *RecSize =
CGM.getSize(SizeInBytes);
4544 Size = CGF.
Builder.CreateNUWMul(Size, RecSize);
4548 QualType KmpDependInfoArrayTy =
C.getConstantArrayType(
4551 CharUnits Sz =
C.getTypeSizeInChars(KmpDependInfoArrayTy);
4553 NumDepsVal = llvm::ConstantInt::get(CGF.
IntPtrTy, NumDependencies);
4558 llvm::Value *Allocator = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
4559 llvm::Value *Args[] = {ThreadID, Size, Allocator};
4563 CGM.getModule(), OMPRTL___kmpc_alloc),
4564 Args,
".dep.arr.addr");
4568 DependenciesArray =
Address(
Addr, KmpDependInfoLlvmTy, Align);
4574 *std::next(KmpDependInfoRD->field_begin(),
4575 static_cast<unsigned int>(RTLDependInfoFields::BaseAddr)));
4577 llvm::PointerUnion<unsigned *, LValue *> Pos;
4594 return DependenciesArray;
4609 Addr.getElementType(),
Addr.emitRawPointer(CGF),
4610 llvm::ConstantInt::get(CGF.
IntPtrTy, -1,
true));
4615 llvm::Value *Allocator = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
4616 llvm::Value *Args[] = {ThreadID, DepObjAddr, Allocator};
4620 CGM.getModule(), OMPRTL___kmpc_free),
4632 llvm::Value *NumDeps;
4643 llvm::BasicBlock *EntryBB = CGF.
Builder.GetInsertBlock();
4645 llvm::PHINode *ElementPHI =
4650 Base.getTBAAInfo());
4654 Base, *std::next(KmpDependInfoRD->field_begin(),
4655 static_cast<unsigned int>(RTLDependInfoFields::Flags)));
4657 llvm::ConstantInt::get(LLVMFlagsTy,
static_cast<unsigned int>(DepKind)),
4661 llvm::Value *ElementNext =
4664 ElementPHI->addIncoming(ElementNext, CGF.
Builder.GetInsertBlock());
4665 llvm::Value *IsEmpty =
4666 CGF.
Builder.CreateICmpEQ(ElementNext, End,
"omp.isempty");
4667 CGF.
Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
4674 llvm::Function *TaskFunction,
4683 llvm::Value *NewTask =
Result.NewTask;
4684 llvm::Function *TaskEntry =
Result.TaskEntry;
4685 llvm::Value *NewTaskNewTaskTTy =
Result.NewTaskNewTaskTTy;
4690 llvm::Value *NumOfElements;
4691 std::tie(NumOfElements, DependenciesArray) =
4702 llvm::Value *TaskArgs[] = { UpLoc, ThreadID, NewTask };
4703 llvm::Value *DepTaskArgs[7];
4704 if (!
Data.Dependences.empty()) {
4705 DepTaskArgs[0] = UpLoc;
4706 DepTaskArgs[1] = ThreadID;
4707 DepTaskArgs[2] = NewTask;
4708 DepTaskArgs[3] = NumOfElements;
4710 DepTaskArgs[5] = CGF.
Builder.getInt32(0);
4711 DepTaskArgs[6] = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
4713 auto &&ThenCodeGen = [
this, &
Data, TDBase, KmpTaskTQTyRD, &TaskArgs,
4716 auto PartIdFI = std::next(KmpTaskTQTyRD->
field_begin(), KmpTaskTPartId);
4720 if (!
Data.Dependences.empty()) {
4723 CGM.getModule(), OMPRTL___kmpc_omp_task_with_deps),
4727 CGM.getModule(), OMPRTL___kmpc_omp_task),
4733 Region->emitUntiedSwitch(CGF);
4736 llvm::Value *DepWaitTaskArgs[7];
4737 if (!
Data.Dependences.empty()) {
4738 DepWaitTaskArgs[0] = UpLoc;
4739 DepWaitTaskArgs[1] = ThreadID;
4740 DepWaitTaskArgs[2] = NumOfElements;
4742 DepWaitTaskArgs[4] = CGF.
Builder.getInt32(0);
4743 DepWaitTaskArgs[5] = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
4744 DepWaitTaskArgs[6] =
4745 llvm::ConstantInt::get(CGF.
Int32Ty,
Data.HasNowaitClause);
4747 auto &M =
CGM.getModule();
4748 auto &&ElseCodeGen = [
this, &M, &TaskArgs, ThreadID, NewTaskNewTaskTTy,
4749 TaskEntry, &
Data, &DepWaitTaskArgs,
4756 if (!
Data.Dependences.empty())
4758 M, OMPRTL___kmpc_omp_taskwait_deps_51),
4761 auto &&
CodeGen = [TaskEntry, ThreadID, NewTaskNewTaskTTy,
4764 llvm::Value *OutlinedFnArgs[] = {ThreadID, NewTaskNewTaskTTy};
4765 CGF.CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, Loc, TaskEntry,
4774 CommonActionTy Action(
OMPBuilder.getOrCreateRuntimeFunction(
4775 M, OMPRTL___kmpc_omp_task_begin_if0),
4778 M, OMPRTL___kmpc_omp_task_complete_if0),
4794 llvm::Function *TaskFunction,
4814 IfVal = llvm::ConstantInt::getSigned(CGF.
IntTy, 1);
4819 *std::next(
Result.KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound));
4826 *std::next(
Result.KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound));
4833 *std::next(
Result.KmpTaskTQTyRD->field_begin(), KmpTaskTStride));
4841 *std::next(
Result.KmpTaskTQTyRD->field_begin(), KmpTaskTReductions));
4842 if (
Data.Reductions) {
4848 enum { NoSchedule = 0, Grainsize = 1, NumTasks = 2 };
4857 llvm::ConstantInt::getSigned(
4859 llvm::ConstantInt::getSigned(
4861 ?
Data.Schedule.getInt() ? NumTasks : Grainsize
4863 Data.Schedule.getPointer()
4866 : llvm::ConstantInt::get(CGF.
Int64Ty, 0)};
4867 if (
Data.HasModifier)
4868 TaskArgs.push_back(llvm::ConstantInt::get(CGF.
Int32Ty, 1));
4870 TaskArgs.push_back(
Result.TaskDupFn
4873 : llvm::ConstantPointerNull::get(CGF.
VoidPtrTy));
4875 CGM.getModule(),
Data.HasModifier
4876 ? OMPRTL___kmpc_taskloop_5
4877 : OMPRTL___kmpc_taskloop),
4894 const Expr *,
const Expr *)> &RedOpGen,
4895 const Expr *XExpr =
nullptr,
const Expr *EExpr =
nullptr,
4896 const Expr *UpExpr =
nullptr) {
4904 llvm::Value *NumElements = CGF.
emitArrayLength(ArrayTy, ElementTy, LHSAddr);
4909 llvm::Value *LHSEnd =
4914 llvm::Value *IsEmpty =
4915 CGF.
Builder.CreateICmpEQ(LHSBegin, LHSEnd,
"omp.arraycpy.isempty");
4916 CGF.
Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
4919 llvm::BasicBlock *EntryBB = CGF.
Builder.GetInsertBlock();
4924 llvm::PHINode *RHSElementPHI = CGF.
Builder.CreatePHI(
4925 RHSBegin->getType(), 2,
"omp.arraycpy.srcElementPast");
4926 RHSElementPHI->addIncoming(RHSBegin, EntryBB);
4931 llvm::PHINode *LHSElementPHI = CGF.
Builder.CreatePHI(
4932 LHSBegin->getType(), 2,
"omp.arraycpy.destElementPast");
4933 LHSElementPHI->addIncoming(LHSBegin, EntryBB);
4940 Scope.addPrivate(LHSVar, LHSElementCurrent);
4941 Scope.addPrivate(RHSVar, RHSElementCurrent);
4943 RedOpGen(CGF, XExpr, EExpr, UpExpr);
4944 Scope.ForceCleanup();
4947 llvm::Value *LHSElementNext = CGF.
Builder.CreateConstGEP1_32(
4949 "omp.arraycpy.dest.element");
4950 llvm::Value *RHSElementNext = CGF.
Builder.CreateConstGEP1_32(
4952 "omp.arraycpy.src.element");
4955 CGF.
Builder.CreateICmpEQ(LHSElementNext, LHSEnd,
"omp.arraycpy.done");
4956 CGF.
Builder.CreateCondBr(Done, DoneBB, BodyBB);
4957 LHSElementPHI->addIncoming(LHSElementNext, CGF.
Builder.GetInsertBlock());
4958 RHSElementPHI->addIncoming(RHSElementNext, CGF.
Builder.GetInsertBlock());
4968 const Expr *ReductionOp) {
4969 if (
const auto *CE = dyn_cast<CallExpr>(ReductionOp))
4970 if (
const auto *OVE = dyn_cast<OpaqueValueExpr>(CE->getCallee()))
4971 if (
const auto *DRE =
4972 dyn_cast<DeclRefExpr>(OVE->getSourceExpr()->IgnoreImpCasts()))
4973 if (
const auto *DRD =
4974 dyn_cast<OMPDeclareReductionDecl>(DRE->getDecl())) {
4975 std::pair<llvm::Function *, llvm::Function *>
Reduction =
4986 StringRef ReducerName,
SourceLocation Loc, llvm::Type *ArgsElemType,
5000 CGM.getTypes().arrangeBuiltinFunctionDeclaration(
C.VoidTy, Args);
5002 auto *Fn = llvm::Function::Create(
CGM.getTypes().GetFunctionType(CGFI),
5003 llvm::GlobalValue::InternalLinkage, Name,
5006 if (!
CGM.getCodeGenOpts().SampleProfileFile.empty())
5007 Fn->addFnAttr(
"sample-profile-suffix-elision-policy",
"selected");
5008 Fn->setDoesNotRecurse();
5027 const auto *IPriv =
Privates.begin();
5029 for (
unsigned I = 0, E = ReductionOps.size(); I < E; ++I, ++IPriv, ++Idx) {
5030 const auto *RHSVar =
5033 const auto *LHSVar =
5036 QualType PrivTy = (*IPriv)->getType();
5052 const auto *ILHS = LHSExprs.begin();
5053 const auto *IRHS = RHSExprs.begin();
5054 for (
const Expr *E : ReductionOps) {
5055 if ((*IPriv)->getType()->isArrayType()) {
5060 CGF, (*IPriv)->getType(), LHSVar, RHSVar,
5062 emitReductionCombiner(CGF, E);
5072 Scope.ForceCleanup();
5078 const Expr *ReductionOp,
5079 const Expr *PrivateRef,
5087 CGF, PrivateRef->
getType(), LHSVar, RHSVar,
5089 emitReductionCombiner(CGF, ReductionOp);
5098 llvm::StringRef Prefix,
const Expr *Ref);
5102 const Expr *LHSExprs,
const Expr *RHSExprs,
const Expr *ReductionOps) {
5129 std::string ReductionVarNameStr;
5130 if (
const auto *DRE = dyn_cast<DeclRefExpr>(
Privates->IgnoreParenCasts()))
5131 ReductionVarNameStr =
5134 ReductionVarNameStr =
"unnamed_priv_var";
5137 std::string SharedName =
5138 CGM.getOpenMPRuntime().getName({
"internal_pivate_", ReductionVarNameStr});
5139 llvm::GlobalVariable *SharedVar =
OMPBuilder.getOrCreateInternalVariable(
5140 LLVMType,
".omp.reduction." + SharedName);
5142 SharedVar->setAlignment(
5150 llvm::Value *BarrierArgs[] = {BarrierLoc, ThreadId};
5155 llvm::Value *IsWorker = CGF.
Builder.CreateICmpEQ(
5156 ThreadId, llvm::ConstantInt::get(ThreadId->getType(), 0));
5157 CGF.
Builder.CreateCondBr(IsWorker, InitBB, InitEndBB);
5161 auto EmitSharedInit = [&]() {
5164 std::pair<llvm::Function *, llvm::Function *> FnPair =
5166 llvm::Function *InitializerFn = FnPair.second;
5167 if (InitializerFn) {
5168 if (
const auto *CE =
5169 dyn_cast<CallExpr>(UDRInitExpr->IgnoreParenImpCasts())) {
5176 LocalScope.addPrivate(OutVD, SharedResult);
5178 (void)LocalScope.Privatize();
5179 if (
const auto *OVE = dyn_cast<OpaqueValueExpr>(
5180 CE->getCallee()->IgnoreParenImpCasts())) {
5206 if (
const auto *DRE = dyn_cast<DeclRefExpr>(
Privates)) {
5207 if (
const auto *VD = dyn_cast<VarDecl>(DRE->getDecl())) {
5218 CGF.
Builder.CreateBr(InitEndBB);
5222 CGM.getModule(), OMPRTL___kmpc_barrier),
5225 const Expr *ReductionOp = ReductionOps;
5230 auto EmitCriticalReduction = [&](
auto ReductionGen) {
5231 std::string CriticalName =
getName({
"reduction_critical"});
5239 std::pair<llvm::Function *, llvm::Function *> FnPair =
5242 if (
const auto *CE = dyn_cast<CallExpr>(ReductionOp)) {
5254 (void)LocalScope.Privatize();
5259 EmitCriticalReduction(ReductionGen);
5264 if (
const auto *Cleanup = dyn_cast<ExprWithCleanups>(ReductionClauseExpr))
5267 const Expr *AssignRHS =
nullptr;
5268 if (
const auto *BinOp = dyn_cast<BinaryOperator>(ReductionClauseExpr)) {
5269 if (BinOp->getOpcode() == BO_Assign)
5270 AssignRHS = BinOp->getRHS();
5271 }
else if (
const auto *OpCall =
5272 dyn_cast<CXXOperatorCallExpr>(ReductionClauseExpr)) {
5273 if (OpCall->getOperator() == OO_Equal)
5274 AssignRHS = OpCall->getArg(1);
5278 "Private Variable Reduction : Invalid ReductionOp expression");
5283 const auto *OmpOutDRE =
5285 const auto *OmpInDRE =
5288 OmpOutDRE && OmpInDRE &&
5289 "Private Variable Reduction : LHSExpr/RHSExpr must be DeclRefExprs");
5293 LocalScope.addPrivate(OmpOutVD, SharedLV.
getAddress());
5294 LocalScope.addPrivate(OmpInVD, LHSLV.
getAddress());
5295 (void)LocalScope.Privatize();
5299 EmitCriticalReduction(ReductionGen);
5303 CGM.getModule(), OMPRTL___kmpc_barrier),
5309 llvm::Value *FinalResultVal =
nullptr;
5313 FinalResultAddr = SharedResult;
5327 CGM.getModule(), OMPRTL___kmpc_barrier),
5338 EmitCriticalReduction(OriginalListCombiner);
5390 if (SimpleReduction) {
5392 const auto *IPriv = OrgPrivates.begin();
5393 const auto *ILHS = OrgLHSExprs.begin();
5394 const auto *IRHS = OrgRHSExprs.begin();
5395 for (
const Expr *E : OrgReductionOps) {
5408 FilteredRHSExprs, FilteredReductionOps;
5409 for (
unsigned I : llvm::seq<unsigned>(
5410 std::min(OrgReductionOps.size(), OrgLHSExprs.size()))) {
5412 FilteredPrivates.emplace_back(OrgPrivates[I]);
5413 FilteredLHSExprs.emplace_back(OrgLHSExprs[I]);
5414 FilteredRHSExprs.emplace_back(OrgRHSExprs[I]);
5415 FilteredReductionOps.emplace_back(OrgReductionOps[I]);
5427 auto Size = RHSExprs.size();
5433 llvm::APInt ArraySize(32, Size);
5434 QualType ReductionArrayTy =
C.getConstantArrayType(
5438 CGF.
CreateMemTemp(ReductionArrayTy,
".omp.reduction.red_list");
5439 const auto *IPriv =
Privates.begin();
5441 for (
unsigned I = 0, E = RHSExprs.size(); I < E; ++I, ++IPriv, ++Idx) {
5447 if ((*IPriv)->getType()->isVariablyModifiedType()) {
5451 llvm::Value *Size = CGF.
Builder.CreateIntCast(
5464 Privates, LHSExprs, RHSExprs, ReductionOps);
5467 std::string Name =
getName({
"reduction"});
5474 llvm::Value *ReductionArrayTySize = CGF.
getTypeSize(ReductionArrayTy);
5477 llvm::Value *Args[] = {
5480 CGF.
Builder.getInt32(RHSExprs.size()),
5481 ReductionArrayTySize,
5489 WithNowait ? OMPRTL___kmpc_reduce_nowait : OMPRTL___kmpc_reduce),
5493 llvm::BasicBlock *DefaultBB = CGF.
createBasicBlock(
".omp.reduction.default");
5494 llvm::SwitchInst *SwInst =
5495 CGF.
Builder.CreateSwitch(Res, DefaultBB, 2);
5504 SwInst->addCase(CGF.
Builder.getInt32(1), Case1BB);
5508 llvm::Value *EndArgs[] = {
5516 const auto *IPriv =
Privates.begin();
5517 const auto *ILHS = LHSExprs.begin();
5518 const auto *IRHS = RHSExprs.begin();
5519 for (
const Expr *E : ReductionOps) {
5528 CommonActionTy Action(
5531 CGM.getModule(), WithNowait ? OMPRTL___kmpc_end_reduce_nowait
5532 : OMPRTL___kmpc_end_reduce),
5545 SwInst->addCase(CGF.
Builder.getInt32(2), Case2BB);
5548 auto &&AtomicCodeGen = [Loc,
Privates, LHSExprs, RHSExprs, ReductionOps](
5550 const auto *ILHS = LHSExprs.begin();
5551 const auto *IRHS = RHSExprs.begin();
5552 const auto *IPriv =
Privates.begin();
5553 for (
const Expr *E : ReductionOps) {
5554 const Expr *XExpr =
nullptr;
5555 const Expr *EExpr =
nullptr;
5556 const Expr *UpExpr =
nullptr;
5558 if (
const auto *BO = dyn_cast<BinaryOperator>(E)) {
5559 if (BO->getOpcode() == BO_Assign) {
5560 XExpr = BO->getLHS();
5561 UpExpr = BO->getRHS();
5565 const Expr *RHSExpr = UpExpr;
5568 if (
const auto *ACO = dyn_cast<AbstractConditionalOperator>(
5572 RHSExpr = ACO->getCond();
5574 if (
const auto *BORHS =
5576 EExpr = BORHS->getRHS();
5577 BO = BORHS->getOpcode();
5582 auto &&AtomicRedGen = [BO, VD,
5584 const Expr *EExpr,
const Expr *UpExpr) {
5585 LValue X = CGF.EmitLValue(XExpr);
5588 E = CGF.EmitAnyExpr(EExpr);
5589 CGF.EmitOMPAtomicSimpleUpdateExpr(
5591 llvm::AtomicOrdering::Monotonic, Loc,
5592 [&CGF, UpExpr, VD, Loc](
RValue XRValue) {
5594 Address LHSTemp = CGF.CreateMemTemp(VD->getType());
5595 CGF.emitOMPSimpleStore(
5596 CGF.MakeAddrLValue(LHSTemp, VD->
getType()), XRValue,
5597 VD->getType().getNonReferenceType(), Loc);
5600 return CGF.EmitAnyExpr(UpExpr);
5603 if ((*IPriv)->getType()->isArrayType()) {
5605 const auto *RHSVar =
5608 AtomicRedGen, XExpr, EExpr, UpExpr);
5611 AtomicRedGen(CGF, XExpr, EExpr, UpExpr);
5618 std::string Name = RT.
getName({
"atomic_reduction"});
5627 if ((*IPriv)->getType()->isArrayType()) {
5628 const auto *LHSVar =
5630 const auto *RHSVar =
5635 CritRedGen(CGF,
nullptr,
nullptr,
nullptr);
5646 llvm::Value *EndArgs[] = {
5651 CommonActionTy Action(
nullptr, {},
5653 CGM.getModule(), OMPRTL___kmpc_end_reduce),
5663 assert(OrgLHSExprs.size() == OrgPrivates.size() &&
5664 "PrivateVarReduction: Privates size mismatch");
5665 assert(OrgLHSExprs.size() == OrgReductionOps.size() &&
5666 "PrivateVarReduction: ReductionOps size mismatch");
5667 for (
unsigned I : llvm::seq<unsigned>(
5668 std::min(OrgReductionOps.size(), OrgLHSExprs.size()))) {
5671 OrgRHSExprs[I], OrgReductionOps[I]);
5680 llvm::raw_svector_ostream Out(Buffer);
5688 Out << Prefix << Name <<
"_"
5690 return std::string(Out.str());
5714 Args.emplace_back(Param);
5715 Args.emplace_back(ParamOrig);
5716 const auto &FnInfo =
5720 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
5724 Fn->addFnAttr(
"sample-profile-suffix-elision-policy",
"selected");
5725 Fn->setDoesNotRecurse();
5732 llvm::Value *Size =
nullptr;
5775 const Expr *ReductionOp,
5777 const Expr *PrivateRef) {
5788 Args.emplace_back(ParamInOut);
5789 Args.emplace_back(ParamIn);
5790 const auto &FnInfo =
5794 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
5798 Fn->addFnAttr(
"sample-profile-suffix-elision-policy",
"selected");
5799 Fn->setDoesNotRecurse();
5802 llvm::Value *Size =
nullptr;
5823 C.getPointerType(LHSVD->getType())->castAs<
PointerType>()));
5830 C.getPointerType(RHSVD->getType())->castAs<
PointerType>()));
5860 Args.emplace_back(Param);
5861 const auto &FnInfo =
5865 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
5869 Fn->addFnAttr(
"sample-profile-suffix-elision-policy",
"selected");
5870 Fn->setDoesNotRecurse();
5875 llvm::Value *Size =
nullptr;
5910 RecordDecl *RD =
C.buildImplicitRecord(
"kmp_taskred_input_t");
5919 C, RD,
C.getIntTypeForBitwidth(32,
false));
5922 unsigned Size =
Data.ReductionVars.size();
5923 llvm::APInt ArraySize(64, Size);
5925 C.getConstantArrayType(RDType, ArraySize,
nullptr,
5930 Data.ReductionCopies,
Data.ReductionOps);
5931 for (
unsigned Cnt = 0; Cnt < Size; ++Cnt) {
5933 llvm::Value *Idxs[] = {llvm::ConstantInt::get(
CGM.SizeTy, 0),
5934 llvm::ConstantInt::get(
CGM.SizeTy, Cnt)};
5950 llvm::Value *SizeValInChars;
5951 llvm::Value *SizeVal;
5952 std::tie(SizeValInChars, SizeVal) = RCG.
getSizes(Cnt);
5958 bool DelayedCreation = !!SizeVal;
5959 SizeValInChars = CGF.
Builder.CreateIntCast(SizeValInChars,
CGM.SizeTy,
5970 llvm::Value *FiniAddr =
5971 Fini ? Fini : llvm::ConstantPointerNull::get(
CGM.VoidPtrTy);
5976 CGM, Loc, RCG, Cnt,
Data.ReductionOps[Cnt], LHSExprs[Cnt],
5977 RHSExprs[Cnt],
Data.ReductionCopies[Cnt]);
5981 if (DelayedCreation) {
5983 llvm::ConstantInt::get(
CGM.Int32Ty, 1,
true),
5988 if (
Data.IsReductionWithTaskMod) {
5994 llvm::Value *Args[] = {
5996 llvm::ConstantInt::get(
CGM.IntTy,
Data.IsWorksharingReduction ? 1 : 0,
5998 llvm::ConstantInt::get(
CGM.IntTy, Size,
true),
6003 CGM.getModule(), OMPRTL___kmpc_taskred_modifier_init),
6007 llvm::Value *Args[] = {
6010 llvm::ConstantInt::get(
CGM.IntTy, Size,
true),
6014 CGM.getModule(), OMPRTL___kmpc_taskred_init),
6020 bool IsWorksharingReduction) {
6026 llvm::Value *Args[] = {IdentTLoc, GTid,
6027 llvm::ConstantInt::get(
CGM.IntTy,
6028 IsWorksharingReduction ? 1 : 0,
6032 CGM.getModule(), OMPRTL___kmpc_task_reduction_modifier_fini),
6044 llvm::Value *SizeVal = CGF.
Builder.CreateIntCast(Sizes.second,
CGM.SizeTy,
6047 CGF,
CGM.getContext().getSizeType(),
6055 llvm::Value *ReductionsPtr,
6068 CGM.getModule(), OMPRTL___kmpc_task_reduction_get_th_data),
6084 auto &M =
CGM.getModule();
6086 llvm::Value *NumOfElements;
6087 std::tie(NumOfElements, DependenciesArray) =
6089 if (!
Data.Dependences.empty()) {
6090 llvm::Value *DepWaitTaskArgs[7];
6091 DepWaitTaskArgs[0] = UpLoc;
6092 DepWaitTaskArgs[1] = ThreadID;
6093 DepWaitTaskArgs[2] = NumOfElements;
6095 DepWaitTaskArgs[4] = CGF.
Builder.getInt32(0);
6096 DepWaitTaskArgs[5] = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
6097 DepWaitTaskArgs[6] =
6098 llvm::ConstantInt::get(CGF.
Int32Ty,
Data.HasNowaitClause);
6107 M, OMPRTL___kmpc_omp_taskwait_deps_51),
6114 llvm::Value *Args[] = {UpLoc, ThreadID};
6117 OMPBuilder.getOrCreateRuntimeFunction(M, OMPRTL___kmpc_omp_taskwait),
6122 if (
auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.
CapturedStmtInfo))
6123 Region->emitUntiedSwitch(CGF);
6132 InlinedOpenMPRegionRAII Region(CGF,
CodeGen, InnerKind, HasCancel,
6133 InnerKind != OMPD_critical &&
6134 InnerKind != OMPD_master &&
6135 InnerKind != OMPD_masked);
6150 RTCancelKind CancelKind = CancelNoreq;
6151 if (CancelRegion == OMPD_parallel)
6152 CancelKind = CancelParallel;
6153 else if (CancelRegion == OMPD_for)
6154 CancelKind = CancelLoop;
6155 else if (CancelRegion == OMPD_sections)
6156 CancelKind = CancelSections;
6158 assert(CancelRegion == OMPD_taskgroup);
6159 CancelKind = CancelTaskgroup;
6171 if (
auto *OMPRegionInfo =
6175 if (CancelRegion == OMPD_taskgroup || OMPRegionInfo->hasCancel()) {
6176 llvm::Value *Args[] = {
6182 CGM.getModule(), OMPRTL___kmpc_cancellationpoint),
6191 CGF.
Builder.CreateCondBr(
Cmp, ExitBB, ContBB);
6193 if (CancelRegion == OMPD_parallel)
6211 auto &M =
CGM.getModule();
6212 if (
auto *OMPRegionInfo =
6214 auto &&ThenGen = [
this, &M, Loc, CancelRegion,
6217 llvm::Value *Args[] = {
6221 llvm::Value *
Result = CGF.EmitRuntimeCall(
6222 OMPBuilder.getOrCreateRuntimeFunction(M, OMPRTL___kmpc_cancel), Args);
6227 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(
".cancel.exit");
6228 llvm::BasicBlock *ContBB = CGF.createBasicBlock(
".cancel.continue");
6229 llvm::Value *
Cmp = CGF.Builder.CreateIsNotNull(
Result);
6230 CGF.Builder.CreateCondBr(
Cmp, ExitBB, ContBB);
6231 CGF.EmitBlock(ExitBB);
6232 if (CancelRegion == OMPD_parallel)
6236 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind());
6237 CGF.EmitBranchThroughCleanup(CancelDest);
6238 CGF.EmitBlock(ContBB,
true);
6256 OMPUsesAllocatorsActionTy(
6257 ArrayRef<std::pair<const Expr *, const Expr *>> Allocators)
6258 : Allocators(Allocators) {}
6262 for (
const auto &AllocatorData : Allocators) {
6264 CGF, AllocatorData.first, AllocatorData.second);
6267 void Exit(CodeGenFunction &CGF)
override {
6270 for (
const auto &AllocatorData : Allocators) {
6272 AllocatorData.first);
6280 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
6282 assert(!ParentName.empty() &&
"Invalid target entry parent name!");
6286 for (
unsigned I = 0, E =
C->getNumberOfAllocators(); I < E; ++I) {
6293 OMPUsesAllocatorsActionTy UsesAllocatorAction(Allocators);
6294 CodeGen.setAction(UsesAllocatorAction);
6300 const Expr *Allocator,
6301 const Expr *AllocatorTraits) {
6303 ThreadId = CGF.
Builder.CreateIntCast(ThreadId, CGF.
IntTy,
true);
6305 llvm::Value *MemSpaceHandle = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
6306 llvm::Value *NumTraits = llvm::ConstantInt::get(
6310 .getLimitedValue());
6317 llvm::Value *Traits =
Addr.emitRawPointer(CGF);
6319 llvm::Value *AllocatorVal =
6321 CGM.getModule(), OMPRTL___kmpc_init_allocator),
6322 {ThreadId, MemSpaceHandle, NumTraits, Traits});
6334 const Expr *Allocator) {
6336 ThreadId = CGF.
Builder.CreateIntCast(ThreadId, CGF.
IntTy,
true);
6338 llvm::Value *AllocatorVal =
6345 OMPRTL___kmpc_destroy_allocator),
6346 {ThreadId, AllocatorVal});
6351 llvm::OpenMPIRBuilder::TargetKernelDefaultAttrs &Attrs) {
6352 assert(Attrs.MaxTeams.size() == 1 && Attrs.MaxThreads.size() == 1 &&
6353 "invalid default attrs structure");
6354 int32_t &MaxTeamsVal = Attrs.MaxTeams.front();
6355 int32_t &MaxThreadsVal = Attrs.MaxThreads.front();
6363 for (
auto *A :
C->getAttrs()) {
6364 int32_t AttrMinThreadsVal = 1, AttrMaxThreadsVal = -1;
6365 int32_t AttrMinBlocksVal = 1, AttrMaxBlocksVal = -1;
6366 if (
auto *
Attr = dyn_cast<CUDALaunchBoundsAttr>(A))
6367 CGM.handleCUDALaunchBoundsAttr(
nullptr,
Attr, &AttrMaxThreadsVal,
6368 &AttrMinBlocksVal, &AttrMaxBlocksVal);
6369 else if (
auto *
Attr = dyn_cast<AMDGPUFlatWorkGroupSizeAttr>(A))
6370 CGM.handleAMDGPUFlatWorkGroupSizeAttr(
6371 nullptr,
Attr,
nullptr, &AttrMinThreadsVal,
6372 &AttrMaxThreadsVal);
6376 Attrs.MinThreads.front() =
6377 std::max(Attrs.MinThreads.front(), AttrMinThreadsVal);
6378 if (AttrMaxThreadsVal > 0)
6379 MaxThreadsVal = MaxThreadsVal > 0
6380 ? std::min(MaxThreadsVal, AttrMaxThreadsVal)
6381 : AttrMaxThreadsVal;
6382 Attrs.MinTeams.front() =
6383 std::max(Attrs.MinTeams.front(), AttrMinBlocksVal);
6384 if (AttrMaxBlocksVal > 0)
6385 MaxTeamsVal = MaxTeamsVal > 0 ? std::min(MaxTeamsVal, AttrMaxBlocksVal)
6393 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
6396 llvm::TargetRegionEntryInfo EntryInfo =
6400 llvm::OpenMPIRBuilder::FunctionGenCallback &&GenerateOutlinedFunction =
6401 [&CGF, &D, &
CodeGen,
this](StringRef EntryFnName) {
6402 const CapturedStmt &CS = *D.getCapturedStmt(OMPD_target);
6404 CGOpenMPTargetRegionInfo CGInfo(CS,
CodeGen, EntryFnName);
6406 if (
CGM.getLangOpts().OpenMPIsTargetDevice && !
isGPU())
6411 cantFail(
OMPBuilder.emitTargetRegionFunction(
6412 EntryInfo, GenerateOutlinedFunction, IsOffloadEntry, OutlinedFn,
6418 CGM.getTargetCodeGenInfo().setTargetAttributes(
nullptr, OutlinedFn,
CGM);
6421 for (
auto *A :
C->getAttrs()) {
6422 if (
auto *
Attr = dyn_cast<AMDGPUWavesPerEUAttr>(A))
6423 CGM.handleAMDGPUWavesPerEUAttr(OutlinedFn,
Attr);
6442 while (
const auto *
C = dyn_cast_or_null<CompoundStmt>(Child)) {
6444 for (
const Stmt *S :
C->body()) {
6445 if (
const auto *E = dyn_cast<Expr>(S)) {
6454 if (
const auto *DS = dyn_cast<DeclStmt>(S)) {
6455 if (llvm::all_of(DS->decls(), [](
const Decl *D) {
6456 if (isa<EmptyDecl>(D) || isa<DeclContext>(D) ||
6457 isa<TypeDecl>(D) || isa<PragmaCommentDecl>(D) ||
6458 isa<PragmaDetectMismatchDecl>(D) || isa<UsingDecl>(D) ||
6459 isa<UsingDirectiveDecl>(D) ||
6460 isa<OMPDeclareReductionDecl>(D) ||
6461 isa<OMPThreadPrivateDecl>(D) || isa<OMPAllocateDecl>(D))
6463 const auto *VD = dyn_cast<VarDecl>(D);
6466 return VD->hasGlobalStorage() || !VD->isUsed();
6476 Child = Child->IgnoreContainers();
6483 int32_t &MaxTeamsVal) {
6487 "Expected target-based executable directive.");
6488 switch (DirectiveKind) {
6490 const auto *CS = D.getInnermostCapturedStmt();
6493 const Stmt *ChildStmt =
6495 if (
const auto *NestedDir =
6496 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) {
6505 MinTeamsVal = MaxTeamsVal =
Constant->getExtValue();
6508 MinTeamsVal = MaxTeamsVal = 0;
6511 MinTeamsVal = MaxTeamsVal = 1;
6515 MinTeamsVal = MaxTeamsVal = -1;
6518 case OMPD_target_teams_loop:
6519 case OMPD_target_teams:
6520 case OMPD_target_teams_distribute:
6521 case OMPD_target_teams_distribute_simd:
6522 case OMPD_target_teams_distribute_parallel_for:
6523 case OMPD_target_teams_distribute_parallel_for_simd: {
6525 const Expr *NumTeams =
6529 MinTeamsVal = MaxTeamsVal =
Constant->getExtValue();
6532 MinTeamsVal = MaxTeamsVal = 0;
6535 case OMPD_target_parallel:
6536 case OMPD_target_parallel_for:
6537 case OMPD_target_parallel_for_simd:
6538 case OMPD_target_parallel_loop:
6539 case OMPD_target_simd:
6540 MinTeamsVal = MaxTeamsVal = 1;
6544 case OMPD_parallel_for:
6545 case OMPD_parallel_loop:
6546 case OMPD_parallel_master:
6547 case OMPD_parallel_sections:
6549 case OMPD_parallel_for_simd:
6551 case OMPD_cancellation_point:
6552 case OMPD_ordered_standalone:
6553 case OMPD_ordered_blockassoc:
6554 case OMPD_threadprivate:
6565 case OMPD_taskyield:
6568 case OMPD_taskgroup:
6574 case OMPD_target_data:
6575 case OMPD_target_exit_data:
6576 case OMPD_target_enter_data:
6577 case OMPD_distribute:
6578 case OMPD_distribute_simd:
6579 case OMPD_distribute_parallel_for:
6580 case OMPD_distribute_parallel_for_simd:
6581 case OMPD_teams_distribute:
6582 case OMPD_teams_distribute_simd:
6583 case OMPD_teams_distribute_parallel_for:
6584 case OMPD_teams_distribute_parallel_for_simd:
6585 case OMPD_target_update:
6586 case OMPD_declare_simd:
6587 case OMPD_declare_variant:
6588 case OMPD_begin_declare_variant:
6589 case OMPD_end_declare_variant:
6590 case OMPD_declare_target:
6591 case OMPD_end_declare_target:
6592 case OMPD_declare_reduction:
6593 case OMPD_declare_mapper:
6595 case OMPD_taskloop_simd:
6596 case OMPD_master_taskloop:
6597 case OMPD_master_taskloop_simd:
6598 case OMPD_parallel_master_taskloop:
6599 case OMPD_parallel_master_taskloop_simd:
6601 case OMPD_metadirective:
6607 llvm_unreachable(
"Unexpected directive kind.");
6613 "Clauses associated with the teams directive expected to be emitted "
6614 "only for the host!");
6616 int32_t MinNT = -1, MaxNT = -1;
6617 const Expr *NumTeams =
6619 if (NumTeams !=
nullptr) {
6622 switch (DirectiveKind) {
6624 const auto *CS = D.getInnermostCapturedStmt();
6625 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6629 return Bld.CreateIntCast(NumTeamsVal, CGF.
Int32Ty,
6632 case OMPD_target_teams:
6633 case OMPD_target_teams_distribute:
6634 case OMPD_target_teams_distribute_simd:
6635 case OMPD_target_teams_distribute_parallel_for:
6636 case OMPD_target_teams_distribute_parallel_for_simd: {
6640 return Bld.CreateIntCast(NumTeamsVal, CGF.
Int32Ty,
6648 assert(MinNT == MaxNT &&
"Num threads ranges require handling here.");
6649 return llvm::ConstantInt::getSigned(CGF.
Int32Ty, MinNT);
6658 bool UpperBoundOnly, llvm::Value **CondVal) {
6661 const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child);
6668 if (CondVal && Dir->hasClausesOfKind<
OMPIfClause>()) {
6669 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6672 for (
const auto *
C : Dir->getClausesOfKind<
OMPIfClause>()) {
6673 if (
C->getNameModifier() == OMPD_unknown ||
6674 C->getNameModifier() == OMPD_parallel) {
6689 if (
const auto *PreInit =
6691 for (
const auto *I : PreInit->decls()) {
6692 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
6708 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6710 const auto *NumThreadsClause =
6712 const Expr *NTExpr = NumThreadsClause->getNumThreads().front();
6713 if (NTExpr->isIntegerConstantExpr(CGF.
getContext()))
6718 : std::min(UpperBound,
6722 if (UpperBound == -1)
6727 if (
const auto *PreInit =
6728 cast_or_null<DeclStmt>(NumThreadsClause->getPreInitStmt())) {
6729 for (
const auto *I : PreInit->decls()) {
6730 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
6749 bool UpperBoundOnly, llvm::Value **CondVal,
const Expr **ThreadLimitExpr) {
6750 assert((!CGF.
getLangOpts().OpenMPIsTargetDevice || UpperBoundOnly) &&
6751 "Clauses associated with the teams directive expected to be emitted "
6752 "only for the host!");
6755 "Expected target-based executable directive.");
6757 const Expr *NT =
nullptr;
6758 const Expr **NTPtr = UpperBoundOnly ?
nullptr : &NT;
6760 auto CheckForConstExpr = [&](
const Expr *E,
const Expr **EPtr) {
6763 UpperBound = UpperBound ?
Constant->getZExtValue()
6764 : std::min(UpperBound,
6769 if (UpperBound == -1)
6775 auto ReturnSequential = [&]() {
6780 switch (DirectiveKind) {
6783 getNumThreads(CGF, CS, NTPtr, UpperBound, UpperBoundOnly, CondVal);
6789 if (
const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) {
6791 ThreadLimitClause = TLC;
6792 if (ThreadLimitExpr) {
6793 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6797 ThreadLimitClause->getThreadLimit().front()->getSourceRange());
6798 if (
const auto *PreInit =
6799 cast_or_null<DeclStmt>(ThreadLimitClause->getPreInitStmt())) {
6800 for (
const auto *I : PreInit->decls()) {
6801 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
6813 if (ThreadLimitClause)
6814 CheckForConstExpr(ThreadLimitClause->getThreadLimit().front(),
6816 if (
const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) {
6819 CS = Dir->getInnermostCapturedStmt();
6822 Dir = dyn_cast_or_null<OMPExecutableDirective>(Child);
6825 CS = Dir->getInnermostCapturedStmt();
6826 getNumThreads(CGF, CS, NTPtr, UpperBound, UpperBoundOnly, CondVal);
6828 return ReturnSequential();
6832 case OMPD_target_teams: {
6836 CheckForConstExpr(ThreadLimitClause->getThreadLimit().front(),
6840 getNumThreads(CGF, CS, NTPtr, UpperBound, UpperBoundOnly, CondVal);
6843 if (
const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) {
6844 if (Dir->getDirectiveKind() == OMPD_distribute) {
6845 CS = Dir->getInnermostCapturedStmt();
6846 getNumThreads(CGF, CS, NTPtr, UpperBound, UpperBoundOnly, CondVal);
6851 case OMPD_target_teams_distribute:
6855 CheckForConstExpr(ThreadLimitClause->getThreadLimit().front(),
6858 getNumThreads(CGF, D.getInnermostCapturedStmt(), NTPtr, UpperBound,
6859 UpperBoundOnly, CondVal);
6861 case OMPD_target_teams_loop:
6862 case OMPD_target_parallel_loop:
6863 case OMPD_target_parallel:
6864 case OMPD_target_parallel_for:
6865 case OMPD_target_parallel_for_simd:
6866 case OMPD_target_teams_distribute_parallel_for:
6867 case OMPD_target_teams_distribute_parallel_for_simd: {
6868 if (CondVal && D.hasClausesOfKind<
OMPIfClause>()) {
6870 for (
const auto *
C : D.getClausesOfKind<
OMPIfClause>()) {
6871 if (
C->getNameModifier() == OMPD_unknown ||
6872 C->getNameModifier() == OMPD_parallel) {
6882 return ReturnSequential();
6892 CheckForConstExpr(ThreadLimitClause->getThreadLimit().front(),
6898 CheckForConstExpr(NumThreadsClause->getNumThreads().front(),
nullptr);
6899 return NumThreadsClause->getNumThreads().front();
6903 case OMPD_target_teams_distribute_simd:
6904 case OMPD_target_simd:
6905 return ReturnSequential();
6909 llvm_unreachable(
"Unsupported directive kind.");
6914 llvm::Value *NumThreadsVal =
nullptr;
6915 llvm::Value *CondVal =
nullptr;
6916 llvm::Value *ThreadLimitVal =
nullptr;
6917 const Expr *ThreadLimitExpr =
nullptr;
6918 int32_t UpperBound = -1;
6921 CGF, D, UpperBound,
false, &CondVal,
6925 if (ThreadLimitExpr) {
6928 ThreadLimitVal = CGF.
Builder.CreateIntCast(ThreadLimitVal, CGF.
Int32Ty,
6933 if (UpperBound == 1) {
6934 NumThreadsVal = CGF.
Builder.getInt32(UpperBound);
6937 NumThreadsVal = CGF.
Builder.CreateIntCast(NumThreadsVal, CGF.
Int32Ty,
6939 }
else if (ThreadLimitVal) {
6942 NumThreadsVal = ThreadLimitVal;
6943 ThreadLimitVal =
nullptr;
6946 assert(!ThreadLimitVal &&
"Default not applicable with thread limit value");
6947 NumThreadsVal = CGF.
Builder.getInt32(0);
6954 NumThreadsVal = CGF.
Builder.CreateSelect(CondVal, NumThreadsVal,
6960 if (ThreadLimitVal) {
6961 NumThreadsVal = CGF.
Builder.CreateSelect(
6962 CGF.
Builder.CreateICmpULT(ThreadLimitVal, NumThreadsVal),
6963 ThreadLimitVal, NumThreadsVal);
6966 return NumThreadsVal;
6976class MappableExprsHandler {
6982 struct AttachPtrExprComparator {
6983 const MappableExprsHandler &Handler;
6985 mutable llvm::DenseMap<std::pair<const Expr *, const Expr *>,
bool>
6986 CachedEqualityComparisons;
6988 AttachPtrExprComparator(
const MappableExprsHandler &H) : Handler(H) {}
6989 AttachPtrExprComparator() =
delete;
6992 bool operator()(
const Expr *LHS,
const Expr *RHS)
const {
6997 const auto ItLHS = Handler.AttachPtrComponentDepthMap.find(LHS);
6998 const auto ItRHS = Handler.AttachPtrComponentDepthMap.find(RHS);
7000 std::optional<size_t> DepthLHS =
7001 (ItLHS != Handler.AttachPtrComponentDepthMap.end()) ? ItLHS->second
7003 std::optional<size_t> DepthRHS =
7004 (ItRHS != Handler.AttachPtrComponentDepthMap.end()) ? ItRHS->second
7008 if (!DepthLHS.has_value() && !DepthRHS.has_value()) {
7010 if (areEqual(LHS, RHS))
7013 return wasComputedBefore(LHS, RHS);
7015 if (!DepthLHS.has_value())
7017 if (!DepthRHS.has_value())
7021 if (DepthLHS.value() != DepthRHS.value())
7022 return DepthLHS.value() < DepthRHS.value();
7025 if (areEqual(LHS, RHS))
7028 return wasComputedBefore(LHS, RHS);
7034 bool areEqual(
const Expr *LHS,
const Expr *RHS)
const {
7036 const auto CachedResultIt = CachedEqualityComparisons.find({LHS, RHS});
7037 if (CachedResultIt != CachedEqualityComparisons.end())
7038 return CachedResultIt->second;
7052 bool wasComputedBefore(
const Expr *LHS,
const Expr *RHS)
const {
7053 const size_t &OrderLHS = Handler.AttachPtrComputationOrderMap.at(LHS);
7054 const size_t &OrderRHS = Handler.AttachPtrComputationOrderMap.at(RHS);
7056 return OrderLHS < OrderRHS;
7065 bool areSemanticallyEqual(
const Expr *LHS,
const Expr *RHS)
const {
7087 if (
const auto *LD = dyn_cast<DeclRefExpr>(LHS)) {
7088 const auto *RD = dyn_cast<DeclRefExpr>(RHS);
7091 return LD->getDecl()->getCanonicalDecl() ==
7092 RD->getDecl()->getCanonicalDecl();
7096 if (
const auto *LA = dyn_cast<ArraySubscriptExpr>(LHS)) {
7097 const auto *RA = dyn_cast<ArraySubscriptExpr>(RHS);
7100 return areSemanticallyEqual(LA->getBase(), RA->getBase()) &&
7101 areSemanticallyEqual(LA->getIdx(), RA->getIdx());
7105 if (
const auto *LM = dyn_cast<MemberExpr>(LHS)) {
7106 const auto *RM = dyn_cast<MemberExpr>(RHS);
7109 if (LM->getMemberDecl()->getCanonicalDecl() !=
7110 RM->getMemberDecl()->getCanonicalDecl())
7112 return areSemanticallyEqual(LM->getBase(), RM->getBase());
7116 if (
const auto *LU = dyn_cast<UnaryOperator>(LHS)) {
7117 const auto *RU = dyn_cast<UnaryOperator>(RHS);
7120 if (LU->getOpcode() != RU->getOpcode())
7122 return areSemanticallyEqual(LU->getSubExpr(), RU->getSubExpr());
7126 if (
const auto *LB = dyn_cast<BinaryOperator>(LHS)) {
7127 const auto *RB = dyn_cast<BinaryOperator>(RHS);
7130 if (LB->getOpcode() != RB->getOpcode())
7132 return areSemanticallyEqual(LB->getLHS(), RB->getLHS()) &&
7133 areSemanticallyEqual(LB->getRHS(), RB->getRHS());
7139 if (
const auto *LAS = dyn_cast<ArraySectionExpr>(LHS)) {
7140 const auto *RAS = dyn_cast<ArraySectionExpr>(RHS);
7143 return areSemanticallyEqual(LAS->getBase(), RAS->getBase()) &&
7144 areSemanticallyEqual(LAS->getLowerBound(),
7145 RAS->getLowerBound()) &&
7146 areSemanticallyEqual(LAS->getLength(), RAS->getLength());
7150 if (
const auto *LC = dyn_cast<CastExpr>(LHS)) {
7151 const auto *RC = dyn_cast<CastExpr>(RHS);
7154 if (LC->getCastKind() != RC->getCastKind())
7156 return areSemanticallyEqual(LC->getSubExpr(), RC->getSubExpr());
7164 if (
const auto *LI = dyn_cast<IntegerLiteral>(LHS)) {
7165 const auto *RI = dyn_cast<IntegerLiteral>(RHS);
7168 return LI->getValue() == RI->getValue();
7172 if (
const auto *LC = dyn_cast<CharacterLiteral>(LHS)) {
7173 const auto *RC = dyn_cast<CharacterLiteral>(RHS);
7176 return LC->getValue() == RC->getValue();
7180 if (
const auto *LF = dyn_cast<FloatingLiteral>(LHS)) {
7181 const auto *RF = dyn_cast<FloatingLiteral>(RHS);
7185 return LF->getValue().bitwiseIsEqual(RF->getValue());
7189 if (
const auto *LS = dyn_cast<StringLiteral>(LHS)) {
7190 const auto *RS = dyn_cast<StringLiteral>(RHS);
7193 return LS->getString() == RS->getString();
7201 if (
const auto *LB = dyn_cast<CXXBoolLiteralExpr>(LHS)) {
7202 const auto *RB = dyn_cast<CXXBoolLiteralExpr>(RHS);
7205 return LB->getValue() == RB->getValue();
7214 static unsigned getFlagMemberOffset() {
7215 unsigned Offset = 0;
7216 for (uint64_t Remain =
7217 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
7218 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF);
7219 !(Remain & 1); Remain = Remain >> 1)
7226 class MappingExprInfo {
7228 const ValueDecl *MapDecl =
nullptr;
7231 const Expr *MapExpr =
nullptr;
7234 MappingExprInfo(
const ValueDecl *MapDecl,
const Expr *MapExpr =
nullptr)
7235 : MapDecl(MapDecl), MapExpr(MapExpr) {}
7237 const ValueDecl *getMapDecl()
const {
return MapDecl; }
7238 const Expr *getMapExpr()
const {
return MapExpr; }
7241 using DeviceInfoTy = llvm::OpenMPIRBuilder::DeviceInfoTy;
7242 using MapBaseValuesArrayTy = llvm::OpenMPIRBuilder::MapValuesArrayTy;
7243 using MapValuesArrayTy = llvm::OpenMPIRBuilder::MapValuesArrayTy;
7244 using MapFlagsArrayTy = llvm::OpenMPIRBuilder::MapFlagsArrayTy;
7245 using MapDimArrayTy = llvm::OpenMPIRBuilder::MapDimArrayTy;
7246 using MapNonContiguousArrayTy =
7247 llvm::OpenMPIRBuilder::MapNonContiguousArrayTy;
7248 using MapExprsArrayTy = SmallVector<MappingExprInfo, 4>;
7249 using MapValueDeclsArrayTy = SmallVector<const ValueDecl *, 4>;
7253 bool ,
const ValueDecl *,
const Expr *>;
7254 using MapDataArrayTy = SmallVector<MapData, 4>;
7259 struct MapCombinedInfoTy : llvm::OpenMPIRBuilder::MapInfosTy {
7260 MapExprsArrayTy Exprs;
7261 MapValueDeclsArrayTy Mappers;
7262 MapValueDeclsArrayTy DevicePtrDecls;
7265 void append(MapCombinedInfoTy &CurInfo) {
7266 Exprs.append(CurInfo.Exprs.begin(), CurInfo.Exprs.end());
7267 DevicePtrDecls.append(CurInfo.DevicePtrDecls.begin(),
7268 CurInfo.DevicePtrDecls.end());
7269 Mappers.append(CurInfo.Mappers.begin(), CurInfo.Mappers.end());
7270 llvm::OpenMPIRBuilder::MapInfosTy::append(CurInfo);
7278 struct StructRangeInfoTy {
7279 MapCombinedInfoTy PreliminaryMapData;
7280 std::pair<
unsigned ,
Address > LowestElem = {
7282 std::pair<
unsigned ,
Address > HighestElem = {
7286 bool IsArraySection =
false;
7287 bool HasCompleteRecord =
false;
7292 struct AttachInfoTy {
7295 const ValueDecl *AttachPtrDecl =
nullptr;
7296 const Expr *AttachMapExpr =
nullptr;
7298 bool isValid()
const {
7305 bool hasAttachEntryForCapturedVar(
const ValueDecl *VD)
const {
7306 for (
const auto &AttachEntry : AttachPtrExprMap) {
7307 if (AttachEntry.second) {
7310 if (
const auto *DRE = dyn_cast<DeclRefExpr>(AttachEntry.second))
7311 if (DRE->getDecl() == VD)
7319 const Expr *getAttachPtrExpr(
7322 const auto It = AttachPtrExprMap.find(Components);
7323 if (It != AttachPtrExprMap.end())
7334 ArrayRef<OpenMPMapModifierKind> MapModifiers;
7335 ArrayRef<OpenMPMotionModifierKind> MotionModifiers;
7336 bool ReturnDevicePointer =
false;
7337 bool IsImplicit =
false;
7338 const ValueDecl *Mapper =
nullptr;
7339 const Expr *VarRef =
nullptr;
7340 bool ForDeviceAddr =
false;
7341 bool HasUdpFbNullify =
false;
7343 MapInfo() =
default;
7347 ArrayRef<OpenMPMapModifierKind> MapModifiers,
7348 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
7349 bool ReturnDevicePointer,
bool IsImplicit,
7350 const ValueDecl *Mapper =
nullptr,
const Expr *VarRef =
nullptr,
7351 bool ForDeviceAddr =
false,
bool HasUdpFbNullify =
false)
7352 : Components(Components), MapType(MapType), MapModifiers(MapModifiers),
7353 MotionModifiers(MotionModifiers),
7354 ReturnDevicePointer(ReturnDevicePointer), IsImplicit(IsImplicit),
7355 Mapper(Mapper), VarRef(VarRef), ForDeviceAddr(ForDeviceAddr),
7356 HasUdpFbNullify(HasUdpFbNullify) {}
7361 llvm::PointerUnion<
const OMPExecutableDirective *,
7362 const OMPDeclareMapperDecl *>
7366 CodeGenFunction &CGF;
7371 llvm::DenseMap<CanonicalDeclPtr<const VarDecl>,
bool> FirstPrivateDecls;
7374 llvm::SmallSet<OpenMPDefaultmapClauseKind, 4> DefaultmapFirstprivateKinds;
7380 SmallVector<OMPClauseMappableExprCommon::MappableExprComponentListRef, 4>>
7387 SmallVector<OMPClauseMappableExprCommon::MappableExprComponentListRef, 4>>
7391 llvm::DenseMap<const ValueDecl *, const OMPMapClause *> LambdasMap;
7406 llvm::DenseMap<const Expr *, std::optional<size_t>>
7407 AttachPtrComponentDepthMap = {{
nullptr, std::nullopt}};
7411 llvm::DenseMap<const Expr *, size_t> AttachPtrComputationOrderMap = {
7416 AttachPtrExprComparator AttachPtrComparator;
7418 llvm::Value *getExprTypeSize(
const Expr *E)
const {
7422 if (
const auto *OAE = dyn_cast<OMPArrayShapingExpr>(E)) {
7424 CGF.
getTypeSize(OAE->getBase()->getType()->getPointeeType());
7425 for (
const Expr *SE : OAE->getDimensions()) {
7436 if (
const auto *RefTy = ExprTy->
getAs<ReferenceType>())
7442 if (
const auto *OAE = dyn_cast<ArraySectionExpr>(E)) {
7444 OAE->getBase()->IgnoreParenImpCasts())
7450 if (!OAE->getLength() && OAE->getColonLocFirst().isValid() &&
7451 !OAE->getLowerBound())
7454 llvm::Value *ElemSize;
7455 if (
const auto *PTy = BaseTy->
getAs<PointerType>()) {
7456 ElemSize = CGF.
getTypeSize(PTy->getPointeeType().getCanonicalType());
7459 assert(ATy &&
"Expecting array type if not a pointer type.");
7460 ElemSize = CGF.
getTypeSize(ATy->getElementType().getCanonicalType());
7465 if (!OAE->getLength() && OAE->getColonLocFirst().isInvalid())
7468 if (
const Expr *LenExpr = OAE->getLength()) {
7472 LenExpr->getExprLoc());
7473 return CGF.
Builder.CreateNUWMul(LengthVal, ElemSize);
7475 assert(!OAE->getLength() && OAE->getColonLocFirst().isValid() &&
7476 OAE->getLowerBound() &&
"expected array_section[lb:].");
7482 OAE->getLowerBound()->getExprLoc());
7483 LBVal = CGF.
Builder.CreateNUWMul(LBVal, ElemSize);
7484 llvm::Value *
Cmp = CGF.
Builder.CreateICmpUGT(LengthVal, LBVal);
7485 llvm::Value *TrueVal = CGF.
Builder.CreateNUWSub(LengthVal, LBVal);
7486 LengthVal = CGF.
Builder.CreateSelect(
7487 Cmp, TrueVal, llvm::ConstantInt::get(CGF.
SizeTy, 0));
7497 OpenMPOffloadMappingFlags getMapTypeBits(
7499 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
bool IsImplicit,
7500 bool AddPtrFlag,
bool AddIsTargetParamFlag,
bool IsNonContiguous)
const {
7501 OpenMPOffloadMappingFlags Bits =
7502 IsImplicit ? OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT
7503 : OpenMPOffloadMappingFlags::OMP_MAP_NONE;
7505 case OMPC_MAP_alloc:
7506 case OMPC_MAP_release:
7513 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_TO;
7516 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_FROM;
7518 case OMPC_MAP_tofrom:
7519 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_TO |
7520 OpenMPOffloadMappingFlags::OMP_MAP_FROM;
7522 case OMPC_MAP_delete:
7523 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_DELETE;
7526 llvm_unreachable(
"Unexpected map type!");
7529 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ;
7530 if (AddIsTargetParamFlag)
7531 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM;
7532 if (llvm::is_contained(MapModifiers, OMPC_MAP_MODIFIER_always))
7533 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_ALWAYS;
7534 if (llvm::is_contained(MapModifiers, OMPC_MAP_MODIFIER_close))
7535 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_CLOSE;
7536 if (llvm::is_contained(MapModifiers, OMPC_MAP_MODIFIER_present) ||
7537 llvm::is_contained(MotionModifiers, OMPC_MOTION_MODIFIER_present))
7538 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_PRESENT;
7539 if (llvm::is_contained(MapModifiers, OMPC_MAP_MODIFIER_ompx_hold))
7540 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_OMPX_HOLD;
7541 if (IsNonContiguous)
7542 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_NON_CONTIG;
7548 bool isFinalArraySectionExpression(
const Expr *E)
const {
7549 const auto *OASE = dyn_cast<ArraySectionExpr>(E);
7556 if (OASE->getColonLocFirst().isInvalid())
7559 const Expr *Length = OASE->getLength();
7566 OASE->getBase()->IgnoreParenImpCasts())
7568 if (
const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.
getTypePtr()))
7569 return ATy->getSExtSize() != 1;
7581 llvm::APSInt ConstLength =
Result.Val.getInt();
7582 return ConstLength.getSExtValue() != 1;
7589 void emitAttachEntry(CodeGenFunction &CGF, MapCombinedInfoTy &CombinedInfo,
7590 const AttachInfoTy &AttachInfo)
const {
7591 assert(AttachInfo.isValid() &&
7592 "Expected valid attach pointer/pointee information!");
7596 llvm::Value *PointerSize = CGF.
Builder.CreateIntCast(
7597 llvm::ConstantInt::get(
7603 CombinedInfo.Exprs.emplace_back(AttachInfo.AttachPtrDecl,
7604 AttachInfo.AttachMapExpr);
7605 CombinedInfo.BasePointers.push_back(
7606 AttachInfo.AttachPtrAddr.emitRawPointer(CGF));
7607 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
7608 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
7609 CombinedInfo.Pointers.push_back(
7610 AttachInfo.AttachPteeAddr.emitRawPointer(CGF));
7611 CombinedInfo.Sizes.push_back(PointerSize);
7612 CombinedInfo.Types.push_back(OpenMPOffloadMappingFlags::OMP_MAP_ATTACH);
7614 CombinedInfo.HasAttachPtr.push_back(
false);
7615 CombinedInfo.Mappers.push_back(
nullptr);
7616 CombinedInfo.NonContigInfo.Dims.push_back(1);
7623 class CopyOverlappedEntryGaps {
7624 CodeGenFunction &CGF;
7625 MapCombinedInfoTy &CombinedInfo;
7626 OpenMPOffloadMappingFlags Flags = OpenMPOffloadMappingFlags::OMP_MAP_NONE;
7627 const ValueDecl *MapDecl =
nullptr;
7628 const Expr *MapExpr =
nullptr;
7630 bool IsNonContiguous =
false;
7634 const RecordDecl *LastParent =
nullptr;
7636 unsigned LastIndex = -1u;
7640 CopyOverlappedEntryGaps(CodeGenFunction &CGF,
7641 MapCombinedInfoTy &CombinedInfo,
7642 OpenMPOffloadMappingFlags Flags,
7643 const ValueDecl *MapDecl,
const Expr *MapExpr,
7644 Address BP, Address LB,
bool IsNonContiguous,
7646 : CGF(CGF), CombinedInfo(CombinedInfo), Flags(Flags), MapDecl(MapDecl),
7647 MapExpr(MapExpr), BP(BP), IsNonContiguous(IsNonContiguous),
7648 DimSize(DimSize), LB(LB) {}
7651 const OMPClauseMappableExprCommon::MappableComponent &MC,
7652 const FieldDecl *FD,
7653 llvm::function_ref<LValue(CodeGenFunction &,
const MemberExpr *)>
7654 EmitMemberExprBase) {
7664 LValue BaseLVal = EmitMemberExprBase(CGF, ME);
7676 copyUntilField(FD, ComponentLB);
7679 if (((int64_t)FieldOffset - (int64_t)Cursor) > 0)
7680 copyUntilField(FD, ComponentLB);
7682 Cursor = FieldOffset + FieldSize;
7687 void copyUntilField(
const FieldDecl *FD, Address ComponentLB) {
7690 llvm::Value *
Size = CGF.
Builder.CreatePtrDiff(ComponentLBPtr, LBPtr);
7691 copySizedChunk(LBPtr, Size);
7694 void copyUntilEnd(Address HB) {
7696 const ASTRecordLayout &RL =
7704 copySizedChunk(LBPtr, Size);
7707 void copySizedChunk(llvm::Value *Base, llvm::Value *Size) {
7708 CombinedInfo.Exprs.emplace_back(MapDecl, MapExpr);
7710 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
7711 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
7712 CombinedInfo.Pointers.push_back(Base);
7713 CombinedInfo.Sizes.push_back(
7715 CombinedInfo.Types.push_back(Flags);
7716 CombinedInfo.HasAttachPtr.push_back(
false);
7717 CombinedInfo.Mappers.push_back(
nullptr);
7718 CombinedInfo.NonContigInfo.Dims.push_back(IsNonContiguous ? DimSize : 1);
7727 void generateInfoForComponentList(
7729 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
7731 MapCombinedInfoTy &CombinedInfo,
7732 MapCombinedInfoTy &StructBaseCombinedInfo,
7733 StructRangeInfoTy &PartialStruct, AttachInfoTy &AttachInfo,
7734 bool IsFirstComponentList,
bool IsImplicit,
7735 bool GenerateAllInfoForClauses,
const ValueDecl *Mapper =
nullptr,
7736 bool ForDeviceAddr =
false,
const ValueDecl *BaseDecl =
nullptr,
7737 const Expr *MapExpr =
nullptr,
7738 ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef>
7739 OverlappedElements = {})
const {
7957 bool IsCaptureFirstInfo = IsFirstComponentList;
7961 bool RequiresReference =
false;
7964 auto CI = Components.rbegin();
7965 auto CE = Components.rend();
7970 bool IsExpressionFirstInfo =
true;
7971 bool FirstPointerInComplexData =
false;
7974 const Expr *AssocExpr = I->getAssociatedExpression();
7975 const auto *AE = dyn_cast<ArraySubscriptExpr>(AssocExpr);
7976 const auto *OASE = dyn_cast<ArraySectionExpr>(AssocExpr);
7977 const auto *OAShE = dyn_cast<OMPArrayShapingExpr>(AssocExpr);
7980 const Expr *AttachPtrExpr = getAttachPtrExpr(Components);
7981 auto [AttachPtrAddr, AttachPteeBaseAddr] =
7982 getAttachPtrAddrAndPteeBaseAddr(AttachPtrExpr, CGF);
7984 bool HasAttachPtr = AttachPtrExpr !=
nullptr;
7985 bool FirstComponentIsForAttachPtr = AssocExpr == AttachPtrExpr;
7986 bool SeenAttachPtr = FirstComponentIsForAttachPtr;
7988 if (FirstComponentIsForAttachPtr) {
7996 }
else if ((AE &&
isa<CXXThisExpr>(AE->getBase()->IgnoreParenImpCasts())) ||
8010 if (
const auto *VD =
8011 dyn_cast_or_null<VarDecl>(I->getAssociatedDeclaration())) {
8012 if (std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
8013 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD)) {
8014 if ((*Res == OMPDeclareTargetDeclAttr::MT_Link) ||
8015 ((*Res == OMPDeclareTargetDeclAttr::MT_To ||
8016 *Res == OMPDeclareTargetDeclAttr::MT_Enter) &&
8018 RequiresReference =
true;
8028 I->getAssociatedDeclaration()->
getType().getNonReferenceType();
8033 const auto *VD = dyn_cast<VarDecl>(I->getAssociatedDeclaration());
8035 !VD || VD->hasLocalStorage() || HasAttachPtr)
8038 FirstPointerInComplexData =
true;
8057 bool ShouldBeMemberOf =
false;
8066 const MemberExpr *EncounteredME =
nullptr;
8078 bool IsNonContiguous =
8079 CombinedInfo.NonContigInfo.IsNonContiguous ||
8080 any_of(Components, [&](
const auto &Component) {
8082 dyn_cast<ArraySectionExpr>(Component.getAssociatedExpression());
8086 const Expr *StrideExpr = OASE->getStride();
8091 "Stride expression must be of integer type");
8104 bool IsPrevMemberReference =
false;
8106 bool IsPartialMapped =
8107 !PartialStruct.PreliminaryMapData.BasePointers.empty();
8114 bool IsMappingWholeStruct =
true;
8115 if (!GenerateAllInfoForClauses) {
8116 IsMappingWholeStruct =
false;
8118 for (
auto TempI = I; TempI != CE; ++TempI) {
8119 const MemberExpr *PossibleME =
8120 dyn_cast<MemberExpr>(TempI->getAssociatedExpression());
8122 IsMappingWholeStruct =
false;
8128 bool SeenFirstNonBinOpExprAfterAttachPtr =
false;
8129 for (; I != CE; ++I) {
8132 if (HasAttachPtr && !SeenAttachPtr) {
8133 SeenAttachPtr = I->getAssociatedExpression() == AttachPtrExpr;
8140 if (HasAttachPtr && !SeenFirstNonBinOpExprAfterAttachPtr) {
8141 const auto *BO = dyn_cast<BinaryOperator>(I->getAssociatedExpression());
8146 SeenFirstNonBinOpExprAfterAttachPtr =
true;
8147 BP = AttachPteeBaseAddr;
8151 if (!EncounteredME) {
8152 EncounteredME = dyn_cast<MemberExpr>(I->getAssociatedExpression());
8155 if (EncounteredME) {
8156 ShouldBeMemberOf =
true;
8159 if (FirstPointerInComplexData) {
8160 QualType Ty = std::prev(I)
8161 ->getAssociatedDeclaration()
8163 .getNonReferenceType();
8165 FirstPointerInComplexData =
false;
8170 auto Next = std::next(I);
8180 bool IsFinalArraySection =
8182 isFinalArraySectionExpression(I->getAssociatedExpression());
8186 const ValueDecl *MapDecl = (I->getAssociatedDeclaration())
8187 ? I->getAssociatedDeclaration()
8189 MapExpr = (I->getAssociatedExpression()) ? I->getAssociatedExpression()
8196 dyn_cast<ArraySectionExpr>(I->getAssociatedExpression());
8198 dyn_cast<OMPArrayShapingExpr>(I->getAssociatedExpression());
8199 const auto *UO = dyn_cast<UnaryOperator>(I->getAssociatedExpression());
8200 const auto *BO = dyn_cast<BinaryOperator>(I->getAssociatedExpression());
8206 I->getAssociatedExpression()->getType()->isAnyPointerType();
8207 bool IsMemberReference =
isa<MemberExpr>(I->getAssociatedExpression()) &&
8210 bool IsNonDerefPointer = IsPointer &&
8211 !(UO && UO->getOpcode() != UO_Deref) && !BO &&
8217 if (
Next == CE || IsMemberReference || IsNonDerefPointer ||
8218 IsFinalArraySection) {
8221 assert((
Next == CE ||
8228 "Unexpected expression");
8232 auto &&EmitMemberExprBase = [](CodeGenFunction &CGF,
8233 const MemberExpr *E) {
8234 const Expr *BaseExpr = E->getBase();
8239 LValueBaseInfo BaseInfo;
8240 TBAAAccessInfo TBAAInfo;
8254 OAShE->getBase()->getType()->getPointeeType()),
8256 OAShE->getBase()->getType()));
8257 }
else if (IsMemberReference) {
8259 LValue BaseLVal = EmitMemberExprBase(CGF, ME);
8274 FinalLowestElem = LowestElem;
8279 bool IsMemberPointerOrAddr =
8281 (((IsPointer || ForDeviceAddr) &&
8282 I->getAssociatedExpression() == EncounteredME) ||
8283 (IsPrevMemberReference && !IsPointer) ||
8284 (IsMemberReference &&
Next != CE &&
8285 !
Next->getAssociatedExpression()->getType()->isPointerType()));
8286 if (!OverlappedElements.empty() &&
Next == CE) {
8288 assert(!PartialStruct.Base.isValid() &&
"The base element is set.");
8289 assert(!IsPointer &&
8290 "Unexpected base element with the pointer type.");
8293 PartialStruct.LowestElem = {0, LowestElem};
8295 I->getAssociatedExpression()->getType());
8300 PartialStruct.HighestElem = {
8301 std::numeric_limits<
decltype(
8302 PartialStruct.HighestElem.first)>
::max(),
8304 PartialStruct.Base = BP;
8305 PartialStruct.LB = LB;
8307 PartialStruct.PreliminaryMapData.BasePointers.empty() &&
8308 "Overlapped elements must be used only once for the variable.");
8309 std::swap(PartialStruct.PreliminaryMapData, CombinedInfo);
8311 OpenMPOffloadMappingFlags Flags =
8312 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF |
8313 getMapTypeBits(MapType, MapModifiers, MotionModifiers, IsImplicit,
8315 false, IsNonContiguous);
8316 CopyOverlappedEntryGaps CopyGaps(CGF, CombinedInfo, Flags, MapDecl,
8317 MapExpr, BP, LB, IsNonContiguous,
8321 Component : OverlappedElements) {
8322 for (
const OMPClauseMappableExprCommon::MappableComponent &MC :
8325 if (
const auto *FD = dyn_cast<FieldDecl>(VD)) {
8326 CopyGaps.processField(MC, FD, EmitMemberExprBase);
8331 CopyGaps.copyUntilEnd(HB);
8334 llvm::Value *
Size = getExprTypeSize(I->getAssociatedExpression());
8341 if ((!IsMemberPointerOrAddr && !IsPartialMapped) ||
8343 if (!IsMappingWholeStruct) {
8344 CombinedInfo.Exprs.emplace_back(MapDecl, MapExpr);
8346 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
8347 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
8349 CombinedInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
8351 CombinedInfo.NonContigInfo.Dims.push_back(IsNonContiguous ? DimSize
8354 StructBaseCombinedInfo.Exprs.emplace_back(MapDecl, MapExpr);
8355 StructBaseCombinedInfo.BasePointers.push_back(
8357 StructBaseCombinedInfo.DevicePtrDecls.push_back(
nullptr);
8358 StructBaseCombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
8359 StructBaseCombinedInfo.Pointers.push_back(LB.
emitRawPointer(CGF));
8360 StructBaseCombinedInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
8362 StructBaseCombinedInfo.NonContigInfo.Dims.push_back(
8363 IsNonContiguous ? DimSize : 1);
8367 bool HasMapper = Mapper &&
Next == CE;
8368 if (!IsMappingWholeStruct)
8369 CombinedInfo.Mappers.push_back(HasMapper ? Mapper :
nullptr);
8371 StructBaseCombinedInfo.Mappers.push_back(HasMapper ? Mapper
8378 OpenMPOffloadMappingFlags Flags = getMapTypeBits(
8379 MapType, MapModifiers, MotionModifiers, IsImplicit,
8380 !IsExpressionFirstInfo || RequiresReference ||
8381 FirstPointerInComplexData || IsMemberReference,
8382 IsCaptureFirstInfo && !RequiresReference, IsNonContiguous);
8384 if (!IsExpressionFirstInfo || IsMemberReference) {
8387 if (IsPointer || (IsMemberReference &&
Next != CE))
8388 Flags &= ~(OpenMPOffloadMappingFlags::OMP_MAP_TO |
8389 OpenMPOffloadMappingFlags::OMP_MAP_FROM |
8390 OpenMPOffloadMappingFlags::OMP_MAP_ALWAYS |
8391 OpenMPOffloadMappingFlags::OMP_MAP_DELETE |
8392 OpenMPOffloadMappingFlags::OMP_MAP_CLOSE);
8394 if (ShouldBeMemberOf) {
8397 Flags |= OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF;
8400 ShouldBeMemberOf =
false;
8404 if (!IsMappingWholeStruct) {
8405 CombinedInfo.Types.push_back(Flags);
8407 CombinedInfo.HasAttachPtr.push_back(HasAttachPtr);
8409 StructBaseCombinedInfo.Types.push_back(Flags);
8410 StructBaseCombinedInfo.HasAttachPtr.push_back(HasAttachPtr);
8417 if (EncounteredME) {
8422 if (!PartialStruct.Base.isValid()) {
8423 PartialStruct.LowestElem = {FieldIndex, LowestElem};
8424 if (IsFinalArraySection && OASE) {
8428 PartialStruct.HighestElem = {FieldIndex, HB};
8430 PartialStruct.HighestElem = {FieldIndex, LowestElem};
8432 PartialStruct.Base = BP;
8433 PartialStruct.LB = BP;
8434 }
else if (FieldIndex < PartialStruct.LowestElem.first) {
8435 PartialStruct.LowestElem = {FieldIndex, LowestElem};
8436 }
else if (FieldIndex > PartialStruct.HighestElem.first) {
8437 if (IsFinalArraySection && OASE) {
8441 PartialStruct.HighestElem = {FieldIndex, HB};
8443 PartialStruct.HighestElem = {FieldIndex, LowestElem};
8449 if (IsFinalArraySection || IsNonContiguous)
8450 PartialStruct.IsArraySection =
true;
8453 if (IsFinalArraySection)
8458 BP = IsMemberReference ? LowestElem : LB;
8459 if (!IsPartialMapped)
8460 IsExpressionFirstInfo =
false;
8461 IsCaptureFirstInfo =
false;
8462 FirstPointerInComplexData =
false;
8463 IsPrevMemberReference = IsMemberReference;
8464 }
else if (FirstPointerInComplexData) {
8465 QualType Ty = Components.rbegin()
8466 ->getAssociatedDeclaration()
8468 .getNonReferenceType();
8470 FirstPointerInComplexData =
false;
8476 PartialStruct.HasCompleteRecord =
true;
8479 if (shouldEmitAttachEntry(AttachPtrExpr, BaseDecl, CGF, CurDir)) {
8480 AttachInfo.AttachPtrAddr = AttachPtrAddr;
8481 AttachInfo.AttachPteeAddr = FinalLowestElem;
8482 AttachInfo.AttachPtrDecl = BaseDecl;
8483 AttachInfo.AttachMapExpr = MapExpr;
8486 if (!IsNonContiguous)
8489 const ASTContext &Context = CGF.
getContext();
8493 MapValuesArrayTy CurOffsets = {llvm::ConstantInt::get(CGF.
CGM.
Int64Ty, 0)};
8494 MapValuesArrayTy CurCounts;
8495 MapValuesArrayTy CurStrides = {llvm::ConstantInt::get(CGF.
CGM.
Int64Ty, 1)};
8496 MapValuesArrayTy DimSizes{llvm::ConstantInt::get(CGF.
CGM.
Int64Ty, 1)};
8502 for (
const OMPClauseMappableExprCommon::MappableComponent &Component :
8504 const Expr *AssocExpr = Component.getAssociatedExpression();
8505 const auto *OASE = dyn_cast<ArraySectionExpr>(AssocExpr);
8515 assert((VAT || CAT || &Component == &*Components.begin()) &&
8516 "Should be either ConstantArray or VariableArray if not the "
8520 if (CurCounts.empty()) {
8521 const Type *ElementType =
nullptr;
8523 ElementType = CAT->getElementType().getTypePtr();
8525 ElementType = VAT->getElementType().getTypePtr();
8526 else if (&Component == &*Components.begin()) {
8533 if (
const auto *PtrType = Ty->
getAs<PointerType>())
8540 "Non-first components should not be raw pointers");
8548 if (&Component != &*Components.begin())
8552 CurCounts.push_back(
8553 llvm::ConstantInt::get(CGF.
Int64Ty, ElementTypeSize));
8558 if (DimSizes.size() < Components.size() - 1) {
8561 llvm::ConstantInt::get(CGF.
Int64Ty, CAT->getZExtSize()));
8563 DimSizes.push_back(CGF.
Builder.CreateIntCast(
8570 auto *DI = DimSizes.begin() + 1;
8572 llvm::Value *DimProd =
8573 llvm::ConstantInt::get(CGF.
CGM.
Int64Ty, ElementTypeSize);
8582 for (
const OMPClauseMappableExprCommon::MappableComponent &Component :
8584 const Expr *AssocExpr = Component.getAssociatedExpression();
8586 if (
const auto *AE = dyn_cast<ArraySubscriptExpr>(AssocExpr)) {
8587 llvm::Value *Offset = CGF.
Builder.CreateIntCast(
8590 CurOffsets.push_back(Offset);
8591 CurCounts.push_back(llvm::ConstantInt::get(CGF.
Int64Ty, 1));
8592 CurStrides.push_back(CurStrides.back());
8596 const auto *OASE = dyn_cast<ArraySectionExpr>(AssocExpr);
8602 const Expr *OffsetExpr = OASE->getLowerBound();
8603 llvm::Value *Offset =
nullptr;
8606 Offset = llvm::ConstantInt::get(CGF.
Int64Ty, 0);
8614 const Expr *CountExpr = OASE->getLength();
8615 llvm::Value *Count =
nullptr;
8621 if (!OASE->getColonLocFirst().isValid() &&
8622 !OASE->getColonLocSecond().isValid()) {
8623 Count = llvm::ConstantInt::get(CGF.
Int64Ty, 1);
8629 const Expr *StrideExpr = OASE->getStride();
8630 llvm::Value *Stride =
8636 Count = CGF.
Builder.CreateUDiv(
8637 CGF.
Builder.CreateNUWSub(*DI, Offset), Stride);
8639 Count = CGF.
Builder.CreateNUWSub(*DI, Offset);
8645 CurCounts.push_back(Count);
8655 const Expr *StrideExpr = OASE->getStride();
8656 llvm::Value *Stride =
8661 DimProd = CGF.
Builder.CreateNUWMul(DimProd, *(DI - 1));
8663 CurStrides.push_back(CGF.
Builder.CreateNUWMul(DimProd, Stride));
8665 CurStrides.push_back(DimProd);
8667 Offset = CGF.
Builder.CreateNUWMul(DimProd, Offset);
8668 CurOffsets.push_back(Offset);
8670 if (DI != DimSizes.end())
8674 CombinedInfo.NonContigInfo.Offsets.push_back(CurOffsets);
8675 CombinedInfo.NonContigInfo.Counts.push_back(CurCounts);
8676 CombinedInfo.NonContigInfo.Strides.push_back(CurStrides);
8682 OpenMPOffloadMappingFlags
8683 getMapModifiersForPrivateClauses(
const CapturedStmt::Capture &Cap)
const {
8691 return OpenMPOffloadMappingFlags::OMP_MAP_TO |
8692 OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ;
8693 return OpenMPOffloadMappingFlags::OMP_MAP_PRIVATE |
8694 OpenMPOffloadMappingFlags::OMP_MAP_TO;
8697 if (I != LambdasMap.end())
8699 return getMapTypeBits(
8700 I->getSecond()->getMapType(), I->getSecond()->getMapTypeModifiers(),
8701 {}, I->getSecond()->isImplicit(),
8705 return OpenMPOffloadMappingFlags::OMP_MAP_TO |
8706 OpenMPOffloadMappingFlags::OMP_MAP_FROM;
8709 void getPlainLayout(
const CXXRecordDecl *RD,
8710 llvm::SmallVectorImpl<const FieldDecl *> &Layout,
8711 bool AsBase)
const {
8714 llvm::StructType *St =
8717 unsigned NumElements = St->getNumElements();
8719 llvm::PointerUnion<const CXXRecordDecl *, const FieldDecl *>, 4>
8720 RecordLayout(NumElements);
8723 for (
const auto &I : RD->
bases()) {
8727 QualType BaseTy = I.getType();
8738 RecordLayout[FieldIndex] =
Base;
8741 for (
const auto &I : RD->
vbases()) {
8742 QualType BaseTy = I.getType();
8749 if (RecordLayout[FieldIndex])
8751 RecordLayout[FieldIndex] =
Base;
8754 assert(!RD->
isUnion() &&
"Unexpected union.");
8755 for (
const auto *Field : RD->
fields()) {
8758 if (!
Field->isBitField() &&
8761 RecordLayout[FieldIndex] =
Field;
8764 for (
const llvm::PointerUnion<const CXXRecordDecl *, const FieldDecl *>
8765 &
Data : RecordLayout) {
8768 if (
const auto *Base = dyn_cast<const CXXRecordDecl *>(
Data))
8769 getPlainLayout(Base, Layout,
true);
8776 static Address getAttachPtrAddr(
const Expr *PointerExpr,
8777 CodeGenFunction &CGF) {
8778 assert(PointerExpr &&
"Cannot get addr from null attach-ptr expr");
8781 if (
auto *DRE = dyn_cast<DeclRefExpr>(PointerExpr)) {
8784 }
else if (
auto *OASE = dyn_cast<ArraySectionExpr>(PointerExpr)) {
8787 }
else if (
auto *ASE = dyn_cast<ArraySubscriptExpr>(PointerExpr)) {
8789 }
else if (
auto *ME = dyn_cast<MemberExpr>(PointerExpr)) {
8791 }
else if (
auto *UO = dyn_cast<UnaryOperator>(PointerExpr)) {
8792 assert(UO->getOpcode() == UO_Deref &&
8793 "Unexpected unary-operator on attach-ptr-expr");
8796 assert(AttachPtrAddr.
isValid() &&
8797 "Failed to get address for attach pointer expression");
8798 return AttachPtrAddr;
8805 static std::pair<Address, Address>
8806 getAttachPtrAddrAndPteeBaseAddr(
const Expr *AttachPtrExpr,
8807 CodeGenFunction &CGF) {
8812 Address AttachPtrAddr = getAttachPtrAddr(AttachPtrExpr, CGF);
8813 assert(AttachPtrAddr.
isValid() &&
"Invalid attach pointer addr");
8815 QualType AttachPtrType =
8820 AttachPtrAddr, AttachPtrType->
castAs<PointerType>());
8821 assert(AttachPteeBaseAddr.
isValid() &&
"Invalid attach pointee base addr");
8823 return {AttachPtrAddr, AttachPteeBaseAddr};
8829 shouldEmitAttachEntry(
const Expr *PointerExpr,
const ValueDecl *MapBaseDecl,
8830 CodeGenFunction &CGF,
8831 llvm::PointerUnion<
const OMPExecutableDirective *,
8832 const OMPDeclareMapperDecl *>
8842 ->getDirectiveKind());
8851 void collectAttachPtrExprInfo(
8853 llvm::PointerUnion<
const OMPExecutableDirective *,
8854 const OMPDeclareMapperDecl *>
8859 ? OMPD_declare_mapper
8862 const auto &[AttachPtrExpr, Depth] =
8866 AttachPtrComputationOrderMap.try_emplace(
8867 AttachPtrExpr, AttachPtrComputationOrderMap.size());
8868 AttachPtrComponentDepthMap.try_emplace(AttachPtrExpr, Depth);
8869 AttachPtrExprMap.try_emplace(Components, AttachPtrExpr);
8877 void generateAllInfoForClauses(
8878 ArrayRef<const OMPClause *> Clauses, MapCombinedInfoTy &CombinedInfo,
8879 llvm::OpenMPIRBuilder &OMPBuilder,
8880 const llvm::DenseSet<CanonicalDeclPtr<const Decl>> &SkipVarSet =
8881 llvm::DenseSet<CanonicalDeclPtr<const Decl>>())
const {
8886 llvm::MapVector<CanonicalDeclPtr<const Decl>,
8887 SmallVector<SmallVector<MapInfo, 8>, 4>>
8893 [&Info, &SkipVarSet](
8894 const ValueDecl *D, MapKind
Kind,
8897 ArrayRef<OpenMPMapModifierKind> MapModifiers,
8898 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
8899 bool ReturnDevicePointer,
bool IsImplicit,
const ValueDecl *Mapper,
8900 const Expr *VarRef =
nullptr,
bool ForDeviceAddr =
false) {
8901 if (SkipVarSet.contains(D))
8903 auto It = Info.try_emplace(D, Total).first;
8904 It->second[
Kind].emplace_back(
8905 L, MapType, MapModifiers, MotionModifiers, ReturnDevicePointer,
8906 IsImplicit, Mapper, VarRef, ForDeviceAddr);
8909 for (
const auto *
Cl : Clauses) {
8910 const auto *
C = dyn_cast<OMPMapClause>(
Cl);
8914 if (llvm::is_contained(
C->getMapTypeModifiers(),
8915 OMPC_MAP_MODIFIER_present))
8917 else if (
C->getMapType() == OMPC_MAP_alloc)
8919 const auto *EI =
C->getVarRefs().begin();
8920 for (
const auto L :
C->component_lists()) {
8921 const Expr *E = (
C->getMapLoc().isValid()) ? *EI :
nullptr;
8922 InfoGen(std::get<0>(L), Kind, std::get<1>(L),
C->getMapType(),
8923 C->getMapTypeModifiers(), {},
8924 false,
C->isImplicit(), std::get<2>(L),
8929 for (
const auto *
Cl : Clauses) {
8930 const auto *
C = dyn_cast<OMPToClause>(
Cl);
8934 if (llvm::is_contained(
C->getMotionModifiers(),
8935 OMPC_MOTION_MODIFIER_present))
8937 if (llvm::is_contained(
C->getMotionModifiers(),
8938 OMPC_MOTION_MODIFIER_iterator)) {
8939 if (
auto *IteratorExpr = dyn_cast<OMPIteratorExpr>(
8940 C->getIteratorModifier()->IgnoreParenImpCasts())) {
8941 const auto *VD =
cast<VarDecl>(IteratorExpr->getIteratorDecl(0));
8946 const auto *EI =
C->getVarRefs().begin();
8947 for (
const auto L :
C->component_lists()) {
8948 InfoGen(std::get<0>(L), Kind, std::get<1>(L), OMPC_MAP_to, {},
8949 C->getMotionModifiers(),
false,
8950 C->isImplicit(), std::get<2>(L), *EI);
8954 for (
const auto *
Cl : Clauses) {
8955 const auto *
C = dyn_cast<OMPFromClause>(
Cl);
8959 if (llvm::is_contained(
C->getMotionModifiers(),
8960 OMPC_MOTION_MODIFIER_present))
8962 if (llvm::is_contained(
C->getMotionModifiers(),
8963 OMPC_MOTION_MODIFIER_iterator)) {
8964 if (
auto *IteratorExpr = dyn_cast<OMPIteratorExpr>(
8965 C->getIteratorModifier()->IgnoreParenImpCasts())) {
8966 const auto *VD =
cast<VarDecl>(IteratorExpr->getIteratorDecl(0));
8971 const auto *EI =
C->getVarRefs().begin();
8972 for (
const auto L :
C->component_lists()) {
8973 InfoGen(std::get<0>(L), Kind, std::get<1>(L), OMPC_MAP_from, {},
8974 C->getMotionModifiers(),
8975 false,
C->isImplicit(), std::get<2>(L),
8988 MapCombinedInfoTy UseDeviceDataCombinedInfo;
8990 auto &&UseDeviceDataCombinedInfoGen =
8991 [&UseDeviceDataCombinedInfo](
const ValueDecl *VD, llvm::Value *
Ptr,
8992 CodeGenFunction &CGF,
bool IsDevAddr,
8993 bool HasUdpFbNullify =
false) {
8994 UseDeviceDataCombinedInfo.Exprs.push_back(VD);
8995 UseDeviceDataCombinedInfo.BasePointers.emplace_back(Ptr);
8996 UseDeviceDataCombinedInfo.DevicePtrDecls.emplace_back(VD);
8997 UseDeviceDataCombinedInfo.DevicePointers.emplace_back(
8998 IsDevAddr ? DeviceInfoTy::Address : DeviceInfoTy::Pointer);
9004 UseDeviceDataCombinedInfo.Pointers.push_back(Ptr);
9005 UseDeviceDataCombinedInfo.Sizes.push_back(
9006 llvm::Constant::getNullValue(CGF.Int64Ty));
9007 OpenMPOffloadMappingFlags Flags =
9008 OpenMPOffloadMappingFlags::OMP_MAP_RETURN_PARAM;
9009 if (HasUdpFbNullify)
9010 Flags |= OpenMPOffloadMappingFlags::OMP_MAP_FB_NULLIFY;
9011 UseDeviceDataCombinedInfo.Types.push_back(Flags);
9012 UseDeviceDataCombinedInfo.HasAttachPtr.push_back(
false);
9013 UseDeviceDataCombinedInfo.Mappers.push_back(
nullptr);
9017 [&UseDeviceDataCombinedInfoGen](
9018 CodeGenFunction &CGF,
const Expr *IE,
const ValueDecl *VD,
9021 bool IsDevAddr,
bool IEIsAttachPtrForDevAddr =
false,
9022 bool HasUdpFbNullify =
false) {
9026 if (IsDevAddr && !IEIsAttachPtrForDevAddr) {
9027 if (IE->isGLValue())
9034 bool TreatDevAddrAsDevPtr = IEIsAttachPtrForDevAddr;
9041 UseDeviceDataCombinedInfoGen(VD, Ptr, CGF, IsDevAddr &&
9042 !TreatDevAddrAsDevPtr,
9046 auto &&IsMapInfoExist =
9047 [&Info,
this](CodeGenFunction &CGF,
const ValueDecl *VD,
const Expr *IE,
9048 const Expr *DesiredAttachPtrExpr,
bool IsDevAddr,
9049 bool HasUdpFbNullify =
false) ->
bool {
9057 if (It != Info.end()) {
9059 for (
auto &
Data : It->second) {
9060 MapInfo *CI =
nullptr;
9064 auto *It = llvm::find_if(
Data, [&](
const MapInfo &MI) {
9065 if (MI.Components.back().getAssociatedDeclaration() != VD)
9068 const Expr *MapAttachPtr = getAttachPtrExpr(MI.Components);
9069 bool Match = AttachPtrComparator.areEqual(MapAttachPtr,
9070 DesiredAttachPtrExpr);
9074 if (It !=
Data.end())
9079 CI->ForDeviceAddr =
true;
9080 CI->ReturnDevicePointer =
true;
9081 CI->HasUdpFbNullify = HasUdpFbNullify;
9085 auto PrevCI = std::next(CI->Components.rbegin());
9086 const auto *VarD = dyn_cast<VarDecl>(VD);
9087 const Expr *AttachPtrExpr = getAttachPtrExpr(CI->Components);
9088 if (CGF.CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory() ||
9090 !VD->getType().getNonReferenceType()->isPointerType() ||
9091 PrevCI == CI->Components.rend() ||
9093 VarD->hasLocalStorage() ||
9094 (isa_and_nonnull<DeclRefExpr>(AttachPtrExpr) &&
9096 CI->ForDeviceAddr = IsDevAddr;
9097 CI->ReturnDevicePointer =
true;
9098 CI->HasUdpFbNullify = HasUdpFbNullify;
9116 for (
const auto *
Cl : Clauses) {
9117 const auto *
C = dyn_cast<OMPUseDevicePtrClause>(
Cl);
9120 bool HasUdpFbNullify =
9121 C->getFallbackModifier() == OMPC_USE_DEVICE_PTR_FALLBACK_fb_nullify;
9122 for (
const auto L :
C->component_lists()) {
9125 assert(!Components.empty() &&
9126 "Not expecting empty list of components!");
9127 const ValueDecl *VD = Components.back().getAssociatedDeclaration();
9129 const Expr *IE = Components.back().getAssociatedExpression();
9137 const Expr *UDPOperandExpr =
9138 Components.front().getAssociatedExpression();
9139 if (IsMapInfoExist(CGF, VD, IE,
9141 false, HasUdpFbNullify))
9143 MapInfoGen(CGF, IE, VD, Components,
false,
9144 false, HasUdpFbNullify);
9148 llvm::SmallDenseSet<CanonicalDeclPtr<const Decl>, 4> Processed;
9149 for (
const auto *
Cl : Clauses) {
9150 const auto *
C = dyn_cast<OMPUseDeviceAddrClause>(
Cl);
9153 for (
const auto L :
C->component_lists()) {
9156 assert(!std::get<1>(L).empty() &&
9157 "Not expecting empty list of components!");
9158 const ValueDecl *VD = std::get<1>(L).back().getAssociatedDeclaration();
9159 if (!Processed.insert(VD).second)
9180 const Expr *UDAAttachPtrExpr = getAttachPtrExpr(Components);
9181 const Expr *IE = std::get<1>(L).back().getAssociatedExpression();
9182 assert((!UDAAttachPtrExpr || UDAAttachPtrExpr == IE) &&
9183 "use_device_addr operand has an attach-ptr, but does not match "
9184 "last component's expr.");
9185 if (IsMapInfoExist(CGF, VD, IE,
9189 MapInfoGen(CGF, IE, VD, Components,
9191 UDAAttachPtrExpr !=
nullptr);
9195 for (
const auto &
Data : Info) {
9196 MapCombinedInfoTy CurInfo;
9198 const ValueDecl *VD = cast_or_null<ValueDecl>(D);
9205 SmallVector<std::pair<const Expr *, MapInfo>, 16> AttachPtrMapInfoPairs;
9208 for (
const auto &M :
Data.second) {
9209 for (
const MapInfo &L : M) {
9210 assert(!L.Components.empty() &&
9211 "Not expecting declaration with no component lists.");
9213 const Expr *AttachPtrExpr = getAttachPtrExpr(L.Components);
9214 AttachPtrMapInfoPairs.emplace_back(AttachPtrExpr, L);
9219 llvm::stable_sort(AttachPtrMapInfoPairs,
9220 [
this](
const auto &LHS,
const auto &RHS) {
9221 return AttachPtrComparator(LHS.first, RHS.first);
9226 auto *It = AttachPtrMapInfoPairs.begin();
9227 while (It != AttachPtrMapInfoPairs.end()) {
9228 const Expr *AttachPtrExpr = It->first;
9230 SmallVector<MapInfo, 8> GroupLists;
9231 while (It != AttachPtrMapInfoPairs.end() &&
9232 (It->first == AttachPtrExpr ||
9233 AttachPtrComparator.areEqual(It->first, AttachPtrExpr))) {
9234 GroupLists.push_back(It->second);
9237 assert(!GroupLists.empty() &&
"GroupLists should not be empty");
9239 StructRangeInfoTy PartialStruct;
9240 AttachInfoTy AttachInfo;
9241 MapCombinedInfoTy GroupCurInfo;
9243 MapCombinedInfoTy GroupStructBaseCurInfo;
9244 for (
const MapInfo &L : GroupLists) {
9246 unsigned CurrentBasePointersIdx = GroupCurInfo.BasePointers.size();
9247 unsigned StructBasePointersIdx =
9248 GroupStructBaseCurInfo.BasePointers.size();
9250 GroupCurInfo.NonContigInfo.IsNonContiguous =
9251 L.Components.back().isNonContiguous();
9252 generateInfoForComponentList(
9253 L.MapType, L.MapModifiers, L.MotionModifiers, L.Components,
9254 GroupCurInfo, GroupStructBaseCurInfo, PartialStruct, AttachInfo,
9255 false, L.IsImplicit,
9256 true, L.Mapper, L.ForDeviceAddr, VD,
9261 if (L.ReturnDevicePointer) {
9265 assert((CurrentBasePointersIdx < GroupCurInfo.BasePointers.size() ||
9266 StructBasePointersIdx <
9267 GroupStructBaseCurInfo.BasePointers.size()) &&
9268 "Unexpected number of mapped base pointers.");
9271 const ValueDecl *RelevantVD =
9272 L.Components.back().getAssociatedDeclaration();
9273 assert(RelevantVD &&
9274 "No relevant declaration related with device pointer??");
9281 auto SetDevicePointerInfo = [&](MapCombinedInfoTy &Info,
9283 Info.DevicePtrDecls[Idx] = RelevantVD;
9284 Info.DevicePointers[Idx] = L.ForDeviceAddr
9285 ? DeviceInfoTy::Address
9286 : DeviceInfoTy::Pointer;
9288 OpenMPOffloadMappingFlags::OMP_MAP_RETURN_PARAM;
9289 if (L.HasUdpFbNullify)
9291 OpenMPOffloadMappingFlags::OMP_MAP_FB_NULLIFY;
9294 if (StructBasePointersIdx <
9295 GroupStructBaseCurInfo.BasePointers.size())
9296 SetDevicePointerInfo(GroupStructBaseCurInfo,
9297 StructBasePointersIdx);
9299 SetDevicePointerInfo(GroupCurInfo, CurrentBasePointersIdx);
9305 MapCombinedInfoTy GroupUnionCurInfo;
9306 GroupUnionCurInfo.append(GroupStructBaseCurInfo);
9307 GroupUnionCurInfo.append(GroupCurInfo);
9311 if (PartialStruct.Base.isValid()) {
9319 GroupUnionCurInfo.NonContigInfo.Dims.insert(
9320 GroupUnionCurInfo.NonContigInfo.Dims.begin(), 1);
9322 CurInfo, GroupUnionCurInfo.Types, PartialStruct, AttachInfo,
9323 !VD, OMPBuilder, VD,
9324 CombinedInfo.BasePointers.size(),
9330 CurInfo.append(GroupUnionCurInfo);
9331 if (AttachInfo.isValid())
9332 emitAttachEntry(CGF, CurInfo, AttachInfo);
9336 CombinedInfo.append(CurInfo);
9339 CombinedInfo.append(UseDeviceDataCombinedInfo);
9343 MappableExprsHandler(
const OMPExecutableDirective &Dir, CodeGenFunction &CGF)
9344 : CurDir(&Dir), CGF(CGF), AttachPtrComparator(*this) {
9346 for (
const auto *
C : Dir.getClausesOfKind<OMPFirstprivateClause>())
9347 for (
const auto *D :
C->varlist())
9348 FirstPrivateDecls.try_emplace(
9351 for (
const auto *
C : Dir.getClausesOfKind<OMPUsesAllocatorsClause>()) {
9352 for (unsigned I = 0, E = C->getNumberOfAllocators(); I < E; ++I) {
9353 OMPUsesAllocatorsClause::Data D = C->getAllocatorData(I);
9354 if (const auto *DRE = dyn_cast_or_null<DeclRefExpr>(D.AllocatorTraits))
9355 FirstPrivateDecls.try_emplace(cast<VarDecl>(DRE->getDecl()),
9357 else if (const auto *VD = dyn_cast<VarDecl>(
9358 cast<DeclRefExpr>(D.Allocator->IgnoreParenImpCasts())
9360 FirstPrivateDecls.try_emplace(VD, true);
9364 for (
const auto *
C : Dir.getClausesOfKind<OMPDefaultmapClause>())
9365 if (
C->getDefaultmapModifier() == OMPC_DEFAULTMAP_MODIFIER_firstprivate)
9366 DefaultmapFirstprivateKinds.insert(
C->getDefaultmapKind());
9368 for (
const auto *
C : Dir.getClausesOfKind<OMPIsDevicePtrClause>())
9369 for (
auto L :
C->component_lists())
9370 DevPointersMap[std::get<0>(L)].push_back(std::get<1>(L));
9372 for (
const auto *
C : Dir.getClausesOfKind<OMPHasDeviceAddrClause>())
9373 for (
auto L :
C->component_lists())
9374 HasDevAddrsMap[std::get<0>(L)].push_back(std::get<1>(L));
9376 for (
const auto *
C : Dir.getClausesOfKind<OMPMapClause>()) {
9377 if (C->getMapType() != OMPC_MAP_to)
9379 for (auto L : C->component_lists()) {
9380 const ValueDecl *VD = std::get<0>(L);
9381 const auto *RD = VD ? VD->getType()
9383 .getNonReferenceType()
9384 ->getAsCXXRecordDecl()
9386 if (RD && RD->isLambda())
9387 LambdasMap.try_emplace(std::get<0>(L), C);
9391 auto CollectAttachPtrExprsForClauseComponents = [
this](
const auto *
C) {
9392 for (
auto L :
C->component_lists()) {
9395 if (!Components.empty())
9396 collectAttachPtrExprInfo(Components, CurDir);
9402 for (
const auto *
C : Dir.getClausesOfKind<OMPMapClause>())
9403 CollectAttachPtrExprsForClauseComponents(
C);
9404 for (
const auto *
C : Dir.getClausesOfKind<OMPToClause>())
9405 CollectAttachPtrExprsForClauseComponents(
C);
9406 for (
const auto *
C : Dir.getClausesOfKind<OMPFromClause>())
9407 CollectAttachPtrExprsForClauseComponents(
C);
9408 for (
const auto *
C : Dir.getClausesOfKind<OMPUseDevicePtrClause>())
9409 CollectAttachPtrExprsForClauseComponents(
C);
9410 for (
const auto *
C : Dir.getClausesOfKind<OMPUseDeviceAddrClause>())
9411 CollectAttachPtrExprsForClauseComponents(
C);
9412 for (
const auto *
C : Dir.getClausesOfKind<OMPIsDevicePtrClause>())
9413 CollectAttachPtrExprsForClauseComponents(
C);
9414 for (
const auto *
C : Dir.getClausesOfKind<OMPHasDeviceAddrClause>())
9415 CollectAttachPtrExprsForClauseComponents(
C);
9419 MappableExprsHandler(
const OMPDeclareMapperDecl &Dir,
CodeGenFunction &CGF)
9420 : CurDir(&Dir), CGF(CGF), AttachPtrComparator(*this) {
9421 auto CollectAttachPtrExprsForClauseComponents = [
this](
const auto *
C) {
9422 for (
auto L :
C->component_lists()) {
9425 if (!Components.empty())
9426 collectAttachPtrExprInfo(Components, CurDir);
9434 if (const auto *C = dyn_cast<OMPMapClause>(Cl))
9435 CollectAttachPtrExprsForClauseComponents(C);
9436 else if (const auto *C = dyn_cast<OMPToClause>(Cl))
9437 CollectAttachPtrExprsForClauseComponents(C);
9438 else if (const auto *C = dyn_cast<OMPFromClause>(Cl))
9439 CollectAttachPtrExprsForClauseComponents(C);
9451 void emitCombinedEntry(MapCombinedInfoTy &CombinedInfo,
9452 MapFlagsArrayTy &CurTypes,
9453 const StructRangeInfoTy &PartialStruct,
9454 AttachInfoTy &AttachInfo,
bool IsMapThis,
9455 llvm::OpenMPIRBuilder &OMPBuilder,
const ValueDecl *VD,
9456 unsigned OffsetForMemberOfFlag,
9457 bool NotTargetParams)
const {
9458 if (CurTypes.size() == 1 &&
9459 ((CurTypes.back() & OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF) !=
9460 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF) &&
9461 !PartialStruct.IsArraySection)
9463 Address LBAddr = PartialStruct.LowestElem.second;
9464 Address HBAddr = PartialStruct.HighestElem.second;
9465 if (PartialStruct.HasCompleteRecord) {
9466 LBAddr = PartialStruct.LB;
9467 HBAddr = PartialStruct.LB;
9469 CombinedInfo.Exprs.push_back(VD);
9471 CombinedInfo.BasePointers.push_back(PartialStruct.Base.emitRawPointer(CGF));
9472 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
9473 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
9476 const CXXMethodDecl *MD =
9478 const CXXRecordDecl *RD = MD ? MD->
getParent() :
nullptr;
9479 bool HasBaseClass = RD && IsMapThis ? RD->
getNumBases() > 0 :
false;
9489 CombinedInfo.Pointers.push_back(PartialStruct.Base.emitRawPointer(CGF));
9494 CombinedInfo.Sizes.push_back(Size);
9496 CombinedInfo.Pointers.push_back(LB);
9499 llvm::Value *HAddr = CGF.
Builder.CreateConstGEP1_32(
9503 llvm::Value *Diff = CGF.
Builder.CreatePtrDiff(CHAddr, CLAddr);
9506 CombinedInfo.Sizes.push_back(Size);
9508 CombinedInfo.Mappers.push_back(
nullptr);
9510 CombinedInfo.Types.push_back(
9511 NotTargetParams ? OpenMPOffloadMappingFlags::OMP_MAP_NONE
9512 : !PartialStruct.PreliminaryMapData.BasePointers.empty()
9513 ? OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ
9514 : OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM);
9522 CombinedInfo.HasAttachPtr.push_back(AttachInfo.isValid());
9525 if (CurTypes.end() !=
9526 llvm::find_if(CurTypes, [](OpenMPOffloadMappingFlags
Type) {
9527 return static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>>(
9528 Type & OpenMPOffloadMappingFlags::OMP_MAP_PRESENT);
9530 CombinedInfo.Types.back() |= OpenMPOffloadMappingFlags::OMP_MAP_PRESENT;
9532 (*CurTypes.begin()) &= ~OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM;
9539 if (CurTypes.end() !=
9540 llvm::find_if(CurTypes, [](OpenMPOffloadMappingFlags
Type) {
9541 return static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>>(
9542 Type & OpenMPOffloadMappingFlags::OMP_MAP_OMPX_HOLD);
9544 CombinedInfo.Types.back() |= OpenMPOffloadMappingFlags::OMP_MAP_OMPX_HOLD;
9545 for (
auto &M : CurTypes)
9546 M |= OpenMPOffloadMappingFlags::OMP_MAP_OMPX_HOLD;
9553 OpenMPOffloadMappingFlags MemberOfFlag = OMPBuilder.getMemberOfFlag(
9554 OffsetForMemberOfFlag + CombinedInfo.BasePointers.size() - 1);
9555 for (
auto &M : CurTypes)
9556 OMPBuilder.setCorrectMemberOfFlag(M, MemberOfFlag);
9573 if (AttachInfo.isValid())
9574 AttachInfo.AttachPteeAddr = LBAddr;
9582 void generateAllInfo(
9583 MapCombinedInfoTy &CombinedInfo, llvm::OpenMPIRBuilder &OMPBuilder,
9584 const llvm::DenseSet<CanonicalDeclPtr<const Decl>> &SkipVarSet =
9585 llvm::DenseSet<CanonicalDeclPtr<const Decl>>())
const {
9587 "Expect a executable directive");
9589 generateAllInfoForClauses(CurExecDir->clauses(), CombinedInfo, OMPBuilder,
9596 void generateAllInfoForMapper(MapCombinedInfoTy &CombinedInfo,
9597 llvm::OpenMPIRBuilder &OMPBuilder)
const {
9599 "Expect a declare mapper directive");
9601 generateAllInfoForClauses(CurMapperDir->clauses(), CombinedInfo,
9606 void generateInfoForLambdaCaptures(
9607 const ValueDecl *VD, llvm::Value *Arg, MapCombinedInfoTy &CombinedInfo,
9608 llvm::DenseMap<llvm::Value *, llvm::Value *> &LambdaPointers)
const {
9616 llvm::DenseMap<const ValueDecl *, FieldDecl *> Captures;
9617 FieldDecl *ThisCapture =
nullptr;
9623 LambdaPointers.try_emplace(ThisLVal.getPointer(CGF),
9624 VDLVal.getPointer(CGF));
9625 CombinedInfo.Exprs.push_back(VD);
9626 CombinedInfo.BasePointers.push_back(ThisLVal.getPointer(CGF));
9627 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
9628 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
9629 CombinedInfo.Pointers.push_back(ThisLValVal.getPointer(CGF));
9630 CombinedInfo.Sizes.push_back(
9633 CombinedInfo.Types.push_back(
9634 OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ |
9635 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL |
9636 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF |
9637 OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT);
9638 CombinedInfo.HasAttachPtr.push_back(
false);
9639 CombinedInfo.Mappers.push_back(
nullptr);
9641 for (
const LambdaCapture &LC : RD->
captures()) {
9642 if (!LC.capturesVariable())
9647 auto It = Captures.find(VD);
9648 assert(It != Captures.end() &&
"Found lambda capture without field.");
9652 LambdaPointers.try_emplace(VarLVal.getPointer(CGF),
9653 VDLVal.getPointer(CGF));
9654 CombinedInfo.Exprs.push_back(VD);
9655 CombinedInfo.BasePointers.push_back(VarLVal.getPointer(CGF));
9656 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
9657 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
9658 CombinedInfo.Pointers.push_back(VarLValVal.getPointer(CGF));
9659 CombinedInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
9665 LambdaPointers.try_emplace(VarLVal.getPointer(CGF),
9666 VDLVal.getPointer(CGF));
9667 CombinedInfo.Exprs.push_back(VD);
9668 CombinedInfo.BasePointers.push_back(VarLVal.getPointer(CGF));
9669 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
9670 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
9671 CombinedInfo.Pointers.push_back(VarRVal.
getScalarVal());
9672 CombinedInfo.Sizes.push_back(llvm::ConstantInt::get(CGF.
Int64Ty, 0));
9674 CombinedInfo.Types.push_back(
9675 OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ |
9676 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL |
9677 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF |
9678 OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT);
9679 CombinedInfo.HasAttachPtr.push_back(
false);
9680 CombinedInfo.Mappers.push_back(
nullptr);
9685 void adjustMemberOfForLambdaCaptures(
9686 llvm::OpenMPIRBuilder &OMPBuilder,
9687 const llvm::DenseMap<llvm::Value *, llvm::Value *> &LambdaPointers,
9688 MapBaseValuesArrayTy &BasePointers, MapValuesArrayTy &Pointers,
9689 MapFlagsArrayTy &Types)
const {
9690 for (
unsigned I = 0, E = Types.size(); I < E; ++I) {
9692 if (Types[I] != (OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ |
9693 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL |
9694 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF |
9695 OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT))
9697 llvm::Value *BasePtr = LambdaPointers.lookup(BasePointers[I]);
9698 assert(BasePtr &&
"Unable to find base lambda address.");
9700 for (
unsigned J = I; J > 0; --J) {
9701 unsigned Idx = J - 1;
9702 if (Pointers[Idx] != BasePtr)
9707 assert(TgtIdx != -1 &&
"Unable to find parent lambda.");
9711 OpenMPOffloadMappingFlags MemberOfFlag =
9712 OMPBuilder.getMemberOfFlag(TgtIdx);
9713 OMPBuilder.setCorrectMemberOfFlag(Types[I], MemberOfFlag);
9719 void populateComponentListsForNonLambdaCaptureFromClauses(
9720 const ValueDecl *VD, MapDataArrayTy &DeclComponentLists,
9722 SmallVector<OMPClauseMappableExprCommon::MappableComponent, 8>>
9723 &StorageForImplicitlyAddedComponentLists)
const {
9724 if (VD && LambdasMap.count(VD))
9730 auto It = DevPointersMap.find(VD);
9731 if (It != DevPointersMap.end())
9732 for (
const auto &MCL : It->second)
9733 DeclComponentLists.emplace_back(MCL, OMPC_MAP_to,
Unknown,
9736 auto I = HasDevAddrsMap.find(VD);
9737 if (I != HasDevAddrsMap.end())
9738 for (
const auto &MCL : I->second)
9739 DeclComponentLists.emplace_back(MCL, OMPC_MAP_tofrom,
Unknown,
9743 "Expect a executable directive");
9745 for (
const auto *
C : CurExecDir->getClausesOfKind<OMPMapClause>()) {
9746 const auto *EI =
C->getVarRefs().begin();
9747 for (
const auto L :
C->decl_component_lists(VD)) {
9748 const ValueDecl *VDecl, *Mapper;
9750 const Expr *E = (
C->getMapLoc().isValid()) ? *EI :
nullptr;
9752 std::tie(VDecl, Components, Mapper) = L;
9753 assert(VDecl == VD &&
"We got information for the wrong declaration??");
9754 assert(!Components.empty() &&
9755 "Not expecting declaration with no component lists.");
9756 DeclComponentLists.emplace_back(Components,
C->getMapType(),
9757 C->getMapTypeModifiers(),
9758 C->isImplicit(), Mapper, E);
9767 addImplicitMapForAttachPtrBaseIfMemberOfCapturedVD(
9768 VD, DeclComponentLists, StorageForImplicitlyAddedComponentLists);
9770 llvm::stable_sort(DeclComponentLists, [](
const MapData &LHS,
9771 const MapData &RHS) {
9772 ArrayRef<OpenMPMapModifierKind> MapModifiers = std::get<2>(LHS);
9775 llvm::is_contained(MapModifiers, clang::OMPC_MAP_MODIFIER_present);
9776 bool HasAllocs = MapType == OMPC_MAP_alloc;
9777 MapModifiers = std::get<2>(RHS);
9778 MapType = std::get<1>(LHS);
9780 llvm::is_contained(MapModifiers, clang::OMPC_MAP_MODIFIER_present);
9781 bool HasAllocsR = MapType == OMPC_MAP_alloc;
9782 return (HasPresent && !HasPresentR) || (HasAllocs && !HasAllocsR);
9818 void addImplicitMapForAttachPtrBaseIfMemberOfCapturedVD(
9819 const ValueDecl *CapturedVD, MapDataArrayTy &DeclComponentLists,
9821 SmallVector<OMPClauseMappableExprCommon::MappableComponent, 8>>
9822 &ComponentVectorStorage)
const {
9823 bool IsThisCapture = CapturedVD ==
nullptr;
9825 for (
const auto &ComponentsAndAttachPtr : AttachPtrExprMap) {
9827 ComponentsWithAttachPtr = ComponentsAndAttachPtr.first;
9828 const Expr *AttachPtrExpr = ComponentsAndAttachPtr.second;
9832 const auto *ME = dyn_cast<MemberExpr>(AttachPtrExpr);
9836 const Expr *
Base = ME->getBase()->IgnoreParenImpCasts();
9857 bool FoundExistingMap =
false;
9858 for (
const MapData &ExistingL : DeclComponentLists) {
9860 ExistingComponents = std::get<0>(ExistingL);
9862 if (ExistingComponents.empty())
9866 const auto &FirstComponent = ExistingComponents.front();
9867 const Expr *FirstExpr = FirstComponent.getAssociatedExpression();
9873 if (AttachPtrComparator.areEqual(FirstExpr, AttachPtrExpr)) {
9874 FoundExistingMap =
true;
9879 if (IsThisCapture) {
9880 if (
const auto *OASE = dyn_cast<ArraySectionExpr>(FirstExpr)) {
9882 FoundExistingMap =
true;
9891 if (
const auto *DRE = dyn_cast<DeclRefExpr>(FirstExpr)) {
9892 if (DRE->getDecl() == CapturedVD) {
9893 FoundExistingMap =
true;
9899 if (FoundExistingMap)
9905 ComponentVectorStorage.emplace_back();
9906 auto &AttachPtrComponents = ComponentVectorStorage.back();
9909 bool SeenAttachPtrComponent =
false;
9915 for (
size_t i = 0; i < ComponentsWithAttachPtr.size(); ++i) {
9916 const auto &Component = ComponentsWithAttachPtr[i];
9917 const Expr *ComponentExpr = Component.getAssociatedExpression();
9919 if (!SeenAttachPtrComponent && ComponentExpr != AttachPtrExpr)
9921 SeenAttachPtrComponent =
true;
9923 AttachPtrComponents.emplace_back(Component.getAssociatedExpression(),
9924 Component.getAssociatedDeclaration(),
9925 Component.isNonContiguous());
9927 assert(!AttachPtrComponents.empty() &&
9928 "Could not populate component-lists for mapping attach-ptr");
9930 DeclComponentLists.emplace_back(
9931 AttachPtrComponents, OMPC_MAP_tofrom,
Unknown,
9932 true,
nullptr, AttachPtrExpr);
9939 void generateInfoForCaptureFromClauseInfo(
9940 const MapDataArrayTy &DeclComponentListsFromClauses,
9941 const CapturedStmt::Capture *Cap, llvm::Value *Arg,
9942 MapCombinedInfoTy &CurCaptureVarInfo, llvm::OpenMPIRBuilder &OMPBuilder,
9943 unsigned OffsetForMemberOfFlag)
const {
9945 "Not expecting to generate map info for a variable array type!");
9954 if (LambdasMap.count(VD))
9960 if (VD && (DevPointersMap.count(VD) || HasDevAddrsMap.count(VD))) {
9961 CurCaptureVarInfo.Exprs.push_back(VD);
9962 CurCaptureVarInfo.BasePointers.emplace_back(Arg);
9963 CurCaptureVarInfo.DevicePtrDecls.emplace_back(VD);
9964 CurCaptureVarInfo.DevicePointers.emplace_back(DeviceInfoTy::Pointer);
9965 CurCaptureVarInfo.Pointers.push_back(Arg);
9966 CurCaptureVarInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
9969 CurCaptureVarInfo.Types.push_back(
9970 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL |
9971 OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM);
9972 CurCaptureVarInfo.HasAttachPtr.push_back(
false);
9973 CurCaptureVarInfo.Mappers.push_back(
nullptr);
9977 auto GenerateInfoForComponentLists =
9978 [&](ArrayRef<MapData> DeclComponentListsFromClauses,
9979 bool IsEligibleForTargetParamFlag) {
9980 MapCombinedInfoTy CurInfoForComponentLists;
9981 StructRangeInfoTy PartialStruct;
9982 AttachInfoTy AttachInfo;
9984 if (DeclComponentListsFromClauses.empty())
9987 generateInfoForCaptureFromComponentLists(
9988 VD, DeclComponentListsFromClauses, CurInfoForComponentLists,
9989 PartialStruct, AttachInfo, IsEligibleForTargetParamFlag);
9994 if (PartialStruct.Base.isValid()) {
9995 CurCaptureVarInfo.append(PartialStruct.PreliminaryMapData);
9997 CurCaptureVarInfo, CurInfoForComponentLists.Types,
9998 PartialStruct, AttachInfo, Cap->
capturesThis(), OMPBuilder,
9999 nullptr, OffsetForMemberOfFlag,
10000 !IsEligibleForTargetParamFlag);
10005 CurCaptureVarInfo.append(CurInfoForComponentLists);
10006 if (AttachInfo.isValid())
10007 emitAttachEntry(CGF, CurCaptureVarInfo, AttachInfo);
10031 SmallVector<std::pair<const Expr *, MapData>, 16> AttachPtrMapDataPairs;
10033 for (
const MapData &L : DeclComponentListsFromClauses) {
10036 const Expr *AttachPtrExpr = getAttachPtrExpr(Components);
10037 AttachPtrMapDataPairs.emplace_back(AttachPtrExpr, L);
10041 llvm::stable_sort(AttachPtrMapDataPairs,
10042 [
this](
const auto &LHS,
const auto &RHS) {
10043 return AttachPtrComparator(LHS.first, RHS.first);
10046 bool NoDefaultMappingDoneForVD = CurCaptureVarInfo.BasePointers.empty();
10047 bool IsFirstGroup =
true;
10051 auto *It = AttachPtrMapDataPairs.begin();
10052 while (It != AttachPtrMapDataPairs.end()) {
10053 const Expr *AttachPtrExpr = It->first;
10055 MapDataArrayTy GroupLists;
10056 while (It != AttachPtrMapDataPairs.end() &&
10057 (It->first == AttachPtrExpr ||
10058 AttachPtrComparator.areEqual(It->first, AttachPtrExpr))) {
10059 GroupLists.push_back(It->second);
10062 assert(!GroupLists.empty() &&
"GroupLists should not be empty");
10067 bool IsEligibleForTargetParamFlag =
10068 IsFirstGroup && NoDefaultMappingDoneForVD;
10070 GenerateInfoForComponentLists(GroupLists, IsEligibleForTargetParamFlag);
10071 IsFirstGroup =
false;
10078 void generateInfoForCaptureFromComponentLists(
10079 const ValueDecl *VD, ArrayRef<MapData> DeclComponentLists,
10080 MapCombinedInfoTy &CurComponentListInfo, StructRangeInfoTy &PartialStruct,
10081 AttachInfoTy &AttachInfo,
bool IsListEligibleForTargetParamFlag)
const {
10083 llvm::SmallDenseMap<
10090 for (
const MapData &L : DeclComponentLists) {
10093 ArrayRef<OpenMPMapModifierKind> MapModifiers;
10095 const ValueDecl *Mapper;
10096 const Expr *VarRef;
10097 std::tie(Components, MapType, MapModifiers, IsImplicit, Mapper, VarRef) =
10100 for (
const MapData &L1 : ArrayRef(DeclComponentLists).slice(Count)) {
10102 std::tie(Components1, MapType, MapModifiers, IsImplicit, Mapper,
10104 auto CI = Components.rbegin();
10105 auto CE = Components.rend();
10106 auto SI = Components1.rbegin();
10107 auto SE = Components1.rend();
10108 for (; CI != CE && SI != SE; ++CI, ++SI) {
10109 if (CI->getAssociatedExpression()->getStmtClass() !=
10110 SI->getAssociatedExpression()->getStmtClass())
10113 if (CI->getAssociatedDeclaration() != SI->getAssociatedDeclaration())
10118 if (CI == CE || SI == SE) {
10120 if (CI == CE && SI == SE)
10122 const auto It = (SI == SE) ? CI : SI;
10129 (std::prev(It)->getAssociatedDeclaration() &&
10131 ->getAssociatedDeclaration()
10133 ->isPointerType()) ||
10134 (It->getAssociatedDeclaration() &&
10135 It->getAssociatedDeclaration()->getType()->isPointerType() &&
10136 std::next(It) != CE && std::next(It) != SE))
10138 const MapData &BaseData = CI == CE ? L : L1;
10140 SI == SE ? Components : Components1;
10141 OverlappedData[&BaseData].push_back(SubData);
10146 llvm::SmallVector<const FieldDecl *, 4> Layout;
10147 if (!OverlappedData.empty()) {
10150 while (BaseType != OrigType) {
10156 getPlainLayout(CRD, Layout,
false);
10162 for (
auto &Pair : OverlappedData) {
10169 auto CI = First.rbegin();
10170 auto CE = First.rend();
10171 auto SI = Second.rbegin();
10172 auto SE = Second.rend();
10173 for (; CI != CE && SI != SE; ++CI, ++SI) {
10174 if (CI->getAssociatedExpression()->getStmtClass() !=
10175 SI->getAssociatedExpression()->getStmtClass())
10178 if (CI->getAssociatedDeclaration() !=
10179 SI->getAssociatedDeclaration())
10184 if (CI == CE && SI == SE)
10188 if (CI == CE || SI == SE)
10193 if (FD1->getParent() == FD2->getParent())
10194 return FD1->getFieldIndex() < FD2->getFieldIndex();
10196 llvm::find_if(Layout, [FD1, FD2](
const FieldDecl *FD) {
10197 return FD == FD1 || FD == FD2;
10205 bool AddTargetParamFlag = IsListEligibleForTargetParamFlag;
10206 MapCombinedInfoTy StructBaseCombinedInfo;
10207 for (
const auto &Pair : OverlappedData) {
10208 const MapData &L = *Pair.getFirst();
10211 ArrayRef<OpenMPMapModifierKind> MapModifiers;
10213 const ValueDecl *Mapper;
10214 const Expr *VarRef;
10215 std::tie(Components, MapType, MapModifiers, IsImplicit, Mapper, VarRef) =
10217 ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef>
10218 OverlappedComponents = Pair.getSecond();
10219 generateInfoForComponentList(
10220 MapType, MapModifiers, {}, Components, CurComponentListInfo,
10221 StructBaseCombinedInfo, PartialStruct, AttachInfo, AddTargetParamFlag,
10222 IsImplicit,
false, Mapper,
10223 false, VD, VarRef, OverlappedComponents);
10224 AddTargetParamFlag =
false;
10227 for (
const MapData &L : DeclComponentLists) {
10230 ArrayRef<OpenMPMapModifierKind> MapModifiers;
10232 const ValueDecl *Mapper;
10233 const Expr *VarRef;
10234 std::tie(Components, MapType, MapModifiers, IsImplicit, Mapper, VarRef) =
10236 auto It = OverlappedData.find(&L);
10237 if (It == OverlappedData.end())
10238 generateInfoForComponentList(
10239 MapType, MapModifiers, {}, Components, CurComponentListInfo,
10240 StructBaseCombinedInfo, PartialStruct, AttachInfo,
10241 AddTargetParamFlag, IsImplicit,
false,
10242 Mapper,
false, VD, VarRef,
10244 AddTargetParamFlag =
false;
10250 bool isEffectivelyFirstprivate(
const VarDecl *VD, QualType
Type)
const {
10252 auto I = FirstPrivateDecls.find(VD);
10253 if (I != FirstPrivateDecls.end() && !I->getSecond())
10257 if (DefaultmapFirstprivateKinds.count(OMPC_DEFAULTMAP_scalar)) {
10258 if (
Type->isScalarType())
10263 if (DefaultmapFirstprivateKinds.count(OMPC_DEFAULTMAP_pointer)) {
10264 if (
Type->isAnyPointerType())
10269 if (DefaultmapFirstprivateKinds.count(OMPC_DEFAULTMAP_aggregate)) {
10270 if (
Type->isAggregateType())
10275 return DefaultmapFirstprivateKinds.count(OMPC_DEFAULTMAP_all);
10280 void generateDefaultMapInfo(
const CapturedStmt::Capture &CI,
10281 const FieldDecl &RI, llvm::Value *CV,
10282 MapCombinedInfoTy &CombinedInfo)
const {
10283 bool IsImplicit =
true;
10286 CombinedInfo.Exprs.push_back(
nullptr);
10287 CombinedInfo.BasePointers.push_back(CV);
10288 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
10289 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
10290 CombinedInfo.Pointers.push_back(CV);
10292 CombinedInfo.Sizes.push_back(
10296 CombinedInfo.Types.push_back(OpenMPOffloadMappingFlags::OMP_MAP_TO |
10297 OpenMPOffloadMappingFlags::OMP_MAP_FROM);
10301 CombinedInfo.BasePointers.push_back(CV);
10302 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
10303 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
10304 CombinedInfo.Pointers.push_back(CV);
10305 bool IsFirstprivate =
10311 CombinedInfo.Types.push_back(
10312 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL);
10313 CombinedInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
10315 }
else if (IsFirstprivate) {
10318 CombinedInfo.Types.push_back(
10319 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL);
10321 CombinedInfo.Sizes.push_back(llvm::Constant::getNullValue(CGF.
Int64Ty));
10325 CombinedInfo.Types.push_back(OpenMPOffloadMappingFlags::OMP_MAP_NONE);
10326 CombinedInfo.Sizes.push_back(llvm::Constant::getNullValue(CGF.
Int64Ty));
10328 auto I = FirstPrivateDecls.find(VD);
10329 if (I != FirstPrivateDecls.end())
10330 IsImplicit = I->getSecond();
10336 bool IsFirstprivate = isEffectivelyFirstprivate(VD, ElementType);
10338 CombinedInfo.BasePointers.push_back(CV);
10339 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
10340 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
10345 CombinedInfo.Pointers.push_back(CV);
10347 CombinedInfo.Sizes.push_back(llvm::Constant::getNullValue(CGF.
Int64Ty));
10348 CombinedInfo.Types.push_back(
10349 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL);
10351 CombinedInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
10356 CombinedInfo.Types.push_back(getMapModifiersForPrivateClauses(CI));
10357 CombinedInfo.Pointers.push_back(CV);
10359 auto I = FirstPrivateDecls.find(VD);
10360 if (I != FirstPrivateDecls.end())
10361 IsImplicit = I->getSecond();
10364 CombinedInfo.Types.back() |=
10365 OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM;
10369 CombinedInfo.Types.back() |= OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT;
10371 CombinedInfo.HasAttachPtr.push_back(
false);
10373 CombinedInfo.Mappers.push_back(
nullptr);
10385 dyn_cast<MemberExpr>(OASE->getBase()->IgnoreParenImpCasts()))
10386 return ME->getMemberDecl();
10392static llvm::Constant *
10394 MappableExprsHandler::MappingExprInfo &MapExprs) {
10397 if (!MapExprs.getMapDecl() && !MapExprs.getMapExpr())
10398 return OMPBuilder.getOrCreateDefaultSrcLocStr(SrcLocStrSize);
10401 if (!MapExprs.getMapDecl() && MapExprs.getMapExpr()) {
10405 Loc = MapExprs.getMapExpr()->getExprLoc();
10407 Loc = MapExprs.getMapDecl()->getLocation();
10410 std::string ExprName;
10411 if (MapExprs.getMapExpr()) {
10413 llvm::raw_string_ostream OS(ExprName);
10414 MapExprs.getMapExpr()->printPretty(OS,
nullptr, P);
10416 ExprName = MapExprs.getMapDecl()->getNameAsString();
10425 return OMPBuilder.getOrCreateSrcLocStr(
FileName, ExprName, PLoc.
getLine(),
10432 CodeGenFunction &CGF, MappableExprsHandler::MapCombinedInfoTy &CombinedInfo,
10434 bool IsNonContiguous =
false,
bool ForEndCall =
false) {
10437 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
10440 InsertPointTy CodeGenIP(CGF.
Builder.GetInsertBlock(),
10441 CGF.
Builder.GetInsertPoint());
10443 auto DeviceAddrCB = [&](
unsigned int I, llvm::Value *NewDecl) {
10444 if (
const ValueDecl *DevVD = CombinedInfo.DevicePtrDecls[I]) {
10449 auto CustomMapperCB = [&](
unsigned int I) {
10450 llvm::Function *MFunc =
nullptr;
10451 if (CombinedInfo.Mappers[I]) {
10452 Info.HasMapper =
true;
10458 cantFail(OMPBuilder.emitOffloadingArraysAndArgs(
10459 AllocaIP, CodeGenIP, Info, Info.RTArgs, CombinedInfo, CustomMapperCB,
10460 IsNonContiguous, ForEndCall, DeviceAddrCB));
10464static const OMPExecutableDirective *
10466 const auto *CS = D.getInnermostCapturedStmt();
10469 const Stmt *ChildStmt =
10472 if (
const auto *NestedDir =
10473 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) {
10475 switch (D.getDirectiveKind()) {
10481 if (DKind == OMPD_teams) {
10482 Body = NestedDir->getInnermostCapturedStmt()->IgnoreContainers(
10487 if (
const auto *NND =
10488 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) {
10489 DKind = NND->getDirectiveKind();
10495 case OMPD_target_teams:
10499 case OMPD_target_parallel:
10500 case OMPD_target_simd:
10501 case OMPD_target_parallel_for:
10502 case OMPD_target_parallel_for_simd:
10504 case OMPD_target_teams_distribute:
10505 case OMPD_target_teams_distribute_simd:
10506 case OMPD_target_teams_distribute_parallel_for:
10507 case OMPD_target_teams_distribute_parallel_for_simd:
10508 case OMPD_parallel:
10510 case OMPD_parallel_for:
10511 case OMPD_parallel_master:
10512 case OMPD_parallel_sections:
10513 case OMPD_for_simd:
10514 case OMPD_parallel_for_simd:
10516 case OMPD_cancellation_point:
10517 case OMPD_ordered_standalone:
10518 case OMPD_ordered_blockassoc:
10519 case OMPD_threadprivate:
10520 case OMPD_allocate:
10525 case OMPD_sections:
10529 case OMPD_critical:
10530 case OMPD_taskyield:
10532 case OMPD_taskwait:
10533 case OMPD_taskgroup:
10539 case OMPD_target_data:
10540 case OMPD_target_exit_data:
10541 case OMPD_target_enter_data:
10542 case OMPD_distribute:
10543 case OMPD_distribute_simd:
10544 case OMPD_distribute_parallel_for:
10545 case OMPD_distribute_parallel_for_simd:
10546 case OMPD_teams_distribute:
10547 case OMPD_teams_distribute_simd:
10548 case OMPD_teams_distribute_parallel_for:
10549 case OMPD_teams_distribute_parallel_for_simd:
10550 case OMPD_target_update:
10551 case OMPD_declare_simd:
10552 case OMPD_declare_variant:
10553 case OMPD_begin_declare_variant:
10554 case OMPD_end_declare_variant:
10555 case OMPD_declare_target:
10556 case OMPD_end_declare_target:
10557 case OMPD_declare_reduction:
10558 case OMPD_declare_mapper:
10559 case OMPD_taskloop:
10560 case OMPD_taskloop_simd:
10561 case OMPD_master_taskloop:
10562 case OMPD_master_taskloop_simd:
10563 case OMPD_parallel_master_taskloop:
10564 case OMPD_parallel_master_taskloop_simd:
10565 case OMPD_requires:
10566 case OMPD_metadirective:
10569 llvm_unreachable(
"Unexpected directive.");
10629 if (
UDMMap.count(D) > 0)
10633 auto *MapperVarDecl =
10635 CharUnits ElementSize =
C.getTypeSizeInChars(Ty);
10636 llvm::Type *ElemTy =
CGM.getTypes().ConvertTypeForMem(Ty);
10639 MappableExprsHandler::MapCombinedInfoTy CombinedInfo;
10640 auto PrivatizeAndGenMapInfoCB =
10641 [&](llvm::OpenMPIRBuilder::InsertPointTy CodeGenIP, llvm::Value *PtrPHI,
10642 llvm::Value *BeginArg) -> llvm::OpenMPIRBuilder::MapInfosTy & {
10643 MapperCGF.
Builder.restoreIP(CodeGenIP);
10653 Scope.addPrivate(MapperVarDecl, PtrCurrent);
10654 (void)
Scope.Privatize();
10657 MappableExprsHandler MEHandler(*D, MapperCGF);
10658 MEHandler.generateAllInfoForMapper(CombinedInfo,
OMPBuilder);
10660 auto FillInfoMap = [&](MappableExprsHandler::MappingExprInfo &MapExpr) {
10663 if (
CGM.getCodeGenOpts().getDebugInfo() !=
10664 llvm::codegenoptions::NoDebugInfo) {
10665 CombinedInfo.Names.resize(CombinedInfo.Exprs.size());
10666 llvm::transform(CombinedInfo.Exprs, CombinedInfo.Names.begin(),
10670 return CombinedInfo;
10673 auto CustomMapperCB = [&](
unsigned I) {
10674 llvm::Function *MapperFunc =
nullptr;
10675 if (CombinedInfo.Mappers[I]) {
10679 assert(MapperFunc &&
"Expect a valid mapper function is available.");
10685 llvm::raw_svector_ostream Out(TyStr);
10686 CGM.getCXXABI().getMangleContext().mangleCanonicalTypeName(Ty, Out);
10687 std::string Name =
getName({
"omp_mapper", TyStr, D->
getName()});
10693 bool PropagatePresentToPointee =
CGM.getLangOpts().OpenMP >= 60;
10694 llvm::Function *NewFn = cantFail(
OMPBuilder.emitUserDefinedMapper(
10695 PrivatizeAndGenMapInfoCB, ElemTy, Name, CustomMapperCB,
10696 false, PropagatePresentToPointee));
10697 UDMMap.try_emplace(D, NewFn);
10704 auto I =
UDMMap.find(D);
10708 return UDMMap.lookup(D);
10721 Kind != OMPD_target_teams_loop)
10724 return llvm::ConstantInt::get(CGF.
Int64Ty, 0);
10727 if (llvm::Value *NumIterations = SizeEmitter(CGF, *LD))
10728 return NumIterations;
10729 return llvm::ConstantInt::get(CGF.
Int64Ty, 0);
10738 if (OffloadingMandatory) {
10739 CGF.
Builder.CreateUnreachable();
10741 if (RequiresOuterTask) {
10742 CapturedVars.clear();
10746 CapturedVars.end());
10747 Args.push_back(llvm::Constant::getNullValue(CGF.
Builder.getPtrTy()));
10754 llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier>
Device,
10757 llvm::Value *DeviceID;
10758 if (
Device.getPointer()) {
10760 Device.getInt() == OMPC_DEVICE_device_num) &&
10761 "Expected device_num modifier.");
10766 DeviceID = CGF.
Builder.getInt64(OMP_DEVICEID_UNDEF);
10771static std::pair<llvm::Value *, OMPDynGroupprivateFallbackType>
10773 llvm::Value *DynGP = CGF.
Builder.getInt32(0);
10774 auto DynGPFallback = OMPDynGroupprivateFallbackType::Abort;
10778 llvm::Value *DynGPVal =
10782 auto FallbackModifier = DynGPClause->getDynGroupprivateFallbackModifier();
10783 switch (FallbackModifier) {
10784 case OMPC_DYN_GROUPPRIVATE_FALLBACK_abort:
10785 DynGPFallback = OMPDynGroupprivateFallbackType::Abort;
10787 case OMPC_DYN_GROUPPRIVATE_FALLBACK_null:
10788 DynGPFallback = OMPDynGroupprivateFallbackType::Null;
10790 case OMPC_DYN_GROUPPRIVATE_FALLBACK_default_mem:
10793 DynGPFallback = OMPDynGroupprivateFallbackType::DefaultMem;
10796 llvm_unreachable(
"Unknown fallback modifier for OpenMP dyn_groupprivate");
10798 }
else if (
auto *OMPXDynCGClause =
10801 llvm::Value *DynCGMemVal = CGF.
EmitScalarExpr(OMPXDynCGClause->getSize(),
10806 return {DynGP, DynGPFallback};
10812 llvm::OpenMPIRBuilder &OMPBuilder,
10814 MappableExprsHandler::MapCombinedInfoTy &CombinedInfo) {
10816 llvm::DenseMap<llvm::Value *, llvm::Value *> LambdaPointers;
10818 auto *CV = CapturedVars.begin();
10821 CI != CE; ++CI, ++RI, ++CV) {
10822 MappableExprsHandler::MapCombinedInfoTy CurInfo;
10827 CurInfo.Exprs.push_back(
nullptr);
10828 CurInfo.BasePointers.push_back(*CV);
10829 CurInfo.DevicePtrDecls.push_back(
nullptr);
10830 CurInfo.DevicePointers.push_back(
10831 MappableExprsHandler::DeviceInfoTy::None);
10832 CurInfo.Pointers.push_back(*CV);
10833 CurInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
10836 CurInfo.Types.push_back(OpenMPOffloadMappingFlags::OMP_MAP_LITERAL |
10837 OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM |
10838 OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT);
10839 CurInfo.HasAttachPtr.push_back(
false);
10840 CurInfo.Mappers.push_back(
nullptr);
10845 bool HasEntryWithCVAsAttachPtr =
false;
10847 HasEntryWithCVAsAttachPtr =
10848 MEHandler.hasAttachEntryForCapturedVar(CapturedVD);
10851 MappableExprsHandler::MapDataArrayTy DeclComponentLists;
10854 StorageForImplicitlyAddedComponentLists;
10855 MEHandler.populateComponentListsForNonLambdaCaptureFromClauses(
10856 CapturedVD, DeclComponentLists,
10857 StorageForImplicitlyAddedComponentLists);
10868 bool HasEntryWithoutAttachPtr =
10869 llvm::any_of(DeclComponentLists, [&](
const auto &MapData) {
10871 Components = std::get<0>(MapData);
10872 return !MEHandler.getAttachPtrExpr(Components);
10877 if (DeclComponentLists.empty() ||
10878 (!HasEntryWithCVAsAttachPtr && !HasEntryWithoutAttachPtr))
10879 MEHandler.generateDefaultMapInfo(*CI, **RI, *CV, CurInfo);
10883 MEHandler.generateInfoForCaptureFromClauseInfo(
10884 DeclComponentLists, CI, *CV, CurInfo, OMPBuilder,
10885 CombinedInfo.BasePointers.size());
10890 MappedVarSet.insert(
nullptr);
10895 MEHandler.generateInfoForLambdaCaptures(CI->
getCapturedVar(), *CV,
10896 CurInfo, LambdaPointers);
10899 assert(!CurInfo.BasePointers.empty() &&
10900 "Non-existing map pointer for capture!");
10901 assert(CurInfo.BasePointers.size() == CurInfo.Pointers.size() &&
10902 CurInfo.BasePointers.size() == CurInfo.Sizes.size() &&
10903 CurInfo.BasePointers.size() == CurInfo.Types.size() &&
10904 CurInfo.BasePointers.size() == CurInfo.Mappers.size() &&
10905 "Inconsistent map information sizes!");
10908 CombinedInfo.append(CurInfo);
10911 MEHandler.adjustMemberOfForLambdaCaptures(
10912 OMPBuilder, LambdaPointers, CombinedInfo.BasePointers,
10913 CombinedInfo.Pointers, CombinedInfo.Types);
10917 MappableExprsHandler::MapCombinedInfoTy &CombinedInfo,
10918 llvm::OpenMPIRBuilder &OMPBuilder,
10925 MEHandler.generateAllInfo(CombinedInfo, OMPBuilder, SkippedVarSet);
10927 auto FillInfoMap = [&](MappableExprsHandler::MappingExprInfo &MapExpr) {
10931 llvm::codegenoptions::NoDebugInfo) {
10932 CombinedInfo.Names.resize(CombinedInfo.Exprs.size());
10933 llvm::transform(CombinedInfo.Exprs, CombinedInfo.Names.begin(),
10941 llvm::OpenMPIRBuilder &OMPBuilder,
10942 MappableExprsHandler::MapCombinedInfoTy &CombinedInfo) {
10944 MappableExprsHandler MEHandler(D, CGF);
10945 llvm::DenseSet<CanonicalDeclPtr<const Decl>> MappedVarSet;
10948 MappedVarSet, CombinedInfo);
10949 genMapInfo(MEHandler, CGF, CombinedInfo, OMPBuilder, MappedVarSet);
10952template <
typename ClauseTy>
10957 const auto *
C = D.getSingleClause<ClauseTy>();
10958 assert(!
C->varlist_empty() &&
10959 "ompx_bare requires explicit num_teams and thread_limit");
10961 for (
auto *E :
C->varlist()) {
10973 llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier>
Device,
10975 llvm::Value *&MapTypesArray, llvm::Value *&MapNamesArray,
10980 llvm::OpenMPIRBuilder &OMPBuilder = OMPRuntime->
getOMPBuilder();
10983 MappableExprsHandler::MapCombinedInfoTy CombinedInfo;
10985 genMapInfo(D, CGF, CS, CapturedVars, OMPBuilder, CombinedInfo);
10988 using OpenMPOffloadMappingFlags = llvm::omp::OpenMPOffloadMappingFlags;
10989 auto *NullPtr = llvm::Constant::getNullValue(CGF.
Builder.getPtrTy());
10990 CombinedInfo.BasePointers.push_back(NullPtr);
10991 CombinedInfo.Pointers.push_back(NullPtr);
10992 CombinedInfo.DevicePointers.push_back(
10993 llvm::OpenMPIRBuilder::DeviceInfoTy::None);
10994 CombinedInfo.Sizes.push_back(CGF.
Builder.getInt64(0));
10995 CombinedInfo.Types.push_back(OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM |
10996 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL);
10997 CombinedInfo.HasAttachPtr.push_back(
false);
10998 if (!CombinedInfo.Names.empty())
10999 CombinedInfo.Names.push_back(NullPtr);
11000 CombinedInfo.Exprs.push_back(
nullptr);
11001 CombinedInfo.Mappers.push_back(
nullptr);
11002 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
11016 MapTypesArray = Info.RTArgs.MapTypesArray;
11017 MapNamesArray = Info.RTArgs.MapNamesArray;
11019 auto &&ThenGen = [&OMPRuntime, OutlinedFn, &D, &CapturedVars,
11020 RequiresOuterTask, &CS, OffloadingMandatory,
Device,
11021 OutlinedFnID, &InputInfo, &MapTypesArray, &MapNamesArray,
11023 bool IsReverseOffloading =
Device.getInt() == OMPC_DEVICE_ancestor;
11025 if (IsReverseOffloading) {
11031 RequiresOuterTask, CS, OffloadingMandatory, CGF);
11035 bool HasNoWait = D.hasClausesOfKind<OMPNowaitClause>();
11036 unsigned NumTargetItems = InputInfo.NumberOfTargetItems;
11038 llvm::Value *BasePointersArray =
11039 InputInfo.BasePointersArray.emitRawPointer(CGF);
11040 llvm::Value *PointersArray = InputInfo.PointersArray.emitRawPointer(CGF);
11041 llvm::Value *SizesArray = InputInfo.SizesArray.emitRawPointer(CGF);
11042 llvm::Value *MappersArray = InputInfo.MappersArray.emitRawPointer(CGF);
11044 auto &&EmitTargetCallFallbackCB =
11045 [&OMPRuntime, OutlinedFn, &D, &CapturedVars, RequiresOuterTask, &CS,
11046 OffloadingMandatory, &CGF](llvm::OpenMPIRBuilder::InsertPointTy IP)
11047 -> llvm::OpenMPIRBuilder::InsertPointTy {
11050 RequiresOuterTask, CS, OffloadingMandatory, CGF);
11063 NumThreads.push_back(
11069 llvm::Value *NumIterations =
11072 llvm::OpenMPIRBuilder::InsertPointTy AllocaIP(
11075 llvm::OpenMPIRBuilder::TargetDataRTArgs RTArgs(
11076 BasePointersArray, PointersArray, SizesArray, MapTypesArray,
11077 nullptr , MappersArray, MapNamesArray);
11079 llvm::OpenMPIRBuilder::TargetKernelArgs Args(
11080 NumTargetItems, RTArgs, NumIterations, NumTeams, NumThreads,
11081 DynCGroupMem, HasNoWait, IsBare,
11082 IsBare, DynCGroupMemFallback);
11084 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
11086 CGF.
Builder, OutlinedFnID, EmitTargetCallFallbackCB, Args, DeviceID,
11088 CGF.
Builder.restoreIP(AfterIP);
11091 if (RequiresOuterTask)
11106 [&OMPRuntime, OutlinedFn, &D, &CapturedVars, RequiresOuterTask, &CS,
11109 RequiresOuterTask, CS, OffloadingMandatory, CGF);
11112 if (RequiresOuterTask) {
11122 llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID,
const Expr *IfCond,
11123 llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier>
Device,
11130 const bool OffloadingMandatory = !
CGM.getLangOpts().OpenMPIsTargetDevice &&
11131 CGM.getLangOpts().OpenMPOffloadMandatory;
11133 assert((OffloadingMandatory || OutlinedFn) &&
"Invalid outlined function!");
11135 const bool RequiresOuterTask =
11137 D.hasClausesOfKind<OMPNowaitClause>() ||
11138 D.hasClausesOfKind<OMPInReductionClause>() ||
11139 (
CGM.getLangOpts().OpenMP >= 51 &&
11143 const CapturedStmt &CS = *D.getCapturedStmt(OMPD_target);
11151 llvm::Value *MapTypesArray =
nullptr;
11152 llvm::Value *MapNamesArray =
nullptr;
11154 auto &&TargetThenGen = [
this, OutlinedFn, &D, &CapturedVars,
11155 RequiresOuterTask, &CS, OffloadingMandatory,
Device,
11156 OutlinedFnID, &InputInfo, &MapTypesArray,
11160 RequiresOuterTask, CS, OffloadingMandatory,
11161 Device, OutlinedFnID, InputInfo, MapTypesArray,
11162 MapNamesArray, SizeEmitter, CGF,
CGM);
11165 auto &&TargetElseGen =
11166 [
this, OutlinedFn, &D, &CapturedVars, RequiresOuterTask, &CS,
11169 CS, OffloadingMandatory, CGF);
11176 if (OutlinedFnID) {
11178 emitIfClause(CGF, IfCond, TargetThenGen, TargetElseGen);
11190 StringRef ParentName) {
11197 if (
auto *E = dyn_cast<OMPExecutableDirective>(S);
11206 bool RequiresDeviceCodegen =
11211 if (RequiresDeviceCodegen) {
11219 if (!
OMPBuilder.OffloadInfoManager.hasTargetRegionEntryInfo(EntryInfo))
11222 switch (E.getDirectiveKind()) {
11227 case OMPD_target_parallel:
11231 case OMPD_target_teams:
11235 case OMPD_target_teams_distribute:
11239 case OMPD_target_teams_distribute_simd:
11243 case OMPD_target_parallel_for:
11247 case OMPD_target_parallel_for_simd:
11251 case OMPD_target_simd:
11255 case OMPD_target_teams_distribute_parallel_for:
11260 case OMPD_target_teams_distribute_parallel_for_simd:
11266 case OMPD_target_teams_loop:
11270 case OMPD_target_parallel_loop:
11274 case OMPD_parallel:
11276 case OMPD_parallel_for:
11277 case OMPD_parallel_master:
11278 case OMPD_parallel_sections:
11279 case OMPD_for_simd:
11280 case OMPD_parallel_for_simd:
11282 case OMPD_cancellation_point:
11283 case OMPD_ordered_standalone:
11284 case OMPD_ordered_blockassoc:
11285 case OMPD_threadprivate:
11286 case OMPD_allocate:
11291 case OMPD_sections:
11295 case OMPD_critical:
11296 case OMPD_taskyield:
11298 case OMPD_taskwait:
11299 case OMPD_taskgroup:
11305 case OMPD_target_data:
11306 case OMPD_target_exit_data:
11307 case OMPD_target_enter_data:
11308 case OMPD_distribute:
11309 case OMPD_distribute_simd:
11310 case OMPD_distribute_parallel_for:
11311 case OMPD_distribute_parallel_for_simd:
11312 case OMPD_teams_distribute:
11313 case OMPD_teams_distribute_simd:
11314 case OMPD_teams_distribute_parallel_for:
11315 case OMPD_teams_distribute_parallel_for_simd:
11316 case OMPD_target_update:
11317 case OMPD_declare_simd:
11318 case OMPD_declare_variant:
11319 case OMPD_begin_declare_variant:
11320 case OMPD_end_declare_variant:
11321 case OMPD_declare_target:
11322 case OMPD_end_declare_target:
11323 case OMPD_declare_reduction:
11324 case OMPD_declare_mapper:
11325 case OMPD_taskloop:
11326 case OMPD_taskloop_simd:
11327 case OMPD_master_taskloop:
11328 case OMPD_master_taskloop_simd:
11329 case OMPD_parallel_master_taskloop:
11330 case OMPD_parallel_master_taskloop_simd:
11331 case OMPD_requires:
11332 case OMPD_metadirective:
11335 llvm_unreachable(
"Unknown target directive for OpenMP device codegen.");
11340 if (
const auto *E = dyn_cast<OMPExecutableDirective>(S)) {
11341 if (!E->hasAssociatedStmt() || !E->getAssociatedStmt())
11349 if (
const auto *L = dyn_cast<LambdaExpr>(S))
11358 std::optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
11359 OMPDeclareTargetDeclAttr::getDeviceType(VD);
11363 if (!IsDevice && DevTy == OMPDeclareTargetDeclAttr::DT_NoHost)
11366 if (IsDevice && DevTy == OMPDeclareTargetDeclAttr::DT_Host)
11374 if (!
CGM.getLangOpts().OpenMPIsTargetDevice) {
11375 if (
const auto *FD = dyn_cast<FunctionDecl>(GD.
getDecl()))
11377 CGM.getLangOpts().OpenMPIsTargetDevice))
11384 if (
const auto *FD = dyn_cast<FunctionDecl>(VD)) {
11385 StringRef Name =
CGM.getMangledName(GD);
11388 CGM.getLangOpts().OpenMPIsTargetDevice))
11393 return !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD) &&
11399 CGM.getLangOpts().OpenMPIsTargetDevice))
11402 if (!
CGM.getLangOpts().OpenMPIsTargetDevice)
11411 StringRef ParentName =
11416 StringRef ParentName =
11423 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
11424 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(
11426 if (!Res || *Res == OMPDeclareTargetDeclAttr::MT_Link ||
11427 ((*Res == OMPDeclareTargetDeclAttr::MT_To ||
11428 *Res == OMPDeclareTargetDeclAttr::MT_Enter) &&
11437 llvm::Constant *
Addr) {
11438 if (
CGM.getLangOpts().OMPTargetTriples.empty() &&
11439 !
CGM.getLangOpts().OpenMPIsTargetDevice)
11442 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
11443 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
11447 if (Res && *Res != OMPDeclareTargetDeclAttr::MT_Link &&
11453 if (Res && *Res == OMPDeclareTargetDeclAttr::MT_Local)
11457 if (
CGM.getLangOpts().OpenMPIsTargetDevice) {
11460 StringRef VarName =
CGM.getMangledName(VD);
11466 auto AddrOfGlobal = [&VD,
this]() {
return CGM.GetAddrOfGlobal(VD); };
11467 auto LinkageForVariable = [&VD,
this]() {
11468 return CGM.getLLVMLinkageVarDefinition(VD);
11471 std::vector<llvm::GlobalVariable *> GeneratedRefs;
11478 CGM.getMangledName(VD), GeneratedRefs,
CGM.getLangOpts().OpenMPSimd,
11479 CGM.getLangOpts().OMPTargetTriples, AddrOfGlobal, LinkageForVariable,
11480 CGM.getTypes().ConvertTypeForMem(
11481 CGM.getContext().getPointerType(VD->
getType())),
11484 for (
auto *ref : GeneratedRefs)
11485 CGM.addCompilerUsedGlobal(ref);
11498 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
11499 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
11503 if (*Res == OMPDeclareTargetDeclAttr::MT_Local ||
11504 ((*Res == OMPDeclareTargetDeclAttr::MT_To ||
11505 *Res == OMPDeclareTargetDeclAttr::MT_Enter) &&
11507 CGM.EmitGlobal(VD);
11509 assert((*Res == OMPDeclareTargetDeclAttr::MT_Link ||
11510 ((*Res == OMPDeclareTargetDeclAttr::MT_To ||
11511 *Res == OMPDeclareTargetDeclAttr::MT_Enter ||
11512 *Res == OMPDeclareTargetDeclAttr::MT_Local) &&
11514 "Expected link clause or to clause with unified memory.");
11515 (void)
CGM.getOpenMPRuntime().getAddrOfDeclareTargetVar(VD);
11523 " Expected target-based directive.");
11528 if (Clause->getClauseKind() == OMPC_unified_shared_memory) {
11530 OMPBuilder.Config.setHasRequiresUnifiedSharedMemory(
true);
11531 }
else if (
const auto *AC =
11532 dyn_cast<OMPAtomicDefaultMemOrderClause>(Clause)) {
11533 switch (AC->getAtomicDefaultMemOrderKind()) {
11534 case OMPC_ATOMIC_DEFAULT_MEM_ORDER_acq_rel:
11537 case OMPC_ATOMIC_DEFAULT_MEM_ORDER_seq_cst:
11540 case OMPC_ATOMIC_DEFAULT_MEM_ORDER_relaxed:
11556 if (!VD || !VD->
hasAttr<OMPAllocateDeclAttr>())
11558 const auto *A = VD->
getAttr<OMPAllocateDeclAttr>();
11559 switch(A->getAllocatorType()) {
11560 case OMPAllocateDeclAttr::OMPNullMemAlloc:
11561 case OMPAllocateDeclAttr::OMPDefaultMemAlloc:
11563 case OMPAllocateDeclAttr::OMPLargeCapMemAlloc:
11564 case OMPAllocateDeclAttr::OMPCGroupMemAlloc:
11565 case OMPAllocateDeclAttr::OMPHighBWMemAlloc:
11566 case OMPAllocateDeclAttr::OMPLowLatMemAlloc:
11567 case OMPAllocateDeclAttr::OMPThreadMemAlloc:
11568 case OMPAllocateDeclAttr::OMPConstMemAlloc:
11569 case OMPAllocateDeclAttr::OMPPTeamMemAlloc:
11572 case OMPAllocateDeclAttr::OMPUserDefinedMemAlloc:
11573 llvm_unreachable(
"Expected predefined allocator for the variables with the "
11574 "static storage.");
11586 if (CGM.getLangOpts().OpenMPIsTargetDevice) {
11587 SavedShouldMarkAsGlobal = CGM.getOpenMPRuntime().ShouldMarkAsGlobal;
11588 CGM.getOpenMPRuntime().ShouldMarkAsGlobal = false;
11593 if (CGM.getLangOpts().OpenMPIsTargetDevice)
11594 CGM.getOpenMPRuntime().ShouldMarkAsGlobal = SavedShouldMarkAsGlobal;
11604 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(D)) {
11606 if (
auto *F = dyn_cast_or_null<llvm::Function>(
11607 CGM.GetGlobalValue(
CGM.getMangledName(GD))))
11608 return !F->isDeclaration();
11620 llvm::Function *OutlinedFn,
11629 llvm::Value *Args[] = {
11631 CGF.
Builder.getInt32(CapturedVars.size()),
11634 RealArgs.append(std::begin(Args), std::end(Args));
11635 RealArgs.append(CapturedVars.begin(), CapturedVars.end());
11637 llvm::FunctionCallee RTLFn =
OMPBuilder.getOrCreateRuntimeFunction(
11638 CGM.getModule(), OMPRTL___kmpc_fork_teams);
11643 const Expr *NumTeams,
11644 const Expr *ThreadLimit,
11651 llvm::Value *NumTeamsVal =
11657 llvm::Value *ThreadLimitVal =
11664 llvm::Value *PushNumTeamsArgs[] = {RTLoc,
getThreadID(CGF, Loc), NumTeamsVal,
11667 CGM.getModule(), OMPRTL___kmpc_push_num_teams),
11672 const Expr *ThreadLimit,
11675 llvm::Value *ThreadLimitVal =
11682 llvm::Value *ThreadLimitArgs[] = {RTLoc,
getThreadID(CGF, Loc),
11685 CGM.getModule(), OMPRTL___kmpc_set_thread_limit),
11700 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
11702 llvm::Value *IfCondVal =
nullptr;
11707 llvm::Value *DeviceID =
nullptr;
11712 DeviceID = CGF.
Builder.getInt64(OMP_DEVICEID_UNDEF);
11716 MappableExprsHandler::MapCombinedInfoTy CombinedInfo;
11717 auto GenMapInfoCB =
11718 [&](InsertPointTy CodeGenIP) -> llvm::OpenMPIRBuilder::MapInfosTy & {
11719 CGF.
Builder.restoreIP(CodeGenIP);
11721 MappableExprsHandler MEHandler(D, CGF);
11722 MEHandler.generateAllInfo(CombinedInfo,
OMPBuilder);
11724 auto FillInfoMap = [&](MappableExprsHandler::MappingExprInfo &MapExpr) {
11727 if (
CGM.getCodeGenOpts().getDebugInfo() !=
11728 llvm::codegenoptions::NoDebugInfo) {
11729 CombinedInfo.Names.resize(CombinedInfo.Exprs.size());
11730 llvm::transform(CombinedInfo.Exprs, CombinedInfo.Names.begin(),
11734 return CombinedInfo;
11736 using BodyGenTy = llvm::OpenMPIRBuilder::BodyGenTy;
11737 auto BodyCB = [&](InsertPointTy CodeGenIP, BodyGenTy BodyGenType) {
11738 CGF.
Builder.restoreIP(CodeGenIP);
11739 switch (BodyGenType) {
11740 case BodyGenTy::Priv:
11744 case BodyGenTy::DupNoPriv:
11746 CodeGen.setAction(NoPrivAction);
11750 case BodyGenTy::NoPriv:
11752 CodeGen.setAction(NoPrivAction);
11757 return InsertPointTy(CGF.
Builder.GetInsertBlock(),
11758 CGF.
Builder.GetInsertPoint());
11761 auto DeviceAddrCB = [&](
unsigned int I, llvm::Value *NewDecl) {
11762 if (
const ValueDecl *DevVD = CombinedInfo.DevicePtrDecls[I]) {
11767 auto CustomMapperCB = [&](
unsigned int I) {
11768 llvm::Function *MFunc =
nullptr;
11769 if (CombinedInfo.Mappers[I]) {
11770 Info.HasMapper =
true;
11782 InsertPointTy CodeGenIP(CGF.
Builder.GetInsertBlock(),
11783 CGF.
Builder.GetInsertPoint());
11784 llvm::OpenMPIRBuilder::LocationDescription OmpLoc(CodeGenIP);
11785 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
11787 OmpLoc, AllocaIP, CodeGenIP, {}, DeviceID,
11788 IfCondVal, Info, GenMapInfoCB, CustomMapperCB,
11789 nullptr, BodyCB, DeviceAddrCB, RTLoc));
11790 CGF.
Builder.restoreIP(AfterIP);
11802 "Expecting either target enter, exit data, or update directives.");
11805 llvm::Value *MapTypesArray =
nullptr;
11806 llvm::Value *MapNamesArray =
nullptr;
11808 auto &&ThenGen = [
this, &D,
Device, &InputInfo, &MapTypesArray,
11811 llvm::Value *DeviceID =
nullptr;
11816 DeviceID = CGF.
Builder.getInt64(OMP_DEVICEID_UNDEF);
11820 llvm::Constant *PointerNum =
11827 {RTLoc, DeviceID, PointerNum,
11835 const bool HasNowait = D.hasClausesOfKind<OMPNowaitClause>();
11836 RuntimeFunction RTLFn;
11837 switch (D.getDirectiveKind()) {
11838 case OMPD_target_enter_data:
11839 RTLFn = HasNowait ? OMPRTL___tgt_target_data_begin_nowait_mapper
11840 : OMPRTL___tgt_target_data_begin_mapper;
11842 case OMPD_target_exit_data:
11843 RTLFn = HasNowait ? OMPRTL___tgt_target_data_end_nowait_mapper
11844 : OMPRTL___tgt_target_data_end_mapper;
11846 case OMPD_target_update:
11847 RTLFn = HasNowait ? OMPRTL___tgt_target_data_update_nowait_mapper
11848 : OMPRTL___tgt_target_data_update_mapper;
11850 case OMPD_parallel:
11852 case OMPD_parallel_for:
11853 case OMPD_parallel_master:
11854 case OMPD_parallel_sections:
11855 case OMPD_for_simd:
11856 case OMPD_parallel_for_simd:
11858 case OMPD_cancellation_point:
11859 case OMPD_ordered_standalone:
11860 case OMPD_ordered_blockassoc:
11861 case OMPD_threadprivate:
11862 case OMPD_allocate:
11867 case OMPD_sections:
11871 case OMPD_critical:
11872 case OMPD_taskyield:
11874 case OMPD_taskwait:
11875 case OMPD_taskgroup:
11881 case OMPD_target_data:
11882 case OMPD_distribute:
11883 case OMPD_distribute_simd:
11884 case OMPD_distribute_parallel_for:
11885 case OMPD_distribute_parallel_for_simd:
11886 case OMPD_teams_distribute:
11887 case OMPD_teams_distribute_simd:
11888 case OMPD_teams_distribute_parallel_for:
11889 case OMPD_teams_distribute_parallel_for_simd:
11890 case OMPD_declare_simd:
11891 case OMPD_declare_variant:
11892 case OMPD_begin_declare_variant:
11893 case OMPD_end_declare_variant:
11894 case OMPD_declare_target:
11895 case OMPD_end_declare_target:
11896 case OMPD_declare_reduction:
11897 case OMPD_declare_mapper:
11898 case OMPD_taskloop:
11899 case OMPD_taskloop_simd:
11900 case OMPD_master_taskloop:
11901 case OMPD_master_taskloop_simd:
11902 case OMPD_parallel_master_taskloop:
11903 case OMPD_parallel_master_taskloop_simd:
11905 case OMPD_target_simd:
11906 case OMPD_target_teams_distribute:
11907 case OMPD_target_teams_distribute_simd:
11908 case OMPD_target_teams_distribute_parallel_for:
11909 case OMPD_target_teams_distribute_parallel_for_simd:
11910 case OMPD_target_teams:
11911 case OMPD_target_parallel:
11912 case OMPD_target_parallel_for:
11913 case OMPD_target_parallel_for_simd:
11914 case OMPD_requires:
11915 case OMPD_metadirective:
11918 llvm_unreachable(
"Unexpected standalone target data directive.");
11922 OffloadingArgs.push_back(llvm::Constant::getNullValue(CGF.
Int32Ty));
11923 OffloadingArgs.push_back(llvm::Constant::getNullValue(CGF.
VoidPtrTy));
11924 OffloadingArgs.push_back(llvm::Constant::getNullValue(CGF.
Int32Ty));
11925 OffloadingArgs.push_back(llvm::Constant::getNullValue(CGF.
VoidPtrTy));
11928 OMPBuilder.getOrCreateRuntimeFunction(
CGM.getModule(), RTLFn),
11932 auto &&TargetThenGen = [
this, &ThenGen, &D, &InputInfo, &MapTypesArray,
11936 MappableExprsHandler::MapCombinedInfoTy CombinedInfo;
11938 MappableExprsHandler MEHandler(D, CGF);
11944 D.hasClausesOfKind<OMPNowaitClause>();
11950 CGM.getPointerAlign());
11955 MapTypesArray = Info.RTArgs.MapTypesArray;
11956 MapNamesArray = Info.RTArgs.MapNamesArray;
11957 if (RequiresOuterTask)
12002 unsigned Offset = 0;
12003 if (
const auto *MD = dyn_cast<CXXMethodDecl>(FD)) {
12004 if (ParamAttrs[Offset].Kind ==
12005 llvm::OpenMPIRBuilder::DeclareSimdKindTy::Vector)
12006 CDT =
C.getPointerType(
C.getCanonicalTagType(MD->
getParent()));
12010 for (
unsigned I = 0, E = FD->
getNumParams(); I < E; ++I) {
12011 if (ParamAttrs[I + Offset].Kind ==
12012 llvm::OpenMPIRBuilder::DeclareSimdKindTy::Vector) {
12024 return C.getTypeSize(CDT);
12035 llvm::OpenMPIRBuilder::DeclareSimdKindTy Kind) {
12041 if (Kind == llvm::OpenMPIRBuilder::DeclareSimdKindTy::Uniform)
12044 if (Kind == llvm::OpenMPIRBuilder::DeclareSimdKindTy::LinearUVal ||
12045 Kind == llvm::OpenMPIRBuilder::DeclareSimdKindTy::LinearRef)
12048 if ((Kind == llvm::OpenMPIRBuilder::DeclareSimdKindTy::Linear ||
12049 Kind == llvm::OpenMPIRBuilder::DeclareSimdKindTy::LinearVal) &&
12059 unsigned Size =
C.getTypeSize(QT);
12062 if (Size != 8 && Size != 16 && Size != 32 && Size != 64 && Size != 128)
12083 llvm::OpenMPIRBuilder::DeclareSimdKindTy Kind,
12088 return C.getTypeSize(PTy);
12091 return C.getTypeSize(QT);
12093 return C.getTypeSize(
C.getUIntPtrType());
12099static std::tuple<unsigned, unsigned, bool>
12106 bool OutputBecomesInput =
false;
12111 RetType, llvm::OpenMPIRBuilder::DeclareSimdKindTy::Vector,
C));
12113 OutputBecomesInput =
true;
12115 for (
unsigned I = 0, E = FD->
getNumParams(); I < E; ++I) {
12120 assert(!Sizes.empty() &&
"Unable to determine NDS and WDS.");
12123 assert(llvm::all_of(Sizes,
12124 [](
unsigned Size) {
12125 return Size == 8 || Size == 16 || Size == 32 ||
12126 Size == 64 || Size == 128;
12130 return std::make_tuple(*llvm::min_element(Sizes), *llvm::max_element(Sizes),
12131 OutputBecomesInput);
12134static llvm::OpenMPIRBuilder::DeclareSimdBranch
12137 case OMPDeclareSimdDeclAttr::BS_Undefined:
12138 return llvm::OpenMPIRBuilder::DeclareSimdBranch::Undefined;
12139 case OMPDeclareSimdDeclAttr::BS_Inbranch:
12140 return llvm::OpenMPIRBuilder::DeclareSimdBranch::Inbranch;
12141 case OMPDeclareSimdDeclAttr::BS_Notinbranch:
12142 return llvm::OpenMPIRBuilder::DeclareSimdBranch::Notinbranch;
12144 llvm_unreachable(
"unexpected declare simd branch state");
12149 unsigned UserVLEN,
unsigned WDS,
char ISA) {
12151 if (UserVLEN == 1) {
12158 if (ISA ==
'n' && UserVLEN && !llvm::isPowerOf2_32(UserVLEN)) {
12164 if (ISA ==
's' && UserVLEN != 0 &&
12165 ((UserVLEN * WDS > 2048) || (UserVLEN * WDS % 128 != 0))) {
12174 llvm::Function *Fn) {
12179 llvm::DenseMap<const Decl *, unsigned> ParamPositions;
12181 ParamPositions.try_emplace(FD, 0);
12182 unsigned ParamPos = ParamPositions.size();
12184 ParamPositions.try_emplace(P->getCanonicalDecl(), ParamPos);
12189 ParamPositions.size());
12191 for (
const Expr *E :
Attr->uniforms()) {
12195 Pos = ParamPositions[FD];
12198 ->getCanonicalDecl();
12199 auto It = ParamPositions.find(PVD);
12200 assert(It != ParamPositions.end() &&
"Function parameter not found");
12203 ParamAttrs[Pos].Kind =
12204 llvm::OpenMPIRBuilder::DeclareSimdKindTy::Uniform;
12207 auto *NI =
Attr->alignments_begin();
12208 for (
const Expr *E :
Attr->aligneds()) {
12213 Pos = ParamPositions[FD];
12217 ->getCanonicalDecl();
12218 auto It = ParamPositions.find(PVD);
12219 assert(It != ParamPositions.end() &&
"Function parameter not found");
12221 ParmTy = PVD->getType();
12223 ParamAttrs[Pos].Alignment =
12225 ? (*NI)->EvaluateKnownConstInt(
C)
12226 : llvm::APSInt::getUnsigned(
12227 C.toCharUnitsFromBits(
C.getOpenMPDefaultSimdAlign(ParmTy))
12232 auto *SI =
Attr->steps_begin();
12233 auto *MI =
Attr->modifiers_begin();
12234 for (
const Expr *E :
Attr->linears()) {
12237 bool IsReferenceType =
false;
12240 unsigned PtrRescalingFactor = 1;
12242 Pos = ParamPositions[FD];
12244 PtrRescalingFactor =
CGM.getContext()
12245 .getTypeSizeInChars(P->getPointeeType())
12249 ->getCanonicalDecl();
12250 auto It = ParamPositions.find(PVD);
12251 assert(It != ParamPositions.end() &&
"Function parameter not found");
12253 if (
auto *P = dyn_cast<PointerType>(PVD->getType()))
12254 PtrRescalingFactor =
CGM.getContext()
12255 .getTypeSizeInChars(P->getPointeeType())
12257 else if (PVD->getType()->isReferenceType()) {
12258 IsReferenceType =
true;
12259 PtrRescalingFactor =
12261 .getTypeSizeInChars(PVD->getType().getNonReferenceType())
12265 llvm::OpenMPIRBuilder::DeclareSimdAttrTy &ParamAttr = ParamAttrs[Pos];
12266 if (*MI == OMPC_LINEAR_ref)
12267 ParamAttr.Kind = llvm::OpenMPIRBuilder::DeclareSimdKindTy::LinearRef;
12268 else if (*MI == OMPC_LINEAR_uval)
12269 ParamAttr.Kind = llvm::OpenMPIRBuilder::DeclareSimdKindTy::LinearUVal;
12270 else if (IsReferenceType)
12271 ParamAttr.Kind = llvm::OpenMPIRBuilder::DeclareSimdKindTy::LinearVal;
12273 ParamAttr.Kind = llvm::OpenMPIRBuilder::DeclareSimdKindTy::Linear;
12275 ParamAttr.StrideOrArg = llvm::APSInt::getUnsigned(1);
12279 if (
const auto *DRE =
12281 if (
const auto *StridePVD =
12282 dyn_cast<ParmVarDecl>(DRE->getDecl())) {
12283 ParamAttr.HasVarStride =
true;
12284 auto It = ParamPositions.find(StridePVD->getCanonicalDecl());
12285 assert(It != ParamPositions.end() &&
12286 "Function parameter not found");
12287 ParamAttr.StrideOrArg = llvm::APSInt::getUnsigned(It->second);
12291 ParamAttr.StrideOrArg =
Result.Val.getInt();
12297 if (!ParamAttr.HasVarStride &&
12299 llvm::OpenMPIRBuilder::DeclareSimdKindTy::Linear ||
12301 llvm::OpenMPIRBuilder::DeclareSimdKindTy::LinearRef))
12302 ParamAttr.StrideOrArg = ParamAttr.StrideOrArg * PtrRescalingFactor;
12306 llvm::APSInt VLENVal;
12308 const Expr *VLENExpr =
Attr->getSimdlen();
12313 llvm::OpenMPIRBuilder::DeclareSimdBranch State =
12315 if (
CGM.getTriple().isX86()) {
12317 assert(NumElts &&
"Non-zero simdlen/cdtsize expected");
12318 OMPBuilder.emitX86DeclareSimdFunction(Fn, NumElts, VLENVal, ParamAttrs,
12320 }
else if (
CGM.getTriple().getArch() == llvm::Triple::aarch64) {
12321 unsigned VLEN = VLENVal.getExtValue();
12324 const unsigned NDS = std::get<0>(
Data);
12325 const unsigned WDS = std::get<1>(
Data);
12326 const bool OutputBecomesInput = std::get<2>(
Data);
12327 if (
CGM.getTarget().hasFeature(
"sve")) {
12330 Fn, VLEN, ParamAttrs, State,
's', NDS, OutputBecomesInput);
12331 }
else if (
CGM.getTarget().hasFeature(
"neon")) {
12334 Fn, VLEN, ParamAttrs, State,
'n', NDS, OutputBecomesInput);
12344class DoacrossCleanupTy final :
public EHScopeStack::Cleanup {
12346 static const int DoacrossFinArgs = 2;
12349 llvm::FunctionCallee RTLFn;
12350 llvm::Value *Args[DoacrossFinArgs];
12353 DoacrossCleanupTy(llvm::FunctionCallee RTLFn,
12356 assert(CallArgs.size() == DoacrossFinArgs);
12357 std::copy(CallArgs.begin(), CallArgs.end(), std::begin(Args));
12374 QualType Int64Ty =
C.getIntTypeForBitwidth(64,
true);
12382 RD =
C.buildImplicitRecord(
"kmp_dim");
12390 RD =
KmpDimTy->castAsRecordDecl();
12392 llvm::APInt Size(32, NumIterations.size());
12398 enum { LowerFD = 0, UpperFD, StrideFD };
12400 for (
unsigned I = 0, E = NumIterations.size(); I < E; ++I) {
12405 DimsLVal, *std::next(RD->
field_begin(), UpperFD));
12407 CGF.
EmitScalarExpr(NumIterations[I]), NumIterations[I]->getType(),
12408 Int64Ty, NumIterations[I]->getExprLoc());
12412 DimsLVal, *std::next(RD->
field_begin(), StrideFD));
12419 llvm::Value *Args[] = {
12422 llvm::ConstantInt::getSigned(
CGM.Int32Ty, NumIterations.size()),
12427 llvm::FunctionCallee RTLFn =
OMPBuilder.getOrCreateRuntimeFunction(
12428 CGM.getModule(), OMPRTL___kmpc_doacross_init);
12430 llvm::Value *FiniArgs[DoacrossCleanupTy::DoacrossFinArgs] = {
12432 llvm::FunctionCallee FiniRTLFn =
OMPBuilder.getOrCreateRuntimeFunction(
12433 CGM.getModule(), OMPRTL___kmpc_doacross_fini);
12438template <
typename T>
12440 const T *
C, llvm::Value *ULoc,
12441 llvm::Value *ThreadID) {
12444 llvm::APInt Size(32,
C->getNumLoops());
12448 for (
unsigned I = 0, E =
C->getNumLoops(); I < E; ++I) {
12449 const Expr *CounterVal =
C->getLoopData(I);
12450 assert(CounterVal);
12457 llvm::Value *Args[] = {
12460 llvm::FunctionCallee RTLFn;
12462 OMPDoacrossKind<T> ODK;
12463 if (ODK.isSource(
C)) {
12465 OMPRTL___kmpc_doacross_post);
12467 assert(ODK.isSink(
C) &&
"Expect sink modifier.");
12469 OMPRTL___kmpc_doacross_wait);
12489 llvm::FunctionCallee Callee,
12491 assert(Loc.
isValid() &&
"Outlined function call location must be valid.");
12494 if (
auto *Fn = dyn_cast<llvm::Function>(Callee.getCallee())) {
12495 if (Fn->doesNotThrow()) {
12506 emitCall(CGF, Loc, OutlinedFn, Args);
12510 if (
const auto *FD = dyn_cast<FunctionDecl>(D))
12511 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(FD))
12517 const VarDecl *TargetParam)
const {
12524 const Expr *Allocator) {
12525 llvm::Value *AllocVal;
12535 AllocVal = llvm::Constant::getNullValue(
12545 if (!AllocateAlignment)
12548 return llvm::ConstantInt::get(
CGM.
SizeTy, AllocateAlignment->getQuantity());
12561 auto I = UntiedData.find(VD);
12562 if (I != UntiedData.end()) {
12563 UntiedAddr = I->second.first;
12564 UntiedRealAddr = I->second.second;
12568 if (CVD->
hasAttr<OMPAllocateDeclAttr>()) {
12577 Size = CGF.
Builder.CreateNUWAdd(
12579 Size = CGF.
Builder.CreateUDiv(Size,
CGM.getSize(Align));
12580 Size = CGF.
Builder.CreateNUWMul(Size,
CGM.getSize(Align));
12586 const auto *AA = CVD->
getAttr<OMPAllocateDeclAttr>();
12587 const Expr *Allocator = AA->getAllocator();
12591 Args.push_back(ThreadID);
12593 Args.push_back(Alignment);
12594 Args.push_back(Size);
12595 Args.push_back(AllocVal);
12596 llvm::omp::RuntimeFunction FnID =
12597 Alignment ? OMPRTL___kmpc_aligned_alloc : OMPRTL___kmpc_alloc;
12599 OMPBuilder.getOrCreateRuntimeFunction(
CGM.getModule(), FnID), Args,
12601 llvm::FunctionCallee FiniRTLFn =
OMPBuilder.getOrCreateRuntimeFunction(
12602 CGM.getModule(), OMPRTL___kmpc_free);
12610 class OMPAllocateCleanupTy final :
public EHScopeStack::Cleanup {
12611 llvm::FunctionCallee RTLFn;
12614 const Expr *AllocExpr;
12617 OMPAllocateCleanupTy(llvm::FunctionCallee RTLFn,
12619 const Expr *AllocExpr)
12620 : RTLFn(RTLFn), LocEncoding(LocEncoding),
Addr(
Addr),
12621 AllocExpr(AllocExpr) {}
12625 llvm::Value *Args[3];
12631 Args[2] = AllocVal;
12639 CGF.
EHStack.pushCleanup<OMPAllocateCleanupTy>(
12641 VDAddr, Allocator);
12642 if (UntiedRealAddr.
isValid())
12645 Region->emitUntiedSwitch(CGF);
12662 assert(CGM.getLangOpts().OpenMP &&
"Not in OpenMP mode.");
12666 CGM.getOpenMPRuntime().NontemporalDeclsStack.emplace_back();
12668 for (
const Stmt *Ref :
C->private_refs()) {
12669 const auto *SimpleRefExpr =
cast<Expr>(Ref)->IgnoreParenImpCasts();
12671 if (
const auto *DRE = dyn_cast<DeclRefExpr>(SimpleRefExpr)) {
12672 VD = DRE->getDecl();
12675 assert((ME->isImplicitCXXThis() ||
12677 "Expected member of current class.");
12678 VD = ME->getMemberDecl();
12688 CGM.getOpenMPRuntime().NontemporalDeclsStack.pop_back();
12694 std::pair<Address, Address>> &LocalVars)
12695 : CGM(CGF.CGM), NeedToPush(!LocalVars.empty()) {
12699 CGF.
CurFn, CGM.getOpenMPRuntime().UntiedLocalVarsStack.size());
12700 CGM.getOpenMPRuntime().UntiedLocalVarsStack.push_back(LocalVars);
12706 CGM.getOpenMPRuntime().UntiedLocalVarsStack.pop_back();
12710 assert(
CGM.getLangOpts().OpenMP &&
"Not in OpenMP mode.");
12712 return llvm::any_of(
12713 CGM.getOpenMPRuntime().NontemporalDeclsStack,
12717void CGOpenMPRuntime::LastprivateConditionalRAII::tryToDisableInnerAnalysis(
12721 llvm::DenseSet<CanonicalDeclPtr<const Decl>> NeedToCheckForLPCs;
12727 const CapturedStmt *CS = S.getCapturedStmt(CaptureRegions.front());
12734 for (
const auto *
C : S.getClausesOfKind<OMPPrivateClause>()) {
12735 for (
const Expr *Ref :
C->varlist()) {
12736 if (!Ref->getType()->isScalarType())
12738 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
12741 NeedToCheckForLPCs.insert(DRE->getDecl());
12744 for (
const auto *
C : S.getClausesOfKind<OMPFirstprivateClause>()) {
12745 for (
const Expr *Ref :
C->varlist()) {
12746 if (!Ref->getType()->isScalarType())
12748 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
12751 NeedToCheckForLPCs.insert(DRE->getDecl());
12754 for (
const auto *
C : S.getClausesOfKind<OMPLastprivateClause>()) {
12755 for (
const Expr *Ref :
C->varlist()) {
12756 if (!Ref->getType()->isScalarType())
12758 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
12761 NeedToCheckForLPCs.insert(DRE->getDecl());
12764 for (
const auto *
C : S.getClausesOfKind<OMPReductionClause>()) {
12765 for (
const Expr *Ref :
C->varlist()) {
12766 if (!Ref->getType()->isScalarType())
12768 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
12771 NeedToCheckForLPCs.insert(DRE->getDecl());
12774 for (
const auto *
C : S.getClausesOfKind<OMPLinearClause>()) {
12775 for (
const Expr *Ref :
C->varlist()) {
12776 if (!Ref->getType()->isScalarType())
12778 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
12781 NeedToCheckForLPCs.insert(DRE->getDecl());
12784 for (
const Decl *VD : NeedToCheckForLPCs) {
12786 llvm::reverse(
CGM.getOpenMPRuntime().LastprivateConditionalStack)) {
12787 if (
Data.DeclToUniqueName.count(VD) > 0) {
12788 if (!
Data.Disabled)
12789 NeedToAddForLPCsAsDisabled.insert(VD);
12796CGOpenMPRuntime::LastprivateConditionalRAII::LastprivateConditionalRAII(
12799 Action((CGM.getLangOpts().OpenMP >= 50 &&
12800 llvm::any_of(S.getClausesOfKind<OMPLastprivateClause>(),
12801 [](const OMPLastprivateClause *
C) {
12802 return C->getKind() ==
12803 OMPC_LASTPRIVATE_conditional;
12805 ? ActionToDo::PushAsLastprivateConditional
12806 : ActionToDo::DoNotPush) {
12807 assert(
CGM.getLangOpts().OpenMP &&
"Not in OpenMP mode.");
12808 if (
CGM.getLangOpts().OpenMP < 50 || Action == ActionToDo::DoNotPush)
12810 assert(Action == ActionToDo::PushAsLastprivateConditional &&
12811 "Expected a push action.");
12813 CGM.getOpenMPRuntime().LastprivateConditionalStack.emplace_back();
12814 for (
const auto *
C : S.getClausesOfKind<OMPLastprivateClause>()) {
12815 if (
C->getKind() != OMPC_LASTPRIVATE_conditional)
12818 for (
const Expr *Ref :
C->varlist()) {
12819 Data.DeclToUniqueName.insert(std::make_pair(
12824 Data.IVLVal = IVLVal;
12828CGOpenMPRuntime::LastprivateConditionalRAII::LastprivateConditionalRAII(
12830 :
CGM(CGF.
CGM), Action(ActionToDo::DoNotPush) {
12834 llvm::DenseSet<CanonicalDeclPtr<const Decl>> NeedToAddForLPCsAsDisabled;
12835 tryToDisableInnerAnalysis(S, NeedToAddForLPCsAsDisabled);
12836 if (!NeedToAddForLPCsAsDisabled.empty()) {
12837 Action = ActionToDo::DisableLastprivateConditional;
12838 LastprivateConditionalData &
Data =
12840 for (
const Decl *VD : NeedToAddForLPCsAsDisabled)
12841 Data.DeclToUniqueName.try_emplace(VD);
12843 Data.Disabled =
true;
12847CGOpenMPRuntime::LastprivateConditionalRAII
12850 return LastprivateConditionalRAII(CGF, S);
12854 if (CGM.getLangOpts().OpenMP < 50)
12856 if (Action == ActionToDo::DisableLastprivateConditional) {
12857 assert(CGM.getOpenMPRuntime().LastprivateConditionalStack.back().Disabled &&
12858 "Expected list of disabled private vars.");
12859 CGM.getOpenMPRuntime().LastprivateConditionalStack.pop_back();
12861 if (Action == ActionToDo::PushAsLastprivateConditional) {
12863 !CGM.getOpenMPRuntime().LastprivateConditionalStack.back().Disabled &&
12864 "Expected list of lastprivate conditional vars.");
12865 CGM.getOpenMPRuntime().LastprivateConditionalStack.pop_back();
12877 auto VI = I->getSecond().find(VD);
12878 if (VI == I->getSecond().end()) {
12879 RecordDecl *RD =
C.buildImplicitRecord(
"lasprivate.conditional");
12884 NewType =
C.getCanonicalTagType(RD);
12887 I->getSecond().try_emplace(VD, NewType, VDField, FiredField, BaseLVal);
12889 NewType = std::get<0>(VI->getSecond());
12890 VDField = std::get<1>(VI->getSecond());
12891 FiredField = std::get<2>(VI->getSecond());
12892 BaseLVal = std::get<3>(VI->getSecond());
12904class LastprivateConditionalRefChecker final
12907 const Expr *FoundE =
nullptr;
12908 const Decl *FoundD =
nullptr;
12909 StringRef UniqueDeclName;
12911 llvm::Function *FoundFn =
nullptr;
12917 llvm::reverse(LPM)) {
12918 auto It = D.DeclToUniqueName.find(E->
getDecl());
12919 if (It == D.DeclToUniqueName.end())
12925 UniqueDeclName = It->second;
12930 return FoundE == E;
12936 llvm::reverse(LPM)) {
12938 if (It == D.DeclToUniqueName.end())
12944 UniqueDeclName = It->second;
12949 return FoundE == E;
12951 bool VisitStmt(
const Stmt *S) {
12952 for (
const Stmt *Child : S->
children()) {
12955 if (
const auto *E = dyn_cast<Expr>(Child))
12963 explicit LastprivateConditionalRefChecker(
12964 ArrayRef<CGOpenMPRuntime::LastprivateConditionalData> LPM)
12966 std::tuple<const Expr *, const Decl *, StringRef, LValue, llvm::Function *>
12967 getFoundData()
const {
12968 return std::make_tuple(FoundE, FoundD, UniqueDeclName, IVLVal, FoundFn);
12975 StringRef UniqueDeclName,
12981 llvm::Constant *LastIV =
OMPBuilder.getOrCreateInternalVariable(
12982 LLIVTy,
getName({UniqueDeclName,
"iv"}));
12990 llvm::GlobalVariable *
Last =
OMPBuilder.getOrCreateInternalVariable(
13006 auto &&
CodeGen = [&LastIVLVal, &IVLVal, IVVal, &LVal, &LastLVal,
13012 llvm::Value *CmpRes;
13014 CmpRes = CGF.
Builder.CreateICmpSLE(LastIVVal, IVVal);
13017 "Loop iteration variable must be integer.");
13018 CmpRes = CGF.
Builder.CreateICmpULE(LastIVVal, IVVal);
13022 CGF.
Builder.CreateCondBr(CmpRes, ThenBB, ExitBB);
13043 "Aggregates are not supported in lastprivate conditional.");
13052 if (
CGM.getLangOpts().OpenMPSimd) {
13066 if (!Checker.Visit(LHS))
13068 const Expr *FoundE;
13069 const Decl *FoundD;
13070 StringRef UniqueDeclName;
13072 llvm::Function *FoundFn;
13073 std::tie(FoundE, FoundD, UniqueDeclName, IVLVal, FoundFn) =
13074 Checker.getFoundData();
13075 if (FoundFn != CGF.
CurFn) {
13080 "Lastprivate conditional is not found in outer region.");
13081 QualType StructTy = std::get<0>(It->getSecond());
13082 const FieldDecl* FiredDecl = std::get<2>(It->getSecond());
13093 FiredLVal, llvm::AtomicOrdering::Unordered,
13111 auto It = llvm::find_if(
13113 if (It == Range.end() || It->Fn != CGF.
CurFn)
13117 "Lastprivates must be registered already.");
13120 const CapturedStmt *CS = D.getCapturedStmt(CaptureRegions.back());
13121 for (
const auto &Pair : It->DeclToUniqueName) {
13122 const auto *VD =
cast<VarDecl>(Pair.first->getCanonicalDecl());
13125 auto I = LPCI->getSecond().find(Pair.first);
13126 assert(I != LPCI->getSecond().end() &&
13127 "Lastprivate must be rehistered already.");
13129 LValue BaseLVal = std::get<3>(I->getSecond());
13133 llvm::Value *
Cmp = CGF.
Builder.CreateIsNotNull(Res);
13137 CGF.
Builder.CreateCondBr(
Cmp, ThenBB, DoneBB);
13162 "Unknown lastprivate conditional variable.");
13163 StringRef UniqueName = It->second;
13164 llvm::GlobalVariable *GV =
CGM.getModule().getNamedGlobal(UniqueName);
13178 llvm_unreachable(
"Not supported in SIMD-only mode");
13185 llvm_unreachable(
"Not supported in SIMD-only mode");
13192 bool Tied,
unsigned &NumberOfParts) {
13193 llvm_unreachable(
"Not supported in SIMD-only mode");
13201 llvm_unreachable(
"Not supported in SIMD-only mode");
13207 const Expr *Hint) {
13208 llvm_unreachable(
"Not supported in SIMD-only mode");
13214 llvm_unreachable(
"Not supported in SIMD-only mode");
13220 const Expr *Filter) {
13221 llvm_unreachable(
"Not supported in SIMD-only mode");
13226 llvm_unreachable(
"Not supported in SIMD-only mode");
13232 llvm_unreachable(
"Not supported in SIMD-only mode");
13240 llvm_unreachable(
"Not supported in SIMD-only mode");
13247 llvm_unreachable(
"Not supported in SIMD-only mode");
13254 bool ForceSimpleCall) {
13255 llvm_unreachable(
"Not supported in SIMD-only mode");
13262 llvm_unreachable(
"Not supported in SIMD-only mode");
13267 llvm_unreachable(
"Not supported in SIMD-only mode");
13273 llvm_unreachable(
"Not supported in SIMD-only mode");
13279 llvm_unreachable(
"Not supported in SIMD-only mode");
13286 llvm_unreachable(
"Not supported in SIMD-only mode");
13292 llvm_unreachable(
"Not supported in SIMD-only mode");
13297 unsigned IVSize,
bool IVSigned,
13300 llvm_unreachable(
"Not supported in SIMD-only mode");
13308 llvm_unreachable(
"Not supported in SIMD-only mode");
13312 ProcBindKind ProcBind,
13314 llvm_unreachable(
"Not supported in SIMD-only mode");
13321 llvm_unreachable(
"Not supported in SIMD-only mode");
13327 llvm_unreachable(
"Not supported in SIMD-only mode");
13332 llvm_unreachable(
"Not supported in SIMD-only mode");
13338 llvm::AtomicOrdering AO) {
13339 llvm_unreachable(
"Not supported in SIMD-only mode");
13344 llvm::Function *TaskFunction,
13346 const Expr *IfCond,
13348 llvm_unreachable(
"Not supported in SIMD-only mode");
13355 llvm_unreachable(
"Not supported in SIMD-only mode");
13362 assert(Options.
SimpleReduction &&
"Only simple reduction is expected.");
13364 ReductionOps, Options);
13370 llvm_unreachable(
"Not supported in SIMD-only mode");
13375 bool IsWorksharingReduction) {
13376 llvm_unreachable(
"Not supported in SIMD-only mode");
13383 llvm_unreachable(
"Not supported in SIMD-only mode");
13388 llvm::Value *ReductionsPtr,
13390 llvm_unreachable(
"Not supported in SIMD-only mode");
13396 llvm_unreachable(
"Not supported in SIMD-only mode");
13402 llvm_unreachable(
"Not supported in SIMD-only mode");
13408 llvm_unreachable(
"Not supported in SIMD-only mode");
13413 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
13415 llvm_unreachable(
"Not supported in SIMD-only mode");
13420 llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID,
const Expr *IfCond,
13421 llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier>
Device,
13425 llvm_unreachable(
"Not supported in SIMD-only mode");
13429 llvm_unreachable(
"Not supported in SIMD-only mode");
13433 llvm_unreachable(
"Not supported in SIMD-only mode");
13443 llvm::Function *OutlinedFn,
13445 llvm_unreachable(
"Not supported in SIMD-only mode");
13449 const Expr *NumTeams,
13450 const Expr *ThreadLimit,
13452 llvm_unreachable(
"Not supported in SIMD-only mode");
13459 llvm_unreachable(
"Not supported in SIMD-only mode");
13465 llvm_unreachable(
"Not supported in SIMD-only mode");
13471 llvm_unreachable(
"Not supported in SIMD-only mode");
13476 llvm_unreachable(
"Not supported in SIMD-only mode");
13481 llvm_unreachable(
"Not supported in SIMD-only mode");
13486 const VarDecl *NativeParam)
const {
13487 llvm_unreachable(
"Not supported in SIMD-only mode");
13493 const VarDecl *TargetParam)
const {
13494 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 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 represents clause 'map' in the 'pragma omp ...' directives.
This represents clause 'nontemporal' in the 'pragma omp ...' directives.
This represents 'num_teams' clause in the 'pragma omp ...' directive.
This represents 'thread_limit' clause in the 'pragma omp ...' directive.
This represents clause 'uses_allocators' in the 'pragma omp target'-based directives.
This represents 'ompx_attribute' clause in a directive that might generate an outlined function.
This represents 'ompx_bare' clause in the 'pragma omp target teams ...' directive.
This represents 'ompx_dyn_cgroup_mem' clause in the 'pragma omp target ...' directive.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
SourceManager & getSourceManager()
const ConstantArrayType * getAsConstantArrayType(QualType T) const
CharUnits getTypeAlignInChars(QualType T) const
Return the ABI-specified alignment of a (complete) type T, in characters.
const ASTRecordLayout & getASTRecordLayout(const RecordDecl *D) const
Get or compute information about the layout of the specified record (struct/union/class) D,...
QualType getPointerType(QualType T) const
Return the uniqued reference to the type for a pointer to the specified type.
QualType getConstantArrayType(QualType EltTy, const llvm::APInt &ArySize, const Expr *SizeExpr, ArraySizeModifier ASM, unsigned IndexTypeQuals) const
Return the unique reference to the type for a constant array of the specified element type.
const LangOptions & getLangOpts() const
QualType getIntTypeForBitwidth(unsigned DestWidth, unsigned Signed) const
getIntTypeForBitwidth - sets integer QualTy according to specified details: bitwidth,...
CharUnits getDeclAlign(const Decl *D, bool ForAlignof=false) const
Return a conservative estimate of the alignment of the specified decl D.
int64_t toBits(CharUnits CharSize) const
Convert a size in characters to a size in bits.
const ArrayType * getAsArrayType(QualType T) const
Type Query functions.
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
static bool hasSameType(QualType T1, QualType T2)
Determine whether the given types T1 and T2 are equivalent.
const VariableArrayType * getAsVariableArrayType(QualType T) const
QualType getSizeType() const
Return the unique type for "size_t" (C99 7.17), defined in <stddef.h>.
unsigned getTypeAlign(QualType T) const
Return the ABI-specified alignment of a (complete) type T, in bits.
CharUnits getSize() const
getSize - Get the record size in characters.
uint64_t getFieldOffset(unsigned FieldNo) const
getFieldOffset - Get the offset of the given field index, in bits.
CharUnits getNonVirtualSize() const
getNonVirtualSize - Get the non-virtual size (in chars) of an object, which is the size of the object...
static QualType getBaseOriginalType(const Expr *Base)
Return original type of the base expression for array section.
Represents an array type, per C99 6.7.5.2 - Array Declarators.
Attr - This represents one attribute.
Represents a base class of a C++ class.
Represents a C++ constructor within a class.
Represents a C++ destructor within a class.
const CXXRecordDecl * getParent() const
Return the parent of this method declaration, which is the class in which this method is defined.
QualType getFunctionObjectParameterType() const
Represents a C++ struct/union/class.
bool isLambda() const
Determine whether this class describes a lambda function object.
void getCaptureFields(llvm::DenseMap< const ValueDecl *, FieldDecl * > &Captures, FieldDecl *&ThisCapture) const
For a closure type, retrieve the mapping from captured variables and this to the non-static data memb...
unsigned getNumBases() const
Retrieves the number of base classes of this class.
base_class_range vbases()
capture_const_range captures() const
CXXDestructorDecl * getDestructor() const
Returns the destructor decl for this class.
CanProxy< U > castAs() const
A wrapper class around a pointer that always points to its canonical declaration.
Describes the capture of either a variable, or 'this', or variable-length array type.
bool capturesVariableByCopy() const
Determine whether this capture handles a variable by copy.
VarDecl * getCapturedVar() const
Retrieve the declaration of the variable being captured.
bool capturesVariableArrayType() const
Determine whether this capture handles a variable-length array type.
bool capturesThis() const
Determine whether this capture handles the C++ 'this' pointer.
bool capturesVariable() const
Determine whether this capture handles a variable (by reference).
This captures a statement into a function.
const Capture * const_capture_iterator
capture_iterator capture_end() const
Retrieve an iterator pointing past the end of the sequence of captures.
const RecordDecl * getCapturedRecordDecl() const
Retrieve the record declaration for captured variables.
Stmt * getCapturedStmt()
Retrieve the statement being captured.
bool capturesVariable(const VarDecl *Var) const
True if this variable has been captured.
capture_iterator capture_begin()
Retrieve an iterator pointing to the first capture.
CharUnits - This is an opaque type for sizes expressed in character units.
bool isZero() const
isZero - Test whether the quantity equals zero.
llvm::Align getAsAlign() const
getAsAlign - Returns Quantity as a valid llvm::Align, Beware llvm::Align assumes power of two 8-bit b...
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
CharUnits alignmentOfArrayElement(CharUnits elementSize) const
Given that this is the alignment of the first element of an array, return the minimum alignment of an...
static CharUnits fromQuantity(QuantityType Quantity)
fromQuantity - Construct a CharUnits quantity from a raw integer type.
CharUnits alignTo(const CharUnits &Align) const
alignTo - Returns the next integer (mod 2**64) that is greater than or equal to this quantity and is ...
std::string SampleProfileFile
Name of the profile file to use with -fprofile-sample-use.
Like RawAddress, an abstract representation of an aligned address, but the pointer contained in this ...
llvm::Value * emitRawPointer(CodeGenFunction &CGF) const
Return the pointer contained in this class after authenticating it and adding offset to it if necessa...
CharUnits getAlignment() const
llvm::Type * getElementType() const
Return the type of the values stored in this address.
Address withPointer(llvm::Value *NewPointer, KnownNonNull_t IsKnownNonNull) const
Return address with different pointer, but same element type and alignment.
Address withElementType(llvm::Type *ElemTy) const
Return address with different element type, but same pointer and alignment.
llvm::PointerType * getType() const
Return the type of the pointer value.
static ApplyDebugLocation CreateArtificial(CodeGenFunction &CGF)
Apply TemporaryLocation if it is valid.
static ApplyDebugLocation CreateDefaultArtificial(CodeGenFunction &CGF, SourceLocation TemporaryLocation)
Apply TemporaryLocation if it is valid.
static ApplyDebugLocation CreateEmpty(CodeGenFunction &CGF)
Set the IRBuilder to not attach debug locations.
llvm::StoreInst * CreateStore(llvm::Value *Val, Address Addr, bool IsVolatile=false)
Address CreateGEP(CodeGenFunction &CGF, Address Addr, llvm::Value *Index, const llvm::Twine &Name="")
Address CreatePointerBitCastOrAddrSpaceCast(Address Addr, llvm::Type *Ty, llvm::Type *ElementTy, const llvm::Twine &Name="")
Address CreateConstArrayGEP(Address Addr, uint64_t Index, const llvm::Twine &Name="")
Given addr = [n x T]* ... produce name = getelementptr inbounds addr, i64 0, i64 index where i64 is a...
llvm::LoadInst * CreateLoad(Address Addr, const llvm::Twine &Name="")
llvm::CallInst * CreateMemCpy(Address Dest, Address Src, llvm::Value *Size, bool IsVolatile=false)
Address CreateConstGEP(Address Addr, uint64_t Index, const llvm::Twine &Name="")
Given addr = T* ... produce name = getelementptr inbounds addr, i64 index where i64 is actually the t...
Address CreateAddrSpaceCast(Address Addr, llvm::Type *Ty, llvm::Type *ElementTy, const llvm::Twine &Name="")
CGFunctionInfo - Class to encapsulate the information about a function definition.
DisableAutoDeclareTargetRAII(CodeGenModule &CGM)
~DisableAutoDeclareTargetRAII()
~LastprivateConditionalRAII()
static LastprivateConditionalRAII disable(CodeGenFunction &CGF, const OMPExecutableDirective &S)
NontemporalDeclsRAII(CodeGenModule &CGM, const OMPLoopDirective &S)
Struct that keeps all the relevant information that should be kept throughout a 'target data' region.
llvm::DenseMap< const ValueDecl *, llvm::Value * > CaptureDeviceAddrMap
Map between the a declaration of a capture and the corresponding new llvm address where the runtime r...
~UntiedTaskLocalDeclsRAII()
UntiedTaskLocalDeclsRAII(CodeGenFunction &CGF, const llvm::MapVector< CanonicalDeclPtr< const VarDecl >, std::pair< Address, Address > > &LocalVars)
virtual Address emitThreadIDAddress(CodeGenFunction &CGF, SourceLocation Loc)
Emits address of the word in a memory where current thread id is stored.
llvm::StringSet ThreadPrivateWithDefinition
Set of threadprivate variables with the generated initializer.
CGOpenMPRuntime(CodeGenModule &CGM)
void emitUpdateDependObjectsClause(CodeGenFunction &CGF, LValue DepobjLVal, OpenMPDependClauseKind NewDepKind, SourceLocation Loc)
Updates the dependency kind in the specified depobj object.
virtual void emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc, const OMPExecutableDirective &D, llvm::Function *TaskFunction, QualType SharedsTy, Address Shareds, const Expr *IfCond, const OMPTaskDataTy &Data)
Emit task region for the task directive.
void createOffloadEntriesAndInfoMetadata()
Creates all the offload entries in the current compilation unit along with the associated metadata.
const Expr * getNumTeamsExprForTargetDirective(CodeGenFunction &CGF, const OMPExecutableDirective &D, int32_t &MinTeamsVal, int32_t &MaxTeamsVal)
Emit the number of teams for a target directive.
virtual Address getAddrOfThreadPrivate(CodeGenFunction &CGF, const VarDecl *VD, Address VDAddr, SourceLocation Loc)
Returns address of the threadprivate variable for the current thread.
void emitDeferredTargetDecls() const
Emit deferred declare target variables marked for deferred emission.
virtual llvm::Value * emitForNext(CodeGenFunction &CGF, SourceLocation Loc, unsigned IVSize, bool IVSigned, Address IL, Address LB, Address UB, Address ST)
Call __kmpc_dispatch_next( ident_t *loc, kmp_int32 tid, kmp_int32 *p_lastiter, kmp_int[32|64] *p_lowe...
bool markAsGlobalTarget(GlobalDecl GD)
Marks the declaration as already emitted for the device code and returns true, if it was marked alrea...
virtual void emitParallelCall(CodeGenFunction &CGF, SourceLocation Loc, llvm::Function *OutlinedFn, ArrayRef< llvm::Value * > CapturedVars, const Expr *IfCond, llvm::Value *NumThreads, OpenMPNumThreadsClauseModifier NumThreadsModifier=OMPC_NUMTHREADS_unknown, OpenMPSeverityClauseKind Severity=OMPC_SEVERITY_fatal, const Expr *Message=nullptr)
Emits code for parallel or serial call of the OutlinedFn with variables captured in a record which ad...
llvm::SmallDenseSet< CanonicalDeclPtr< const Decl > > NontemporalDeclsSet
virtual void emitTargetDataStandAloneCall(CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, const Expr *Device)
Emit the data mapping/movement code associated with the directive D that should be of the form 'targe...
virtual void emitNumThreadsClause(CodeGenFunction &CGF, llvm::Value *NumThreads, SourceLocation Loc, OpenMPNumThreadsClauseModifier Modifier=OMPC_NUMTHREADS_unknown, OpenMPSeverityClauseKind Severity=OMPC_SEVERITY_fatal, SourceLocation SeverityLoc=SourceLocation(), const Expr *Message=nullptr, SourceLocation MessageLoc=SourceLocation())
Emits call to void __kmpc_push_num_threads(ident_t *loc, kmp_int32global_tid, kmp_int32 num_threads) ...
QualType SavedKmpTaskloopTQTy
Saved kmp_task_t for taskloop-based directive.
virtual void emitSingleRegion(CodeGenFunction &CGF, const RegionCodeGenTy &SingleOpGen, SourceLocation Loc, ArrayRef< const Expr * > CopyprivateVars, ArrayRef< const Expr * > DestExprs, ArrayRef< const Expr * > SrcExprs, ArrayRef< const Expr * > AssignmentOps)
Emits a single region.
virtual bool emitTargetGlobal(GlobalDecl GD)
Emit the global GD if it is meaningful for the target.
void setLocThreadIdInsertPt(CodeGenFunction &CGF, bool AtCurrentPoint=false)
std::string getOutlinedHelperName(StringRef Name) const
Get the function name of an outlined region.
bool HasEmittedDeclareTargetRegion
Flag for keeping track of weather a device routine has been emitted.
llvm::Constant * getOrCreateThreadPrivateCache(const VarDecl *VD)
If the specified mangled name is not in the module, create and return threadprivate cache object.
virtual Address getTaskReductionItem(CodeGenFunction &CGF, SourceLocation Loc, llvm::Value *ReductionsPtr, LValue SharedLVal)
Get the address of void * type of the privatue copy of the reduction item specified by the SharedLVal...
virtual void emitForDispatchDeinit(CodeGenFunction &CGF, SourceLocation Loc)
This is used for non static scheduled types and when the ordered clause is present on the loop constr...
void emitCall(CodeGenFunction &CGF, SourceLocation Loc, llvm::FunctionCallee Callee, ArrayRef< llvm::Value * > Args={}) const
Emits Callee function call with arguments Args with location Loc.
virtual void getDefaultScheduleAndChunk(CodeGenFunction &CGF, const OMPLoopDirective &S, OpenMPScheduleClauseKind &ScheduleKind, const Expr *&ChunkExpr) const
Choose default schedule type and chunk value for the schedule clause.
virtual std::pair< llvm::Function *, llvm::Function * > getUserDefinedReduction(const OMPDeclareReductionDecl *D)
Get combiner/initializer for the specified user-defined reduction, if any.
virtual bool isGPU() const
Returns true if the current target is a GPU.
static const Stmt * getSingleCompoundChild(ASTContext &Ctx, const Stmt *Body)
Checks if the Body is the CompoundStmt and returns its child statement iff there is only one that is ...
virtual void emitDeclareTargetFunction(const FunctionDecl *FD, llvm::GlobalValue *GV)
Emit code for handling declare target functions in the runtime.
bool HasRequiresUnifiedSharedMemory
Flag for keeping track of weather a requires unified_shared_memory directive is present.
llvm::Value * emitUpdateLocation(CodeGenFunction &CGF, SourceLocation Loc, unsigned Flags=0, bool EmitLoc=false)
Emits object of ident_t type with info for source location.
bool isLocalVarInUntiedTask(CodeGenFunction &CGF, const VarDecl *VD) const
Returns true if the variable is a local variable in untied task.
virtual void emitTeamsCall(CodeGenFunction &CGF, const OMPExecutableDirective &D, SourceLocation Loc, llvm::Function *OutlinedFn, ArrayRef< llvm::Value * > CapturedVars)
Emits code for teams call of the OutlinedFn with variables captured in a record which address is stor...
virtual void emitCancellationPointCall(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind CancelRegion)
Emit code for 'cancellation point' construct.
virtual llvm::Function * emitThreadPrivateVarDefinition(const VarDecl *VD, Address VDAddr, SourceLocation Loc, bool PerformInit, CodeGenFunction *CGF=nullptr)
Emit a code for initialization of threadprivate variable.
FunctionUDMMapTy FunctionUDMMap
virtual ConstantAddress getAddrOfDeclareTargetVar(const VarDecl *VD)
Returns the address of the variable marked as declare target with link clause OR as declare target wi...
llvm::Function * getOrCreateUserDefinedMapperFunc(const OMPDeclareMapperDecl *D)
Get the function for the specified user-defined mapper.
OpenMPLocThreadIDMapTy OpenMPLocThreadIDMap
virtual void functionFinished(CodeGenFunction &CGF)
Cleans up references to the objects in finished function.
virtual llvm::Function * emitTeamsOutlinedFunction(CodeGenFunction &CGF, const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen)
Emits outlined function for the specified OpenMP teams directive D.
QualType KmpTaskTQTy
Type typedef struct kmp_task { void * shareds; /**< pointer to block of pointers to shared vars / k...
llvm::OpenMPIRBuilder OMPBuilder
An OpenMP-IR-Builder instance.
virtual void emitDoacrossInit(CodeGenFunction &CGF, const OMPLoopDirective &D, ArrayRef< Expr * > NumIterations)
Emit initialization for doacross loop nesting support.
virtual void adjustTargetSpecificDataForLambdas(CodeGenFunction &CGF, const OMPExecutableDirective &D) const
Adjust some parameters for the target-based directives, like addresses of the variables captured by r...
FunctionUDRMapTy FunctionUDRMap
virtual void emitTargetDataCalls(CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, const Expr *Device, const RegionCodeGenTy &CodeGen, CGOpenMPRuntime::TargetDataInfo &Info)
Emit the target data mapping code associated with D.
virtual unsigned getDefaultLocationReserved2Flags() const
Returns additional flags that can be stored in reserved_2 field of the default location.
virtual Address getParameterAddress(CodeGenFunction &CGF, const VarDecl *NativeParam, const VarDecl *TargetParam) const
Gets the address of the native argument basing on the address of the target-specific parameter.
void emitUsesAllocatorsFini(CodeGenFunction &CGF, const Expr *Allocator)
Destroys user defined allocators specified in the uses_allocators clause.
QualType KmpTaskAffinityInfoTy
Type typedef struct kmp_task_affinity_info { kmp_intptr_t base_addr; size_t len; struct { bool flag1 ...
void emitPrivateReduction(CodeGenFunction &CGF, SourceLocation Loc, const Expr *Privates, const Expr *LHSExprs, const Expr *RHSExprs, const Expr *ReductionOps)
Emits code for private variable reduction.
llvm::Value * emitNumTeamsForTargetDirective(CodeGenFunction &CGF, const OMPExecutableDirective &D)
virtual void emitTargetOutlinedFunctionHelper(const OMPExecutableDirective &D, StringRef ParentName, llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID, bool IsOffloadEntry, const RegionCodeGenTy &CodeGen)
Helper to emit outlined function for 'target' directive.
void scanForTargetRegionsFunctions(const Stmt *S, StringRef ParentName)
Start scanning from statement S and emit all target regions found along the way.
SmallVector< llvm::Value *, 4 > emitDepobjElementsSizes(CodeGenFunction &CGF, QualType &KmpDependInfoTy, const OMPTaskDataTy::DependData &Data)
virtual llvm::Value * emitMessageClause(CodeGenFunction &CGF, const Expr *Message, SourceLocation Loc)
virtual void emitTaskgroupRegion(CodeGenFunction &CGF, const RegionCodeGenTy &TaskgroupOpGen, SourceLocation Loc)
Emit a taskgroup region.
llvm::DenseMap< llvm::Function *, llvm::DenseMap< CanonicalDeclPtr< const Decl >, std::tuple< QualType, const FieldDecl *, const FieldDecl *, LValue > > > LastprivateConditionalToTypes
Maps local variables marked as lastprivate conditional to their internal types.
virtual bool emitTargetGlobalVariable(GlobalDecl GD)
Emit the global variable if it is a valid device global variable.
virtual void emitNumTeamsClause(CodeGenFunction &CGF, const Expr *NumTeams, const Expr *ThreadLimit, SourceLocation Loc)
Emits call to void __kmpc_push_num_teams(ident_t *loc, kmp_int32global_tid, kmp_int32 num_teams,...
bool hasRequiresUnifiedSharedMemory() const
Return whether the unified_shared_memory has been specified.
virtual Address getAddrOfArtificialThreadPrivate(CodeGenFunction &CGF, QualType VarType, StringRef Name)
Creates artificial threadprivate variable with name Name and type VarType.
void emitUserDefinedMapper(const OMPDeclareMapperDecl *D, CodeGenFunction *CGF=nullptr)
Emit the function for the user defined mapper construct.
bool HasEmittedTargetRegion
Flag for keeping track of weather a target region has been emitted.
void emitDepobjElements(CodeGenFunction &CGF, QualType &KmpDependInfoTy, LValue PosLVal, const OMPTaskDataTy::DependData &Data, Address DependenciesArray)
std::string getReductionFuncName(StringRef Name) const
Get the function name of a reduction function.
virtual void processRequiresDirective(const OMPRequiresDecl *D)
Perform check on requires decl to ensure that target architecture supports unified addressing.
llvm::DenseSet< CanonicalDeclPtr< const Decl > > AlreadyEmittedTargetDecls
List of the emitted declarations.
virtual llvm::Value * emitTaskReductionInit(CodeGenFunction &CGF, SourceLocation Loc, ArrayRef< const Expr * > LHSExprs, ArrayRef< const Expr * > RHSExprs, const OMPTaskDataTy &Data)
Emit a code for initialization of task reduction clause.
llvm::Value * getThreadID(CodeGenFunction &CGF, SourceLocation Loc)
Gets thread id value for the current thread.
virtual void emitLastprivateConditionalFinalUpdate(CodeGenFunction &CGF, LValue PrivLVal, const VarDecl *VD, SourceLocation Loc)
Gets the address of the global copy used for lastprivate conditional update, if any.
llvm::MapVector< CanonicalDeclPtr< const VarDecl >, std::pair< Address, Address > > UntiedLocalVarsAddressesMap
virtual void emitErrorCall(CodeGenFunction &CGF, SourceLocation Loc, Expr *ME, bool IsFatal)
Emit __kmpc_error call for error directive extern void __kmpc_error(ident_t *loc, int severity,...
void clearLocThreadIdInsertPt(CodeGenFunction &CGF)
virtual void emitTaskyieldCall(CodeGenFunction &CGF, SourceLocation Loc)
Emits code for a taskyield directive.
std::string getName(ArrayRef< StringRef > Parts) const
Get the platform-specific name separator.
QualType KmpRoutineEntryPtrQTy
void computeMinAndMaxThreadsAndTeams(const OMPExecutableDirective &D, CodeGenFunction &CGF, llvm::OpenMPIRBuilder::TargetKernelDefaultAttrs &Attrs)
Helper to determine the min/max number of threads/teams for D.
virtual void emitFlush(CodeGenFunction &CGF, ArrayRef< const Expr * > Vars, SourceLocation Loc, llvm::AtomicOrdering AO)
Emit flush of the variables specified in 'omp flush' directive.
virtual void emitTaskwaitCall(CodeGenFunction &CGF, SourceLocation Loc, const OMPTaskDataTy &Data)
Emit code for 'taskwait' directive.
virtual void emitProcBindClause(CodeGenFunction &CGF, llvm::omp::ProcBindKind ProcBind, SourceLocation Loc)
Emit call to void __kmpc_push_proc_bind(ident_t *loc, kmp_int32global_tid, int proc_bind) to generate...
void emitLastprivateConditionalUpdate(CodeGenFunction &CGF, LValue IVLVal, StringRef UniqueDeclName, LValue LVal, SourceLocation Loc)
Emit update for lastprivate conditional data.
virtual void emitTaskLoopCall(CodeGenFunction &CGF, SourceLocation Loc, const OMPLoopDirective &D, llvm::Function *TaskFunction, QualType SharedsTy, Address Shareds, const Expr *IfCond, const OMPTaskDataTy &Data)
Emit task region for the taskloop directive.
virtual void emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind Kind, bool EmitChecks=true, bool ForceSimpleCall=false)
Emit an implicit/explicit barrier for OpenMP threads.
static unsigned getDefaultFlagsForBarriers(OpenMPDirectiveKind Kind)
Returns default flags for the barriers depending on the directive, for which this barier is going to ...
virtual bool emitTargetFunctions(GlobalDecl GD)
Emit the target regions enclosed in GD function definition or the function itself in case it is a val...
TaskResultTy emitTaskInit(CodeGenFunction &CGF, SourceLocation Loc, const OMPExecutableDirective &D, llvm::Function *TaskFunction, QualType SharedsTy, Address Shareds, const OMPTaskDataTy &Data)
Emit task region for the task directive.
llvm::Value * emitTargetNumIterationsCall(CodeGenFunction &CGF, const OMPExecutableDirective &D, llvm::function_ref< llvm::Value *(CodeGenFunction &CGF, const OMPLoopDirective &D)> SizeEmitter)
Return the trip count of loops associated with constructs / 'target teams distribute' and 'teams dist...
llvm::StringMap< llvm::AssertingVH< llvm::GlobalVariable >, llvm::BumpPtrAllocator > InternalVars
An ordered map of auto-generated variables to their unique names.
virtual void emitDistributeStaticInit(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDistScheduleClauseKind SchedKind, const StaticRTInput &Values)
llvm::SmallVector< UntiedLocalVarsAddressesMap, 4 > UntiedLocalVarsStack
virtual void emitForStaticFinish(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind DKind)
Call the appropriate runtime routine to notify that we finished all the work with current loop.
virtual void emitThreadLimitClause(CodeGenFunction &CGF, const Expr *ThreadLimit, SourceLocation Loc)
Emits call to void __kmpc_set_thread_limit(ident_t *loc, kmp_int32global_tid, kmp_int32 thread_limit)...
void emitIfClause(CodeGenFunction &CGF, const Expr *Cond, const RegionCodeGenTy &ThenGen, const RegionCodeGenTy &ElseGen)
Emits code for OpenMP 'if' clause using specified CodeGen function.
Address emitDepobjDependClause(CodeGenFunction &CGF, const OMPTaskDataTy::DependData &Dependencies, SourceLocation Loc)
Emits list of dependecies based on the provided data (array of dependence/expression pairs) for depob...
bool isNontemporalDecl(const ValueDecl *VD) const
Checks if the VD variable is marked as nontemporal declaration in current context.
virtual llvm::Function * emitParallelOutlinedFunction(CodeGenFunction &CGF, const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen)
Emits outlined function for the specified OpenMP parallel directive D.
const Expr * getNumThreadsExprForTargetDirective(CodeGenFunction &CGF, const OMPExecutableDirective &D, int32_t &UpperBound, bool UpperBoundOnly, llvm::Value **CondExpr=nullptr, const Expr **ThreadLimitExpr=nullptr)
Check for a number of threads upper bound constant value (stored in UpperBound), or expression (retur...
virtual void registerVTableOffloadEntry(llvm::GlobalVariable *VTable, const VarDecl *VD)
Register VTable to OpenMP offload entry.
virtual llvm::Value * emitSeverityClause(OpenMPSeverityClauseKind Severity, SourceLocation Loc)
llvm::SmallVector< LastprivateConditionalData, 4 > LastprivateConditionalStack
Stack for list of addresses of declarations in current context marked as lastprivate conditional.
virtual void emitForStaticInit(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind DKind, const OpenMPScheduleTy &ScheduleKind, const StaticRTInput &Values)
Call the appropriate runtime routine to initialize it before start of loop.
virtual void emitDeclareSimdFunction(const FunctionDecl *FD, llvm::Function *Fn)
Marks function Fn with properly mangled versions of vector functions.
llvm::AtomicOrdering getDefaultMemoryOrdering() const
Gets default memory ordering as specified in requires directive.
virtual bool isStaticNonchunked(OpenMPScheduleClauseKind ScheduleKind, bool Chunked) const
Check if the specified ScheduleKind is static non-chunked.
virtual void emitAndRegisterVTable(CodeGenModule &CGM, CXXRecordDecl *CXXRecord, const VarDecl *VD)
Emit and register VTable for the C++ class in OpenMP offload entry.
llvm::Value * getCriticalRegionLock(StringRef CriticalName)
Returns corresponding lock object for the specified critical region name.
virtual void emitCancelCall(CodeGenFunction &CGF, SourceLocation Loc, const Expr *IfCond, OpenMPDirectiveKind CancelRegion)
Emit code for 'cancel' construct.
QualType SavedKmpTaskTQTy
Saved kmp_task_t for task directive.
virtual void emitMasterRegion(CodeGenFunction &CGF, const RegionCodeGenTy &MasterOpGen, SourceLocation Loc)
Emits a master region.
virtual llvm::Function * emitTaskOutlinedFunction(const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, const VarDecl *PartIDVar, const VarDecl *TaskTVar, OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen, bool Tied, unsigned &NumberOfParts)
Emits outlined function for the OpenMP task directive D.
llvm::DenseMap< llvm::Function *, unsigned > FunctionToUntiedTaskStackMap
Maps function to the position of the untied task locals stack.
void emitDestroyClause(CodeGenFunction &CGF, LValue DepobjLVal, SourceLocation Loc)
Emits the code to destroy the dependency object provided in depobj directive.
virtual void emitTaskReductionFixups(CodeGenFunction &CGF, SourceLocation Loc, ReductionCodeGen &RCG, unsigned N)
Required to resolve existing problems in the runtime.
llvm::ArrayType * KmpCriticalNameTy
Type kmp_critical_name, originally defined as typedef kmp_int32 kmp_critical_name[8];.
virtual void emitDoacrossOrdered(CodeGenFunction &CGF, const OMPDependClause *C)
Emit code for doacross ordered directive with 'depend' clause.
llvm::DenseMap< const OMPDeclareMapperDecl *, llvm::Function * > UDMMap
Map from the user-defined mapper declaration to its corresponding functions.
virtual void checkAndEmitLastprivateConditional(CodeGenFunction &CGF, const Expr *LHS)
Checks if the provided LVal is lastprivate conditional and emits the code to update the value of the ...
std::pair< llvm::Value *, LValue > getDepobjElements(CodeGenFunction &CGF, LValue DepobjLVal, SourceLocation Loc)
Returns the number of the elements and the address of the depobj dependency array.
llvm::SmallDenseSet< const VarDecl * > DeferredGlobalVariables
List of variables that can become declare target implicitly and, thus, must be emitted.
void emitUsesAllocatorsInit(CodeGenFunction &CGF, const Expr *Allocator, const Expr *AllocatorTraits)
Initializes user defined allocators specified in the uses_allocators clauses.
virtual void registerVTable(const OMPExecutableDirective &D)
Emit code for registering vtable by scanning through map clause in OpenMP target region.
llvm::Type * KmpRoutineEntryPtrTy
Type typedef kmp_int32 (* kmp_routine_entry_t)(kmp_int32, void *);.
llvm::Type * getIdentTyPointerTy()
Returns pointer to ident_t type.
void emitSingleReductionCombiner(CodeGenFunction &CGF, const Expr *ReductionOp, const Expr *PrivateRef, const DeclRefExpr *LHS, const DeclRefExpr *RHS)
Emits single reduction combiner.
llvm::OpenMPIRBuilder & getOMPBuilder()
virtual void emitTargetOutlinedFunction(const OMPExecutableDirective &D, StringRef ParentName, llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID, bool IsOffloadEntry, const RegionCodeGenTy &CodeGen)
Emit outilined function for 'target' directive.
virtual void emitCriticalRegion(CodeGenFunction &CGF, StringRef CriticalName, const RegionCodeGenTy &CriticalOpGen, SourceLocation Loc, const Expr *Hint=nullptr)
Emits a critical region.
virtual void emitForOrderedIterationEnd(CodeGenFunction &CGF, SourceLocation Loc, unsigned IVSize, bool IVSigned)
Call the appropriate runtime routine to notify that we finished iteration of the ordered loop with th...
virtual void emitOutlinedFunctionCall(CodeGenFunction &CGF, SourceLocation Loc, llvm::FunctionCallee OutlinedFn, ArrayRef< llvm::Value * > Args={}) const
Emits call of the outlined function with the provided arguments, translating these arguments to corre...
llvm::Value * emitNumThreadsForTargetDirective(CodeGenFunction &CGF, const OMPExecutableDirective &D)
Emit an expression that denotes the number of threads a target region shall use.
void emitThreadPrivateVarInit(CodeGenFunction &CGF, Address VDAddr, llvm::Value *Ctor, llvm::Value *CopyCtor, llvm::Value *Dtor, SourceLocation Loc)
Emits initialization code for the threadprivate variables.
virtual void emitUserDefinedReduction(CodeGenFunction *CGF, const OMPDeclareReductionDecl *D)
Emit code for the specified user defined reduction construct.
virtual void checkAndEmitSharedLastprivateConditional(CodeGenFunction &CGF, const OMPExecutableDirective &D, const llvm::DenseSet< CanonicalDeclPtr< const VarDecl > > &IgnoredDecls)
Checks if the lastprivate conditional was updated in inner region and writes the value.
QualType KmpDimTy
struct kmp_dim { // loop bounds info casted to kmp_int64 kmp_int64 lo; // lower kmp_int64 up; // uppe...
virtual void emitInlinedDirective(CodeGenFunction &CGF, OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen, bool HasCancel=false)
Emit code for the directive that does not require outlining.
virtual void registerTargetGlobalVariable(const VarDecl *VD, llvm::Constant *Addr)
Checks if the provided global decl GD is a declare target variable and registers it when emitting cod...
virtual void emitFunctionProlog(CodeGenFunction &CGF, const Decl *D)
Emits OpenMP-specific function prolog.
void emitKmpRoutineEntryT(QualType KmpInt32Ty)
Build type kmp_routine_entry_t (if not built yet).
virtual bool isStaticChunked(OpenMPScheduleClauseKind ScheduleKind, bool Chunked) const
Check if the specified ScheduleKind is static chunked.
virtual void emitTargetCall(CodeGenFunction &CGF, const OMPExecutableDirective &D, llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID, const Expr *IfCond, llvm::PointerIntPair< const Expr *, 2, OpenMPDeviceClauseModifier > Device, llvm::function_ref< llvm::Value *(CodeGenFunction &CGF, const OMPLoopDirective &D)> SizeEmitter)
Emit the target offloading code associated with D.
virtual bool hasAllocateAttributeForGlobalVar(const VarDecl *VD, LangAS &AS)
Checks if the variable has associated OMPAllocateDeclAttr attribute with the predefined allocator and...
llvm::AtomicOrdering RequiresAtomicOrdering
Atomic ordering from the omp requires directive.
virtual void emitReduction(CodeGenFunction &CGF, SourceLocation Loc, ArrayRef< const Expr * > Privates, ArrayRef< const Expr * > LHSExprs, ArrayRef< const Expr * > RHSExprs, ArrayRef< const Expr * > ReductionOps, ReductionOptionsTy Options)
Emit a code for reduction clause.
std::pair< llvm::Value *, Address > emitDependClause(CodeGenFunction &CGF, ArrayRef< OMPTaskDataTy::DependData > Dependencies, SourceLocation Loc)
Emits list of dependecies based on the provided data (array of dependence/expression pairs).
llvm::StringMap< llvm::WeakTrackingVH > EmittedNonTargetVariables
List of the global variables with their addresses that should not be emitted for the target.
virtual bool isDynamic(OpenMPScheduleClauseKind ScheduleKind) const
Check if the specified ScheduleKind is dynamic.
Address emitLastprivateConditionalInit(CodeGenFunction &CGF, const VarDecl *VD)
Create specialized alloca to handle lastprivate conditionals.
virtual void emitOrderedRegion(CodeGenFunction &CGF, const RegionCodeGenTy &OrderedOpGen, SourceLocation Loc, bool IsThreads)
Emit an ordered region.
virtual Address getAddressOfLocalVariable(CodeGenFunction &CGF, const VarDecl *VD)
Gets the OpenMP-specific address of the local variable.
virtual void emitTaskReductionFini(CodeGenFunction &CGF, SourceLocation Loc, bool IsWorksharingReduction)
Emits the following code for reduction clause with task modifier:
virtual void emitMaskedRegion(CodeGenFunction &CGF, const RegionCodeGenTy &MaskedOpGen, SourceLocation Loc, const Expr *Filter=nullptr)
Emits a masked region.
QualType KmpDependInfoTy
Type typedef struct kmp_depend_info { kmp_intptr_t base_addr; size_t len; struct { bool in:1; bool ou...
llvm::Function * emitReductionFunction(StringRef ReducerName, SourceLocation Loc, llvm::Type *ArgsElemType, ArrayRef< const Expr * > Privates, ArrayRef< const Expr * > LHSExprs, ArrayRef< const Expr * > RHSExprs, ArrayRef< const Expr * > ReductionOps)
Emits reduction function.
virtual void emitForDispatchInit(CodeGenFunction &CGF, SourceLocation Loc, const OpenMPScheduleTy &ScheduleKind, unsigned IVSize, bool IVSigned, bool Ordered, const DispatchRTInput &DispatchValues)
Call the appropriate runtime routine to initialize it before start of loop.
Address getTaskReductionItem(CodeGenFunction &CGF, SourceLocation Loc, llvm::Value *ReductionsPtr, LValue SharedLVal) override
Get the address of void * type of the privatue copy of the reduction item specified by the SharedLVal...
void emitCriticalRegion(CodeGenFunction &CGF, StringRef CriticalName, const RegionCodeGenTy &CriticalOpGen, SourceLocation Loc, const Expr *Hint=nullptr) override
Emits a critical region.
void emitDistributeStaticInit(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDistScheduleClauseKind SchedKind, const StaticRTInput &Values) override
void emitForStaticInit(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind DKind, const OpenMPScheduleTy &ScheduleKind, const StaticRTInput &Values) override
Call the appropriate runtime routine to initialize it before start of loop.
bool emitTargetGlobalVariable(GlobalDecl GD) override
Emit the global variable if it is a valid device global variable.
llvm::Value * emitForNext(CodeGenFunction &CGF, SourceLocation Loc, unsigned IVSize, bool IVSigned, Address IL, Address LB, Address UB, Address ST) override
Call __kmpc_dispatch_next( ident_t *loc, kmp_int32 tid, kmp_int32 *p_lastiter, kmp_int[32|64] *p_lowe...
llvm::Function * emitThreadPrivateVarDefinition(const VarDecl *VD, Address VDAddr, SourceLocation Loc, bool PerformInit, CodeGenFunction *CGF=nullptr) override
Emit a code for initialization of threadprivate variable.
void emitTargetDataStandAloneCall(CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, const Expr *Device) override
Emit the data mapping/movement code associated with the directive D that should be of the form 'targe...
llvm::Function * emitTeamsOutlinedFunction(CodeGenFunction &CGF, const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) override
Emits outlined function for the specified OpenMP teams directive D.
void emitParallelCall(CodeGenFunction &CGF, SourceLocation Loc, llvm::Function *OutlinedFn, ArrayRef< llvm::Value * > CapturedVars, const Expr *IfCond, llvm::Value *NumThreads, OpenMPNumThreadsClauseModifier NumThreadsModifier=OMPC_NUMTHREADS_unknown, OpenMPSeverityClauseKind Severity=OMPC_SEVERITY_fatal, const Expr *Message=nullptr) override
Emits code for parallel or serial call of the OutlinedFn with variables captured in a record which ad...
void emitReduction(CodeGenFunction &CGF, SourceLocation Loc, ArrayRef< const Expr * > Privates, ArrayRef< const Expr * > LHSExprs, ArrayRef< const Expr * > RHSExprs, ArrayRef< const Expr * > ReductionOps, ReductionOptionsTy Options) override
Emit a code for reduction clause.
void emitFlush(CodeGenFunction &CGF, ArrayRef< const Expr * > Vars, SourceLocation Loc, llvm::AtomicOrdering AO) override
Emit flush of the variables specified in 'omp flush' directive.
void emitDoacrossOrdered(CodeGenFunction &CGF, const OMPDependClause *C) override
Emit code for doacross ordered directive with 'depend' clause.
void emitTaskyieldCall(CodeGenFunction &CGF, SourceLocation Loc) override
Emits a masked region.
Address getAddrOfArtificialThreadPrivate(CodeGenFunction &CGF, QualType VarType, StringRef Name) override
Creates artificial threadprivate variable with name Name and type VarType.
Address getAddrOfThreadPrivate(CodeGenFunction &CGF, const VarDecl *VD, Address VDAddr, SourceLocation Loc) override
Returns address of the threadprivate variable for the current thread.
void emitSingleRegion(CodeGenFunction &CGF, const RegionCodeGenTy &SingleOpGen, SourceLocation Loc, ArrayRef< const Expr * > CopyprivateVars, ArrayRef< const Expr * > DestExprs, ArrayRef< const Expr * > SrcExprs, ArrayRef< const Expr * > AssignmentOps) override
Emits a single region.
void emitTaskReductionFixups(CodeGenFunction &CGF, SourceLocation Loc, ReductionCodeGen &RCG, unsigned N) override
Required to resolve existing problems in the runtime.
llvm::Function * emitParallelOutlinedFunction(CodeGenFunction &CGF, const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) override
Emits outlined function for the specified OpenMP parallel directive D.
void emitCancellationPointCall(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind CancelRegion) override
Emit code for 'cancellation point' construct.
void emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind Kind, bool EmitChecks=true, bool ForceSimpleCall=false) override
Emit an implicit/explicit barrier for OpenMP threads.
Address getParameterAddress(CodeGenFunction &CGF, const VarDecl *NativeParam, const VarDecl *TargetParam) const override
Gets the address of the native argument basing on the address of the target-specific parameter.
void emitTeamsCall(CodeGenFunction &CGF, const OMPExecutableDirective &D, SourceLocation Loc, llvm::Function *OutlinedFn, ArrayRef< llvm::Value * > CapturedVars) override
Emits code for teams call of the OutlinedFn with variables captured in a record which address is stor...
void emitForOrderedIterationEnd(CodeGenFunction &CGF, SourceLocation Loc, unsigned IVSize, bool IVSigned) override
Call the appropriate runtime routine to notify that we finished iteration of the ordered loop with th...
bool emitTargetGlobal(GlobalDecl GD) override
Emit the global GD if it is meaningful for the target.
void emitTaskReductionFini(CodeGenFunction &CGF, SourceLocation Loc, bool IsWorksharingReduction) override
Emits the following code for reduction clause with task modifier:
void emitOrderedRegion(CodeGenFunction &CGF, const RegionCodeGenTy &OrderedOpGen, SourceLocation Loc, bool IsThreads) override
Emit an ordered region.
void emitForStaticFinish(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind DKind) override
Call the appropriate runtime routine to notify that we finished all the work with current loop.
llvm::Value * emitTaskReductionInit(CodeGenFunction &CGF, SourceLocation Loc, ArrayRef< const Expr * > LHSExprs, ArrayRef< const Expr * > RHSExprs, const OMPTaskDataTy &Data) override
Emit a code for initialization of task reduction clause.
void emitProcBindClause(CodeGenFunction &CGF, llvm::omp::ProcBindKind ProcBind, SourceLocation Loc) override
Emit call to void __kmpc_push_proc_bind(ident_t *loc, kmp_int32global_tid, int proc_bind) to generate...
void emitTargetOutlinedFunction(const OMPExecutableDirective &D, StringRef ParentName, llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID, bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) override
Emit outilined function for 'target' directive.
void emitMasterRegion(CodeGenFunction &CGF, const RegionCodeGenTy &MasterOpGen, SourceLocation Loc) override
Emits a master region.
void emitNumTeamsClause(CodeGenFunction &CGF, const Expr *NumTeams, const Expr *ThreadLimit, SourceLocation Loc) override
Emits call to void __kmpc_push_num_teams(ident_t *loc, kmp_int32global_tid, kmp_int32 num_teams,...
void emitForDispatchDeinit(CodeGenFunction &CGF, SourceLocation Loc) override
This is used for non static scheduled types and when the ordered clause is present on the loop constr...
const VarDecl * translateParameter(const FieldDecl *FD, const VarDecl *NativeParam) const override
Translates the native parameter of outlined function if this is required for target.
void emitNumThreadsClause(CodeGenFunction &CGF, llvm::Value *NumThreads, SourceLocation Loc, OpenMPNumThreadsClauseModifier Modifier=OMPC_NUMTHREADS_unknown, OpenMPSeverityClauseKind Severity=OMPC_SEVERITY_fatal, SourceLocation SeverityLoc=SourceLocation(), const Expr *Message=nullptr, SourceLocation MessageLoc=SourceLocation()) override
Emits call to void __kmpc_push_num_threads(ident_t *loc, kmp_int32global_tid, kmp_int32 num_threads) ...
void emitMaskedRegion(CodeGenFunction &CGF, const RegionCodeGenTy &MaskedOpGen, SourceLocation Loc, const Expr *Filter=nullptr) override
Emits a masked region.
void emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc, const OMPExecutableDirective &D, llvm::Function *TaskFunction, QualType SharedsTy, Address Shareds, const Expr *IfCond, const OMPTaskDataTy &Data) override
Emit task region for the task directive.
void emitTargetCall(CodeGenFunction &CGF, const OMPExecutableDirective &D, llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID, const Expr *IfCond, llvm::PointerIntPair< const Expr *, 2, OpenMPDeviceClauseModifier > Device, llvm::function_ref< llvm::Value *(CodeGenFunction &CGF, const OMPLoopDirective &D)> SizeEmitter) override
Emit the target offloading code associated with D.
bool emitTargetFunctions(GlobalDecl GD) override
Emit the target regions enclosed in GD function definition or the function itself in case it is a val...
void emitDoacrossInit(CodeGenFunction &CGF, const OMPLoopDirective &D, ArrayRef< Expr * > NumIterations) override
Emit initialization for doacross loop nesting support.
void emitCancelCall(CodeGenFunction &CGF, SourceLocation Loc, const Expr *IfCond, OpenMPDirectiveKind CancelRegion) override
Emit code for 'cancel' construct.
void emitTaskwaitCall(CodeGenFunction &CGF, SourceLocation Loc, const OMPTaskDataTy &Data) override
Emit code for 'taskwait' directive.
void emitTaskgroupRegion(CodeGenFunction &CGF, const RegionCodeGenTy &TaskgroupOpGen, SourceLocation Loc) override
Emit a taskgroup region.
void emitTargetDataCalls(CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, const Expr *Device, const RegionCodeGenTy &CodeGen, CGOpenMPRuntime::TargetDataInfo &Info) override
Emit the target data mapping code associated with D.
void emitForDispatchInit(CodeGenFunction &CGF, SourceLocation Loc, const OpenMPScheduleTy &ScheduleKind, unsigned IVSize, bool IVSigned, bool Ordered, const DispatchRTInput &DispatchValues) override
This is used for non static scheduled types and when the ordered clause is present on the loop constr...
llvm::Function * emitTaskOutlinedFunction(const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, const VarDecl *PartIDVar, const VarDecl *TaskTVar, OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen, bool Tied, unsigned &NumberOfParts) override
Emits outlined function for the OpenMP task directive D.
void emitTaskLoopCall(CodeGenFunction &CGF, SourceLocation Loc, const OMPLoopDirective &D, llvm::Function *TaskFunction, QualType SharedsTy, Address Shareds, const Expr *IfCond, const OMPTaskDataTy &Data) override
Emit task region for the taskloop directive.
unsigned getNonVirtualBaseLLVMFieldNo(const CXXRecordDecl *RD) const
llvm::StructType * getLLVMType() const
Return the "complete object" LLVM type associated with this record.
llvm::StructType * getBaseSubobjectLLVMType() const
Return the "base subobject" LLVM type associated with this record.
unsigned getLLVMFieldNo(const FieldDecl *FD) const
Return llvm::StructType element number that corresponds to the field FD.
unsigned getVirtualBaseIndex(const CXXRecordDecl *base) const
Return the LLVM field index corresponding to the given virtual base.
API for captured statement code generation.
virtual void EmitBody(CodeGenFunction &CGF, const Stmt *S)
Emit the captured statement body.
virtual const FieldDecl * lookup(const VarDecl *VD) const
Lookup the captured field decl for a variable.
RAII for correct setting/restoring of CapturedStmtInfo.
The scope used to remap some variables as private in the OpenMP loop body (or other captured region e...
bool Privatize()
Privatizes local variables previously registered as private.
bool addPrivate(const VarDecl *LocalVD, Address Addr)
Registers LocalVD variable as a private with Addr as the address of the corresponding private variabl...
An RAII object to set (and then clear) a mapping for an OpaqueValueExpr.
Enters a new scope for capturing cleanups, all of which will be executed once the scope is exited.
CodeGenFunction - This class organizes the per-function state that is used while generating LLVM code...
LValue EmitLoadOfReferenceLValue(LValue RefLVal)
void EmitBranchOnBoolExpr(const Expr *Cond, llvm::BasicBlock *TrueBlock, llvm::BasicBlock *FalseBlock, uint64_t TrueCount, Stmt::Likelihood LH=Stmt::LH_None, const Expr *ConditionalOp=nullptr, const VarDecl *ConditionalDecl=nullptr)
EmitBranchOnBoolExpr - Emit a branch on a boolean condition (e.g.
void emitDestroy(Address addr, QualType type, Destroyer *destroyer, bool useEHCleanupForArray)
emitDestroy - Immediately perform the destruction of the given object.
JumpDest getJumpDestInCurrentScope(llvm::BasicBlock *Target)
The given basic block lies in the current EH scope, but may be a target of a potentially scope-crossi...
static void EmitOMPTargetParallelDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetParallelDirective &S)
void EmitNullInitialization(Address DestPtr, QualType Ty)
EmitNullInitialization - Generate code to set a value of the given type to null, If the type contains...
Address LoadCXXThisAddress()
CGCapturedStmtInfo * CapturedStmtInfo
ComplexPairTy EmitLoadOfComplex(LValue src, SourceLocation loc)
EmitLoadOfComplex - Load a complex number from the specified l-value.
static void EmitOMPTargetDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetDirective &S)
Emit device code for the target directive.
static void EmitOMPTargetTeamsDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsDirective &S)
Emit device code for the target teams directive.
static void EmitOMPTargetTeamsDistributeDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsDistributeDirective &S)
Emit device code for the target teams distribute directive.
llvm::Function * GenerateOpenMPCapturedStmtFunctionAggregate(const CapturedStmt &S, const OMPExecutableDirective &D)
llvm::BasicBlock * createBasicBlock(const Twine &name="", llvm::Function *parent=nullptr, llvm::BasicBlock *before=nullptr)
createBasicBlock - Create an LLVM basic block.
const LangOptions & getLangOpts() const
AutoVarEmission EmitAutoVarAlloca(const VarDecl &var)
EmitAutoVarAlloca - Emit the alloca and debug information for a local variable.
void pushDestroy(QualType::DestructionKind dtorKind, Address addr, QualType type)
pushDestroy - Push the standard destructor for the given type as at least a normal cleanup.
Address EmitLoadOfPointer(Address Ptr, const PointerType *PtrTy, LValueBaseInfo *BaseInfo=nullptr, TBAAAccessInfo *TBAAInfo=nullptr)
Load a pointer with type PtrTy stored at address Ptr.
void EmitBranchThroughCleanup(JumpDest Dest)
EmitBranchThroughCleanup - Emit a branch from the current insert block through the normal cleanup han...
const Decl * CurCodeDecl
CurCodeDecl - This is the inner-most code context, which includes blocks.
Destroyer * getDestroyer(QualType::DestructionKind destructionKind)
llvm::AssertingVH< llvm::Instruction > AllocaInsertPt
AllocaInsertPoint - This is an instruction in the entry block before which we prefer to insert alloca...
void EmitAggregateAssign(LValue Dest, LValue Src, QualType EltTy)
Emit an aggregate assignment.
JumpDest ReturnBlock
ReturnBlock - Unified return block.
void EmitAggregateCopy(LValue Dest, LValue Src, QualType EltTy, AggValueSlot::Overlap_t MayOverlap, bool isVolatile=false)
EmitAggregateCopy - Emit an aggregate copy.
LValue EmitLValueForField(LValue Base, const FieldDecl *Field, bool IsInBounds=true)
RawAddress CreateDefaultAlignTempAlloca(llvm::Type *Ty, const Twine &Name="tmp")
CreateDefaultAlignedTempAlloca - This creates an alloca with the default ABI alignment of the given L...
void GenerateOpenMPCapturedVars(const CapturedStmt &S, SmallVectorImpl< llvm::Value * > &CapturedVars)
void EmitIgnoredExpr(const Expr *E)
EmitIgnoredExpr - Emit an expression in a context which ignores the result.
RValue EmitLoadOfLValue(LValue V, SourceLocation Loc)
EmitLoadOfLValue - Given an expression that represents a value lvalue, this method emits the address ...
LValue EmitArraySectionExpr(const ArraySectionExpr *E, bool IsLowerBound=true)
LValue EmitOMPSharedLValue(const Expr *E)
Emits the lvalue for the expression with possibly captured variable.
void StartFunction(GlobalDecl GD, QualType RetTy, llvm::Function *Fn, const CGFunctionInfo &FnInfo, const FunctionArgList &Args, SourceLocation Loc=SourceLocation(), SourceLocation StartLoc=SourceLocation())
Emit code for the start of a function.
void EmitOMPCopy(QualType OriginalType, Address DestAddr, Address SrcAddr, const VarDecl *DestVD, const VarDecl *SrcVD, const Expr *Copy)
Emit proper copying of data from one variable to another.
llvm::Value * EvaluateExprAsBool(const Expr *E)
EvaluateExprAsBool - Perform the usual unary conversions on the specified expression and compare the ...
JumpDest getOMPCancelDestination(OpenMPDirectiveKind Kind)
llvm::Value * emitArrayLength(const ArrayType *arrayType, QualType &baseType, Address &addr)
emitArrayLength - Compute the length of an array, even if it's a VLA, and drill down to the base elem...
void EmitOMPAggregateAssign(Address DestAddr, Address SrcAddr, QualType OriginalType, const llvm::function_ref< void(Address, Address)> CopyGen)
Perform element by element copying of arrays with type OriginalType from SrcAddr to DestAddr using co...
bool HaveInsertPoint() const
HaveInsertPoint - True if an insertion point is defined.
CGDebugInfo * getDebugInfo()
llvm::Value * getTypeSize(QualType Ty)
Returns calculated size of the specified type.
LValue MakeRawAddrLValue(llvm::Value *V, QualType T, CharUnits Alignment, AlignmentSource Source=AlignmentSource::Type)
Same as MakeAddrLValue above except that the pointer is known to be unsigned.
LValue EmitLValueForFieldInitialization(LValue Base, const FieldDecl *Field)
EmitLValueForFieldInitialization - Like EmitLValueForField, except that if the Field is a reference,...
RawAddress CreateMemTempWithoutCast(QualType T, const Twine &Name="tmp")
CreateMemTemp - Create a temporary memory object of the given type, with appropriate alignmen without...
VlaSizePair getVLASize(const VariableArrayType *vla)
Returns an LLVM value that corresponds to the size, in non-variably-sized elements,...
llvm::CallInst * EmitNounwindRuntimeCall(llvm::FunctionCallee callee, const Twine &name="")
ASTContext & getContext() const
llvm::Value * EmitLoadOfScalar(Address Addr, bool Volatile, QualType Ty, SourceLocation Loc, AlignmentSource Source=AlignmentSource::Type, bool isNontemporal=false)
EmitLoadOfScalar - Load a scalar value from an address, taking care to appropriately convert from the...
void EmitStoreOfComplex(ComplexPairTy V, LValue dest, bool isInit)
EmitStoreOfComplex - Store a complex number into the specified l-value.
const Decl * CurFuncDecl
CurFuncDecl - Holds the Decl for the current outermost non-closure context.
void EmitAutoVarCleanups(const AutoVarEmission &emission)
void EmitStoreThroughLValue(RValue Src, LValue Dst, bool isInit=false)
EmitStoreThroughLValue - Store the specified rvalue into the specified lvalue, where both are guarant...
LValue EmitLoadOfPointerLValue(Address Ptr, const PointerType *PtrTy)
void EmitAnyExprToMem(const Expr *E, Address Location, Qualifiers Quals, bool IsInitializer)
EmitAnyExprToMem - Emits the code necessary to evaluate an arbitrary expression into the given memory...
bool needsEHCleanup(QualType::DestructionKind kind)
Determines whether an EH cleanup is required to destroy a type with the given destruction kind.
llvm::DenseMap< const ValueDecl *, FieldDecl * > LambdaCaptureFields
llvm::CallInst * EmitRuntimeCall(llvm::FunctionCallee callee, const Twine &name="")
llvm::Type * ConvertTypeForMem(QualType T)
static void EmitOMPTargetTeamsDistributeParallelForDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsDistributeParallelForDirective &S)
static void EmitOMPTargetParallelForSimdDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetParallelForSimdDirective &S)
Emit device code for the target parallel for simd directive.
CodeGenTypes & getTypes() const
static TypeEvaluationKind getEvaluationKind(QualType T)
getEvaluationKind - Return the TypeEvaluationKind of QualType T.
void EmitOMPTargetTaskBasedDirective(const OMPExecutableDirective &S, const RegionCodeGenTy &BodyGen, OMPTargetDataInfo &InputInfo)
Address EmitPointerWithAlignment(const Expr *Addr, LValueBaseInfo *BaseInfo=nullptr, TBAAAccessInfo *TBAAInfo=nullptr, KnownNonNull_t IsKnownNonNull=NotKnownNonNull)
EmitPointerWithAlignment - Given an expression with a pointer type, emit the value and compute our be...
static void EmitOMPTargetTeamsDistributeParallelForSimdDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsDistributeParallelForSimdDirective &S)
Emit device code for the target teams distribute parallel for simd directive.
void EmitBranch(llvm::BasicBlock *Block)
EmitBranch - Emit a branch to the specified basic block from the current insert block,...
llvm::Function * GenerateOpenMPCapturedStmtFunction(const CapturedStmt &S, const OMPExecutableDirective &D)
RawAddress CreateMemTemp(QualType T, const Twine &Name="tmp", RawAddress *Alloca=nullptr)
CreateMemTemp - Create a temporary memory object of the given type, with appropriate alignmen and cas...
void EmitVarDecl(const VarDecl &D)
EmitVarDecl - Emit a local variable declaration.
llvm::Value * EmitCheckedInBoundsGEP(llvm::Type *ElemTy, llvm::Value *Ptr, ArrayRef< llvm::Value * > IdxList, bool SignedIndices, bool IsSubtraction, SourceLocation Loc, const Twine &Name="")
Same as IRBuilder::CreateInBoundsGEP, but additionally emits a check to detect undefined behavior whe...
static void EmitOMPTargetParallelGenericLoopDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetParallelGenericLoopDirective &S)
Emit device code for the target parallel loop directive.
llvm::Value * EmitScalarExpr(const Expr *E, bool IgnoreResultAssign=false)
EmitScalarExpr - Emit the computation of the specified expression of LLVM scalar type,...
static bool IsWrappedCXXThis(const Expr *E)
Check if E is a C++ "this" pointer wrapped in value-preserving casts.
LValue MakeAddrLValue(Address Addr, QualType T, AlignmentSource Source=AlignmentSource::Type)
void FinishFunction(SourceLocation EndLoc=SourceLocation())
FinishFunction - Complete IR generation of the current function.
void EmitAtomicStore(RValue rvalue, LValue lvalue, bool isInit)
static void EmitOMPTargetSimdDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetSimdDirective &S)
Emit device code for the target simd directive.
static void EmitOMPTargetParallelForDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetParallelForDirective &S)
Emit device code for the target parallel for directive.
Address GetAddrOfLocalVar(const VarDecl *VD)
GetAddrOfLocalVar - Return the address of a local variable.
bool ConstantFoldsToSimpleInteger(const Expr *Cond, bool &Result, bool AllowLabels=false)
ConstantFoldsToSimpleInteger - If the specified expression does not fold to a constant,...
static void EmitOMPTargetTeamsGenericLoopDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsGenericLoopDirective &S)
Emit device code for the target teams loop directive.
LValue EmitMemberExpr(const MemberExpr *E)
std::pair< llvm::Value *, llvm::Value * > ComplexPairTy
Address ReturnValue
ReturnValue - The temporary alloca to hold the return value.
LValue EmitLValue(const Expr *E, KnownNonNull_t IsKnownNonNull=NotKnownNonNull)
EmitLValue - Emit code to compute a designator that specifies the location of the expression.
void incrementProfileCounter(const Stmt *S, llvm::Value *StepV=nullptr)
Increment the profiler's counter for the given statement by StepV.
static void EmitOMPTargetTeamsDistributeSimdDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsDistributeSimdDirective &S)
Emit device code for the target teams distribute simd directive.
llvm::Value * EmitScalarConversion(llvm::Value *Src, QualType SrcTy, QualType DstTy, SourceLocation Loc)
Emit a conversion from the specified type to the specified destination type, both of which are LLVM s...
void EmitVariablyModifiedType(QualType Ty)
EmitVLASize - Capture all the sizes for the VLA expressions in the given variably-modified type and s...
bool isTrivialInitializer(const Expr *Init)
Determine whether the given initializer is trivial in the sense that it requires no code to be genera...
void EmitStoreOfScalar(llvm::Value *Value, Address Addr, bool Volatile, QualType Ty, AlignmentSource Source=AlignmentSource::Type, bool isInit=false, bool isNontemporal=false)
EmitStoreOfScalar - Store a scalar value to an address, taking care to appropriately convert from the...
void EmitBlock(llvm::BasicBlock *BB, bool IsFinished=false)
EmitBlock - Emit the given block.
void EmitExprAsInit(const Expr *init, const ValueDecl *D, LValue lvalue, bool capturedByInit)
EmitExprAsInit - Emits the code necessary to initialize a location in memory with the given initializ...
LValue MakeNaturalAlignRawAddrLValue(llvm::Value *V, QualType T)
This class organizes the cross-function state that is used while generating LLVM code.
void SetInternalFunctionAttributes(GlobalDecl GD, llvm::Function *F, const CGFunctionInfo &FI)
Set the attributes on the LLVM function for the given decl and function info.
llvm::Module & getModule() const
const IntrusiveRefCntPtr< llvm::vfs::FileSystem > & getFileSystem() const
DiagnosticsEngine & getDiags() const
const LangOptions & getLangOpts() const
CharUnits getNaturalTypeAlignment(QualType T, LValueBaseInfo *BaseInfo=nullptr, TBAAAccessInfo *TBAAInfo=nullptr, bool forPointeeType=false)
CodeGenTypes & getTypes()
CGOpenMPRuntime & getOpenMPRuntime()
Return a reference to the configured OpenMP runtime.
TBAAAccessInfo getTBAAInfoForSubobject(LValue Base, QualType AccessType)
getTBAAInfoForSubobject - Get TBAA information for an access with a given base lvalue.
ASTContext & getContext() const
const CodeGenOptions & getCodeGenOpts() const
StringRef getMangledName(GlobalDecl GD)
std::optional< CharUnits > getOMPAllocateAlignment(const VarDecl *VD)
Return the alignment specified in an allocate directive, if present.
llvm::Constant * EmitNullConstant(QualType T)
Return the result of value-initializing the given type, i.e.
llvm::Type * ConvertType(QualType T)
ConvertType - Convert type T into a llvm::Type.
llvm::FunctionType * GetFunctionType(const CGFunctionInfo &Info)
GetFunctionType - Get the LLVM function type for.
const CGFunctionInfo & arrangeBuiltinFunctionDeclaration(QualType resultType, const FunctionArgList &args)
A builtin function is a freestanding function using the default C conventions.
const CGRecordLayout & getCGRecordLayout(const RecordDecl *)
getCGRecordLayout - Return record layout info for the given record decl.
llvm::GlobalVariable * GetAddrOfVTable(const CXXRecordDecl *RD)
GetAddrOfVTable - Get the address of the VTable for the given record decl.
A specialization of Address that requires the address to be an LLVM Constant.
static ConstantAddress invalid()
bool requiresLandingPad() const
void pushTerminate()
Push a terminate handler on the stack.
void popTerminate()
Pops a terminate handler off the stack.
FunctionArgList - Type for representing both the decl and type of parameters to a function.
LValue - This represents an lvalue references.
CharUnits getAlignment() const
llvm::Value * getPointer(CodeGenFunction &CGF) const
const Qualifiers & getQuals() const
Address getAddress() const
LValueBaseInfo getBaseInfo() const
TBAAAccessInfo getTBAAInfo() const
A basic class for pre|post-action for advanced codegen sequence for OpenMP region.
virtual void Enter(CodeGenFunction &CGF)
RValue - This trivial value class is used to represent the result of an expression that is evaluated.
static RValue get(llvm::Value *V)
static RValue getComplex(llvm::Value *V1, llvm::Value *V2)
llvm::Value * getScalarVal() const
getScalarVal() - Return the Value* of this scalar value.
An abstract representation of an aligned address.
llvm::Type * getElementType() const
Return the type of the values stored in this address.
llvm::Value * getPointer() const
static RawAddress invalid()
Class intended to support codegen of all kind of the reduction clauses.
LValue getSharedLValue(unsigned N) const
Returns LValue for the reduction item.
const Expr * getRefExpr(unsigned N) const
Returns the base declaration of the reduction item.
LValue getOrigLValue(unsigned N) const
Returns LValue for the original reduction item.
bool needCleanups(unsigned N)
Returns true if the private copy requires cleanups.
void emitAggregateType(CodeGenFunction &CGF, unsigned N)
Emits the code for the variable-modified type, if required.
const VarDecl * getBaseDecl(unsigned N) const
Returns the base declaration of the reduction item.
QualType getPrivateType(unsigned N) const
Return the type of the private item.
bool usesReductionInitializer(unsigned N) const
Returns true if the initialization of the reduction item uses initializer from declare reduction cons...
void emitSharedOrigLValue(CodeGenFunction &CGF, unsigned N)
Emits lvalue for the shared and original reduction item.
void emitInitialization(CodeGenFunction &CGF, unsigned N, Address PrivateAddr, Address SharedAddr, llvm::function_ref< bool(CodeGenFunction &)> DefaultInit)
Performs initialization of the private copy for the reduction item.
std::pair< llvm::Value *, llvm::Value * > getSizes(unsigned N) const
Returns the size of the reduction item (in chars and total number of elements in the item),...
ReductionCodeGen(ArrayRef< const Expr * > Shareds, ArrayRef< const Expr * > Origs, ArrayRef< const Expr * > Privates, ArrayRef< const Expr * > ReductionOps)
void emitCleanups(CodeGenFunction &CGF, unsigned N, Address PrivateAddr)
Emits cleanup code for the reduction item.
Address adjustPrivateAddress(CodeGenFunction &CGF, unsigned N, Address PrivateAddr)
Adjusts PrivatedAddr for using instead of the original variable address in normal operations.
Class provides a way to call simple version of codegen for OpenMP region, or an advanced with possibl...
void operator()(CodeGenFunction &CGF) const
void setAction(PrePostActionTy &Action) const
ConstStmtVisitor - This class implements a simple visitor for Stmt subclasses.
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
void addDecl(Decl *D)
Add the declaration D into this context.
A reference to a declared variable, function, enum, etc.
Decl - This represents one declaration (or definition), e.g.
ASTContext & getASTContext() const LLVM_READONLY
virtual Stmt * getBody() const
getBody - If this Decl represents a declaration for a body of code, such as a function or method defi...
llvm::iterator_range< specific_attr_iterator< T > > specific_attrs() const
SourceLocation getLocation() const
DeclContext * getDeclContext()
virtual Decl * getCanonicalDecl()
Retrieves the "canonical" declaration of the given declaration.
SourceLocation getBeginLoc() const LLVM_READONLY
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
This represents one expression.
bool isIntegerConstantExpr(const ASTContext &Ctx) const
Expr * IgnoreParenNoopCasts(const ASTContext &Ctx) LLVM_READONLY
Skip past any parentheses and casts which do not change the value (including ptr->int casts of the sa...
@ SE_AllowSideEffects
Allow any unmodeled side effect.
@ SE_AllowUndefinedBehavior
Allow UB that we can give a value, but not arbitrary unmodeled side effects.
Expr * IgnoreParenCasts() LLVM_READONLY
Skip past any parentheses and casts which might surround this expression until reaching a fixed point...
llvm::APSInt EvaluateKnownConstInt(const ASTContext &Ctx) const
EvaluateKnownConstInt - Call EvaluateAsRValue and return the folded integer.
Expr * IgnoreParenImpCasts() LLVM_READONLY
Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...
bool isEvaluatable(const ASTContext &Ctx, SideEffectsKind AllowSideEffects=SE_NoSideEffects) const
isEvaluatable - Call EvaluateAsRValue to see if this expression can be constant folded without side-e...
bool HasSideEffects(const ASTContext &Ctx, bool IncludePossibleEffects=true) const
HasSideEffects - This routine returns true for all those expressions which have any effect other than...
std::optional< llvm::APSInt > getIntegerConstantExpr(const ASTContext &Ctx, bool AllowRelaxedEval=false) const
isIntegerConstantExpr - Return the value if this expression is a valid integer constant expression.
bool EvaluateAsBooleanCondition(bool &Result, const ASTContext &Ctx, bool InConstantContext=false) const
EvaluateAsBooleanCondition - Return true if this is a constant which we can fold and convert to a boo...
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
static bool isSameComparisonOperand(const Expr *E1, const Expr *E2)
Checks that the two Expr's will refer to the same value as a comparison operand.
bool hasNonTrivialCall(const ASTContext &Ctx) const
Determine whether this expression involves a call to any function that is not trivial.
Represents a member of a struct/union/class.
unsigned getFieldIndex() const
Returns the index of this field within its record, as appropriate for passing to ASTRecordLayout::get...
const RecordDecl * getParent() const
Returns the parent of this field declaration, which is the struct in which this field is defined.
static FieldDecl * Create(const ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, const IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, Expr *BW, bool Mutable, InClassInitStyle InitStyle)
Represents a function declaration or definition.
const ParmVarDecl * getParamDecl(unsigned i) const
QualType getReturnType() const
ArrayRef< ParmVarDecl * > parameters() const
FunctionDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
FunctionDecl * getMostRecentDecl()
Returns the most recent (re)declaration of this declaration.
unsigned getNumParams() const
Return the number of parameters this function must have based on its FunctionType.
FunctionDecl * getPreviousDecl()
Return the previous declaration of this declaration or NULL if this is the first declaration.
GlobalDecl - represents a global declaration.
const Decl * getDecl() const
static ImplicitParamDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation IdLoc, const IdentifierInfo *Id, QualType T, ImplicitParamKind ParamKind)
Create implicit parameter.
static IntegerLiteral * Create(const ASTContext &C, const llvm::APInt &V, QualType type, SourceLocation l)
Returns a new integer literal with value 'V' and type 'type'.
An lvalue reference type, per C++11 [dcl.ref].
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
ValueDecl * getMemberDecl() const
Retrieve the member declaration to which this expression refers.
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
bool isExternallyVisible() const
const Stmt * getPreInitStmt() const
Get pre-initialization statement for the clause.
This is a basic class for representing single OpenMP clause.
ArrayRef< OMPClause * > clauses() const
This represents 'pragma omp declare mapper ...' directive.
Expr * getMapperVarRef()
Get the variable declared in the mapper.
This represents 'pragma omp declare reduction ...' directive.
Expr * getInitializer()
Get initializer expression (if specified) of the declare reduction construct.
Expr * getInitPriv()
Get Priv variable of the initializer.
Expr * getCombinerOut()
Get Out variable of the combiner.
Expr * getCombinerIn()
Get In variable of the combiner.
Expr * getCombiner()
Get combiner expression of the declare reduction construct.
Expr * getInitOrig()
Get Orig variable of the initializer.
OMPDeclareReductionInitKind getInitializerKind() const
Get initializer kind.
This represents 'if' clause in the 'pragma omp ...' directive.
Expr * getCondition() const
Returns condition.
OMPIteratorHelperData & getHelper(unsigned I)
Fetches helper data for the specified iteration space.
unsigned numOfIterators() const
Returns number of iterator definitions.
This represents 'num_threads' clause in the 'pragma omp ...' directive.
This represents 'pragma omp requires...' directive.
clauselist_range clauselists()
This represents 'threadset' clause in the 'pragma omp task ...' directive.
OpaqueValueExpr - An expression referring to an opaque object of a fixed type and value class.
Represents a parameter to a function.
PointerType - C99 6.7.5.1 - Pointer Declarators.
Represents an unpacked "presumed" location which can be presented to the user.
unsigned getColumn() const
Return the presumed column number of this location.
const char * getFilename() const
Return the presumed filename of this location.
unsigned getLine() const
Return the presumed line number of this location.
A (possibly-)qualified type.
void addRestrict()
Add the restrict qualifier to this QualType.
QualType withRestrict() const
bool isNull() const
Return true if this QualType doesn't point to a type yet.
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
Qualifiers getQualifiers() const
Retrieve the set of qualifiers applied to this type.
QualType getNonReferenceType() const
If Type is a reference type (e.g., const int&), returns the type that the reference refers to ("const...
QualType getCanonicalType() const
DestructionKind isDestructedType() const
Returns a nonzero value if objects of this type require non-trivial work to clean up after.
Represents a struct/union/class.
field_iterator field_end() const
field_range fields() const
virtual void completeDefinition()
Note that the definition of this type is now complete.
field_iterator field_begin() const
Scope - A scope is a transient data structure that is used while parsing the program.
Encodes a location in the source.
static SourceLocation getFromRawEncoding(UIntTy Encoding)
Turn a raw encoding of a SourceLocation object into a real SourceLocation.
bool isValid() const
Return true if this is a valid SourceLocation object.
UIntTy getRawEncoding() const
When a SourceLocation itself cannot be used, this returns an (opaque) 32-bit integer encoding for it.
This class handles loading and caching of source files into memory.
PresumedLoc getPresumedLoc(SourceLocation Loc, bool UseLineDirectives=true) const
Returns the "presumed" location of a SourceLocation specifies.
Stmt - This represents one statement.
StmtClass getStmtClass() const
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Stmt * IgnoreContainers(bool IgnoreCaptured=false)
Skip no-op (attributed, compound) container stmts and skip captured stmt at the top,...
SourceLocation getBeginLoc() const LLVM_READONLY
void startDefinition()
Starts the definition of this tag declaration.
The base class of the type hierarchy.
const Type * getPointeeOrArrayElementType() const
If this is a pointer type, return the pointee type.
bool isSignedIntegerType() const
Return true if this is an integer type that is signed, according to C99 6.2.5p4 [char,...
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
RecordDecl * getAsRecordDecl() const
Retrieves the RecordDecl this type refers to.
bool isPointerType() const
CanQualType getCanonicalTypeUnqualified() const
bool isIntegerType() const
isIntegerType() does not include complex integers (a GCC extension).
const T * castAs() const
Member-template castAs<specific type>.
bool isReferenceType() const
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
bool isLValueReferenceType() const
bool isAggregateType() const
Determines whether the type is a C++ aggregate type or C aggregate or union type.
RecordDecl * castAsRecordDecl() const
QualType getCanonicalTypeInternal() const
const Type * getBaseElementTypeUnsafe() const
Get the base element type of this type, potentially discarding type qualifiers.
bool isVariablyModifiedType() const
Whether this type is a variably-modified type (C99 6.7.5).
const ArrayType * getAsArrayTypeUnsafe() const
A variant of getAs<> for array types which silently discards qualifiers from the outermost type.
bool isFloatingType() const
bool isUnsignedIntegerType() const
Return true if this is an integer type that is unsigned, according to C99 6.2.5p6 [which returns true...
bool isAnyPointerType() const
const T * getAs() const
Member-template getAs<specific type>'.
bool isRecordType() const
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Represents a variable declaration or definition.
VarDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
VarDecl * getDefinition(ASTContext &)
Get the real (not just tentative) definition for this declaration.
const Expr * getInit() const
bool hasExternalStorage() const
Returns true if a variable has extern or private_extern storage.
@ DeclarationOnly
This declaration is only a declaration.
DefinitionKind hasDefinition(ASTContext &) const
Check whether this variable is defined in this translation unit.
bool isLocalVarDeclOrParm() const
Similar to isLocalVarDecl but also includes parameters.
const Expr * getAnyInitializer() const
Get the initializer for this variable, no matter which declaration it is attached to.
Represents a C array with a specified size that is not an integer-constant-expression.
Expr * getSizeExpr() const
specific_attr_iterator - Iterates over a subrange of an AttrVec, only providing attributes that are o...
bool isEmptyRecordForLayout(const ASTContext &Context, QualType T)
isEmptyRecordForLayout - Return true iff a structure contains only empty base classes (per isEmptyRec...
@ Type
The l-value was considered opaque, so the alignment was determined from a type.
@ Decl
The l-value was an access to a declared entity or something equivalently strong, like the address of ...
bool isEmptyFieldForLayout(const ASTContext &Context, const FieldDecl *FD)
isEmptyFieldForLayout - Return true iff the field is "empty", that is, either a zero-width bit-field ...
ComparisonResult
Indicates the result of a tentative comparison.
@ Address
A pointer to a ValueDecl.
Top level wrappers for InstallAPI frontend operations.
bool isOpenMPWorksharingDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a worksharing directive.
CanQual< Type > CanQualType
Represents a canonical, potentially-qualified type.
bool needsTaskBasedThreadLimit(OpenMPDirectiveKind DKind)
Checks if the specified target directive, combined or not, needs task based thread_limit.
@ Match
This is not an overload because the signature exactly matches an existing declaration.
@ Ctor_Complete
Complete object ctor.
Privates[]
This class represents the 'transparent' clause in the 'pragma omp task' directive.
bool isa(CodeGen::Address addr)
if(T->getSizeExpr()) TRY_TO(TraverseStmt(const_cast< Expr * >(T -> getSizeExpr())))
bool isOpenMPTargetDataManagementDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a target data offload directive.
static bool classof(const OMPClause *T)
@ Conditional
A conditional (?:) operator.
@ ICIS_NoInit
No in-class initializer.
bool isOpenMPDistributeDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a distribute directive.
@ LCK_ByRef
Capturing by reference.
LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE()
@ Private
'private' clause, allowed on 'parallel', 'serial', 'loop', 'parallel loop', and 'serial loop' constru...
@ Reduction
'reduction' clause, allowed on Parallel, Serial, Loop, and the combined constructs.
@ Present
'present' clause, allowed on Compute and Combined constructs, plus 'data' and 'declare'.
OpenMPScheduleClauseModifier
OpenMP modifiers for 'schedule' clause.
@ OMPC_SCHEDULE_MODIFIER_last
@ OMPC_SCHEDULE_MODIFIER_unknown
nullptr
This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...
bool isOpenMPParallelDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a parallel-kind directive.
OpenMPDistScheduleClauseKind
OpenMP attributes for 'dist_schedule' clause.
bool isOpenMPTaskingDirective(OpenMPDirectiveKind Kind)
Checks if the specified directive kind is one of tasking directives - task, taskloop,...
bool isOpenMPTargetExecutionDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a target code offload directive.
@ OMPC_DYN_GROUPPRIVATE_FALLBACK_unknown
@ Result
The result type of a method or function.
bool isOpenMPTeamsDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a teams-kind directive.
const FunctionProtoType * T
OpenMPDependClauseKind
OpenMP attributes for 'depend' clause.
@ Dtor_Complete
Complete object dtor.
@ Union
The "union" keyword.
bool isOpenMPTargetMapEnteringDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a map-entering target directive.
@ Type
The name was classified as a type.
bool isOpenMPLoopDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a directive with an associated loop construct.
OpenMPSeverityClauseKind
OpenMP attributes for 'severity' clause.
LangAS
Defines the address space values used by the address space qualifier of QualType.
llvm::omp::Directive OpenMPDirectiveKind
OpenMP directives.
bool isOpenMPSimdDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a simd directive.
@ VK_PRValue
A pr-value expression (in the C++11 taxonomy) produces a temporary value.
@ VK_LValue
An l-value expression is a reference to an object with independent storage.
for(const auto &A :T->param_types())
void getOpenMPCaptureRegions(llvm::SmallVectorImpl< OpenMPDirectiveKind > &CaptureRegions, OpenMPDirectiveKind DKind)
Return the captured regions of an OpenMP directive.
OpenMPNumThreadsClauseModifier
@ OMPC_ATOMIC_DEFAULT_MEM_ORDER_unknown
U cast(CodeGen::Address addr)
OpenMPMapModifierKind
OpenMP modifier kind for 'map' clause.
@ OMPC_MAP_MODIFIER_unknown
@ Other
Other implicit parameter.
OpenMPScheduleClauseKind
OpenMP attributes for 'schedule' clause.
bool isOpenMPTaskLoopDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a taskloop directive.
OpenMPThreadsetKind
OpenMP modifiers for 'threadset' clause.
OpenMPMapClauseKind
OpenMP mapping kind for 'map' clause.
Diagnostic wrappers for TextAPI types for error reporting.
__packed_splat4 __packed_splat2 __packed_splat8 __packed_splat4 int32_t
__packed_splat4 __packed_splat2 __packed_splat8 __packed_splat4 __packed_splat2 __packed_splat4 __packed_splat2 __packed_splat8 __packed_splat4 uint32_t
Data for list of allocators.
Expr * AllocatorTraits
Allocator traits.
Expr * Allocator
Allocator.
Maps the expression for the lastprivate variable to the global copy used to store new value because o...
llvm::SmallVector< bool, 8 > IsPrivateVarReduction
A jump destination is an abstract label, branching to which may require a jump out through normal cle...
llvm::BasicBlock * getBlock() const
unsigned NumberOfTargetItems
Address BasePointersArray
llvm::PointerType * VoidPtrTy
llvm::IntegerType * Int64Ty
llvm::IntegerType * Int8Ty
i8, i16, i32, and i64
llvm::CallingConv::ID getRuntimeCC() const
llvm::IntegerType * SizeTy
llvm::PointerType * VoidPtrPtrTy
llvm::IntegerType * Int32Ty
llvm::IntegerType * IntPtrTy
llvm::IntegerType * IntTy
int
CharUnits getPointerAlign() const
OpenMPDependClauseKind DepKind
const Expr * IteratorExpr
SmallVector< const Expr *, 4 > DepExprs
EvalResult is a struct with detailed info about an evaluated expression.
Extra information about a function prototype.
Expr * CounterUpdate
Updater for the internal counter: ++CounterVD;.
Scheduling data for loop-based OpenMP directives.
bool UseFusedDistChunkSchedule
Request the fused distr_static_chunk + static_chunkone runtime schedule in for_static_init.
OpenMPScheduleClauseModifier M2
OpenMPScheduleClauseModifier M1
OpenMPScheduleClauseKind Schedule
Describes how types, statements, expressions, and declarations should be printed.