31#include "llvm/ADT/ArrayRef.h"
32#include "llvm/ADT/SmallSet.h"
33#include "llvm/ADT/SmallVector.h"
34#include "llvm/ADT/StringExtras.h"
35#include "llvm/Bitcode/BitcodeReader.h"
36#include "llvm/IR/Constants.h"
37#include "llvm/IR/DerivedTypes.h"
38#include "llvm/IR/GlobalValue.h"
39#include "llvm/IR/InstrTypes.h"
40#include "llvm/IR/Value.h"
41#include "llvm/Support/AtomicOrdering.h"
42#include "llvm/Support/raw_ostream.h"
50using namespace llvm::omp;
57 enum CGOpenMPRegionKind {
60 ParallelOutlinedRegion,
70 CGOpenMPRegionInfo(
const CapturedStmt &CS,
71 const CGOpenMPRegionKind RegionKind,
74 : CGCapturedStmtInfo(CS,
CR_OpenMP), RegionKind(RegionKind),
75 CodeGen(CodeGen), Kind(Kind), HasCancel(HasCancel) {}
77 CGOpenMPRegionInfo(
const CGOpenMPRegionKind RegionKind,
80 : CGCapturedStmtInfo(
CR_OpenMP), RegionKind(RegionKind), CodeGen(CodeGen),
81 Kind(Kind), HasCancel(HasCancel) {}
85 virtual const VarDecl *getThreadIDVariable()
const = 0;
88 void EmitBody(CodeGenFunction &CGF,
const Stmt *S)
override;
92 virtual LValue getThreadIDVariableLValue(CodeGenFunction &CGF);
94 virtual void emitUntiedSwitch(CodeGenFunction & ) {}
96 CGOpenMPRegionKind getRegionKind()
const {
return RegionKind; }
100 bool hasCancel()
const {
return HasCancel; }
102 static bool classof(
const CGCapturedStmtInfo *Info) {
106 ~CGOpenMPRegionInfo()
override =
default;
109 CGOpenMPRegionKind RegionKind;
110 RegionCodeGenTy CodeGen;
116class CGOpenMPOutlinedRegionInfo final :
public CGOpenMPRegionInfo {
118 CGOpenMPOutlinedRegionInfo(
const CapturedStmt &CS,
const VarDecl *ThreadIDVar,
119 const RegionCodeGenTy &CodeGen,
121 StringRef HelperName)
122 : CGOpenMPRegionInfo(CS, ParallelOutlinedRegion, CodeGen,
Kind,
124 ThreadIDVar(ThreadIDVar), HelperName(HelperName) {
125 assert(ThreadIDVar !=
nullptr &&
"No ThreadID in OpenMP region.");
130 const VarDecl *getThreadIDVariable()
const override {
return ThreadIDVar; }
133 StringRef getHelperName()
const override {
return HelperName; }
135 static bool classof(
const CGCapturedStmtInfo *Info) {
136 return CGOpenMPRegionInfo::classof(Info) &&
138 ParallelOutlinedRegion;
144 const VarDecl *ThreadIDVar;
145 StringRef HelperName;
149class CGOpenMPTaskOutlinedRegionInfo final :
public CGOpenMPRegionInfo {
151 class UntiedTaskActionTy final :
public PrePostActionTy {
153 const VarDecl *PartIDVar;
154 const RegionCodeGenTy UntiedCodeGen;
155 llvm::SwitchInst *UntiedSwitch =
nullptr;
158 UntiedTaskActionTy(
bool Tied,
const VarDecl *PartIDVar,
159 const RegionCodeGenTy &UntiedCodeGen)
160 : Untied(!Tied), PartIDVar(PartIDVar), UntiedCodeGen(UntiedCodeGen) {}
161 void Enter(CodeGenFunction &CGF)
override {
166 PartIDVar->
getType()->castAs<PointerType>());
170 UntiedSwitch = CGF.
Builder.CreateSwitch(Res, DoneBB);
174 UntiedSwitch->addCase(CGF.
Builder.getInt32(0),
176 emitUntiedSwitch(CGF);
179 void emitUntiedSwitch(CodeGenFunction &CGF)
const {
183 PartIDVar->
getType()->castAs<PointerType>());
187 CodeGenFunction::JumpDest CurPoint =
191 UntiedSwitch->addCase(CGF.
Builder.getInt32(UntiedSwitch->getNumCases()),
197 unsigned getNumberOfParts()
const {
return UntiedSwitch->getNumCases(); }
199 CGOpenMPTaskOutlinedRegionInfo(
const CapturedStmt &CS,
200 const VarDecl *ThreadIDVar,
201 const RegionCodeGenTy &CodeGen,
203 const UntiedTaskActionTy &Action)
204 : CGOpenMPRegionInfo(CS, TaskOutlinedRegion, CodeGen,
Kind, HasCancel),
205 ThreadIDVar(ThreadIDVar), Action(Action) {
206 assert(ThreadIDVar !=
nullptr &&
"No ThreadID in OpenMP region.");
211 const VarDecl *getThreadIDVariable()
const override {
return ThreadIDVar; }
214 LValue getThreadIDVariableLValue(CodeGenFunction &CGF)
override;
217 StringRef getHelperName()
const override {
return ".omp_outlined."; }
219 void emitUntiedSwitch(CodeGenFunction &CGF)
override {
220 Action.emitUntiedSwitch(CGF);
223 static bool classof(
const CGCapturedStmtInfo *Info) {
224 return CGOpenMPRegionInfo::classof(Info) &&
232 const VarDecl *ThreadIDVar;
234 const UntiedTaskActionTy &Action;
239class CGOpenMPInlinedRegionInfo :
public CGOpenMPRegionInfo {
241 CGOpenMPInlinedRegionInfo(CodeGenFunction::CGCapturedStmtInfo *OldCSI,
242 const RegionCodeGenTy &CodeGen,
244 : CGOpenMPRegionInfo(InlinedRegion, CodeGen,
Kind, HasCancel),
246 OuterRegionInfo(dyn_cast_or_null<CGOpenMPRegionInfo>(OldCSI)) {}
249 llvm::Value *getContextValue()
const override {
251 return OuterRegionInfo->getContextValue();
252 llvm_unreachable(
"No context value for inlined OpenMP region");
255 void setContextValue(llvm::Value *
V)
override {
256 if (OuterRegionInfo) {
257 OuterRegionInfo->setContextValue(
V);
260 llvm_unreachable(
"No context value for inlined OpenMP region");
264 const FieldDecl *lookup(
const VarDecl *VD)
const override {
266 return OuterRegionInfo->lookup(VD);
272 FieldDecl *getThisFieldDecl()
const override {
274 return OuterRegionInfo->getThisFieldDecl();
280 const VarDecl *getThreadIDVariable()
const override {
282 return OuterRegionInfo->getThreadIDVariable();
287 LValue getThreadIDVariableLValue(CodeGenFunction &CGF)
override {
289 return OuterRegionInfo->getThreadIDVariableLValue(CGF);
290 llvm_unreachable(
"No LValue for inlined OpenMP construct");
294 StringRef getHelperName()
const override {
295 if (
auto *OuterRegionInfo = getOldCSI())
296 return OuterRegionInfo->getHelperName();
297 llvm_unreachable(
"No helper name for inlined OpenMP construct");
300 void emitUntiedSwitch(CodeGenFunction &CGF)
override {
302 OuterRegionInfo->emitUntiedSwitch(CGF);
305 CodeGenFunction::CGCapturedStmtInfo *getOldCSI()
const {
return OldCSI; }
307 static bool classof(
const CGCapturedStmtInfo *Info) {
308 return CGOpenMPRegionInfo::classof(Info) &&
312 ~CGOpenMPInlinedRegionInfo()
override =
default;
316 CodeGenFunction::CGCapturedStmtInfo *OldCSI;
317 CGOpenMPRegionInfo *OuterRegionInfo;
325class CGOpenMPTargetRegionInfo final :
public CGOpenMPRegionInfo {
327 CGOpenMPTargetRegionInfo(
const CapturedStmt &CS,
328 const RegionCodeGenTy &CodeGen, StringRef HelperName)
329 : CGOpenMPRegionInfo(CS, TargetRegion, CodeGen, OMPD_target,
331 HelperName(HelperName) {}
335 const VarDecl *getThreadIDVariable()
const override {
return nullptr; }
338 StringRef getHelperName()
const override {
return HelperName; }
340 static bool classof(
const CGCapturedStmtInfo *Info) {
341 return CGOpenMPRegionInfo::classof(Info) &&
346 StringRef HelperName;
350 llvm_unreachable(
"No codegen for expressions");
354class CGOpenMPInnerExprInfo final :
public CGOpenMPInlinedRegionInfo {
356 CGOpenMPInnerExprInfo(CodeGenFunction &CGF,
const CapturedStmt &CS)
357 : CGOpenMPInlinedRegionInfo(CGF.CapturedStmtInfo, EmptyCodeGen,
365 if (!C.capturesVariable() && !C.capturesVariableByCopy())
368 const VarDecl *VD = C.getCapturedVar();
369 if (VD->isLocalVarDeclOrParm())
372 DeclRefExpr DRE(CGF.getContext(), const_cast<VarDecl *>(VD),
374 VD->getType().getNonReferenceType(), VK_LValue,
376 PrivScope.addPrivate(VD, CGF.EmitLValue(&DRE).getAddress());
378 (
void)PrivScope.Privatize();
382 const FieldDecl *lookup(
const VarDecl *VD)
const override {
383 if (
const FieldDecl *FD = CGOpenMPInlinedRegionInfo::lookup(VD))
389 void EmitBody(CodeGenFunction &CGF,
const Stmt *S)
override {
390 llvm_unreachable(
"No body for expressions");
395 const VarDecl *getThreadIDVariable()
const override {
396 llvm_unreachable(
"No thread id for expressions");
400 StringRef getHelperName()
const override {
401 llvm_unreachable(
"No helper name for expressions");
404 static bool classof(
const CGCapturedStmtInfo *Info) {
return false; }
408 CodeGenFunction::OMPPrivateScope PrivScope;
412class InlinedOpenMPRegionRAII {
413 CodeGenFunction &CGF;
414 llvm::DenseMap<const ValueDecl *, FieldDecl *> LambdaCaptureFields;
415 FieldDecl *LambdaThisCaptureField =
nullptr;
416 const CodeGen::CGBlockInfo *BlockInfo =
nullptr;
417 bool NoInheritance =
false;
424 InlinedOpenMPRegionRAII(CodeGenFunction &CGF,
const RegionCodeGenTy &CodeGen,
426 bool NoInheritance =
true)
427 : CGF(CGF), NoInheritance(NoInheritance) {
429 CGF.CapturedStmtInfo =
new CGOpenMPInlinedRegionInfo(
430 CGF.CapturedStmtInfo, CodeGen, Kind, HasCancel);
432 std::swap(CGF.LambdaCaptureFields, LambdaCaptureFields);
433 LambdaThisCaptureField = CGF.LambdaThisCaptureField;
434 CGF.LambdaThisCaptureField =
nullptr;
435 BlockInfo = CGF.BlockInfo;
436 CGF.BlockInfo =
nullptr;
440 ~InlinedOpenMPRegionRAII() {
444 delete CGF.CapturedStmtInfo;
445 CGF.CapturedStmtInfo = OldCSI;
447 std::swap(CGF.LambdaCaptureFields, LambdaCaptureFields);
448 CGF.LambdaThisCaptureField = LambdaThisCaptureField;
449 CGF.BlockInfo = BlockInfo;
457enum OpenMPLocationFlags :
unsigned {
459 OMP_IDENT_IMD = 0x01,
461 OMP_IDENT_KMPC = 0x02,
463 OMP_ATOMIC_REDUCE = 0x10,
465 OMP_IDENT_BARRIER_EXPL = 0x20,
467 OMP_IDENT_BARRIER_IMPL = 0x40,
469 OMP_IDENT_BARRIER_IMPL_FOR = 0x40,
471 OMP_IDENT_BARRIER_IMPL_SECTIONS = 0xC0,
473 OMP_IDENT_BARRIER_IMPL_SINGLE = 0x140,
475 OMP_IDENT_WORK_LOOP = 0x200,
477 OMP_IDENT_WORK_SECTIONS = 0x400,
479 OMP_IDENT_WORK_DISTRIBUTE = 0x800,
509enum IdentFieldIndex {
511 IdentField_Reserved_1,
515 IdentField_Reserved_2,
517 IdentField_Reserved_3,
526enum OpenMPSchedType {
529 OMP_sch_static_chunked = 33,
531 OMP_sch_dynamic_chunked = 35,
532 OMP_sch_guided_chunked = 36,
533 OMP_sch_runtime = 37,
536 OMP_sch_static_balanced_chunked = 45,
539 OMP_ord_static_chunked = 65,
541 OMP_ord_dynamic_chunked = 67,
542 OMP_ord_guided_chunked = 68,
543 OMP_ord_runtime = 69,
545 OMP_sch_default = OMP_sch_static,
547 OMP_dist_sch_static_chunked = 91,
548 OMP_dist_sch_static = 92,
554 OMP_dist_sch_static_chunked_sch_static_chunkone = 93,
557 OMP_sch_modifier_monotonic = (1 << 29),
559 OMP_sch_modifier_nonmonotonic = (1 << 30),
564class CleanupTy final :
public EHScopeStack::Cleanup {
565 PrePostActionTy *Action;
568 explicit CleanupTy(PrePostActionTy *Action) : Action(Action) {}
569 void Emit(CodeGenFunction &CGF, Flags )
override {
582 Callback(CodeGen, CGF, *PrePostAction);
585 Callback(CodeGen, CGF, Action);
593 if (
const auto *CE = dyn_cast<CallExpr>(ReductionOp))
594 if (
const auto *OVE = dyn_cast<OpaqueValueExpr>(CE->getCallee()))
595 if (
const auto *DRE =
596 dyn_cast<DeclRefExpr>(OVE->getSourceExpr()->IgnoreImpCasts()))
597 if (
const auto *DRD = dyn_cast<OMPDeclareReductionDecl>(DRE->getDecl()))
608 std::pair<llvm::Function *, llvm::Function *>
Reduction =
628 auto *GV =
new llvm::GlobalVariable(
630 llvm::GlobalValue::PrivateLinkage,
Init, Name);
671 llvm::Value *NumElements = CGF.
emitArrayLength(ArrayTy, ElementTy, DestAddr);
675 llvm::Value *SrcBegin =
nullptr;
677 SrcBegin = SrcAddr.emitRawPointer(CGF);
680 llvm::Value *DestEnd =
685 llvm::Value *IsEmpty =
686 CGF.
Builder.CreateICmpEQ(DestBegin, DestEnd,
"omp.arrayinit.isempty");
687 CGF.
Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
690 llvm::BasicBlock *EntryBB = CGF.
Builder.GetInsertBlock();
695 llvm::PHINode *SrcElementPHI =
nullptr;
698 SrcElementPHI = CGF.
Builder.CreatePHI(SrcBegin->getType(), 2,
699 "omp.arraycpy.srcElementPast");
700 SrcElementPHI->addIncoming(SrcBegin, EntryBB);
702 Address(SrcElementPHI, SrcAddr.getElementType(),
703 SrcAddr.getAlignment().alignmentOfArrayElement(ElementSize));
705 llvm::PHINode *DestElementPHI = CGF.
Builder.CreatePHI(
706 DestBegin->getType(), 2,
"omp.arraycpy.destElementPast");
707 DestElementPHI->addIncoming(DestBegin, EntryBB);
715 if (EmitDeclareReductionInit) {
717 SrcElementCurrent, ElementTy);
725 llvm::Value *SrcElementNext = CGF.
Builder.CreateConstGEP1_32(
726 SrcAddr.getElementType(), SrcElementPHI, 1,
727 "omp.arraycpy.dest.element");
728 SrcElementPHI->addIncoming(SrcElementNext, CGF.
Builder.GetInsertBlock());
732 llvm::Value *DestElementNext = CGF.
Builder.CreateConstGEP1_32(
734 "omp.arraycpy.dest.element");
737 CGF.
Builder.CreateICmpEQ(DestElementNext, DestEnd,
"omp.arraycpy.done");
738 CGF.
Builder.CreateCondBr(Done, DoneBB, BodyBB);
739 DestElementPHI->addIncoming(DestElementNext, CGF.
Builder.GetInsertBlock());
751 if (
const auto *OASE = dyn_cast<ArraySectionExpr>(E))
756void ReductionCodeGen::emitAggregateInitialization(
758 const OMPDeclareReductionDecl *DRD) {
762 const auto *PrivateVD =
764 bool EmitDeclareReductionInit =
767 EmitDeclareReductionInit,
768 EmitDeclareReductionInit ? ClausesData[N].ReductionOp
769 : PrivateVD->getInit(),
777 ClausesData.reserve(Shareds.size());
778 SharedAddresses.reserve(Shareds.size());
779 Sizes.reserve(Shareds.size());
780 BaseDecls.reserve(Shareds.size());
781 const auto *IOrig = Origs.begin();
782 const auto *IPriv =
Privates.begin();
783 const auto *IRed = ReductionOps.begin();
784 for (
const Expr *Ref : Shareds) {
785 ClausesData.emplace_back(Ref, *IOrig, *IPriv, *IRed);
786 std::advance(IOrig, 1);
787 std::advance(IPriv, 1);
788 std::advance(IRed, 1);
793 assert(SharedAddresses.size() == N && OrigAddresses.size() == N &&
794 "Number of generated lvalues must be exactly N.");
795 LValue First = emitSharedLValue(CGF, ClausesData[N].Shared);
796 LValue Second = emitSharedLValueUB(CGF, ClausesData[N].Shared);
797 SharedAddresses.emplace_back(
First, Second);
798 if (ClausesData[N].Shared == ClausesData[N].Ref) {
799 OrigAddresses.emplace_back(
First, Second);
801 LValue First = emitSharedLValue(CGF, ClausesData[N].Ref);
802 LValue Second = emitSharedLValueUB(CGF, ClausesData[N].Ref);
803 OrigAddresses.emplace_back(
First, Second);
812 CGF.
getTypeSize(OrigAddresses[N].first.getType().getNonReferenceType()),
817 llvm::Value *SizeInChars;
818 auto *ElemType = OrigAddresses[N].first.getAddress().getElementType();
819 auto *ElemSizeOf = llvm::ConstantExpr::getSizeOf(ElemType);
820 if (AsArraySection) {
821 Size = CGF.
Builder.CreatePtrDiff(ElemType,
822 OrigAddresses[N].second.getPointer(CGF),
823 OrigAddresses[N].first.getPointer(CGF));
824 Size = CGF.
Builder.CreateZExtOrTrunc(Size, ElemSizeOf->getType());
825 Size = CGF.
Builder.CreateNUWAdd(
826 Size, llvm::ConstantInt::get(Size->getType(), 1));
827 SizeInChars = CGF.
Builder.CreateNUWMul(Size, ElemSizeOf);
830 CGF.
getTypeSize(OrigAddresses[N].first.getType().getNonReferenceType());
831 Size = CGF.
Builder.CreateExactUDiv(SizeInChars, ElemSizeOf);
833 Sizes.emplace_back(SizeInChars, Size);
846 assert(!Size && !Sizes[N].second &&
847 "Size should be nullptr for non-variably modified reduction "
862 assert(SharedAddresses.size() > N &&
"No variable was generated");
863 const auto *PrivateVD =
869 (void)DefaultInit(CGF);
870 emitAggregateInitialization(CGF, N, PrivateAddr, SharedAddr, DRD);
871 }
else if (DRD && (DRD->
getInitializer() || !PrivateVD->hasInit())) {
872 (void)DefaultInit(CGF);
873 QualType SharedType = SharedAddresses[N].first.getType();
875 PrivateAddr, SharedAddr, SharedType);
876 }
else if (!DefaultInit(CGF) && PrivateVD->hasInit() &&
879 PrivateVD->
getType().getQualifiers(),
897 CGF.
pushDestroy(DTorKind, PrivateAddr, PrivateType);
916 BaseLV.getType(), BaseLV.getBaseInfo(),
950 const VarDecl *OrigVD =
nullptr;
951 if (
const auto *OASE = dyn_cast<ArraySectionExpr>(Ref)) {
952 const Expr *
Base = OASE->getBase()->IgnoreParenImpCasts();
953 while (
const auto *TempOASE = dyn_cast<ArraySectionExpr>(
Base))
954 Base = TempOASE->getBase()->IgnoreParenImpCasts();
955 while (
const auto *TempASE = dyn_cast<ArraySubscriptExpr>(
Base))
956 Base = TempASE->getBase()->IgnoreParenImpCasts();
959 }
else if (
const auto *ASE = dyn_cast<ArraySubscriptExpr>(Ref)) {
960 const Expr *
Base = ASE->getBase()->IgnoreParenImpCasts();
961 while (
const auto *TempASE = dyn_cast<ArraySubscriptExpr>(
Base))
962 Base = TempASE->getBase()->IgnoreParenImpCasts();
973 BaseDecls.emplace_back(OrigVD);
976 loadToBegin(CGF, OrigVD->getType(), SharedAddresses[N].first.getType(),
978 Address SharedAddr = SharedAddresses[N].first.getAddress();
979 llvm::Value *Adjustment = CGF.
Builder.CreatePtrDiff(
982 llvm::Value *PrivatePointer =
988 SharedAddresses[N].first.getType(),
991 BaseDecls.emplace_back(
1005 getThreadIDVariable()->
getType()->castAs<PointerType>());
1023LValue CGOpenMPTaskOutlinedRegionInfo::getThreadIDVariableLValue(
1026 getThreadIDVariable()->
getType(),
1044 llvm::OpenMPIRBuilderConfig Config(
1045 CGM.getLangOpts().OpenMPIsTargetDevice,
isGPU(),
1046 CGM.getLangOpts().OpenMPOffloadMandatory,
1049 Config.setDefaultTargetAS(
1051 Config.setRuntimeCC(
CGM.getRuntimeCC());
1056 CGM.getLangOpts().OpenMPIsTargetDevice
1057 ?
CGM.getLangOpts().OMPHostIRFile
1062 if (
CGM.getLangOpts().OpenMPForceUSM) {
1064 OMPBuilder.Config.setHasRequiresUnifiedSharedMemory(
true);
1072 if (!
Data.getValue().pointsToAliveValue())
1074 auto *GV = dyn_cast<llvm::GlobalVariable>(
Data.getValue());
1077 if (!GV->isDeclaration() || GV->getNumUses() > 0)
1079 GV->eraseFromParent();
1084 return OMPBuilder.createPlatformSpecificName(Parts);
1087static llvm::Function *
1089 const Expr *CombinerInitializer,
const VarDecl *In,
1090 const VarDecl *Out,
bool IsCombiner) {
1093 QualType PtrTy =
C.getPointerType(Ty).withRestrict();
1095 C,
nullptr, Out->getLocation(),
1098 C,
nullptr, In->getLocation(),
1105 {IsCombiner ?
"omp_combiner" :
"omp_initializer",
""});
1106 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
1110 Fn->addFnAttr(
"sample-profile-suffix-elision-policy",
"selected");
1112 Fn->removeFnAttr(llvm::Attribute::NoInline);
1113 Fn->removeFnAttr(llvm::Attribute::OptimizeNone);
1114 Fn->addFnAttr(llvm::Attribute::AlwaysInline);
1120 Out->getLocation());
1130 (void)
Scope.Privatize();
1131 if (!IsCombiner && Out->hasInit() &&
1134 Out->getType().getQualifiers(),
1137 if (CombinerInitializer)
1139 Scope.ForceCleanup();
1168std::pair<llvm::Function *, llvm::Function *>
1180struct PushAndPopStackRAII {
1181 PushAndPopStackRAII(llvm::OpenMPIRBuilder *OMPBuilder,
CodeGenFunction &CGF,
1182 bool HasCancel, llvm::omp::Directive Kind)
1183 : OMPBuilder(OMPBuilder) {
1199 auto FiniCB = [&CGF](llvm::OpenMPIRBuilder::InsertPointTy IP) {
1200 assert(IP.getBlock()->end() == IP.getPoint() &&
1201 "Clang CG should cause non-terminated block!");
1202 CGBuilderTy::InsertPointGuard IPG(CGF.
Builder);
1207 return llvm::Error::success();
1212 llvm::OpenMPIRBuilder::FinalizationInfo FI({FiniCB, Kind, HasCancel});
1213 OMPBuilder->pushFinalizationCB(std::move(FI));
1215 ~PushAndPopStackRAII() {
1217 OMPBuilder->popFinalizationCB();
1219 llvm::OpenMPIRBuilder *OMPBuilder;
1228 "thread id variable must be of type kmp_int32 *");
1230 bool HasCancel =
false;
1231 if (
const auto *OPD = dyn_cast<OMPParallelDirective>(&D))
1232 HasCancel = OPD->hasCancel();
1233 else if (
const auto *OPD = dyn_cast<OMPTargetParallelDirective>(&D))
1234 HasCancel = OPD->hasCancel();
1235 else if (
const auto *OPSD = dyn_cast<OMPParallelSectionsDirective>(&D))
1236 HasCancel = OPSD->hasCancel();
1237 else if (
const auto *OPFD = dyn_cast<OMPParallelForDirective>(&D))
1238 HasCancel = OPFD->hasCancel();
1239 else if (
const auto *OPFD = dyn_cast<OMPTargetParallelForDirective>(&D))
1240 HasCancel = OPFD->hasCancel();
1241 else if (
const auto *OPFD = dyn_cast<OMPDistributeParallelForDirective>(&D))
1242 HasCancel = OPFD->hasCancel();
1243 else if (
const auto *OPFD =
1244 dyn_cast<OMPTeamsDistributeParallelForDirective>(&D))
1245 HasCancel = OPFD->hasCancel();
1246 else if (
const auto *OPFD =
1247 dyn_cast<OMPTargetTeamsDistributeParallelForDirective>(&D))
1248 HasCancel = OPFD->hasCancel();
1253 PushAndPopStackRAII PSR(&OMPBuilder, CGF, HasCancel, InnermostKind);
1254 CGOpenMPOutlinedRegionInfo CGInfo(*CS, ThreadIDVar,
CodeGen, InnermostKind,
1255 HasCancel, OutlinedHelperName);
1261 std::string Suffix =
getName({
"omp_outlined"});
1262 return (Name + Suffix).str();
1270 std::string Suffix =
getName({
"omp",
"reduction",
"reduction_func"});
1271 return (Name + Suffix).str();
1278 const CapturedStmt *CS = D.getCapturedStmt(OMPD_parallel);
1288 const CapturedStmt *CS = D.getCapturedStmt(OMPD_teams);
1298 bool Tied,
unsigned &NumberOfParts) {
1301 llvm::Value *ThreadID =
getThreadID(CGF, D.getBeginLoc());
1303 llvm::Value *TaskArgs[] = {
1305 CGF.EmitLoadOfPointerLValue(CGF.GetAddrOfLocalVar(TaskTVar),
1308 CGF.EmitRuntimeCall(
OMPBuilder.getOrCreateRuntimeFunction(
1309 CGM.getModule(), OMPRTL___kmpc_omp_task),
1312 CGOpenMPTaskOutlinedRegionInfo::UntiedTaskActionTy Action(Tied, PartIDVar,
1316 "thread id variable must be of type kmp_int32 for tasks");
1321 bool HasCancel =
false;
1322 if (
const auto *TD = dyn_cast<OMPTaskDirective>(&D))
1323 HasCancel = TD->hasCancel();
1324 else if (
const auto *TD = dyn_cast<OMPTaskLoopDirective>(&D))
1325 HasCancel = TD->hasCancel();
1326 else if (
const auto *TD = dyn_cast<OMPMasterTaskLoopDirective>(&D))
1327 HasCancel = TD->hasCancel();
1328 else if (
const auto *TD = dyn_cast<OMPParallelMasterTaskLoopDirective>(&D))
1329 HasCancel = TD->hasCancel();
1332 CGOpenMPTaskOutlinedRegionInfo CGInfo(*CS, ThreadIDVar,
CodeGen,
1333 InnermostKind, HasCancel, Action);
1335 llvm::Function *Res = CGF.GenerateCapturedStmtFunction(*CS);
1337 NumberOfParts = Action.getNumberOfParts();
1342 bool AtCurrentPoint) {
1344 assert(!Elem.ServiceInsertPt &&
"Insert point is set already.");
1346 llvm::Value *Undef = llvm::UndefValue::get(CGF.
Int32Ty);
1347 if (AtCurrentPoint) {
1348 Elem.ServiceInsertPt =
new llvm::BitCastInst(Undef, CGF.
Int32Ty,
"svcpt",
1349 CGF.
Builder.GetInsertBlock());
1351 Elem.ServiceInsertPt =
new llvm::BitCastInst(Undef, CGF.
Int32Ty,
"svcpt");
1352 Elem.ServiceInsertPt->insertAfter(CGF.
AllocaInsertPt->getIterator());
1358 if (Elem.ServiceInsertPt) {
1359 llvm::Instruction *Ptr = Elem.ServiceInsertPt;
1360 Elem.ServiceInsertPt =
nullptr;
1361 Ptr->eraseFromParent();
1368 llvm::raw_svector_ostream OS(Buffer);
1377 if (
const auto *FD = dyn_cast_or_null<FunctionDecl>(CGF.
CurFuncDecl))
1378 OS << FD->getQualifiedNameAsString();
1385 unsigned Flags,
bool EmitLoc) {
1386 uint32_t SrcLocStrSize;
1387 llvm::Constant *SrcLocStr;
1388 if ((!EmitLoc &&
CGM.getCodeGenOpts().getDebugInfo() ==
1389 llvm::codegenoptions::NoDebugInfo) ||
1391 SrcLocStr =
OMPBuilder.getOrCreateDefaultSrcLocStr(SrcLocStrSize);
1393 std::string FunctionName;
1395 if (
const auto *FD = dyn_cast_or_null<FunctionDecl>(CGF.
CurFuncDecl))
1396 FunctionName = FD->getQualifiedNameAsString();
1409 SrcLocStr, SrcLocStrSize, llvm::omp::IdentFlag(Flags), Reserved2Flags);
1414 assert(CGF.
CurFn &&
"No function in current CodeGenFunction.");
1417 if (
CGM.getLangOpts().OpenMPIRBuilder) {
1420 uint32_t SrcLocStrSize;
1421 auto *SrcLocStr =
OMPBuilder.getOrCreateSrcLocStr(
1424 OMPBuilder.getOrCreateIdent(SrcLocStr, SrcLocStrSize));
1427 llvm::Value *ThreadID =
nullptr;
1432 ThreadID = I->second.ThreadID;
1433 if (ThreadID !=
nullptr)
1437 if (
auto *OMPRegionInfo =
1439 if (OMPRegionInfo->getThreadIDVariable()) {
1441 LValue LVal = OMPRegionInfo->getThreadIDVariableLValue(CGF);
1445 CGF.
Builder.GetInsertBlock() == TopBlock ||
1450 CGF.
Builder.GetInsertBlock()) {
1454 if (CGF.
Builder.GetInsertBlock() == TopBlock)
1466 if (!Elem.ServiceInsertPt)
1468 CGBuilderTy::InsertPointGuard IPG(CGF.
Builder);
1469 CGF.
Builder.SetInsertPoint(Elem.ServiceInsertPt);
1473 OMPRTL___kmpc_global_thread_num),
1476 Elem.ThreadID =
Call;
1481 assert(CGF.
CurFn &&
"No function in current CodeGenFunction.");
1487 for (
const auto *D : I->second)
1492 for (
const auto *D : I->second)
1504static llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseKind
1506 std::optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
1507 OMPDeclareTargetDeclAttr::getDeviceType(VD);
1509 return llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseNone;
1511 switch ((
int)*DevTy) {
1512 case OMPDeclareTargetDeclAttr::DT_Host:
1513 return llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseHost;
1515 case OMPDeclareTargetDeclAttr::DT_NoHost:
1516 return llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseNoHost;
1518 case OMPDeclareTargetDeclAttr::DT_Any:
1519 return llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseAny;
1522 return llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseNone;
1527static llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryKind
1529 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> MapType =
1530 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
1532 return llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryNone;
1533 switch ((
int)*MapType) {
1534 case OMPDeclareTargetDeclAttr::MapTypeTy::MT_To:
1535 return llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryTo;
1537 case OMPDeclareTargetDeclAttr::MapTypeTy::MT_Enter:
1538 return llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryEnter;
1539 case OMPDeclareTargetDeclAttr::MapTypeTy::MT_Link:
1540 return llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryLink;
1542 case OMPDeclareTargetDeclAttr::MapTypeTy::MT_Local:
1544 llvm_unreachable(
"MT_Local should not reach convertCaptureClause");
1547 return llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryNone;
1556 auto FileInfoCallBack = [&]() {
1561 PLoc =
SM.getPresumedLoc(BeginLoc,
false);
1566 return OMPBuilder.getTargetEntryUniqueInfo(FileInfoCallBack,
1571 auto AddrOfGlobal = [&VD,
this]() {
return CGM.GetAddrOfGlobal(VD); };
1573 auto LinkageForVariable = [&VD,
this]() {
1574 return CGM.getLLVMLinkageVarDefinition(VD);
1577 std::vector<llvm::GlobalVariable *> GeneratedRefs;
1579 llvm::Type *LlvmPtrTy =
CGM.getTypes().ConvertTypeForMem(
1580 CGM.getContext().getPointerType(VD->
getType()));
1581 llvm::Constant *addr =
OMPBuilder.getAddrOfDeclareTargetVar(
1587 CGM.getMangledName(VD), GeneratedRefs,
CGM.getLangOpts().OpenMPSimd,
1588 CGM.getLangOpts().OMPTargetTriples, LlvmPtrTy, AddrOfGlobal,
1589 LinkageForVariable);
1598 assert(!
CGM.getLangOpts().OpenMPUseTLS ||
1599 !
CGM.getContext().getTargetInfo().isTLSSupported());
1601 std::string Suffix =
getName({
"cache",
""});
1602 return OMPBuilder.getOrCreateInternalVariable(
1603 CGM.Int8PtrPtrTy, Twine(
CGM.getMangledName(VD)).concat(Suffix).str());
1610 if (
CGM.getLangOpts().OpenMPUseTLS &&
1611 CGM.getContext().getTargetInfo().isTLSSupported())
1615 llvm::Value *Args[] = {
1618 CGM.getSize(
CGM.GetTargetTypeStoreSize(VarTy)),
1623 CGM.getModule(), OMPRTL___kmpc_threadprivate_cached),
1635 CGM.getModule(), OMPRTL___kmpc_global_thread_num),
1639 llvm::Value *Args[] = {
1642 Ctor, CopyCtor, Dtor};
1645 CGM.getModule(), OMPRTL___kmpc_threadprivate_register),
1652 if (
CGM.getLangOpts().OpenMPUseTLS &&
1653 CGM.getContext().getTargetInfo().isTLSSupported())
1660 llvm::Value *Ctor =
nullptr, *CopyCtor =
nullptr, *Dtor =
nullptr;
1662 if (
CGM.getLangOpts().CPlusPlus && PerformInit) {
1667 CGM.getContext(),
nullptr, Loc,
1671 const auto &FI =
CGM.getTypes().arrangeBuiltinFunctionDeclaration(
1672 CGM.getContext().VoidPtrTy, Args);
1673 llvm::FunctionType *FTy =
CGM.getTypes().GetFunctionType(FI);
1674 std::string Name =
getName({
"__kmpc_global_ctor_",
""});
1675 llvm::Function *Fn =
1676 CGM.CreateGlobalInitOrCleanUpFunction(FTy, Name, FI, Loc);
1681 CGM.getContext().VoidPtrTy, Dst->getLocation());
1688 CGM.getContext().VoidPtrTy, Dst->getLocation());
1698 CGM.getContext(),
nullptr, Loc,
1702 const auto &FI =
CGM.getTypes().arrangeBuiltinFunctionDeclaration(
1703 CGM.getContext().VoidTy, Args);
1704 llvm::FunctionType *FTy =
CGM.getTypes().GetFunctionType(FI);
1705 std::string Name =
getName({
"__kmpc_global_dtor_",
""});
1706 llvm::Function *Fn =
1707 CGM.CreateGlobalInitOrCleanUpFunction(FTy, Name, FI, Loc);
1715 false,
CGM.getContext().VoidPtrTy, Dst->getLocation());
1730 CopyCtor = llvm::Constant::getNullValue(
CGM.DefaultPtrTy);
1731 if (Ctor ==
nullptr) {
1732 Ctor = llvm::Constant::getNullValue(
CGM.DefaultPtrTy);
1734 if (Dtor ==
nullptr) {
1735 Dtor = llvm::Constant::getNullValue(
CGM.DefaultPtrTy);
1738 auto *InitFunctionTy =
1739 llvm::FunctionType::get(
CGM.VoidTy,
false);
1740 std::string Name =
getName({
"__omp_threadprivate_init_",
""});
1741 llvm::Function *InitFunction =
CGM.CreateGlobalInitOrCleanUpFunction(
1742 InitFunctionTy, Name,
CGM.getTypes().arrangeNullaryFunction());
1746 CGM.getTypes().arrangeNullaryFunction(), ArgList,
1750 return InitFunction;
1758 llvm::GlobalValue *GV) {
1759 std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr =
1760 OMPDeclareTargetDeclAttr::getActiveAttr(FD);
1763 if (!ActiveAttr || !(*ActiveAttr)->getIndirect())
1770 OMPBuilder.OffloadInfoManager.getTargetRegionEntryFnName(Name, EntryInfo);
1776 llvm::GlobalValue *
Addr = GV;
1777 if (
CGM.getLangOpts().OpenMPIsTargetDevice) {
1778 llvm::PointerType *FnPtrTy = llvm::PointerType::get(
1779 CGM.getLLVMContext(),
1780 CGM.getModule().getDataLayout().getProgramAddressSpace());
1781 Addr =
new llvm::GlobalVariable(
1782 CGM.getModule(), FnPtrTy,
1783 true, llvm::GlobalValue::ExternalLinkage, GV, Name,
1784 nullptr, llvm::GlobalValue::NotThreadLocal,
1785 CGM.getModule().getDataLayout().getDefaultGlobalsAddressSpace());
1786 Addr->setVisibility(llvm::GlobalValue::ProtectedVisibility);
1793 OMPBuilder.OffloadInfoManager.registerDeviceGlobalVarEntryInfo(
1794 Name,
Addr,
CGM.GetTargetTypeStoreSize(
CGM.VoidPtrTy).getQuantity(),
1795 llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryIndirect,
1796 llvm::GlobalValue::WeakODRLinkage);
1809 llvm::OpenMPIRBuilder &
OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
1825 llvm::GlobalVariable *
Addr = VTable;
1827 OMPBuilder.OffloadInfoManager.getTargetRegionEntryFnName(AddrName, EntryInfo);
1828 AddrName.append(
"addr");
1830 if (
CGM.getLangOpts().OpenMPIsTargetDevice) {
1831 Addr =
new llvm::GlobalVariable(
1832 CGM.getModule(), VTable->getType(),
1833 true, llvm::GlobalValue::ExternalLinkage, VTable,
1835 nullptr, llvm::GlobalValue::NotThreadLocal,
1836 CGM.getModule().getDataLayout().getDefaultGlobalsAddressSpace());
1837 Addr->setVisibility(llvm::GlobalValue::ProtectedVisibility);
1839 OMPBuilder.OffloadInfoManager.registerDeviceGlobalVarEntryInfo(
1841 CGM.getDataLayout().getTypeAllocSize(VTable->getInitializer()->getType()),
1842 llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryIndirectVTable,
1843 llvm::GlobalValue::WeakODRLinkage);
1852 !
CGM.getOpenMPRuntime().VTableDeclMap.contains(
CXXRecord)) {
1853 auto Res =
CGM.getOpenMPRuntime().VTableDeclMap.try_emplace(
CXXRecord, VD);
1858 assert(VTablesAddr &&
"Expected non-null VTable address");
1859 CGM.getOpenMPRuntime().registerVTableOffloadEntry(VTablesAddr, VD);
1877 auto GetVTableDecl = [](
const Expr *E) {
1888 if (
auto *DRE = dyn_cast<DeclRefExpr>(E)) {
1890 }
else if (
auto *MRE = dyn_cast<MemberExpr>(E)) {
1891 if (
auto *BaseDRE = dyn_cast<DeclRefExpr>(MRE->getBase())) {
1892 if (
auto *BaseVD = dyn_cast<VarDecl>(BaseDRE->getDecl()))
1896 return std::pair<CXXRecordDecl *, const VarDecl *>(
CXXRecord, VD);
1900 for (
const auto *E :
C->varlist()) {
1901 auto DeclPair = GetVTableDecl(E);
1903 if (DeclPair.second)
1912 std::string Suffix =
getName({
"artificial",
""});
1914 llvm::GlobalVariable *GAddr =
OMPBuilder.getOrCreateInternalVariable(
1915 VarLVType, Twine(Name).concat(Suffix).str());
1916 if (
CGM.getLangOpts().OpenMP &&
CGM.getLangOpts().OpenMPUseTLS &&
1917 CGM.getTarget().isTLSSupported()) {
1918 GAddr->setThreadLocal(
true);
1919 return Address(GAddr, GAddr->getValueType(),
1920 CGM.getContext().getTypeAlignInChars(VarType));
1922 std::string CacheSuffix =
getName({
"cache",
""});
1923 llvm::Value *Args[] = {
1931 Twine(Name).concat(Suffix).concat(CacheSuffix).str())};
1936 CGM.getModule(), OMPRTL___kmpc_threadprivate_cached),
1939 VarLVType,
CGM.getContext().getTypeAlignInChars(VarType));
1989 auto &M =
CGM.getModule();
1990 auto &&ThenGen = [&M, OutlinedFn, CapturedVars, RTLoc,
1993 llvm::Value *Args[] = {
1995 CGF.
Builder.getInt32(CapturedVars.size()),
1998 RealArgs.append(std::begin(Args), std::end(Args));
1999 RealArgs.append(CapturedVars.begin(), CapturedVars.end());
2001 llvm::FunctionCallee RTLFn =
2002 OMPBuilder.getOrCreateRuntimeFunction(M, OMPRTL___kmpc_fork_call);
2005 auto &&ElseGen = [&M, OutlinedFn, CapturedVars, RTLoc, Loc,
2011 llvm::Value *Args[] = {RTLoc, ThreadID};
2013 M, OMPRTL___kmpc_serialized_parallel),
2020 ".bound.zero.addr");
2025 OutlinedFnArgs.push_back(ZeroAddrBound.
getPointer());
2026 OutlinedFnArgs.append(CapturedVars.begin(), CapturedVars.end());
2034 OutlinedFn->removeFnAttr(llvm::Attribute::AlwaysInline);
2035 OutlinedFn->addFnAttr(llvm::Attribute::NoInline);
2041 M, OMPRTL___kmpc_end_serialized_parallel),
2060 if (
auto *OMPRegionInfo =
2062 if (OMPRegionInfo->getThreadIDVariable())
2063 return OMPRegionInfo->getThreadIDVariableLValue(CGF).getAddress();
2073 return ThreadIDTemp;
2077 std::string Prefix = Twine(
"gomp_critical_user_", CriticalName).str();
2078 std::string Name =
getName({Prefix,
"var"});
2079 llvm::GlobalVariable *GV =
2081 CGM.setDSOLocal(GV);
2088 llvm::FunctionCallee EnterCallee;
2090 llvm::FunctionCallee ExitCallee;
2093 llvm::BasicBlock *ContBlock =
nullptr;
2096 CommonActionTy(llvm::FunctionCallee EnterCallee,
2098 llvm::FunctionCallee ExitCallee,
2100 : EnterCallee(EnterCallee), EnterArgs(EnterArgs), ExitCallee(ExitCallee),
2105 llvm::Value *CallBool = CGF.
Builder.CreateIsNotNull(EnterRes);
2109 CGF.
Builder.CreateCondBr(CallBool, ThenBlock, ContBlock);
2113 void Done(CodeGenFunction &CGF) {
2118 void Exit(CodeGenFunction &CGF)
override {
2125 StringRef CriticalName,
2134 llvm::FunctionCallee RuntimeFcn =
OMPBuilder.getOrCreateRuntimeFunction(
2136 Hint ? OMPRTL___kmpc_critical_with_hint : OMPRTL___kmpc_critical);
2138 unsigned LockVarArgIdx = 2;
2140 RuntimeFcn.getFunctionType()
2141 ->getParamType(LockVarArgIdx)
2142 ->getPointerAddressSpace())
2144 LockVar, RuntimeFcn.getFunctionType()->getParamType(LockVarArgIdx));
2150 EnterArgs.push_back(CGF.
Builder.CreateIntCast(
2153 CommonActionTy Action(RuntimeFcn, EnterArgs,
2155 CGM.getModule(), OMPRTL___kmpc_end_critical),
2172 CommonActionTy Action(
OMPBuilder.getOrCreateRuntimeFunction(
2173 CGM.getModule(), OMPRTL___kmpc_master),
2176 CGM.getModule(), OMPRTL___kmpc_end_master),
2194 llvm::Value *FilterVal = Filter
2196 : llvm::ConstantInt::get(
CGM.Int32Ty, 0);
2201 CommonActionTy Action(
OMPBuilder.getOrCreateRuntimeFunction(
2202 CGM.getModule(), OMPRTL___kmpc_masked),
2205 CGM.getModule(), OMPRTL___kmpc_end_masked),
2221 llvm::Value *Args[] = {
2223 llvm::ConstantInt::get(
CGM.IntTy, 0,
true)};
2225 CGM.getModule(), OMPRTL___kmpc_omp_taskyield),
2229 if (
auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.
CapturedStmtInfo))
2230 Region->emitUntiedSwitch(CGF);
2243 CommonActionTy Action(
OMPBuilder.getOrCreateRuntimeFunction(
2244 CGM.getModule(), OMPRTL___kmpc_taskgroup),
2247 CGM.getModule(), OMPRTL___kmpc_end_taskgroup),
2256 unsigned Index,
const VarDecl *Var) {
2285 llvm::GlobalValue::InternalLinkage, Name,
2289 Fn->addFnAttr(
"sample-profile-suffix-elision-policy",
"selected");
2290 Fn->setDoesNotRecurse();
2307 for (
unsigned I = 0, E = AssignmentOps.size(); I < E; ++I) {
2308 const auto *DestVar =
2312 const auto *SrcVar =
2318 CGF.
EmitOMPCopy(
Type, DestAddr, SrcAddr, DestVar, SrcVar, AssignmentOps[I]);
2333 assert(CopyprivateVars.size() == SrcExprs.size() &&
2334 CopyprivateVars.size() == DstExprs.size() &&
2335 CopyprivateVars.size() == AssignmentOps.size());
2347 if (!CopyprivateVars.empty()) {
2350 C.getIntTypeForBitwidth(32, 1);
2356 CommonActionTy Action(
OMPBuilder.getOrCreateRuntimeFunction(
2357 CGM.getModule(), OMPRTL___kmpc_single),
2360 CGM.getModule(), OMPRTL___kmpc_end_single),
2373 llvm::APInt ArraySize(32, CopyprivateVars.size());
2374 QualType CopyprivateArrayTy =
C.getConstantArrayType(
2379 CopyprivateArrayTy,
".omp.copyprivate.cpr_list");
2380 for (
unsigned I = 0, E = CopyprivateVars.size(); I < E; ++I) {
2392 SrcExprs, DstExprs, AssignmentOps, Loc);
2393 llvm::Value *BufSize = CGF.
getTypeSize(CopyprivateArrayTy);
2397 llvm::Value *Args[] = {
2401 CL.emitRawPointer(CGF),
2406 CGM.getModule(), OMPRTL___kmpc_copyprivate),
2422 CommonActionTy Action(
OMPBuilder.getOrCreateRuntimeFunction(
2423 CGM.getModule(), OMPRTL___kmpc_ordered),
2426 CGM.getModule(), OMPRTL___kmpc_end_ordered),
2437 if (Kind == OMPD_for)
2438 Flags = OMP_IDENT_BARRIER_IMPL_FOR;
2439 else if (Kind == OMPD_sections)
2440 Flags = OMP_IDENT_BARRIER_IMPL_SECTIONS;
2441 else if (Kind == OMPD_single)
2442 Flags = OMP_IDENT_BARRIER_IMPL_SINGLE;
2443 else if (Kind == OMPD_barrier)
2444 Flags = OMP_IDENT_BARRIER_EXPL;
2446 Flags = OMP_IDENT_BARRIER_IMPL;
2456 S.getClausesOfKind<OMPOrderedClause>(),
2457 [](
const OMPOrderedClause *
C) { return C->getNumForLoops(); })) {
2458 ScheduleKind = OMPC_SCHEDULE_static;
2460 llvm::APInt ChunkSize(32, 1);
2470 bool ForceSimpleCall) {
2472 auto *OMPRegionInfo =
2475 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
2478 CGF.
Builder.restoreIP(AfterIP);
2491 if (OMPRegionInfo) {
2492 if (!ForceSimpleCall && OMPRegionInfo->hasCancel()) {
2495 OMPRTL___kmpc_cancel_barrier),
2504 CGF.
Builder.CreateCondBr(
Cmp, ExitBB, ContBB);
2516 CGM.getModule(), OMPRTL___kmpc_barrier),
2521 Expr *ME,
bool IsFatal) {
2523 : llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
2526 llvm::Value *Args[] = {
2528 llvm::ConstantInt::get(
CGM.Int32Ty, IsFatal ? 2 : 1),
2529 CGF.
Builder.CreatePointerCast(MVL,
CGM.Int8PtrTy)};
2531 CGM.getModule(), OMPRTL___kmpc_error),
2537 bool Chunked,
bool Ordered) {
2538 switch (ScheduleKind) {
2539 case OMPC_SCHEDULE_static:
2540 return Chunked ? (Ordered ? OMP_ord_static_chunked : OMP_sch_static_chunked)
2541 : (Ordered ? OMP_ord_static : OMP_sch_static);
2542 case OMPC_SCHEDULE_dynamic:
2543 return Ordered ? OMP_ord_dynamic_chunked : OMP_sch_dynamic_chunked;
2544 case OMPC_SCHEDULE_guided:
2545 return Ordered ? OMP_ord_guided_chunked : OMP_sch_guided_chunked;
2546 case OMPC_SCHEDULE_runtime:
2547 return Ordered ? OMP_ord_runtime : OMP_sch_runtime;
2548 case OMPC_SCHEDULE_auto:
2549 return Ordered ? OMP_ord_auto : OMP_sch_auto;
2551 assert(!Chunked &&
"chunk was specified but schedule kind not known");
2552 return Ordered ? OMP_ord_static : OMP_sch_static;
2554 llvm_unreachable(
"Unexpected runtime schedule");
2558static OpenMPSchedType
2561 return Chunked ? OMP_dist_sch_static_chunked : OMP_dist_sch_static;
2565 bool Chunked)
const {
2566 OpenMPSchedType Schedule =
2568 return Schedule == OMP_sch_static;
2574 return Schedule == OMP_dist_sch_static;
2578 bool Chunked)
const {
2579 OpenMPSchedType Schedule =
2581 return Schedule == OMP_sch_static_chunked;
2587 return Schedule == OMP_dist_sch_static_chunked;
2591 OpenMPSchedType Schedule =
2593 assert(Schedule != OMP_sch_static_chunked &&
"cannot be chunked here");
2594 return Schedule != OMP_sch_static;
2602 case OMPC_SCHEDULE_MODIFIER_monotonic:
2603 Modifier = OMP_sch_modifier_monotonic;
2605 case OMPC_SCHEDULE_MODIFIER_nonmonotonic:
2606 Modifier = OMP_sch_modifier_nonmonotonic;
2608 case OMPC_SCHEDULE_MODIFIER_simd:
2609 if (Schedule == OMP_sch_static_chunked)
2610 Schedule = OMP_sch_static_balanced_chunked;
2617 case OMPC_SCHEDULE_MODIFIER_monotonic:
2618 Modifier = OMP_sch_modifier_monotonic;
2620 case OMPC_SCHEDULE_MODIFIER_nonmonotonic:
2621 Modifier = OMP_sch_modifier_nonmonotonic;
2623 case OMPC_SCHEDULE_MODIFIER_simd:
2624 if (Schedule == OMP_sch_static_chunked)
2625 Schedule = OMP_sch_static_balanced_chunked;
2637 if (CGM.
getLangOpts().OpenMP >= 50 && Modifier == 0) {
2638 if (!(Schedule == OMP_sch_static_chunked || Schedule == OMP_sch_static ||
2639 Schedule == OMP_sch_static_balanced_chunked ||
2640 Schedule == OMP_ord_static_chunked || Schedule == OMP_ord_static ||
2641 Schedule == OMP_dist_sch_static_chunked ||
2642 Schedule == OMP_dist_sch_static ||
2643 Schedule == OMP_dist_sch_static_chunked_sch_static_chunkone))
2644 Modifier = OMP_sch_modifier_nonmonotonic;
2646 return Schedule | Modifier;
2656 ScheduleKind.
Schedule, DispatchValues.
Chunk !=
nullptr, Ordered);
2658 (Schedule != OMP_sch_static && Schedule != OMP_sch_static_chunked &&
2659 Schedule != OMP_ord_static && Schedule != OMP_ord_static_chunked &&
2660 Schedule != OMP_sch_static_balanced_chunked));
2667 llvm::Value *Chunk = DispatchValues.
Chunk ? DispatchValues.
Chunk
2668 : CGF.
Builder.getIntN(IVSize, 1);
2669 llvm::Value *Args[] = {
2673 CGM, Schedule, ScheduleKind.
M1, ScheduleKind.
M2)),
2676 CGF.
Builder.getIntN(IVSize, 1),
2693 CodeGenFunction &CGF, llvm::Value *UpdateLocation, llvm::Value *ThreadId,
2694 llvm::FunctionCallee ForStaticInitFunction, OpenMPSchedType Schedule,
2701 assert(Schedule == OMP_sch_static || Schedule == OMP_sch_static_chunked ||
2702 Schedule == OMP_sch_static_balanced_chunked ||
2703 Schedule == OMP_ord_static || Schedule == OMP_ord_static_chunked ||
2704 Schedule == OMP_dist_sch_static ||
2705 Schedule == OMP_dist_sch_static_chunked ||
2706 Schedule == OMP_dist_sch_static_chunked_sch_static_chunkone);
2713 llvm::Value *Chunk = Values.
Chunk;
2714 if (Chunk ==
nullptr) {
2715 assert((Schedule == OMP_sch_static || Schedule == OMP_ord_static ||
2716 Schedule == OMP_dist_sch_static) &&
2717 "expected static non-chunked schedule");
2721 assert((Schedule == OMP_sch_static_chunked ||
2722 Schedule == OMP_sch_static_balanced_chunked ||
2723 Schedule == OMP_ord_static_chunked ||
2724 Schedule == OMP_dist_sch_static_chunked ||
2725 Schedule == OMP_dist_sch_static_chunked_sch_static_chunkone) &&
2726 "expected static chunked schedule");
2728 llvm::Value *Args[] = {
2748 OpenMPSchedType ScheduleNum =
2750 ? OMP_dist_sch_static_chunked_sch_static_chunkone
2754 "Expected loop-based or sections-based directive.");
2757 ? OMP_IDENT_WORK_LOOP
2758 : OMP_IDENT_WORK_SECTIONS);
2760 llvm::FunctionCallee StaticInitFunction =
2765 ScheduleNum, ScheduleKind.
M1, ScheduleKind.
M2, Values);
2772 OpenMPSchedType ScheduleNum =
2774 llvm::Value *UpdatedLocation =
2777 llvm::FunctionCallee StaticInitFunction;
2778 bool isGPUDistribute =
2779 CGM.getLangOpts().OpenMPIsTargetDevice &&
CGM.getTriple().isGPU();
2780 StaticInitFunction =
OMPBuilder.createForStaticInitFunction(
2791 assert((DKind == OMPD_distribute || DKind == OMPD_for ||
2792 DKind == OMPD_sections) &&
2793 "Expected distribute, for, or sections directive kind");
2797 llvm::Value *Args[] = {
2800 (DKind == OMPD_target_teams_loop)
2801 ? OMP_IDENT_WORK_DISTRIBUTE
2803 ? OMP_IDENT_WORK_LOOP
2804 : OMP_IDENT_WORK_SECTIONS),
2808 CGM.getLangOpts().OpenMPIsTargetDevice &&
CGM.getTriple().isGPU())
2811 CGM.getModule(), OMPRTL___kmpc_distribute_static_fini),
2815 CGM.getModule(), OMPRTL___kmpc_for_static_fini),
2840 llvm::Value *Args[] = {
2848 OMPBuilder.createDispatchNextFunction(IVSize, IVSigned), Args);
2855 const Expr *Message,
2858 return llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
2867 return llvm::ConstantInt::get(
CGM.Int32Ty,
2868 Severity == OMPC_SEVERITY_warning ? 1 : 2);
2884 RuntimeFunction FnID = OMPRTL___kmpc_push_num_threads;
2885 if (Modifier == OMPC_NUMTHREADS_strict) {
2886 FnID = OMPRTL___kmpc_push_num_threads_strict;
2891 OMPBuilder.getOrCreateRuntimeFunction(
CGM.getModule(), FnID), Args);
2895 ProcBindKind ProcBind,
2899 assert(ProcBind != OMP_PROC_BIND_unknown &&
"Unsupported proc_bind value.");
2901 llvm::Value *Args[] = {
2903 llvm::ConstantInt::get(
CGM.IntTy,
unsigned(ProcBind),
true)};
2905 CGM.getModule(), OMPRTL___kmpc_push_proc_bind),
2918 CGM.getModule(), OMPRTL___kmpc_flush),
2925enum KmpTaskTFields {
2952 if (
CGM.getLangOpts().OpenMPSimd ||
OMPBuilder.OffloadInfoManager.empty())
2955 llvm::OpenMPIRBuilder::EmitMetadataErrorReportFunctionTy &&ErrorReportFn =
2956 [
this](llvm::OpenMPIRBuilder::EmitMetadataErrorKind Kind,
2957 const llvm::TargetRegionEntryInfo &EntryInfo) ->
void {
2959 if (Kind != llvm::OpenMPIRBuilder::EMIT_MD_GLOBAL_VAR_LINK_ERROR) {
2960 for (
auto I =
CGM.getContext().getSourceManager().fileinfo_begin(),
2961 E =
CGM.getContext().getSourceManager().fileinfo_end();
2963 if (I->getFirst().getUniqueID().getDevice() == EntryInfo.DeviceID &&
2964 I->getFirst().getUniqueID().getFile() == EntryInfo.FileID) {
2965 Loc =
CGM.getContext().getSourceManager().translateFileLineCol(
2966 I->getFirst(), EntryInfo.Line, 1);
2972 case llvm::OpenMPIRBuilder::EMIT_MD_TARGET_REGION_ERROR: {
2973 CGM.getDiags().Report(Loc,
2974 diag::err_target_region_offloading_entry_incorrect)
2975 << EntryInfo.ParentName;
2977 case llvm::OpenMPIRBuilder::EMIT_MD_DECLARE_TARGET_ERROR: {
2978 CGM.getDiags().Report(
2979 Loc, diag::err_target_var_offloading_entry_incorrect_with_parent)
2980 << EntryInfo.ParentName;
2982 case llvm::OpenMPIRBuilder::EMIT_MD_GLOBAL_VAR_LINK_ERROR: {
2983 CGM.getDiags().Report(diag::err_target_var_offloading_entry_incorrect);
2985 case llvm::OpenMPIRBuilder::EMIT_MD_GLOBAL_VAR_INDIRECT_ERROR: {
2986 unsigned DiagID =
CGM.getDiags().getCustomDiagID(
2988 "target variable is incorrect: the "
2989 "address is invalid.");
2990 CGM.getDiags().Report(DiagID);
2995 OMPBuilder.createOffloadEntriesAndInfoMetadata(ErrorReportFn);
3002 QualType KmpRoutineEntryTyArgs[] = {KmpInt32Ty,
C.VoidPtrTy};
3005 C.getFunctionType(KmpInt32Ty, KmpRoutineEntryTyArgs, EPI));
3011struct PrivateHelpersTy {
3012 PrivateHelpersTy(
const Expr *OriginalRef,
const VarDecl *Original,
3014 : OriginalRef(OriginalRef), Original(Original), PrivateCopy(PrivateCopy),
3015 PrivateElemInit(PrivateElemInit) {}
3016 PrivateHelpersTy(
const VarDecl *Original) : Original(Original) {}
3017 const Expr *OriginalRef =
nullptr;
3018 const VarDecl *Original =
nullptr;
3019 const VarDecl *PrivateCopy =
nullptr;
3020 const VarDecl *PrivateElemInit =
nullptr;
3021 bool isLocalPrivate()
const {
3022 return !OriginalRef && !PrivateCopy && !PrivateElemInit;
3025typedef std::pair<CharUnits , PrivateHelpersTy> PrivateDataTy;
3030 if (!CVD->
hasAttr<OMPAllocateDeclAttr>())
3032 const auto *AA = CVD->
getAttr<OMPAllocateDeclAttr>();
3034 return !(AA->getAllocatorType() == OMPAllocateDeclAttr::OMPDefaultMemAlloc &&
3035 !AA->getAllocator());
3045 RecordDecl *RD =
C.buildImplicitRecord(
".kmp_privates.t");
3047 for (
const auto &Pair :
Privates) {
3048 const VarDecl *VD = Pair.second.Original;
3052 if (Pair.second.isLocalPrivate()) {
3075 QualType KmpRoutineEntryPointerQTy) {
3095 CanQualType KmpCmplrdataTy =
C.getCanonicalTagType(UD);
3096 RecordDecl *RD =
C.buildImplicitRecord(
"kmp_task_t");
3126 RecordDecl *RD =
C.buildImplicitRecord(
"kmp_task_t_with_privates");
3146static llvm::Function *
3149 QualType KmpTaskTWithPrivatesPtrQTy,
3151 QualType SharedsPtrTy, llvm::Function *TaskFunction,
3152 llvm::Value *TaskPrivatesMap) {
3158 C,
nullptr, Loc,
nullptr,
3161 const auto &TaskEntryFnInfo =
3163 llvm::FunctionType *TaskEntryTy =
3166 auto *TaskEntry = llvm::Function::Create(
3167 TaskEntryTy, llvm::GlobalValue::InternalLinkage, Name, &CGM.
getModule());
3170 TaskEntry->addFnAttr(
"sample-profile-suffix-elision-policy",
"selected");
3171 TaskEntry->setDoesNotRecurse();
3186 const auto *KmpTaskTWithPrivatesQTyRD =
3191 auto PartIdFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTPartId);
3193 llvm::Value *PartidParam = PartIdLVal.getPointer(CGF);
3195 auto SharedsFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTShareds);
3201 auto PrivatesFI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin(), 1);
3202 llvm::Value *PrivatesParam;
3203 if (PrivatesFI != KmpTaskTWithPrivatesQTyRD->field_end()) {
3206 PrivatesLVal.getPointer(CGF), CGF.
VoidPtrTy);
3208 PrivatesParam = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
3211 llvm::Value *CommonArgs[] = {
3212 GtidParam, PartidParam, PrivatesParam, TaskPrivatesMap,
3218 std::end(CommonArgs));
3220 auto LBFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound);
3223 auto UBFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound);
3226 auto StFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTStride);
3229 auto LIFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLastIter);
3232 auto RFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTReductions);
3235 CallArgs.push_back(LBParam);
3236 CallArgs.push_back(UBParam);
3237 CallArgs.push_back(StParam);
3238 CallArgs.push_back(LIParam);
3239 CallArgs.push_back(RParam);
3241 CallArgs.push_back(SharedsParam);
3254 QualType KmpTaskTWithPrivatesPtrQTy,
3255 QualType KmpTaskTWithPrivatesQTy) {
3261 C,
nullptr, Loc,
nullptr,
3264 const auto &DestructorFnInfo =
3266 llvm::FunctionType *DestructorFnTy =
3270 auto *DestructorFn =
3271 llvm::Function::Create(DestructorFnTy, llvm::GlobalValue::InternalLinkage,
3276 DestructorFn->addFnAttr(
"sample-profile-suffix-elision-policy",
"selected");
3277 DestructorFn->setDoesNotRecurse();
3285 const auto *KmpTaskTWithPrivatesQTyRD =
3287 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin());
3289 for (
const auto *Field : FI->getType()->castAsRecordDecl()->fields()) {
3291 Field->getType().isDestructedType()) {
3293 CGF.
pushDestroy(DtorKind, FieldLValue.getAddress(), Field->getType());
3297 return DestructorFn;
3317 C,
nullptr, Loc,
nullptr,
3318 C.getPointerType(PrivatesQTy).withConst().withRestrict(),
3320 Args.push_back(TaskPrivatesArg);
3321 llvm::DenseMap<CanonicalDeclPtr<const VarDecl>,
unsigned> PrivateVarsPos;
3322 unsigned Counter = 1;
3323 for (
const Expr *E :
Data.PrivateVars) {
3325 C,
nullptr, Loc,
nullptr,
3326 C.getPointerType(
C.getPointerType(E->
getType()))
3331 PrivateVarsPos[VD] = Counter;
3334 for (
const Expr *E :
Data.FirstprivateVars) {
3336 C,
nullptr, Loc,
nullptr,
3337 C.getPointerType(
C.getPointerType(E->
getType()))
3342 PrivateVarsPos[VD] = Counter;
3345 for (
const Expr *E :
Data.LastprivateVars) {
3347 C,
nullptr, Loc,
nullptr,
3348 C.getPointerType(
C.getPointerType(E->
getType()))
3353 PrivateVarsPos[VD] = Counter;
3359 Ty =
C.getPointerType(Ty);
3361 Ty =
C.getPointerType(Ty);
3363 C,
nullptr, Loc,
nullptr,
3364 C.getPointerType(
C.getPointerType(Ty)).withConst().withRestrict(),
3366 PrivateVarsPos[VD] = Counter;
3369 const auto &TaskPrivatesMapFnInfo =
3371 llvm::FunctionType *TaskPrivatesMapTy =
3375 auto *TaskPrivatesMap = llvm::Function::Create(
3376 TaskPrivatesMapTy, llvm::GlobalValue::InternalLinkage, Name,
3379 TaskPrivatesMapFnInfo);
3381 TaskPrivatesMap->addFnAttr(
"sample-profile-suffix-elision-policy",
3384 TaskPrivatesMap->removeFnAttr(llvm::Attribute::NoInline);
3385 TaskPrivatesMap->removeFnAttr(llvm::Attribute::OptimizeNone);
3386 TaskPrivatesMap->addFnAttr(llvm::Attribute::AlwaysInline);
3390 TaskPrivatesMapFnInfo, Args, Loc, Loc);
3398 for (
const FieldDecl *Field : PrivatesQTyRD->fields()) {
3400 const VarDecl *VD = Args[PrivateVarsPos[
Privates[Counter].second.Original]];
3404 RefLVal.getAddress(), RefLVal.getType()->castAs<
PointerType>());
3409 return TaskPrivatesMap;
3415 Address KmpTaskSharedsPtr, LValue TDBase,
3421 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->
field_begin());
3435 if ((!IsTargetTask && !
Data.FirstprivateVars.empty() && ForDup) ||
3436 (IsTargetTask && KmpTaskSharedsPtr.
isValid())) {
3443 FI = FI->getType()->castAsRecordDecl()->field_begin();
3444 for (
const PrivateDataTy &Pair :
Privates) {
3446 if (Pair.second.isLocalPrivate()) {
3450 const VarDecl *VD = Pair.second.PrivateCopy;
3455 if (
const VarDecl *Elem = Pair.second.PrivateElemInit) {
3456 const VarDecl *OriginalVD = Pair.second.Original;
3459 LValue SharedRefLValue;
3462 if (IsTargetTask && !SharedField) {
3466 ->getNumParams() == 0 &&
3469 ->getDeclContext()) &&
3470 "Expected artificial target data variable.");
3473 }
else if (ForDup) {
3476 SharedRefLValue.getAddress().withAlignment(
3477 C.getDeclAlign(OriginalVD)),
3479 SharedRefLValue.getTBAAInfo());
3481 Pair.second.Original->getCanonicalDecl()) > 0 ||
3483 SharedRefLValue = CGF.
EmitLValue(Pair.second.OriginalRef);
3486 InlinedOpenMPRegionRAII Region(
3489 SharedRefLValue = CGF.
EmitLValue(Pair.second.OriginalRef);
3500 PrivateLValue.getAddress(), SharedRefLValue.getAddress(),
Type,
3501 [&CGF, Elem,
Init, &CapturesInfo](
Address DestElement,
3504 CodeGenFunction::OMPPrivateScope InitScope(CGF);
3505 InitScope.addPrivate(Elem, SrcElement);
3506 (void)InitScope.Privatize();
3508 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(
3509 CGF, &CapturesInfo);
3510 CGF.EmitAnyExprToMem(Init, DestElement,
3511 Init->getType().getQualifiers(),
3517 InitScope.addPrivate(Elem, SharedRefLValue.getAddress());
3518 (void)InitScope.Privatize();
3534 bool InitRequired =
false;
3535 for (
const PrivateDataTy &Pair :
Privates) {
3536 if (Pair.second.isLocalPrivate())
3538 const VarDecl *VD = Pair.second.PrivateCopy;
3540 InitRequired = InitRequired || (isa_and_nonnull<CXXConstructExpr>(
Init) &&
3545 return InitRequired;
3562 QualType KmpTaskTWithPrivatesPtrQTy,
3569 C,
nullptr, Loc,
nullptr, KmpTaskTWithPrivatesPtrQTy,
3572 C,
nullptr, Loc,
nullptr, KmpTaskTWithPrivatesPtrQTy,
3578 const auto &TaskDupFnInfo =
3582 auto *TaskDup = llvm::Function::Create(
3583 TaskDupTy, llvm::GlobalValue::InternalLinkage, Name, &CGM.
getModule());
3586 TaskDup->addFnAttr(
"sample-profile-suffix-elision-policy",
"selected");
3587 TaskDup->setDoesNotRecurse();
3597 auto LIFI = std::next(KmpTaskTQTyRD->
field_begin(), KmpTaskTLastIter);
3599 TDBase, *KmpTaskTWithPrivatesQTyRD->
field_begin());
3609 if (!
Data.FirstprivateVars.empty()) {
3614 TDBase, *KmpTaskTWithPrivatesQTyRD->
field_begin());
3622 emitPrivatesInit(CGF, D, KmpTaskSharedsPtr, TDBase, KmpTaskTWithPrivatesQTyRD,
3633 for (
const PrivateDataTy &P :
Privates) {
3634 if (P.second.isLocalPrivate())
3636 QualType Ty = P.second.Original->getType().getNonReferenceType();
3645class OMPIteratorGeneratorScope final
3647 CodeGenFunction &CGF;
3648 const OMPIteratorExpr *E =
nullptr;
3649 SmallVector<CodeGenFunction::JumpDest, 4> ContDests;
3650 SmallVector<CodeGenFunction::JumpDest, 4> ExitDests;
3651 OMPIteratorGeneratorScope() =
delete;
3652 OMPIteratorGeneratorScope(OMPIteratorGeneratorScope &) =
delete;
3655 OMPIteratorGeneratorScope(CodeGenFunction &CGF,
const OMPIteratorExpr *E)
3656 : CodeGenFunction::OMPPrivateScope(CGF), CGF(CGF), E(E) {
3659 SmallVector<llvm::Value *, 4> Uppers;
3661 Uppers.push_back(CGF.EmitScalarExpr(E->getHelper(I).Upper));
3662 const auto *VD = cast<VarDecl>(E->getIteratorDecl(I));
3663 addPrivate(VD, CGF.CreateMemTemp(VD->getType(), VD->getName()));
3664 const OMPIteratorHelperData &HelperData = E->getHelper(I);
3666 HelperData.CounterVD,
3667 CGF.CreateMemTemp(HelperData.CounterVD->getType(),
"counter.addr"));
3672 const OMPIteratorHelperData &HelperData = E->getHelper(I);
3674 CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(HelperData.CounterVD),
3675 HelperData.CounterVD->getType());
3677 CGF.EmitStoreOfScalar(
3678 llvm::ConstantInt::get(CLVal.getAddress().getElementType(), 0),
3680 CodeGenFunction::JumpDest &ContDest =
3681 ContDests.emplace_back(CGF.getJumpDestInCurrentScope(
"iter.cont"));
3682 CodeGenFunction::JumpDest &ExitDest =
3683 ExitDests.emplace_back(CGF.getJumpDestInCurrentScope(
"iter.exit"));
3685 llvm::Value *N = Uppers[I];
3688 CGF.EmitBlock(ContDest.getBlock());
3690 CGF.EmitLoadOfScalar(CLVal, HelperData.CounterVD->getLocation());
3692 HelperData.CounterVD->getType()->isSignedIntegerOrEnumerationType()
3693 ? CGF.Builder.CreateICmpSLT(CVal, N)
3694 : CGF.Builder.CreateICmpULT(CVal, N);
3695 llvm::BasicBlock *BodyBB = CGF.createBasicBlock(
"iter.body");
3696 CGF.Builder.CreateCondBr(Cmp, BodyBB, ExitDest.getBlock());
3698 CGF.EmitBlock(BodyBB);
3700 CGF.EmitIgnoredExpr(HelperData.Update);
3703 ~OMPIteratorGeneratorScope() {
3708 const OMPIteratorHelperData &HelperData = E->
getHelper(I - 1);
3713 CGF.
EmitBlock(ExitDests[I - 1].getBlock(), I == 1);
3719static std::pair<llvm::Value *, llvm::Value *>
3721 const auto *OASE = dyn_cast<OMPArrayShapingExpr>(E);
3724 const Expr *
Base = OASE->getBase();
3729 llvm::Value *SizeVal;
3732 SizeVal = CGF.
getTypeSize(OASE->getBase()->getType()->getPointeeType());
3733 for (
const Expr *SE : OASE->getDimensions()) {
3737 SizeVal = CGF.
Builder.CreateNUWMul(SizeVal, Sz);
3739 }
else if (
const auto *ASE =
3742 Address UpAddrAddress = UpAddrLVal.getAddress();
3743 llvm::Value *UpAddr = CGF.
Builder.CreateConstGEP1_32(
3746 SizeVal = CGF.
Builder.CreatePtrDiff(UpAddr,
Addr,
"",
true);
3750 return std::make_pair(
Addr, SizeVal);
3755 QualType FlagsTy =
C.getIntTypeForBitwidth(32,
false);
3756 if (KmpTaskAffinityInfoTy.
isNull()) {
3758 C.buildImplicitRecord(
"kmp_task_affinity_info_t");
3764 KmpTaskAffinityInfoTy =
C.getCanonicalTagType(KmpAffinityInfoRD);
3771 llvm::Function *TaskFunction,
QualType SharedsTy,
3776 const auto *I =
Data.PrivateCopies.begin();
3777 for (
const Expr *E :
Data.PrivateVars) {
3785 I =
Data.FirstprivateCopies.begin();
3786 const auto *IElemInitRef =
Data.FirstprivateInits.begin();
3787 for (
const Expr *E :
Data.FirstprivateVars) {
3797 I =
Data.LastprivateCopies.begin();
3798 for (
const Expr *E :
Data.LastprivateVars) {
3808 Privates.emplace_back(
CGM.getPointerAlign(), PrivateHelpersTy(VD));
3810 Privates.emplace_back(
C.getDeclAlign(VD), PrivateHelpersTy(VD));
3813 [](
const PrivateDataTy &L,
const PrivateDataTy &R) {
3814 return L.first > R.first;
3816 QualType KmpInt32Ty =
C.getIntTypeForBitwidth(32, 1);
3827 assert((D.getDirectiveKind() == OMPD_task ||
3830 "Expected taskloop, task or target directive");
3837 const auto *KmpTaskTQTyRD =
KmpTaskTQTy->castAsRecordDecl();
3839 const RecordDecl *KmpTaskTWithPrivatesQTyRD =
3842 C.getCanonicalTagType(KmpTaskTWithPrivatesQTyRD);
3843 QualType KmpTaskTWithPrivatesPtrQTy =
3844 C.getPointerType(KmpTaskTWithPrivatesQTy);
3845 llvm::Type *KmpTaskTWithPrivatesPtrTy = CGF.
Builder.getPtrTy(0);
3846 llvm::Value *KmpTaskTWithPrivatesTySize =
3848 QualType SharedsPtrTy =
C.getPointerType(SharedsTy);
3851 llvm::Value *TaskPrivatesMap =
nullptr;
3852 llvm::Type *TaskPrivatesMapTy =
3853 std::next(TaskFunction->arg_begin(), 3)->getType();
3855 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->
field_begin());
3859 TaskPrivatesMap, TaskPrivatesMapTy);
3861 TaskPrivatesMap = llvm::ConstantPointerNull::get(
3867 CGM, Loc, D.getDirectiveKind(), KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy,
3868 KmpTaskTWithPrivatesQTy,
KmpTaskTQTy, SharedsPtrTy, TaskFunction,
3880 DestructorsFlag = 0x8,
3881 PriorityFlag = 0x20,
3882 DetachableFlag = 0x40,
3883 FreeAgentFlag = 0x80,
3884 TransparentFlag = 0x100,
3886 unsigned Flags =
Data.Tied ? TiedFlag : 0;
3887 bool NeedsCleanup =
false;
3892 Flags = Flags | DestructorsFlag;
3896 if (Kind == OMPC_THREADSET_omp_pool)
3897 Flags = Flags | FreeAgentFlag;
3899 if (D.getSingleClause<OMPTransparentClause>())
3900 Flags |= TransparentFlag;
3902 if (
Data.Priority.getInt())
3903 Flags = Flags | PriorityFlag;
3905 Flags = Flags | DetachableFlag;
3906 llvm::Value *TaskFlags =
3907 Data.Final.getPointer()
3908 ? CGF.
Builder.CreateSelect(
Data.Final.getPointer(),
3909 CGF.
Builder.getInt32(FinalFlag),
3911 : CGF.
Builder.getInt32(
Data.Final.getInt() ? FinalFlag : 0);
3912 TaskFlags = CGF.
Builder.CreateOr(TaskFlags, CGF.
Builder.getInt32(Flags));
3913 llvm::Value *SharedsSize =
CGM.getSize(
C.getTypeSizeInChars(SharedsTy));
3915 getThreadID(CGF, Loc), TaskFlags, KmpTaskTWithPrivatesTySize,
3918 llvm::Value *NewTask;
3919 if (D.hasClausesOfKind<OMPNowaitClause>()) {
3925 llvm::Value *DeviceID;
3930 DeviceID = CGF.
Builder.getInt64(OMP_DEVICEID_UNDEF);
3931 AllocArgs.push_back(DeviceID);
3934 CGM.getModule(), OMPRTL___kmpc_omp_target_task_alloc),
3939 CGM.getModule(), OMPRTL___kmpc_omp_task_alloc),
3952 llvm::Value *Tid =
getThreadID(CGF, DC->getBeginLoc());
3953 Tid = CGF.
Builder.CreateIntCast(Tid, CGF.
IntTy,
false);
3956 CGM.getModule(), OMPRTL___kmpc_task_allow_completion_event),
3957 {Loc, Tid, NewTask});
3968 llvm::Value *NumOfElements =
nullptr;
3969 unsigned NumAffinities = 0;
3971 if (
const Expr *Modifier =
C->getModifier()) {
3973 for (
unsigned I = 0, E = IE->numOfIterators(); I < E; ++I) {
3977 NumOfElements ? CGF.
Builder.CreateNUWMul(NumOfElements, Sz) : Sz;
3980 NumAffinities +=
C->varlist_size();
3985 enum RTLAffinityInfoFieldsTy { BaseAddr, Len, Flags };
3987 QualType KmpTaskAffinityInfoArrayTy;
3988 if (NumOfElements) {
3989 NumOfElements = CGF.
Builder.CreateNUWAdd(
3990 llvm::ConstantInt::get(CGF.
SizeTy, NumAffinities), NumOfElements);
3993 C.getIntTypeForBitwidth(
C.getTypeSize(
C.getSizeType()), 0),
3997 KmpTaskAffinityInfoArrayTy =
C.getVariableArrayType(
4005 NumOfElements = CGF.
Builder.CreateIntCast(NumOfElements, CGF.
Int32Ty,
4008 KmpTaskAffinityInfoArrayTy =
C.getConstantArrayType(
4010 llvm::APInt(
C.getTypeSize(
C.getSizeType()), NumAffinities),
nullptr,
4015 NumOfElements = llvm::ConstantInt::get(
CGM.Int32Ty, NumAffinities,
4022 bool HasIterator =
false;
4024 if (
C->getModifier()) {
4028 for (
const Expr *E :
C->varlist()) {
4037 Base, *std::next(KmpAffinityInfoRD->field_begin(), BaseAddr));
4042 Base, *std::next(KmpAffinityInfoRD->field_begin(), Len));
4056 const Expr *Modifier =
C->getModifier();
4059 OMPIteratorGeneratorScope IteratorScope(
4061 for (
const Expr *E :
C->varlist()) {
4071 Base, *std::next(KmpAffinityInfoRD->field_begin(), BaseAddr));
4076 Base, *std::next(KmpAffinityInfoRD->field_begin(), Len));
4078 Idx = CGF.
Builder.CreateNUWAdd(
4079 Idx, llvm::ConstantInt::get(Idx->getType(), 1));
4094 CGM.getModule(), OMPRTL___kmpc_omp_reg_task_with_affinity),
4095 {LocRef, GTid, NewTask, NumOfElements, AffinListPtr});
4097 llvm::Value *NewTaskNewTaskTTy =
4099 NewTask, KmpTaskTWithPrivatesPtrTy);
4101 KmpTaskTWithPrivatesQTy);
4112 *std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTShareds)),
4114 CGF.
Int8Ty,
CGM.getNaturalTypeAlignment(SharedsTy));
4128 CGM, Loc, D, KmpTaskTWithPrivatesPtrQTy, KmpTaskTWithPrivatesQTyRD,
4129 KmpTaskTQTyRD, SharedsTy, SharedsPtrTy,
Data,
Privates,
4130 !
Data.LastprivateVars.empty());
4134 enum { Priority = 0, Destructors = 1 };
4136 auto FI = std::next(KmpTaskTQTyRD->field_begin(), Data1);
4137 const auto *KmpCmplrdataUD = (*FI)->getType()->castAsRecordDecl();
4138 assert(KmpCmplrdataUD->isUnion());
4141 CGM, Loc, KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy,
4142 KmpTaskTWithPrivatesQTy);
4145 Data1LV, *std::next(KmpCmplrdataUD->field_begin(), Destructors));
4151 if (
Data.Priority.getInt()) {
4153 TDBase, *std::next(KmpTaskTQTyRD->field_begin(), Data2));
4155 Data2LV, *std::next(KmpCmplrdataUD->field_begin(), Priority));
4158 Result.NewTask = NewTask;
4159 Result.TaskEntry = TaskEntry;
4160 Result.NewTaskNewTaskTTy = NewTaskNewTaskTTy;
4162 Result.KmpTaskTQTyRD = KmpTaskTQTyRD;
4168 RTLDependenceKindTy DepKind;
4170 case OMPC_DEPEND_in:
4171 DepKind = RTLDependenceKindTy::DepIn;
4174 case OMPC_DEPEND_out:
4175 case OMPC_DEPEND_inout:
4176 DepKind = RTLDependenceKindTy::DepInOut;
4178 case OMPC_DEPEND_mutexinoutset:
4179 DepKind = RTLDependenceKindTy::DepMutexInOutSet;
4181 case OMPC_DEPEND_inoutset:
4182 DepKind = RTLDependenceKindTy::DepInOutSet;
4184 case OMPC_DEPEND_outallmemory:
4185 DepKind = RTLDependenceKindTy::DepOmpAllMem;
4187 case OMPC_DEPEND_source:
4188 case OMPC_DEPEND_sink:
4189 case OMPC_DEPEND_depobj:
4190 case OMPC_DEPEND_inoutallmemory:
4192 llvm_unreachable(
"Unknown task dependence type");
4200 FlagsTy =
C.getIntTypeForBitwidth(
C.getTypeSize(
C.BoolTy),
false);
4201 if (KmpDependInfoTy.
isNull()) {
4202 RecordDecl *KmpDependInfoRD =
C.buildImplicitRecord(
"kmp_depend_info");
4208 KmpDependInfoTy =
C.getCanonicalTagType(KmpDependInfoRD);
4212std::pair<llvm::Value *, LValue>
4225 CGF,
Base.getAddress(),
4226 llvm::ConstantInt::get(CGF.
IntPtrTy, -1,
true));
4232 *std::next(KmpDependInfoRD->field_begin(),
4233 static_cast<unsigned int>(RTLDependInfoFields::BaseAddr)));
4235 return std::make_pair(NumDeps,
Base);
4239 llvm::PointerUnion<unsigned *, LValue *> Pos,
4249 OMPIteratorGeneratorScope IteratorScope(
4250 CGF, cast_or_null<OMPIteratorExpr>(
4251 Data.IteratorExpr ?
Data.IteratorExpr->IgnoreParenImpCasts()
4253 for (
const Expr *E :
Data.DepExprs) {
4263 Size = llvm::ConstantInt::get(CGF.
SizeTy, 0);
4266 if (
unsigned *P = dyn_cast<unsigned *>(Pos)) {
4270 assert(E &&
"Expected a non-null expression");
4279 *std::next(KmpDependInfoRD->field_begin(),
4280 static_cast<unsigned int>(RTLDependInfoFields::BaseAddr)));
4284 Base, *std::next(KmpDependInfoRD->field_begin(),
4285 static_cast<unsigned int>(RTLDependInfoFields::Len)));
4291 *std::next(KmpDependInfoRD->field_begin(),
4292 static_cast<unsigned int>(RTLDependInfoFields::Flags)));
4294 llvm::ConstantInt::get(LLVMFlagsTy,
static_cast<unsigned int>(DepKind)),
4296 if (
unsigned *P = dyn_cast<unsigned *>(Pos)) {
4301 Idx = CGF.
Builder.CreateNUWAdd(Idx,
4302 llvm::ConstantInt::get(Idx->getType(), 1));
4311 assert(
Data.DepKind == OMPC_DEPEND_depobj &&
4312 "Expected depobj dependency kind.");
4317 OMPIteratorGeneratorScope IteratorScope(
4318 CGF, cast_or_null<OMPIteratorExpr>(
4319 Data.IteratorExpr ?
Data.IteratorExpr->IgnoreParenImpCasts()
4321 for (
const Expr *E :
Data.DepExprs) {
4322 llvm::Value *NumDeps;
4325 std::tie(NumDeps,
Base) =
4329 C.getUIntPtrType());
4333 llvm::Value *Add = CGF.
Builder.CreateNUWAdd(PrevVal, NumDeps);
4335 SizeLVals.push_back(NumLVal);
4338 for (
unsigned I = 0, E = SizeLVals.size(); I < E; ++I) {
4341 Sizes.push_back(Size);
4351 assert(
Data.DepKind == OMPC_DEPEND_depobj &&
4352 "Expected depobj dependency kind.");
4355 OMPIteratorGeneratorScope IteratorScope(
4356 CGF, cast_or_null<OMPIteratorExpr>(
4357 Data.IteratorExpr ?
Data.IteratorExpr->IgnoreParenImpCasts()
4359 for (
const Expr *E :
Data.DepExprs) {
4360 llvm::Value *NumDeps;
4363 std::tie(NumDeps,
Base) =
4367 llvm::Value *Size = CGF.
Builder.CreateNUWMul(
4376 llvm::Value *Add = CGF.
Builder.CreateNUWAdd(Pos, NumDeps);
4392 llvm::Value *NumOfElements =
nullptr;
4393 unsigned NumDependencies = std::accumulate(
4394 Dependencies.begin(), Dependencies.end(), 0,
4396 return D.DepKind == OMPC_DEPEND_depobj
4398 : (V + (D.IteratorExpr ? 0 : D.DepExprs.size()));
4402 bool HasDepobjDeps =
false;
4403 bool HasRegularWithIterators =
false;
4404 llvm::Value *NumOfDepobjElements = llvm::ConstantInt::get(CGF.
IntPtrTy, 0);
4405 llvm::Value *NumOfRegularWithIterators =
4406 llvm::ConstantInt::get(CGF.
IntPtrTy, 0);
4410 if (D.
DepKind == OMPC_DEPEND_depobj) {
4413 for (llvm::Value *Size : Sizes) {
4414 NumOfDepobjElements =
4415 CGF.
Builder.CreateNUWAdd(NumOfDepobjElements, Size);
4417 HasDepobjDeps =
true;
4422 if (
const auto *IE = cast_or_null<OMPIteratorExpr>(D.
IteratorExpr)) {
4423 llvm::Value *ClauseIteratorSpace =
4424 llvm::ConstantInt::get(CGF.
IntPtrTy, 1);
4428 ClauseIteratorSpace = CGF.
Builder.CreateNUWMul(Sz, ClauseIteratorSpace);
4430 llvm::Value *NumClauseDeps = CGF.
Builder.CreateNUWMul(
4431 ClauseIteratorSpace,
4433 NumOfRegularWithIterators =
4434 CGF.
Builder.CreateNUWAdd(NumOfRegularWithIterators, NumClauseDeps);
4435 HasRegularWithIterators =
true;
4441 if (HasDepobjDeps || HasRegularWithIterators) {
4442 NumOfElements = llvm::ConstantInt::get(
CGM.IntPtrTy, NumDependencies,
4444 if (HasDepobjDeps) {
4446 CGF.
Builder.CreateNUWAdd(NumOfDepobjElements, NumOfElements);
4448 if (HasRegularWithIterators) {
4450 CGF.
Builder.CreateNUWAdd(NumOfRegularWithIterators, NumOfElements);
4453 Loc,
C.getIntTypeForBitwidth(64, 0),
4457 KmpDependInfoArrayTy =
4466 NumOfElements = CGF.
Builder.CreateIntCast(NumOfElements, CGF.
Int32Ty,
4469 KmpDependInfoArrayTy =
C.getConstantArrayType(
4475 NumOfElements = llvm::ConstantInt::get(
CGM.Int32Ty, NumDependencies,
4480 if (Dep.DepKind == OMPC_DEPEND_depobj || Dep.IteratorExpr)
4490 if (Dep.DepKind == OMPC_DEPEND_depobj || !Dep.IteratorExpr)
4495 if (HasDepobjDeps) {
4497 if (Dep.DepKind != OMPC_DEPEND_depobj)
4504 return std::make_pair(NumOfElements, DependenciesArray);
4515 unsigned NumDependencies = Dependencies.
DepExprs.size();
4525 llvm::Value *NumDepsVal;
4527 if (
const auto *IE =
4528 cast_or_null<OMPIteratorExpr>(Dependencies.
IteratorExpr)) {
4529 NumDepsVal = llvm::ConstantInt::get(CGF.
SizeTy, 1);
4533 NumDepsVal = CGF.
Builder.CreateNUWMul(NumDepsVal, Sz);
4535 Size = CGF.
Builder.CreateNUWAdd(llvm::ConstantInt::get(CGF.
SizeTy, 1),
4539 llvm::Value *RecSize =
CGM.getSize(SizeInBytes);
4540 Size = CGF.
Builder.CreateNUWMul(Size, RecSize);
4544 QualType KmpDependInfoArrayTy =
C.getConstantArrayType(
4547 CharUnits Sz =
C.getTypeSizeInChars(KmpDependInfoArrayTy);
4549 NumDepsVal = llvm::ConstantInt::get(CGF.
IntPtrTy, NumDependencies);
4554 llvm::Value *Allocator = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
4555 llvm::Value *Args[] = {ThreadID, Size, Allocator};
4559 CGM.getModule(), OMPRTL___kmpc_alloc),
4560 Args,
".dep.arr.addr");
4564 DependenciesArray =
Address(
Addr, KmpDependInfoLlvmTy, Align);
4570 *std::next(KmpDependInfoRD->field_begin(),
4571 static_cast<unsigned int>(RTLDependInfoFields::BaseAddr)));
4573 llvm::PointerUnion<unsigned *, LValue *> Pos;
4590 return DependenciesArray;
4605 Addr.getElementType(),
Addr.emitRawPointer(CGF),
4606 llvm::ConstantInt::get(CGF.
IntPtrTy, -1,
true));
4611 llvm::Value *Allocator = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
4612 llvm::Value *Args[] = {ThreadID, DepObjAddr, Allocator};
4616 CGM.getModule(), OMPRTL___kmpc_free),
4628 llvm::Value *NumDeps;
4639 llvm::BasicBlock *EntryBB = CGF.
Builder.GetInsertBlock();
4641 llvm::PHINode *ElementPHI =
4646 Base.getTBAAInfo());
4650 Base, *std::next(KmpDependInfoRD->field_begin(),
4651 static_cast<unsigned int>(RTLDependInfoFields::Flags)));
4653 llvm::ConstantInt::get(LLVMFlagsTy,
static_cast<unsigned int>(DepKind)),
4657 llvm::Value *ElementNext =
4660 ElementPHI->addIncoming(ElementNext, CGF.
Builder.GetInsertBlock());
4661 llvm::Value *IsEmpty =
4662 CGF.
Builder.CreateICmpEQ(ElementNext, End,
"omp.isempty");
4663 CGF.
Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
4670 llvm::Function *TaskFunction,
4679 llvm::Value *NewTask =
Result.NewTask;
4680 llvm::Function *TaskEntry =
Result.TaskEntry;
4681 llvm::Value *NewTaskNewTaskTTy =
Result.NewTaskNewTaskTTy;
4686 llvm::Value *NumOfElements;
4687 std::tie(NumOfElements, DependenciesArray) =
4698 llvm::Value *TaskArgs[] = { UpLoc, ThreadID, NewTask };
4699 llvm::Value *DepTaskArgs[7];
4700 if (!
Data.Dependences.empty()) {
4701 DepTaskArgs[0] = UpLoc;
4702 DepTaskArgs[1] = ThreadID;
4703 DepTaskArgs[2] = NewTask;
4704 DepTaskArgs[3] = NumOfElements;
4706 DepTaskArgs[5] = CGF.
Builder.getInt32(0);
4707 DepTaskArgs[6] = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
4709 auto &&ThenCodeGen = [
this, &
Data, TDBase, KmpTaskTQTyRD, &TaskArgs,
4712 auto PartIdFI = std::next(KmpTaskTQTyRD->
field_begin(), KmpTaskTPartId);
4716 if (!
Data.Dependences.empty()) {
4719 CGM.getModule(), OMPRTL___kmpc_omp_task_with_deps),
4723 CGM.getModule(), OMPRTL___kmpc_omp_task),
4729 Region->emitUntiedSwitch(CGF);
4732 llvm::Value *DepWaitTaskArgs[7];
4733 if (!
Data.Dependences.empty()) {
4734 DepWaitTaskArgs[0] = UpLoc;
4735 DepWaitTaskArgs[1] = ThreadID;
4736 DepWaitTaskArgs[2] = NumOfElements;
4738 DepWaitTaskArgs[4] = CGF.
Builder.getInt32(0);
4739 DepWaitTaskArgs[5] = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
4740 DepWaitTaskArgs[6] =
4741 llvm::ConstantInt::get(CGF.
Int32Ty,
Data.HasNowaitClause);
4743 auto &M =
CGM.getModule();
4744 auto &&ElseCodeGen = [
this, &M, &TaskArgs, ThreadID, NewTaskNewTaskTTy,
4745 TaskEntry, &
Data, &DepWaitTaskArgs,
4752 if (!
Data.Dependences.empty())
4754 M, OMPRTL___kmpc_omp_taskwait_deps_51),
4757 auto &&
CodeGen = [TaskEntry, ThreadID, NewTaskNewTaskTTy,
4760 llvm::Value *OutlinedFnArgs[] = {ThreadID, NewTaskNewTaskTTy};
4761 CGF.CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, Loc, TaskEntry,
4770 CommonActionTy Action(
OMPBuilder.getOrCreateRuntimeFunction(
4771 M, OMPRTL___kmpc_omp_task_begin_if0),
4774 M, OMPRTL___kmpc_omp_task_complete_if0),
4790 llvm::Function *TaskFunction,
4810 IfVal = llvm::ConstantInt::getSigned(CGF.
IntTy, 1);
4815 *std::next(
Result.KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound));
4822 *std::next(
Result.KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound));
4829 *std::next(
Result.KmpTaskTQTyRD->field_begin(), KmpTaskTStride));
4837 *std::next(
Result.KmpTaskTQTyRD->field_begin(), KmpTaskTReductions));
4838 if (
Data.Reductions) {
4844 enum { NoSchedule = 0, Grainsize = 1, NumTasks = 2 };
4853 llvm::ConstantInt::getSigned(
4855 llvm::ConstantInt::getSigned(
4857 ?
Data.Schedule.getInt() ? NumTasks : Grainsize
4859 Data.Schedule.getPointer()
4862 : llvm::ConstantInt::get(CGF.
Int64Ty, 0)};
4863 if (
Data.HasModifier)
4864 TaskArgs.push_back(llvm::ConstantInt::get(CGF.
Int32Ty, 1));
4866 TaskArgs.push_back(
Result.TaskDupFn
4869 : llvm::ConstantPointerNull::get(CGF.
VoidPtrTy));
4871 CGM.getModule(),
Data.HasModifier
4872 ? OMPRTL___kmpc_taskloop_5
4873 : OMPRTL___kmpc_taskloop),
4890 const Expr *,
const Expr *)> &RedOpGen,
4891 const Expr *XExpr =
nullptr,
const Expr *EExpr =
nullptr,
4892 const Expr *UpExpr =
nullptr) {
4900 llvm::Value *NumElements = CGF.
emitArrayLength(ArrayTy, ElementTy, LHSAddr);
4905 llvm::Value *LHSEnd =
4910 llvm::Value *IsEmpty =
4911 CGF.
Builder.CreateICmpEQ(LHSBegin, LHSEnd,
"omp.arraycpy.isempty");
4912 CGF.
Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
4915 llvm::BasicBlock *EntryBB = CGF.
Builder.GetInsertBlock();
4920 llvm::PHINode *RHSElementPHI = CGF.
Builder.CreatePHI(
4921 RHSBegin->getType(), 2,
"omp.arraycpy.srcElementPast");
4922 RHSElementPHI->addIncoming(RHSBegin, EntryBB);
4927 llvm::PHINode *LHSElementPHI = CGF.
Builder.CreatePHI(
4928 LHSBegin->getType(), 2,
"omp.arraycpy.destElementPast");
4929 LHSElementPHI->addIncoming(LHSBegin, EntryBB);
4936 Scope.addPrivate(LHSVar, LHSElementCurrent);
4937 Scope.addPrivate(RHSVar, RHSElementCurrent);
4939 RedOpGen(CGF, XExpr, EExpr, UpExpr);
4940 Scope.ForceCleanup();
4943 llvm::Value *LHSElementNext = CGF.
Builder.CreateConstGEP1_32(
4945 "omp.arraycpy.dest.element");
4946 llvm::Value *RHSElementNext = CGF.
Builder.CreateConstGEP1_32(
4948 "omp.arraycpy.src.element");
4951 CGF.
Builder.CreateICmpEQ(LHSElementNext, LHSEnd,
"omp.arraycpy.done");
4952 CGF.
Builder.CreateCondBr(Done, DoneBB, BodyBB);
4953 LHSElementPHI->addIncoming(LHSElementNext, CGF.
Builder.GetInsertBlock());
4954 RHSElementPHI->addIncoming(RHSElementNext, CGF.
Builder.GetInsertBlock());
4964 const Expr *ReductionOp) {
4965 if (
const auto *CE = dyn_cast<CallExpr>(ReductionOp))
4966 if (
const auto *OVE = dyn_cast<OpaqueValueExpr>(CE->getCallee()))
4967 if (
const auto *DRE =
4968 dyn_cast<DeclRefExpr>(OVE->getSourceExpr()->IgnoreImpCasts()))
4969 if (
const auto *DRD =
4970 dyn_cast<OMPDeclareReductionDecl>(DRE->getDecl())) {
4971 std::pair<llvm::Function *, llvm::Function *>
Reduction =
4982 StringRef ReducerName,
SourceLocation Loc, llvm::Type *ArgsElemType,
4996 CGM.getTypes().arrangeBuiltinFunctionDeclaration(
C.VoidTy, Args);
4998 auto *Fn = llvm::Function::Create(
CGM.getTypes().GetFunctionType(CGFI),
4999 llvm::GlobalValue::InternalLinkage, Name,
5002 if (!
CGM.getCodeGenOpts().SampleProfileFile.empty())
5003 Fn->addFnAttr(
"sample-profile-suffix-elision-policy",
"selected");
5004 Fn->setDoesNotRecurse();
5023 const auto *IPriv =
Privates.begin();
5025 for (
unsigned I = 0, E = ReductionOps.size(); I < E; ++I, ++IPriv, ++Idx) {
5026 const auto *RHSVar =
5029 const auto *LHSVar =
5032 QualType PrivTy = (*IPriv)->getType();
5048 const auto *ILHS = LHSExprs.begin();
5049 const auto *IRHS = RHSExprs.begin();
5050 for (
const Expr *E : ReductionOps) {
5051 if ((*IPriv)->getType()->isArrayType()) {
5056 CGF, (*IPriv)->getType(), LHSVar, RHSVar,
5058 emitReductionCombiner(CGF, E);
5068 Scope.ForceCleanup();
5074 const Expr *ReductionOp,
5075 const Expr *PrivateRef,
5083 CGF, PrivateRef->
getType(), LHSVar, RHSVar,
5085 emitReductionCombiner(CGF, ReductionOp);
5094 llvm::StringRef Prefix,
const Expr *Ref);
5098 const Expr *LHSExprs,
const Expr *RHSExprs,
const Expr *ReductionOps) {
5125 std::string ReductionVarNameStr;
5126 if (
const auto *DRE = dyn_cast<DeclRefExpr>(
Privates->IgnoreParenCasts()))
5127 ReductionVarNameStr =
5130 ReductionVarNameStr =
"unnamed_priv_var";
5133 std::string SharedName =
5134 CGM.getOpenMPRuntime().getName({
"internal_pivate_", ReductionVarNameStr});
5135 llvm::GlobalVariable *SharedVar =
OMPBuilder.getOrCreateInternalVariable(
5136 LLVMType,
".omp.reduction." + SharedName);
5138 SharedVar->setAlignment(
5146 llvm::Value *BarrierArgs[] = {BarrierLoc, ThreadId};
5151 llvm::Value *IsWorker = CGF.
Builder.CreateICmpEQ(
5152 ThreadId, llvm::ConstantInt::get(ThreadId->getType(), 0));
5153 CGF.
Builder.CreateCondBr(IsWorker, InitBB, InitEndBB);
5157 auto EmitSharedInit = [&]() {
5160 std::pair<llvm::Function *, llvm::Function *> FnPair =
5162 llvm::Function *InitializerFn = FnPair.second;
5163 if (InitializerFn) {
5164 if (
const auto *CE =
5165 dyn_cast<CallExpr>(UDRInitExpr->IgnoreParenImpCasts())) {
5172 LocalScope.addPrivate(OutVD, SharedResult);
5174 (void)LocalScope.Privatize();
5175 if (
const auto *OVE = dyn_cast<OpaqueValueExpr>(
5176 CE->getCallee()->IgnoreParenImpCasts())) {
5202 if (
const auto *DRE = dyn_cast<DeclRefExpr>(
Privates)) {
5203 if (
const auto *VD = dyn_cast<VarDecl>(DRE->getDecl())) {
5214 CGF.
Builder.CreateBr(InitEndBB);
5218 CGM.getModule(), OMPRTL___kmpc_barrier),
5221 const Expr *ReductionOp = ReductionOps;
5226 auto EmitCriticalReduction = [&](
auto ReductionGen) {
5227 std::string CriticalName =
getName({
"reduction_critical"});
5235 std::pair<llvm::Function *, llvm::Function *> FnPair =
5238 if (
const auto *CE = dyn_cast<CallExpr>(ReductionOp)) {
5250 (void)LocalScope.Privatize();
5255 EmitCriticalReduction(ReductionGen);
5260 if (
const auto *Cleanup = dyn_cast<ExprWithCleanups>(ReductionClauseExpr))
5263 const Expr *AssignRHS =
nullptr;
5264 if (
const auto *BinOp = dyn_cast<BinaryOperator>(ReductionClauseExpr)) {
5265 if (BinOp->getOpcode() == BO_Assign)
5266 AssignRHS = BinOp->getRHS();
5267 }
else if (
const auto *OpCall =
5268 dyn_cast<CXXOperatorCallExpr>(ReductionClauseExpr)) {
5269 if (OpCall->getOperator() == OO_Equal)
5270 AssignRHS = OpCall->getArg(1);
5274 "Private Variable Reduction : Invalid ReductionOp expression");
5279 const auto *OmpOutDRE =
5281 const auto *OmpInDRE =
5284 OmpOutDRE && OmpInDRE &&
5285 "Private Variable Reduction : LHSExpr/RHSExpr must be DeclRefExprs");
5289 LocalScope.addPrivate(OmpOutVD, SharedLV.
getAddress());
5290 LocalScope.addPrivate(OmpInVD, LHSLV.
getAddress());
5291 (void)LocalScope.Privatize();
5295 EmitCriticalReduction(ReductionGen);
5299 CGM.getModule(), OMPRTL___kmpc_barrier),
5305 llvm::Value *FinalResultVal =
nullptr;
5309 FinalResultAddr = SharedResult;
5323 CGM.getModule(), OMPRTL___kmpc_barrier),
5334 EmitCriticalReduction(OriginalListCombiner);
5386 if (SimpleReduction) {
5388 const auto *IPriv = OrgPrivates.begin();
5389 const auto *ILHS = OrgLHSExprs.begin();
5390 const auto *IRHS = OrgRHSExprs.begin();
5391 for (
const Expr *E : OrgReductionOps) {
5404 FilteredRHSExprs, FilteredReductionOps;
5405 for (
unsigned I : llvm::seq<unsigned>(
5406 std::min(OrgReductionOps.size(), OrgLHSExprs.size()))) {
5408 FilteredPrivates.emplace_back(OrgPrivates[I]);
5409 FilteredLHSExprs.emplace_back(OrgLHSExprs[I]);
5410 FilteredRHSExprs.emplace_back(OrgRHSExprs[I]);
5411 FilteredReductionOps.emplace_back(OrgReductionOps[I]);
5423 auto Size = RHSExprs.size();
5429 llvm::APInt ArraySize(32, Size);
5430 QualType ReductionArrayTy =
C.getConstantArrayType(
5434 CGF.
CreateMemTemp(ReductionArrayTy,
".omp.reduction.red_list");
5435 const auto *IPriv =
Privates.begin();
5437 for (
unsigned I = 0, E = RHSExprs.size(); I < E; ++I, ++IPriv, ++Idx) {
5443 if ((*IPriv)->getType()->isVariablyModifiedType()) {
5447 llvm::Value *Size = CGF.
Builder.CreateIntCast(
5460 Privates, LHSExprs, RHSExprs, ReductionOps);
5463 std::string Name =
getName({
"reduction"});
5470 llvm::Value *ReductionArrayTySize = CGF.
getTypeSize(ReductionArrayTy);
5473 llvm::Value *Args[] = {
5476 CGF.
Builder.getInt32(RHSExprs.size()),
5477 ReductionArrayTySize,
5485 WithNowait ? OMPRTL___kmpc_reduce_nowait : OMPRTL___kmpc_reduce),
5489 llvm::BasicBlock *DefaultBB = CGF.
createBasicBlock(
".omp.reduction.default");
5490 llvm::SwitchInst *SwInst =
5491 CGF.
Builder.CreateSwitch(Res, DefaultBB, 2);
5500 SwInst->addCase(CGF.
Builder.getInt32(1), Case1BB);
5504 llvm::Value *EndArgs[] = {
5512 const auto *IPriv =
Privates.begin();
5513 const auto *ILHS = LHSExprs.begin();
5514 const auto *IRHS = RHSExprs.begin();
5515 for (
const Expr *E : ReductionOps) {
5524 CommonActionTy Action(
5527 CGM.getModule(), WithNowait ? OMPRTL___kmpc_end_reduce_nowait
5528 : OMPRTL___kmpc_end_reduce),
5541 SwInst->addCase(CGF.
Builder.getInt32(2), Case2BB);
5544 auto &&AtomicCodeGen = [Loc,
Privates, LHSExprs, RHSExprs, ReductionOps](
5546 const auto *ILHS = LHSExprs.begin();
5547 const auto *IRHS = RHSExprs.begin();
5548 const auto *IPriv =
Privates.begin();
5549 for (
const Expr *E : ReductionOps) {
5550 const Expr *XExpr =
nullptr;
5551 const Expr *EExpr =
nullptr;
5552 const Expr *UpExpr =
nullptr;
5554 if (
const auto *BO = dyn_cast<BinaryOperator>(E)) {
5555 if (BO->getOpcode() == BO_Assign) {
5556 XExpr = BO->getLHS();
5557 UpExpr = BO->getRHS();
5561 const Expr *RHSExpr = UpExpr;
5564 if (
const auto *ACO = dyn_cast<AbstractConditionalOperator>(
5568 RHSExpr = ACO->getCond();
5570 if (
const auto *BORHS =
5572 EExpr = BORHS->getRHS();
5573 BO = BORHS->getOpcode();
5578 auto &&AtomicRedGen = [BO, VD,
5580 const Expr *EExpr,
const Expr *UpExpr) {
5581 LValue X = CGF.EmitLValue(XExpr);
5584 E = CGF.EmitAnyExpr(EExpr);
5585 CGF.EmitOMPAtomicSimpleUpdateExpr(
5587 llvm::AtomicOrdering::Monotonic, Loc,
5588 [&CGF, UpExpr, VD, Loc](
RValue XRValue) {
5590 Address LHSTemp = CGF.CreateMemTemp(VD->getType());
5591 CGF.emitOMPSimpleStore(
5592 CGF.MakeAddrLValue(LHSTemp, VD->
getType()), XRValue,
5593 VD->getType().getNonReferenceType(), Loc);
5596 return CGF.EmitAnyExpr(UpExpr);
5599 if ((*IPriv)->getType()->isArrayType()) {
5601 const auto *RHSVar =
5604 AtomicRedGen, XExpr, EExpr, UpExpr);
5607 AtomicRedGen(CGF, XExpr, EExpr, UpExpr);
5614 std::string Name = RT.
getName({
"atomic_reduction"});
5623 if ((*IPriv)->getType()->isArrayType()) {
5624 const auto *LHSVar =
5626 const auto *RHSVar =
5631 CritRedGen(CGF,
nullptr,
nullptr,
nullptr);
5642 llvm::Value *EndArgs[] = {
5647 CommonActionTy Action(
nullptr, {},
5649 CGM.getModule(), OMPRTL___kmpc_end_reduce),
5659 assert(OrgLHSExprs.size() == OrgPrivates.size() &&
5660 "PrivateVarReduction: Privates size mismatch");
5661 assert(OrgLHSExprs.size() == OrgReductionOps.size() &&
5662 "PrivateVarReduction: ReductionOps size mismatch");
5663 for (
unsigned I : llvm::seq<unsigned>(
5664 std::min(OrgReductionOps.size(), OrgLHSExprs.size()))) {
5667 OrgRHSExprs[I], OrgReductionOps[I]);
5676 llvm::raw_svector_ostream Out(Buffer);
5684 Out << Prefix << Name <<
"_"
5686 return std::string(Out.str());
5710 Args.emplace_back(Param);
5711 Args.emplace_back(ParamOrig);
5712 const auto &FnInfo =
5716 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
5720 Fn->addFnAttr(
"sample-profile-suffix-elision-policy",
"selected");
5721 Fn->setDoesNotRecurse();
5728 llvm::Value *Size =
nullptr;
5771 const Expr *ReductionOp,
5773 const Expr *PrivateRef) {
5784 Args.emplace_back(ParamInOut);
5785 Args.emplace_back(ParamIn);
5786 const auto &FnInfo =
5790 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
5794 Fn->addFnAttr(
"sample-profile-suffix-elision-policy",
"selected");
5795 Fn->setDoesNotRecurse();
5798 llvm::Value *Size =
nullptr;
5819 C.getPointerType(LHSVD->getType())->castAs<
PointerType>()));
5826 C.getPointerType(RHSVD->getType())->castAs<
PointerType>()));
5856 Args.emplace_back(Param);
5857 const auto &FnInfo =
5861 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
5865 Fn->addFnAttr(
"sample-profile-suffix-elision-policy",
"selected");
5866 Fn->setDoesNotRecurse();
5871 llvm::Value *Size =
nullptr;
5906 RecordDecl *RD =
C.buildImplicitRecord(
"kmp_taskred_input_t");
5915 C, RD,
C.getIntTypeForBitwidth(32,
false));
5918 unsigned Size =
Data.ReductionVars.size();
5919 llvm::APInt ArraySize(64, Size);
5921 C.getConstantArrayType(RDType, ArraySize,
nullptr,
5926 Data.ReductionCopies,
Data.ReductionOps);
5927 for (
unsigned Cnt = 0; Cnt < Size; ++Cnt) {
5929 llvm::Value *Idxs[] = {llvm::ConstantInt::get(
CGM.SizeTy, 0),
5930 llvm::ConstantInt::get(
CGM.SizeTy, Cnt)};
5946 llvm::Value *SizeValInChars;
5947 llvm::Value *SizeVal;
5948 std::tie(SizeValInChars, SizeVal) = RCG.
getSizes(Cnt);
5954 bool DelayedCreation = !!SizeVal;
5955 SizeValInChars = CGF.
Builder.CreateIntCast(SizeValInChars,
CGM.SizeTy,
5966 llvm::Value *FiniAddr =
5967 Fini ? Fini : llvm::ConstantPointerNull::get(
CGM.VoidPtrTy);
5972 CGM, Loc, RCG, Cnt,
Data.ReductionOps[Cnt], LHSExprs[Cnt],
5973 RHSExprs[Cnt],
Data.ReductionCopies[Cnt]);
5977 if (DelayedCreation) {
5979 llvm::ConstantInt::get(
CGM.Int32Ty, 1,
true),
5984 if (
Data.IsReductionWithTaskMod) {
5990 llvm::Value *Args[] = {
5992 llvm::ConstantInt::get(
CGM.IntTy,
Data.IsWorksharingReduction ? 1 : 0,
5994 llvm::ConstantInt::get(
CGM.IntTy, Size,
true),
5999 CGM.getModule(), OMPRTL___kmpc_taskred_modifier_init),
6003 llvm::Value *Args[] = {
6006 llvm::ConstantInt::get(
CGM.IntTy, Size,
true),
6010 CGM.getModule(), OMPRTL___kmpc_taskred_init),
6016 bool IsWorksharingReduction) {
6022 llvm::Value *Args[] = {IdentTLoc, GTid,
6023 llvm::ConstantInt::get(
CGM.IntTy,
6024 IsWorksharingReduction ? 1 : 0,
6028 CGM.getModule(), OMPRTL___kmpc_task_reduction_modifier_fini),
6040 llvm::Value *SizeVal = CGF.
Builder.CreateIntCast(Sizes.second,
CGM.SizeTy,
6043 CGF,
CGM.getContext().getSizeType(),
6051 llvm::Value *ReductionsPtr,
6064 CGM.getModule(), OMPRTL___kmpc_task_reduction_get_th_data),
6080 auto &M =
CGM.getModule();
6082 llvm::Value *NumOfElements;
6083 std::tie(NumOfElements, DependenciesArray) =
6085 if (!
Data.Dependences.empty()) {
6086 llvm::Value *DepWaitTaskArgs[7];
6087 DepWaitTaskArgs[0] = UpLoc;
6088 DepWaitTaskArgs[1] = ThreadID;
6089 DepWaitTaskArgs[2] = NumOfElements;
6091 DepWaitTaskArgs[4] = CGF.
Builder.getInt32(0);
6092 DepWaitTaskArgs[5] = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
6093 DepWaitTaskArgs[6] =
6094 llvm::ConstantInt::get(CGF.
Int32Ty,
Data.HasNowaitClause);
6103 M, OMPRTL___kmpc_omp_taskwait_deps_51),
6110 llvm::Value *Args[] = {UpLoc, ThreadID};
6113 OMPBuilder.getOrCreateRuntimeFunction(M, OMPRTL___kmpc_omp_taskwait),
6118 if (
auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.
CapturedStmtInfo))
6119 Region->emitUntiedSwitch(CGF);
6128 InlinedOpenMPRegionRAII Region(CGF,
CodeGen, InnerKind, HasCancel,
6129 InnerKind != OMPD_critical &&
6130 InnerKind != OMPD_master &&
6131 InnerKind != OMPD_masked);
6146 RTCancelKind CancelKind = CancelNoreq;
6147 if (CancelRegion == OMPD_parallel)
6148 CancelKind = CancelParallel;
6149 else if (CancelRegion == OMPD_for)
6150 CancelKind = CancelLoop;
6151 else if (CancelRegion == OMPD_sections)
6152 CancelKind = CancelSections;
6154 assert(CancelRegion == OMPD_taskgroup);
6155 CancelKind = CancelTaskgroup;
6167 if (
auto *OMPRegionInfo =
6171 if (CancelRegion == OMPD_taskgroup || OMPRegionInfo->hasCancel()) {
6172 llvm::Value *Args[] = {
6178 CGM.getModule(), OMPRTL___kmpc_cancellationpoint),
6187 CGF.
Builder.CreateCondBr(
Cmp, ExitBB, ContBB);
6189 if (CancelRegion == OMPD_parallel)
6207 auto &M =
CGM.getModule();
6208 if (
auto *OMPRegionInfo =
6210 auto &&ThenGen = [
this, &M, Loc, CancelRegion,
6213 llvm::Value *Args[] = {
6217 llvm::Value *
Result = CGF.EmitRuntimeCall(
6218 OMPBuilder.getOrCreateRuntimeFunction(M, OMPRTL___kmpc_cancel), Args);
6223 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(
".cancel.exit");
6224 llvm::BasicBlock *ContBB = CGF.createBasicBlock(
".cancel.continue");
6225 llvm::Value *
Cmp = CGF.Builder.CreateIsNotNull(
Result);
6226 CGF.Builder.CreateCondBr(
Cmp, ExitBB, ContBB);
6227 CGF.EmitBlock(ExitBB);
6228 if (CancelRegion == OMPD_parallel)
6232 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind());
6233 CGF.EmitBranchThroughCleanup(CancelDest);
6234 CGF.EmitBlock(ContBB,
true);
6252 OMPUsesAllocatorsActionTy(
6253 ArrayRef<std::pair<const Expr *, const Expr *>> Allocators)
6254 : Allocators(Allocators) {}
6258 for (
const auto &AllocatorData : Allocators) {
6260 CGF, AllocatorData.first, AllocatorData.second);
6263 void Exit(CodeGenFunction &CGF)
override {
6266 for (
const auto &AllocatorData : Allocators) {
6268 AllocatorData.first);
6276 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
6278 assert(!ParentName.empty() &&
"Invalid target entry parent name!");
6282 for (
unsigned I = 0, E =
C->getNumberOfAllocators(); I < E; ++I) {
6289 OMPUsesAllocatorsActionTy UsesAllocatorAction(Allocators);
6290 CodeGen.setAction(UsesAllocatorAction);
6296 const Expr *Allocator,
6297 const Expr *AllocatorTraits) {
6299 ThreadId = CGF.
Builder.CreateIntCast(ThreadId, CGF.
IntTy,
true);
6301 llvm::Value *MemSpaceHandle = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
6302 llvm::Value *NumTraits = llvm::ConstantInt::get(
6306 .getLimitedValue());
6313 llvm::Value *Traits =
Addr.emitRawPointer(CGF);
6315 llvm::Value *AllocatorVal =
6317 CGM.getModule(), OMPRTL___kmpc_init_allocator),
6318 {ThreadId, MemSpaceHandle, NumTraits, Traits});
6330 const Expr *Allocator) {
6332 ThreadId = CGF.
Builder.CreateIntCast(ThreadId, CGF.
IntTy,
true);
6334 llvm::Value *AllocatorVal =
6341 OMPRTL___kmpc_destroy_allocator),
6342 {ThreadId, AllocatorVal});
6347 llvm::OpenMPIRBuilder::TargetKernelDefaultAttrs &Attrs) {
6348 assert(Attrs.MaxTeams.size() == 1 && Attrs.MaxThreads.size() == 1 &&
6349 "invalid default attrs structure");
6350 int32_t &MaxTeamsVal = Attrs.MaxTeams.front();
6351 int32_t &MaxThreadsVal = Attrs.MaxThreads.front();
6358 for (
auto *A :
C->getAttrs()) {
6359 int32_t AttrMinThreadsVal = 1, AttrMaxThreadsVal = -1;
6360 int32_t AttrMinBlocksVal = 1, AttrMaxBlocksVal = -1;
6361 if (
auto *
Attr = dyn_cast<CUDALaunchBoundsAttr>(A))
6362 CGM.handleCUDALaunchBoundsAttr(
nullptr,
Attr, &AttrMaxThreadsVal,
6363 &AttrMinBlocksVal, &AttrMaxBlocksVal);
6364 else if (
auto *
Attr = dyn_cast<AMDGPUFlatWorkGroupSizeAttr>(A))
6365 CGM.handleAMDGPUFlatWorkGroupSizeAttr(
6366 nullptr,
Attr,
nullptr, &AttrMinThreadsVal,
6367 &AttrMaxThreadsVal);
6371 Attrs.MinThreads = std::max(Attrs.MinThreads, AttrMinThreadsVal);
6372 if (AttrMaxThreadsVal > 0)
6373 MaxThreadsVal = MaxThreadsVal > 0
6374 ? std::min(MaxThreadsVal, AttrMaxThreadsVal)
6375 : AttrMaxThreadsVal;
6376 Attrs.MinTeams = std::max(Attrs.MinTeams, AttrMinBlocksVal);
6377 if (AttrMaxBlocksVal > 0)
6378 MaxTeamsVal = MaxTeamsVal > 0 ? std::min(MaxTeamsVal, AttrMaxBlocksVal)
6386 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
6389 llvm::TargetRegionEntryInfo EntryInfo =
6393 llvm::OpenMPIRBuilder::FunctionGenCallback &&GenerateOutlinedFunction =
6394 [&CGF, &D, &
CodeGen,
this](StringRef EntryFnName) {
6395 const CapturedStmt &CS = *D.getCapturedStmt(OMPD_target);
6397 CGOpenMPTargetRegionInfo CGInfo(CS,
CodeGen, EntryFnName);
6399 if (
CGM.getLangOpts().OpenMPIsTargetDevice && !
isGPU())
6404 cantFail(
OMPBuilder.emitTargetRegionFunction(
6405 EntryInfo, GenerateOutlinedFunction, IsOffloadEntry, OutlinedFn,
6411 CGM.getTargetCodeGenInfo().setTargetAttributes(
nullptr, OutlinedFn,
CGM);
6414 for (
auto *A :
C->getAttrs()) {
6415 if (
auto *
Attr = dyn_cast<AMDGPUWavesPerEUAttr>(A))
6416 CGM.handleAMDGPUWavesPerEUAttr(OutlinedFn,
Attr);
6435 while (
const auto *
C = dyn_cast_or_null<CompoundStmt>(Child)) {
6437 for (
const Stmt *S :
C->body()) {
6438 if (
const auto *E = dyn_cast<Expr>(S)) {
6447 if (
const auto *DS = dyn_cast<DeclStmt>(S)) {
6448 if (llvm::all_of(DS->decls(), [](
const Decl *D) {
6449 if (isa<EmptyDecl>(D) || isa<DeclContext>(D) ||
6450 isa<TypeDecl>(D) || isa<PragmaCommentDecl>(D) ||
6451 isa<PragmaDetectMismatchDecl>(D) || isa<UsingDecl>(D) ||
6452 isa<UsingDirectiveDecl>(D) ||
6453 isa<OMPDeclareReductionDecl>(D) ||
6454 isa<OMPThreadPrivateDecl>(D) || isa<OMPAllocateDecl>(D))
6456 const auto *VD = dyn_cast<VarDecl>(D);
6459 return VD->hasGlobalStorage() || !VD->isUsed();
6469 Child = Child->IgnoreContainers();
6476 int32_t &MaxTeamsVal) {
6480 "Expected target-based executable directive.");
6481 switch (DirectiveKind) {
6483 const auto *CS = D.getInnermostCapturedStmt();
6486 const Stmt *ChildStmt =
6488 if (
const auto *NestedDir =
6489 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) {
6498 MinTeamsVal = MaxTeamsVal =
Constant->getExtValue();
6501 MinTeamsVal = MaxTeamsVal = 0;
6504 MinTeamsVal = MaxTeamsVal = 1;
6508 MinTeamsVal = MaxTeamsVal = -1;
6511 case OMPD_target_teams_loop:
6512 case OMPD_target_teams:
6513 case OMPD_target_teams_distribute:
6514 case OMPD_target_teams_distribute_simd:
6515 case OMPD_target_teams_distribute_parallel_for:
6516 case OMPD_target_teams_distribute_parallel_for_simd: {
6518 const Expr *NumTeams =
6522 MinTeamsVal = MaxTeamsVal =
Constant->getExtValue();
6525 MinTeamsVal = MaxTeamsVal = 0;
6528 case OMPD_target_parallel:
6529 case OMPD_target_parallel_for:
6530 case OMPD_target_parallel_for_simd:
6531 case OMPD_target_parallel_loop:
6532 case OMPD_target_simd:
6533 MinTeamsVal = MaxTeamsVal = 1;
6537 case OMPD_parallel_for:
6538 case OMPD_parallel_loop:
6539 case OMPD_parallel_master:
6540 case OMPD_parallel_sections:
6542 case OMPD_parallel_for_simd:
6544 case OMPD_cancellation_point:
6546 case OMPD_threadprivate:
6557 case OMPD_taskyield:
6560 case OMPD_taskgroup:
6566 case OMPD_target_data:
6567 case OMPD_target_exit_data:
6568 case OMPD_target_enter_data:
6569 case OMPD_distribute:
6570 case OMPD_distribute_simd:
6571 case OMPD_distribute_parallel_for:
6572 case OMPD_distribute_parallel_for_simd:
6573 case OMPD_teams_distribute:
6574 case OMPD_teams_distribute_simd:
6575 case OMPD_teams_distribute_parallel_for:
6576 case OMPD_teams_distribute_parallel_for_simd:
6577 case OMPD_target_update:
6578 case OMPD_declare_simd:
6579 case OMPD_declare_variant:
6580 case OMPD_begin_declare_variant:
6581 case OMPD_end_declare_variant:
6582 case OMPD_declare_target:
6583 case OMPD_end_declare_target:
6584 case OMPD_declare_reduction:
6585 case OMPD_declare_mapper:
6587 case OMPD_taskloop_simd:
6588 case OMPD_master_taskloop:
6589 case OMPD_master_taskloop_simd:
6590 case OMPD_parallel_master_taskloop:
6591 case OMPD_parallel_master_taskloop_simd:
6593 case OMPD_metadirective:
6599 llvm_unreachable(
"Unexpected directive kind.");
6605 "Clauses associated with the teams directive expected to be emitted "
6606 "only for the host!");
6608 int32_t MinNT = -1, MaxNT = -1;
6609 const Expr *NumTeams =
6611 if (NumTeams !=
nullptr) {
6614 switch (DirectiveKind) {
6616 const auto *CS = D.getInnermostCapturedStmt();
6617 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6621 return Bld.CreateIntCast(NumTeamsVal, CGF.
Int32Ty,
6624 case OMPD_target_teams:
6625 case OMPD_target_teams_distribute:
6626 case OMPD_target_teams_distribute_simd:
6627 case OMPD_target_teams_distribute_parallel_for:
6628 case OMPD_target_teams_distribute_parallel_for_simd: {
6632 return Bld.CreateIntCast(NumTeamsVal, CGF.
Int32Ty,
6640 assert(MinNT == MaxNT &&
"Num threads ranges require handling here.");
6641 return llvm::ConstantInt::getSigned(CGF.
Int32Ty, MinNT);
6650 bool UpperBoundOnly, llvm::Value **CondVal) {
6653 const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child);
6660 if (CondVal && Dir->hasClausesOfKind<
OMPIfClause>()) {
6661 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6664 for (
const auto *
C : Dir->getClausesOfKind<
OMPIfClause>()) {
6665 if (
C->getNameModifier() == OMPD_unknown ||
6666 C->getNameModifier() == OMPD_parallel) {
6681 if (
const auto *PreInit =
6683 for (
const auto *I : PreInit->decls()) {
6684 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
6700 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6702 const auto *NumThreadsClause =
6704 const Expr *NTExpr = NumThreadsClause->getNumThreads();
6705 if (NTExpr->isIntegerConstantExpr(CGF.
getContext()))
6710 : std::min(UpperBound,
6714 if (UpperBound == -1)
6719 if (
const auto *PreInit =
6720 cast_or_null<DeclStmt>(NumThreadsClause->getPreInitStmt())) {
6721 for (
const auto *I : PreInit->decls()) {
6722 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
6741 bool UpperBoundOnly, llvm::Value **CondVal,
const Expr **ThreadLimitExpr) {
6742 assert((!CGF.
getLangOpts().OpenMPIsTargetDevice || UpperBoundOnly) &&
6743 "Clauses associated with the teams directive expected to be emitted "
6744 "only for the host!");
6747 "Expected target-based executable directive.");
6749 const Expr *NT =
nullptr;
6750 const Expr **NTPtr = UpperBoundOnly ?
nullptr : &NT;
6752 auto CheckForConstExpr = [&](
const Expr *E,
const Expr **EPtr) {
6755 UpperBound = UpperBound ?
Constant->getZExtValue()
6756 : std::min(UpperBound,
6761 if (UpperBound == -1)
6767 auto ReturnSequential = [&]() {
6772 switch (DirectiveKind) {
6775 getNumThreads(CGF, CS, NTPtr, UpperBound, UpperBoundOnly, CondVal);
6781 if (
const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) {
6783 ThreadLimitClause = TLC;
6784 if (ThreadLimitExpr) {
6785 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6789 ThreadLimitClause->getThreadLimit().front()->getSourceRange());
6790 if (
const auto *PreInit =
6791 cast_or_null<DeclStmt>(ThreadLimitClause->getPreInitStmt())) {
6792 for (
const auto *I : PreInit->decls()) {
6793 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
6805 if (ThreadLimitClause)
6806 CheckForConstExpr(ThreadLimitClause->getThreadLimit().front(),
6808 if (
const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) {
6811 CS = Dir->getInnermostCapturedStmt();
6814 Dir = dyn_cast_or_null<OMPExecutableDirective>(Child);
6817 CS = Dir->getInnermostCapturedStmt();
6818 getNumThreads(CGF, CS, NTPtr, UpperBound, UpperBoundOnly, CondVal);
6820 return ReturnSequential();
6824 case OMPD_target_teams: {
6828 CheckForConstExpr(ThreadLimitClause->getThreadLimit().front(),
6832 getNumThreads(CGF, CS, NTPtr, UpperBound, UpperBoundOnly, CondVal);
6835 if (
const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) {
6836 if (Dir->getDirectiveKind() == OMPD_distribute) {
6837 CS = Dir->getInnermostCapturedStmt();
6838 getNumThreads(CGF, CS, NTPtr, UpperBound, UpperBoundOnly, CondVal);
6843 case OMPD_target_teams_distribute:
6847 CheckForConstExpr(ThreadLimitClause->getThreadLimit().front(),
6850 getNumThreads(CGF, D.getInnermostCapturedStmt(), NTPtr, UpperBound,
6851 UpperBoundOnly, CondVal);
6853 case OMPD_target_teams_loop:
6854 case OMPD_target_parallel_loop:
6855 case OMPD_target_parallel:
6856 case OMPD_target_parallel_for:
6857 case OMPD_target_parallel_for_simd:
6858 case OMPD_target_teams_distribute_parallel_for:
6859 case OMPD_target_teams_distribute_parallel_for_simd: {
6860 if (CondVal && D.hasClausesOfKind<
OMPIfClause>()) {
6862 for (
const auto *
C : D.getClausesOfKind<
OMPIfClause>()) {
6863 if (
C->getNameModifier() == OMPD_unknown ||
6864 C->getNameModifier() == OMPD_parallel) {
6874 return ReturnSequential();
6884 CheckForConstExpr(ThreadLimitClause->getThreadLimit().front(),
6890 CheckForConstExpr(NumThreadsClause->getNumThreads(),
nullptr);
6891 return NumThreadsClause->getNumThreads();
6895 case OMPD_target_teams_distribute_simd:
6896 case OMPD_target_simd:
6897 return ReturnSequential();
6901 llvm_unreachable(
"Unsupported directive kind.");
6906 llvm::Value *NumThreadsVal =
nullptr;
6907 llvm::Value *CondVal =
nullptr;
6908 llvm::Value *ThreadLimitVal =
nullptr;
6909 const Expr *ThreadLimitExpr =
nullptr;
6910 int32_t UpperBound = -1;
6913 CGF, D, UpperBound,
false, &CondVal,
6917 if (ThreadLimitExpr) {
6920 ThreadLimitVal = CGF.
Builder.CreateIntCast(ThreadLimitVal, CGF.
Int32Ty,
6925 if (UpperBound == 1) {
6926 NumThreadsVal = CGF.
Builder.getInt32(UpperBound);
6929 NumThreadsVal = CGF.
Builder.CreateIntCast(NumThreadsVal, CGF.
Int32Ty,
6931 }
else if (ThreadLimitVal) {
6934 NumThreadsVal = ThreadLimitVal;
6935 ThreadLimitVal =
nullptr;
6938 assert(!ThreadLimitVal &&
"Default not applicable with thread limit value");
6939 NumThreadsVal = CGF.
Builder.getInt32(0);
6946 NumThreadsVal = CGF.
Builder.CreateSelect(CondVal, NumThreadsVal,
6952 if (ThreadLimitVal) {
6953 NumThreadsVal = CGF.
Builder.CreateSelect(
6954 CGF.
Builder.CreateICmpULT(ThreadLimitVal, NumThreadsVal),
6955 ThreadLimitVal, NumThreadsVal);
6958 return NumThreadsVal;
6968class MappableExprsHandler {
6974 struct AttachPtrExprComparator {
6975 const MappableExprsHandler &Handler;
6977 mutable llvm::DenseMap<std::pair<const Expr *, const Expr *>,
bool>
6978 CachedEqualityComparisons;
6980 AttachPtrExprComparator(
const MappableExprsHandler &H) : Handler(H) {}
6981 AttachPtrExprComparator() =
delete;
6984 bool operator()(
const Expr *LHS,
const Expr *RHS)
const {
6989 const auto ItLHS = Handler.AttachPtrComponentDepthMap.find(LHS);
6990 const auto ItRHS = Handler.AttachPtrComponentDepthMap.find(RHS);
6992 std::optional<size_t> DepthLHS =
6993 (ItLHS != Handler.AttachPtrComponentDepthMap.end()) ? ItLHS->second
6995 std::optional<size_t> DepthRHS =
6996 (ItRHS != Handler.AttachPtrComponentDepthMap.end()) ? ItRHS->second
7000 if (!DepthLHS.has_value() && !DepthRHS.has_value()) {
7002 if (areEqual(LHS, RHS))
7005 return wasComputedBefore(LHS, RHS);
7007 if (!DepthLHS.has_value())
7009 if (!DepthRHS.has_value())
7013 if (DepthLHS.value() != DepthRHS.value())
7014 return DepthLHS.value() < DepthRHS.value();
7017 if (areEqual(LHS, RHS))
7020 return wasComputedBefore(LHS, RHS);
7026 bool areEqual(
const Expr *LHS,
const Expr *RHS)
const {
7028 const auto CachedResultIt = CachedEqualityComparisons.find({LHS, RHS});
7029 if (CachedResultIt != CachedEqualityComparisons.end())
7030 return CachedResultIt->second;
7044 bool wasComputedBefore(
const Expr *LHS,
const Expr *RHS)
const {
7045 const size_t &OrderLHS = Handler.AttachPtrComputationOrderMap.at(LHS);
7046 const size_t &OrderRHS = Handler.AttachPtrComputationOrderMap.at(RHS);
7048 return OrderLHS < OrderRHS;
7057 bool areSemanticallyEqual(
const Expr *LHS,
const Expr *RHS)
const {
7079 if (
const auto *LD = dyn_cast<DeclRefExpr>(LHS)) {
7080 const auto *RD = dyn_cast<DeclRefExpr>(RHS);
7083 return LD->getDecl()->getCanonicalDecl() ==
7084 RD->getDecl()->getCanonicalDecl();
7088 if (
const auto *LA = dyn_cast<ArraySubscriptExpr>(LHS)) {
7089 const auto *RA = dyn_cast<ArraySubscriptExpr>(RHS);
7092 return areSemanticallyEqual(LA->getBase(), RA->getBase()) &&
7093 areSemanticallyEqual(LA->getIdx(), RA->getIdx());
7097 if (
const auto *LM = dyn_cast<MemberExpr>(LHS)) {
7098 const auto *RM = dyn_cast<MemberExpr>(RHS);
7101 if (LM->getMemberDecl()->getCanonicalDecl() !=
7102 RM->getMemberDecl()->getCanonicalDecl())
7104 return areSemanticallyEqual(LM->getBase(), RM->getBase());
7108 if (
const auto *LU = dyn_cast<UnaryOperator>(LHS)) {
7109 const auto *RU = dyn_cast<UnaryOperator>(RHS);
7112 if (LU->getOpcode() != RU->getOpcode())
7114 return areSemanticallyEqual(LU->getSubExpr(), RU->getSubExpr());
7118 if (
const auto *LB = dyn_cast<BinaryOperator>(LHS)) {
7119 const auto *RB = dyn_cast<BinaryOperator>(RHS);
7122 if (LB->getOpcode() != RB->getOpcode())
7124 return areSemanticallyEqual(LB->getLHS(), RB->getLHS()) &&
7125 areSemanticallyEqual(LB->getRHS(), RB->getRHS());
7131 if (
const auto *LAS = dyn_cast<ArraySectionExpr>(LHS)) {
7132 const auto *RAS = dyn_cast<ArraySectionExpr>(RHS);
7135 return areSemanticallyEqual(LAS->getBase(), RAS->getBase()) &&
7136 areSemanticallyEqual(LAS->getLowerBound(),
7137 RAS->getLowerBound()) &&
7138 areSemanticallyEqual(LAS->getLength(), RAS->getLength());
7142 if (
const auto *LC = dyn_cast<CastExpr>(LHS)) {
7143 const auto *RC = dyn_cast<CastExpr>(RHS);
7146 if (LC->getCastKind() != RC->getCastKind())
7148 return areSemanticallyEqual(LC->getSubExpr(), RC->getSubExpr());
7156 if (
const auto *LI = dyn_cast<IntegerLiteral>(LHS)) {
7157 const auto *RI = dyn_cast<IntegerLiteral>(RHS);
7160 return LI->getValue() == RI->getValue();
7164 if (
const auto *LC = dyn_cast<CharacterLiteral>(LHS)) {
7165 const auto *RC = dyn_cast<CharacterLiteral>(RHS);
7168 return LC->getValue() == RC->getValue();
7172 if (
const auto *LF = dyn_cast<FloatingLiteral>(LHS)) {
7173 const auto *RF = dyn_cast<FloatingLiteral>(RHS);
7177 return LF->getValue().bitwiseIsEqual(RF->getValue());
7181 if (
const auto *LS = dyn_cast<StringLiteral>(LHS)) {
7182 const auto *RS = dyn_cast<StringLiteral>(RHS);
7185 return LS->getString() == RS->getString();
7193 if (
const auto *LB = dyn_cast<CXXBoolLiteralExpr>(LHS)) {
7194 const auto *RB = dyn_cast<CXXBoolLiteralExpr>(RHS);
7197 return LB->getValue() == RB->getValue();
7206 static unsigned getFlagMemberOffset() {
7207 unsigned Offset = 0;
7208 for (uint64_t Remain =
7209 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
7210 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF);
7211 !(Remain & 1); Remain = Remain >> 1)
7218 class MappingExprInfo {
7220 const ValueDecl *MapDecl =
nullptr;
7223 const Expr *MapExpr =
nullptr;
7226 MappingExprInfo(
const ValueDecl *MapDecl,
const Expr *MapExpr =
nullptr)
7227 : MapDecl(MapDecl), MapExpr(MapExpr) {}
7229 const ValueDecl *getMapDecl()
const {
return MapDecl; }
7230 const Expr *getMapExpr()
const {
return MapExpr; }
7233 using DeviceInfoTy = llvm::OpenMPIRBuilder::DeviceInfoTy;
7234 using MapBaseValuesArrayTy = llvm::OpenMPIRBuilder::MapValuesArrayTy;
7235 using MapValuesArrayTy = llvm::OpenMPIRBuilder::MapValuesArrayTy;
7236 using MapFlagsArrayTy = llvm::OpenMPIRBuilder::MapFlagsArrayTy;
7237 using MapDimArrayTy = llvm::OpenMPIRBuilder::MapDimArrayTy;
7238 using MapNonContiguousArrayTy =
7239 llvm::OpenMPIRBuilder::MapNonContiguousArrayTy;
7240 using MapExprsArrayTy = SmallVector<MappingExprInfo, 4>;
7241 using MapValueDeclsArrayTy = SmallVector<const ValueDecl *, 4>;
7245 bool ,
const ValueDecl *,
const Expr *>;
7246 using MapDataArrayTy = SmallVector<MapData, 4>;
7251 struct MapCombinedInfoTy : llvm::OpenMPIRBuilder::MapInfosTy {
7252 MapExprsArrayTy Exprs;
7253 MapValueDeclsArrayTy Mappers;
7254 MapValueDeclsArrayTy DevicePtrDecls;
7257 void append(MapCombinedInfoTy &CurInfo) {
7258 Exprs.append(CurInfo.Exprs.begin(), CurInfo.Exprs.end());
7259 DevicePtrDecls.append(CurInfo.DevicePtrDecls.begin(),
7260 CurInfo.DevicePtrDecls.end());
7261 Mappers.append(CurInfo.Mappers.begin(), CurInfo.Mappers.end());
7262 llvm::OpenMPIRBuilder::MapInfosTy::append(CurInfo);
7270 struct StructRangeInfoTy {
7271 MapCombinedInfoTy PreliminaryMapData;
7272 std::pair<
unsigned ,
Address > LowestElem = {
7274 std::pair<
unsigned ,
Address > HighestElem = {
7278 bool IsArraySection =
false;
7279 bool HasCompleteRecord =
false;
7284 struct AttachInfoTy {
7287 const ValueDecl *AttachPtrDecl =
nullptr;
7288 const Expr *AttachMapExpr =
nullptr;
7290 bool isValid()
const {
7297 bool hasAttachEntryForCapturedVar(
const ValueDecl *VD)
const {
7298 for (
const auto &AttachEntry : AttachPtrExprMap) {
7299 if (AttachEntry.second) {
7302 if (
const auto *DRE = dyn_cast<DeclRefExpr>(AttachEntry.second))
7303 if (DRE->getDecl() == VD)
7311 const Expr *getAttachPtrExpr(
7314 const auto It = AttachPtrExprMap.find(Components);
7315 if (It != AttachPtrExprMap.end())
7326 ArrayRef<OpenMPMapModifierKind> MapModifiers;
7327 ArrayRef<OpenMPMotionModifierKind> MotionModifiers;
7328 bool ReturnDevicePointer =
false;
7329 bool IsImplicit =
false;
7330 const ValueDecl *Mapper =
nullptr;
7331 const Expr *VarRef =
nullptr;
7332 bool ForDeviceAddr =
false;
7333 bool HasUdpFbNullify =
false;
7335 MapInfo() =
default;
7339 ArrayRef<OpenMPMapModifierKind> MapModifiers,
7340 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
7341 bool ReturnDevicePointer,
bool IsImplicit,
7342 const ValueDecl *Mapper =
nullptr,
const Expr *VarRef =
nullptr,
7343 bool ForDeviceAddr =
false,
bool HasUdpFbNullify =
false)
7344 : Components(Components), MapType(MapType), MapModifiers(MapModifiers),
7345 MotionModifiers(MotionModifiers),
7346 ReturnDevicePointer(ReturnDevicePointer), IsImplicit(IsImplicit),
7347 Mapper(Mapper), VarRef(VarRef), ForDeviceAddr(ForDeviceAddr),
7348 HasUdpFbNullify(HasUdpFbNullify) {}
7353 llvm::PointerUnion<
const OMPExecutableDirective *,
7354 const OMPDeclareMapperDecl *>
7358 CodeGenFunction &CGF;
7363 llvm::DenseMap<CanonicalDeclPtr<const VarDecl>,
bool> FirstPrivateDecls;
7366 llvm::SmallSet<OpenMPDefaultmapClauseKind, 4> DefaultmapFirstprivateKinds;
7372 SmallVector<OMPClauseMappableExprCommon::MappableExprComponentListRef, 4>>
7379 SmallVector<OMPClauseMappableExprCommon::MappableExprComponentListRef, 4>>
7383 llvm::DenseMap<const ValueDecl *, const OMPMapClause *> LambdasMap;
7398 llvm::DenseMap<const Expr *, std::optional<size_t>>
7399 AttachPtrComponentDepthMap = {{
nullptr, std::nullopt}};
7403 llvm::DenseMap<const Expr *, size_t> AttachPtrComputationOrderMap = {
7408 AttachPtrExprComparator AttachPtrComparator;
7410 llvm::Value *getExprTypeSize(
const Expr *E)
const {
7414 if (
const auto *OAE = dyn_cast<OMPArrayShapingExpr>(E)) {
7416 CGF.
getTypeSize(OAE->getBase()->getType()->getPointeeType());
7417 for (
const Expr *SE : OAE->getDimensions()) {
7428 if (
const auto *RefTy = ExprTy->
getAs<ReferenceType>())
7434 if (
const auto *OAE = dyn_cast<ArraySectionExpr>(E)) {
7436 OAE->getBase()->IgnoreParenImpCasts())
7442 if (!OAE->getLength() && OAE->getColonLocFirst().isValid() &&
7443 !OAE->getLowerBound())
7446 llvm::Value *ElemSize;
7447 if (
const auto *PTy = BaseTy->
getAs<PointerType>()) {
7448 ElemSize = CGF.
getTypeSize(PTy->getPointeeType().getCanonicalType());
7451 assert(ATy &&
"Expecting array type if not a pointer type.");
7452 ElemSize = CGF.
getTypeSize(ATy->getElementType().getCanonicalType());
7457 if (!OAE->getLength() && OAE->getColonLocFirst().isInvalid())
7460 if (
const Expr *LenExpr = OAE->getLength()) {
7464 LenExpr->getExprLoc());
7465 return CGF.
Builder.CreateNUWMul(LengthVal, ElemSize);
7467 assert(!OAE->getLength() && OAE->getColonLocFirst().isValid() &&
7468 OAE->getLowerBound() &&
"expected array_section[lb:].");
7474 OAE->getLowerBound()->getExprLoc());
7475 LBVal = CGF.
Builder.CreateNUWMul(LBVal, ElemSize);
7476 llvm::Value *
Cmp = CGF.
Builder.CreateICmpUGT(LengthVal, LBVal);
7477 llvm::Value *TrueVal = CGF.
Builder.CreateNUWSub(LengthVal, LBVal);
7478 LengthVal = CGF.
Builder.CreateSelect(
7479 Cmp, TrueVal, llvm::ConstantInt::get(CGF.
SizeTy, 0));
7489 OpenMPOffloadMappingFlags getMapTypeBits(
7491 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
bool IsImplicit,
7492 bool AddPtrFlag,
bool AddIsTargetParamFlag,
bool IsNonContiguous)
const {
7493 OpenMPOffloadMappingFlags Bits =
7494 IsImplicit ? OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT
7495 : OpenMPOffloadMappingFlags::OMP_MAP_NONE;
7497 case OMPC_MAP_alloc:
7498 case OMPC_MAP_release:
7505 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_TO;
7508 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_FROM;
7510 case OMPC_MAP_tofrom:
7511 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_TO |
7512 OpenMPOffloadMappingFlags::OMP_MAP_FROM;
7514 case OMPC_MAP_delete:
7515 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_DELETE;
7518 llvm_unreachable(
"Unexpected map type!");
7521 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ;
7522 if (AddIsTargetParamFlag)
7523 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM;
7524 if (llvm::is_contained(MapModifiers, OMPC_MAP_MODIFIER_always))
7525 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_ALWAYS;
7526 if (llvm::is_contained(MapModifiers, OMPC_MAP_MODIFIER_close))
7527 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_CLOSE;
7528 if (llvm::is_contained(MapModifiers, OMPC_MAP_MODIFIER_present) ||
7529 llvm::is_contained(MotionModifiers, OMPC_MOTION_MODIFIER_present))
7530 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_PRESENT;
7531 if (llvm::is_contained(MapModifiers, OMPC_MAP_MODIFIER_ompx_hold))
7532 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_OMPX_HOLD;
7533 if (IsNonContiguous)
7534 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_NON_CONTIG;
7540 bool isFinalArraySectionExpression(
const Expr *E)
const {
7541 const auto *OASE = dyn_cast<ArraySectionExpr>(E);
7548 if (OASE->getColonLocFirst().isInvalid())
7551 const Expr *Length = OASE->getLength();
7558 OASE->getBase()->IgnoreParenImpCasts())
7560 if (
const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.
getTypePtr()))
7561 return ATy->getSExtSize() != 1;
7573 llvm::APSInt ConstLength =
Result.Val.getInt();
7574 return ConstLength.getSExtValue() != 1;
7581 void emitAttachEntry(CodeGenFunction &CGF, MapCombinedInfoTy &CombinedInfo,
7582 const AttachInfoTy &AttachInfo)
const {
7583 assert(AttachInfo.isValid() &&
7584 "Expected valid attach pointer/pointee information!");
7588 llvm::Value *PointerSize = CGF.
Builder.CreateIntCast(
7589 llvm::ConstantInt::get(
7595 CombinedInfo.Exprs.emplace_back(AttachInfo.AttachPtrDecl,
7596 AttachInfo.AttachMapExpr);
7597 CombinedInfo.BasePointers.push_back(
7598 AttachInfo.AttachPtrAddr.emitRawPointer(CGF));
7599 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
7600 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
7601 CombinedInfo.Pointers.push_back(
7602 AttachInfo.AttachPteeAddr.emitRawPointer(CGF));
7603 CombinedInfo.Sizes.push_back(PointerSize);
7604 CombinedInfo.Types.push_back(OpenMPOffloadMappingFlags::OMP_MAP_ATTACH);
7605 CombinedInfo.Mappers.push_back(
nullptr);
7606 CombinedInfo.NonContigInfo.Dims.push_back(1);
7613 class CopyOverlappedEntryGaps {
7614 CodeGenFunction &CGF;
7615 MapCombinedInfoTy &CombinedInfo;
7616 OpenMPOffloadMappingFlags Flags = OpenMPOffloadMappingFlags::OMP_MAP_NONE;
7617 const ValueDecl *MapDecl =
nullptr;
7618 const Expr *MapExpr =
nullptr;
7620 bool IsNonContiguous =
false;
7624 const RecordDecl *LastParent =
nullptr;
7626 unsigned LastIndex = -1u;
7630 CopyOverlappedEntryGaps(CodeGenFunction &CGF,
7631 MapCombinedInfoTy &CombinedInfo,
7632 OpenMPOffloadMappingFlags Flags,
7633 const ValueDecl *MapDecl,
const Expr *MapExpr,
7634 Address BP, Address LB,
bool IsNonContiguous,
7636 : CGF(CGF), CombinedInfo(CombinedInfo), Flags(Flags), MapDecl(MapDecl),
7637 MapExpr(MapExpr), BP(BP), IsNonContiguous(IsNonContiguous),
7638 DimSize(DimSize), LB(LB) {}
7641 const OMPClauseMappableExprCommon::MappableComponent &MC,
7642 const FieldDecl *FD,
7643 llvm::function_ref<LValue(CodeGenFunction &,
const MemberExpr *)>
7644 EmitMemberExprBase) {
7654 LValue BaseLVal = EmitMemberExprBase(CGF, ME);
7666 copyUntilField(FD, ComponentLB);
7669 if (((int64_t)FieldOffset - (int64_t)Cursor) > 0)
7670 copyUntilField(FD, ComponentLB);
7672 Cursor = FieldOffset + FieldSize;
7677 void copyUntilField(
const FieldDecl *FD, Address ComponentLB) {
7680 llvm::Value *
Size = CGF.
Builder.CreatePtrDiff(ComponentLBPtr, LBPtr);
7681 copySizedChunk(LBPtr, Size);
7684 void copyUntilEnd(Address HB) {
7686 const ASTRecordLayout &RL =
7694 copySizedChunk(LBPtr, Size);
7697 void copySizedChunk(llvm::Value *Base, llvm::Value *Size) {
7698 CombinedInfo.Exprs.emplace_back(MapDecl, MapExpr);
7700 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
7701 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
7702 CombinedInfo.Pointers.push_back(Base);
7703 CombinedInfo.Sizes.push_back(
7705 CombinedInfo.Types.push_back(Flags);
7706 CombinedInfo.Mappers.push_back(
nullptr);
7707 CombinedInfo.NonContigInfo.Dims.push_back(IsNonContiguous ? DimSize : 1);
7716 void generateInfoForComponentList(
7718 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
7720 MapCombinedInfoTy &CombinedInfo,
7721 MapCombinedInfoTy &StructBaseCombinedInfo,
7722 StructRangeInfoTy &PartialStruct, AttachInfoTy &AttachInfo,
7723 bool IsFirstComponentList,
bool IsImplicit,
7724 bool GenerateAllInfoForClauses,
const ValueDecl *Mapper =
nullptr,
7725 bool ForDeviceAddr =
false,
const ValueDecl *BaseDecl =
nullptr,
7726 const Expr *MapExpr =
nullptr,
7727 ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef>
7728 OverlappedElements = {})
const {
7946 bool IsCaptureFirstInfo = IsFirstComponentList;
7950 bool RequiresReference =
false;
7953 auto CI = Components.rbegin();
7954 auto CE = Components.rend();
7959 bool IsExpressionFirstInfo =
true;
7960 bool FirstPointerInComplexData =
false;
7963 const Expr *AssocExpr = I->getAssociatedExpression();
7964 const auto *AE = dyn_cast<ArraySubscriptExpr>(AssocExpr);
7965 const auto *OASE = dyn_cast<ArraySectionExpr>(AssocExpr);
7966 const auto *OAShE = dyn_cast<OMPArrayShapingExpr>(AssocExpr);
7969 const Expr *AttachPtrExpr = getAttachPtrExpr(Components);
7970 auto [AttachPtrAddr, AttachPteeBaseAddr] =
7971 getAttachPtrAddrAndPteeBaseAddr(AttachPtrExpr, CGF);
7973 bool HasAttachPtr = AttachPtrExpr !=
nullptr;
7974 bool FirstComponentIsForAttachPtr = AssocExpr == AttachPtrExpr;
7975 bool SeenAttachPtr = FirstComponentIsForAttachPtr;
7977 if (FirstComponentIsForAttachPtr) {
7985 }
else if ((AE &&
isa<CXXThisExpr>(AE->getBase()->IgnoreParenImpCasts())) ||
7999 if (
const auto *VD =
8000 dyn_cast_or_null<VarDecl>(I->getAssociatedDeclaration())) {
8001 if (std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
8002 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD)) {
8003 if ((*Res == OMPDeclareTargetDeclAttr::MT_Link) ||
8004 ((*Res == OMPDeclareTargetDeclAttr::MT_To ||
8005 *Res == OMPDeclareTargetDeclAttr::MT_Enter) &&
8007 RequiresReference =
true;
8017 I->getAssociatedDeclaration()->
getType().getNonReferenceType();
8022 const auto *VD = dyn_cast<VarDecl>(I->getAssociatedDeclaration());
8024 !VD || VD->hasLocalStorage() || HasAttachPtr)
8027 FirstPointerInComplexData =
true;
8046 bool ShouldBeMemberOf =
false;
8055 const MemberExpr *EncounteredME =
nullptr;
8067 bool IsNonContiguous =
8068 CombinedInfo.NonContigInfo.IsNonContiguous ||
8069 any_of(Components, [&](
const auto &Component) {
8071 dyn_cast<ArraySectionExpr>(Component.getAssociatedExpression());
8075 const Expr *StrideExpr = OASE->getStride();
8080 "Stride expression must be of integer type");
8093 bool IsPrevMemberReference =
false;
8095 bool IsPartialMapped =
8096 !PartialStruct.PreliminaryMapData.BasePointers.empty();
8103 bool IsMappingWholeStruct =
true;
8104 if (!GenerateAllInfoForClauses) {
8105 IsMappingWholeStruct =
false;
8107 for (
auto TempI = I; TempI != CE; ++TempI) {
8108 const MemberExpr *PossibleME =
8109 dyn_cast<MemberExpr>(TempI->getAssociatedExpression());
8111 IsMappingWholeStruct =
false;
8117 bool SeenFirstNonBinOpExprAfterAttachPtr =
false;
8118 for (; I != CE; ++I) {
8121 if (HasAttachPtr && !SeenAttachPtr) {
8122 SeenAttachPtr = I->getAssociatedExpression() == AttachPtrExpr;
8129 if (HasAttachPtr && !SeenFirstNonBinOpExprAfterAttachPtr) {
8130 const auto *BO = dyn_cast<BinaryOperator>(I->getAssociatedExpression());
8135 SeenFirstNonBinOpExprAfterAttachPtr =
true;
8136 BP = AttachPteeBaseAddr;
8140 if (!EncounteredME) {
8141 EncounteredME = dyn_cast<MemberExpr>(I->getAssociatedExpression());
8144 if (EncounteredME) {
8145 ShouldBeMemberOf =
true;
8148 if (FirstPointerInComplexData) {
8149 QualType Ty = std::prev(I)
8150 ->getAssociatedDeclaration()
8152 .getNonReferenceType();
8154 FirstPointerInComplexData =
false;
8159 auto Next = std::next(I);
8169 bool IsFinalArraySection =
8171 isFinalArraySectionExpression(I->getAssociatedExpression());
8175 const ValueDecl *MapDecl = (I->getAssociatedDeclaration())
8176 ? I->getAssociatedDeclaration()
8178 MapExpr = (I->getAssociatedExpression()) ? I->getAssociatedExpression()
8185 dyn_cast<ArraySectionExpr>(I->getAssociatedExpression());
8187 dyn_cast<OMPArrayShapingExpr>(I->getAssociatedExpression());
8188 const auto *UO = dyn_cast<UnaryOperator>(I->getAssociatedExpression());
8189 const auto *BO = dyn_cast<BinaryOperator>(I->getAssociatedExpression());
8195 I->getAssociatedExpression()->getType()->isAnyPointerType();
8196 bool IsMemberReference =
isa<MemberExpr>(I->getAssociatedExpression()) &&
8199 bool IsNonDerefPointer = IsPointer &&
8200 !(UO && UO->getOpcode() != UO_Deref) && !BO &&
8206 if (
Next == CE || IsMemberReference || IsNonDerefPointer ||
8207 IsFinalArraySection) {
8210 assert((
Next == CE ||
8217 "Unexpected expression");
8221 auto &&EmitMemberExprBase = [](CodeGenFunction &CGF,
8222 const MemberExpr *E) {
8223 const Expr *BaseExpr = E->getBase();
8228 LValueBaseInfo BaseInfo;
8229 TBAAAccessInfo TBAAInfo;
8243 OAShE->getBase()->getType()->getPointeeType()),
8245 OAShE->getBase()->getType()));
8246 }
else if (IsMemberReference) {
8248 LValue BaseLVal = EmitMemberExprBase(CGF, ME);
8263 FinalLowestElem = LowestElem;
8268 bool IsMemberPointerOrAddr =
8270 (((IsPointer || ForDeviceAddr) &&
8271 I->getAssociatedExpression() == EncounteredME) ||
8272 (IsPrevMemberReference && !IsPointer) ||
8273 (IsMemberReference &&
Next != CE &&
8274 !
Next->getAssociatedExpression()->getType()->isPointerType()));
8275 if (!OverlappedElements.empty() &&
Next == CE) {
8277 assert(!PartialStruct.Base.isValid() &&
"The base element is set.");
8278 assert(!IsPointer &&
8279 "Unexpected base element with the pointer type.");
8282 PartialStruct.LowestElem = {0, LowestElem};
8284 I->getAssociatedExpression()->getType());
8289 PartialStruct.HighestElem = {
8290 std::numeric_limits<
decltype(
8291 PartialStruct.HighestElem.first)>
::max(),
8293 PartialStruct.Base = BP;
8294 PartialStruct.LB = LB;
8296 PartialStruct.PreliminaryMapData.BasePointers.empty() &&
8297 "Overlapped elements must be used only once for the variable.");
8298 std::swap(PartialStruct.PreliminaryMapData, CombinedInfo);
8300 OpenMPOffloadMappingFlags Flags =
8301 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF |
8302 getMapTypeBits(MapType, MapModifiers, MotionModifiers, IsImplicit,
8304 false, IsNonContiguous);
8305 CopyOverlappedEntryGaps CopyGaps(CGF, CombinedInfo, Flags, MapDecl,
8306 MapExpr, BP, LB, IsNonContiguous,
8310 Component : OverlappedElements) {
8311 for (
const OMPClauseMappableExprCommon::MappableComponent &MC :
8314 if (
const auto *FD = dyn_cast<FieldDecl>(VD)) {
8315 CopyGaps.processField(MC, FD, EmitMemberExprBase);
8320 CopyGaps.copyUntilEnd(HB);
8323 llvm::Value *
Size = getExprTypeSize(I->getAssociatedExpression());
8330 if ((!IsMemberPointerOrAddr && !IsPartialMapped) ||
8332 if (!IsMappingWholeStruct) {
8333 CombinedInfo.Exprs.emplace_back(MapDecl, MapExpr);
8335 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
8336 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
8338 CombinedInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
8340 CombinedInfo.NonContigInfo.Dims.push_back(IsNonContiguous ? DimSize
8343 StructBaseCombinedInfo.Exprs.emplace_back(MapDecl, MapExpr);
8344 StructBaseCombinedInfo.BasePointers.push_back(
8346 StructBaseCombinedInfo.DevicePtrDecls.push_back(
nullptr);
8347 StructBaseCombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
8348 StructBaseCombinedInfo.Pointers.push_back(LB.
emitRawPointer(CGF));
8349 StructBaseCombinedInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
8351 StructBaseCombinedInfo.NonContigInfo.Dims.push_back(
8352 IsNonContiguous ? DimSize : 1);
8356 bool HasMapper = Mapper &&
Next == CE;
8357 if (!IsMappingWholeStruct)
8358 CombinedInfo.Mappers.push_back(HasMapper ? Mapper :
nullptr);
8360 StructBaseCombinedInfo.Mappers.push_back(HasMapper ? Mapper
8367 OpenMPOffloadMappingFlags Flags = getMapTypeBits(
8368 MapType, MapModifiers, MotionModifiers, IsImplicit,
8369 !IsExpressionFirstInfo || RequiresReference ||
8370 FirstPointerInComplexData || IsMemberReference,
8371 IsCaptureFirstInfo && !RequiresReference, IsNonContiguous);
8373 if (!IsExpressionFirstInfo || IsMemberReference) {
8376 if (IsPointer || (IsMemberReference &&
Next != CE))
8377 Flags &= ~(OpenMPOffloadMappingFlags::OMP_MAP_TO |
8378 OpenMPOffloadMappingFlags::OMP_MAP_FROM |
8379 OpenMPOffloadMappingFlags::OMP_MAP_ALWAYS |
8380 OpenMPOffloadMappingFlags::OMP_MAP_DELETE |
8381 OpenMPOffloadMappingFlags::OMP_MAP_CLOSE);
8383 if (ShouldBeMemberOf) {
8386 Flags |= OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF;
8389 ShouldBeMemberOf =
false;
8393 if (!IsMappingWholeStruct)
8394 CombinedInfo.Types.push_back(Flags);
8396 StructBaseCombinedInfo.Types.push_back(Flags);
8402 if (EncounteredME) {
8407 if (!PartialStruct.Base.isValid()) {
8408 PartialStruct.LowestElem = {FieldIndex, LowestElem};
8409 if (IsFinalArraySection && OASE) {
8413 PartialStruct.HighestElem = {FieldIndex, HB};
8415 PartialStruct.HighestElem = {FieldIndex, LowestElem};
8417 PartialStruct.Base = BP;
8418 PartialStruct.LB = BP;
8419 }
else if (FieldIndex < PartialStruct.LowestElem.first) {
8420 PartialStruct.LowestElem = {FieldIndex, LowestElem};
8421 }
else if (FieldIndex > PartialStruct.HighestElem.first) {
8422 if (IsFinalArraySection && OASE) {
8426 PartialStruct.HighestElem = {FieldIndex, HB};
8428 PartialStruct.HighestElem = {FieldIndex, LowestElem};
8434 if (IsFinalArraySection || IsNonContiguous)
8435 PartialStruct.IsArraySection =
true;
8438 if (IsFinalArraySection)
8443 BP = IsMemberReference ? LowestElem : LB;
8444 if (!IsPartialMapped)
8445 IsExpressionFirstInfo =
false;
8446 IsCaptureFirstInfo =
false;
8447 FirstPointerInComplexData =
false;
8448 IsPrevMemberReference = IsMemberReference;
8449 }
else if (FirstPointerInComplexData) {
8450 QualType Ty = Components.rbegin()
8451 ->getAssociatedDeclaration()
8453 .getNonReferenceType();
8455 FirstPointerInComplexData =
false;
8461 PartialStruct.HasCompleteRecord =
true;
8464 if (shouldEmitAttachEntry(AttachPtrExpr, BaseDecl, CGF, CurDir)) {
8465 AttachInfo.AttachPtrAddr = AttachPtrAddr;
8466 AttachInfo.AttachPteeAddr = FinalLowestElem;
8467 AttachInfo.AttachPtrDecl = BaseDecl;
8468 AttachInfo.AttachMapExpr = MapExpr;
8471 if (!IsNonContiguous)
8474 const ASTContext &Context = CGF.
getContext();
8478 MapValuesArrayTy CurOffsets = {llvm::ConstantInt::get(CGF.
CGM.
Int64Ty, 0)};
8479 MapValuesArrayTy CurCounts;
8480 MapValuesArrayTy CurStrides = {llvm::ConstantInt::get(CGF.
CGM.
Int64Ty, 1)};
8481 MapValuesArrayTy DimSizes{llvm::ConstantInt::get(CGF.
CGM.
Int64Ty, 1)};
8487 for (
const OMPClauseMappableExprCommon::MappableComponent &Component :
8489 const Expr *AssocExpr = Component.getAssociatedExpression();
8490 const auto *OASE = dyn_cast<ArraySectionExpr>(AssocExpr);
8500 assert((VAT || CAT || &Component == &*Components.begin()) &&
8501 "Should be either ConstantArray or VariableArray if not the "
8505 if (CurCounts.empty()) {
8506 const Type *ElementType =
nullptr;
8508 ElementType = CAT->getElementType().getTypePtr();
8510 ElementType = VAT->getElementType().getTypePtr();
8511 else if (&Component == &*Components.begin()) {
8518 if (
const auto *PtrType = Ty->
getAs<PointerType>())
8525 "Non-first components should not be raw pointers");
8533 if (&Component != &*Components.begin())
8537 CurCounts.push_back(
8538 llvm::ConstantInt::get(CGF.
Int64Ty, ElementTypeSize));
8543 if (DimSizes.size() < Components.size() - 1) {
8546 llvm::ConstantInt::get(CGF.
Int64Ty, CAT->getZExtSize()));
8548 DimSizes.push_back(CGF.
Builder.CreateIntCast(
8555 auto *DI = DimSizes.begin() + 1;
8557 llvm::Value *DimProd =
8558 llvm::ConstantInt::get(CGF.
CGM.
Int64Ty, ElementTypeSize);
8567 for (
const OMPClauseMappableExprCommon::MappableComponent &Component :
8569 const Expr *AssocExpr = Component.getAssociatedExpression();
8571 if (
const auto *AE = dyn_cast<ArraySubscriptExpr>(AssocExpr)) {
8572 llvm::Value *Offset = CGF.
Builder.CreateIntCast(
8575 CurOffsets.push_back(Offset);
8576 CurCounts.push_back(llvm::ConstantInt::get(CGF.
Int64Ty, 1));
8577 CurStrides.push_back(CurStrides.back());
8581 const auto *OASE = dyn_cast<ArraySectionExpr>(AssocExpr);
8587 const Expr *OffsetExpr = OASE->getLowerBound();
8588 llvm::Value *Offset =
nullptr;
8591 Offset = llvm::ConstantInt::get(CGF.
Int64Ty, 0);
8599 const Expr *CountExpr = OASE->getLength();
8600 llvm::Value *Count =
nullptr;
8606 if (!OASE->getColonLocFirst().isValid() &&
8607 !OASE->getColonLocSecond().isValid()) {
8608 Count = llvm::ConstantInt::get(CGF.
Int64Ty, 1);
8614 const Expr *StrideExpr = OASE->getStride();
8615 llvm::Value *Stride =
8621 Count = CGF.
Builder.CreateUDiv(
8622 CGF.
Builder.CreateNUWSub(*DI, Offset), Stride);
8624 Count = CGF.
Builder.CreateNUWSub(*DI, Offset);
8630 CurCounts.push_back(Count);
8640 const Expr *StrideExpr = OASE->getStride();
8641 llvm::Value *Stride =
8646 DimProd = CGF.
Builder.CreateNUWMul(DimProd, *(DI - 1));
8648 CurStrides.push_back(CGF.
Builder.CreateNUWMul(DimProd, Stride));
8650 CurStrides.push_back(DimProd);
8652 Offset = CGF.
Builder.CreateNUWMul(DimProd, Offset);
8653 CurOffsets.push_back(Offset);
8655 if (DI != DimSizes.end())
8659 CombinedInfo.NonContigInfo.Offsets.push_back(CurOffsets);
8660 CombinedInfo.NonContigInfo.Counts.push_back(CurCounts);
8661 CombinedInfo.NonContigInfo.Strides.push_back(CurStrides);
8667 OpenMPOffloadMappingFlags
8668 getMapModifiersForPrivateClauses(
const CapturedStmt::Capture &Cap)
const {
8676 return OpenMPOffloadMappingFlags::OMP_MAP_TO |
8677 OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ;
8678 return OpenMPOffloadMappingFlags::OMP_MAP_PRIVATE |
8679 OpenMPOffloadMappingFlags::OMP_MAP_TO;
8682 if (I != LambdasMap.end())
8684 return getMapTypeBits(
8685 I->getSecond()->getMapType(), I->getSecond()->getMapTypeModifiers(),
8686 {}, I->getSecond()->isImplicit(),
8690 return OpenMPOffloadMappingFlags::OMP_MAP_TO |
8691 OpenMPOffloadMappingFlags::OMP_MAP_FROM;
8694 void getPlainLayout(
const CXXRecordDecl *RD,
8695 llvm::SmallVectorImpl<const FieldDecl *> &Layout,
8696 bool AsBase)
const {
8699 llvm::StructType *St =
8702 unsigned NumElements = St->getNumElements();
8704 llvm::PointerUnion<const CXXRecordDecl *, const FieldDecl *>, 4>
8705 RecordLayout(NumElements);
8708 for (
const auto &I : RD->
bases()) {
8712 QualType BaseTy = I.getType();
8723 RecordLayout[FieldIndex] =
Base;
8726 for (
const auto &I : RD->
vbases()) {
8727 QualType BaseTy = I.getType();
8734 if (RecordLayout[FieldIndex])
8736 RecordLayout[FieldIndex] =
Base;
8739 assert(!RD->
isUnion() &&
"Unexpected union.");
8740 for (
const auto *Field : RD->
fields()) {
8743 if (!
Field->isBitField() &&
8746 RecordLayout[FieldIndex] =
Field;
8749 for (
const llvm::PointerUnion<const CXXRecordDecl *, const FieldDecl *>
8750 &
Data : RecordLayout) {
8753 if (
const auto *Base = dyn_cast<const CXXRecordDecl *>(
Data))
8754 getPlainLayout(Base, Layout,
true);
8761 static Address getAttachPtrAddr(
const Expr *PointerExpr,
8762 CodeGenFunction &CGF) {
8763 assert(PointerExpr &&
"Cannot get addr from null attach-ptr expr");
8766 if (
auto *DRE = dyn_cast<DeclRefExpr>(PointerExpr)) {
8769 }
else if (
auto *OASE = dyn_cast<ArraySectionExpr>(PointerExpr)) {
8772 }
else if (
auto *ASE = dyn_cast<ArraySubscriptExpr>(PointerExpr)) {
8774 }
else if (
auto *ME = dyn_cast<MemberExpr>(PointerExpr)) {
8776 }
else if (
auto *UO = dyn_cast<UnaryOperator>(PointerExpr)) {
8777 assert(UO->getOpcode() == UO_Deref &&
8778 "Unexpected unary-operator on attach-ptr-expr");
8781 assert(AttachPtrAddr.
isValid() &&
8782 "Failed to get address for attach pointer expression");
8783 return AttachPtrAddr;
8790 static std::pair<Address, Address>
8791 getAttachPtrAddrAndPteeBaseAddr(
const Expr *AttachPtrExpr,
8792 CodeGenFunction &CGF) {
8797 Address AttachPtrAddr = getAttachPtrAddr(AttachPtrExpr, CGF);
8798 assert(AttachPtrAddr.
isValid() &&
"Invalid attach pointer addr");
8800 QualType AttachPtrType =
8805 AttachPtrAddr, AttachPtrType->
castAs<PointerType>());
8806 assert(AttachPteeBaseAddr.
isValid() &&
"Invalid attach pointee base addr");
8808 return {AttachPtrAddr, AttachPteeBaseAddr};
8814 shouldEmitAttachEntry(
const Expr *PointerExpr,
const ValueDecl *MapBaseDecl,
8815 CodeGenFunction &CGF,
8816 llvm::PointerUnion<
const OMPExecutableDirective *,
8817 const OMPDeclareMapperDecl *>
8827 ->getDirectiveKind());
8836 void collectAttachPtrExprInfo(
8838 llvm::PointerUnion<
const OMPExecutableDirective *,
8839 const OMPDeclareMapperDecl *>
8844 ? OMPD_declare_mapper
8847 const auto &[AttachPtrExpr, Depth] =
8851 AttachPtrComputationOrderMap.try_emplace(
8852 AttachPtrExpr, AttachPtrComputationOrderMap.size());
8853 AttachPtrComponentDepthMap.try_emplace(AttachPtrExpr, Depth);
8854 AttachPtrExprMap.try_emplace(Components, AttachPtrExpr);
8862 void generateAllInfoForClauses(
8863 ArrayRef<const OMPClause *> Clauses, MapCombinedInfoTy &CombinedInfo,
8864 llvm::OpenMPIRBuilder &OMPBuilder,
8865 const llvm::DenseSet<CanonicalDeclPtr<const Decl>> &SkipVarSet =
8866 llvm::DenseSet<CanonicalDeclPtr<const Decl>>())
const {
8871 llvm::MapVector<CanonicalDeclPtr<const Decl>,
8872 SmallVector<SmallVector<MapInfo, 8>, 4>>
8878 [&Info, &SkipVarSet](
8879 const ValueDecl *D, MapKind
Kind,
8882 ArrayRef<OpenMPMapModifierKind> MapModifiers,
8883 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
8884 bool ReturnDevicePointer,
bool IsImplicit,
const ValueDecl *Mapper,
8885 const Expr *VarRef =
nullptr,
bool ForDeviceAddr =
false) {
8886 if (SkipVarSet.contains(D))
8888 auto It = Info.try_emplace(D, Total).first;
8889 It->second[
Kind].emplace_back(
8890 L, MapType, MapModifiers, MotionModifiers, ReturnDevicePointer,
8891 IsImplicit, Mapper, VarRef, ForDeviceAddr);
8894 for (
const auto *
Cl : Clauses) {
8895 const auto *
C = dyn_cast<OMPMapClause>(
Cl);
8899 if (llvm::is_contained(
C->getMapTypeModifiers(),
8900 OMPC_MAP_MODIFIER_present))
8902 else if (
C->getMapType() == OMPC_MAP_alloc)
8904 const auto *EI =
C->getVarRefs().begin();
8905 for (
const auto L :
C->component_lists()) {
8906 const Expr *E = (
C->getMapLoc().isValid()) ? *EI :
nullptr;
8907 InfoGen(std::get<0>(L), Kind, std::get<1>(L),
C->getMapType(),
8908 C->getMapTypeModifiers(), {},
8909 false,
C->isImplicit(), std::get<2>(L),
8914 for (
const auto *
Cl : Clauses) {
8915 const auto *
C = dyn_cast<OMPToClause>(
Cl);
8919 if (llvm::is_contained(
C->getMotionModifiers(),
8920 OMPC_MOTION_MODIFIER_present))
8922 if (llvm::is_contained(
C->getMotionModifiers(),
8923 OMPC_MOTION_MODIFIER_iterator)) {
8924 if (
auto *IteratorExpr = dyn_cast<OMPIteratorExpr>(
8925 C->getIteratorModifier()->IgnoreParenImpCasts())) {
8926 const auto *VD =
cast<VarDecl>(IteratorExpr->getIteratorDecl(0));
8931 const auto *EI =
C->getVarRefs().begin();
8932 for (
const auto L :
C->component_lists()) {
8933 InfoGen(std::get<0>(L), Kind, std::get<1>(L), OMPC_MAP_to, {},
8934 C->getMotionModifiers(),
false,
8935 C->isImplicit(), std::get<2>(L), *EI);
8939 for (
const auto *
Cl : Clauses) {
8940 const auto *
C = dyn_cast<OMPFromClause>(
Cl);
8944 if (llvm::is_contained(
C->getMotionModifiers(),
8945 OMPC_MOTION_MODIFIER_present))
8947 if (llvm::is_contained(
C->getMotionModifiers(),
8948 OMPC_MOTION_MODIFIER_iterator)) {
8949 if (
auto *IteratorExpr = dyn_cast<OMPIteratorExpr>(
8950 C->getIteratorModifier()->IgnoreParenImpCasts())) {
8951 const auto *VD =
cast<VarDecl>(IteratorExpr->getIteratorDecl(0));
8956 const auto *EI =
C->getVarRefs().begin();
8957 for (
const auto L :
C->component_lists()) {
8958 InfoGen(std::get<0>(L), Kind, std::get<1>(L), OMPC_MAP_from, {},
8959 C->getMotionModifiers(),
8960 false,
C->isImplicit(), std::get<2>(L),
8973 MapCombinedInfoTy UseDeviceDataCombinedInfo;
8975 auto &&UseDeviceDataCombinedInfoGen =
8976 [&UseDeviceDataCombinedInfo](
const ValueDecl *VD, llvm::Value *Ptr,
8977 CodeGenFunction &CGF,
bool IsDevAddr,
8978 bool HasUdpFbNullify =
false) {
8979 UseDeviceDataCombinedInfo.Exprs.push_back(VD);
8980 UseDeviceDataCombinedInfo.BasePointers.emplace_back(Ptr);
8981 UseDeviceDataCombinedInfo.DevicePtrDecls.emplace_back(VD);
8982 UseDeviceDataCombinedInfo.DevicePointers.emplace_back(
8983 IsDevAddr ? DeviceInfoTy::Address : DeviceInfoTy::Pointer);
8989 UseDeviceDataCombinedInfo.Pointers.push_back(Ptr);
8990 UseDeviceDataCombinedInfo.Sizes.push_back(
8991 llvm::Constant::getNullValue(CGF.Int64Ty));
8992 OpenMPOffloadMappingFlags Flags =
8993 OpenMPOffloadMappingFlags::OMP_MAP_RETURN_PARAM;
8994 if (HasUdpFbNullify)
8995 Flags |= OpenMPOffloadMappingFlags::OMP_MAP_FB_NULLIFY;
8996 UseDeviceDataCombinedInfo.Types.push_back(Flags);
8997 UseDeviceDataCombinedInfo.Mappers.push_back(
nullptr);
9001 [&UseDeviceDataCombinedInfoGen](
9002 CodeGenFunction &CGF,
const Expr *IE,
const ValueDecl *VD,
9005 bool IsDevAddr,
bool IEIsAttachPtrForDevAddr =
false,
9006 bool HasUdpFbNullify =
false) {
9010 if (IsDevAddr && !IEIsAttachPtrForDevAddr) {
9011 if (IE->isGLValue())
9018 bool TreatDevAddrAsDevPtr = IEIsAttachPtrForDevAddr;
9025 UseDeviceDataCombinedInfoGen(VD, Ptr, CGF, IsDevAddr &&
9026 !TreatDevAddrAsDevPtr,
9030 auto &&IsMapInfoExist =
9031 [&Info,
this](CodeGenFunction &CGF,
const ValueDecl *VD,
const Expr *IE,
9032 const Expr *DesiredAttachPtrExpr,
bool IsDevAddr,
9033 bool HasUdpFbNullify =
false) ->
bool {
9041 if (It != Info.end()) {
9043 for (
auto &
Data : It->second) {
9044 MapInfo *CI =
nullptr;
9048 auto *It = llvm::find_if(
Data, [&](
const MapInfo &MI) {
9049 if (MI.Components.back().getAssociatedDeclaration() != VD)
9052 const Expr *MapAttachPtr = getAttachPtrExpr(MI.Components);
9053 bool Match = AttachPtrComparator.areEqual(MapAttachPtr,
9054 DesiredAttachPtrExpr);
9058 if (It !=
Data.end())
9063 CI->ForDeviceAddr =
true;
9064 CI->ReturnDevicePointer =
true;
9065 CI->HasUdpFbNullify = HasUdpFbNullify;
9069 auto PrevCI = std::next(CI->Components.rbegin());
9070 const auto *VarD = dyn_cast<VarDecl>(VD);
9071 const Expr *AttachPtrExpr = getAttachPtrExpr(CI->Components);
9072 if (CGF.CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory() ||
9074 !VD->getType().getNonReferenceType()->isPointerType() ||
9075 PrevCI == CI->Components.rend() ||
9077 VarD->hasLocalStorage() ||
9078 (isa_and_nonnull<DeclRefExpr>(AttachPtrExpr) &&
9080 CI->ForDeviceAddr = IsDevAddr;
9081 CI->ReturnDevicePointer =
true;
9082 CI->HasUdpFbNullify = HasUdpFbNullify;
9100 for (
const auto *
Cl : Clauses) {
9101 const auto *
C = dyn_cast<OMPUseDevicePtrClause>(
Cl);
9104 bool HasUdpFbNullify =
9105 C->getFallbackModifier() == OMPC_USE_DEVICE_PTR_FALLBACK_fb_nullify;
9106 for (
const auto L :
C->component_lists()) {
9109 assert(!Components.empty() &&
9110 "Not expecting empty list of components!");
9111 const ValueDecl *VD = Components.back().getAssociatedDeclaration();
9113 const Expr *IE = Components.back().getAssociatedExpression();
9121 const Expr *UDPOperandExpr =
9122 Components.front().getAssociatedExpression();
9123 if (IsMapInfoExist(CGF, VD, IE,
9125 false, HasUdpFbNullify))
9127 MapInfoGen(CGF, IE, VD, Components,
false,
9128 false, HasUdpFbNullify);
9132 llvm::SmallDenseSet<CanonicalDeclPtr<const Decl>, 4> Processed;
9133 for (
const auto *
Cl : Clauses) {
9134 const auto *
C = dyn_cast<OMPUseDeviceAddrClause>(
Cl);
9137 for (
const auto L :
C->component_lists()) {
9140 assert(!std::get<1>(L).empty() &&
9141 "Not expecting empty list of components!");
9142 const ValueDecl *VD = std::get<1>(L).back().getAssociatedDeclaration();
9143 if (!Processed.insert(VD).second)
9164 const Expr *UDAAttachPtrExpr = getAttachPtrExpr(Components);
9165 const Expr *IE = std::get<1>(L).back().getAssociatedExpression();
9166 assert((!UDAAttachPtrExpr || UDAAttachPtrExpr == IE) &&
9167 "use_device_addr operand has an attach-ptr, but does not match "
9168 "last component's expr.");
9169 if (IsMapInfoExist(CGF, VD, IE,
9173 MapInfoGen(CGF, IE, VD, Components,
9175 UDAAttachPtrExpr !=
nullptr);
9179 for (
const auto &
Data : Info) {
9180 MapCombinedInfoTy CurInfo;
9182 const ValueDecl *VD = cast_or_null<ValueDecl>(D);
9189 SmallVector<std::pair<const Expr *, MapInfo>, 16> AttachPtrMapInfoPairs;
9192 for (
const auto &M :
Data.second) {
9193 for (
const MapInfo &L : M) {
9194 assert(!L.Components.empty() &&
9195 "Not expecting declaration with no component lists.");
9197 const Expr *AttachPtrExpr = getAttachPtrExpr(L.Components);
9198 AttachPtrMapInfoPairs.emplace_back(AttachPtrExpr, L);
9203 llvm::stable_sort(AttachPtrMapInfoPairs,
9204 [
this](
const auto &LHS,
const auto &RHS) {
9205 return AttachPtrComparator(LHS.first, RHS.first);
9210 auto *It = AttachPtrMapInfoPairs.begin();
9211 while (It != AttachPtrMapInfoPairs.end()) {
9212 const Expr *AttachPtrExpr = It->first;
9214 SmallVector<MapInfo, 8> GroupLists;
9215 while (It != AttachPtrMapInfoPairs.end() &&
9216 (It->first == AttachPtrExpr ||
9217 AttachPtrComparator.areEqual(It->first, AttachPtrExpr))) {
9218 GroupLists.push_back(It->second);
9221 assert(!GroupLists.empty() &&
"GroupLists should not be empty");
9223 StructRangeInfoTy PartialStruct;
9224 AttachInfoTy AttachInfo;
9225 MapCombinedInfoTy GroupCurInfo;
9227 MapCombinedInfoTy GroupStructBaseCurInfo;
9228 for (
const MapInfo &L : GroupLists) {
9230 unsigned CurrentBasePointersIdx = GroupCurInfo.BasePointers.size();
9231 unsigned StructBasePointersIdx =
9232 GroupStructBaseCurInfo.BasePointers.size();
9234 GroupCurInfo.NonContigInfo.IsNonContiguous =
9235 L.Components.back().isNonContiguous();
9236 generateInfoForComponentList(
9237 L.MapType, L.MapModifiers, L.MotionModifiers, L.Components,
9238 GroupCurInfo, GroupStructBaseCurInfo, PartialStruct, AttachInfo,
9239 false, L.IsImplicit,
9240 true, L.Mapper, L.ForDeviceAddr, VD,
9245 if (L.ReturnDevicePointer) {
9249 assert((CurrentBasePointersIdx < GroupCurInfo.BasePointers.size() ||
9250 StructBasePointersIdx <
9251 GroupStructBaseCurInfo.BasePointers.size()) &&
9252 "Unexpected number of mapped base pointers.");
9255 const ValueDecl *RelevantVD =
9256 L.Components.back().getAssociatedDeclaration();
9257 assert(RelevantVD &&
9258 "No relevant declaration related with device pointer??");
9265 auto SetDevicePointerInfo = [&](MapCombinedInfoTy &Info,
9267 Info.DevicePtrDecls[Idx] = RelevantVD;
9268 Info.DevicePointers[Idx] = L.ForDeviceAddr
9269 ? DeviceInfoTy::Address
9270 : DeviceInfoTy::Pointer;
9272 OpenMPOffloadMappingFlags::OMP_MAP_RETURN_PARAM;
9273 if (L.HasUdpFbNullify)
9275 OpenMPOffloadMappingFlags::OMP_MAP_FB_NULLIFY;
9278 if (StructBasePointersIdx <
9279 GroupStructBaseCurInfo.BasePointers.size())
9280 SetDevicePointerInfo(GroupStructBaseCurInfo,
9281 StructBasePointersIdx);
9283 SetDevicePointerInfo(GroupCurInfo, CurrentBasePointersIdx);
9289 MapCombinedInfoTy GroupUnionCurInfo;
9290 GroupUnionCurInfo.append(GroupStructBaseCurInfo);
9291 GroupUnionCurInfo.append(GroupCurInfo);
9295 if (PartialStruct.Base.isValid()) {
9303 GroupUnionCurInfo.NonContigInfo.Dims.insert(
9304 GroupUnionCurInfo.NonContigInfo.Dims.begin(), 1);
9306 CurInfo, GroupUnionCurInfo.Types, PartialStruct, AttachInfo,
9307 !VD, OMPBuilder, VD,
9308 CombinedInfo.BasePointers.size(),
9314 CurInfo.append(GroupUnionCurInfo);
9315 if (AttachInfo.isValid())
9316 emitAttachEntry(CGF, CurInfo, AttachInfo);
9320 CombinedInfo.append(CurInfo);
9323 CombinedInfo.append(UseDeviceDataCombinedInfo);
9327 MappableExprsHandler(
const OMPExecutableDirective &Dir, CodeGenFunction &CGF)
9328 : CurDir(&Dir), CGF(CGF), AttachPtrComparator(*this) {
9330 for (
const auto *
C : Dir.getClausesOfKind<OMPFirstprivateClause>())
9331 for (
const auto *D :
C->varlist())
9332 FirstPrivateDecls.try_emplace(
9335 for (
const auto *
C : Dir.getClausesOfKind<OMPUsesAllocatorsClause>()) {
9336 for (unsigned I = 0, E = C->getNumberOfAllocators(); I < E; ++I) {
9337 OMPUsesAllocatorsClause::Data D = C->getAllocatorData(I);
9338 if (const auto *DRE = dyn_cast_or_null<DeclRefExpr>(D.AllocatorTraits))
9339 FirstPrivateDecls.try_emplace(cast<VarDecl>(DRE->getDecl()),
9341 else if (const auto *VD = dyn_cast<VarDecl>(
9342 cast<DeclRefExpr>(D.Allocator->IgnoreParenImpCasts())
9344 FirstPrivateDecls.try_emplace(VD, true);
9348 for (
const auto *
C : Dir.getClausesOfKind<OMPDefaultmapClause>())
9349 if (
C->getDefaultmapModifier() == OMPC_DEFAULTMAP_MODIFIER_firstprivate)
9350 DefaultmapFirstprivateKinds.insert(
C->getDefaultmapKind());
9352 for (
const auto *
C : Dir.getClausesOfKind<OMPIsDevicePtrClause>())
9353 for (
auto L :
C->component_lists())
9354 DevPointersMap[std::get<0>(L)].push_back(std::get<1>(L));
9356 for (
const auto *
C : Dir.getClausesOfKind<OMPHasDeviceAddrClause>())
9357 for (
auto L :
C->component_lists())
9358 HasDevAddrsMap[std::get<0>(L)].push_back(std::get<1>(L));
9360 for (
const auto *
C : Dir.getClausesOfKind<OMPMapClause>()) {
9361 if (C->getMapType() != OMPC_MAP_to)
9363 for (auto L : C->component_lists()) {
9364 const ValueDecl *VD = std::get<0>(L);
9365 const auto *RD = VD ? VD->getType()
9367 .getNonReferenceType()
9368 ->getAsCXXRecordDecl()
9370 if (RD && RD->isLambda())
9371 LambdasMap.try_emplace(std::get<0>(L), C);
9375 auto CollectAttachPtrExprsForClauseComponents = [
this](
const auto *
C) {
9376 for (
auto L :
C->component_lists()) {
9379 if (!Components.empty())
9380 collectAttachPtrExprInfo(Components, CurDir);
9386 for (
const auto *
C : Dir.getClausesOfKind<OMPMapClause>())
9387 CollectAttachPtrExprsForClauseComponents(
C);
9388 for (
const auto *
C : Dir.getClausesOfKind<OMPToClause>())
9389 CollectAttachPtrExprsForClauseComponents(
C);
9390 for (
const auto *
C : Dir.getClausesOfKind<OMPFromClause>())
9391 CollectAttachPtrExprsForClauseComponents(
C);
9392 for (
const auto *
C : Dir.getClausesOfKind<OMPUseDevicePtrClause>())
9393 CollectAttachPtrExprsForClauseComponents(
C);
9394 for (
const auto *
C : Dir.getClausesOfKind<OMPUseDeviceAddrClause>())
9395 CollectAttachPtrExprsForClauseComponents(
C);
9396 for (
const auto *
C : Dir.getClausesOfKind<OMPIsDevicePtrClause>())
9397 CollectAttachPtrExprsForClauseComponents(
C);
9398 for (
const auto *
C : Dir.getClausesOfKind<OMPHasDeviceAddrClause>())
9399 CollectAttachPtrExprsForClauseComponents(
C);
9403 MappableExprsHandler(
const OMPDeclareMapperDecl &Dir,
CodeGenFunction &CGF)
9404 : CurDir(&Dir), CGF(CGF), AttachPtrComparator(*this) {}
9414 void emitCombinedEntry(MapCombinedInfoTy &CombinedInfo,
9415 MapFlagsArrayTy &CurTypes,
9416 const StructRangeInfoTy &PartialStruct,
9417 AttachInfoTy &AttachInfo,
bool IsMapThis,
9418 llvm::OpenMPIRBuilder &OMPBuilder,
const ValueDecl *VD,
9419 unsigned OffsetForMemberOfFlag,
9420 bool NotTargetParams)
const {
9421 if (CurTypes.size() == 1 &&
9422 ((CurTypes.back() & OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF) !=
9423 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF) &&
9424 !PartialStruct.IsArraySection)
9426 Address LBAddr = PartialStruct.LowestElem.second;
9427 Address HBAddr = PartialStruct.HighestElem.second;
9428 if (PartialStruct.HasCompleteRecord) {
9429 LBAddr = PartialStruct.LB;
9430 HBAddr = PartialStruct.LB;
9432 CombinedInfo.Exprs.push_back(VD);
9434 CombinedInfo.BasePointers.push_back(PartialStruct.Base.emitRawPointer(CGF));
9435 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
9436 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
9439 const CXXMethodDecl *MD =
9441 const CXXRecordDecl *RD = MD ? MD->
getParent() :
nullptr;
9442 bool HasBaseClass = RD && IsMapThis ? RD->
getNumBases() > 0 :
false;
9452 CombinedInfo.Pointers.push_back(PartialStruct.Base.emitRawPointer(CGF));
9457 CombinedInfo.Sizes.push_back(Size);
9459 CombinedInfo.Pointers.push_back(LB);
9462 llvm::Value *HAddr = CGF.
Builder.CreateConstGEP1_32(
9466 llvm::Value *Diff = CGF.
Builder.CreatePtrDiff(CHAddr, CLAddr);
9469 CombinedInfo.Sizes.push_back(Size);
9471 CombinedInfo.Mappers.push_back(
nullptr);
9473 CombinedInfo.Types.push_back(
9474 NotTargetParams ? OpenMPOffloadMappingFlags::OMP_MAP_NONE
9475 : !PartialStruct.PreliminaryMapData.BasePointers.empty()
9476 ? OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ
9477 : OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM);
9480 if (CurTypes.end() !=
9481 llvm::find_if(CurTypes, [](OpenMPOffloadMappingFlags
Type) {
9482 return static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>>(
9483 Type & OpenMPOffloadMappingFlags::OMP_MAP_PRESENT);
9485 CombinedInfo.Types.back() |= OpenMPOffloadMappingFlags::OMP_MAP_PRESENT;
9487 (*CurTypes.begin()) &= ~OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM;
9494 if (CurTypes.end() !=
9495 llvm::find_if(CurTypes, [](OpenMPOffloadMappingFlags
Type) {
9496 return static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>>(
9497 Type & OpenMPOffloadMappingFlags::OMP_MAP_OMPX_HOLD);
9499 CombinedInfo.Types.back() |= OpenMPOffloadMappingFlags::OMP_MAP_OMPX_HOLD;
9500 for (
auto &M : CurTypes)
9501 M |= OpenMPOffloadMappingFlags::OMP_MAP_OMPX_HOLD;
9508 OpenMPOffloadMappingFlags MemberOfFlag = OMPBuilder.getMemberOfFlag(
9509 OffsetForMemberOfFlag + CombinedInfo.BasePointers.size() - 1);
9510 for (
auto &M : CurTypes)
9511 OMPBuilder.setCorrectMemberOfFlag(M, MemberOfFlag);
9528 if (AttachInfo.isValid())
9529 AttachInfo.AttachPteeAddr = LBAddr;
9537 void generateAllInfo(
9538 MapCombinedInfoTy &CombinedInfo, llvm::OpenMPIRBuilder &OMPBuilder,
9539 const llvm::DenseSet<CanonicalDeclPtr<const Decl>> &SkipVarSet =
9540 llvm::DenseSet<CanonicalDeclPtr<const Decl>>())
const {
9542 "Expect a executable directive");
9544 generateAllInfoForClauses(CurExecDir->clauses(), CombinedInfo, OMPBuilder,
9551 void generateAllInfoForMapper(MapCombinedInfoTy &CombinedInfo,
9552 llvm::OpenMPIRBuilder &OMPBuilder)
const {
9554 "Expect a declare mapper directive");
9556 generateAllInfoForClauses(CurMapperDir->clauses(), CombinedInfo,
9561 void generateInfoForLambdaCaptures(
9562 const ValueDecl *VD, llvm::Value *Arg, MapCombinedInfoTy &CombinedInfo,
9563 llvm::DenseMap<llvm::Value *, llvm::Value *> &LambdaPointers)
const {
9571 llvm::DenseMap<const ValueDecl *, FieldDecl *> Captures;
9572 FieldDecl *ThisCapture =
nullptr;
9578 LambdaPointers.try_emplace(ThisLVal.getPointer(CGF),
9579 VDLVal.getPointer(CGF));
9580 CombinedInfo.Exprs.push_back(VD);
9581 CombinedInfo.BasePointers.push_back(ThisLVal.getPointer(CGF));
9582 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
9583 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
9584 CombinedInfo.Pointers.push_back(ThisLValVal.getPointer(CGF));
9585 CombinedInfo.Sizes.push_back(
9588 CombinedInfo.Types.push_back(
9589 OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ |
9590 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL |
9591 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF |
9592 OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT);
9593 CombinedInfo.Mappers.push_back(
nullptr);
9595 for (
const LambdaCapture &LC : RD->
captures()) {
9596 if (!LC.capturesVariable())
9601 auto It = Captures.find(VD);
9602 assert(It != Captures.end() &&
"Found lambda capture without field.");
9606 LambdaPointers.try_emplace(VarLVal.getPointer(CGF),
9607 VDLVal.getPointer(CGF));
9608 CombinedInfo.Exprs.push_back(VD);
9609 CombinedInfo.BasePointers.push_back(VarLVal.getPointer(CGF));
9610 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
9611 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
9612 CombinedInfo.Pointers.push_back(VarLValVal.getPointer(CGF));
9613 CombinedInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
9619 LambdaPointers.try_emplace(VarLVal.getPointer(CGF),
9620 VDLVal.getPointer(CGF));
9621 CombinedInfo.Exprs.push_back(VD);
9622 CombinedInfo.BasePointers.push_back(VarLVal.getPointer(CGF));
9623 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
9624 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
9625 CombinedInfo.Pointers.push_back(VarRVal.
getScalarVal());
9626 CombinedInfo.Sizes.push_back(llvm::ConstantInt::get(CGF.
Int64Ty, 0));
9628 CombinedInfo.Types.push_back(
9629 OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ |
9630 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL |
9631 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF |
9632 OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT);
9633 CombinedInfo.Mappers.push_back(
nullptr);
9638 void adjustMemberOfForLambdaCaptures(
9639 llvm::OpenMPIRBuilder &OMPBuilder,
9640 const llvm::DenseMap<llvm::Value *, llvm::Value *> &LambdaPointers,
9641 MapBaseValuesArrayTy &BasePointers, MapValuesArrayTy &Pointers,
9642 MapFlagsArrayTy &Types)
const {
9643 for (
unsigned I = 0, E = Types.size(); I < E; ++I) {
9645 if (Types[I] != (OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ |
9646 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL |
9647 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF |
9648 OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT))
9650 llvm::Value *BasePtr = LambdaPointers.lookup(BasePointers[I]);
9651 assert(BasePtr &&
"Unable to find base lambda address.");
9653 for (
unsigned J = I; J > 0; --J) {
9654 unsigned Idx = J - 1;
9655 if (Pointers[Idx] != BasePtr)
9660 assert(TgtIdx != -1 &&
"Unable to find parent lambda.");
9664 OpenMPOffloadMappingFlags MemberOfFlag =
9665 OMPBuilder.getMemberOfFlag(TgtIdx);
9666 OMPBuilder.setCorrectMemberOfFlag(Types[I], MemberOfFlag);
9672 void populateComponentListsForNonLambdaCaptureFromClauses(
9673 const ValueDecl *VD, MapDataArrayTy &DeclComponentLists,
9675 SmallVector<OMPClauseMappableExprCommon::MappableComponent, 8>>
9676 &StorageForImplicitlyAddedComponentLists)
const {
9677 if (VD && LambdasMap.count(VD))
9683 auto It = DevPointersMap.find(VD);
9684 if (It != DevPointersMap.end())
9685 for (
const auto &MCL : It->second)
9686 DeclComponentLists.emplace_back(MCL, OMPC_MAP_to,
Unknown,
9689 auto I = HasDevAddrsMap.find(VD);
9690 if (I != HasDevAddrsMap.end())
9691 for (
const auto &MCL : I->second)
9692 DeclComponentLists.emplace_back(MCL, OMPC_MAP_tofrom,
Unknown,
9696 "Expect a executable directive");
9698 for (
const auto *
C : CurExecDir->getClausesOfKind<OMPMapClause>()) {
9699 const auto *EI =
C->getVarRefs().begin();
9700 for (
const auto L :
C->decl_component_lists(VD)) {
9701 const ValueDecl *VDecl, *Mapper;
9703 const Expr *E = (
C->getMapLoc().isValid()) ? *EI :
nullptr;
9705 std::tie(VDecl, Components, Mapper) = L;
9706 assert(VDecl == VD &&
"We got information for the wrong declaration??");
9707 assert(!Components.empty() &&
9708 "Not expecting declaration with no component lists.");
9709 DeclComponentLists.emplace_back(Components,
C->getMapType(),
9710 C->getMapTypeModifiers(),
9711 C->isImplicit(), Mapper, E);
9720 addImplicitMapForAttachPtrBaseIfMemberOfCapturedVD(
9721 VD, DeclComponentLists, StorageForImplicitlyAddedComponentLists);
9723 llvm::stable_sort(DeclComponentLists, [](
const MapData &LHS,
9724 const MapData &RHS) {
9725 ArrayRef<OpenMPMapModifierKind> MapModifiers = std::get<2>(LHS);
9728 llvm::is_contained(MapModifiers, clang::OMPC_MAP_MODIFIER_present);
9729 bool HasAllocs = MapType == OMPC_MAP_alloc;
9730 MapModifiers = std::get<2>(RHS);
9731 MapType = std::get<1>(LHS);
9733 llvm::is_contained(MapModifiers, clang::OMPC_MAP_MODIFIER_present);
9734 bool HasAllocsR = MapType == OMPC_MAP_alloc;
9735 return (HasPresent && !HasPresentR) || (HasAllocs && !HasAllocsR);
9771 void addImplicitMapForAttachPtrBaseIfMemberOfCapturedVD(
9772 const ValueDecl *CapturedVD, MapDataArrayTy &DeclComponentLists,
9774 SmallVector<OMPClauseMappableExprCommon::MappableComponent, 8>>
9775 &ComponentVectorStorage)
const {
9776 bool IsThisCapture = CapturedVD ==
nullptr;
9778 for (
const auto &ComponentsAndAttachPtr : AttachPtrExprMap) {
9780 ComponentsWithAttachPtr = ComponentsAndAttachPtr.first;
9781 const Expr *AttachPtrExpr = ComponentsAndAttachPtr.second;
9785 const auto *ME = dyn_cast<MemberExpr>(AttachPtrExpr);
9789 const Expr *
Base = ME->getBase()->IgnoreParenImpCasts();
9810 bool FoundExistingMap =
false;
9811 for (
const MapData &ExistingL : DeclComponentLists) {
9813 ExistingComponents = std::get<0>(ExistingL);
9815 if (ExistingComponents.empty())
9819 const auto &FirstComponent = ExistingComponents.front();
9820 const Expr *FirstExpr = FirstComponent.getAssociatedExpression();
9826 if (AttachPtrComparator.areEqual(FirstExpr, AttachPtrExpr)) {
9827 FoundExistingMap =
true;
9832 if (IsThisCapture) {
9833 if (
const auto *OASE = dyn_cast<ArraySectionExpr>(FirstExpr)) {
9835 FoundExistingMap =
true;
9844 if (
const auto *DRE = dyn_cast<DeclRefExpr>(FirstExpr)) {
9845 if (DRE->getDecl() == CapturedVD) {
9846 FoundExistingMap =
true;
9852 if (FoundExistingMap)
9858 ComponentVectorStorage.emplace_back();
9859 auto &AttachPtrComponents = ComponentVectorStorage.back();
9862 bool SeenAttachPtrComponent =
false;
9868 for (
size_t i = 0; i < ComponentsWithAttachPtr.size(); ++i) {
9869 const auto &Component = ComponentsWithAttachPtr[i];
9870 const Expr *ComponentExpr = Component.getAssociatedExpression();
9872 if (!SeenAttachPtrComponent && ComponentExpr != AttachPtrExpr)
9874 SeenAttachPtrComponent =
true;
9876 AttachPtrComponents.emplace_back(Component.getAssociatedExpression(),
9877 Component.getAssociatedDeclaration(),
9878 Component.isNonContiguous());
9880 assert(!AttachPtrComponents.empty() &&
9881 "Could not populate component-lists for mapping attach-ptr");
9883 DeclComponentLists.emplace_back(
9884 AttachPtrComponents, OMPC_MAP_tofrom,
Unknown,
9885 true,
nullptr, AttachPtrExpr);
9892 void generateInfoForCaptureFromClauseInfo(
9893 const MapDataArrayTy &DeclComponentListsFromClauses,
9894 const CapturedStmt::Capture *Cap, llvm::Value *Arg,
9895 MapCombinedInfoTy &CurCaptureVarInfo, llvm::OpenMPIRBuilder &OMPBuilder,
9896 unsigned OffsetForMemberOfFlag)
const {
9898 "Not expecting to generate map info for a variable array type!");
9907 if (LambdasMap.count(VD))
9913 if (VD && (DevPointersMap.count(VD) || HasDevAddrsMap.count(VD))) {
9914 CurCaptureVarInfo.Exprs.push_back(VD);
9915 CurCaptureVarInfo.BasePointers.emplace_back(Arg);
9916 CurCaptureVarInfo.DevicePtrDecls.emplace_back(VD);
9917 CurCaptureVarInfo.DevicePointers.emplace_back(DeviceInfoTy::Pointer);
9918 CurCaptureVarInfo.Pointers.push_back(Arg);
9919 CurCaptureVarInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
9922 CurCaptureVarInfo.Types.push_back(
9923 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL |
9924 OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM);
9925 CurCaptureVarInfo.Mappers.push_back(
nullptr);
9929 auto GenerateInfoForComponentLists =
9930 [&](ArrayRef<MapData> DeclComponentListsFromClauses,
9931 bool IsEligibleForTargetParamFlag) {
9932 MapCombinedInfoTy CurInfoForComponentLists;
9933 StructRangeInfoTy PartialStruct;
9934 AttachInfoTy AttachInfo;
9936 if (DeclComponentListsFromClauses.empty())
9939 generateInfoForCaptureFromComponentLists(
9940 VD, DeclComponentListsFromClauses, CurInfoForComponentLists,
9941 PartialStruct, AttachInfo, IsEligibleForTargetParamFlag);
9946 if (PartialStruct.Base.isValid()) {
9947 CurCaptureVarInfo.append(PartialStruct.PreliminaryMapData);
9949 CurCaptureVarInfo, CurInfoForComponentLists.Types,
9950 PartialStruct, AttachInfo, Cap->
capturesThis(), OMPBuilder,
9951 nullptr, OffsetForMemberOfFlag,
9952 !IsEligibleForTargetParamFlag);
9957 CurCaptureVarInfo.append(CurInfoForComponentLists);
9958 if (AttachInfo.isValid())
9959 emitAttachEntry(CGF, CurCaptureVarInfo, AttachInfo);
9983 SmallVector<std::pair<const Expr *, MapData>, 16> AttachPtrMapDataPairs;
9985 for (
const MapData &L : DeclComponentListsFromClauses) {
9988 const Expr *AttachPtrExpr = getAttachPtrExpr(Components);
9989 AttachPtrMapDataPairs.emplace_back(AttachPtrExpr, L);
9993 llvm::stable_sort(AttachPtrMapDataPairs,
9994 [
this](
const auto &LHS,
const auto &RHS) {
9995 return AttachPtrComparator(LHS.first, RHS.first);
9998 bool NoDefaultMappingDoneForVD = CurCaptureVarInfo.BasePointers.empty();
9999 bool IsFirstGroup =
true;
10003 auto *It = AttachPtrMapDataPairs.begin();
10004 while (It != AttachPtrMapDataPairs.end()) {
10005 const Expr *AttachPtrExpr = It->first;
10007 MapDataArrayTy GroupLists;
10008 while (It != AttachPtrMapDataPairs.end() &&
10009 (It->first == AttachPtrExpr ||
10010 AttachPtrComparator.areEqual(It->first, AttachPtrExpr))) {
10011 GroupLists.push_back(It->second);
10014 assert(!GroupLists.empty() &&
"GroupLists should not be empty");
10019 bool IsEligibleForTargetParamFlag =
10020 IsFirstGroup && NoDefaultMappingDoneForVD;
10022 GenerateInfoForComponentLists(GroupLists, IsEligibleForTargetParamFlag);
10023 IsFirstGroup =
false;
10030 void generateInfoForCaptureFromComponentLists(
10031 const ValueDecl *VD, ArrayRef<MapData> DeclComponentLists,
10032 MapCombinedInfoTy &CurComponentListInfo, StructRangeInfoTy &PartialStruct,
10033 AttachInfoTy &AttachInfo,
bool IsListEligibleForTargetParamFlag)
const {
10035 llvm::SmallDenseMap<
10042 for (
const MapData &L : DeclComponentLists) {
10045 ArrayRef<OpenMPMapModifierKind> MapModifiers;
10047 const ValueDecl *Mapper;
10048 const Expr *VarRef;
10049 std::tie(Components, MapType, MapModifiers, IsImplicit, Mapper, VarRef) =
10052 for (
const MapData &L1 : ArrayRef(DeclComponentLists).slice(Count)) {
10054 std::tie(Components1, MapType, MapModifiers, IsImplicit, Mapper,
10056 auto CI = Components.rbegin();
10057 auto CE = Components.rend();
10058 auto SI = Components1.rbegin();
10059 auto SE = Components1.rend();
10060 for (; CI != CE && SI != SE; ++CI, ++SI) {
10061 if (CI->getAssociatedExpression()->getStmtClass() !=
10062 SI->getAssociatedExpression()->getStmtClass())
10065 if (CI->getAssociatedDeclaration() != SI->getAssociatedDeclaration())
10070 if (CI == CE || SI == SE) {
10072 if (CI == CE && SI == SE)
10074 const auto It = (SI == SE) ? CI : SI;
10081 (std::prev(It)->getAssociatedDeclaration() &&
10083 ->getAssociatedDeclaration()
10085 ->isPointerType()) ||
10086 (It->getAssociatedDeclaration() &&
10087 It->getAssociatedDeclaration()->getType()->isPointerType() &&
10088 std::next(It) != CE && std::next(It) != SE))
10090 const MapData &BaseData = CI == CE ? L : L1;
10092 SI == SE ? Components : Components1;
10093 OverlappedData[&BaseData].push_back(SubData);
10098 llvm::SmallVector<const FieldDecl *, 4> Layout;
10099 if (!OverlappedData.empty()) {
10102 while (BaseType != OrigType) {
10108 getPlainLayout(CRD, Layout,
false);
10114 for (
auto &Pair : OverlappedData) {
10121 auto CI = First.rbegin();
10122 auto CE = First.rend();
10123 auto SI = Second.rbegin();
10124 auto SE = Second.rend();
10125 for (; CI != CE && SI != SE; ++CI, ++SI) {
10126 if (CI->getAssociatedExpression()->getStmtClass() !=
10127 SI->getAssociatedExpression()->getStmtClass())
10130 if (CI->getAssociatedDeclaration() !=
10131 SI->getAssociatedDeclaration())
10136 if (CI == CE && SI == SE)
10140 if (CI == CE || SI == SE)
10145 if (FD1->getParent() == FD2->getParent())
10146 return FD1->getFieldIndex() < FD2->getFieldIndex();
10148 llvm::find_if(Layout, [FD1, FD2](
const FieldDecl *FD) {
10149 return FD == FD1 || FD == FD2;
10157 bool AddTargetParamFlag = IsListEligibleForTargetParamFlag;
10158 MapCombinedInfoTy StructBaseCombinedInfo;
10159 for (
const auto &Pair : OverlappedData) {
10160 const MapData &L = *Pair.getFirst();
10163 ArrayRef<OpenMPMapModifierKind> MapModifiers;
10165 const ValueDecl *Mapper;
10166 const Expr *VarRef;
10167 std::tie(Components, MapType, MapModifiers, IsImplicit, Mapper, VarRef) =
10169 ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef>
10170 OverlappedComponents = Pair.getSecond();
10171 generateInfoForComponentList(
10172 MapType, MapModifiers, {}, Components, CurComponentListInfo,
10173 StructBaseCombinedInfo, PartialStruct, AttachInfo, AddTargetParamFlag,
10174 IsImplicit,
false, Mapper,
10175 false, VD, VarRef, OverlappedComponents);
10176 AddTargetParamFlag =
false;
10179 for (
const MapData &L : DeclComponentLists) {
10182 ArrayRef<OpenMPMapModifierKind> MapModifiers;
10184 const ValueDecl *Mapper;
10185 const Expr *VarRef;
10186 std::tie(Components, MapType, MapModifiers, IsImplicit, Mapper, VarRef) =
10188 auto It = OverlappedData.find(&L);
10189 if (It == OverlappedData.end())
10190 generateInfoForComponentList(
10191 MapType, MapModifiers, {}, Components, CurComponentListInfo,
10192 StructBaseCombinedInfo, PartialStruct, AttachInfo,
10193 AddTargetParamFlag, IsImplicit,
false,
10194 Mapper,
false, VD, VarRef,
10196 AddTargetParamFlag =
false;
10202 bool isEffectivelyFirstprivate(
const VarDecl *VD, QualType
Type)
const {
10204 auto I = FirstPrivateDecls.find(VD);
10205 if (I != FirstPrivateDecls.end() && !I->getSecond())
10209 if (DefaultmapFirstprivateKinds.count(OMPC_DEFAULTMAP_scalar)) {
10210 if (
Type->isScalarType())
10215 if (DefaultmapFirstprivateKinds.count(OMPC_DEFAULTMAP_pointer)) {
10216 if (
Type->isAnyPointerType())
10221 if (DefaultmapFirstprivateKinds.count(OMPC_DEFAULTMAP_aggregate)) {
10222 if (
Type->isAggregateType())
10227 return DefaultmapFirstprivateKinds.count(OMPC_DEFAULTMAP_all);
10232 void generateDefaultMapInfo(
const CapturedStmt::Capture &CI,
10233 const FieldDecl &RI, llvm::Value *CV,
10234 MapCombinedInfoTy &CombinedInfo)
const {
10235 bool IsImplicit =
true;
10238 CombinedInfo.Exprs.push_back(
nullptr);
10239 CombinedInfo.BasePointers.push_back(CV);
10240 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
10241 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
10242 CombinedInfo.Pointers.push_back(CV);
10244 CombinedInfo.Sizes.push_back(
10248 CombinedInfo.Types.push_back(OpenMPOffloadMappingFlags::OMP_MAP_TO |
10249 OpenMPOffloadMappingFlags::OMP_MAP_FROM);
10253 CombinedInfo.BasePointers.push_back(CV);
10254 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
10255 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
10256 CombinedInfo.Pointers.push_back(CV);
10257 bool IsFirstprivate =
10263 CombinedInfo.Types.push_back(
10264 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL);
10265 CombinedInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
10267 }
else if (IsFirstprivate) {
10270 CombinedInfo.Types.push_back(
10271 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL);
10273 CombinedInfo.Sizes.push_back(llvm::Constant::getNullValue(CGF.
Int64Ty));
10277 CombinedInfo.Types.push_back(OpenMPOffloadMappingFlags::OMP_MAP_NONE);
10278 CombinedInfo.Sizes.push_back(llvm::Constant::getNullValue(CGF.
Int64Ty));
10280 auto I = FirstPrivateDecls.find(VD);
10281 if (I != FirstPrivateDecls.end())
10282 IsImplicit = I->getSecond();
10288 bool IsFirstprivate = isEffectivelyFirstprivate(VD, ElementType);
10290 CombinedInfo.BasePointers.push_back(CV);
10291 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
10292 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
10297 CombinedInfo.Pointers.push_back(CV);
10299 CombinedInfo.Sizes.push_back(llvm::Constant::getNullValue(CGF.
Int64Ty));
10300 CombinedInfo.Types.push_back(
10301 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL);
10303 CombinedInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
10308 CombinedInfo.Types.push_back(getMapModifiersForPrivateClauses(CI));
10309 CombinedInfo.Pointers.push_back(CV);
10311 auto I = FirstPrivateDecls.find(VD);
10312 if (I != FirstPrivateDecls.end())
10313 IsImplicit = I->getSecond();
10316 CombinedInfo.Types.back() |=
10317 OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM;
10321 CombinedInfo.Types.back() |= OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT;
10324 CombinedInfo.Mappers.push_back(
nullptr);
10336 dyn_cast<MemberExpr>(OASE->getBase()->IgnoreParenImpCasts()))
10337 return ME->getMemberDecl();
10343static llvm::Constant *
10345 MappableExprsHandler::MappingExprInfo &MapExprs) {
10348 if (!MapExprs.getMapDecl() && !MapExprs.getMapExpr())
10349 return OMPBuilder.getOrCreateDefaultSrcLocStr(SrcLocStrSize);
10352 if (!MapExprs.getMapDecl() && MapExprs.getMapExpr()) {
10356 Loc = MapExprs.getMapExpr()->getExprLoc();
10358 Loc = MapExprs.getMapDecl()->getLocation();
10361 std::string ExprName;
10362 if (MapExprs.getMapExpr()) {
10364 llvm::raw_string_ostream OS(ExprName);
10365 MapExprs.getMapExpr()->printPretty(OS,
nullptr, P);
10367 ExprName = MapExprs.getMapDecl()->getNameAsString();
10376 return OMPBuilder.getOrCreateSrcLocStr(
FileName, ExprName, PLoc.
getLine(),
10383 CodeGenFunction &CGF, MappableExprsHandler::MapCombinedInfoTy &CombinedInfo,
10385 bool IsNonContiguous =
false,
bool ForEndCall =
false) {
10388 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
10391 InsertPointTy CodeGenIP(CGF.
Builder.GetInsertBlock(),
10392 CGF.
Builder.GetInsertPoint());
10394 auto DeviceAddrCB = [&](
unsigned int I, llvm::Value *NewDecl) {
10395 if (
const ValueDecl *DevVD = CombinedInfo.DevicePtrDecls[I]) {
10400 auto CustomMapperCB = [&](
unsigned int I) {
10401 llvm::Function *MFunc =
nullptr;
10402 if (CombinedInfo.Mappers[I]) {
10403 Info.HasMapper =
true;
10409 cantFail(OMPBuilder.emitOffloadingArraysAndArgs(
10410 AllocaIP, CodeGenIP, Info, Info.RTArgs, CombinedInfo, CustomMapperCB,
10411 IsNonContiguous, ForEndCall, DeviceAddrCB));
10415static const OMPExecutableDirective *
10417 const auto *CS = D.getInnermostCapturedStmt();
10420 const Stmt *ChildStmt =
10423 if (
const auto *NestedDir =
10424 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) {
10426 switch (D.getDirectiveKind()) {
10432 if (DKind == OMPD_teams) {
10433 Body = NestedDir->getInnermostCapturedStmt()->IgnoreContainers(
10438 if (
const auto *NND =
10439 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) {
10440 DKind = NND->getDirectiveKind();
10446 case OMPD_target_teams:
10450 case OMPD_target_parallel:
10451 case OMPD_target_simd:
10452 case OMPD_target_parallel_for:
10453 case OMPD_target_parallel_for_simd:
10455 case OMPD_target_teams_distribute:
10456 case OMPD_target_teams_distribute_simd:
10457 case OMPD_target_teams_distribute_parallel_for:
10458 case OMPD_target_teams_distribute_parallel_for_simd:
10459 case OMPD_parallel:
10461 case OMPD_parallel_for:
10462 case OMPD_parallel_master:
10463 case OMPD_parallel_sections:
10464 case OMPD_for_simd:
10465 case OMPD_parallel_for_simd:
10467 case OMPD_cancellation_point:
10469 case OMPD_threadprivate:
10470 case OMPD_allocate:
10475 case OMPD_sections:
10479 case OMPD_critical:
10480 case OMPD_taskyield:
10482 case OMPD_taskwait:
10483 case OMPD_taskgroup:
10489 case OMPD_target_data:
10490 case OMPD_target_exit_data:
10491 case OMPD_target_enter_data:
10492 case OMPD_distribute:
10493 case OMPD_distribute_simd:
10494 case OMPD_distribute_parallel_for:
10495 case OMPD_distribute_parallel_for_simd:
10496 case OMPD_teams_distribute:
10497 case OMPD_teams_distribute_simd:
10498 case OMPD_teams_distribute_parallel_for:
10499 case OMPD_teams_distribute_parallel_for_simd:
10500 case OMPD_target_update:
10501 case OMPD_declare_simd:
10502 case OMPD_declare_variant:
10503 case OMPD_begin_declare_variant:
10504 case OMPD_end_declare_variant:
10505 case OMPD_declare_target:
10506 case OMPD_end_declare_target:
10507 case OMPD_declare_reduction:
10508 case OMPD_declare_mapper:
10509 case OMPD_taskloop:
10510 case OMPD_taskloop_simd:
10511 case OMPD_master_taskloop:
10512 case OMPD_master_taskloop_simd:
10513 case OMPD_parallel_master_taskloop:
10514 case OMPD_parallel_master_taskloop_simd:
10515 case OMPD_requires:
10516 case OMPD_metadirective:
10519 llvm_unreachable(
"Unexpected directive.");
10558 if (
UDMMap.count(D) > 0)
10562 auto *MapperVarDecl =
10564 CharUnits ElementSize =
C.getTypeSizeInChars(Ty);
10565 llvm::Type *ElemTy =
CGM.getTypes().ConvertTypeForMem(Ty);
10568 MappableExprsHandler::MapCombinedInfoTy CombinedInfo;
10569 auto PrivatizeAndGenMapInfoCB =
10570 [&](llvm::OpenMPIRBuilder::InsertPointTy CodeGenIP, llvm::Value *PtrPHI,
10571 llvm::Value *BeginArg) -> llvm::OpenMPIRBuilder::MapInfosTy & {
10572 MapperCGF.
Builder.restoreIP(CodeGenIP);
10582 Scope.addPrivate(MapperVarDecl, PtrCurrent);
10583 (void)
Scope.Privatize();
10586 MappableExprsHandler MEHandler(*D, MapperCGF);
10587 MEHandler.generateAllInfoForMapper(CombinedInfo,
OMPBuilder);
10589 auto FillInfoMap = [&](MappableExprsHandler::MappingExprInfo &MapExpr) {
10592 if (
CGM.getCodeGenOpts().getDebugInfo() !=
10593 llvm::codegenoptions::NoDebugInfo) {
10594 CombinedInfo.Names.resize(CombinedInfo.Exprs.size());
10595 llvm::transform(CombinedInfo.Exprs, CombinedInfo.Names.begin(),
10599 return CombinedInfo;
10602 auto CustomMapperCB = [&](
unsigned I) {
10603 llvm::Function *MapperFunc =
nullptr;
10604 if (CombinedInfo.Mappers[I]) {
10608 assert(MapperFunc &&
"Expect a valid mapper function is available.");
10614 llvm::raw_svector_ostream Out(TyStr);
10615 CGM.getCXXABI().getMangleContext().mangleCanonicalTypeName(Ty, Out);
10616 std::string Name =
getName({
"omp_mapper", TyStr, D->
getName()});
10618 llvm::Function *NewFn = cantFail(
OMPBuilder.emitUserDefinedMapper(
10619 PrivatizeAndGenMapInfoCB, ElemTy, Name, CustomMapperCB));
10620 UDMMap.try_emplace(D, NewFn);
10627 auto I =
UDMMap.find(D);
10631 return UDMMap.lookup(D);
10644 Kind != OMPD_target_teams_loop)
10647 return llvm::ConstantInt::get(CGF.
Int64Ty, 0);
10650 if (llvm::Value *NumIterations = SizeEmitter(CGF, *LD))
10651 return NumIterations;
10652 return llvm::ConstantInt::get(CGF.
Int64Ty, 0);
10661 if (OffloadingMandatory) {
10662 CGF.
Builder.CreateUnreachable();
10664 if (RequiresOuterTask) {
10665 CapturedVars.clear();
10669 CapturedVars.end());
10670 Args.push_back(llvm::Constant::getNullValue(CGF.
Builder.getPtrTy()));
10677 llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier>
Device,
10680 llvm::Value *DeviceID;
10681 if (
Device.getPointer()) {
10683 Device.getInt() == OMPC_DEVICE_device_num) &&
10684 "Expected device_num modifier.");
10689 DeviceID = CGF.
Builder.getInt64(OMP_DEVICEID_UNDEF);
10694static std::pair<llvm::Value *, OMPDynGroupprivateFallbackType>
10696 llvm::Value *DynGP = CGF.
Builder.getInt32(0);
10697 auto DynGPFallback = OMPDynGroupprivateFallbackType::Abort;
10701 llvm::Value *DynGPVal =
10705 auto FallbackModifier = DynGPClause->getDynGroupprivateFallbackModifier();
10706 switch (FallbackModifier) {
10707 case OMPC_DYN_GROUPPRIVATE_FALLBACK_abort:
10708 DynGPFallback = OMPDynGroupprivateFallbackType::Abort;
10710 case OMPC_DYN_GROUPPRIVATE_FALLBACK_null:
10711 DynGPFallback = OMPDynGroupprivateFallbackType::Null;
10713 case OMPC_DYN_GROUPPRIVATE_FALLBACK_default_mem:
10716 DynGPFallback = OMPDynGroupprivateFallbackType::DefaultMem;
10719 llvm_unreachable(
"Unknown fallback modifier for OpenMP dyn_groupprivate");
10721 }
else if (
auto *OMPXDynCGClause =
10724 llvm::Value *DynCGMemVal = CGF.
EmitScalarExpr(OMPXDynCGClause->getSize(),
10729 return {DynGP, DynGPFallback};
10735 llvm::OpenMPIRBuilder &OMPBuilder,
10737 MappableExprsHandler::MapCombinedInfoTy &CombinedInfo) {
10739 llvm::DenseMap<llvm::Value *, llvm::Value *> LambdaPointers;
10741 auto *CV = CapturedVars.begin();
10744 CI != CE; ++CI, ++RI, ++CV) {
10745 MappableExprsHandler::MapCombinedInfoTy CurInfo;
10750 CurInfo.Exprs.push_back(
nullptr);
10751 CurInfo.BasePointers.push_back(*CV);
10752 CurInfo.DevicePtrDecls.push_back(
nullptr);
10753 CurInfo.DevicePointers.push_back(
10754 MappableExprsHandler::DeviceInfoTy::None);
10755 CurInfo.Pointers.push_back(*CV);
10756 CurInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
10759 CurInfo.Types.push_back(OpenMPOffloadMappingFlags::OMP_MAP_LITERAL |
10760 OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM |
10761 OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT);
10762 CurInfo.Mappers.push_back(
nullptr);
10767 bool HasEntryWithCVAsAttachPtr =
false;
10769 HasEntryWithCVAsAttachPtr =
10770 MEHandler.hasAttachEntryForCapturedVar(CapturedVD);
10773 MappableExprsHandler::MapDataArrayTy DeclComponentLists;
10776 StorageForImplicitlyAddedComponentLists;
10777 MEHandler.populateComponentListsForNonLambdaCaptureFromClauses(
10778 CapturedVD, DeclComponentLists,
10779 StorageForImplicitlyAddedComponentLists);
10790 bool HasEntryWithoutAttachPtr =
10791 llvm::any_of(DeclComponentLists, [&](
const auto &MapData) {
10793 Components = std::get<0>(MapData);
10794 return !MEHandler.getAttachPtrExpr(Components);
10799 if (DeclComponentLists.empty() ||
10800 (!HasEntryWithCVAsAttachPtr && !HasEntryWithoutAttachPtr))
10801 MEHandler.generateDefaultMapInfo(*CI, **RI, *CV, CurInfo);
10805 MEHandler.generateInfoForCaptureFromClauseInfo(
10806 DeclComponentLists, CI, *CV, CurInfo, OMPBuilder,
10807 CombinedInfo.BasePointers.size());
10812 MappedVarSet.insert(
nullptr);
10817 MEHandler.generateInfoForLambdaCaptures(CI->
getCapturedVar(), *CV,
10818 CurInfo, LambdaPointers);
10821 assert(!CurInfo.BasePointers.empty() &&
10822 "Non-existing map pointer for capture!");
10823 assert(CurInfo.BasePointers.size() == CurInfo.Pointers.size() &&
10824 CurInfo.BasePointers.size() == CurInfo.Sizes.size() &&
10825 CurInfo.BasePointers.size() == CurInfo.Types.size() &&
10826 CurInfo.BasePointers.size() == CurInfo.Mappers.size() &&
10827 "Inconsistent map information sizes!");
10830 CombinedInfo.append(CurInfo);
10833 MEHandler.adjustMemberOfForLambdaCaptures(
10834 OMPBuilder, LambdaPointers, CombinedInfo.BasePointers,
10835 CombinedInfo.Pointers, CombinedInfo.Types);
10839 MappableExprsHandler::MapCombinedInfoTy &CombinedInfo,
10840 llvm::OpenMPIRBuilder &OMPBuilder,
10847 MEHandler.generateAllInfo(CombinedInfo, OMPBuilder, SkippedVarSet);
10849 auto FillInfoMap = [&](MappableExprsHandler::MappingExprInfo &MapExpr) {
10853 llvm::codegenoptions::NoDebugInfo) {
10854 CombinedInfo.Names.resize(CombinedInfo.Exprs.size());
10855 llvm::transform(CombinedInfo.Exprs, CombinedInfo.Names.begin(),
10863 llvm::OpenMPIRBuilder &OMPBuilder,
10864 MappableExprsHandler::MapCombinedInfoTy &CombinedInfo) {
10866 MappableExprsHandler MEHandler(D, CGF);
10867 llvm::DenseSet<CanonicalDeclPtr<const Decl>> MappedVarSet;
10870 MappedVarSet, CombinedInfo);
10871 genMapInfo(MEHandler, CGF, CombinedInfo, OMPBuilder, MappedVarSet);
10874template <
typename ClauseTy>
10879 const auto *
C = D.getSingleClause<ClauseTy>();
10880 assert(!
C->varlist_empty() &&
10881 "ompx_bare requires explicit num_teams and thread_limit");
10883 for (
auto *E :
C->varlist()) {
10895 llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier>
Device,
10897 llvm::Value *&MapTypesArray, llvm::Value *&MapNamesArray,
10902 llvm::OpenMPIRBuilder &OMPBuilder = OMPRuntime->
getOMPBuilder();
10905 MappableExprsHandler::MapCombinedInfoTy CombinedInfo;
10907 genMapInfo(D, CGF, CS, CapturedVars, OMPBuilder, CombinedInfo);
10910 using OpenMPOffloadMappingFlags = llvm::omp::OpenMPOffloadMappingFlags;
10911 auto *NullPtr = llvm::Constant::getNullValue(CGF.
Builder.getPtrTy());
10912 CombinedInfo.BasePointers.push_back(NullPtr);
10913 CombinedInfo.Pointers.push_back(NullPtr);
10914 CombinedInfo.DevicePointers.push_back(
10915 llvm::OpenMPIRBuilder::DeviceInfoTy::None);
10916 CombinedInfo.Sizes.push_back(CGF.
Builder.getInt64(0));
10917 CombinedInfo.Types.push_back(OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM |
10918 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL);
10919 if (!CombinedInfo.Names.empty())
10920 CombinedInfo.Names.push_back(NullPtr);
10921 CombinedInfo.Exprs.push_back(
nullptr);
10922 CombinedInfo.Mappers.push_back(
nullptr);
10923 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
10937 MapTypesArray = Info.RTArgs.MapTypesArray;
10938 MapNamesArray = Info.RTArgs.MapNamesArray;
10940 auto &&ThenGen = [&OMPRuntime, OutlinedFn, &D, &CapturedVars,
10941 RequiresOuterTask, &CS, OffloadingMandatory,
Device,
10942 OutlinedFnID, &InputInfo, &MapTypesArray, &MapNamesArray,
10944 bool IsReverseOffloading =
Device.getInt() == OMPC_DEVICE_ancestor;
10946 if (IsReverseOffloading) {
10952 RequiresOuterTask, CS, OffloadingMandatory, CGF);
10956 bool HasNoWait = D.hasClausesOfKind<OMPNowaitClause>();
10957 unsigned NumTargetItems = InputInfo.NumberOfTargetItems;
10959 llvm::Value *BasePointersArray =
10960 InputInfo.BasePointersArray.emitRawPointer(CGF);
10961 llvm::Value *PointersArray = InputInfo.PointersArray.emitRawPointer(CGF);
10962 llvm::Value *SizesArray = InputInfo.SizesArray.emitRawPointer(CGF);
10963 llvm::Value *MappersArray = InputInfo.MappersArray.emitRawPointer(CGF);
10965 auto &&EmitTargetCallFallbackCB =
10966 [&OMPRuntime, OutlinedFn, &D, &CapturedVars, RequiresOuterTask, &CS,
10967 OffloadingMandatory, &CGF](llvm::OpenMPIRBuilder::InsertPointTy IP)
10968 -> llvm::OpenMPIRBuilder::InsertPointTy {
10971 RequiresOuterTask, CS, OffloadingMandatory, CGF);
10984 NumThreads.push_back(
10990 llvm::Value *NumIterations =
10993 llvm::OpenMPIRBuilder::InsertPointTy AllocaIP(
10996 llvm::OpenMPIRBuilder::TargetDataRTArgs RTArgs(
10997 BasePointersArray, PointersArray, SizesArray, MapTypesArray,
10998 nullptr , MappersArray, MapNamesArray);
11000 llvm::OpenMPIRBuilder::TargetKernelArgs Args(
11001 NumTargetItems, RTArgs, NumIterations, NumTeams, NumThreads,
11002 DynCGroupMem, HasNoWait, IsBare,
11003 DynCGroupMemFallback);
11005 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
11007 CGF.
Builder, OutlinedFnID, EmitTargetCallFallbackCB, Args, DeviceID,
11009 CGF.
Builder.restoreIP(AfterIP);
11012 if (RequiresOuterTask)
11027 [&OMPRuntime, OutlinedFn, &D, &CapturedVars, RequiresOuterTask, &CS,
11030 RequiresOuterTask, CS, OffloadingMandatory, CGF);
11033 if (RequiresOuterTask) {
11043 llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID,
const Expr *IfCond,
11044 llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier>
Device,
11051 const bool OffloadingMandatory = !
CGM.getLangOpts().OpenMPIsTargetDevice &&
11052 CGM.getLangOpts().OpenMPOffloadMandatory;
11054 assert((OffloadingMandatory || OutlinedFn) &&
"Invalid outlined function!");
11056 const bool RequiresOuterTask =
11058 D.hasClausesOfKind<OMPNowaitClause>() ||
11059 D.hasClausesOfKind<OMPInReductionClause>() ||
11060 (
CGM.getLangOpts().OpenMP >= 51 &&
11064 const CapturedStmt &CS = *D.getCapturedStmt(OMPD_target);
11072 llvm::Value *MapTypesArray =
nullptr;
11073 llvm::Value *MapNamesArray =
nullptr;
11075 auto &&TargetThenGen = [
this, OutlinedFn, &D, &CapturedVars,
11076 RequiresOuterTask, &CS, OffloadingMandatory,
Device,
11077 OutlinedFnID, &InputInfo, &MapTypesArray,
11081 RequiresOuterTask, CS, OffloadingMandatory,
11082 Device, OutlinedFnID, InputInfo, MapTypesArray,
11083 MapNamesArray, SizeEmitter, CGF,
CGM);
11086 auto &&TargetElseGen =
11087 [
this, OutlinedFn, &D, &CapturedVars, RequiresOuterTask, &CS,
11090 CS, OffloadingMandatory, CGF);
11097 if (OutlinedFnID) {
11099 emitIfClause(CGF, IfCond, TargetThenGen, TargetElseGen);
11111 StringRef ParentName) {
11118 if (
auto *E = dyn_cast<OMPExecutableDirective>(S);
11127 bool RequiresDeviceCodegen =
11132 if (RequiresDeviceCodegen) {
11140 if (!
OMPBuilder.OffloadInfoManager.hasTargetRegionEntryInfo(EntryInfo))
11143 switch (E.getDirectiveKind()) {
11148 case OMPD_target_parallel:
11152 case OMPD_target_teams:
11156 case OMPD_target_teams_distribute:
11160 case OMPD_target_teams_distribute_simd:
11164 case OMPD_target_parallel_for:
11168 case OMPD_target_parallel_for_simd:
11172 case OMPD_target_simd:
11176 case OMPD_target_teams_distribute_parallel_for:
11181 case OMPD_target_teams_distribute_parallel_for_simd:
11187 case OMPD_target_teams_loop:
11191 case OMPD_target_parallel_loop:
11195 case OMPD_parallel:
11197 case OMPD_parallel_for:
11198 case OMPD_parallel_master:
11199 case OMPD_parallel_sections:
11200 case OMPD_for_simd:
11201 case OMPD_parallel_for_simd:
11203 case OMPD_cancellation_point:
11205 case OMPD_threadprivate:
11206 case OMPD_allocate:
11211 case OMPD_sections:
11215 case OMPD_critical:
11216 case OMPD_taskyield:
11218 case OMPD_taskwait:
11219 case OMPD_taskgroup:
11225 case OMPD_target_data:
11226 case OMPD_target_exit_data:
11227 case OMPD_target_enter_data:
11228 case OMPD_distribute:
11229 case OMPD_distribute_simd:
11230 case OMPD_distribute_parallel_for:
11231 case OMPD_distribute_parallel_for_simd:
11232 case OMPD_teams_distribute:
11233 case OMPD_teams_distribute_simd:
11234 case OMPD_teams_distribute_parallel_for:
11235 case OMPD_teams_distribute_parallel_for_simd:
11236 case OMPD_target_update:
11237 case OMPD_declare_simd:
11238 case OMPD_declare_variant:
11239 case OMPD_begin_declare_variant:
11240 case OMPD_end_declare_variant:
11241 case OMPD_declare_target:
11242 case OMPD_end_declare_target:
11243 case OMPD_declare_reduction:
11244 case OMPD_declare_mapper:
11245 case OMPD_taskloop:
11246 case OMPD_taskloop_simd:
11247 case OMPD_master_taskloop:
11248 case OMPD_master_taskloop_simd:
11249 case OMPD_parallel_master_taskloop:
11250 case OMPD_parallel_master_taskloop_simd:
11251 case OMPD_requires:
11252 case OMPD_metadirective:
11255 llvm_unreachable(
"Unknown target directive for OpenMP device codegen.");
11260 if (
const auto *E = dyn_cast<OMPExecutableDirective>(S)) {
11261 if (!E->hasAssociatedStmt() || !E->getAssociatedStmt())
11269 if (
const auto *L = dyn_cast<LambdaExpr>(S))
11278 std::optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
11279 OMPDeclareTargetDeclAttr::getDeviceType(VD);
11283 if (!IsDevice && DevTy == OMPDeclareTargetDeclAttr::DT_NoHost)
11286 if (IsDevice && DevTy == OMPDeclareTargetDeclAttr::DT_Host)
11294 if (!
CGM.getLangOpts().OpenMPIsTargetDevice) {
11295 if (
const auto *FD = dyn_cast<FunctionDecl>(GD.
getDecl()))
11297 CGM.getLangOpts().OpenMPIsTargetDevice))
11304 if (
const auto *FD = dyn_cast<FunctionDecl>(VD)) {
11305 StringRef Name =
CGM.getMangledName(GD);
11308 CGM.getLangOpts().OpenMPIsTargetDevice))
11313 return !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD) &&
11319 CGM.getLangOpts().OpenMPIsTargetDevice))
11322 if (!
CGM.getLangOpts().OpenMPIsTargetDevice)
11331 StringRef ParentName =
11336 StringRef ParentName =
11343 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
11344 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(
11346 if (!Res || *Res == OMPDeclareTargetDeclAttr::MT_Link ||
11347 ((*Res == OMPDeclareTargetDeclAttr::MT_To ||
11348 *Res == OMPDeclareTargetDeclAttr::MT_Enter) &&
11357 llvm::Constant *
Addr) {
11358 if (
CGM.getLangOpts().OMPTargetTriples.empty() &&
11359 !
CGM.getLangOpts().OpenMPIsTargetDevice)
11362 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
11363 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
11367 if (Res && *Res != OMPDeclareTargetDeclAttr::MT_Link &&
11373 if (Res && *Res == OMPDeclareTargetDeclAttr::MT_Local)
11377 if (
CGM.getLangOpts().OpenMPIsTargetDevice) {
11380 StringRef VarName =
CGM.getMangledName(VD);
11386 auto AddrOfGlobal = [&VD,
this]() {
return CGM.GetAddrOfGlobal(VD); };
11387 auto LinkageForVariable = [&VD,
this]() {
11388 return CGM.getLLVMLinkageVarDefinition(VD);
11391 std::vector<llvm::GlobalVariable *> GeneratedRefs;
11398 CGM.getMangledName(VD), GeneratedRefs,
CGM.getLangOpts().OpenMPSimd,
11399 CGM.getLangOpts().OMPTargetTriples, AddrOfGlobal, LinkageForVariable,
11400 CGM.getTypes().ConvertTypeForMem(
11401 CGM.getContext().getPointerType(VD->
getType())),
11404 for (
auto *ref : GeneratedRefs)
11405 CGM.addCompilerUsedGlobal(ref);
11418 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
11419 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
11423 if (*Res == OMPDeclareTargetDeclAttr::MT_Local ||
11424 ((*Res == OMPDeclareTargetDeclAttr::MT_To ||
11425 *Res == OMPDeclareTargetDeclAttr::MT_Enter) &&
11427 CGM.EmitGlobal(VD);
11429 assert((*Res == OMPDeclareTargetDeclAttr::MT_Link ||
11430 ((*Res == OMPDeclareTargetDeclAttr::MT_To ||
11431 *Res == OMPDeclareTargetDeclAttr::MT_Enter ||
11432 *Res == OMPDeclareTargetDeclAttr::MT_Local) &&
11434 "Expected link clause or to clause with unified memory.");
11435 (void)
CGM.getOpenMPRuntime().getAddrOfDeclareTargetVar(VD);
11443 " Expected target-based directive.");
11448 if (Clause->getClauseKind() == OMPC_unified_shared_memory) {
11450 OMPBuilder.Config.setHasRequiresUnifiedSharedMemory(
true);
11451 }
else if (
const auto *AC =
11452 dyn_cast<OMPAtomicDefaultMemOrderClause>(Clause)) {
11453 switch (AC->getAtomicDefaultMemOrderKind()) {
11454 case OMPC_ATOMIC_DEFAULT_MEM_ORDER_acq_rel:
11457 case OMPC_ATOMIC_DEFAULT_MEM_ORDER_seq_cst:
11460 case OMPC_ATOMIC_DEFAULT_MEM_ORDER_relaxed:
11476 if (!VD || !VD->
hasAttr<OMPAllocateDeclAttr>())
11478 const auto *A = VD->
getAttr<OMPAllocateDeclAttr>();
11479 switch(A->getAllocatorType()) {
11480 case OMPAllocateDeclAttr::OMPNullMemAlloc:
11481 case OMPAllocateDeclAttr::OMPDefaultMemAlloc:
11483 case OMPAllocateDeclAttr::OMPLargeCapMemAlloc:
11484 case OMPAllocateDeclAttr::OMPCGroupMemAlloc:
11485 case OMPAllocateDeclAttr::OMPHighBWMemAlloc:
11486 case OMPAllocateDeclAttr::OMPLowLatMemAlloc:
11487 case OMPAllocateDeclAttr::OMPThreadMemAlloc:
11488 case OMPAllocateDeclAttr::OMPConstMemAlloc:
11489 case OMPAllocateDeclAttr::OMPPTeamMemAlloc:
11492 case OMPAllocateDeclAttr::OMPUserDefinedMemAlloc:
11493 llvm_unreachable(
"Expected predefined allocator for the variables with the "
11494 "static storage.");
11506 if (CGM.getLangOpts().OpenMPIsTargetDevice) {
11507 SavedShouldMarkAsGlobal = CGM.getOpenMPRuntime().ShouldMarkAsGlobal;
11508 CGM.getOpenMPRuntime().ShouldMarkAsGlobal = false;
11513 if (CGM.getLangOpts().OpenMPIsTargetDevice)
11514 CGM.getOpenMPRuntime().ShouldMarkAsGlobal = SavedShouldMarkAsGlobal;
11524 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(D)) {
11526 if (
auto *F = dyn_cast_or_null<llvm::Function>(
11527 CGM.GetGlobalValue(
CGM.getMangledName(GD))))
11528 return !F->isDeclaration();
11540 llvm::Function *OutlinedFn,
11549 llvm::Value *Args[] = {
11551 CGF.
Builder.getInt32(CapturedVars.size()),
11554 RealArgs.append(std::begin(Args), std::end(Args));
11555 RealArgs.append(CapturedVars.begin(), CapturedVars.end());
11557 llvm::FunctionCallee RTLFn =
OMPBuilder.getOrCreateRuntimeFunction(
11558 CGM.getModule(), OMPRTL___kmpc_fork_teams);
11563 const Expr *NumTeams,
11564 const Expr *ThreadLimit,
11571 llvm::Value *NumTeamsVal =
11577 llvm::Value *ThreadLimitVal =
11584 llvm::Value *PushNumTeamsArgs[] = {RTLoc,
getThreadID(CGF, Loc), NumTeamsVal,
11587 CGM.getModule(), OMPRTL___kmpc_push_num_teams),
11592 const Expr *ThreadLimit,
11595 llvm::Value *ThreadLimitVal =
11602 llvm::Value *ThreadLimitArgs[] = {RTLoc,
getThreadID(CGF, Loc),
11605 CGM.getModule(), OMPRTL___kmpc_set_thread_limit),
11620 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
11622 llvm::Value *IfCondVal =
nullptr;
11627 llvm::Value *DeviceID =
nullptr;
11632 DeviceID = CGF.
Builder.getInt64(OMP_DEVICEID_UNDEF);
11636 MappableExprsHandler::MapCombinedInfoTy CombinedInfo;
11637 auto GenMapInfoCB =
11638 [&](InsertPointTy CodeGenIP) -> llvm::OpenMPIRBuilder::MapInfosTy & {
11639 CGF.
Builder.restoreIP(CodeGenIP);
11641 MappableExprsHandler MEHandler(D, CGF);
11642 MEHandler.generateAllInfo(CombinedInfo,
OMPBuilder);
11644 auto FillInfoMap = [&](MappableExprsHandler::MappingExprInfo &MapExpr) {
11647 if (
CGM.getCodeGenOpts().getDebugInfo() !=
11648 llvm::codegenoptions::NoDebugInfo) {
11649 CombinedInfo.Names.resize(CombinedInfo.Exprs.size());
11650 llvm::transform(CombinedInfo.Exprs, CombinedInfo.Names.begin(),
11654 return CombinedInfo;
11656 using BodyGenTy = llvm::OpenMPIRBuilder::BodyGenTy;
11657 auto BodyCB = [&](InsertPointTy CodeGenIP, BodyGenTy BodyGenType) {
11658 CGF.
Builder.restoreIP(CodeGenIP);
11659 switch (BodyGenType) {
11660 case BodyGenTy::Priv:
11664 case BodyGenTy::DupNoPriv:
11666 CodeGen.setAction(NoPrivAction);
11670 case BodyGenTy::NoPriv:
11672 CodeGen.setAction(NoPrivAction);
11677 return InsertPointTy(CGF.
Builder.GetInsertBlock(),
11678 CGF.
Builder.GetInsertPoint());
11681 auto DeviceAddrCB = [&](
unsigned int I, llvm::Value *NewDecl) {
11682 if (
const ValueDecl *DevVD = CombinedInfo.DevicePtrDecls[I]) {
11687 auto CustomMapperCB = [&](
unsigned int I) {
11688 llvm::Function *MFunc =
nullptr;
11689 if (CombinedInfo.Mappers[I]) {
11690 Info.HasMapper =
true;
11702 InsertPointTy CodeGenIP(CGF.
Builder.GetInsertBlock(),
11703 CGF.
Builder.GetInsertPoint());
11704 llvm::OpenMPIRBuilder::LocationDescription OmpLoc(CodeGenIP);
11705 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
11707 OmpLoc, AllocaIP, CodeGenIP, {}, DeviceID,
11708 IfCondVal, Info, GenMapInfoCB, CustomMapperCB,
11709 nullptr, BodyCB, DeviceAddrCB, RTLoc));
11710 CGF.
Builder.restoreIP(AfterIP);
11722 "Expecting either target enter, exit data, or update directives.");
11725 llvm::Value *MapTypesArray =
nullptr;
11726 llvm::Value *MapNamesArray =
nullptr;
11728 auto &&ThenGen = [
this, &D,
Device, &InputInfo, &MapTypesArray,
11731 llvm::Value *DeviceID =
nullptr;
11736 DeviceID = CGF.
Builder.getInt64(OMP_DEVICEID_UNDEF);
11740 llvm::Constant *PointerNum =
11747 {RTLoc, DeviceID, PointerNum,
11755 const bool HasNowait = D.hasClausesOfKind<OMPNowaitClause>();
11756 RuntimeFunction RTLFn;
11757 switch (D.getDirectiveKind()) {
11758 case OMPD_target_enter_data:
11759 RTLFn = HasNowait ? OMPRTL___tgt_target_data_begin_nowait_mapper
11760 : OMPRTL___tgt_target_data_begin_mapper;
11762 case OMPD_target_exit_data:
11763 RTLFn = HasNowait ? OMPRTL___tgt_target_data_end_nowait_mapper
11764 : OMPRTL___tgt_target_data_end_mapper;
11766 case OMPD_target_update:
11767 RTLFn = HasNowait ? OMPRTL___tgt_target_data_update_nowait_mapper
11768 : OMPRTL___tgt_target_data_update_mapper;
11770 case OMPD_parallel:
11772 case OMPD_parallel_for:
11773 case OMPD_parallel_master:
11774 case OMPD_parallel_sections:
11775 case OMPD_for_simd:
11776 case OMPD_parallel_for_simd:
11778 case OMPD_cancellation_point:
11780 case OMPD_threadprivate:
11781 case OMPD_allocate:
11786 case OMPD_sections:
11790 case OMPD_critical:
11791 case OMPD_taskyield:
11793 case OMPD_taskwait:
11794 case OMPD_taskgroup:
11800 case OMPD_target_data:
11801 case OMPD_distribute:
11802 case OMPD_distribute_simd:
11803 case OMPD_distribute_parallel_for:
11804 case OMPD_distribute_parallel_for_simd:
11805 case OMPD_teams_distribute:
11806 case OMPD_teams_distribute_simd:
11807 case OMPD_teams_distribute_parallel_for:
11808 case OMPD_teams_distribute_parallel_for_simd:
11809 case OMPD_declare_simd:
11810 case OMPD_declare_variant:
11811 case OMPD_begin_declare_variant:
11812 case OMPD_end_declare_variant:
11813 case OMPD_declare_target:
11814 case OMPD_end_declare_target:
11815 case OMPD_declare_reduction:
11816 case OMPD_declare_mapper:
11817 case OMPD_taskloop:
11818 case OMPD_taskloop_simd:
11819 case OMPD_master_taskloop:
11820 case OMPD_master_taskloop_simd:
11821 case OMPD_parallel_master_taskloop:
11822 case OMPD_parallel_master_taskloop_simd:
11824 case OMPD_target_simd:
11825 case OMPD_target_teams_distribute:
11826 case OMPD_target_teams_distribute_simd:
11827 case OMPD_target_teams_distribute_parallel_for:
11828 case OMPD_target_teams_distribute_parallel_for_simd:
11829 case OMPD_target_teams:
11830 case OMPD_target_parallel:
11831 case OMPD_target_parallel_for:
11832 case OMPD_target_parallel_for_simd:
11833 case OMPD_requires:
11834 case OMPD_metadirective:
11837 llvm_unreachable(
"Unexpected standalone target data directive.");
11841 OffloadingArgs.push_back(llvm::Constant::getNullValue(CGF.
Int32Ty));
11842 OffloadingArgs.push_back(llvm::Constant::getNullValue(CGF.
VoidPtrTy));
11843 OffloadingArgs.push_back(llvm::Constant::getNullValue(CGF.
Int32Ty));
11844 OffloadingArgs.push_back(llvm::Constant::getNullValue(CGF.
VoidPtrTy));
11847 OMPBuilder.getOrCreateRuntimeFunction(
CGM.getModule(), RTLFn),
11851 auto &&TargetThenGen = [
this, &ThenGen, &D, &InputInfo, &MapTypesArray,
11855 MappableExprsHandler::MapCombinedInfoTy CombinedInfo;
11857 MappableExprsHandler MEHandler(D, CGF);
11863 D.hasClausesOfKind<OMPNowaitClause>();
11869 CGM.getPointerAlign());
11874 MapTypesArray = Info.RTArgs.MapTypesArray;
11875 MapNamesArray = Info.RTArgs.MapNamesArray;
11876 if (RequiresOuterTask)
11921 unsigned Offset = 0;
11922 if (
const auto *MD = dyn_cast<CXXMethodDecl>(FD)) {
11923 if (ParamAttrs[Offset].Kind ==
11924 llvm::OpenMPIRBuilder::DeclareSimdKindTy::Vector)
11925 CDT =
C.getPointerType(
C.getCanonicalTagType(MD->
getParent()));
11929 for (
unsigned I = 0, E = FD->
getNumParams(); I < E; ++I) {
11930 if (ParamAttrs[I + Offset].Kind ==
11931 llvm::OpenMPIRBuilder::DeclareSimdKindTy::Vector) {
11943 return C.getTypeSize(CDT);
11954 llvm::OpenMPIRBuilder::DeclareSimdKindTy Kind) {
11960 if (Kind == llvm::OpenMPIRBuilder::DeclareSimdKindTy::Uniform)
11963 if (Kind == llvm::OpenMPIRBuilder::DeclareSimdKindTy::LinearUVal ||
11964 Kind == llvm::OpenMPIRBuilder::DeclareSimdKindTy::LinearRef)
11967 if ((Kind == llvm::OpenMPIRBuilder::DeclareSimdKindTy::Linear ||
11968 Kind == llvm::OpenMPIRBuilder::DeclareSimdKindTy::LinearVal) &&
11978 unsigned Size =
C.getTypeSize(QT);
11981 if (Size != 8 && Size != 16 && Size != 32 && Size != 64 && Size != 128)
12002 llvm::OpenMPIRBuilder::DeclareSimdKindTy Kind,
12007 return C.getTypeSize(PTy);
12010 return C.getTypeSize(QT);
12012 return C.getTypeSize(
C.getUIntPtrType());
12018static std::tuple<unsigned, unsigned, bool>
12025 bool OutputBecomesInput =
false;
12030 RetType, llvm::OpenMPIRBuilder::DeclareSimdKindTy::Vector,
C));
12032 OutputBecomesInput =
true;
12034 for (
unsigned I = 0, E = FD->
getNumParams(); I < E; ++I) {
12039 assert(!Sizes.empty() &&
"Unable to determine NDS and WDS.");
12042 assert(llvm::all_of(Sizes,
12043 [](
unsigned Size) {
12044 return Size == 8 || Size == 16 || Size == 32 ||
12045 Size == 64 || Size == 128;
12049 return std::make_tuple(*llvm::min_element(Sizes), *llvm::max_element(Sizes),
12050 OutputBecomesInput);
12053static llvm::OpenMPIRBuilder::DeclareSimdBranch
12056 case OMPDeclareSimdDeclAttr::BS_Undefined:
12057 return llvm::OpenMPIRBuilder::DeclareSimdBranch::Undefined;
12058 case OMPDeclareSimdDeclAttr::BS_Inbranch:
12059 return llvm::OpenMPIRBuilder::DeclareSimdBranch::Inbranch;
12060 case OMPDeclareSimdDeclAttr::BS_Notinbranch:
12061 return llvm::OpenMPIRBuilder::DeclareSimdBranch::Notinbranch;
12063 llvm_unreachable(
"unexpected declare simd branch state");
12068 unsigned UserVLEN,
unsigned WDS,
char ISA) {
12070 if (UserVLEN == 1) {
12077 if (ISA ==
'n' && UserVLEN && !llvm::isPowerOf2_32(UserVLEN)) {
12083 if (ISA ==
's' && UserVLEN != 0 &&
12084 ((UserVLEN * WDS > 2048) || (UserVLEN * WDS % 128 != 0))) {
12093 llvm::Function *Fn) {
12098 llvm::DenseMap<const Decl *, unsigned> ParamPositions;
12100 ParamPositions.try_emplace(FD, 0);
12101 unsigned ParamPos = ParamPositions.size();
12103 ParamPositions.try_emplace(P->getCanonicalDecl(), ParamPos);
12108 ParamPositions.size());
12110 for (
const Expr *E :
Attr->uniforms()) {
12114 Pos = ParamPositions[FD];
12117 ->getCanonicalDecl();
12118 auto It = ParamPositions.find(PVD);
12119 assert(It != ParamPositions.end() &&
"Function parameter not found");
12122 ParamAttrs[Pos].Kind =
12123 llvm::OpenMPIRBuilder::DeclareSimdKindTy::Uniform;
12126 auto *NI =
Attr->alignments_begin();
12127 for (
const Expr *E :
Attr->aligneds()) {
12132 Pos = ParamPositions[FD];
12136 ->getCanonicalDecl();
12137 auto It = ParamPositions.find(PVD);
12138 assert(It != ParamPositions.end() &&
"Function parameter not found");
12140 ParmTy = PVD->getType();
12142 ParamAttrs[Pos].Alignment =
12144 ? (*NI)->EvaluateKnownConstInt(
C)
12145 : llvm::APSInt::getUnsigned(
12146 C.toCharUnitsFromBits(
C.getOpenMPDefaultSimdAlign(ParmTy))
12151 auto *SI =
Attr->steps_begin();
12152 auto *MI =
Attr->modifiers_begin();
12153 for (
const Expr *E :
Attr->linears()) {
12156 bool IsReferenceType =
false;
12159 unsigned PtrRescalingFactor = 1;
12161 Pos = ParamPositions[FD];
12163 PtrRescalingFactor =
CGM.getContext()
12164 .getTypeSizeInChars(P->getPointeeType())
12168 ->getCanonicalDecl();
12169 auto It = ParamPositions.find(PVD);
12170 assert(It != ParamPositions.end() &&
"Function parameter not found");
12172 if (
auto *P = dyn_cast<PointerType>(PVD->getType()))
12173 PtrRescalingFactor =
CGM.getContext()
12174 .getTypeSizeInChars(P->getPointeeType())
12176 else if (PVD->getType()->isReferenceType()) {
12177 IsReferenceType =
true;
12178 PtrRescalingFactor =
12180 .getTypeSizeInChars(PVD->getType().getNonReferenceType())
12184 llvm::OpenMPIRBuilder::DeclareSimdAttrTy &ParamAttr = ParamAttrs[Pos];
12185 if (*MI == OMPC_LINEAR_ref)
12186 ParamAttr.Kind = llvm::OpenMPIRBuilder::DeclareSimdKindTy::LinearRef;
12187 else if (*MI == OMPC_LINEAR_uval)
12188 ParamAttr.Kind = llvm::OpenMPIRBuilder::DeclareSimdKindTy::LinearUVal;
12189 else if (IsReferenceType)
12190 ParamAttr.Kind = llvm::OpenMPIRBuilder::DeclareSimdKindTy::LinearVal;
12192 ParamAttr.Kind = llvm::OpenMPIRBuilder::DeclareSimdKindTy::Linear;
12194 ParamAttr.StrideOrArg = llvm::APSInt::getUnsigned(1);
12198 if (
const auto *DRE =
12200 if (
const auto *StridePVD =
12201 dyn_cast<ParmVarDecl>(DRE->getDecl())) {
12202 ParamAttr.HasVarStride =
true;
12203 auto It = ParamPositions.find(StridePVD->getCanonicalDecl());
12204 assert(It != ParamPositions.end() &&
12205 "Function parameter not found");
12206 ParamAttr.StrideOrArg = llvm::APSInt::getUnsigned(It->second);
12210 ParamAttr.StrideOrArg =
Result.Val.getInt();
12216 if (!ParamAttr.HasVarStride &&
12218 llvm::OpenMPIRBuilder::DeclareSimdKindTy::Linear ||
12220 llvm::OpenMPIRBuilder::DeclareSimdKindTy::LinearRef))
12221 ParamAttr.StrideOrArg = ParamAttr.StrideOrArg * PtrRescalingFactor;
12225 llvm::APSInt VLENVal;
12227 const Expr *VLENExpr =
Attr->getSimdlen();
12232 llvm::OpenMPIRBuilder::DeclareSimdBranch State =
12234 if (
CGM.getTriple().isX86()) {
12236 assert(NumElts &&
"Non-zero simdlen/cdtsize expected");
12237 OMPBuilder.emitX86DeclareSimdFunction(Fn, NumElts, VLENVal, ParamAttrs,
12239 }
else if (
CGM.getTriple().getArch() == llvm::Triple::aarch64) {
12240 unsigned VLEN = VLENVal.getExtValue();
12243 const unsigned NDS = std::get<0>(
Data);
12244 const unsigned WDS = std::get<1>(
Data);
12245 const bool OutputBecomesInput = std::get<2>(
Data);
12246 if (
CGM.getTarget().hasFeature(
"sve")) {
12249 Fn, VLEN, ParamAttrs, State,
's', NDS, OutputBecomesInput);
12250 }
else if (
CGM.getTarget().hasFeature(
"neon")) {
12253 Fn, VLEN, ParamAttrs, State,
'n', NDS, OutputBecomesInput);
12263class DoacrossCleanupTy final :
public EHScopeStack::Cleanup {
12265 static const int DoacrossFinArgs = 2;
12268 llvm::FunctionCallee RTLFn;
12269 llvm::Value *Args[DoacrossFinArgs];
12272 DoacrossCleanupTy(llvm::FunctionCallee RTLFn,
12275 assert(CallArgs.size() == DoacrossFinArgs);
12276 std::copy(CallArgs.begin(), CallArgs.end(), std::begin(Args));
12293 QualType Int64Ty =
C.getIntTypeForBitwidth(64,
true);
12301 RD =
C.buildImplicitRecord(
"kmp_dim");
12309 RD =
KmpDimTy->castAsRecordDecl();
12311 llvm::APInt Size(32, NumIterations.size());
12317 enum { LowerFD = 0, UpperFD, StrideFD };
12319 for (
unsigned I = 0, E = NumIterations.size(); I < E; ++I) {
12324 DimsLVal, *std::next(RD->
field_begin(), UpperFD));
12326 CGF.
EmitScalarExpr(NumIterations[I]), NumIterations[I]->getType(),
12327 Int64Ty, NumIterations[I]->getExprLoc());
12331 DimsLVal, *std::next(RD->
field_begin(), StrideFD));
12338 llvm::Value *Args[] = {
12341 llvm::ConstantInt::getSigned(
CGM.Int32Ty, NumIterations.size()),
12346 llvm::FunctionCallee RTLFn =
OMPBuilder.getOrCreateRuntimeFunction(
12347 CGM.getModule(), OMPRTL___kmpc_doacross_init);
12349 llvm::Value *FiniArgs[DoacrossCleanupTy::DoacrossFinArgs] = {
12351 llvm::FunctionCallee FiniRTLFn =
OMPBuilder.getOrCreateRuntimeFunction(
12352 CGM.getModule(), OMPRTL___kmpc_doacross_fini);
12357template <
typename T>
12359 const T *
C, llvm::Value *ULoc,
12360 llvm::Value *ThreadID) {
12363 llvm::APInt Size(32,
C->getNumLoops());
12367 for (
unsigned I = 0, E =
C->getNumLoops(); I < E; ++I) {
12368 const Expr *CounterVal =
C->getLoopData(I);
12369 assert(CounterVal);
12376 llvm::Value *Args[] = {
12379 llvm::FunctionCallee RTLFn;
12381 OMPDoacrossKind<T> ODK;
12382 if (ODK.isSource(
C)) {
12384 OMPRTL___kmpc_doacross_post);
12386 assert(ODK.isSink(
C) &&
"Expect sink modifier.");
12388 OMPRTL___kmpc_doacross_wait);
12408 llvm::FunctionCallee Callee,
12410 assert(Loc.
isValid() &&
"Outlined function call location must be valid.");
12413 if (
auto *Fn = dyn_cast<llvm::Function>(Callee.getCallee())) {
12414 if (Fn->doesNotThrow()) {
12425 emitCall(CGF, Loc, OutlinedFn, Args);
12429 if (
const auto *FD = dyn_cast<FunctionDecl>(D))
12430 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(FD))
12436 const VarDecl *TargetParam)
const {
12443 const Expr *Allocator) {
12444 llvm::Value *AllocVal;
12454 AllocVal = llvm::Constant::getNullValue(
12464 if (!AllocateAlignment)
12467 return llvm::ConstantInt::get(
CGM.
SizeTy, AllocateAlignment->getQuantity());
12480 auto I = UntiedData.find(VD);
12481 if (I != UntiedData.end()) {
12482 UntiedAddr = I->second.first;
12483 UntiedRealAddr = I->second.second;
12487 if (CVD->
hasAttr<OMPAllocateDeclAttr>()) {
12496 Size = CGF.
Builder.CreateNUWAdd(
12498 Size = CGF.
Builder.CreateUDiv(Size,
CGM.getSize(Align));
12499 Size = CGF.
Builder.CreateNUWMul(Size,
CGM.getSize(Align));
12505 const auto *AA = CVD->
getAttr<OMPAllocateDeclAttr>();
12506 const Expr *Allocator = AA->getAllocator();
12510 Args.push_back(ThreadID);
12512 Args.push_back(Alignment);
12513 Args.push_back(Size);
12514 Args.push_back(AllocVal);
12515 llvm::omp::RuntimeFunction FnID =
12516 Alignment ? OMPRTL___kmpc_aligned_alloc : OMPRTL___kmpc_alloc;
12518 OMPBuilder.getOrCreateRuntimeFunction(
CGM.getModule(), FnID), Args,
12520 llvm::FunctionCallee FiniRTLFn =
OMPBuilder.getOrCreateRuntimeFunction(
12521 CGM.getModule(), OMPRTL___kmpc_free);
12529 class OMPAllocateCleanupTy final :
public EHScopeStack::Cleanup {
12530 llvm::FunctionCallee RTLFn;
12533 const Expr *AllocExpr;
12536 OMPAllocateCleanupTy(llvm::FunctionCallee RTLFn,
12538 const Expr *AllocExpr)
12539 : RTLFn(RTLFn), LocEncoding(LocEncoding),
Addr(
Addr),
12540 AllocExpr(AllocExpr) {}
12544 llvm::Value *Args[3];
12550 Args[2] = AllocVal;
12558 CGF.
EHStack.pushCleanup<OMPAllocateCleanupTy>(
12560 VDAddr, Allocator);
12561 if (UntiedRealAddr.
isValid())
12564 Region->emitUntiedSwitch(CGF);
12581 assert(CGM.getLangOpts().OpenMP &&
"Not in OpenMP mode.");
12585 CGM.getOpenMPRuntime().NontemporalDeclsStack.emplace_back();
12587 for (
const Stmt *Ref :
C->private_refs()) {
12588 const auto *SimpleRefExpr =
cast<Expr>(Ref)->IgnoreParenImpCasts();
12590 if (
const auto *DRE = dyn_cast<DeclRefExpr>(SimpleRefExpr)) {
12591 VD = DRE->getDecl();
12594 assert((ME->isImplicitCXXThis() ||
12596 "Expected member of current class.");
12597 VD = ME->getMemberDecl();
12607 CGM.getOpenMPRuntime().NontemporalDeclsStack.pop_back();
12613 std::pair<Address, Address>> &LocalVars)
12614 : CGM(CGF.CGM), NeedToPush(!LocalVars.empty()) {
12618 CGF.
CurFn, CGM.getOpenMPRuntime().UntiedLocalVarsStack.size());
12619 CGM.getOpenMPRuntime().UntiedLocalVarsStack.push_back(LocalVars);
12625 CGM.getOpenMPRuntime().UntiedLocalVarsStack.pop_back();
12629 assert(
CGM.getLangOpts().OpenMP &&
"Not in OpenMP mode.");
12631 return llvm::any_of(
12632 CGM.getOpenMPRuntime().NontemporalDeclsStack,
12636void CGOpenMPRuntime::LastprivateConditionalRAII::tryToDisableInnerAnalysis(
12640 llvm::DenseSet<CanonicalDeclPtr<const Decl>> NeedToCheckForLPCs;
12646 const CapturedStmt *CS = S.getCapturedStmt(CaptureRegions.front());
12653 for (
const auto *
C : S.getClausesOfKind<OMPPrivateClause>()) {
12654 for (
const Expr *Ref :
C->varlist()) {
12655 if (!Ref->getType()->isScalarType())
12657 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
12660 NeedToCheckForLPCs.insert(DRE->getDecl());
12663 for (
const auto *
C : S.getClausesOfKind<OMPFirstprivateClause>()) {
12664 for (
const Expr *Ref :
C->varlist()) {
12665 if (!Ref->getType()->isScalarType())
12667 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
12670 NeedToCheckForLPCs.insert(DRE->getDecl());
12673 for (
const auto *
C : S.getClausesOfKind<OMPLastprivateClause>()) {
12674 for (
const Expr *Ref :
C->varlist()) {
12675 if (!Ref->getType()->isScalarType())
12677 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
12680 NeedToCheckForLPCs.insert(DRE->getDecl());
12683 for (
const auto *
C : S.getClausesOfKind<OMPReductionClause>()) {
12684 for (
const Expr *Ref :
C->varlist()) {
12685 if (!Ref->getType()->isScalarType())
12687 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
12690 NeedToCheckForLPCs.insert(DRE->getDecl());
12693 for (
const auto *
C : S.getClausesOfKind<OMPLinearClause>()) {
12694 for (
const Expr *Ref :
C->varlist()) {
12695 if (!Ref->getType()->isScalarType())
12697 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
12700 NeedToCheckForLPCs.insert(DRE->getDecl());
12703 for (
const Decl *VD : NeedToCheckForLPCs) {
12705 llvm::reverse(
CGM.getOpenMPRuntime().LastprivateConditionalStack)) {
12706 if (
Data.DeclToUniqueName.count(VD) > 0) {
12707 if (!
Data.Disabled)
12708 NeedToAddForLPCsAsDisabled.insert(VD);
12715CGOpenMPRuntime::LastprivateConditionalRAII::LastprivateConditionalRAII(
12718 Action((CGM.getLangOpts().OpenMP >= 50 &&
12719 llvm::any_of(S.getClausesOfKind<OMPLastprivateClause>(),
12720 [](const OMPLastprivateClause *
C) {
12721 return C->getKind() ==
12722 OMPC_LASTPRIVATE_conditional;
12724 ? ActionToDo::PushAsLastprivateConditional
12725 : ActionToDo::DoNotPush) {
12726 assert(
CGM.getLangOpts().OpenMP &&
"Not in OpenMP mode.");
12727 if (
CGM.getLangOpts().OpenMP < 50 || Action == ActionToDo::DoNotPush)
12729 assert(Action == ActionToDo::PushAsLastprivateConditional &&
12730 "Expected a push action.");
12732 CGM.getOpenMPRuntime().LastprivateConditionalStack.emplace_back();
12733 for (
const auto *
C : S.getClausesOfKind<OMPLastprivateClause>()) {
12734 if (
C->getKind() != OMPC_LASTPRIVATE_conditional)
12737 for (
const Expr *Ref :
C->varlist()) {
12738 Data.DeclToUniqueName.insert(std::make_pair(
12743 Data.IVLVal = IVLVal;
12747CGOpenMPRuntime::LastprivateConditionalRAII::LastprivateConditionalRAII(
12749 :
CGM(CGF.
CGM), Action(ActionToDo::DoNotPush) {
12753 llvm::DenseSet<CanonicalDeclPtr<const Decl>> NeedToAddForLPCsAsDisabled;
12754 tryToDisableInnerAnalysis(S, NeedToAddForLPCsAsDisabled);
12755 if (!NeedToAddForLPCsAsDisabled.empty()) {
12756 Action = ActionToDo::DisableLastprivateConditional;
12757 LastprivateConditionalData &
Data =
12759 for (
const Decl *VD : NeedToAddForLPCsAsDisabled)
12760 Data.DeclToUniqueName.try_emplace(VD);
12762 Data.Disabled =
true;
12766CGOpenMPRuntime::LastprivateConditionalRAII
12769 return LastprivateConditionalRAII(CGF, S);
12773 if (CGM.getLangOpts().OpenMP < 50)
12775 if (Action == ActionToDo::DisableLastprivateConditional) {
12776 assert(CGM.getOpenMPRuntime().LastprivateConditionalStack.back().Disabled &&
12777 "Expected list of disabled private vars.");
12778 CGM.getOpenMPRuntime().LastprivateConditionalStack.pop_back();
12780 if (Action == ActionToDo::PushAsLastprivateConditional) {
12782 !CGM.getOpenMPRuntime().LastprivateConditionalStack.back().Disabled &&
12783 "Expected list of lastprivate conditional vars.");
12784 CGM.getOpenMPRuntime().LastprivateConditionalStack.pop_back();
12796 auto VI = I->getSecond().find(VD);
12797 if (VI == I->getSecond().end()) {
12798 RecordDecl *RD =
C.buildImplicitRecord(
"lasprivate.conditional");
12803 NewType =
C.getCanonicalTagType(RD);
12806 I->getSecond().try_emplace(VD, NewType, VDField, FiredField, BaseLVal);
12808 NewType = std::get<0>(VI->getSecond());
12809 VDField = std::get<1>(VI->getSecond());
12810 FiredField = std::get<2>(VI->getSecond());
12811 BaseLVal = std::get<3>(VI->getSecond());
12823class LastprivateConditionalRefChecker final
12826 const Expr *FoundE =
nullptr;
12827 const Decl *FoundD =
nullptr;
12828 StringRef UniqueDeclName;
12830 llvm::Function *FoundFn =
nullptr;
12836 llvm::reverse(LPM)) {
12837 auto It = D.DeclToUniqueName.find(E->
getDecl());
12838 if (It == D.DeclToUniqueName.end())
12844 UniqueDeclName = It->second;
12849 return FoundE == E;
12855 llvm::reverse(LPM)) {
12857 if (It == D.DeclToUniqueName.end())
12863 UniqueDeclName = It->second;
12868 return FoundE == E;
12870 bool VisitStmt(
const Stmt *S) {
12871 for (
const Stmt *Child : S->
children()) {
12874 if (
const auto *E = dyn_cast<Expr>(Child))
12882 explicit LastprivateConditionalRefChecker(
12883 ArrayRef<CGOpenMPRuntime::LastprivateConditionalData> LPM)
12885 std::tuple<const Expr *, const Decl *, StringRef, LValue, llvm::Function *>
12886 getFoundData()
const {
12887 return std::make_tuple(FoundE, FoundD, UniqueDeclName, IVLVal, FoundFn);
12894 StringRef UniqueDeclName,
12900 llvm::Constant *LastIV =
OMPBuilder.getOrCreateInternalVariable(
12901 LLIVTy,
getName({UniqueDeclName,
"iv"}));
12909 llvm::GlobalVariable *
Last =
OMPBuilder.getOrCreateInternalVariable(
12925 auto &&
CodeGen = [&LastIVLVal, &IVLVal, IVVal, &LVal, &LastLVal,
12931 llvm::Value *CmpRes;
12933 CmpRes = CGF.
Builder.CreateICmpSLE(LastIVVal, IVVal);
12936 "Loop iteration variable must be integer.");
12937 CmpRes = CGF.
Builder.CreateICmpULE(LastIVVal, IVVal);
12941 CGF.
Builder.CreateCondBr(CmpRes, ThenBB, ExitBB);
12962 "Aggregates are not supported in lastprivate conditional.");
12971 if (
CGM.getLangOpts().OpenMPSimd) {
12985 if (!Checker.Visit(LHS))
12987 const Expr *FoundE;
12988 const Decl *FoundD;
12989 StringRef UniqueDeclName;
12991 llvm::Function *FoundFn;
12992 std::tie(FoundE, FoundD, UniqueDeclName, IVLVal, FoundFn) =
12993 Checker.getFoundData();
12994 if (FoundFn != CGF.
CurFn) {
12999 "Lastprivate conditional is not found in outer region.");
13000 QualType StructTy = std::get<0>(It->getSecond());
13001 const FieldDecl* FiredDecl = std::get<2>(It->getSecond());
13012 FiredLVal, llvm::AtomicOrdering::Unordered,
13030 auto It = llvm::find_if(
13032 if (It == Range.end() || It->Fn != CGF.
CurFn)
13036 "Lastprivates must be registered already.");
13039 const CapturedStmt *CS = D.getCapturedStmt(CaptureRegions.back());
13040 for (
const auto &Pair : It->DeclToUniqueName) {
13041 const auto *VD =
cast<VarDecl>(Pair.first->getCanonicalDecl());
13044 auto I = LPCI->getSecond().find(Pair.first);
13045 assert(I != LPCI->getSecond().end() &&
13046 "Lastprivate must be rehistered already.");
13048 LValue BaseLVal = std::get<3>(I->getSecond());
13052 llvm::Value *
Cmp = CGF.
Builder.CreateIsNotNull(Res);
13056 CGF.
Builder.CreateCondBr(
Cmp, ThenBB, DoneBB);
13081 "Unknown lastprivate conditional variable.");
13082 StringRef UniqueName = It->second;
13083 llvm::GlobalVariable *GV =
CGM.getModule().getNamedGlobal(UniqueName);
13097 llvm_unreachable(
"Not supported in SIMD-only mode");
13104 llvm_unreachable(
"Not supported in SIMD-only mode");
13111 bool Tied,
unsigned &NumberOfParts) {
13112 llvm_unreachable(
"Not supported in SIMD-only mode");
13120 llvm_unreachable(
"Not supported in SIMD-only mode");
13126 const Expr *Hint) {
13127 llvm_unreachable(
"Not supported in SIMD-only mode");
13133 llvm_unreachable(
"Not supported in SIMD-only mode");
13139 const Expr *Filter) {
13140 llvm_unreachable(
"Not supported in SIMD-only mode");
13145 llvm_unreachable(
"Not supported in SIMD-only mode");
13151 llvm_unreachable(
"Not supported in SIMD-only mode");
13159 llvm_unreachable(
"Not supported in SIMD-only mode");
13166 llvm_unreachable(
"Not supported in SIMD-only mode");
13173 bool ForceSimpleCall) {
13174 llvm_unreachable(
"Not supported in SIMD-only mode");
13181 llvm_unreachable(
"Not supported in SIMD-only mode");
13186 llvm_unreachable(
"Not supported in SIMD-only mode");
13192 llvm_unreachable(
"Not supported in SIMD-only mode");
13198 llvm_unreachable(
"Not supported in SIMD-only mode");
13205 llvm_unreachable(
"Not supported in SIMD-only mode");
13211 llvm_unreachable(
"Not supported in SIMD-only mode");
13216 unsigned IVSize,
bool IVSigned,
13219 llvm_unreachable(
"Not supported in SIMD-only mode");
13227 llvm_unreachable(
"Not supported in SIMD-only mode");
13231 ProcBindKind ProcBind,
13233 llvm_unreachable(
"Not supported in SIMD-only mode");
13240 llvm_unreachable(
"Not supported in SIMD-only mode");
13246 llvm_unreachable(
"Not supported in SIMD-only mode");
13251 llvm_unreachable(
"Not supported in SIMD-only mode");
13257 llvm::AtomicOrdering AO) {
13258 llvm_unreachable(
"Not supported in SIMD-only mode");
13263 llvm::Function *TaskFunction,
13265 const Expr *IfCond,
13267 llvm_unreachable(
"Not supported in SIMD-only mode");
13274 llvm_unreachable(
"Not supported in SIMD-only mode");
13281 assert(Options.
SimpleReduction &&
"Only simple reduction is expected.");
13283 ReductionOps, Options);
13289 llvm_unreachable(
"Not supported in SIMD-only mode");
13294 bool IsWorksharingReduction) {
13295 llvm_unreachable(
"Not supported in SIMD-only mode");
13302 llvm_unreachable(
"Not supported in SIMD-only mode");
13307 llvm::Value *ReductionsPtr,
13309 llvm_unreachable(
"Not supported in SIMD-only mode");
13315 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::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
13334 llvm_unreachable(
"Not supported in SIMD-only mode");
13339 llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID,
const Expr *IfCond,
13340 llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier>
Device,
13344 llvm_unreachable(
"Not supported in SIMD-only mode");
13348 llvm_unreachable(
"Not supported in SIMD-only mode");
13352 llvm_unreachable(
"Not supported in SIMD-only mode");
13362 llvm::Function *OutlinedFn,
13364 llvm_unreachable(
"Not supported in SIMD-only mode");
13368 const Expr *NumTeams,
13369 const Expr *ThreadLimit,
13371 llvm_unreachable(
"Not supported in SIMD-only mode");
13378 llvm_unreachable(
"Not supported in SIMD-only mode");
13384 llvm_unreachable(
"Not supported in SIMD-only mode");
13390 llvm_unreachable(
"Not supported in SIMD-only mode");
13395 llvm_unreachable(
"Not supported in SIMD-only mode");
13400 llvm_unreachable(
"Not supported in SIMD-only mode");
13405 const VarDecl *NativeParam)
const {
13406 llvm_unreachable(
"Not supported in SIMD-only mode");
13412 const VarDecl *TargetParam)
const {
13413 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)
virtual void emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc, const OMPExecutableDirective &D, llvm::Function *TaskFunction, QualType SharedsTy, Address Shareds, const Expr *IfCond, const OMPTaskDataTy &Data)
Emit task region for the task directive.
void createOffloadEntriesAndInfoMetadata()
Creates all the offload entries in the current compilation unit along with the associated metadata.
const Expr * getNumTeamsExprForTargetDirective(CodeGenFunction &CGF, const OMPExecutableDirective &D, int32_t &MinTeamsVal, int32_t &MaxTeamsVal)
Emit the number of teams for a target directive.
virtual Address getAddrOfThreadPrivate(CodeGenFunction &CGF, const VarDecl *VD, Address VDAddr, SourceLocation Loc)
Returns address of the threadprivate variable for the current thread.
void emitDeferredTargetDecls() const
Emit deferred declare target variables marked for deferred emission.
virtual llvm::Value * emitForNext(CodeGenFunction &CGF, SourceLocation Loc, unsigned IVSize, bool IVSigned, Address IL, Address LB, Address UB, Address ST)
Call __kmpc_dispatch_next( ident_t *loc, kmp_int32 tid, kmp_int32 *p_lastiter, kmp_int[32|64] *p_lowe...
bool markAsGlobalTarget(GlobalDecl GD)
Marks the declaration as already emitted for the device code and returns true, if it was marked alrea...
virtual void emitParallelCall(CodeGenFunction &CGF, SourceLocation Loc, llvm::Function *OutlinedFn, ArrayRef< llvm::Value * > CapturedVars, const Expr *IfCond, llvm::Value *NumThreads, OpenMPNumThreadsClauseModifier NumThreadsModifier=OMPC_NUMTHREADS_unknown, OpenMPSeverityClauseKind Severity=OMPC_SEVERITY_fatal, const Expr *Message=nullptr)
Emits code for parallel or serial call of the OutlinedFn with variables captured in a record which ad...
llvm::SmallDenseSet< CanonicalDeclPtr< const Decl > > NontemporalDeclsSet
virtual void emitTargetDataStandAloneCall(CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, const Expr *Device)
Emit the data mapping/movement code associated with the directive D that should be of the form 'targe...
virtual void emitNumThreadsClause(CodeGenFunction &CGF, llvm::Value *NumThreads, SourceLocation Loc, OpenMPNumThreadsClauseModifier Modifier=OMPC_NUMTHREADS_unknown, OpenMPSeverityClauseKind Severity=OMPC_SEVERITY_fatal, SourceLocation SeverityLoc=SourceLocation(), const Expr *Message=nullptr, SourceLocation MessageLoc=SourceLocation())
Emits call to void __kmpc_push_num_threads(ident_t *loc, kmp_int32global_tid, kmp_int32 num_threads) ...
QualType SavedKmpTaskloopTQTy
Saved kmp_task_t for taskloop-based directive.
virtual void emitSingleRegion(CodeGenFunction &CGF, const RegionCodeGenTy &SingleOpGen, SourceLocation Loc, ArrayRef< const Expr * > CopyprivateVars, ArrayRef< const Expr * > DestExprs, ArrayRef< const Expr * > SrcExprs, ArrayRef< const Expr * > AssignmentOps)
Emits a single region.
virtual bool emitTargetGlobal(GlobalDecl GD)
Emit the global GD if it is meaningful for the target.
void setLocThreadIdInsertPt(CodeGenFunction &CGF, bool AtCurrentPoint=false)
std::string getOutlinedHelperName(StringRef Name) const
Get the function name of an outlined region.
bool HasEmittedDeclareTargetRegion
Flag for keeping track of weather a device routine has been emitted.
llvm::Constant * getOrCreateThreadPrivateCache(const VarDecl *VD)
If the specified mangled name is not in the module, create and return threadprivate cache object.
virtual Address getTaskReductionItem(CodeGenFunction &CGF, SourceLocation Loc, llvm::Value *ReductionsPtr, LValue SharedLVal)
Get the address of void * type of the privatue copy of the reduction item specified by the SharedLVal...
virtual void emitForDispatchDeinit(CodeGenFunction &CGF, SourceLocation Loc)
This is used for non static scheduled types and when the ordered clause is present on the loop constr...
void emitCall(CodeGenFunction &CGF, SourceLocation Loc, llvm::FunctionCallee Callee, ArrayRef< llvm::Value * > Args={}) const
Emits Callee function call with arguments Args with location Loc.
virtual void getDefaultScheduleAndChunk(CodeGenFunction &CGF, const OMPLoopDirective &S, OpenMPScheduleClauseKind &ScheduleKind, const Expr *&ChunkExpr) const
Choose default schedule type and chunk value for the schedule clause.
virtual std::pair< llvm::Function *, llvm::Function * > getUserDefinedReduction(const OMPDeclareReductionDecl *D)
Get combiner/initializer for the specified user-defined reduction, if any.
virtual bool isGPU() const
Returns true if the current target is a GPU.
static const Stmt * getSingleCompoundChild(ASTContext &Ctx, const Stmt *Body)
Checks if the Body is the CompoundStmt and returns its child statement iff there is only one that is ...
virtual void emitDeclareTargetFunction(const FunctionDecl *FD, llvm::GlobalValue *GV)
Emit code for handling declare target functions in the runtime.
bool HasRequiresUnifiedSharedMemory
Flag for keeping track of weather a requires unified_shared_memory directive is present.
llvm::Value * emitUpdateLocation(CodeGenFunction &CGF, SourceLocation Loc, unsigned Flags=0, bool EmitLoc=false)
Emits object of ident_t type with info for source location.
bool isLocalVarInUntiedTask(CodeGenFunction &CGF, const VarDecl *VD) const
Returns true if the variable is a local variable in untied task.
virtual void emitTeamsCall(CodeGenFunction &CGF, const OMPExecutableDirective &D, SourceLocation Loc, llvm::Function *OutlinedFn, ArrayRef< llvm::Value * > CapturedVars)
Emits code for teams call of the OutlinedFn with variables captured in a record which address is stor...
virtual void emitCancellationPointCall(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind CancelRegion)
Emit code for 'cancellation point' construct.
virtual llvm::Function * emitThreadPrivateVarDefinition(const VarDecl *VD, Address VDAddr, SourceLocation Loc, bool PerformInit, CodeGenFunction *CGF=nullptr)
Emit a code for initialization of threadprivate variable.
FunctionUDMMapTy FunctionUDMMap
virtual ConstantAddress getAddrOfDeclareTargetVar(const VarDecl *VD)
Returns the address of the variable marked as declare target with link clause OR as declare target wi...
llvm::Function * getOrCreateUserDefinedMapperFunc(const OMPDeclareMapperDecl *D)
Get the function for the specified user-defined mapper.
OpenMPLocThreadIDMapTy OpenMPLocThreadIDMap
virtual void functionFinished(CodeGenFunction &CGF)
Cleans up references to the objects in finished function.
virtual llvm::Function * emitTeamsOutlinedFunction(CodeGenFunction &CGF, const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen)
Emits outlined function for the specified OpenMP teams directive D.
QualType KmpTaskTQTy
Type typedef struct kmp_task { void * shareds; /**< pointer to block of pointers to shared vars / k...
llvm::OpenMPIRBuilder OMPBuilder
An OpenMP-IR-Builder instance.
virtual void emitDoacrossInit(CodeGenFunction &CGF, const OMPLoopDirective &D, ArrayRef< Expr * > NumIterations)
Emit initialization for doacross loop nesting support.
virtual void adjustTargetSpecificDataForLambdas(CodeGenFunction &CGF, const OMPExecutableDirective &D) const
Adjust some parameters for the target-based directives, like addresses of the variables captured by r...
FunctionUDRMapTy FunctionUDRMap
virtual void emitTargetDataCalls(CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, const Expr *Device, const RegionCodeGenTy &CodeGen, CGOpenMPRuntime::TargetDataInfo &Info)
Emit the target data mapping code associated with D.
virtual unsigned getDefaultLocationReserved2Flags() const
Returns additional flags that can be stored in reserved_2 field of the default location.
virtual Address getParameterAddress(CodeGenFunction &CGF, const VarDecl *NativeParam, const VarDecl *TargetParam) const
Gets the address of the native argument basing on the address of the target-specific parameter.
void emitUsesAllocatorsFini(CodeGenFunction &CGF, const Expr *Allocator)
Destroys user defined allocators specified in the uses_allocators clause.
QualType KmpTaskAffinityInfoTy
Type typedef struct kmp_task_affinity_info { kmp_intptr_t base_addr; size_t len; struct { bool flag1 ...
void emitPrivateReduction(CodeGenFunction &CGF, SourceLocation Loc, const Expr *Privates, const Expr *LHSExprs, const Expr *RHSExprs, const Expr *ReductionOps)
Emits code for private variable reduction.
llvm::Value * emitNumTeamsForTargetDirective(CodeGenFunction &CGF, const OMPExecutableDirective &D)
virtual void emitTargetOutlinedFunctionHelper(const OMPExecutableDirective &D, StringRef ParentName, llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID, bool IsOffloadEntry, const RegionCodeGenTy &CodeGen)
Helper to emit outlined function for 'target' directive.
void scanForTargetRegionsFunctions(const Stmt *S, StringRef ParentName)
Start scanning from statement S and emit all target regions found along the way.
SmallVector< llvm::Value *, 4 > emitDepobjElementsSizes(CodeGenFunction &CGF, QualType &KmpDependInfoTy, const OMPTaskDataTy::DependData &Data)
virtual llvm::Value * emitMessageClause(CodeGenFunction &CGF, const Expr *Message, SourceLocation Loc)
virtual void emitTaskgroupRegion(CodeGenFunction &CGF, const RegionCodeGenTy &TaskgroupOpGen, SourceLocation Loc)
Emit a taskgroup region.
llvm::DenseMap< llvm::Function *, llvm::DenseMap< CanonicalDeclPtr< const Decl >, std::tuple< QualType, const FieldDecl *, const FieldDecl *, LValue > > > LastprivateConditionalToTypes
Maps local variables marked as lastprivate conditional to their internal types.
virtual bool emitTargetGlobalVariable(GlobalDecl GD)
Emit the global variable if it is a valid device global variable.
virtual void emitNumTeamsClause(CodeGenFunction &CGF, const Expr *NumTeams, const Expr *ThreadLimit, SourceLocation Loc)
Emits call to void __kmpc_push_num_teams(ident_t *loc, kmp_int32global_tid, kmp_int32 num_teams,...
bool hasRequiresUnifiedSharedMemory() const
Return whether the unified_shared_memory has been specified.
virtual Address getAddrOfArtificialThreadPrivate(CodeGenFunction &CGF, QualType VarType, StringRef Name)
Creates artificial threadprivate variable with name Name and type VarType.
void emitUserDefinedMapper(const OMPDeclareMapperDecl *D, CodeGenFunction *CGF=nullptr)
Emit the function for the user defined mapper construct.
bool HasEmittedTargetRegion
Flag for keeping track of weather a target region has been emitted.
void emitDepobjElements(CodeGenFunction &CGF, QualType &KmpDependInfoTy, LValue PosLVal, const OMPTaskDataTy::DependData &Data, Address DependenciesArray)
std::string getReductionFuncName(StringRef Name) const
Get the function name of a reduction function.
virtual void processRequiresDirective(const OMPRequiresDecl *D)
Perform check on requires decl to ensure that target architecture supports unified addressing.
llvm::DenseSet< CanonicalDeclPtr< const Decl > > AlreadyEmittedTargetDecls
List of the emitted declarations.
virtual llvm::Value * emitTaskReductionInit(CodeGenFunction &CGF, SourceLocation Loc, ArrayRef< const Expr * > LHSExprs, ArrayRef< const Expr * > RHSExprs, const OMPTaskDataTy &Data)
Emit a code for initialization of task reduction clause.
llvm::Value * getThreadID(CodeGenFunction &CGF, SourceLocation Loc)
Gets thread id value for the current thread.
void emitUpdateClause(CodeGenFunction &CGF, LValue DepobjLVal, OpenMPDependClauseKind NewDepKind, SourceLocation Loc)
Updates the dependency kind in the specified depobj object.
virtual void emitLastprivateConditionalFinalUpdate(CodeGenFunction &CGF, LValue PrivLVal, const VarDecl *VD, SourceLocation Loc)
Gets the address of the global copy used for lastprivate conditional update, if any.
llvm::MapVector< CanonicalDeclPtr< const VarDecl >, std::pair< Address, Address > > UntiedLocalVarsAddressesMap
virtual void emitErrorCall(CodeGenFunction &CGF, SourceLocation Loc, Expr *ME, bool IsFatal)
Emit __kmpc_error call for error directive extern void __kmpc_error(ident_t *loc, int severity,...
void clearLocThreadIdInsertPt(CodeGenFunction &CGF)
virtual void emitTaskyieldCall(CodeGenFunction &CGF, SourceLocation Loc)
Emits code for a taskyield directive.
std::string getName(ArrayRef< StringRef > Parts) const
Get the platform-specific name separator.
QualType KmpRoutineEntryPtrQTy
void computeMinAndMaxThreadsAndTeams(const OMPExecutableDirective &D, CodeGenFunction &CGF, llvm::OpenMPIRBuilder::TargetKernelDefaultAttrs &Attrs)
Helper to determine the min/max number of threads/teams for D.
virtual void emitFlush(CodeGenFunction &CGF, ArrayRef< const Expr * > Vars, SourceLocation Loc, llvm::AtomicOrdering AO)
Emit flush of the variables specified in 'omp flush' directive.
virtual void emitTaskwaitCall(CodeGenFunction &CGF, SourceLocation Loc, const OMPTaskDataTy &Data)
Emit code for 'taskwait' directive.
virtual void emitProcBindClause(CodeGenFunction &CGF, llvm::omp::ProcBindKind ProcBind, SourceLocation Loc)
Emit call to void __kmpc_push_proc_bind(ident_t *loc, kmp_int32global_tid, int proc_bind) to generate...
void emitLastprivateConditionalUpdate(CodeGenFunction &CGF, LValue IVLVal, StringRef UniqueDeclName, LValue LVal, SourceLocation Loc)
Emit update for lastprivate conditional data.
virtual void emitTaskLoopCall(CodeGenFunction &CGF, SourceLocation Loc, const OMPLoopDirective &D, llvm::Function *TaskFunction, QualType SharedsTy, Address Shareds, const Expr *IfCond, const OMPTaskDataTy &Data)
Emit task region for the taskloop directive.
virtual void emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind Kind, bool EmitChecks=true, bool ForceSimpleCall=false)
Emit an implicit/explicit barrier for OpenMP threads.
static unsigned getDefaultFlagsForBarriers(OpenMPDirectiveKind Kind)
Returns default flags for the barriers depending on the directive, for which this barier is going to ...
virtual bool emitTargetFunctions(GlobalDecl GD)
Emit the target regions enclosed in GD function definition or the function itself in case it is a val...
TaskResultTy emitTaskInit(CodeGenFunction &CGF, SourceLocation Loc, const OMPExecutableDirective &D, llvm::Function *TaskFunction, QualType SharedsTy, Address Shareds, const OMPTaskDataTy &Data)
Emit task region for the task directive.
llvm::Value * emitTargetNumIterationsCall(CodeGenFunction &CGF, const OMPExecutableDirective &D, llvm::function_ref< llvm::Value *(CodeGenFunction &CGF, const OMPLoopDirective &D)> SizeEmitter)
Return the trip count of loops associated with constructs / 'target teams distribute' and 'teams dist...
llvm::StringMap< llvm::AssertingVH< llvm::GlobalVariable >, llvm::BumpPtrAllocator > InternalVars
An ordered map of auto-generated variables to their unique names.
virtual void emitDistributeStaticInit(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDistScheduleClauseKind SchedKind, const StaticRTInput &Values)
llvm::SmallVector< UntiedLocalVarsAddressesMap, 4 > UntiedLocalVarsStack
virtual void emitForStaticFinish(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind DKind)
Call the appropriate runtime routine to notify that we finished all the work with current loop.
virtual void emitThreadLimitClause(CodeGenFunction &CGF, const Expr *ThreadLimit, SourceLocation Loc)
Emits call to void __kmpc_set_thread_limit(ident_t *loc, kmp_int32global_tid, kmp_int32 thread_limit)...
void emitIfClause(CodeGenFunction &CGF, const Expr *Cond, const RegionCodeGenTy &ThenGen, const RegionCodeGenTy &ElseGen)
Emits code for OpenMP 'if' clause using specified CodeGen function.
Address emitDepobjDependClause(CodeGenFunction &CGF, const OMPTaskDataTy::DependData &Dependencies, SourceLocation Loc)
Emits list of dependecies based on the provided data (array of dependence/expression pairs) for depob...
bool isNontemporalDecl(const ValueDecl *VD) const
Checks if the VD variable is marked as nontemporal declaration in current context.
virtual llvm::Function * emitParallelOutlinedFunction(CodeGenFunction &CGF, const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen)
Emits outlined function for the specified OpenMP parallel directive D.
const Expr * getNumThreadsExprForTargetDirective(CodeGenFunction &CGF, const OMPExecutableDirective &D, int32_t &UpperBound, bool UpperBoundOnly, llvm::Value **CondExpr=nullptr, const Expr **ThreadLimitExpr=nullptr)
Check for a number of threads upper bound constant value (stored in UpperBound), or expression (retur...
virtual void registerVTableOffloadEntry(llvm::GlobalVariable *VTable, const VarDecl *VD)
Register VTable to OpenMP offload entry.
virtual llvm::Value * emitSeverityClause(OpenMPSeverityClauseKind Severity, SourceLocation Loc)
llvm::SmallVector< LastprivateConditionalData, 4 > LastprivateConditionalStack
Stack for list of addresses of declarations in current context marked as lastprivate conditional.
virtual void emitForStaticInit(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind DKind, const OpenMPScheduleTy &ScheduleKind, const StaticRTInput &Values)
Call the appropriate runtime routine to initialize it before start of loop.
virtual void emitDeclareSimdFunction(const FunctionDecl *FD, llvm::Function *Fn)
Marks function Fn with properly mangled versions of vector functions.
llvm::AtomicOrdering getDefaultMemoryOrdering() const
Gets default memory ordering as specified in requires directive.
virtual bool isStaticNonchunked(OpenMPScheduleClauseKind ScheduleKind, bool Chunked) const
Check if the specified ScheduleKind is static non-chunked.
virtual void emitAndRegisterVTable(CodeGenModule &CGM, CXXRecordDecl *CXXRecord, const VarDecl *VD)
Emit and register VTable for the C++ class in OpenMP offload entry.
llvm::Value * getCriticalRegionLock(StringRef CriticalName)
Returns corresponding lock object for the specified critical region name.
virtual void emitCancelCall(CodeGenFunction &CGF, SourceLocation Loc, const Expr *IfCond, OpenMPDirectiveKind CancelRegion)
Emit code for 'cancel' construct.
QualType SavedKmpTaskTQTy
Saved kmp_task_t for task directive.
virtual void emitMasterRegion(CodeGenFunction &CGF, const RegionCodeGenTy &MasterOpGen, SourceLocation Loc)
Emits a master region.
virtual llvm::Function * emitTaskOutlinedFunction(const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, const VarDecl *PartIDVar, const VarDecl *TaskTVar, OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen, bool Tied, unsigned &NumberOfParts)
Emits outlined function for the OpenMP task directive D.
llvm::DenseMap< llvm::Function *, unsigned > FunctionToUntiedTaskStackMap
Maps function to the position of the untied task locals stack.
void emitDestroyClause(CodeGenFunction &CGF, LValue DepobjLVal, SourceLocation Loc)
Emits the code to destroy the dependency object provided in depobj directive.
virtual void emitTaskReductionFixups(CodeGenFunction &CGF, SourceLocation Loc, ReductionCodeGen &RCG, unsigned N)
Required to resolve existing problems in the runtime.
llvm::ArrayType * KmpCriticalNameTy
Type kmp_critical_name, originally defined as typedef kmp_int32 kmp_critical_name[8];.
virtual void emitDoacrossOrdered(CodeGenFunction &CGF, const OMPDependClause *C)
Emit code for doacross ordered directive with 'depend' clause.
llvm::DenseMap< const OMPDeclareMapperDecl *, llvm::Function * > UDMMap
Map from the user-defined mapper declaration to its corresponding functions.
virtual void checkAndEmitLastprivateConditional(CodeGenFunction &CGF, const Expr *LHS)
Checks if the provided LVal is lastprivate conditional and emits the code to update the value of the ...
std::pair< llvm::Value *, LValue > getDepobjElements(CodeGenFunction &CGF, LValue DepobjLVal, SourceLocation Loc)
Returns the number of the elements and the address of the depobj dependency array.
llvm::SmallDenseSet< const VarDecl * > DeferredGlobalVariables
List of variables that can become declare target implicitly and, thus, must be emitted.
void emitUsesAllocatorsInit(CodeGenFunction &CGF, const Expr *Allocator, const Expr *AllocatorTraits)
Initializes user defined allocators specified in the uses_allocators clauses.
virtual void registerVTable(const OMPExecutableDirective &D)
Emit code for registering vtable by scanning through map clause in OpenMP target region.
llvm::Type * KmpRoutineEntryPtrTy
Type typedef kmp_int32 (* kmp_routine_entry_t)(kmp_int32, void *);.
llvm::Type * getIdentTyPointerTy()
Returns pointer to ident_t type.
void emitSingleReductionCombiner(CodeGenFunction &CGF, const Expr *ReductionOp, const Expr *PrivateRef, const DeclRefExpr *LHS, const DeclRefExpr *RHS)
Emits single reduction combiner.
llvm::OpenMPIRBuilder & getOMPBuilder()
virtual void emitTargetOutlinedFunction(const OMPExecutableDirective &D, StringRef ParentName, llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID, bool IsOffloadEntry, const RegionCodeGenTy &CodeGen)
Emit outilined function for 'target' directive.
virtual void emitCriticalRegion(CodeGenFunction &CGF, StringRef CriticalName, const RegionCodeGenTy &CriticalOpGen, SourceLocation Loc, const Expr *Hint=nullptr)
Emits a critical region.
virtual void emitForOrderedIterationEnd(CodeGenFunction &CGF, SourceLocation Loc, unsigned IVSize, bool IVSigned)
Call the appropriate runtime routine to notify that we finished iteration of the ordered loop with th...
virtual void emitOutlinedFunctionCall(CodeGenFunction &CGF, SourceLocation Loc, llvm::FunctionCallee OutlinedFn, ArrayRef< llvm::Value * > Args={}) const
Emits call of the outlined function with the provided arguments, translating these arguments to corre...
llvm::Value * emitNumThreadsForTargetDirective(CodeGenFunction &CGF, const OMPExecutableDirective &D)
Emit an expression that denotes the number of threads a target region shall use.
void emitThreadPrivateVarInit(CodeGenFunction &CGF, Address VDAddr, llvm::Value *Ctor, llvm::Value *CopyCtor, llvm::Value *Dtor, SourceLocation Loc)
Emits initialization code for the threadprivate variables.
virtual void emitUserDefinedReduction(CodeGenFunction *CGF, const OMPDeclareReductionDecl *D)
Emit code for the specified user defined reduction construct.
virtual void checkAndEmitSharedLastprivateConditional(CodeGenFunction &CGF, const OMPExecutableDirective &D, const llvm::DenseSet< CanonicalDeclPtr< const VarDecl > > &IgnoredDecls)
Checks if the lastprivate conditional was updated in inner region and writes the value.
QualType KmpDimTy
struct kmp_dim { // loop bounds info casted to kmp_int64 kmp_int64 lo; // lower kmp_int64 up; // uppe...
virtual void emitInlinedDirective(CodeGenFunction &CGF, OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen, bool HasCancel=false)
Emit code for the directive that does not require outlining.
virtual void registerTargetGlobalVariable(const VarDecl *VD, llvm::Constant *Addr)
Checks if the provided global decl GD is a declare target variable and registers it when emitting cod...
virtual void emitFunctionProlog(CodeGenFunction &CGF, const Decl *D)
Emits OpenMP-specific function prolog.
void emitKmpRoutineEntryT(QualType KmpInt32Ty)
Build type kmp_routine_entry_t (if not built yet).
virtual bool isStaticChunked(OpenMPScheduleClauseKind ScheduleKind, bool Chunked) const
Check if the specified ScheduleKind is static chunked.
virtual void emitTargetCall(CodeGenFunction &CGF, const OMPExecutableDirective &D, llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID, const Expr *IfCond, llvm::PointerIntPair< const Expr *, 2, OpenMPDeviceClauseModifier > Device, llvm::function_ref< llvm::Value *(CodeGenFunction &CGF, const OMPLoopDirective &D)> SizeEmitter)
Emit the target offloading code associated with D.
virtual bool hasAllocateAttributeForGlobalVar(const VarDecl *VD, LangAS &AS)
Checks if the variable has associated OMPAllocateDeclAttr attribute with the predefined allocator and...
llvm::AtomicOrdering RequiresAtomicOrdering
Atomic ordering from the omp requires directive.
virtual void emitReduction(CodeGenFunction &CGF, SourceLocation Loc, ArrayRef< const Expr * > Privates, ArrayRef< const Expr * > LHSExprs, ArrayRef< const Expr * > RHSExprs, ArrayRef< const Expr * > ReductionOps, ReductionOptionsTy Options)
Emit a code for reduction clause.
std::pair< llvm::Value *, Address > emitDependClause(CodeGenFunction &CGF, ArrayRef< OMPTaskDataTy::DependData > Dependencies, SourceLocation Loc)
Emits list of dependecies based on the provided data (array of dependence/expression pairs).
llvm::StringMap< llvm::WeakTrackingVH > EmittedNonTargetVariables
List of the global variables with their addresses that should not be emitted for the target.
virtual bool isDynamic(OpenMPScheduleClauseKind ScheduleKind) const
Check if the specified ScheduleKind is dynamic.
Address emitLastprivateConditionalInit(CodeGenFunction &CGF, const VarDecl *VD)
Create specialized alloca to handle lastprivate conditionals.
virtual void emitOrderedRegion(CodeGenFunction &CGF, const RegionCodeGenTy &OrderedOpGen, SourceLocation Loc, bool IsThreads)
Emit an ordered region.
virtual Address getAddressOfLocalVariable(CodeGenFunction &CGF, const VarDecl *VD)
Gets the OpenMP-specific address of the local variable.
virtual void emitTaskReductionFini(CodeGenFunction &CGF, SourceLocation Loc, bool IsWorksharingReduction)
Emits the following code for reduction clause with task modifier:
virtual void emitMaskedRegion(CodeGenFunction &CGF, const RegionCodeGenTy &MaskedOpGen, SourceLocation Loc, const Expr *Filter=nullptr)
Emits a masked region.
QualType KmpDependInfoTy
Type typedef struct kmp_depend_info { kmp_intptr_t base_addr; size_t len; struct { bool in:1; bool ou...
llvm::Function * emitReductionFunction(StringRef ReducerName, SourceLocation Loc, llvm::Type *ArgsElemType, ArrayRef< const Expr * > Privates, ArrayRef< const Expr * > LHSExprs, ArrayRef< const Expr * > RHSExprs, ArrayRef< const Expr * > ReductionOps)
Emits reduction function.
virtual void emitForDispatchInit(CodeGenFunction &CGF, SourceLocation Loc, const OpenMPScheduleTy &ScheduleKind, unsigned IVSize, bool IVSigned, bool Ordered, const DispatchRTInput &DispatchValues)
Call the appropriate runtime routine to initialize it before start of loop.
Address getTaskReductionItem(CodeGenFunction &CGF, SourceLocation Loc, llvm::Value *ReductionsPtr, LValue SharedLVal) override
Get the address of void * type of the privatue copy of the reduction item specified by the SharedLVal...
void emitCriticalRegion(CodeGenFunction &CGF, StringRef CriticalName, const RegionCodeGenTy &CriticalOpGen, SourceLocation Loc, const Expr *Hint=nullptr) override
Emits a critical region.
void emitDistributeStaticInit(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDistScheduleClauseKind SchedKind, const StaticRTInput &Values) override
void emitForStaticInit(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind DKind, const OpenMPScheduleTy &ScheduleKind, const StaticRTInput &Values) override
Call the appropriate runtime routine to initialize it before start of loop.
bool emitTargetGlobalVariable(GlobalDecl GD) override
Emit the global variable if it is a valid device global variable.
llvm::Value * emitForNext(CodeGenFunction &CGF, SourceLocation Loc, unsigned IVSize, bool IVSigned, Address IL, Address LB, Address UB, Address ST) override
Call __kmpc_dispatch_next( ident_t *loc, kmp_int32 tid, kmp_int32 *p_lastiter, kmp_int[32|64] *p_lowe...
llvm::Function * emitThreadPrivateVarDefinition(const VarDecl *VD, Address VDAddr, SourceLocation Loc, bool PerformInit, CodeGenFunction *CGF=nullptr) override
Emit a code for initialization of threadprivate variable.
void emitTargetDataStandAloneCall(CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, const Expr *Device) override
Emit the data mapping/movement code associated with the directive D that should be of the form 'targe...
llvm::Function * emitTeamsOutlinedFunction(CodeGenFunction &CGF, const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) override
Emits outlined function for the specified OpenMP teams directive D.
void emitParallelCall(CodeGenFunction &CGF, SourceLocation Loc, llvm::Function *OutlinedFn, ArrayRef< llvm::Value * > CapturedVars, const Expr *IfCond, llvm::Value *NumThreads, OpenMPNumThreadsClauseModifier NumThreadsModifier=OMPC_NUMTHREADS_unknown, OpenMPSeverityClauseKind Severity=OMPC_SEVERITY_fatal, const Expr *Message=nullptr) override
Emits code for parallel or serial call of the OutlinedFn with variables captured in a record which ad...
void emitReduction(CodeGenFunction &CGF, SourceLocation Loc, ArrayRef< const Expr * > Privates, ArrayRef< const Expr * > LHSExprs, ArrayRef< const Expr * > RHSExprs, ArrayRef< const Expr * > ReductionOps, ReductionOptionsTy Options) override
Emit a code for reduction clause.
void emitFlush(CodeGenFunction &CGF, ArrayRef< const Expr * > Vars, SourceLocation Loc, llvm::AtomicOrdering AO) override
Emit flush of the variables specified in 'omp flush' directive.
void emitDoacrossOrdered(CodeGenFunction &CGF, const OMPDependClause *C) override
Emit code for doacross ordered directive with 'depend' clause.
void emitTaskyieldCall(CodeGenFunction &CGF, SourceLocation Loc) override
Emits a masked region.
Address getAddrOfArtificialThreadPrivate(CodeGenFunction &CGF, QualType VarType, StringRef Name) override
Creates artificial threadprivate variable with name Name and type VarType.
Address getAddrOfThreadPrivate(CodeGenFunction &CGF, const VarDecl *VD, Address VDAddr, SourceLocation Loc) override
Returns address of the threadprivate variable for the current thread.
void emitSingleRegion(CodeGenFunction &CGF, const RegionCodeGenTy &SingleOpGen, SourceLocation Loc, ArrayRef< const Expr * > CopyprivateVars, ArrayRef< const Expr * > DestExprs, ArrayRef< const Expr * > SrcExprs, ArrayRef< const Expr * > AssignmentOps) override
Emits a single region.
void emitTaskReductionFixups(CodeGenFunction &CGF, SourceLocation Loc, ReductionCodeGen &RCG, unsigned N) override
Required to resolve existing problems in the runtime.
llvm::Function * emitParallelOutlinedFunction(CodeGenFunction &CGF, const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) override
Emits outlined function for the specified OpenMP parallel directive D.
void emitCancellationPointCall(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind CancelRegion) override
Emit code for 'cancellation point' construct.
void emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind Kind, bool EmitChecks=true, bool ForceSimpleCall=false) override
Emit an implicit/explicit barrier for OpenMP threads.
Address getParameterAddress(CodeGenFunction &CGF, const VarDecl *NativeParam, const VarDecl *TargetParam) const override
Gets the address of the native argument basing on the address of the target-specific parameter.
void emitTeamsCall(CodeGenFunction &CGF, const OMPExecutableDirective &D, SourceLocation Loc, llvm::Function *OutlinedFn, ArrayRef< llvm::Value * > CapturedVars) override
Emits code for teams call of the OutlinedFn with variables captured in a record which address is stor...
void emitForOrderedIterationEnd(CodeGenFunction &CGF, SourceLocation Loc, unsigned IVSize, bool IVSigned) override
Call the appropriate runtime routine to notify that we finished iteration of the ordered loop with th...
bool emitTargetGlobal(GlobalDecl GD) override
Emit the global GD if it is meaningful for the target.
void emitTaskReductionFini(CodeGenFunction &CGF, SourceLocation Loc, bool IsWorksharingReduction) override
Emits the following code for reduction clause with task modifier:
void emitOrderedRegion(CodeGenFunction &CGF, const RegionCodeGenTy &OrderedOpGen, SourceLocation Loc, bool IsThreads) override
Emit an ordered region.
void emitForStaticFinish(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind DKind) override
Call the appropriate runtime routine to notify that we finished all the work with current loop.
llvm::Value * emitTaskReductionInit(CodeGenFunction &CGF, SourceLocation Loc, ArrayRef< const Expr * > LHSExprs, ArrayRef< const Expr * > RHSExprs, const OMPTaskDataTy &Data) override
Emit a code for initialization of task reduction clause.
void emitProcBindClause(CodeGenFunction &CGF, llvm::omp::ProcBindKind ProcBind, SourceLocation Loc) override
Emit call to void __kmpc_push_proc_bind(ident_t *loc, kmp_int32global_tid, int proc_bind) to generate...
void emitTargetOutlinedFunction(const OMPExecutableDirective &D, StringRef ParentName, llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID, bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) override
Emit outilined function for 'target' directive.
void emitMasterRegion(CodeGenFunction &CGF, const RegionCodeGenTy &MasterOpGen, SourceLocation Loc) override
Emits a master region.
void emitNumTeamsClause(CodeGenFunction &CGF, const Expr *NumTeams, const Expr *ThreadLimit, SourceLocation Loc) override
Emits call to void __kmpc_push_num_teams(ident_t *loc, kmp_int32global_tid, kmp_int32 num_teams,...
void emitForDispatchDeinit(CodeGenFunction &CGF, SourceLocation Loc) override
This is used for non static scheduled types and when the ordered clause is present on the loop constr...
const VarDecl * translateParameter(const FieldDecl *FD, const VarDecl *NativeParam) const override
Translates the native parameter of outlined function if this is required for target.
void emitNumThreadsClause(CodeGenFunction &CGF, llvm::Value *NumThreads, SourceLocation Loc, OpenMPNumThreadsClauseModifier Modifier=OMPC_NUMTHREADS_unknown, OpenMPSeverityClauseKind Severity=OMPC_SEVERITY_fatal, SourceLocation SeverityLoc=SourceLocation(), const Expr *Message=nullptr, SourceLocation MessageLoc=SourceLocation()) override
Emits call to void __kmpc_push_num_threads(ident_t *loc, kmp_int32global_tid, kmp_int32 num_threads) ...
void emitMaskedRegion(CodeGenFunction &CGF, const RegionCodeGenTy &MaskedOpGen, SourceLocation Loc, const Expr *Filter=nullptr) override
Emits a masked region.
void emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc, const OMPExecutableDirective &D, llvm::Function *TaskFunction, QualType SharedsTy, Address Shareds, const Expr *IfCond, const OMPTaskDataTy &Data) override
Emit task region for the task directive.
void emitTargetCall(CodeGenFunction &CGF, const OMPExecutableDirective &D, llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID, const Expr *IfCond, llvm::PointerIntPair< const Expr *, 2, OpenMPDeviceClauseModifier > Device, llvm::function_ref< llvm::Value *(CodeGenFunction &CGF, const OMPLoopDirective &D)> SizeEmitter) override
Emit the target offloading code associated with D.
bool emitTargetFunctions(GlobalDecl GD) override
Emit the target regions enclosed in GD function definition or the function itself in case it is a val...
void emitDoacrossInit(CodeGenFunction &CGF, const OMPLoopDirective &D, ArrayRef< Expr * > NumIterations) override
Emit initialization for doacross loop nesting support.
void emitCancelCall(CodeGenFunction &CGF, SourceLocation Loc, const Expr *IfCond, OpenMPDirectiveKind CancelRegion) override
Emit code for 'cancel' construct.
void emitTaskwaitCall(CodeGenFunction &CGF, SourceLocation Loc, const OMPTaskDataTy &Data) override
Emit code for 'taskwait' directive.
void emitTaskgroupRegion(CodeGenFunction &CGF, const RegionCodeGenTy &TaskgroupOpGen, SourceLocation Loc) override
Emit a taskgroup region.
void emitTargetDataCalls(CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, const Expr *Device, const RegionCodeGenTy &CodeGen, CGOpenMPRuntime::TargetDataInfo &Info) override
Emit the target data mapping code associated with D.
void emitForDispatchInit(CodeGenFunction &CGF, SourceLocation Loc, const OpenMPScheduleTy &ScheduleKind, unsigned IVSize, bool IVSigned, bool Ordered, const DispatchRTInput &DispatchValues) override
This is used for non static scheduled types and when the ordered clause is present on the loop constr...
llvm::Function * emitTaskOutlinedFunction(const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, const VarDecl *PartIDVar, const VarDecl *TaskTVar, OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen, bool Tied, unsigned &NumberOfParts) override
Emits outlined function for the OpenMP task directive D.
void emitTaskLoopCall(CodeGenFunction &CGF, SourceLocation Loc, const OMPLoopDirective &D, llvm::Function *TaskFunction, QualType SharedsTy, Address Shareds, const Expr *IfCond, const OMPTaskDataTy &Data) override
Emit task region for the taskloop directive.
unsigned getNonVirtualBaseLLVMFieldNo(const CXXRecordDecl *RD) const
llvm::StructType * getLLVMType() const
Return the "complete object" LLVM type associated with this record.
llvm::StructType * getBaseSubobjectLLVMType() const
Return the "base subobject" LLVM type associated with this record.
unsigned getLLVMFieldNo(const FieldDecl *FD) const
Return llvm::StructType element number that corresponds to the field FD.
unsigned getVirtualBaseIndex(const CXXRecordDecl *base) const
Return the LLVM field index corresponding to the given virtual base.
API for captured statement code generation.
virtual void EmitBody(CodeGenFunction &CGF, const Stmt *S)
Emit the captured statement body.
virtual const FieldDecl * lookup(const VarDecl *VD) const
Lookup the captured field decl for a variable.
RAII for correct setting/restoring of CapturedStmtInfo.
The scope used to remap some variables as private in the OpenMP loop body (or other captured region e...
bool Privatize()
Privatizes local variables previously registered as private.
bool addPrivate(const VarDecl *LocalVD, Address Addr)
Registers LocalVD variable as a private with Addr as the address of the corresponding private variabl...
An RAII object to set (and then clear) a mapping for an OpaqueValueExpr.
Enters a new scope for capturing cleanups, all of which will be executed once the scope is exited.
CodeGenFunction - This class organizes the per-function state that is used while generating LLVM code...
LValue EmitLoadOfReferenceLValue(LValue RefLVal)
void EmitBranchOnBoolExpr(const Expr *Cond, llvm::BasicBlock *TrueBlock, llvm::BasicBlock *FalseBlock, uint64_t TrueCount, Stmt::Likelihood LH=Stmt::LH_None, const Expr *ConditionalOp=nullptr, const VarDecl *ConditionalDecl=nullptr)
EmitBranchOnBoolExpr - Emit a branch on a boolean condition (e.g.
void emitDestroy(Address addr, QualType type, Destroyer *destroyer, bool useEHCleanupForArray)
emitDestroy - Immediately perform the destruction of the given object.
JumpDest getJumpDestInCurrentScope(llvm::BasicBlock *Target)
The given basic block lies in the current EH scope, but may be a target of a potentially scope-crossi...
static void EmitOMPTargetParallelDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetParallelDirective &S)
void EmitNullInitialization(Address DestPtr, QualType Ty)
EmitNullInitialization - Generate code to set a value of the given type to null, If the type contains...
Address LoadCXXThisAddress()
CGCapturedStmtInfo * CapturedStmtInfo
ComplexPairTy EmitLoadOfComplex(LValue src, SourceLocation loc)
EmitLoadOfComplex - Load a complex number from the specified l-value.
static void EmitOMPTargetDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetDirective &S)
Emit device code for the target directive.
static void EmitOMPTargetTeamsDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsDirective &S)
Emit device code for the target teams directive.
static void EmitOMPTargetTeamsDistributeDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsDistributeDirective &S)
Emit device code for the target teams distribute directive.
llvm::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...
std::optional< llvm::APSInt > getIntegerConstantExpr(const ASTContext &Ctx) const
isIntegerConstantExpr - Return the value if this expression is a valid integer constant expression.
bool HasSideEffects(const ASTContext &Ctx, bool IncludePossibleEffects=true) const
HasSideEffects - This routine returns true for all those expressions which have any effect other than...
bool EvaluateAsBooleanCondition(bool &Result, const ASTContext &Ctx, bool InConstantContext=false) const
EvaluateAsBooleanCondition - Return true if this is a constant which we can fold and convert to a boo...
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
static bool isSameComparisonOperand(const Expr *E1, const Expr *E2)
Checks that the two Expr's will refer to the same value as a comparison operand.
bool hasNonTrivialCall(const ASTContext &Ctx) const
Determine whether this expression involves a call to any function that is not trivial.
Represents a member of a struct/union/class.
unsigned getFieldIndex() const
Returns the index of this field within its record, as appropriate for passing to ASTRecordLayout::get...
const RecordDecl * getParent() const
Returns the parent of this field declaration, which is the struct in which this field is defined.
static FieldDecl * Create(const ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, const IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, Expr *BW, bool Mutable, InClassInitStyle InitStyle)
Represents a function declaration or definition.
const ParmVarDecl * getParamDecl(unsigned i) const
QualType getReturnType() const
ArrayRef< ParmVarDecl * > parameters() const
FunctionDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
FunctionDecl * getMostRecentDecl()
Returns the most recent (re)declaration of this declaration.
unsigned getNumParams() const
Return the number of parameters this function must have based on its FunctionType.
FunctionDecl * getPreviousDecl()
Return the previous declaration of this declaration or NULL if this is the first declaration.
GlobalDecl - represents a global declaration.
const Decl * getDecl() const
static ImplicitParamDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation IdLoc, 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.
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.
The JSON file list parser is used to communicate input to InstallAPI.
bool isOpenMPWorksharingDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a worksharing directive.
CanQual< Type > CanQualType
Represents a canonical, potentially-qualified type.
bool needsTaskBasedThreadLimit(OpenMPDirectiveKind DKind)
Checks if the specified target directive, combined or not, needs task based thread_limit.
@ Match
This is not an overload because the signature exactly matches an existing declaration.
@ Ctor_Complete
Complete object ctor.
Privates[]
This class represents the 'transparent' clause in the 'pragma omp task' directive.
bool isa(CodeGen::Address addr)
if(T->getSizeExpr()) TRY_TO(TraverseStmt(const_cast< Expr * >(T -> getSizeExpr())))
bool isOpenMPTargetDataManagementDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a target data offload directive.
static bool classof(const OMPClause *T)
@ Conditional
A conditional (?:) operator.
@ ICIS_NoInit
No in-class initializer.
bool isOpenMPDistributeDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a distribute directive.
@ LCK_ByRef
Capturing by reference.
LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE()
@ Private
'private' clause, allowed on 'parallel', 'serial', 'loop', 'parallel loop', and 'serial loop' constru...
@ Reduction
'reduction' clause, allowed on Parallel, Serial, Loop, and the combined constructs.
@ Present
'present' clause, allowed on Compute and Combined constructs, plus 'data' and 'declare'.
OpenMPScheduleClauseModifier
OpenMP modifiers for 'schedule' clause.
@ OMPC_SCHEDULE_MODIFIER_last
@ OMPC_SCHEDULE_MODIFIER_unknown
nullptr
This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...
bool isOpenMPParallelDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a parallel-kind directive.
OpenMPDistScheduleClauseKind
OpenMP attributes for 'dist_schedule' clause.
bool isOpenMPTaskingDirective(OpenMPDirectiveKind Kind)
Checks if the specified directive kind is one of tasking directives - task, taskloop,...
bool isOpenMPTargetExecutionDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a target code offload directive.
@ OMPC_DYN_GROUPPRIVATE_FALLBACK_unknown
@ Result
The result type of a method or function.
bool isOpenMPTeamsDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a teams-kind directive.
OpenMPDependClauseKind
OpenMP attributes for 'depend' clause.
@ Dtor_Complete
Complete object dtor.
@ Union
The "union" keyword.
bool isOpenMPTargetMapEnteringDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a map-entering target directive.
@ Type
The name was classified as a type.
bool isOpenMPLoopDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a directive with an associated loop construct.
OpenMPSeverityClauseKind
OpenMP attributes for 'severity' clause.
LangAS
Defines the address space values used by the address space qualifier of QualType.
llvm::omp::Directive OpenMPDirectiveKind
OpenMP directives.
bool isOpenMPSimdDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a simd directive.
@ VK_PRValue
A pr-value expression (in the C++11 taxonomy) produces a temporary value.
@ VK_LValue
An l-value expression is a reference to an object with independent storage.
for(const auto &A :T->param_types())
void getOpenMPCaptureRegions(llvm::SmallVectorImpl< OpenMPDirectiveKind > &CaptureRegions, OpenMPDirectiveKind DKind)
Return the captured regions of an OpenMP directive.
OpenMPNumThreadsClauseModifier
@ OMPC_ATOMIC_DEFAULT_MEM_ORDER_unknown
U cast(CodeGen::Address addr)
OpenMPMapModifierKind
OpenMP modifier kind for 'map' clause.
@ OMPC_MAP_MODIFIER_unknown
@ Other
Other implicit parameter.
OpenMPScheduleClauseKind
OpenMP attributes for 'schedule' clause.
bool isOpenMPTaskLoopDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a taskloop directive.
OpenMPThreadsetKind
OpenMP modifiers for 'threadset' clause.
OpenMPMapClauseKind
OpenMP mapping kind for 'map' clause.
Diagnostic wrappers for TextAPI types for error reporting.
__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.