31#include "llvm/ADT/ArrayRef.h"
32#include "llvm/ADT/SmallSet.h"
33#include "llvm/ADT/SmallVector.h"
34#include "llvm/ADT/StringExtras.h"
35#include "llvm/Bitcode/BitcodeReader.h"
36#include "llvm/IR/Constants.h"
37#include "llvm/IR/DerivedTypes.h"
38#include "llvm/IR/GlobalValue.h"
39#include "llvm/IR/InstrTypes.h"
40#include "llvm/IR/Value.h"
41#include "llvm/Support/AtomicOrdering.h"
42#include "llvm/Support/raw_ostream.h"
50using namespace llvm::omp;
57 enum CGOpenMPRegionKind {
60 ParallelOutlinedRegion,
70 CGOpenMPRegionInfo(
const CapturedStmt &CS,
71 const CGOpenMPRegionKind RegionKind,
74 : CGCapturedStmtInfo(CS,
CR_OpenMP), RegionKind(RegionKind),
75 CodeGen(CodeGen), Kind(Kind), HasCancel(HasCancel) {}
77 CGOpenMPRegionInfo(
const CGOpenMPRegionKind RegionKind,
80 : CGCapturedStmtInfo(
CR_OpenMP), RegionKind(RegionKind), CodeGen(CodeGen),
81 Kind(Kind), HasCancel(HasCancel) {}
85 virtual const VarDecl *getThreadIDVariable()
const = 0;
88 void EmitBody(CodeGenFunction &CGF,
const Stmt *S)
override;
92 virtual LValue getThreadIDVariableLValue(CodeGenFunction &CGF);
94 virtual void emitUntiedSwitch(CodeGenFunction & ) {}
96 CGOpenMPRegionKind getRegionKind()
const {
return RegionKind; }
100 bool hasCancel()
const {
return HasCancel; }
102 static bool classof(
const CGCapturedStmtInfo *Info) {
106 ~CGOpenMPRegionInfo()
override =
default;
109 CGOpenMPRegionKind RegionKind;
110 RegionCodeGenTy CodeGen;
116class CGOpenMPOutlinedRegionInfo final :
public CGOpenMPRegionInfo {
118 CGOpenMPOutlinedRegionInfo(
const CapturedStmt &CS,
const VarDecl *ThreadIDVar,
119 const RegionCodeGenTy &CodeGen,
121 StringRef HelperName)
122 : CGOpenMPRegionInfo(CS, ParallelOutlinedRegion, CodeGen,
Kind,
124 ThreadIDVar(ThreadIDVar), HelperName(HelperName) {
125 assert(ThreadIDVar !=
nullptr &&
"No ThreadID in OpenMP region.");
130 const VarDecl *getThreadIDVariable()
const override {
return ThreadIDVar; }
133 StringRef getHelperName()
const override {
return HelperName; }
135 static bool classof(
const CGCapturedStmtInfo *Info) {
136 return CGOpenMPRegionInfo::classof(Info) &&
138 ParallelOutlinedRegion;
144 const VarDecl *ThreadIDVar;
145 StringRef HelperName;
149class CGOpenMPTaskOutlinedRegionInfo final :
public CGOpenMPRegionInfo {
151 class UntiedTaskActionTy final :
public PrePostActionTy {
153 const VarDecl *PartIDVar;
154 const RegionCodeGenTy UntiedCodeGen;
155 llvm::SwitchInst *UntiedSwitch =
nullptr;
158 UntiedTaskActionTy(
bool Tied,
const VarDecl *PartIDVar,
159 const RegionCodeGenTy &UntiedCodeGen)
160 : Untied(!Tied), PartIDVar(PartIDVar), UntiedCodeGen(UntiedCodeGen) {}
161 void Enter(CodeGenFunction &CGF)
override {
166 PartIDVar->
getType()->castAs<PointerType>());
170 UntiedSwitch = CGF.
Builder.CreateSwitch(Res, DoneBB);
174 UntiedSwitch->addCase(CGF.
Builder.getInt32(0),
176 emitUntiedSwitch(CGF);
179 void emitUntiedSwitch(CodeGenFunction &CGF)
const {
183 PartIDVar->
getType()->castAs<PointerType>());
187 CodeGenFunction::JumpDest CurPoint =
191 UntiedSwitch->addCase(CGF.
Builder.getInt32(UntiedSwitch->getNumCases()),
197 unsigned getNumberOfParts()
const {
return UntiedSwitch->getNumCases(); }
199 CGOpenMPTaskOutlinedRegionInfo(
const CapturedStmt &CS,
200 const VarDecl *ThreadIDVar,
201 const RegionCodeGenTy &CodeGen,
203 const UntiedTaskActionTy &Action)
204 : CGOpenMPRegionInfo(CS, TaskOutlinedRegion, CodeGen,
Kind, HasCancel),
205 ThreadIDVar(ThreadIDVar), Action(Action) {
206 assert(ThreadIDVar !=
nullptr &&
"No ThreadID in OpenMP region.");
211 const VarDecl *getThreadIDVariable()
const override {
return ThreadIDVar; }
214 LValue getThreadIDVariableLValue(CodeGenFunction &CGF)
override;
217 StringRef getHelperName()
const override {
return ".omp_outlined."; }
219 void emitUntiedSwitch(CodeGenFunction &CGF)
override {
220 Action.emitUntiedSwitch(CGF);
223 static bool classof(
const CGCapturedStmtInfo *Info) {
224 return CGOpenMPRegionInfo::classof(Info) &&
232 const VarDecl *ThreadIDVar;
234 const UntiedTaskActionTy &Action;
239class CGOpenMPInlinedRegionInfo :
public CGOpenMPRegionInfo {
241 CGOpenMPInlinedRegionInfo(CodeGenFunction::CGCapturedStmtInfo *OldCSI,
242 const RegionCodeGenTy &CodeGen,
244 : CGOpenMPRegionInfo(InlinedRegion, CodeGen,
Kind, HasCancel),
246 OuterRegionInfo(dyn_cast_or_null<CGOpenMPRegionInfo>(OldCSI)) {}
249 llvm::Value *getContextValue()
const override {
251 return OuterRegionInfo->getContextValue();
252 llvm_unreachable(
"No context value for inlined OpenMP region");
255 void setContextValue(llvm::Value *
V)
override {
256 if (OuterRegionInfo) {
257 OuterRegionInfo->setContextValue(
V);
260 llvm_unreachable(
"No context value for inlined OpenMP region");
264 const FieldDecl *lookup(
const VarDecl *VD)
const override {
266 return OuterRegionInfo->lookup(VD);
272 FieldDecl *getThisFieldDecl()
const override {
274 return OuterRegionInfo->getThisFieldDecl();
280 const VarDecl *getThreadIDVariable()
const override {
282 return OuterRegionInfo->getThreadIDVariable();
287 LValue getThreadIDVariableLValue(CodeGenFunction &CGF)
override {
289 return OuterRegionInfo->getThreadIDVariableLValue(CGF);
290 llvm_unreachable(
"No LValue for inlined OpenMP construct");
294 StringRef getHelperName()
const override {
295 if (
auto *OuterRegionInfo = getOldCSI())
296 return OuterRegionInfo->getHelperName();
297 llvm_unreachable(
"No helper name for inlined OpenMP construct");
300 void emitUntiedSwitch(CodeGenFunction &CGF)
override {
302 OuterRegionInfo->emitUntiedSwitch(CGF);
305 CodeGenFunction::CGCapturedStmtInfo *getOldCSI()
const {
return OldCSI; }
307 static bool classof(
const CGCapturedStmtInfo *Info) {
308 return CGOpenMPRegionInfo::classof(Info) &&
312 ~CGOpenMPInlinedRegionInfo()
override =
default;
316 CodeGenFunction::CGCapturedStmtInfo *OldCSI;
317 CGOpenMPRegionInfo *OuterRegionInfo;
325class CGOpenMPTargetRegionInfo final :
public CGOpenMPRegionInfo {
327 CGOpenMPTargetRegionInfo(
const CapturedStmt &CS,
328 const RegionCodeGenTy &CodeGen, StringRef HelperName)
329 : CGOpenMPRegionInfo(CS, TargetRegion, CodeGen, OMPD_target,
331 HelperName(HelperName) {}
335 const VarDecl *getThreadIDVariable()
const override {
return nullptr; }
338 StringRef getHelperName()
const override {
return HelperName; }
340 static bool classof(
const CGCapturedStmtInfo *Info) {
341 return CGOpenMPRegionInfo::classof(Info) &&
346 StringRef HelperName;
350 llvm_unreachable(
"No codegen for expressions");
354class CGOpenMPInnerExprInfo final :
public CGOpenMPInlinedRegionInfo {
356 CGOpenMPInnerExprInfo(CodeGenFunction &CGF,
const CapturedStmt &CS)
357 : CGOpenMPInlinedRegionInfo(CGF.CapturedStmtInfo, EmptyCodeGen,
365 if (!C.capturesVariable() && !C.capturesVariableByCopy())
368 const VarDecl *VD = C.getCapturedVar();
369 if (VD->isLocalVarDeclOrParm())
372 DeclRefExpr DRE(CGF.getContext(), const_cast<VarDecl *>(VD),
374 VD->getType().getNonReferenceType(), VK_LValue,
376 PrivScope.addPrivate(VD, CGF.EmitLValue(&DRE).getAddress());
378 (
void)PrivScope.Privatize();
382 const FieldDecl *lookup(
const VarDecl *VD)
const override {
383 if (
const FieldDecl *FD = CGOpenMPInlinedRegionInfo::lookup(VD))
389 void EmitBody(CodeGenFunction &CGF,
const Stmt *S)
override {
390 llvm_unreachable(
"No body for expressions");
395 const VarDecl *getThreadIDVariable()
const override {
396 llvm_unreachable(
"No thread id for expressions");
400 StringRef getHelperName()
const override {
401 llvm_unreachable(
"No helper name for expressions");
404 static bool classof(
const CGCapturedStmtInfo *Info) {
return false; }
408 CodeGenFunction::OMPPrivateScope PrivScope;
412class InlinedOpenMPRegionRAII {
413 CodeGenFunction &CGF;
414 llvm::DenseMap<const ValueDecl *, FieldDecl *> LambdaCaptureFields;
415 FieldDecl *LambdaThisCaptureField =
nullptr;
416 const CodeGen::CGBlockInfo *BlockInfo =
nullptr;
417 bool NoInheritance =
false;
424 InlinedOpenMPRegionRAII(CodeGenFunction &CGF,
const RegionCodeGenTy &CodeGen,
426 bool NoInheritance =
true)
427 : CGF(CGF), NoInheritance(NoInheritance) {
429 CGF.CapturedStmtInfo =
new CGOpenMPInlinedRegionInfo(
430 CGF.CapturedStmtInfo, CodeGen, Kind, HasCancel);
432 std::swap(CGF.LambdaCaptureFields, LambdaCaptureFields);
433 LambdaThisCaptureField = CGF.LambdaThisCaptureField;
434 CGF.LambdaThisCaptureField =
nullptr;
435 BlockInfo = CGF.BlockInfo;
436 CGF.BlockInfo =
nullptr;
440 ~InlinedOpenMPRegionRAII() {
444 delete CGF.CapturedStmtInfo;
445 CGF.CapturedStmtInfo = OldCSI;
447 std::swap(CGF.LambdaCaptureFields, LambdaCaptureFields);
448 CGF.LambdaThisCaptureField = LambdaThisCaptureField;
449 CGF.BlockInfo = BlockInfo;
457enum OpenMPLocationFlags :
unsigned {
459 OMP_IDENT_IMD = 0x01,
461 OMP_IDENT_KMPC = 0x02,
463 OMP_ATOMIC_REDUCE = 0x10,
465 OMP_IDENT_BARRIER_EXPL = 0x20,
467 OMP_IDENT_BARRIER_IMPL = 0x40,
469 OMP_IDENT_BARRIER_IMPL_FOR = 0x40,
471 OMP_IDENT_BARRIER_IMPL_SECTIONS = 0xC0,
473 OMP_IDENT_BARRIER_IMPL_SINGLE = 0x140,
475 OMP_IDENT_WORK_LOOP = 0x200,
477 OMP_IDENT_WORK_SECTIONS = 0x400,
479 OMP_IDENT_WORK_DISTRIBUTE = 0x800,
509enum IdentFieldIndex {
511 IdentField_Reserved_1,
515 IdentField_Reserved_2,
517 IdentField_Reserved_3,
526enum OpenMPSchedType {
529 OMP_sch_static_chunked = 33,
531 OMP_sch_dynamic_chunked = 35,
532 OMP_sch_guided_chunked = 36,
533 OMP_sch_runtime = 37,
536 OMP_sch_static_balanced_chunked = 45,
539 OMP_ord_static_chunked = 65,
541 OMP_ord_dynamic_chunked = 67,
542 OMP_ord_guided_chunked = 68,
543 OMP_ord_runtime = 69,
545 OMP_sch_default = OMP_sch_static,
547 OMP_dist_sch_static_chunked = 91,
548 OMP_dist_sch_static = 92,
551 OMP_sch_modifier_monotonic = (1 << 29),
553 OMP_sch_modifier_nonmonotonic = (1 << 30),
558class CleanupTy final :
public EHScopeStack::Cleanup {
559 PrePostActionTy *Action;
562 explicit CleanupTy(PrePostActionTy *Action) : Action(Action) {}
563 void Emit(CodeGenFunction &CGF, Flags )
override {
576 Callback(CodeGen, CGF, *PrePostAction);
579 Callback(CodeGen, CGF, Action);
587 if (
const auto *CE = dyn_cast<CallExpr>(ReductionOp))
588 if (
const auto *OVE = dyn_cast<OpaqueValueExpr>(CE->getCallee()))
589 if (
const auto *DRE =
590 dyn_cast<DeclRefExpr>(OVE->getSourceExpr()->IgnoreImpCasts()))
591 if (
const auto *DRD = dyn_cast<OMPDeclareReductionDecl>(DRE->getDecl()))
602 std::pair<llvm::Function *, llvm::Function *>
Reduction =
622 auto *GV =
new llvm::GlobalVariable(
624 llvm::GlobalValue::PrivateLinkage,
Init, Name);
665 llvm::Value *NumElements = CGF.
emitArrayLength(ArrayTy, ElementTy, DestAddr);
669 llvm::Value *SrcBegin =
nullptr;
671 SrcBegin = SrcAddr.emitRawPointer(CGF);
674 llvm::Value *DestEnd =
679 llvm::Value *IsEmpty =
680 CGF.
Builder.CreateICmpEQ(DestBegin, DestEnd,
"omp.arrayinit.isempty");
681 CGF.
Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
684 llvm::BasicBlock *EntryBB = CGF.
Builder.GetInsertBlock();
689 llvm::PHINode *SrcElementPHI =
nullptr;
692 SrcElementPHI = CGF.
Builder.CreatePHI(SrcBegin->getType(), 2,
693 "omp.arraycpy.srcElementPast");
694 SrcElementPHI->addIncoming(SrcBegin, EntryBB);
696 Address(SrcElementPHI, SrcAddr.getElementType(),
697 SrcAddr.getAlignment().alignmentOfArrayElement(ElementSize));
699 llvm::PHINode *DestElementPHI = CGF.
Builder.CreatePHI(
700 DestBegin->getType(), 2,
"omp.arraycpy.destElementPast");
701 DestElementPHI->addIncoming(DestBegin, EntryBB);
709 if (EmitDeclareReductionInit) {
711 SrcElementCurrent, ElementTy);
719 llvm::Value *SrcElementNext = CGF.
Builder.CreateConstGEP1_32(
720 SrcAddr.getElementType(), SrcElementPHI, 1,
721 "omp.arraycpy.dest.element");
722 SrcElementPHI->addIncoming(SrcElementNext, CGF.
Builder.GetInsertBlock());
726 llvm::Value *DestElementNext = CGF.
Builder.CreateConstGEP1_32(
728 "omp.arraycpy.dest.element");
731 CGF.
Builder.CreateICmpEQ(DestElementNext, DestEnd,
"omp.arraycpy.done");
732 CGF.
Builder.CreateCondBr(Done, DoneBB, BodyBB);
733 DestElementPHI->addIncoming(DestElementNext, CGF.
Builder.GetInsertBlock());
745 if (
const auto *OASE = dyn_cast<ArraySectionExpr>(E))
750void ReductionCodeGen::emitAggregateInitialization(
752 const OMPDeclareReductionDecl *DRD) {
756 const auto *PrivateVD =
758 bool EmitDeclareReductionInit =
761 EmitDeclareReductionInit,
762 EmitDeclareReductionInit ? ClausesData[N].ReductionOp
763 : PrivateVD->getInit(),
771 ClausesData.reserve(Shareds.size());
772 SharedAddresses.reserve(Shareds.size());
773 Sizes.reserve(Shareds.size());
774 BaseDecls.reserve(Shareds.size());
775 const auto *IOrig = Origs.begin();
776 const auto *IPriv =
Privates.begin();
777 const auto *IRed = ReductionOps.begin();
778 for (
const Expr *Ref : Shareds) {
779 ClausesData.emplace_back(Ref, *IOrig, *IPriv, *IRed);
780 std::advance(IOrig, 1);
781 std::advance(IPriv, 1);
782 std::advance(IRed, 1);
787 assert(SharedAddresses.size() == N && OrigAddresses.size() == N &&
788 "Number of generated lvalues must be exactly N.");
789 LValue First = emitSharedLValue(CGF, ClausesData[N].Shared);
790 LValue Second = emitSharedLValueUB(CGF, ClausesData[N].Shared);
791 SharedAddresses.emplace_back(
First, Second);
792 if (ClausesData[N].Shared == ClausesData[N].Ref) {
793 OrigAddresses.emplace_back(
First, Second);
795 LValue First = emitSharedLValue(CGF, ClausesData[N].Ref);
796 LValue Second = emitSharedLValueUB(CGF, ClausesData[N].Ref);
797 OrigAddresses.emplace_back(
First, Second);
806 CGF.
getTypeSize(OrigAddresses[N].first.getType().getNonReferenceType()),
811 llvm::Value *SizeInChars;
812 auto *ElemType = OrigAddresses[N].first.getAddress().getElementType();
813 auto *ElemSizeOf = llvm::ConstantExpr::getSizeOf(ElemType);
814 if (AsArraySection) {
815 Size = CGF.
Builder.CreatePtrDiff(ElemType,
816 OrigAddresses[N].second.getPointer(CGF),
817 OrigAddresses[N].first.getPointer(CGF));
818 Size = CGF.
Builder.CreateNUWAdd(
819 Size, llvm::ConstantInt::get(Size->getType(), 1));
820 SizeInChars = CGF.
Builder.CreateNUWMul(Size, ElemSizeOf);
823 CGF.
getTypeSize(OrigAddresses[N].first.getType().getNonReferenceType());
824 Size = CGF.
Builder.CreateExactUDiv(SizeInChars, ElemSizeOf);
826 Sizes.emplace_back(SizeInChars, Size);
839 assert(!Size && !Sizes[N].second &&
840 "Size should be nullptr for non-variably modified reduction "
855 assert(SharedAddresses.size() > N &&
"No variable was generated");
856 const auto *PrivateVD =
862 (void)DefaultInit(CGF);
863 emitAggregateInitialization(CGF, N, PrivateAddr, SharedAddr, DRD);
864 }
else if (DRD && (DRD->
getInitializer() || !PrivateVD->hasInit())) {
865 (void)DefaultInit(CGF);
866 QualType SharedType = SharedAddresses[N].first.getType();
868 PrivateAddr, SharedAddr, SharedType);
869 }
else if (!DefaultInit(CGF) && PrivateVD->hasInit() &&
872 PrivateVD->
getType().getQualifiers(),
890 CGF.
pushDestroy(DTorKind, PrivateAddr, PrivateType);
909 BaseLV.getType(), BaseLV.getBaseInfo(),
943 const VarDecl *OrigVD =
nullptr;
944 if (
const auto *OASE = dyn_cast<ArraySectionExpr>(Ref)) {
945 const Expr *
Base = OASE->getBase()->IgnoreParenImpCasts();
946 while (
const auto *TempOASE = dyn_cast<ArraySectionExpr>(
Base))
947 Base = TempOASE->getBase()->IgnoreParenImpCasts();
948 while (
const auto *TempASE = dyn_cast<ArraySubscriptExpr>(
Base))
949 Base = TempASE->getBase()->IgnoreParenImpCasts();
952 }
else if (
const auto *ASE = dyn_cast<ArraySubscriptExpr>(Ref)) {
953 const Expr *
Base = ASE->getBase()->IgnoreParenImpCasts();
954 while (
const auto *TempASE = dyn_cast<ArraySubscriptExpr>(
Base))
955 Base = TempASE->getBase()->IgnoreParenImpCasts();
966 BaseDecls.emplace_back(OrigVD);
969 loadToBegin(CGF, OrigVD->getType(), SharedAddresses[N].first.getType(),
971 Address SharedAddr = SharedAddresses[N].first.getAddress();
972 llvm::Value *Adjustment = CGF.
Builder.CreatePtrDiff(
975 llvm::Value *PrivatePointer =
981 SharedAddresses[N].first.getType(),
984 BaseDecls.emplace_back(
998 getThreadIDVariable()->
getType()->castAs<PointerType>());
1016LValue CGOpenMPTaskOutlinedRegionInfo::getThreadIDVariableLValue(
1019 getThreadIDVariable()->
getType(),
1037 llvm::OpenMPIRBuilderConfig Config(
1038 CGM.getLangOpts().OpenMPIsTargetDevice,
isGPU(),
1039 CGM.getLangOpts().OpenMPOffloadMandatory,
1042 Config.setDefaultTargetAS(
1044 Config.setRuntimeCC(
CGM.getRuntimeCC());
1049 CGM.getLangOpts().OpenMPIsTargetDevice
1050 ?
CGM.getLangOpts().OMPHostIRFile
1055 if (
CGM.getLangOpts().OpenMPForceUSM) {
1057 OMPBuilder.Config.setHasRequiresUnifiedSharedMemory(
true);
1065 if (!
Data.getValue().pointsToAliveValue())
1067 auto *GV = dyn_cast<llvm::GlobalVariable>(
Data.getValue());
1070 if (!GV->isDeclaration() || GV->getNumUses() > 0)
1072 GV->eraseFromParent();
1077 return OMPBuilder.createPlatformSpecificName(Parts);
1080static llvm::Function *
1082 const Expr *CombinerInitializer,
const VarDecl *In,
1083 const VarDecl *Out,
bool IsCombiner) {
1086 QualType PtrTy =
C.getPointerType(Ty).withRestrict();
1092 Args.push_back(&OmpOutParm);
1093 Args.push_back(&OmpInParm);
1098 {IsCombiner ?
"omp_combiner" :
"omp_initializer",
""});
1099 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
1103 Fn->addFnAttr(
"sample-profile-suffix-elision-policy",
"selected");
1105 Fn->removeFnAttr(llvm::Attribute::NoInline);
1106 Fn->removeFnAttr(llvm::Attribute::OptimizeNone);
1107 Fn->addFnAttr(llvm::Attribute::AlwaysInline);
1113 Out->getLocation());
1123 (void)
Scope.Privatize();
1124 if (!IsCombiner && Out->hasInit() &&
1127 Out->getType().getQualifiers(),
1130 if (CombinerInitializer)
1132 Scope.ForceCleanup();
1161std::pair<llvm::Function *, llvm::Function *>
1173struct PushAndPopStackRAII {
1174 PushAndPopStackRAII(llvm::OpenMPIRBuilder *OMPBuilder,
CodeGenFunction &CGF,
1175 bool HasCancel, llvm::omp::Directive Kind)
1176 : OMPBuilder(OMPBuilder) {
1192 auto FiniCB = [&CGF](llvm::OpenMPIRBuilder::InsertPointTy IP) {
1193 assert(IP.getBlock()->end() == IP.getPoint() &&
1194 "Clang CG should cause non-terminated block!");
1195 CGBuilderTy::InsertPointGuard IPG(CGF.
Builder);
1200 return llvm::Error::success();
1205 llvm::OpenMPIRBuilder::FinalizationInfo FI({FiniCB, Kind, HasCancel});
1206 OMPBuilder->pushFinalizationCB(std::move(FI));
1208 ~PushAndPopStackRAII() {
1210 OMPBuilder->popFinalizationCB();
1212 llvm::OpenMPIRBuilder *OMPBuilder;
1221 "thread id variable must be of type kmp_int32 *");
1223 bool HasCancel =
false;
1224 if (
const auto *OPD = dyn_cast<OMPParallelDirective>(&D))
1225 HasCancel = OPD->hasCancel();
1226 else if (
const auto *OPD = dyn_cast<OMPTargetParallelDirective>(&D))
1227 HasCancel = OPD->hasCancel();
1228 else if (
const auto *OPSD = dyn_cast<OMPParallelSectionsDirective>(&D))
1229 HasCancel = OPSD->hasCancel();
1230 else if (
const auto *OPFD = dyn_cast<OMPParallelForDirective>(&D))
1231 HasCancel = OPFD->hasCancel();
1232 else if (
const auto *OPFD = dyn_cast<OMPTargetParallelForDirective>(&D))
1233 HasCancel = OPFD->hasCancel();
1234 else if (
const auto *OPFD = dyn_cast<OMPDistributeParallelForDirective>(&D))
1235 HasCancel = OPFD->hasCancel();
1236 else if (
const auto *OPFD =
1237 dyn_cast<OMPTeamsDistributeParallelForDirective>(&D))
1238 HasCancel = OPFD->hasCancel();
1239 else if (
const auto *OPFD =
1240 dyn_cast<OMPTargetTeamsDistributeParallelForDirective>(&D))
1241 HasCancel = OPFD->hasCancel();
1246 PushAndPopStackRAII PSR(&OMPBuilder, CGF, HasCancel, InnermostKind);
1247 CGOpenMPOutlinedRegionInfo CGInfo(*CS, ThreadIDVar,
CodeGen, InnermostKind,
1248 HasCancel, OutlinedHelperName);
1254 std::string Suffix =
getName({
"omp_outlined"});
1255 return (Name + Suffix).str();
1263 std::string Suffix =
getName({
"omp",
"reduction",
"reduction_func"});
1264 return (Name + Suffix).str();
1271 const CapturedStmt *CS = D.getCapturedStmt(OMPD_parallel);
1281 const CapturedStmt *CS = D.getCapturedStmt(OMPD_teams);
1291 bool Tied,
unsigned &NumberOfParts) {
1294 llvm::Value *ThreadID =
getThreadID(CGF, D.getBeginLoc());
1296 llvm::Value *TaskArgs[] = {
1298 CGF.EmitLoadOfPointerLValue(CGF.GetAddrOfLocalVar(TaskTVar),
1301 CGF.EmitRuntimeCall(
OMPBuilder.getOrCreateRuntimeFunction(
1302 CGM.getModule(), OMPRTL___kmpc_omp_task),
1305 CGOpenMPTaskOutlinedRegionInfo::UntiedTaskActionTy Action(Tied, PartIDVar,
1309 "thread id variable must be of type kmp_int32 for tasks");
1314 bool HasCancel =
false;
1315 if (
const auto *TD = dyn_cast<OMPTaskDirective>(&D))
1316 HasCancel = TD->hasCancel();
1317 else if (
const auto *TD = dyn_cast<OMPTaskLoopDirective>(&D))
1318 HasCancel = TD->hasCancel();
1319 else if (
const auto *TD = dyn_cast<OMPMasterTaskLoopDirective>(&D))
1320 HasCancel = TD->hasCancel();
1321 else if (
const auto *TD = dyn_cast<OMPParallelMasterTaskLoopDirective>(&D))
1322 HasCancel = TD->hasCancel();
1325 CGOpenMPTaskOutlinedRegionInfo CGInfo(*CS, ThreadIDVar,
CodeGen,
1326 InnermostKind, HasCancel, Action);
1328 llvm::Function *Res = CGF.GenerateCapturedStmtFunction(*CS);
1330 NumberOfParts = Action.getNumberOfParts();
1335 bool AtCurrentPoint) {
1337 assert(!Elem.ServiceInsertPt &&
"Insert point is set already.");
1339 llvm::Value *Undef = llvm::UndefValue::get(CGF.
Int32Ty);
1340 if (AtCurrentPoint) {
1341 Elem.ServiceInsertPt =
new llvm::BitCastInst(Undef, CGF.
Int32Ty,
"svcpt",
1342 CGF.
Builder.GetInsertBlock());
1344 Elem.ServiceInsertPt =
new llvm::BitCastInst(Undef, CGF.
Int32Ty,
"svcpt");
1345 Elem.ServiceInsertPt->insertAfter(CGF.
AllocaInsertPt->getIterator());
1351 if (Elem.ServiceInsertPt) {
1352 llvm::Instruction *Ptr = Elem.ServiceInsertPt;
1353 Elem.ServiceInsertPt =
nullptr;
1354 Ptr->eraseFromParent();
1361 llvm::raw_svector_ostream OS(Buffer);
1370 if (
const auto *FD = dyn_cast_or_null<FunctionDecl>(CGF.
CurFuncDecl))
1371 OS << FD->getQualifiedNameAsString();
1378 unsigned Flags,
bool EmitLoc) {
1379 uint32_t SrcLocStrSize;
1380 llvm::Constant *SrcLocStr;
1381 if ((!EmitLoc &&
CGM.getCodeGenOpts().getDebugInfo() ==
1382 llvm::codegenoptions::NoDebugInfo) ||
1384 SrcLocStr =
OMPBuilder.getOrCreateDefaultSrcLocStr(SrcLocStrSize);
1386 std::string FunctionName;
1388 if (
const auto *FD = dyn_cast_or_null<FunctionDecl>(CGF.
CurFuncDecl))
1389 FunctionName = FD->getQualifiedNameAsString();
1402 SrcLocStr, SrcLocStrSize, llvm::omp::IdentFlag(Flags), Reserved2Flags);
1407 assert(CGF.
CurFn &&
"No function in current CodeGenFunction.");
1410 if (
CGM.getLangOpts().OpenMPIRBuilder) {
1413 uint32_t SrcLocStrSize;
1414 auto *SrcLocStr =
OMPBuilder.getOrCreateSrcLocStr(
1417 OMPBuilder.getOrCreateIdent(SrcLocStr, SrcLocStrSize));
1420 llvm::Value *ThreadID =
nullptr;
1425 ThreadID = I->second.ThreadID;
1426 if (ThreadID !=
nullptr)
1430 if (
auto *OMPRegionInfo =
1432 if (OMPRegionInfo->getThreadIDVariable()) {
1434 LValue LVal = OMPRegionInfo->getThreadIDVariableLValue(CGF);
1438 CGF.
Builder.GetInsertBlock() == TopBlock ||
1443 CGF.
Builder.GetInsertBlock()) {
1447 if (CGF.
Builder.GetInsertBlock() == TopBlock)
1459 if (!Elem.ServiceInsertPt)
1461 CGBuilderTy::InsertPointGuard IPG(CGF.
Builder);
1462 CGF.
Builder.SetInsertPoint(Elem.ServiceInsertPt);
1466 OMPRTL___kmpc_global_thread_num),
1469 Elem.ThreadID =
Call;
1474 assert(CGF.
CurFn &&
"No function in current CodeGenFunction.");
1480 for (
const auto *D : I->second)
1485 for (
const auto *D : I->second)
1497static llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseKind
1499 std::optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
1500 OMPDeclareTargetDeclAttr::getDeviceType(VD);
1502 return llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseNone;
1504 switch ((
int)*DevTy) {
1505 case OMPDeclareTargetDeclAttr::DT_Host:
1506 return llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseHost;
1508 case OMPDeclareTargetDeclAttr::DT_NoHost:
1509 return llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseNoHost;
1511 case OMPDeclareTargetDeclAttr::DT_Any:
1512 return llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseAny;
1515 return llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseNone;
1520static llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryKind
1522 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> MapType =
1523 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
1525 return llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryNone;
1526 switch ((
int)*MapType) {
1527 case OMPDeclareTargetDeclAttr::MapTypeTy::MT_To:
1528 return llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryTo;
1530 case OMPDeclareTargetDeclAttr::MapTypeTy::MT_Enter:
1531 return llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryEnter;
1533 case OMPDeclareTargetDeclAttr::MapTypeTy::MT_Link:
1534 return llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryLink;
1537 return llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryNone;
1546 auto FileInfoCallBack = [&]() {
1551 PLoc =
SM.getPresumedLoc(BeginLoc,
false);
1556 return OMPBuilder.getTargetEntryUniqueInfo(FileInfoCallBack,
1561 auto AddrOfGlobal = [&VD,
this]() {
return CGM.GetAddrOfGlobal(VD); };
1563 auto LinkageForVariable = [&VD,
this]() {
1564 return CGM.getLLVMLinkageVarDefinition(VD);
1567 std::vector<llvm::GlobalVariable *> GeneratedRefs;
1569 llvm::Type *LlvmPtrTy =
CGM.getTypes().ConvertTypeForMem(
1570 CGM.getContext().getPointerType(VD->
getType()));
1571 llvm::Constant *addr =
OMPBuilder.getAddrOfDeclareTargetVar(
1577 CGM.getMangledName(VD), GeneratedRefs,
CGM.getLangOpts().OpenMPSimd,
1578 CGM.getLangOpts().OMPTargetTriples, LlvmPtrTy, AddrOfGlobal,
1579 LinkageForVariable);
1588 assert(!
CGM.getLangOpts().OpenMPUseTLS ||
1589 !
CGM.getContext().getTargetInfo().isTLSSupported());
1591 std::string Suffix =
getName({
"cache",
""});
1592 return OMPBuilder.getOrCreateInternalVariable(
1593 CGM.Int8PtrPtrTy, Twine(
CGM.getMangledName(VD)).concat(Suffix).str());
1600 if (
CGM.getLangOpts().OpenMPUseTLS &&
1601 CGM.getContext().getTargetInfo().isTLSSupported())
1605 llvm::Value *Args[] = {
1608 CGM.getSize(
CGM.GetTargetTypeStoreSize(VarTy)),
1613 CGM.getModule(), OMPRTL___kmpc_threadprivate_cached),
1625 CGM.getModule(), OMPRTL___kmpc_global_thread_num),
1629 llvm::Value *Args[] = {
1632 Ctor, CopyCtor, Dtor};
1635 CGM.getModule(), OMPRTL___kmpc_threadprivate_register),
1642 if (
CGM.getLangOpts().OpenMPUseTLS &&
1643 CGM.getContext().getTargetInfo().isTLSSupported())
1650 llvm::Value *Ctor =
nullptr, *CopyCtor =
nullptr, *Dtor =
nullptr;
1652 if (
CGM.getLangOpts().CPlusPlus && PerformInit) {
1658 nullptr,
CGM.getContext().VoidPtrTy,
1660 Args.push_back(&Dst);
1662 const auto &FI =
CGM.getTypes().arrangeBuiltinFunctionDeclaration(
1663 CGM.getContext().VoidPtrTy, Args);
1664 llvm::FunctionType *FTy =
CGM.getTypes().GetFunctionType(FI);
1665 std::string Name =
getName({
"__kmpc_global_ctor_",
""});
1666 llvm::Function *Fn =
1667 CGM.CreateGlobalInitOrCleanUpFunction(FTy, Name, FI, Loc);
1690 nullptr,
CGM.getContext().VoidPtrTy,
1692 Args.push_back(&Dst);
1694 const auto &FI =
CGM.getTypes().arrangeBuiltinFunctionDeclaration(
1695 CGM.getContext().VoidTy, Args);
1696 llvm::FunctionType *FTy =
CGM.getTypes().GetFunctionType(FI);
1697 std::string Name =
getName({
"__kmpc_global_dtor_",
""});
1698 llvm::Function *Fn =
1699 CGM.CreateGlobalInitOrCleanUpFunction(FTy, Name, FI, Loc);
1722 CopyCtor = llvm::Constant::getNullValue(
CGM.DefaultPtrTy);
1723 if (Ctor ==
nullptr) {
1724 Ctor = llvm::Constant::getNullValue(
CGM.DefaultPtrTy);
1726 if (Dtor ==
nullptr) {
1727 Dtor = llvm::Constant::getNullValue(
CGM.DefaultPtrTy);
1730 auto *InitFunctionTy =
1731 llvm::FunctionType::get(
CGM.VoidTy,
false);
1732 std::string Name =
getName({
"__omp_threadprivate_init_",
""});
1733 llvm::Function *InitFunction =
CGM.CreateGlobalInitOrCleanUpFunction(
1734 InitFunctionTy, Name,
CGM.getTypes().arrangeNullaryFunction());
1738 CGM.getTypes().arrangeNullaryFunction(), ArgList,
1742 return InitFunction;
1750 llvm::GlobalValue *GV) {
1751 std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr =
1752 OMPDeclareTargetDeclAttr::getActiveAttr(FD);
1755 if (!ActiveAttr || !(*ActiveAttr)->getIndirect())
1762 OMPBuilder.OffloadInfoManager.getTargetRegionEntryFnName(Name, EntryInfo);
1768 llvm::GlobalValue *
Addr = GV;
1769 if (
CGM.getLangOpts().OpenMPIsTargetDevice) {
1770 llvm::PointerType *FnPtrTy = llvm::PointerType::get(
1771 CGM.getLLVMContext(),
1772 CGM.getModule().getDataLayout().getProgramAddressSpace());
1773 Addr =
new llvm::GlobalVariable(
1774 CGM.getModule(), FnPtrTy,
1775 true, llvm::GlobalValue::ExternalLinkage, GV, Name,
1776 nullptr, llvm::GlobalValue::NotThreadLocal,
1777 CGM.getModule().getDataLayout().getDefaultGlobalsAddressSpace());
1778 Addr->setVisibility(llvm::GlobalValue::ProtectedVisibility);
1785 OMPBuilder.OffloadInfoManager.registerDeviceGlobalVarEntryInfo(
1786 Name,
Addr,
CGM.GetTargetTypeStoreSize(
CGM.VoidPtrTy).getQuantity(),
1787 llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryIndirect,
1788 llvm::GlobalValue::WeakODRLinkage);
1801 llvm::OpenMPIRBuilder &
OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
1817 llvm::GlobalVariable *
Addr = VTable;
1819 OMPBuilder.OffloadInfoManager.getTargetRegionEntryFnName(AddrName, EntryInfo);
1820 AddrName.append(
"addr");
1822 if (
CGM.getLangOpts().OpenMPIsTargetDevice) {
1823 Addr =
new llvm::GlobalVariable(
1824 CGM.getModule(), VTable->getType(),
1825 true, llvm::GlobalValue::ExternalLinkage, VTable,
1827 nullptr, llvm::GlobalValue::NotThreadLocal,
1828 CGM.getModule().getDataLayout().getDefaultGlobalsAddressSpace());
1829 Addr->setVisibility(llvm::GlobalValue::ProtectedVisibility);
1831 OMPBuilder.OffloadInfoManager.registerDeviceGlobalVarEntryInfo(
1833 CGM.getDataLayout().getTypeAllocSize(VTable->getInitializer()->getType()),
1834 llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryIndirectVTable,
1835 llvm::GlobalValue::WeakODRLinkage);
1844 !
CGM.getOpenMPRuntime().VTableDeclMap.contains(
CXXRecord)) {
1845 auto Res =
CGM.getOpenMPRuntime().VTableDeclMap.try_emplace(
CXXRecord, VD);
1850 assert(VTablesAddr &&
"Expected non-null VTable address");
1851 CGM.getOpenMPRuntime().registerVTableOffloadEntry(VTablesAddr, VD);
1869 auto GetVTableDecl = [](
const Expr *E) {
1880 if (
auto *DRE = dyn_cast<DeclRefExpr>(E)) {
1882 }
else if (
auto *MRE = dyn_cast<MemberExpr>(E)) {
1883 if (
auto *BaseDRE = dyn_cast<DeclRefExpr>(MRE->getBase())) {
1884 if (
auto *BaseVD = dyn_cast<VarDecl>(BaseDRE->getDecl()))
1888 return std::pair<CXXRecordDecl *, const VarDecl *>(
CXXRecord, VD);
1892 for (
const auto *E :
C->varlist()) {
1893 auto DeclPair = GetVTableDecl(E);
1895 if (DeclPair.second)
1904 std::string Suffix =
getName({
"artificial",
""});
1906 llvm::GlobalVariable *GAddr =
OMPBuilder.getOrCreateInternalVariable(
1907 VarLVType, Twine(Name).concat(Suffix).str());
1908 if (
CGM.getLangOpts().OpenMP &&
CGM.getLangOpts().OpenMPUseTLS &&
1909 CGM.getTarget().isTLSSupported()) {
1910 GAddr->setThreadLocal(
true);
1911 return Address(GAddr, GAddr->getValueType(),
1912 CGM.getContext().getTypeAlignInChars(VarType));
1914 std::string CacheSuffix =
getName({
"cache",
""});
1915 llvm::Value *Args[] = {
1923 Twine(Name).concat(Suffix).concat(CacheSuffix).str())};
1928 CGM.getModule(), OMPRTL___kmpc_threadprivate_cached),
1931 VarLVType,
CGM.getContext().getTypeAlignInChars(VarType));
1981 auto &M =
CGM.getModule();
1982 auto &&ThenGen = [&M, OutlinedFn, CapturedVars, RTLoc,
1985 llvm::Value *Args[] = {
1987 CGF.
Builder.getInt32(CapturedVars.size()),
1990 RealArgs.append(std::begin(Args), std::end(Args));
1991 RealArgs.append(CapturedVars.begin(), CapturedVars.end());
1993 llvm::FunctionCallee RTLFn =
1994 OMPBuilder.getOrCreateRuntimeFunction(M, OMPRTL___kmpc_fork_call);
1997 auto &&ElseGen = [&M, OutlinedFn, CapturedVars, RTLoc, Loc,
2003 llvm::Value *Args[] = {RTLoc, ThreadID};
2005 M, OMPRTL___kmpc_serialized_parallel),
2012 ".bound.zero.addr");
2017 OutlinedFnArgs.push_back(ZeroAddrBound.
getPointer());
2018 OutlinedFnArgs.append(CapturedVars.begin(), CapturedVars.end());
2026 OutlinedFn->removeFnAttr(llvm::Attribute::AlwaysInline);
2027 OutlinedFn->addFnAttr(llvm::Attribute::NoInline);
2033 M, OMPRTL___kmpc_end_serialized_parallel),
2052 if (
auto *OMPRegionInfo =
2054 if (OMPRegionInfo->getThreadIDVariable())
2055 return OMPRegionInfo->getThreadIDVariableLValue(CGF).getAddress();
2064 return ThreadIDTemp;
2068 std::string Prefix = Twine(
"gomp_critical_user_", CriticalName).str();
2069 std::string Name =
getName({Prefix,
"var"});
2076 llvm::FunctionCallee EnterCallee;
2078 llvm::FunctionCallee ExitCallee;
2081 llvm::BasicBlock *ContBlock =
nullptr;
2084 CommonActionTy(llvm::FunctionCallee EnterCallee,
2086 llvm::FunctionCallee ExitCallee,
2088 : EnterCallee(EnterCallee), EnterArgs(EnterArgs), ExitCallee(ExitCallee),
2093 llvm::Value *CallBool = CGF.
Builder.CreateIsNotNull(EnterRes);
2097 CGF.
Builder.CreateCondBr(CallBool, ThenBlock, ContBlock);
2101 void Done(CodeGenFunction &CGF) {
2106 void Exit(CodeGenFunction &CGF)
override {
2113 StringRef CriticalName,
2122 llvm::FunctionCallee RuntimeFcn =
OMPBuilder.getOrCreateRuntimeFunction(
2124 Hint ? OMPRTL___kmpc_critical_with_hint : OMPRTL___kmpc_critical);
2126 unsigned LockVarArgIdx = 2;
2128 RuntimeFcn.getFunctionType()
2129 ->getParamType(LockVarArgIdx)
2130 ->getPointerAddressSpace())
2132 LockVar, RuntimeFcn.getFunctionType()->getParamType(LockVarArgIdx));
2138 EnterArgs.push_back(CGF.
Builder.CreateIntCast(
2141 CommonActionTy Action(RuntimeFcn, EnterArgs,
2143 CGM.getModule(), OMPRTL___kmpc_end_critical),
2160 CommonActionTy Action(
OMPBuilder.getOrCreateRuntimeFunction(
2161 CGM.getModule(), OMPRTL___kmpc_master),
2164 CGM.getModule(), OMPRTL___kmpc_end_master),
2182 llvm::Value *FilterVal = Filter
2184 : llvm::ConstantInt::get(
CGM.Int32Ty, 0);
2189 CommonActionTy Action(
OMPBuilder.getOrCreateRuntimeFunction(
2190 CGM.getModule(), OMPRTL___kmpc_masked),
2193 CGM.getModule(), OMPRTL___kmpc_end_masked),
2209 llvm::Value *Args[] = {
2211 llvm::ConstantInt::get(
CGM.IntTy, 0,
true)};
2213 CGM.getModule(), OMPRTL___kmpc_omp_taskyield),
2217 if (
auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.
CapturedStmtInfo))
2218 Region->emitUntiedSwitch(CGF);
2231 CommonActionTy Action(
OMPBuilder.getOrCreateRuntimeFunction(
2232 CGM.getModule(), OMPRTL___kmpc_taskgroup),
2235 CGM.getModule(), OMPRTL___kmpc_end_taskgroup),
2244 unsigned Index,
const VarDecl *Var) {
2265 Args.push_back(&LHSArg);
2266 Args.push_back(&RHSArg);
2272 llvm::GlobalValue::InternalLinkage, Name,
2276 Fn->addFnAttr(
"sample-profile-suffix-elision-policy",
"selected");
2277 Fn->setDoesNotRecurse();
2294 for (
unsigned I = 0, E = AssignmentOps.size(); I < E; ++I) {
2295 const auto *DestVar =
2299 const auto *SrcVar =
2305 CGF.
EmitOMPCopy(
Type, DestAddr, SrcAddr, DestVar, SrcVar, AssignmentOps[I]);
2320 assert(CopyprivateVars.size() == SrcExprs.size() &&
2321 CopyprivateVars.size() == DstExprs.size() &&
2322 CopyprivateVars.size() == AssignmentOps.size());
2334 if (!CopyprivateVars.empty()) {
2337 C.getIntTypeForBitwidth(32, 1);
2338 DidIt = CGF.
CreateMemTemp(KmpInt32Ty,
".omp.copyprivate.did_it");
2343 CommonActionTy Action(
OMPBuilder.getOrCreateRuntimeFunction(
2344 CGM.getModule(), OMPRTL___kmpc_single),
2347 CGM.getModule(), OMPRTL___kmpc_end_single),
2360 llvm::APInt ArraySize(32, CopyprivateVars.size());
2361 QualType CopyprivateArrayTy =
C.getConstantArrayType(
2366 CGF.
CreateMemTemp(CopyprivateArrayTy,
".omp.copyprivate.cpr_list");
2367 for (
unsigned I = 0, E = CopyprivateVars.size(); I < E; ++I) {
2379 SrcExprs, DstExprs, AssignmentOps, Loc);
2380 llvm::Value *BufSize = CGF.
getTypeSize(CopyprivateArrayTy);
2384 llvm::Value *Args[] = {
2388 CL.emitRawPointer(CGF),
2393 CGM.getModule(), OMPRTL___kmpc_copyprivate),
2409 CommonActionTy Action(
OMPBuilder.getOrCreateRuntimeFunction(
2410 CGM.getModule(), OMPRTL___kmpc_ordered),
2413 CGM.getModule(), OMPRTL___kmpc_end_ordered),
2424 if (Kind == OMPD_for)
2425 Flags = OMP_IDENT_BARRIER_IMPL_FOR;
2426 else if (Kind == OMPD_sections)
2427 Flags = OMP_IDENT_BARRIER_IMPL_SECTIONS;
2428 else if (Kind == OMPD_single)
2429 Flags = OMP_IDENT_BARRIER_IMPL_SINGLE;
2430 else if (Kind == OMPD_barrier)
2431 Flags = OMP_IDENT_BARRIER_EXPL;
2433 Flags = OMP_IDENT_BARRIER_IMPL;
2443 S.getClausesOfKind<OMPOrderedClause>(),
2444 [](
const OMPOrderedClause *
C) { return C->getNumForLoops(); })) {
2445 ScheduleKind = OMPC_SCHEDULE_static;
2447 llvm::APInt ChunkSize(32, 1);
2457 bool ForceSimpleCall) {
2459 auto *OMPRegionInfo =
2462 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
2465 CGF.
Builder.restoreIP(AfterIP);
2478 if (OMPRegionInfo) {
2479 if (!ForceSimpleCall && OMPRegionInfo->hasCancel()) {
2482 OMPRTL___kmpc_cancel_barrier),
2491 CGF.
Builder.CreateCondBr(Cmp, ExitBB, ContBB);
2503 CGM.getModule(), OMPRTL___kmpc_barrier),
2508 Expr *ME,
bool IsFatal) {
2510 : llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
2513 llvm::Value *Args[] = {
2515 llvm::ConstantInt::get(
CGM.Int32Ty, IsFatal ? 2 : 1),
2516 CGF.
Builder.CreatePointerCast(MVL,
CGM.Int8PtrTy)};
2518 CGM.getModule(), OMPRTL___kmpc_error),
2524 bool Chunked,
bool Ordered) {
2525 switch (ScheduleKind) {
2526 case OMPC_SCHEDULE_static:
2527 return Chunked ? (Ordered ? OMP_ord_static_chunked : OMP_sch_static_chunked)
2528 : (Ordered ? OMP_ord_static : OMP_sch_static);
2529 case OMPC_SCHEDULE_dynamic:
2530 return Ordered ? OMP_ord_dynamic_chunked : OMP_sch_dynamic_chunked;
2531 case OMPC_SCHEDULE_guided:
2532 return Ordered ? OMP_ord_guided_chunked : OMP_sch_guided_chunked;
2533 case OMPC_SCHEDULE_runtime:
2534 return Ordered ? OMP_ord_runtime : OMP_sch_runtime;
2535 case OMPC_SCHEDULE_auto:
2536 return Ordered ? OMP_ord_auto : OMP_sch_auto;
2538 assert(!Chunked &&
"chunk was specified but schedule kind not known");
2539 return Ordered ? OMP_ord_static : OMP_sch_static;
2541 llvm_unreachable(
"Unexpected runtime schedule");
2545static OpenMPSchedType
2548 return Chunked ? OMP_dist_sch_static_chunked : OMP_dist_sch_static;
2552 bool Chunked)
const {
2553 OpenMPSchedType Schedule =
2555 return Schedule == OMP_sch_static;
2561 return Schedule == OMP_dist_sch_static;
2565 bool Chunked)
const {
2566 OpenMPSchedType Schedule =
2568 return Schedule == OMP_sch_static_chunked;
2574 return Schedule == OMP_dist_sch_static_chunked;
2578 OpenMPSchedType Schedule =
2580 assert(Schedule != OMP_sch_static_chunked &&
"cannot be chunked here");
2581 return Schedule != OMP_sch_static;
2589 case OMPC_SCHEDULE_MODIFIER_monotonic:
2590 Modifier = OMP_sch_modifier_monotonic;
2592 case OMPC_SCHEDULE_MODIFIER_nonmonotonic:
2593 Modifier = OMP_sch_modifier_nonmonotonic;
2595 case OMPC_SCHEDULE_MODIFIER_simd:
2596 if (Schedule == OMP_sch_static_chunked)
2597 Schedule = OMP_sch_static_balanced_chunked;
2604 case OMPC_SCHEDULE_MODIFIER_monotonic:
2605 Modifier = OMP_sch_modifier_monotonic;
2607 case OMPC_SCHEDULE_MODIFIER_nonmonotonic:
2608 Modifier = OMP_sch_modifier_nonmonotonic;
2610 case OMPC_SCHEDULE_MODIFIER_simd:
2611 if (Schedule == OMP_sch_static_chunked)
2612 Schedule = OMP_sch_static_balanced_chunked;
2624 if (CGM.
getLangOpts().OpenMP >= 50 && Modifier == 0) {
2625 if (!(Schedule == OMP_sch_static_chunked || Schedule == OMP_sch_static ||
2626 Schedule == OMP_sch_static_balanced_chunked ||
2627 Schedule == OMP_ord_static_chunked || Schedule == OMP_ord_static ||
2628 Schedule == OMP_dist_sch_static_chunked ||
2629 Schedule == OMP_dist_sch_static))
2630 Modifier = OMP_sch_modifier_nonmonotonic;
2632 return Schedule | Modifier;
2642 ScheduleKind.
Schedule, DispatchValues.
Chunk !=
nullptr, Ordered);
2644 (Schedule != OMP_sch_static && Schedule != OMP_sch_static_chunked &&
2645 Schedule != OMP_ord_static && Schedule != OMP_ord_static_chunked &&
2646 Schedule != OMP_sch_static_balanced_chunked));
2653 llvm::Value *Chunk = DispatchValues.
Chunk ? DispatchValues.
Chunk
2654 : CGF.
Builder.getIntN(IVSize, 1);
2655 llvm::Value *Args[] = {
2659 CGM, Schedule, ScheduleKind.
M1, ScheduleKind.
M2)),
2662 CGF.
Builder.getIntN(IVSize, 1),
2679 CodeGenFunction &CGF, llvm::Value *UpdateLocation, llvm::Value *ThreadId,
2680 llvm::FunctionCallee ForStaticInitFunction, OpenMPSchedType Schedule,
2687 assert(Schedule == OMP_sch_static || Schedule == OMP_sch_static_chunked ||
2688 Schedule == OMP_sch_static_balanced_chunked ||
2689 Schedule == OMP_ord_static || Schedule == OMP_ord_static_chunked ||
2690 Schedule == OMP_dist_sch_static ||
2691 Schedule == OMP_dist_sch_static_chunked);
2698 llvm::Value *Chunk = Values.
Chunk;
2699 if (Chunk ==
nullptr) {
2700 assert((Schedule == OMP_sch_static || Schedule == OMP_ord_static ||
2701 Schedule == OMP_dist_sch_static) &&
2702 "expected static non-chunked schedule");
2706 assert((Schedule == OMP_sch_static_chunked ||
2707 Schedule == OMP_sch_static_balanced_chunked ||
2708 Schedule == OMP_ord_static_chunked ||
2709 Schedule == OMP_dist_sch_static_chunked) &&
2710 "expected static chunked schedule");
2712 llvm::Value *Args[] = {
2735 "Expected loop-based or sections-based directive.");
2738 ? OMP_IDENT_WORK_LOOP
2739 : OMP_IDENT_WORK_SECTIONS);
2741 llvm::FunctionCallee StaticInitFunction =
2746 ScheduleNum, ScheduleKind.
M1, ScheduleKind.
M2, Values);
2753 OpenMPSchedType ScheduleNum =
2755 llvm::Value *UpdatedLocation =
2758 llvm::FunctionCallee StaticInitFunction;
2759 bool isGPUDistribute =
2760 CGM.getLangOpts().OpenMPIsTargetDevice &&
CGM.getTriple().isGPU();
2761 StaticInitFunction =
OMPBuilder.createForStaticInitFunction(
2772 assert((DKind == OMPD_distribute || DKind == OMPD_for ||
2773 DKind == OMPD_sections) &&
2774 "Expected distribute, for, or sections directive kind");
2778 llvm::Value *Args[] = {
2781 (DKind == OMPD_target_teams_loop)
2782 ? OMP_IDENT_WORK_DISTRIBUTE
2784 ? OMP_IDENT_WORK_LOOP
2785 : OMP_IDENT_WORK_SECTIONS),
2789 CGM.getLangOpts().OpenMPIsTargetDevice &&
CGM.getTriple().isGPU())
2792 CGM.getModule(), OMPRTL___kmpc_distribute_static_fini),
2796 CGM.getModule(), OMPRTL___kmpc_for_static_fini),
2821 llvm::Value *Args[] = {
2829 OMPBuilder.createDispatchNextFunction(IVSize, IVSigned), Args);
2836 const Expr *Message,
2839 return llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
2848 return llvm::ConstantInt::get(
CGM.Int32Ty,
2849 Severity == OMPC_SEVERITY_warning ? 1 : 2);
2865 RuntimeFunction FnID = OMPRTL___kmpc_push_num_threads;
2866 if (Modifier == OMPC_NUMTHREADS_strict) {
2867 FnID = OMPRTL___kmpc_push_num_threads_strict;
2872 OMPBuilder.getOrCreateRuntimeFunction(
CGM.getModule(), FnID), Args);
2876 ProcBindKind ProcBind,
2880 assert(ProcBind != OMP_PROC_BIND_unknown &&
"Unsupported proc_bind value.");
2882 llvm::Value *Args[] = {
2884 llvm::ConstantInt::get(
CGM.IntTy,
unsigned(ProcBind),
true)};
2886 CGM.getModule(), OMPRTL___kmpc_push_proc_bind),
2899 CGM.getModule(), OMPRTL___kmpc_flush),
2906enum KmpTaskTFields {
2933 if (
CGM.getLangOpts().OpenMPSimd ||
OMPBuilder.OffloadInfoManager.empty())
2936 llvm::OpenMPIRBuilder::EmitMetadataErrorReportFunctionTy &&ErrorReportFn =
2937 [
this](llvm::OpenMPIRBuilder::EmitMetadataErrorKind Kind,
2938 const llvm::TargetRegionEntryInfo &EntryInfo) ->
void {
2940 if (Kind != llvm::OpenMPIRBuilder::EMIT_MD_GLOBAL_VAR_LINK_ERROR) {
2941 for (
auto I =
CGM.getContext().getSourceManager().fileinfo_begin(),
2942 E =
CGM.getContext().getSourceManager().fileinfo_end();
2944 if (I->getFirst().getUniqueID().getDevice() == EntryInfo.DeviceID &&
2945 I->getFirst().getUniqueID().getFile() == EntryInfo.FileID) {
2946 Loc =
CGM.getContext().getSourceManager().translateFileLineCol(
2947 I->getFirst(), EntryInfo.Line, 1);
2953 case llvm::OpenMPIRBuilder::EMIT_MD_TARGET_REGION_ERROR: {
2954 CGM.getDiags().Report(Loc,
2955 diag::err_target_region_offloading_entry_incorrect)
2956 << EntryInfo.ParentName;
2958 case llvm::OpenMPIRBuilder::EMIT_MD_DECLARE_TARGET_ERROR: {
2959 CGM.getDiags().Report(
2960 Loc, diag::err_target_var_offloading_entry_incorrect_with_parent)
2961 << EntryInfo.ParentName;
2963 case llvm::OpenMPIRBuilder::EMIT_MD_GLOBAL_VAR_LINK_ERROR: {
2964 CGM.getDiags().Report(diag::err_target_var_offloading_entry_incorrect);
2966 case llvm::OpenMPIRBuilder::EMIT_MD_GLOBAL_VAR_INDIRECT_ERROR: {
2967 unsigned DiagID =
CGM.getDiags().getCustomDiagID(
2969 "target variable is incorrect: the "
2970 "address is invalid.");
2971 CGM.getDiags().Report(DiagID);
2976 OMPBuilder.createOffloadEntriesAndInfoMetadata(ErrorReportFn);
2983 QualType KmpRoutineEntryTyArgs[] = {KmpInt32Ty,
C.VoidPtrTy};
2986 C.getFunctionType(KmpInt32Ty, KmpRoutineEntryTyArgs, EPI));
2992struct PrivateHelpersTy {
2993 PrivateHelpersTy(
const Expr *OriginalRef,
const VarDecl *Original,
2995 : OriginalRef(OriginalRef), Original(Original), PrivateCopy(PrivateCopy),
2996 PrivateElemInit(PrivateElemInit) {}
2997 PrivateHelpersTy(
const VarDecl *Original) : Original(Original) {}
2998 const Expr *OriginalRef =
nullptr;
2999 const VarDecl *Original =
nullptr;
3000 const VarDecl *PrivateCopy =
nullptr;
3001 const VarDecl *PrivateElemInit =
nullptr;
3002 bool isLocalPrivate()
const {
3003 return !OriginalRef && !PrivateCopy && !PrivateElemInit;
3006typedef std::pair<CharUnits , PrivateHelpersTy> PrivateDataTy;
3011 if (!CVD->
hasAttr<OMPAllocateDeclAttr>())
3013 const auto *AA = CVD->
getAttr<OMPAllocateDeclAttr>();
3015 return !(AA->getAllocatorType() == OMPAllocateDeclAttr::OMPDefaultMemAlloc &&
3016 !AA->getAllocator());
3026 RecordDecl *RD =
C.buildImplicitRecord(
".kmp_privates.t");
3028 for (
const auto &Pair :
Privates) {
3029 const VarDecl *VD = Pair.second.Original;
3033 if (Pair.second.isLocalPrivate()) {
3056 QualType KmpRoutineEntryPointerQTy) {
3076 CanQualType KmpCmplrdataTy =
C.getCanonicalTagType(UD);
3077 RecordDecl *RD =
C.buildImplicitRecord(
"kmp_task_t");
3107 RecordDecl *RD =
C.buildImplicitRecord(
"kmp_task_t_with_privates");
3127static llvm::Function *
3130 QualType KmpTaskTWithPrivatesPtrQTy,
3132 QualType SharedsPtrTy, llvm::Function *TaskFunction,
3133 llvm::Value *TaskPrivatesMap) {
3141 Args.push_back(&GtidArg);
3142 Args.push_back(&TaskTypeArg);
3143 const auto &TaskEntryFnInfo =
3145 llvm::FunctionType *TaskEntryTy =
3148 auto *TaskEntry = llvm::Function::Create(
3149 TaskEntryTy, llvm::GlobalValue::InternalLinkage, Name, &CGM.
getModule());
3152 TaskEntry->addFnAttr(
"sample-profile-suffix-elision-policy",
"selected");
3153 TaskEntry->setDoesNotRecurse();
3168 const auto *KmpTaskTWithPrivatesQTyRD =
3173 auto PartIdFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTPartId);
3175 llvm::Value *PartidParam = PartIdLVal.getPointer(CGF);
3177 auto SharedsFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTShareds);
3183 auto PrivatesFI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin(), 1);
3184 llvm::Value *PrivatesParam;
3185 if (PrivatesFI != KmpTaskTWithPrivatesQTyRD->field_end()) {
3188 PrivatesLVal.getPointer(CGF), CGF.
VoidPtrTy);
3190 PrivatesParam = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
3193 llvm::Value *CommonArgs[] = {
3194 GtidParam, PartidParam, PrivatesParam, TaskPrivatesMap,
3200 std::end(CommonArgs));
3202 auto LBFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound);
3205 auto UBFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound);
3208 auto StFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTStride);
3211 auto LIFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLastIter);
3214 auto RFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTReductions);
3217 CallArgs.push_back(LBParam);
3218 CallArgs.push_back(UBParam);
3219 CallArgs.push_back(StParam);
3220 CallArgs.push_back(LIParam);
3221 CallArgs.push_back(RParam);
3223 CallArgs.push_back(SharedsParam);
3236 QualType KmpTaskTWithPrivatesPtrQTy,
3237 QualType KmpTaskTWithPrivatesQTy) {
3245 Args.push_back(&GtidArg);
3246 Args.push_back(&TaskTypeArg);
3247 const auto &DestructorFnInfo =
3249 llvm::FunctionType *DestructorFnTy =
3253 auto *DestructorFn =
3254 llvm::Function::Create(DestructorFnTy, llvm::GlobalValue::InternalLinkage,
3259 DestructorFn->addFnAttr(
"sample-profile-suffix-elision-policy",
"selected");
3260 DestructorFn->setDoesNotRecurse();
3268 const auto *KmpTaskTWithPrivatesQTyRD =
3270 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin());
3272 for (
const auto *Field : FI->getType()->castAsRecordDecl()->fields()) {
3274 Field->getType().isDestructedType()) {
3276 CGF.
pushDestroy(DtorKind, FieldLValue.getAddress(), Field->getType());
3280 return DestructorFn;
3300 C,
nullptr, Loc,
nullptr,
3301 C.getPointerType(PrivatesQTy).withConst().withRestrict(),
3303 Args.push_back(&TaskPrivatesArg);
3304 llvm::DenseMap<CanonicalDeclPtr<const VarDecl>,
unsigned> PrivateVarsPos;
3305 unsigned Counter = 1;
3306 for (
const Expr *E :
Data.PrivateVars) {
3308 C,
nullptr, Loc,
nullptr,
3309 C.getPointerType(
C.getPointerType(E->
getType()))
3314 PrivateVarsPos[VD] = Counter;
3317 for (
const Expr *E :
Data.FirstprivateVars) {
3319 C,
nullptr, Loc,
nullptr,
3320 C.getPointerType(
C.getPointerType(E->
getType()))
3325 PrivateVarsPos[VD] = Counter;
3328 for (
const Expr *E :
Data.LastprivateVars) {
3330 C,
nullptr, Loc,
nullptr,
3331 C.getPointerType(
C.getPointerType(E->
getType()))
3336 PrivateVarsPos[VD] = Counter;
3342 Ty =
C.getPointerType(Ty);
3344 Ty =
C.getPointerType(Ty);
3346 C,
nullptr, Loc,
nullptr,
3347 C.getPointerType(
C.getPointerType(Ty)).withConst().withRestrict(),
3349 PrivateVarsPos[VD] = Counter;
3352 const auto &TaskPrivatesMapFnInfo =
3354 llvm::FunctionType *TaskPrivatesMapTy =
3358 auto *TaskPrivatesMap = llvm::Function::Create(
3359 TaskPrivatesMapTy, llvm::GlobalValue::InternalLinkage, Name,
3362 TaskPrivatesMapFnInfo);
3364 TaskPrivatesMap->addFnAttr(
"sample-profile-suffix-elision-policy",
3367 TaskPrivatesMap->removeFnAttr(llvm::Attribute::NoInline);
3368 TaskPrivatesMap->removeFnAttr(llvm::Attribute::OptimizeNone);
3369 TaskPrivatesMap->addFnAttr(llvm::Attribute::AlwaysInline);
3373 TaskPrivatesMapFnInfo, Args, Loc, Loc);
3381 for (
const FieldDecl *Field : PrivatesQTyRD->fields()) {
3383 const VarDecl *VD = Args[PrivateVarsPos[
Privates[Counter].second.Original]];
3387 RefLVal.getAddress(), RefLVal.getType()->castAs<
PointerType>());
3392 return TaskPrivatesMap;
3398 Address KmpTaskSharedsPtr, LValue TDBase,
3404 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->
field_begin());
3418 if ((!IsTargetTask && !
Data.FirstprivateVars.empty() && ForDup) ||
3419 (IsTargetTask && KmpTaskSharedsPtr.
isValid())) {
3426 FI = FI->getType()->castAsRecordDecl()->field_begin();
3427 for (
const PrivateDataTy &Pair :
Privates) {
3429 if (Pair.second.isLocalPrivate()) {
3433 const VarDecl *VD = Pair.second.PrivateCopy;
3438 if (
const VarDecl *Elem = Pair.second.PrivateElemInit) {
3439 const VarDecl *OriginalVD = Pair.second.Original;
3442 LValue SharedRefLValue;
3445 if (IsTargetTask && !SharedField) {
3449 ->getNumParams() == 0 &&
3452 ->getDeclContext()) &&
3453 "Expected artificial target data variable.");
3456 }
else if (ForDup) {
3459 SharedRefLValue.getAddress().withAlignment(
3460 C.getDeclAlign(OriginalVD)),
3462 SharedRefLValue.getTBAAInfo());
3464 Pair.second.Original->getCanonicalDecl()) > 0 ||
3466 SharedRefLValue = CGF.
EmitLValue(Pair.second.OriginalRef);
3469 InlinedOpenMPRegionRAII Region(
3472 SharedRefLValue = CGF.
EmitLValue(Pair.second.OriginalRef);
3483 PrivateLValue.getAddress(), SharedRefLValue.getAddress(),
Type,
3484 [&CGF, Elem,
Init, &CapturesInfo](
Address DestElement,
3487 CodeGenFunction::OMPPrivateScope InitScope(CGF);
3488 InitScope.addPrivate(Elem, SrcElement);
3489 (void)InitScope.Privatize();
3491 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(
3492 CGF, &CapturesInfo);
3493 CGF.EmitAnyExprToMem(Init, DestElement,
3494 Init->getType().getQualifiers(),
3500 InitScope.addPrivate(Elem, SharedRefLValue.getAddress());
3501 (void)InitScope.Privatize();
3517 bool InitRequired =
false;
3518 for (
const PrivateDataTy &Pair :
Privates) {
3519 if (Pair.second.isLocalPrivate())
3521 const VarDecl *VD = Pair.second.PrivateCopy;
3523 InitRequired = InitRequired || (isa_and_nonnull<CXXConstructExpr>(
Init) &&
3528 return InitRequired;
3545 QualType KmpTaskTWithPrivatesPtrQTy,
3553 KmpTaskTWithPrivatesPtrQTy,
3556 KmpTaskTWithPrivatesPtrQTy,
3560 Args.push_back(&DstArg);
3561 Args.push_back(&SrcArg);
3562 Args.push_back(&LastprivArg);
3563 const auto &TaskDupFnInfo =
3567 auto *TaskDup = llvm::Function::Create(
3568 TaskDupTy, llvm::GlobalValue::InternalLinkage, Name, &CGM.
getModule());
3571 TaskDup->addFnAttr(
"sample-profile-suffix-elision-policy",
"selected");
3572 TaskDup->setDoesNotRecurse();
3582 auto LIFI = std::next(KmpTaskTQTyRD->
field_begin(), KmpTaskTLastIter);
3584 TDBase, *KmpTaskTWithPrivatesQTyRD->
field_begin());
3594 if (!
Data.FirstprivateVars.empty()) {
3599 TDBase, *KmpTaskTWithPrivatesQTyRD->
field_begin());
3607 emitPrivatesInit(CGF, D, KmpTaskSharedsPtr, TDBase, KmpTaskTWithPrivatesQTyRD,
3618 for (
const PrivateDataTy &P :
Privates) {
3619 if (P.second.isLocalPrivate())
3621 QualType Ty = P.second.Original->getType().getNonReferenceType();
3630class OMPIteratorGeneratorScope final
3632 CodeGenFunction &CGF;
3633 const OMPIteratorExpr *E =
nullptr;
3634 SmallVector<CodeGenFunction::JumpDest, 4> ContDests;
3635 SmallVector<CodeGenFunction::JumpDest, 4> ExitDests;
3636 OMPIteratorGeneratorScope() =
delete;
3637 OMPIteratorGeneratorScope(OMPIteratorGeneratorScope &) =
delete;
3640 OMPIteratorGeneratorScope(CodeGenFunction &CGF,
const OMPIteratorExpr *E)
3641 : CodeGenFunction::OMPPrivateScope(CGF), CGF(CGF), E(E) {
3644 SmallVector<llvm::Value *, 4> Uppers;
3646 Uppers.push_back(CGF.EmitScalarExpr(E->getHelper(I).Upper));
3647 const auto *VD = cast<VarDecl>(E->getIteratorDecl(I));
3648 addPrivate(VD, CGF.CreateMemTemp(VD->getType(), VD->getName()));
3649 const OMPIteratorHelperData &HelperData = E->getHelper(I);
3651 HelperData.CounterVD,
3652 CGF.CreateMemTemp(HelperData.CounterVD->getType(),
"counter.addr"));
3657 const OMPIteratorHelperData &HelperData = E->getHelper(I);
3659 CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(HelperData.CounterVD),
3660 HelperData.CounterVD->getType());
3662 CGF.EmitStoreOfScalar(
3663 llvm::ConstantInt::get(CLVal.getAddress().getElementType(), 0),
3665 CodeGenFunction::JumpDest &ContDest =
3666 ContDests.emplace_back(CGF.getJumpDestInCurrentScope(
"iter.cont"));
3667 CodeGenFunction::JumpDest &ExitDest =
3668 ExitDests.emplace_back(CGF.getJumpDestInCurrentScope(
"iter.exit"));
3670 llvm::Value *N = Uppers[I];
3673 CGF.EmitBlock(ContDest.getBlock());
3675 CGF.EmitLoadOfScalar(CLVal, HelperData.CounterVD->getLocation());
3677 HelperData.CounterVD->getType()->isSignedIntegerOrEnumerationType()
3678 ? CGF.Builder.CreateICmpSLT(CVal, N)
3679 : CGF.Builder.CreateICmpULT(CVal, N);
3680 llvm::BasicBlock *BodyBB = CGF.createBasicBlock(
"iter.body");
3681 CGF.Builder.CreateCondBr(Cmp, BodyBB, ExitDest.getBlock());
3683 CGF.EmitBlock(BodyBB);
3685 CGF.EmitIgnoredExpr(HelperData.Update);
3688 ~OMPIteratorGeneratorScope() {
3693 const OMPIteratorHelperData &HelperData = E->
getHelper(I - 1);
3698 CGF.
EmitBlock(ExitDests[I - 1].getBlock(), I == 1);
3704static std::pair<llvm::Value *, llvm::Value *>
3706 const auto *OASE = dyn_cast<OMPArrayShapingExpr>(E);
3709 const Expr *
Base = OASE->getBase();
3714 llvm::Value *SizeVal;
3717 SizeVal = CGF.
getTypeSize(OASE->getBase()->getType()->getPointeeType());
3718 for (
const Expr *SE : OASE->getDimensions()) {
3722 SizeVal = CGF.
Builder.CreateNUWMul(SizeVal, Sz);
3724 }
else if (
const auto *ASE =
3727 Address UpAddrAddress = UpAddrLVal.getAddress();
3728 llvm::Value *UpAddr = CGF.
Builder.CreateConstGEP1_32(
3732 llvm::Value *UpIntPtr = CGF.
Builder.CreatePtrToInt(UpAddr, CGF.
SizeTy);
3733 SizeVal = CGF.
Builder.CreateNUWSub(UpIntPtr, LowIntPtr);
3737 return std::make_pair(
Addr, SizeVal);
3742 QualType FlagsTy =
C.getIntTypeForBitwidth(32,
false);
3743 if (KmpTaskAffinityInfoTy.
isNull()) {
3745 C.buildImplicitRecord(
"kmp_task_affinity_info_t");
3751 KmpTaskAffinityInfoTy =
C.getCanonicalTagType(KmpAffinityInfoRD);
3758 llvm::Function *TaskFunction,
QualType SharedsTy,
3763 const auto *I =
Data.PrivateCopies.begin();
3764 for (
const Expr *E :
Data.PrivateVars) {
3772 I =
Data.FirstprivateCopies.begin();
3773 const auto *IElemInitRef =
Data.FirstprivateInits.begin();
3774 for (
const Expr *E :
Data.FirstprivateVars) {
3784 I =
Data.LastprivateCopies.begin();
3785 for (
const Expr *E :
Data.LastprivateVars) {
3795 Privates.emplace_back(
CGM.getPointerAlign(), PrivateHelpersTy(VD));
3797 Privates.emplace_back(
C.getDeclAlign(VD), PrivateHelpersTy(VD));
3800 [](
const PrivateDataTy &L,
const PrivateDataTy &R) {
3801 return L.first > R.first;
3803 QualType KmpInt32Ty =
C.getIntTypeForBitwidth(32, 1);
3814 assert((D.getDirectiveKind() == OMPD_task ||
3817 "Expected taskloop, task or target directive");
3824 const auto *KmpTaskTQTyRD =
KmpTaskTQTy->castAsRecordDecl();
3826 const RecordDecl *KmpTaskTWithPrivatesQTyRD =
3829 C.getCanonicalTagType(KmpTaskTWithPrivatesQTyRD);
3830 QualType KmpTaskTWithPrivatesPtrQTy =
3831 C.getPointerType(KmpTaskTWithPrivatesQTy);
3832 llvm::Type *KmpTaskTWithPrivatesPtrTy = CGF.
Builder.getPtrTy(0);
3833 llvm::Value *KmpTaskTWithPrivatesTySize =
3835 QualType SharedsPtrTy =
C.getPointerType(SharedsTy);
3838 llvm::Value *TaskPrivatesMap =
nullptr;
3839 llvm::Type *TaskPrivatesMapTy =
3840 std::next(TaskFunction->arg_begin(), 3)->getType();
3842 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->
field_begin());
3846 TaskPrivatesMap, TaskPrivatesMapTy);
3848 TaskPrivatesMap = llvm::ConstantPointerNull::get(
3854 CGM, Loc, D.getDirectiveKind(), KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy,
3855 KmpTaskTWithPrivatesQTy,
KmpTaskTQTy, SharedsPtrTy, TaskFunction,
3867 DestructorsFlag = 0x8,
3868 PriorityFlag = 0x20,
3869 DetachableFlag = 0x40,
3870 FreeAgentFlag = 0x80,
3871 TransparentFlag = 0x100,
3873 unsigned Flags =
Data.Tied ? TiedFlag : 0;
3874 bool NeedsCleanup =
false;
3879 Flags = Flags | DestructorsFlag;
3883 if (Kind == OMPC_THREADSET_omp_pool)
3884 Flags = Flags | FreeAgentFlag;
3886 if (D.getSingleClause<OMPTransparentClause>())
3887 Flags |= TransparentFlag;
3889 if (
Data.Priority.getInt())
3890 Flags = Flags | PriorityFlag;
3892 Flags = Flags | DetachableFlag;
3893 llvm::Value *TaskFlags =
3894 Data.Final.getPointer()
3895 ? CGF.
Builder.CreateSelect(
Data.Final.getPointer(),
3896 CGF.
Builder.getInt32(FinalFlag),
3898 : CGF.
Builder.getInt32(
Data.Final.getInt() ? FinalFlag : 0);
3899 TaskFlags = CGF.
Builder.CreateOr(TaskFlags, CGF.
Builder.getInt32(Flags));
3900 llvm::Value *SharedsSize =
CGM.getSize(
C.getTypeSizeInChars(SharedsTy));
3902 getThreadID(CGF, Loc), TaskFlags, KmpTaskTWithPrivatesTySize,
3905 llvm::Value *NewTask;
3906 if (D.hasClausesOfKind<OMPNowaitClause>()) {
3912 llvm::Value *DeviceID;
3917 DeviceID = CGF.
Builder.getInt64(OMP_DEVICEID_UNDEF);
3918 AllocArgs.push_back(DeviceID);
3921 CGM.getModule(), OMPRTL___kmpc_omp_target_task_alloc),
3926 CGM.getModule(), OMPRTL___kmpc_omp_task_alloc),
3939 llvm::Value *Tid =
getThreadID(CGF, DC->getBeginLoc());
3940 Tid = CGF.
Builder.CreateIntCast(Tid, CGF.
IntTy,
false);
3943 CGM.getModule(), OMPRTL___kmpc_task_allow_completion_event),
3944 {Loc, Tid, NewTask});
3955 llvm::Value *NumOfElements =
nullptr;
3956 unsigned NumAffinities = 0;
3958 if (
const Expr *Modifier =
C->getModifier()) {
3960 for (
unsigned I = 0, E = IE->numOfIterators(); I < E; ++I) {
3964 NumOfElements ? CGF.
Builder.CreateNUWMul(NumOfElements, Sz) : Sz;
3967 NumAffinities +=
C->varlist_size();
3972 enum RTLAffinityInfoFieldsTy { BaseAddr, Len, Flags };
3974 QualType KmpTaskAffinityInfoArrayTy;
3975 if (NumOfElements) {
3976 NumOfElements = CGF.
Builder.CreateNUWAdd(
3977 llvm::ConstantInt::get(CGF.
SizeTy, NumAffinities), NumOfElements);
3980 C.getIntTypeForBitwidth(
C.getTypeSize(
C.getSizeType()), 0),
3984 KmpTaskAffinityInfoArrayTy =
C.getVariableArrayType(
3992 NumOfElements = CGF.
Builder.CreateIntCast(NumOfElements, CGF.
Int32Ty,
3995 KmpTaskAffinityInfoArrayTy =
C.getConstantArrayType(
3997 llvm::APInt(
C.getTypeSize(
C.getSizeType()), NumAffinities),
nullptr,
4000 CGF.
CreateMemTemp(KmpTaskAffinityInfoArrayTy,
".affs.arr.addr");
4002 NumOfElements = llvm::ConstantInt::get(
CGM.Int32Ty, NumAffinities,
4009 bool HasIterator =
false;
4011 if (
C->getModifier()) {
4015 for (
const Expr *E :
C->varlist()) {
4024 Base, *std::next(KmpAffinityInfoRD->field_begin(), BaseAddr));
4029 Base, *std::next(KmpAffinityInfoRD->field_begin(), Len));
4043 const Expr *Modifier =
C->getModifier();
4046 OMPIteratorGeneratorScope IteratorScope(
4048 for (
const Expr *E :
C->varlist()) {
4058 Base, *std::next(KmpAffinityInfoRD->field_begin(), BaseAddr));
4063 Base, *std::next(KmpAffinityInfoRD->field_begin(), Len));
4065 Idx = CGF.
Builder.CreateNUWAdd(
4066 Idx, llvm::ConstantInt::get(Idx->getType(), 1));
4081 CGM.getModule(), OMPRTL___kmpc_omp_reg_task_with_affinity),
4082 {LocRef, GTid, NewTask, NumOfElements, AffinListPtr});
4084 llvm::Value *NewTaskNewTaskTTy =
4086 NewTask, KmpTaskTWithPrivatesPtrTy);
4088 KmpTaskTWithPrivatesQTy);
4099 *std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTShareds)),
4101 CGF.
Int8Ty,
CGM.getNaturalTypeAlignment(SharedsTy));
4115 CGM, Loc, D, KmpTaskTWithPrivatesPtrQTy, KmpTaskTWithPrivatesQTyRD,
4116 KmpTaskTQTyRD, SharedsTy, SharedsPtrTy,
Data,
Privates,
4117 !
Data.LastprivateVars.empty());
4121 enum { Priority = 0, Destructors = 1 };
4123 auto FI = std::next(KmpTaskTQTyRD->field_begin(), Data1);
4124 const auto *KmpCmplrdataUD = (*FI)->getType()->castAsRecordDecl();
4125 assert(KmpCmplrdataUD->isUnion());
4128 CGM, Loc, KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy,
4129 KmpTaskTWithPrivatesQTy);
4132 Data1LV, *std::next(KmpCmplrdataUD->field_begin(), Destructors));
4138 if (
Data.Priority.getInt()) {
4140 TDBase, *std::next(KmpTaskTQTyRD->field_begin(), Data2));
4142 Data2LV, *std::next(KmpCmplrdataUD->field_begin(), Priority));
4145 Result.NewTask = NewTask;
4146 Result.TaskEntry = TaskEntry;
4147 Result.NewTaskNewTaskTTy = NewTaskNewTaskTTy;
4149 Result.KmpTaskTQTyRD = KmpTaskTQTyRD;
4155 RTLDependenceKindTy DepKind;
4157 case OMPC_DEPEND_in:
4158 DepKind = RTLDependenceKindTy::DepIn;
4161 case OMPC_DEPEND_out:
4162 case OMPC_DEPEND_inout:
4163 DepKind = RTLDependenceKindTy::DepInOut;
4165 case OMPC_DEPEND_mutexinoutset:
4166 DepKind = RTLDependenceKindTy::DepMutexInOutSet;
4168 case OMPC_DEPEND_inoutset:
4169 DepKind = RTLDependenceKindTy::DepInOutSet;
4171 case OMPC_DEPEND_outallmemory:
4172 DepKind = RTLDependenceKindTy::DepOmpAllMem;
4174 case OMPC_DEPEND_source:
4175 case OMPC_DEPEND_sink:
4176 case OMPC_DEPEND_depobj:
4177 case OMPC_DEPEND_inoutallmemory:
4179 llvm_unreachable(
"Unknown task dependence type");
4187 FlagsTy =
C.getIntTypeForBitwidth(
C.getTypeSize(
C.BoolTy),
false);
4188 if (KmpDependInfoTy.
isNull()) {
4189 RecordDecl *KmpDependInfoRD =
C.buildImplicitRecord(
"kmp_depend_info");
4195 KmpDependInfoTy =
C.getCanonicalTagType(KmpDependInfoRD);
4199std::pair<llvm::Value *, LValue>
4212 CGF,
Base.getAddress(),
4213 llvm::ConstantInt::get(CGF.
IntPtrTy, -1,
true));
4219 *std::next(KmpDependInfoRD->field_begin(),
4220 static_cast<unsigned int>(RTLDependInfoFields::BaseAddr)));
4222 return std::make_pair(NumDeps,
Base);
4226 llvm::PointerUnion<unsigned *, LValue *> Pos,
4236 OMPIteratorGeneratorScope IteratorScope(
4237 CGF, cast_or_null<OMPIteratorExpr>(
4238 Data.IteratorExpr ?
Data.IteratorExpr->IgnoreParenImpCasts()
4240 for (
const Expr *E :
Data.DepExprs) {
4250 Size = llvm::ConstantInt::get(CGF.
SizeTy, 0);
4253 if (
unsigned *P = dyn_cast<unsigned *>(Pos)) {
4257 assert(E &&
"Expected a non-null expression");
4266 *std::next(KmpDependInfoRD->field_begin(),
4267 static_cast<unsigned int>(RTLDependInfoFields::BaseAddr)));
4271 Base, *std::next(KmpDependInfoRD->field_begin(),
4272 static_cast<unsigned int>(RTLDependInfoFields::Len)));
4278 *std::next(KmpDependInfoRD->field_begin(),
4279 static_cast<unsigned int>(RTLDependInfoFields::Flags)));
4281 llvm::ConstantInt::get(LLVMFlagsTy,
static_cast<unsigned int>(DepKind)),
4283 if (
unsigned *P = dyn_cast<unsigned *>(Pos)) {
4288 Idx = CGF.
Builder.CreateNUWAdd(Idx,
4289 llvm::ConstantInt::get(Idx->getType(), 1));
4298 assert(
Data.DepKind == OMPC_DEPEND_depobj &&
4299 "Expected depobj dependency kind.");
4304 OMPIteratorGeneratorScope IteratorScope(
4305 CGF, cast_or_null<OMPIteratorExpr>(
4306 Data.IteratorExpr ?
Data.IteratorExpr->IgnoreParenImpCasts()
4308 for (
const Expr *E :
Data.DepExprs) {
4309 llvm::Value *NumDeps;
4312 std::tie(NumDeps,
Base) =
4316 C.getUIntPtrType());
4320 llvm::Value *Add = CGF.
Builder.CreateNUWAdd(PrevVal, NumDeps);
4322 SizeLVals.push_back(NumLVal);
4325 for (
unsigned I = 0, E = SizeLVals.size(); I < E; ++I) {
4328 Sizes.push_back(Size);
4338 assert(
Data.DepKind == OMPC_DEPEND_depobj &&
4339 "Expected depobj dependency kind.");
4342 OMPIteratorGeneratorScope IteratorScope(
4343 CGF, cast_or_null<OMPIteratorExpr>(
4344 Data.IteratorExpr ?
Data.IteratorExpr->IgnoreParenImpCasts()
4346 for (
const Expr *E :
Data.DepExprs) {
4347 llvm::Value *NumDeps;
4350 std::tie(NumDeps,
Base) =
4354 llvm::Value *Size = CGF.
Builder.CreateNUWMul(
4363 llvm::Value *Add = CGF.
Builder.CreateNUWAdd(Pos, NumDeps);
4379 llvm::Value *NumOfElements =
nullptr;
4380 unsigned NumDependencies = std::accumulate(
4381 Dependencies.begin(), Dependencies.end(), 0,
4383 return D.DepKind == OMPC_DEPEND_depobj
4385 : (V + (D.IteratorExpr ? 0 : D.DepExprs.size()));
4389 bool HasDepobjDeps =
false;
4390 bool HasRegularWithIterators =
false;
4391 llvm::Value *NumOfDepobjElements = llvm::ConstantInt::get(CGF.
IntPtrTy, 0);
4392 llvm::Value *NumOfRegularWithIterators =
4393 llvm::ConstantInt::get(CGF.
IntPtrTy, 0);
4397 if (D.
DepKind == OMPC_DEPEND_depobj) {
4400 for (llvm::Value *Size : Sizes) {
4401 NumOfDepobjElements =
4402 CGF.
Builder.CreateNUWAdd(NumOfDepobjElements, Size);
4404 HasDepobjDeps =
true;
4409 if (
const auto *IE = cast_or_null<OMPIteratorExpr>(D.
IteratorExpr)) {
4410 llvm::Value *ClauseIteratorSpace =
4411 llvm::ConstantInt::get(CGF.
IntPtrTy, 1);
4415 ClauseIteratorSpace = CGF.
Builder.CreateNUWMul(Sz, ClauseIteratorSpace);
4417 llvm::Value *NumClauseDeps = CGF.
Builder.CreateNUWMul(
4418 ClauseIteratorSpace,
4420 NumOfRegularWithIterators =
4421 CGF.
Builder.CreateNUWAdd(NumOfRegularWithIterators, NumClauseDeps);
4422 HasRegularWithIterators =
true;
4428 if (HasDepobjDeps || HasRegularWithIterators) {
4429 NumOfElements = llvm::ConstantInt::get(
CGM.IntPtrTy, NumDependencies,
4431 if (HasDepobjDeps) {
4433 CGF.
Builder.CreateNUWAdd(NumOfDepobjElements, NumOfElements);
4435 if (HasRegularWithIterators) {
4437 CGF.
Builder.CreateNUWAdd(NumOfRegularWithIterators, NumOfElements);
4440 Loc,
C.getIntTypeForBitwidth(64, 0),
4444 KmpDependInfoArrayTy =
4453 NumOfElements = CGF.
Builder.CreateIntCast(NumOfElements, CGF.
Int32Ty,
4456 KmpDependInfoArrayTy =
C.getConstantArrayType(
4462 NumOfElements = llvm::ConstantInt::get(
CGM.Int32Ty, NumDependencies,
4467 if (Dep.DepKind == OMPC_DEPEND_depobj || Dep.IteratorExpr)
4473 CGF.
CreateMemTemp(
C.getSizeType(),
"dep.counter.addr"),
C.getSizeType());
4476 if (Dep.DepKind == OMPC_DEPEND_depobj || !Dep.IteratorExpr)
4481 if (HasDepobjDeps) {
4483 if (Dep.DepKind != OMPC_DEPEND_depobj)
4490 return std::make_pair(NumOfElements, DependenciesArray);
4501 unsigned NumDependencies = Dependencies.
DepExprs.size();
4511 llvm::Value *NumDepsVal;
4513 if (
const auto *IE =
4514 cast_or_null<OMPIteratorExpr>(Dependencies.
IteratorExpr)) {
4515 NumDepsVal = llvm::ConstantInt::get(CGF.
SizeTy, 1);
4519 NumDepsVal = CGF.
Builder.CreateNUWMul(NumDepsVal, Sz);
4521 Size = CGF.
Builder.CreateNUWAdd(llvm::ConstantInt::get(CGF.
SizeTy, 1),
4525 llvm::Value *RecSize =
CGM.getSize(SizeInBytes);
4526 Size = CGF.
Builder.CreateNUWMul(Size, RecSize);
4530 QualType KmpDependInfoArrayTy =
C.getConstantArrayType(
4533 CharUnits Sz =
C.getTypeSizeInChars(KmpDependInfoArrayTy);
4535 NumDepsVal = llvm::ConstantInt::get(CGF.
IntPtrTy, NumDependencies);
4540 llvm::Value *Allocator = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
4541 llvm::Value *Args[] = {ThreadID, Size, Allocator};
4545 CGM.getModule(), OMPRTL___kmpc_alloc),
4546 Args,
".dep.arr.addr");
4550 DependenciesArray =
Address(
Addr, KmpDependInfoLlvmTy, Align);
4556 *std::next(KmpDependInfoRD->field_begin(),
4557 static_cast<unsigned int>(RTLDependInfoFields::BaseAddr)));
4559 llvm::PointerUnion<unsigned *, LValue *> Pos;
4576 return DependenciesArray;
4591 Addr.getElementType(),
Addr.emitRawPointer(CGF),
4592 llvm::ConstantInt::get(CGF.
IntPtrTy, -1,
true));
4597 llvm::Value *Allocator = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
4598 llvm::Value *Args[] = {ThreadID, DepObjAddr, Allocator};
4602 CGM.getModule(), OMPRTL___kmpc_free),
4614 llvm::Value *NumDeps;
4625 llvm::BasicBlock *EntryBB = CGF.
Builder.GetInsertBlock();
4627 llvm::PHINode *ElementPHI =
4632 Base.getTBAAInfo());
4636 Base, *std::next(KmpDependInfoRD->field_begin(),
4637 static_cast<unsigned int>(RTLDependInfoFields::Flags)));
4639 llvm::ConstantInt::get(LLVMFlagsTy,
static_cast<unsigned int>(DepKind)),
4643 llvm::Value *ElementNext =
4646 ElementPHI->addIncoming(ElementNext, CGF.
Builder.GetInsertBlock());
4647 llvm::Value *IsEmpty =
4648 CGF.
Builder.CreateICmpEQ(ElementNext, End,
"omp.isempty");
4649 CGF.
Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
4656 llvm::Function *TaskFunction,
4665 llvm::Value *NewTask =
Result.NewTask;
4666 llvm::Function *TaskEntry =
Result.TaskEntry;
4667 llvm::Value *NewTaskNewTaskTTy =
Result.NewTaskNewTaskTTy;
4672 llvm::Value *NumOfElements;
4673 std::tie(NumOfElements, DependenciesArray) =
4684 llvm::Value *TaskArgs[] = { UpLoc, ThreadID, NewTask };
4685 llvm::Value *DepTaskArgs[7];
4686 if (!
Data.Dependences.empty()) {
4687 DepTaskArgs[0] = UpLoc;
4688 DepTaskArgs[1] = ThreadID;
4689 DepTaskArgs[2] = NewTask;
4690 DepTaskArgs[3] = NumOfElements;
4692 DepTaskArgs[5] = CGF.
Builder.getInt32(0);
4693 DepTaskArgs[6] = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
4695 auto &&ThenCodeGen = [
this, &
Data, TDBase, KmpTaskTQTyRD, &TaskArgs,
4698 auto PartIdFI = std::next(KmpTaskTQTyRD->
field_begin(), KmpTaskTPartId);
4702 if (!
Data.Dependences.empty()) {
4705 CGM.getModule(), OMPRTL___kmpc_omp_task_with_deps),
4709 CGM.getModule(), OMPRTL___kmpc_omp_task),
4715 Region->emitUntiedSwitch(CGF);
4718 llvm::Value *DepWaitTaskArgs[7];
4719 if (!
Data.Dependences.empty()) {
4720 DepWaitTaskArgs[0] = UpLoc;
4721 DepWaitTaskArgs[1] = ThreadID;
4722 DepWaitTaskArgs[2] = NumOfElements;
4724 DepWaitTaskArgs[4] = CGF.
Builder.getInt32(0);
4725 DepWaitTaskArgs[5] = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
4726 DepWaitTaskArgs[6] =
4727 llvm::ConstantInt::get(CGF.
Int32Ty,
Data.HasNowaitClause);
4729 auto &M =
CGM.getModule();
4730 auto &&ElseCodeGen = [
this, &M, &TaskArgs, ThreadID, NewTaskNewTaskTTy,
4731 TaskEntry, &
Data, &DepWaitTaskArgs,
4738 if (!
Data.Dependences.empty())
4740 M, OMPRTL___kmpc_omp_taskwait_deps_51),
4743 auto &&
CodeGen = [TaskEntry, ThreadID, NewTaskNewTaskTTy,
4746 llvm::Value *OutlinedFnArgs[] = {ThreadID, NewTaskNewTaskTTy};
4747 CGF.CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, Loc, TaskEntry,
4756 CommonActionTy Action(
OMPBuilder.getOrCreateRuntimeFunction(
4757 M, OMPRTL___kmpc_omp_task_begin_if0),
4760 M, OMPRTL___kmpc_omp_task_complete_if0),
4776 llvm::Function *TaskFunction,
4796 IfVal = llvm::ConstantInt::getSigned(CGF.
IntTy, 1);
4801 *std::next(
Result.KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound));
4808 *std::next(
Result.KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound));
4815 *std::next(
Result.KmpTaskTQTyRD->field_begin(), KmpTaskTStride));
4823 *std::next(
Result.KmpTaskTQTyRD->field_begin(), KmpTaskTReductions));
4824 if (
Data.Reductions) {
4830 enum { NoSchedule = 0, Grainsize = 1, NumTasks = 2 };
4839 llvm::ConstantInt::getSigned(
4841 llvm::ConstantInt::getSigned(
4843 ?
Data.Schedule.getInt() ? NumTasks : Grainsize
4845 Data.Schedule.getPointer()
4848 : llvm::ConstantInt::get(CGF.
Int64Ty, 0)};
4849 if (
Data.HasModifier)
4850 TaskArgs.push_back(llvm::ConstantInt::get(CGF.
Int32Ty, 1));
4852 TaskArgs.push_back(
Result.TaskDupFn
4855 : llvm::ConstantPointerNull::get(CGF.
VoidPtrTy));
4857 CGM.getModule(),
Data.HasModifier
4858 ? OMPRTL___kmpc_taskloop_5
4859 : OMPRTL___kmpc_taskloop),
4876 const Expr *,
const Expr *)> &RedOpGen,
4877 const Expr *XExpr =
nullptr,
const Expr *EExpr =
nullptr,
4878 const Expr *UpExpr =
nullptr) {
4886 llvm::Value *NumElements = CGF.
emitArrayLength(ArrayTy, ElementTy, LHSAddr);
4891 llvm::Value *LHSEnd =
4896 llvm::Value *IsEmpty =
4897 CGF.
Builder.CreateICmpEQ(LHSBegin, LHSEnd,
"omp.arraycpy.isempty");
4898 CGF.
Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
4901 llvm::BasicBlock *EntryBB = CGF.
Builder.GetInsertBlock();
4906 llvm::PHINode *RHSElementPHI = CGF.
Builder.CreatePHI(
4907 RHSBegin->getType(), 2,
"omp.arraycpy.srcElementPast");
4908 RHSElementPHI->addIncoming(RHSBegin, EntryBB);
4913 llvm::PHINode *LHSElementPHI = CGF.
Builder.CreatePHI(
4914 LHSBegin->getType(), 2,
"omp.arraycpy.destElementPast");
4915 LHSElementPHI->addIncoming(LHSBegin, EntryBB);
4922 Scope.addPrivate(LHSVar, LHSElementCurrent);
4923 Scope.addPrivate(RHSVar, RHSElementCurrent);
4925 RedOpGen(CGF, XExpr, EExpr, UpExpr);
4926 Scope.ForceCleanup();
4929 llvm::Value *LHSElementNext = CGF.
Builder.CreateConstGEP1_32(
4931 "omp.arraycpy.dest.element");
4932 llvm::Value *RHSElementNext = CGF.
Builder.CreateConstGEP1_32(
4934 "omp.arraycpy.src.element");
4937 CGF.
Builder.CreateICmpEQ(LHSElementNext, LHSEnd,
"omp.arraycpy.done");
4938 CGF.
Builder.CreateCondBr(Done, DoneBB, BodyBB);
4939 LHSElementPHI->addIncoming(LHSElementNext, CGF.
Builder.GetInsertBlock());
4940 RHSElementPHI->addIncoming(RHSElementNext, CGF.
Builder.GetInsertBlock());
4950 const Expr *ReductionOp) {
4951 if (
const auto *CE = dyn_cast<CallExpr>(ReductionOp))
4952 if (
const auto *OVE = dyn_cast<OpaqueValueExpr>(CE->getCallee()))
4953 if (
const auto *DRE =
4954 dyn_cast<DeclRefExpr>(OVE->getSourceExpr()->IgnoreImpCasts()))
4955 if (
const auto *DRD =
4956 dyn_cast<OMPDeclareReductionDecl>(DRE->getDecl())) {
4957 std::pair<llvm::Function *, llvm::Function *>
Reduction =
4968 StringRef ReducerName,
SourceLocation Loc, llvm::Type *ArgsElemType,
4979 Args.push_back(&LHSArg);
4980 Args.push_back(&RHSArg);
4982 CGM.getTypes().arrangeBuiltinFunctionDeclaration(
C.VoidTy, Args);
4984 auto *Fn = llvm::Function::Create(
CGM.getTypes().GetFunctionType(CGFI),
4985 llvm::GlobalValue::InternalLinkage, Name,
4988 if (!
CGM.getCodeGenOpts().SampleProfileFile.empty())
4989 Fn->addFnAttr(
"sample-profile-suffix-elision-policy",
"selected");
4990 Fn->setDoesNotRecurse();
5009 const auto *IPriv =
Privates.begin();
5011 for (
unsigned I = 0, E = ReductionOps.size(); I < E; ++I, ++IPriv, ++Idx) {
5012 const auto *RHSVar =
5015 const auto *LHSVar =
5018 QualType PrivTy = (*IPriv)->getType();
5034 const auto *ILHS = LHSExprs.begin();
5035 const auto *IRHS = RHSExprs.begin();
5036 for (
const Expr *E : ReductionOps) {
5037 if ((*IPriv)->getType()->isArrayType()) {
5042 CGF, (*IPriv)->getType(), LHSVar, RHSVar,
5044 emitReductionCombiner(CGF, E);
5054 Scope.ForceCleanup();
5060 const Expr *ReductionOp,
5061 const Expr *PrivateRef,
5069 CGF, PrivateRef->
getType(), LHSVar, RHSVar,
5071 emitReductionCombiner(CGF, ReductionOp);
5080 llvm::StringRef Prefix,
const Expr *Ref);
5084 const Expr *LHSExprs,
const Expr *RHSExprs,
const Expr *ReductionOps) {
5111 std::string ReductionVarNameStr;
5112 if (
const auto *DRE = dyn_cast<DeclRefExpr>(
Privates->IgnoreParenCasts()))
5113 ReductionVarNameStr =
5116 ReductionVarNameStr =
"unnamed_priv_var";
5119 std::string SharedName =
5120 CGM.getOpenMPRuntime().getName({
"internal_pivate_", ReductionVarNameStr});
5121 llvm::GlobalVariable *SharedVar =
OMPBuilder.getOrCreateInternalVariable(
5122 LLVMType,
".omp.reduction." + SharedName);
5124 SharedVar->setAlignment(
5132 llvm::Value *BarrierArgs[] = {BarrierLoc, ThreadId};
5137 llvm::Value *IsWorker = CGF.
Builder.CreateICmpEQ(
5138 ThreadId, llvm::ConstantInt::get(ThreadId->getType(), 0));
5139 CGF.
Builder.CreateCondBr(IsWorker, InitBB, InitEndBB);
5143 auto EmitSharedInit = [&]() {
5146 std::pair<llvm::Function *, llvm::Function *> FnPair =
5148 llvm::Function *InitializerFn = FnPair.second;
5149 if (InitializerFn) {
5150 if (
const auto *CE =
5151 dyn_cast<CallExpr>(UDRInitExpr->IgnoreParenImpCasts())) {
5158 LocalScope.addPrivate(OutVD, SharedResult);
5160 (void)LocalScope.Privatize();
5161 if (
const auto *OVE = dyn_cast<OpaqueValueExpr>(
5162 CE->getCallee()->IgnoreParenImpCasts())) {
5188 if (
const auto *DRE = dyn_cast<DeclRefExpr>(
Privates)) {
5189 if (
const auto *VD = dyn_cast<VarDecl>(DRE->getDecl())) {
5200 CGF.
Builder.CreateBr(InitEndBB);
5204 CGM.getModule(), OMPRTL___kmpc_barrier),
5207 const Expr *ReductionOp = ReductionOps;
5212 auto EmitCriticalReduction = [&](
auto ReductionGen) {
5213 std::string CriticalName =
getName({
"reduction_critical"});
5221 std::pair<llvm::Function *, llvm::Function *> FnPair =
5224 if (
const auto *CE = dyn_cast<CallExpr>(ReductionOp)) {
5236 (void)LocalScope.Privatize();
5241 EmitCriticalReduction(ReductionGen);
5246 if (
const auto *Cleanup = dyn_cast<ExprWithCleanups>(ReductionClauseExpr))
5249 const Expr *AssignRHS =
nullptr;
5250 if (
const auto *BinOp = dyn_cast<BinaryOperator>(ReductionClauseExpr)) {
5251 if (BinOp->getOpcode() == BO_Assign)
5252 AssignRHS = BinOp->getRHS();
5253 }
else if (
const auto *OpCall =
5254 dyn_cast<CXXOperatorCallExpr>(ReductionClauseExpr)) {
5255 if (OpCall->getOperator() == OO_Equal)
5256 AssignRHS = OpCall->getArg(1);
5260 "Private Variable Reduction : Invalid ReductionOp expression");
5265 const auto *OmpOutDRE =
5267 const auto *OmpInDRE =
5270 OmpOutDRE && OmpInDRE &&
5271 "Private Variable Reduction : LHSExpr/RHSExpr must be DeclRefExprs");
5275 LocalScope.addPrivate(OmpOutVD, SharedLV.
getAddress());
5276 LocalScope.addPrivate(OmpInVD, LHSLV.
getAddress());
5277 (void)LocalScope.Privatize();
5281 EmitCriticalReduction(ReductionGen);
5285 CGM.getModule(), OMPRTL___kmpc_barrier),
5291 llvm::Value *FinalResultVal =
nullptr;
5295 FinalResultAddr = SharedResult;
5309 CGM.getModule(), OMPRTL___kmpc_barrier),
5320 EmitCriticalReduction(OriginalListCombiner);
5372 if (SimpleReduction) {
5374 const auto *IPriv = OrgPrivates.begin();
5375 const auto *ILHS = OrgLHSExprs.begin();
5376 const auto *IRHS = OrgRHSExprs.begin();
5377 for (
const Expr *E : OrgReductionOps) {
5390 FilteredRHSExprs, FilteredReductionOps;
5391 for (
unsigned I : llvm::seq<unsigned>(
5392 std::min(OrgReductionOps.size(), OrgLHSExprs.size()))) {
5394 FilteredPrivates.emplace_back(OrgPrivates[I]);
5395 FilteredLHSExprs.emplace_back(OrgLHSExprs[I]);
5396 FilteredRHSExprs.emplace_back(OrgRHSExprs[I]);
5397 FilteredReductionOps.emplace_back(OrgReductionOps[I]);
5409 auto Size = RHSExprs.size();
5415 llvm::APInt ArraySize(32, Size);
5416 QualType ReductionArrayTy =
C.getConstantArrayType(
5420 CGF.
CreateMemTemp(ReductionArrayTy,
".omp.reduction.red_list");
5421 const auto *IPriv =
Privates.begin();
5423 for (
unsigned I = 0, E = RHSExprs.size(); I < E; ++I, ++IPriv, ++Idx) {
5429 if ((*IPriv)->getType()->isVariablyModifiedType()) {
5433 llvm::Value *Size = CGF.
Builder.CreateIntCast(
5446 Privates, LHSExprs, RHSExprs, ReductionOps);
5449 std::string Name =
getName({
"reduction"});
5456 llvm::Value *ReductionArrayTySize = CGF.
getTypeSize(ReductionArrayTy);
5459 llvm::Value *Args[] = {
5462 CGF.
Builder.getInt32(RHSExprs.size()),
5463 ReductionArrayTySize,
5471 WithNowait ? OMPRTL___kmpc_reduce_nowait : OMPRTL___kmpc_reduce),
5475 llvm::BasicBlock *DefaultBB = CGF.
createBasicBlock(
".omp.reduction.default");
5476 llvm::SwitchInst *SwInst =
5477 CGF.
Builder.CreateSwitch(Res, DefaultBB, 2);
5486 SwInst->addCase(CGF.
Builder.getInt32(1), Case1BB);
5490 llvm::Value *EndArgs[] = {
5498 const auto *IPriv =
Privates.begin();
5499 const auto *ILHS = LHSExprs.begin();
5500 const auto *IRHS = RHSExprs.begin();
5501 for (
const Expr *E : ReductionOps) {
5510 CommonActionTy Action(
5513 CGM.getModule(), WithNowait ? OMPRTL___kmpc_end_reduce_nowait
5514 : OMPRTL___kmpc_end_reduce),
5527 SwInst->addCase(CGF.
Builder.getInt32(2), Case2BB);
5530 auto &&AtomicCodeGen = [Loc,
Privates, LHSExprs, RHSExprs, ReductionOps](
5532 const auto *ILHS = LHSExprs.begin();
5533 const auto *IRHS = RHSExprs.begin();
5534 const auto *IPriv =
Privates.begin();
5535 for (
const Expr *E : ReductionOps) {
5536 const Expr *XExpr =
nullptr;
5537 const Expr *EExpr =
nullptr;
5538 const Expr *UpExpr =
nullptr;
5540 if (
const auto *BO = dyn_cast<BinaryOperator>(E)) {
5541 if (BO->getOpcode() == BO_Assign) {
5542 XExpr = BO->getLHS();
5543 UpExpr = BO->getRHS();
5547 const Expr *RHSExpr = UpExpr;
5550 if (
const auto *ACO = dyn_cast<AbstractConditionalOperator>(
5554 RHSExpr = ACO->getCond();
5556 if (
const auto *BORHS =
5558 EExpr = BORHS->getRHS();
5559 BO = BORHS->getOpcode();
5564 auto &&AtomicRedGen = [BO, VD,
5566 const Expr *EExpr,
const Expr *UpExpr) {
5567 LValue X = CGF.EmitLValue(XExpr);
5570 E = CGF.EmitAnyExpr(EExpr);
5571 CGF.EmitOMPAtomicSimpleUpdateExpr(
5573 llvm::AtomicOrdering::Monotonic, Loc,
5574 [&CGF, UpExpr, VD, Loc](
RValue XRValue) {
5576 Address LHSTemp = CGF.CreateMemTemp(VD->getType());
5577 CGF.emitOMPSimpleStore(
5578 CGF.MakeAddrLValue(LHSTemp, VD->
getType()), XRValue,
5579 VD->getType().getNonReferenceType(), Loc);
5582 return CGF.EmitAnyExpr(UpExpr);
5585 if ((*IPriv)->getType()->isArrayType()) {
5587 const auto *RHSVar =
5590 AtomicRedGen, XExpr, EExpr, UpExpr);
5593 AtomicRedGen(CGF, XExpr, EExpr, UpExpr);
5600 std::string Name = RT.
getName({
"atomic_reduction"});
5609 if ((*IPriv)->getType()->isArrayType()) {
5610 const auto *LHSVar =
5612 const auto *RHSVar =
5617 CritRedGen(CGF,
nullptr,
nullptr,
nullptr);
5628 llvm::Value *EndArgs[] = {
5633 CommonActionTy Action(
nullptr, {},
5635 CGM.getModule(), OMPRTL___kmpc_end_reduce),
5645 assert(OrgLHSExprs.size() == OrgPrivates.size() &&
5646 "PrivateVarReduction: Privates size mismatch");
5647 assert(OrgLHSExprs.size() == OrgReductionOps.size() &&
5648 "PrivateVarReduction: ReductionOps size mismatch");
5649 for (
unsigned I : llvm::seq<unsigned>(
5650 std::min(OrgReductionOps.size(), OrgLHSExprs.size()))) {
5653 OrgRHSExprs[I], OrgReductionOps[I]);
5662 llvm::raw_svector_ostream Out(Buffer);
5670 Out << Prefix << Name <<
"_"
5672 return std::string(Out.str());
5694 Args.emplace_back(&Param);
5695 Args.emplace_back(&ParamOrig);
5696 const auto &FnInfo =
5700 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
5704 Fn->addFnAttr(
"sample-profile-suffix-elision-policy",
"selected");
5705 Fn->setDoesNotRecurse();
5712 llvm::Value *Size =
nullptr;
5755 const Expr *ReductionOp,
5757 const Expr *PrivateRef) {
5766 Args.emplace_back(&ParamInOut);
5767 Args.emplace_back(&ParamIn);
5768 const auto &FnInfo =
5772 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
5776 Fn->addFnAttr(
"sample-profile-suffix-elision-policy",
"selected");
5777 Fn->setDoesNotRecurse();
5780 llvm::Value *Size =
nullptr;
5801 C.getPointerType(LHSVD->getType())->castAs<
PointerType>()));
5808 C.getPointerType(RHSVD->getType())->castAs<
PointerType>()));
5837 Args.emplace_back(&Param);
5838 const auto &FnInfo =
5842 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
5846 Fn->addFnAttr(
"sample-profile-suffix-elision-policy",
"selected");
5847 Fn->setDoesNotRecurse();
5852 llvm::Value *Size =
nullptr;
5887 RecordDecl *RD =
C.buildImplicitRecord(
"kmp_taskred_input_t");
5896 C, RD,
C.getIntTypeForBitwidth(32,
false));
5899 unsigned Size =
Data.ReductionVars.size();
5900 llvm::APInt ArraySize(64, Size);
5902 C.getConstantArrayType(RDType, ArraySize,
nullptr,
5907 Data.ReductionCopies,
Data.ReductionOps);
5908 for (
unsigned Cnt = 0; Cnt < Size; ++Cnt) {
5910 llvm::Value *Idxs[] = {llvm::ConstantInt::get(
CGM.SizeTy, 0),
5911 llvm::ConstantInt::get(
CGM.SizeTy, Cnt)};
5927 llvm::Value *SizeValInChars;
5928 llvm::Value *SizeVal;
5929 std::tie(SizeValInChars, SizeVal) = RCG.
getSizes(Cnt);
5935 bool DelayedCreation = !!SizeVal;
5936 SizeValInChars = CGF.
Builder.CreateIntCast(SizeValInChars,
CGM.SizeTy,
5947 llvm::Value *FiniAddr =
5948 Fini ? Fini : llvm::ConstantPointerNull::get(
CGM.VoidPtrTy);
5953 CGM, Loc, RCG, Cnt,
Data.ReductionOps[Cnt], LHSExprs[Cnt],
5954 RHSExprs[Cnt],
Data.ReductionCopies[Cnt]);
5958 if (DelayedCreation) {
5960 llvm::ConstantInt::get(
CGM.Int32Ty, 1,
true),
5965 if (
Data.IsReductionWithTaskMod) {
5971 llvm::Value *Args[] = {
5973 llvm::ConstantInt::get(
CGM.IntTy,
Data.IsWorksharingReduction ? 1 : 0,
5975 llvm::ConstantInt::get(
CGM.IntTy, Size,
true),
5980 CGM.getModule(), OMPRTL___kmpc_taskred_modifier_init),
5984 llvm::Value *Args[] = {
5987 llvm::ConstantInt::get(
CGM.IntTy, Size,
true),
5991 CGM.getModule(), OMPRTL___kmpc_taskred_init),
5997 bool IsWorksharingReduction) {
6003 llvm::Value *Args[] = {IdentTLoc, GTid,
6004 llvm::ConstantInt::get(
CGM.IntTy,
6005 IsWorksharingReduction ? 1 : 0,
6009 CGM.getModule(), OMPRTL___kmpc_task_reduction_modifier_fini),
6021 llvm::Value *SizeVal = CGF.
Builder.CreateIntCast(Sizes.second,
CGM.SizeTy,
6024 CGF,
CGM.getContext().getSizeType(),
6032 llvm::Value *ReductionsPtr,
6045 CGM.getModule(), OMPRTL___kmpc_task_reduction_get_th_data),
6061 auto &M =
CGM.getModule();
6063 llvm::Value *NumOfElements;
6064 std::tie(NumOfElements, DependenciesArray) =
6066 if (!
Data.Dependences.empty()) {
6067 llvm::Value *DepWaitTaskArgs[7];
6068 DepWaitTaskArgs[0] = UpLoc;
6069 DepWaitTaskArgs[1] = ThreadID;
6070 DepWaitTaskArgs[2] = NumOfElements;
6072 DepWaitTaskArgs[4] = CGF.
Builder.getInt32(0);
6073 DepWaitTaskArgs[5] = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
6074 DepWaitTaskArgs[6] =
6075 llvm::ConstantInt::get(CGF.
Int32Ty,
Data.HasNowaitClause);
6084 M, OMPRTL___kmpc_omp_taskwait_deps_51),
6091 llvm::Value *Args[] = {UpLoc, ThreadID};
6094 OMPBuilder.getOrCreateRuntimeFunction(M, OMPRTL___kmpc_omp_taskwait),
6099 if (
auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.
CapturedStmtInfo))
6100 Region->emitUntiedSwitch(CGF);
6109 InlinedOpenMPRegionRAII Region(CGF,
CodeGen, InnerKind, HasCancel,
6110 InnerKind != OMPD_critical &&
6111 InnerKind != OMPD_master &&
6112 InnerKind != OMPD_masked);
6127 RTCancelKind CancelKind = CancelNoreq;
6128 if (CancelRegion == OMPD_parallel)
6129 CancelKind = CancelParallel;
6130 else if (CancelRegion == OMPD_for)
6131 CancelKind = CancelLoop;
6132 else if (CancelRegion == OMPD_sections)
6133 CancelKind = CancelSections;
6135 assert(CancelRegion == OMPD_taskgroup);
6136 CancelKind = CancelTaskgroup;
6148 if (
auto *OMPRegionInfo =
6152 if (CancelRegion == OMPD_taskgroup || OMPRegionInfo->hasCancel()) {
6153 llvm::Value *Args[] = {
6159 CGM.getModule(), OMPRTL___kmpc_cancellationpoint),
6168 CGF.
Builder.CreateCondBr(Cmp, ExitBB, ContBB);
6170 if (CancelRegion == OMPD_parallel)
6188 auto &M =
CGM.getModule();
6189 if (
auto *OMPRegionInfo =
6191 auto &&ThenGen = [
this, &M, Loc, CancelRegion,
6194 llvm::Value *Args[] = {
6198 llvm::Value *
Result = CGF.EmitRuntimeCall(
6199 OMPBuilder.getOrCreateRuntimeFunction(M, OMPRTL___kmpc_cancel), Args);
6204 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(
".cancel.exit");
6205 llvm::BasicBlock *ContBB = CGF.createBasicBlock(
".cancel.continue");
6206 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(
Result);
6207 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB);
6208 CGF.EmitBlock(ExitBB);
6209 if (CancelRegion == OMPD_parallel)
6213 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind());
6214 CGF.EmitBranchThroughCleanup(CancelDest);
6215 CGF.EmitBlock(ContBB,
true);
6233 OMPUsesAllocatorsActionTy(
6234 ArrayRef<std::pair<const Expr *, const Expr *>> Allocators)
6235 : Allocators(Allocators) {}
6239 for (
const auto &AllocatorData : Allocators) {
6241 CGF, AllocatorData.first, AllocatorData.second);
6244 void Exit(CodeGenFunction &CGF)
override {
6247 for (
const auto &AllocatorData : Allocators) {
6249 AllocatorData.first);
6257 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
6259 assert(!ParentName.empty() &&
"Invalid target entry parent name!");
6263 for (
unsigned I = 0, E =
C->getNumberOfAllocators(); I < E; ++I) {
6270 OMPUsesAllocatorsActionTy UsesAllocatorAction(Allocators);
6271 CodeGen.setAction(UsesAllocatorAction);
6277 const Expr *Allocator,
6278 const Expr *AllocatorTraits) {
6280 ThreadId = CGF.
Builder.CreateIntCast(ThreadId, CGF.
IntTy,
true);
6282 llvm::Value *MemSpaceHandle = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
6283 llvm::Value *NumTraits = llvm::ConstantInt::get(
6287 .getLimitedValue());
6294 llvm::Value *Traits =
Addr.emitRawPointer(CGF);
6296 llvm::Value *AllocatorVal =
6298 CGM.getModule(), OMPRTL___kmpc_init_allocator),
6299 {ThreadId, MemSpaceHandle, NumTraits, Traits});
6311 const Expr *Allocator) {
6313 ThreadId = CGF.
Builder.CreateIntCast(ThreadId, CGF.
IntTy,
true);
6315 llvm::Value *AllocatorVal =
6322 OMPRTL___kmpc_destroy_allocator),
6323 {ThreadId, AllocatorVal});
6328 llvm::OpenMPIRBuilder::TargetKernelDefaultAttrs &Attrs) {
6329 assert(Attrs.MaxTeams.size() == 1 && Attrs.MaxThreads.size() == 1 &&
6330 "invalid default attrs structure");
6331 int32_t &MaxTeamsVal = Attrs.MaxTeams.front();
6332 int32_t &MaxThreadsVal = Attrs.MaxThreads.front();
6339 for (
auto *A :
C->getAttrs()) {
6340 int32_t AttrMinThreadsVal = 1, AttrMaxThreadsVal = -1;
6341 int32_t AttrMinBlocksVal = 1, AttrMaxBlocksVal = -1;
6342 if (
auto *
Attr = dyn_cast<CUDALaunchBoundsAttr>(A))
6343 CGM.handleCUDALaunchBoundsAttr(
nullptr,
Attr, &AttrMaxThreadsVal,
6344 &AttrMinBlocksVal, &AttrMaxBlocksVal);
6345 else if (
auto *
Attr = dyn_cast<AMDGPUFlatWorkGroupSizeAttr>(A))
6346 CGM.handleAMDGPUFlatWorkGroupSizeAttr(
6347 nullptr,
Attr,
nullptr, &AttrMinThreadsVal,
6348 &AttrMaxThreadsVal);
6352 Attrs.MinThreads = std::max(Attrs.MinThreads, AttrMinThreadsVal);
6353 if (AttrMaxThreadsVal > 0)
6354 MaxThreadsVal = MaxThreadsVal > 0
6355 ? std::min(MaxThreadsVal, AttrMaxThreadsVal)
6356 : AttrMaxThreadsVal;
6357 Attrs.MinTeams = std::max(Attrs.MinTeams, AttrMinBlocksVal);
6358 if (AttrMaxBlocksVal > 0)
6359 MaxTeamsVal = MaxTeamsVal > 0 ? std::min(MaxTeamsVal, AttrMaxBlocksVal)
6367 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
6370 llvm::TargetRegionEntryInfo EntryInfo =
6374 llvm::OpenMPIRBuilder::FunctionGenCallback &&GenerateOutlinedFunction =
6375 [&CGF, &D, &
CodeGen](StringRef EntryFnName) {
6376 const CapturedStmt &CS = *D.getCapturedStmt(OMPD_target);
6378 CGOpenMPTargetRegionInfo CGInfo(CS,
CodeGen, EntryFnName);
6383 cantFail(
OMPBuilder.emitTargetRegionFunction(
6384 EntryInfo, GenerateOutlinedFunction, IsOffloadEntry, OutlinedFn,
6390 CGM.getTargetCodeGenInfo().setTargetAttributes(
nullptr, OutlinedFn,
CGM);
6393 for (
auto *A :
C->getAttrs()) {
6394 if (
auto *
Attr = dyn_cast<AMDGPUWavesPerEUAttr>(A))
6395 CGM.handleAMDGPUWavesPerEUAttr(OutlinedFn,
Attr);
6414 while (
const auto *
C = dyn_cast_or_null<CompoundStmt>(Child)) {
6416 for (
const Stmt *S :
C->body()) {
6417 if (
const auto *E = dyn_cast<Expr>(S)) {
6426 if (
const auto *DS = dyn_cast<DeclStmt>(S)) {
6427 if (llvm::all_of(DS->decls(), [](
const Decl *D) {
6428 if (isa<EmptyDecl>(D) || isa<DeclContext>(D) ||
6429 isa<TypeDecl>(D) || isa<PragmaCommentDecl>(D) ||
6430 isa<PragmaDetectMismatchDecl>(D) || isa<UsingDecl>(D) ||
6431 isa<UsingDirectiveDecl>(D) ||
6432 isa<OMPDeclareReductionDecl>(D) ||
6433 isa<OMPThreadPrivateDecl>(D) || isa<OMPAllocateDecl>(D))
6435 const auto *VD = dyn_cast<VarDecl>(D);
6438 return VD->hasGlobalStorage() || !VD->isUsed();
6448 Child = Child->IgnoreContainers();
6455 int32_t &MaxTeamsVal) {
6459 "Expected target-based executable directive.");
6460 switch (DirectiveKind) {
6462 const auto *CS = D.getInnermostCapturedStmt();
6465 const Stmt *ChildStmt =
6467 if (
const auto *NestedDir =
6468 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) {
6477 MinTeamsVal = MaxTeamsVal = Constant->getExtValue();
6480 MinTeamsVal = MaxTeamsVal = 0;
6483 MinTeamsVal = MaxTeamsVal = 1;
6487 MinTeamsVal = MaxTeamsVal = -1;
6490 case OMPD_target_teams_loop:
6491 case OMPD_target_teams:
6492 case OMPD_target_teams_distribute:
6493 case OMPD_target_teams_distribute_simd:
6494 case OMPD_target_teams_distribute_parallel_for:
6495 case OMPD_target_teams_distribute_parallel_for_simd: {
6497 const Expr *NumTeams =
6501 MinTeamsVal = MaxTeamsVal = Constant->getExtValue();
6504 MinTeamsVal = MaxTeamsVal = 0;
6507 case OMPD_target_parallel:
6508 case OMPD_target_parallel_for:
6509 case OMPD_target_parallel_for_simd:
6510 case OMPD_target_parallel_loop:
6511 case OMPD_target_simd:
6512 MinTeamsVal = MaxTeamsVal = 1;
6516 case OMPD_parallel_for:
6517 case OMPD_parallel_loop:
6518 case OMPD_parallel_master:
6519 case OMPD_parallel_sections:
6521 case OMPD_parallel_for_simd:
6523 case OMPD_cancellation_point:
6525 case OMPD_threadprivate:
6536 case OMPD_taskyield:
6539 case OMPD_taskgroup:
6545 case OMPD_target_data:
6546 case OMPD_target_exit_data:
6547 case OMPD_target_enter_data:
6548 case OMPD_distribute:
6549 case OMPD_distribute_simd:
6550 case OMPD_distribute_parallel_for:
6551 case OMPD_distribute_parallel_for_simd:
6552 case OMPD_teams_distribute:
6553 case OMPD_teams_distribute_simd:
6554 case OMPD_teams_distribute_parallel_for:
6555 case OMPD_teams_distribute_parallel_for_simd:
6556 case OMPD_target_update:
6557 case OMPD_declare_simd:
6558 case OMPD_declare_variant:
6559 case OMPD_begin_declare_variant:
6560 case OMPD_end_declare_variant:
6561 case OMPD_declare_target:
6562 case OMPD_end_declare_target:
6563 case OMPD_declare_reduction:
6564 case OMPD_declare_mapper:
6566 case OMPD_taskloop_simd:
6567 case OMPD_master_taskloop:
6568 case OMPD_master_taskloop_simd:
6569 case OMPD_parallel_master_taskloop:
6570 case OMPD_parallel_master_taskloop_simd:
6572 case OMPD_metadirective:
6578 llvm_unreachable(
"Unexpected directive kind.");
6584 "Clauses associated with the teams directive expected to be emitted "
6585 "only for the host!");
6587 int32_t MinNT = -1, MaxNT = -1;
6588 const Expr *NumTeams =
6590 if (NumTeams !=
nullptr) {
6593 switch (DirectiveKind) {
6595 const auto *CS = D.getInnermostCapturedStmt();
6596 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6600 return Bld.CreateIntCast(NumTeamsVal, CGF.
Int32Ty,
6603 case OMPD_target_teams:
6604 case OMPD_target_teams_distribute:
6605 case OMPD_target_teams_distribute_simd:
6606 case OMPD_target_teams_distribute_parallel_for:
6607 case OMPD_target_teams_distribute_parallel_for_simd: {
6611 return Bld.CreateIntCast(NumTeamsVal, CGF.
Int32Ty,
6619 assert(MinNT == MaxNT &&
"Num threads ranges require handling here.");
6620 return llvm::ConstantInt::getSigned(CGF.
Int32Ty, MinNT);
6628 const Expr **E, int32_t &UpperBound,
6629 bool UpperBoundOnly, llvm::Value **CondVal) {
6632 const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child);
6639 if (CondVal && Dir->hasClausesOfKind<
OMPIfClause>()) {
6640 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6643 for (
const auto *
C : Dir->getClausesOfKind<
OMPIfClause>()) {
6644 if (
C->getNameModifier() == OMPD_unknown ||
6645 C->getNameModifier() == OMPD_parallel) {
6660 if (
const auto *PreInit =
6662 for (
const auto *I : PreInit->decls()) {
6663 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
6679 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6681 const auto *NumThreadsClause =
6683 const Expr *NTExpr = NumThreadsClause->getNumThreads();
6684 if (NTExpr->isIntegerConstantExpr(CGF.
getContext()))
6685 if (
auto Constant = NTExpr->getIntegerConstantExpr(CGF.
getContext()))
6688 ? Constant->getZExtValue()
6689 : std::min(UpperBound,
6690 static_cast<int32_t
>(Constant->getZExtValue()));
6693 if (UpperBound == -1)
6698 if (
const auto *PreInit =
6699 cast_or_null<DeclStmt>(NumThreadsClause->getPreInitStmt())) {
6700 for (
const auto *I : PreInit->decls()) {
6701 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
6720 bool UpperBoundOnly, llvm::Value **CondVal,
const Expr **ThreadLimitExpr) {
6721 assert((!CGF.
getLangOpts().OpenMPIsTargetDevice || UpperBoundOnly) &&
6722 "Clauses associated with the teams directive expected to be emitted "
6723 "only for the host!");
6726 "Expected target-based executable directive.");
6728 const Expr *NT =
nullptr;
6729 const Expr **NTPtr = UpperBoundOnly ?
nullptr : &NT;
6731 auto CheckForConstExpr = [&](
const Expr *E,
const Expr **EPtr) {
6734 UpperBound = UpperBound ? Constant->getZExtValue()
6735 : std::min(UpperBound,
6736 int32_t(Constant->getZExtValue()));
6740 if (UpperBound == -1)
6746 auto ReturnSequential = [&]() {
6751 switch (DirectiveKind) {
6754 getNumThreads(CGF, CS, NTPtr, UpperBound, UpperBoundOnly, CondVal);
6760 if (
const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) {
6762 ThreadLimitClause = TLC;
6763 if (ThreadLimitExpr) {
6764 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6768 ThreadLimitClause->getThreadLimit().front()->getSourceRange());
6769 if (
const auto *PreInit =
6770 cast_or_null<DeclStmt>(ThreadLimitClause->getPreInitStmt())) {
6771 for (
const auto *I : PreInit->decls()) {
6772 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
6784 if (ThreadLimitClause)
6785 CheckForConstExpr(ThreadLimitClause->getThreadLimit().front(),
6787 if (
const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) {
6790 CS = Dir->getInnermostCapturedStmt();
6793 Dir = dyn_cast_or_null<OMPExecutableDirective>(Child);
6796 CS = Dir->getInnermostCapturedStmt();
6797 getNumThreads(CGF, CS, NTPtr, UpperBound, UpperBoundOnly, CondVal);
6799 return ReturnSequential();
6803 case OMPD_target_teams: {
6807 CheckForConstExpr(ThreadLimitClause->getThreadLimit().front(),
6811 getNumThreads(CGF, CS, NTPtr, UpperBound, UpperBoundOnly, CondVal);
6814 if (
const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) {
6815 if (Dir->getDirectiveKind() == OMPD_distribute) {
6816 CS = Dir->getInnermostCapturedStmt();
6817 getNumThreads(CGF, CS, NTPtr, UpperBound, UpperBoundOnly, CondVal);
6822 case OMPD_target_teams_distribute:
6826 CheckForConstExpr(ThreadLimitClause->getThreadLimit().front(),
6829 getNumThreads(CGF, D.getInnermostCapturedStmt(), NTPtr, UpperBound,
6830 UpperBoundOnly, CondVal);
6832 case OMPD_target_teams_loop:
6833 case OMPD_target_parallel_loop:
6834 case OMPD_target_parallel:
6835 case OMPD_target_parallel_for:
6836 case OMPD_target_parallel_for_simd:
6837 case OMPD_target_teams_distribute_parallel_for:
6838 case OMPD_target_teams_distribute_parallel_for_simd: {
6839 if (CondVal && D.hasClausesOfKind<
OMPIfClause>()) {
6841 for (
const auto *
C : D.getClausesOfKind<
OMPIfClause>()) {
6842 if (
C->getNameModifier() == OMPD_unknown ||
6843 C->getNameModifier() == OMPD_parallel) {
6853 return ReturnSequential();
6863 CheckForConstExpr(ThreadLimitClause->getThreadLimit().front(),
6869 CheckForConstExpr(NumThreadsClause->getNumThreads(),
nullptr);
6870 return NumThreadsClause->getNumThreads();
6874 case OMPD_target_teams_distribute_simd:
6875 case OMPD_target_simd:
6876 return ReturnSequential();
6880 llvm_unreachable(
"Unsupported directive kind.");
6885 llvm::Value *NumThreadsVal =
nullptr;
6886 llvm::Value *CondVal =
nullptr;
6887 llvm::Value *ThreadLimitVal =
nullptr;
6888 const Expr *ThreadLimitExpr =
nullptr;
6889 int32_t UpperBound = -1;
6892 CGF, D, UpperBound,
false, &CondVal,
6896 if (ThreadLimitExpr) {
6899 ThreadLimitVal = CGF.
Builder.CreateIntCast(ThreadLimitVal, CGF.
Int32Ty,
6904 if (UpperBound == 1) {
6905 NumThreadsVal = CGF.
Builder.getInt32(UpperBound);
6908 NumThreadsVal = CGF.
Builder.CreateIntCast(NumThreadsVal, CGF.
Int32Ty,
6910 }
else if (ThreadLimitVal) {
6913 NumThreadsVal = ThreadLimitVal;
6914 ThreadLimitVal =
nullptr;
6917 assert(!ThreadLimitVal &&
"Default not applicable with thread limit value");
6918 NumThreadsVal = CGF.
Builder.getInt32(0);
6925 NumThreadsVal = CGF.
Builder.CreateSelect(CondVal, NumThreadsVal,
6931 if (ThreadLimitVal) {
6932 NumThreadsVal = CGF.
Builder.CreateSelect(
6933 CGF.
Builder.CreateICmpULT(ThreadLimitVal, NumThreadsVal),
6934 ThreadLimitVal, NumThreadsVal);
6937 return NumThreadsVal;
6947class MappableExprsHandler {
6953 struct AttachPtrExprComparator {
6954 const MappableExprsHandler &Handler;
6956 mutable llvm::DenseMap<std::pair<const Expr *, const Expr *>,
bool>
6957 CachedEqualityComparisons;
6959 AttachPtrExprComparator(
const MappableExprsHandler &H) : Handler(H) {}
6960 AttachPtrExprComparator() =
delete;
6963 bool operator()(
const Expr *LHS,
const Expr *RHS)
const {
6968 const auto ItLHS = Handler.AttachPtrComponentDepthMap.find(LHS);
6969 const auto ItRHS = Handler.AttachPtrComponentDepthMap.find(RHS);
6971 std::optional<size_t> DepthLHS =
6972 (ItLHS != Handler.AttachPtrComponentDepthMap.end()) ? ItLHS->second
6974 std::optional<size_t> DepthRHS =
6975 (ItRHS != Handler.AttachPtrComponentDepthMap.end()) ? ItRHS->second
6979 if (!DepthLHS.has_value() && !DepthRHS.has_value()) {
6981 if (areEqual(LHS, RHS))
6984 return wasComputedBefore(LHS, RHS);
6986 if (!DepthLHS.has_value())
6988 if (!DepthRHS.has_value())
6992 if (DepthLHS.value() != DepthRHS.value())
6993 return DepthLHS.value() < DepthRHS.value();
6996 if (areEqual(LHS, RHS))
6999 return wasComputedBefore(LHS, RHS);
7005 bool areEqual(
const Expr *LHS,
const Expr *RHS)
const {
7007 const auto CachedResultIt = CachedEqualityComparisons.find({LHS, RHS});
7008 if (CachedResultIt != CachedEqualityComparisons.end())
7009 return CachedResultIt->second;
7023 bool wasComputedBefore(
const Expr *LHS,
const Expr *RHS)
const {
7024 const size_t &OrderLHS = Handler.AttachPtrComputationOrderMap.at(LHS);
7025 const size_t &OrderRHS = Handler.AttachPtrComputationOrderMap.at(RHS);
7027 return OrderLHS < OrderRHS;
7036 bool areSemanticallyEqual(
const Expr *LHS,
const Expr *RHS)
const {
7058 if (
const auto *LD = dyn_cast<DeclRefExpr>(LHS)) {
7059 const auto *RD = dyn_cast<DeclRefExpr>(RHS);
7062 return LD->getDecl()->getCanonicalDecl() ==
7063 RD->getDecl()->getCanonicalDecl();
7067 if (
const auto *LA = dyn_cast<ArraySubscriptExpr>(LHS)) {
7068 const auto *RA = dyn_cast<ArraySubscriptExpr>(RHS);
7071 return areSemanticallyEqual(LA->getBase(), RA->getBase()) &&
7072 areSemanticallyEqual(LA->getIdx(), RA->getIdx());
7076 if (
const auto *LM = dyn_cast<MemberExpr>(LHS)) {
7077 const auto *RM = dyn_cast<MemberExpr>(RHS);
7080 if (LM->getMemberDecl()->getCanonicalDecl() !=
7081 RM->getMemberDecl()->getCanonicalDecl())
7083 return areSemanticallyEqual(LM->getBase(), RM->getBase());
7087 if (
const auto *LU = dyn_cast<UnaryOperator>(LHS)) {
7088 const auto *RU = dyn_cast<UnaryOperator>(RHS);
7091 if (LU->getOpcode() != RU->getOpcode())
7093 return areSemanticallyEqual(LU->getSubExpr(), RU->getSubExpr());
7097 if (
const auto *LB = dyn_cast<BinaryOperator>(LHS)) {
7098 const auto *RB = dyn_cast<BinaryOperator>(RHS);
7101 if (LB->getOpcode() != RB->getOpcode())
7103 return areSemanticallyEqual(LB->getLHS(), RB->getLHS()) &&
7104 areSemanticallyEqual(LB->getRHS(), RB->getRHS());
7110 if (
const auto *LAS = dyn_cast<ArraySectionExpr>(LHS)) {
7111 const auto *RAS = dyn_cast<ArraySectionExpr>(RHS);
7114 return areSemanticallyEqual(LAS->getBase(), RAS->getBase()) &&
7115 areSemanticallyEqual(LAS->getLowerBound(),
7116 RAS->getLowerBound()) &&
7117 areSemanticallyEqual(LAS->getLength(), RAS->getLength());
7121 if (
const auto *LC = dyn_cast<CastExpr>(LHS)) {
7122 const auto *RC = dyn_cast<CastExpr>(RHS);
7125 if (LC->getCastKind() != RC->getCastKind())
7127 return areSemanticallyEqual(LC->getSubExpr(), RC->getSubExpr());
7135 if (
const auto *LI = dyn_cast<IntegerLiteral>(LHS)) {
7136 const auto *RI = dyn_cast<IntegerLiteral>(RHS);
7139 return LI->getValue() == RI->getValue();
7143 if (
const auto *LC = dyn_cast<CharacterLiteral>(LHS)) {
7144 const auto *RC = dyn_cast<CharacterLiteral>(RHS);
7147 return LC->getValue() == RC->getValue();
7151 if (
const auto *LF = dyn_cast<FloatingLiteral>(LHS)) {
7152 const auto *RF = dyn_cast<FloatingLiteral>(RHS);
7156 return LF->getValue().bitwiseIsEqual(RF->getValue());
7160 if (
const auto *LS = dyn_cast<StringLiteral>(LHS)) {
7161 const auto *RS = dyn_cast<StringLiteral>(RHS);
7164 return LS->getString() == RS->getString();
7172 if (
const auto *LB = dyn_cast<CXXBoolLiteralExpr>(LHS)) {
7173 const auto *RB = dyn_cast<CXXBoolLiteralExpr>(RHS);
7176 return LB->getValue() == RB->getValue();
7185 static unsigned getFlagMemberOffset() {
7186 unsigned Offset = 0;
7187 for (uint64_t Remain =
7188 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
7189 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF);
7190 !(Remain & 1); Remain = Remain >> 1)
7197 class MappingExprInfo {
7199 const ValueDecl *MapDecl =
nullptr;
7202 const Expr *MapExpr =
nullptr;
7205 MappingExprInfo(
const ValueDecl *MapDecl,
const Expr *MapExpr =
nullptr)
7206 : MapDecl(MapDecl), MapExpr(MapExpr) {}
7208 const ValueDecl *getMapDecl()
const {
return MapDecl; }
7209 const Expr *getMapExpr()
const {
return MapExpr; }
7212 using DeviceInfoTy = llvm::OpenMPIRBuilder::DeviceInfoTy;
7213 using MapBaseValuesArrayTy = llvm::OpenMPIRBuilder::MapValuesArrayTy;
7214 using MapValuesArrayTy = llvm::OpenMPIRBuilder::MapValuesArrayTy;
7215 using MapFlagsArrayTy = llvm::OpenMPIRBuilder::MapFlagsArrayTy;
7216 using MapDimArrayTy = llvm::OpenMPIRBuilder::MapDimArrayTy;
7217 using MapNonContiguousArrayTy =
7218 llvm::OpenMPIRBuilder::MapNonContiguousArrayTy;
7219 using MapExprsArrayTy = SmallVector<MappingExprInfo, 4>;
7220 using MapValueDeclsArrayTy = SmallVector<const ValueDecl *, 4>;
7224 bool ,
const ValueDecl *,
const Expr *>;
7225 using MapDataArrayTy = SmallVector<MapData, 4>;
7230 struct MapCombinedInfoTy : llvm::OpenMPIRBuilder::MapInfosTy {
7231 MapExprsArrayTy Exprs;
7232 MapValueDeclsArrayTy Mappers;
7233 MapValueDeclsArrayTy DevicePtrDecls;
7236 void append(MapCombinedInfoTy &CurInfo) {
7237 Exprs.append(CurInfo.Exprs.begin(), CurInfo.Exprs.end());
7238 DevicePtrDecls.append(CurInfo.DevicePtrDecls.begin(),
7239 CurInfo.DevicePtrDecls.end());
7240 Mappers.append(CurInfo.Mappers.begin(), CurInfo.Mappers.end());
7241 llvm::OpenMPIRBuilder::MapInfosTy::append(CurInfo);
7249 struct StructRangeInfoTy {
7250 MapCombinedInfoTy PreliminaryMapData;
7251 std::pair<
unsigned , Address > LowestElem = {
7253 std::pair<
unsigned , Address > HighestElem = {
7257 bool IsArraySection =
false;
7258 bool HasCompleteRecord =
false;
7263 struct AttachInfoTy {
7266 const ValueDecl *AttachPtrDecl =
nullptr;
7267 const Expr *AttachMapExpr =
nullptr;
7269 bool isValid()
const {
7276 bool hasAttachEntryForCapturedVar(
const ValueDecl *VD)
const {
7277 for (
const auto &AttachEntry : AttachPtrExprMap) {
7278 if (AttachEntry.second) {
7281 if (
const auto *DRE = dyn_cast<DeclRefExpr>(AttachEntry.second))
7282 if (DRE->getDecl() == VD)
7290 const Expr *getAttachPtrExpr(
7293 const auto It = AttachPtrExprMap.find(Components);
7294 if (It != AttachPtrExprMap.end())
7305 ArrayRef<OpenMPMapModifierKind> MapModifiers;
7306 ArrayRef<OpenMPMotionModifierKind> MotionModifiers;
7307 bool ReturnDevicePointer =
false;
7308 bool IsImplicit =
false;
7309 const ValueDecl *Mapper =
nullptr;
7310 const Expr *VarRef =
nullptr;
7311 bool ForDeviceAddr =
false;
7312 bool HasUdpFbNullify =
false;
7314 MapInfo() =
default;
7318 ArrayRef<OpenMPMapModifierKind> MapModifiers,
7319 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
7320 bool ReturnDevicePointer,
bool IsImplicit,
7321 const ValueDecl *Mapper =
nullptr,
const Expr *VarRef =
nullptr,
7322 bool ForDeviceAddr =
false,
bool HasUdpFbNullify =
false)
7323 : Components(Components), MapType(MapType), MapModifiers(MapModifiers),
7324 MotionModifiers(MotionModifiers),
7325 ReturnDevicePointer(ReturnDevicePointer), IsImplicit(IsImplicit),
7326 Mapper(Mapper), VarRef(VarRef), ForDeviceAddr(ForDeviceAddr),
7327 HasUdpFbNullify(HasUdpFbNullify) {}
7332 llvm::PointerUnion<
const OMPExecutableDirective *,
7333 const OMPDeclareMapperDecl *>
7337 CodeGenFunction &CGF;
7342 llvm::DenseMap<CanonicalDeclPtr<const VarDecl>,
bool> FirstPrivateDecls;
7345 llvm::SmallSet<OpenMPDefaultmapClauseKind, 4> DefaultmapFirstprivateKinds;
7351 SmallVector<OMPClauseMappableExprCommon::MappableExprComponentListRef, 4>>
7358 SmallVector<OMPClauseMappableExprCommon::MappableExprComponentListRef, 4>>
7362 llvm::DenseMap<const ValueDecl *, const OMPMapClause *> LambdasMap;
7377 llvm::DenseMap<const Expr *, std::optional<size_t>>
7378 AttachPtrComponentDepthMap = {{
nullptr, std::nullopt}};
7382 llvm::DenseMap<const Expr *, size_t> AttachPtrComputationOrderMap = {
7387 AttachPtrExprComparator AttachPtrComparator;
7389 llvm::Value *getExprTypeSize(
const Expr *E)
const {
7393 if (
const auto *OAE = dyn_cast<OMPArrayShapingExpr>(E)) {
7395 CGF.
getTypeSize(OAE->getBase()->getType()->getPointeeType());
7396 for (
const Expr *SE : OAE->getDimensions()) {
7407 if (
const auto *RefTy = ExprTy->
getAs<ReferenceType>())
7413 if (
const auto *OAE = dyn_cast<ArraySectionExpr>(E)) {
7415 OAE->getBase()->IgnoreParenImpCasts())
7421 if (!OAE->getLength() && OAE->getColonLocFirst().isValid() &&
7422 !OAE->getLowerBound())
7425 llvm::Value *ElemSize;
7426 if (
const auto *PTy = BaseTy->
getAs<PointerType>()) {
7427 ElemSize = CGF.
getTypeSize(PTy->getPointeeType().getCanonicalType());
7430 assert(ATy &&
"Expecting array type if not a pointer type.");
7431 ElemSize = CGF.
getTypeSize(ATy->getElementType().getCanonicalType());
7436 if (!OAE->getLength() && OAE->getColonLocFirst().isInvalid())
7439 if (
const Expr *LenExpr = OAE->getLength()) {
7443 LenExpr->getExprLoc());
7444 return CGF.
Builder.CreateNUWMul(LengthVal, ElemSize);
7446 assert(!OAE->getLength() && OAE->getColonLocFirst().isValid() &&
7447 OAE->getLowerBound() &&
"expected array_section[lb:].");
7453 OAE->getLowerBound()->getExprLoc());
7454 LBVal = CGF.
Builder.CreateNUWMul(LBVal, ElemSize);
7455 llvm::Value *Cmp = CGF.
Builder.CreateICmpUGT(LengthVal, LBVal);
7456 llvm::Value *TrueVal = CGF.
Builder.CreateNUWSub(LengthVal, LBVal);
7457 LengthVal = CGF.
Builder.CreateSelect(
7458 Cmp, TrueVal, llvm::ConstantInt::get(CGF.
SizeTy, 0));
7468 OpenMPOffloadMappingFlags getMapTypeBits(
7470 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
bool IsImplicit,
7471 bool AddPtrFlag,
bool AddIsTargetParamFlag,
bool IsNonContiguous)
const {
7472 OpenMPOffloadMappingFlags Bits =
7473 IsImplicit ? OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT
7474 : OpenMPOffloadMappingFlags::OMP_MAP_NONE;
7476 case OMPC_MAP_alloc:
7477 case OMPC_MAP_release:
7484 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_TO;
7487 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_FROM;
7489 case OMPC_MAP_tofrom:
7490 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_TO |
7491 OpenMPOffloadMappingFlags::OMP_MAP_FROM;
7493 case OMPC_MAP_delete:
7494 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_DELETE;
7497 llvm_unreachable(
"Unexpected map type!");
7500 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ;
7501 if (AddIsTargetParamFlag)
7502 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM;
7503 if (llvm::is_contained(MapModifiers, OMPC_MAP_MODIFIER_always))
7504 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_ALWAYS;
7505 if (llvm::is_contained(MapModifiers, OMPC_MAP_MODIFIER_close))
7506 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_CLOSE;
7507 if (llvm::is_contained(MapModifiers, OMPC_MAP_MODIFIER_present) ||
7508 llvm::is_contained(MotionModifiers, OMPC_MOTION_MODIFIER_present))
7509 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_PRESENT;
7510 if (llvm::is_contained(MapModifiers, OMPC_MAP_MODIFIER_ompx_hold))
7511 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_OMPX_HOLD;
7512 if (IsNonContiguous)
7513 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_NON_CONTIG;
7519 bool isFinalArraySectionExpression(
const Expr *E)
const {
7520 const auto *OASE = dyn_cast<ArraySectionExpr>(E);
7527 if (OASE->getColonLocFirst().isInvalid())
7530 const Expr *Length = OASE->getLength();
7537 OASE->getBase()->IgnoreParenImpCasts())
7539 if (
const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.
getTypePtr()))
7540 return ATy->getSExtSize() != 1;
7552 llvm::APSInt ConstLength =
Result.Val.getInt();
7553 return ConstLength.getSExtValue() != 1;
7560 void emitAttachEntry(CodeGenFunction &CGF, MapCombinedInfoTy &CombinedInfo,
7561 const AttachInfoTy &AttachInfo)
const {
7562 assert(AttachInfo.isValid() &&
7563 "Expected valid attach pointer/pointee information!");
7567 llvm::Value *PointerSize = CGF.
Builder.CreateIntCast(
7568 llvm::ConstantInt::get(
7574 CombinedInfo.Exprs.emplace_back(AttachInfo.AttachPtrDecl,
7575 AttachInfo.AttachMapExpr);
7576 CombinedInfo.BasePointers.push_back(
7577 AttachInfo.AttachPtrAddr.emitRawPointer(CGF));
7578 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
7579 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
7580 CombinedInfo.Pointers.push_back(
7581 AttachInfo.AttachPteeAddr.emitRawPointer(CGF));
7582 CombinedInfo.Sizes.push_back(PointerSize);
7583 CombinedInfo.Types.push_back(OpenMPOffloadMappingFlags::OMP_MAP_ATTACH);
7584 CombinedInfo.Mappers.push_back(
nullptr);
7585 CombinedInfo.NonContigInfo.Dims.push_back(1);
7592 class CopyOverlappedEntryGaps {
7593 CodeGenFunction &CGF;
7594 MapCombinedInfoTy &CombinedInfo;
7595 OpenMPOffloadMappingFlags Flags = OpenMPOffloadMappingFlags::OMP_MAP_NONE;
7596 const ValueDecl *MapDecl =
nullptr;
7597 const Expr *MapExpr =
nullptr;
7599 bool IsNonContiguous =
false;
7603 const RecordDecl *LastParent =
nullptr;
7605 unsigned LastIndex = -1u;
7609 CopyOverlappedEntryGaps(CodeGenFunction &CGF,
7610 MapCombinedInfoTy &CombinedInfo,
7611 OpenMPOffloadMappingFlags Flags,
7612 const ValueDecl *MapDecl,
const Expr *MapExpr,
7613 Address BP, Address LB,
bool IsNonContiguous,
7615 : CGF(CGF), CombinedInfo(CombinedInfo), Flags(Flags), MapDecl(MapDecl),
7616 MapExpr(MapExpr), BP(BP), IsNonContiguous(IsNonContiguous),
7617 DimSize(DimSize), LB(LB) {}
7620 const OMPClauseMappableExprCommon::MappableComponent &MC,
7621 const FieldDecl *FD,
7622 llvm::function_ref<LValue(CodeGenFunction &,
const MemberExpr *)>
7623 EmitMemberExprBase) {
7633 LValue BaseLVal = EmitMemberExprBase(CGF, ME);
7645 copyUntilField(FD, ComponentLB);
7648 if (((int64_t)FieldOffset - (int64_t)Cursor) > 0)
7649 copyUntilField(FD, ComponentLB);
7651 Cursor = FieldOffset + FieldSize;
7656 void copyUntilField(
const FieldDecl *FD, Address ComponentLB) {
7660 CGF.
Builder.CreatePtrDiff(CGF.
Int8Ty, ComponentLBPtr, LBPtr);
7661 copySizedChunk(LBPtr, Size);
7664 void copyUntilEnd(Address HB) {
7666 const ASTRecordLayout &RL =
7675 copySizedChunk(LBPtr, Size);
7678 void copySizedChunk(llvm::Value *Base, llvm::Value *Size) {
7679 CombinedInfo.Exprs.emplace_back(MapDecl, MapExpr);
7681 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
7682 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
7683 CombinedInfo.Pointers.push_back(Base);
7684 CombinedInfo.Sizes.push_back(
7686 CombinedInfo.Types.push_back(Flags);
7687 CombinedInfo.Mappers.push_back(
nullptr);
7688 CombinedInfo.NonContigInfo.Dims.push_back(IsNonContiguous ? DimSize : 1);
7697 void generateInfoForComponentList(
7699 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
7701 MapCombinedInfoTy &CombinedInfo,
7702 MapCombinedInfoTy &StructBaseCombinedInfo,
7703 StructRangeInfoTy &PartialStruct, AttachInfoTy &AttachInfo,
7704 bool IsFirstComponentList,
bool IsImplicit,
7705 bool GenerateAllInfoForClauses,
const ValueDecl *Mapper =
nullptr,
7706 bool ForDeviceAddr =
false,
const ValueDecl *BaseDecl =
nullptr,
7707 const Expr *MapExpr =
nullptr,
7708 ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef>
7709 OverlappedElements = {})
const {
7927 bool IsCaptureFirstInfo = IsFirstComponentList;
7931 bool RequiresReference =
false;
7934 auto CI = Components.rbegin();
7935 auto CE = Components.rend();
7940 bool IsExpressionFirstInfo =
true;
7941 bool FirstPointerInComplexData =
false;
7944 const Expr *AssocExpr = I->getAssociatedExpression();
7945 const auto *AE = dyn_cast<ArraySubscriptExpr>(AssocExpr);
7946 const auto *OASE = dyn_cast<ArraySectionExpr>(AssocExpr);
7947 const auto *OAShE = dyn_cast<OMPArrayShapingExpr>(AssocExpr);
7950 const Expr *AttachPtrExpr = getAttachPtrExpr(Components);
7951 auto [AttachPtrAddr, AttachPteeBaseAddr] =
7952 getAttachPtrAddrAndPteeBaseAddr(AttachPtrExpr, CGF);
7954 bool HasAttachPtr = AttachPtrExpr !=
nullptr;
7955 bool FirstComponentIsForAttachPtr = AssocExpr == AttachPtrExpr;
7956 bool SeenAttachPtr = FirstComponentIsForAttachPtr;
7958 if (FirstComponentIsForAttachPtr) {
7966 }
else if ((AE &&
isa<CXXThisExpr>(AE->getBase()->IgnoreParenImpCasts())) ||
7980 if (
const auto *VD =
7981 dyn_cast_or_null<VarDecl>(I->getAssociatedDeclaration())) {
7982 if (std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
7983 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD)) {
7984 if ((*Res == OMPDeclareTargetDeclAttr::MT_Link) ||
7985 ((*Res == OMPDeclareTargetDeclAttr::MT_To ||
7986 *Res == OMPDeclareTargetDeclAttr::MT_Enter) &&
7988 RequiresReference =
true;
7998 I->getAssociatedDeclaration()->
getType().getNonReferenceType();
8003 const auto *VD = dyn_cast<VarDecl>(I->getAssociatedDeclaration());
8005 !VD || VD->hasLocalStorage() || HasAttachPtr)
8008 FirstPointerInComplexData =
true;
8027 bool ShouldBeMemberOf =
false;
8036 const MemberExpr *EncounteredME =
nullptr;
8048 bool IsNonContiguous =
8049 CombinedInfo.NonContigInfo.IsNonContiguous ||
8050 any_of(Components, [&](
const auto &Component) {
8052 dyn_cast<ArraySectionExpr>(Component.getAssociatedExpression());
8056 const Expr *StrideExpr = OASE->getStride();
8060 const auto Constant =
8065 return !Constant->isOne();
8068 bool IsPrevMemberReference =
false;
8070 bool IsPartialMapped =
8071 !PartialStruct.PreliminaryMapData.BasePointers.empty();
8078 bool IsMappingWholeStruct =
true;
8079 if (!GenerateAllInfoForClauses) {
8080 IsMappingWholeStruct =
false;
8082 for (
auto TempI = I; TempI != CE; ++TempI) {
8083 const MemberExpr *PossibleME =
8084 dyn_cast<MemberExpr>(TempI->getAssociatedExpression());
8086 IsMappingWholeStruct =
false;
8092 bool SeenFirstNonBinOpExprAfterAttachPtr =
false;
8093 for (; I != CE; ++I) {
8096 if (HasAttachPtr && !SeenAttachPtr) {
8097 SeenAttachPtr = I->getAssociatedExpression() == AttachPtrExpr;
8104 if (HasAttachPtr && !SeenFirstNonBinOpExprAfterAttachPtr) {
8105 const auto *BO = dyn_cast<BinaryOperator>(I->getAssociatedExpression());
8110 SeenFirstNonBinOpExprAfterAttachPtr =
true;
8111 BP = AttachPteeBaseAddr;
8115 if (!EncounteredME) {
8116 EncounteredME = dyn_cast<MemberExpr>(I->getAssociatedExpression());
8119 if (EncounteredME) {
8120 ShouldBeMemberOf =
true;
8123 if (FirstPointerInComplexData) {
8124 QualType Ty = std::prev(I)
8125 ->getAssociatedDeclaration()
8127 .getNonReferenceType();
8129 FirstPointerInComplexData =
false;
8134 auto Next = std::next(I);
8144 bool IsFinalArraySection =
8146 isFinalArraySectionExpression(I->getAssociatedExpression());
8150 const ValueDecl *MapDecl = (I->getAssociatedDeclaration())
8151 ? I->getAssociatedDeclaration()
8153 MapExpr = (I->getAssociatedExpression()) ? I->getAssociatedExpression()
8160 dyn_cast<ArraySectionExpr>(I->getAssociatedExpression());
8162 dyn_cast<OMPArrayShapingExpr>(I->getAssociatedExpression());
8163 const auto *UO = dyn_cast<UnaryOperator>(I->getAssociatedExpression());
8164 const auto *BO = dyn_cast<BinaryOperator>(I->getAssociatedExpression());
8170 I->getAssociatedExpression()->getType()->isAnyPointerType();
8171 bool IsMemberReference =
isa<MemberExpr>(I->getAssociatedExpression()) &&
8174 bool IsNonDerefPointer = IsPointer &&
8175 !(UO && UO->getOpcode() != UO_Deref) && !BO &&
8181 if (
Next == CE || IsMemberReference || IsNonDerefPointer ||
8182 IsFinalArraySection) {
8185 assert((
Next == CE ||
8192 "Unexpected expression");
8196 auto &&EmitMemberExprBase = [](CodeGenFunction &CGF,
8197 const MemberExpr *E) {
8198 const Expr *BaseExpr = E->getBase();
8203 LValueBaseInfo BaseInfo;
8204 TBAAAccessInfo TBAAInfo;
8218 OAShE->getBase()->getType()->getPointeeType()),
8220 OAShE->getBase()->getType()));
8221 }
else if (IsMemberReference) {
8223 LValue BaseLVal = EmitMemberExprBase(CGF, ME);
8238 FinalLowestElem = LowestElem;
8243 bool IsMemberPointerOrAddr =
8245 (((IsPointer || ForDeviceAddr) &&
8246 I->getAssociatedExpression() == EncounteredME) ||
8247 (IsPrevMemberReference && !IsPointer) ||
8248 (IsMemberReference &&
Next != CE &&
8249 !
Next->getAssociatedExpression()->getType()->isPointerType()));
8250 if (!OverlappedElements.empty() &&
Next == CE) {
8252 assert(!PartialStruct.Base.isValid() &&
"The base element is set.");
8253 assert(!IsPointer &&
8254 "Unexpected base element with the pointer type.");
8257 PartialStruct.LowestElem = {0, LowestElem};
8259 I->getAssociatedExpression()->getType());
8264 PartialStruct.HighestElem = {
8265 std::numeric_limits<
decltype(
8266 PartialStruct.HighestElem.first)>
::max(),
8268 PartialStruct.Base = BP;
8269 PartialStruct.LB = LB;
8271 PartialStruct.PreliminaryMapData.BasePointers.empty() &&
8272 "Overlapped elements must be used only once for the variable.");
8273 std::swap(PartialStruct.PreliminaryMapData, CombinedInfo);
8275 OpenMPOffloadMappingFlags Flags =
8276 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF |
8277 getMapTypeBits(MapType, MapModifiers, MotionModifiers, IsImplicit,
8279 false, IsNonContiguous);
8280 CopyOverlappedEntryGaps CopyGaps(CGF, CombinedInfo, Flags, MapDecl,
8281 MapExpr, BP, LB, IsNonContiguous,
8285 Component : OverlappedElements) {
8286 for (
const OMPClauseMappableExprCommon::MappableComponent &MC :
8289 if (
const auto *FD = dyn_cast<FieldDecl>(VD)) {
8290 CopyGaps.processField(MC, FD, EmitMemberExprBase);
8295 CopyGaps.copyUntilEnd(HB);
8298 llvm::Value *
Size = getExprTypeSize(I->getAssociatedExpression());
8305 if ((!IsMemberPointerOrAddr && !IsPartialMapped) ||
8307 if (!IsMappingWholeStruct) {
8308 CombinedInfo.Exprs.emplace_back(MapDecl, MapExpr);
8310 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
8311 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
8313 CombinedInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
8315 CombinedInfo.NonContigInfo.Dims.push_back(IsNonContiguous ? DimSize
8318 StructBaseCombinedInfo.Exprs.emplace_back(MapDecl, MapExpr);
8319 StructBaseCombinedInfo.BasePointers.push_back(
8321 StructBaseCombinedInfo.DevicePtrDecls.push_back(
nullptr);
8322 StructBaseCombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
8323 StructBaseCombinedInfo.Pointers.push_back(LB.
emitRawPointer(CGF));
8324 StructBaseCombinedInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
8326 StructBaseCombinedInfo.NonContigInfo.Dims.push_back(
8327 IsNonContiguous ? DimSize : 1);
8331 bool HasMapper = Mapper &&
Next == CE;
8332 if (!IsMappingWholeStruct)
8333 CombinedInfo.Mappers.push_back(HasMapper ? Mapper :
nullptr);
8335 StructBaseCombinedInfo.Mappers.push_back(HasMapper ? Mapper
8342 OpenMPOffloadMappingFlags Flags = getMapTypeBits(
8343 MapType, MapModifiers, MotionModifiers, IsImplicit,
8344 !IsExpressionFirstInfo || RequiresReference ||
8345 FirstPointerInComplexData || IsMemberReference,
8346 IsCaptureFirstInfo && !RequiresReference, IsNonContiguous);
8348 if (!IsExpressionFirstInfo || IsMemberReference) {
8351 if (IsPointer || (IsMemberReference &&
Next != CE))
8352 Flags &= ~(OpenMPOffloadMappingFlags::OMP_MAP_TO |
8353 OpenMPOffloadMappingFlags::OMP_MAP_FROM |
8354 OpenMPOffloadMappingFlags::OMP_MAP_ALWAYS |
8355 OpenMPOffloadMappingFlags::OMP_MAP_DELETE |
8356 OpenMPOffloadMappingFlags::OMP_MAP_CLOSE);
8358 if (ShouldBeMemberOf) {
8361 Flags |= OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF;
8364 ShouldBeMemberOf =
false;
8368 if (!IsMappingWholeStruct)
8369 CombinedInfo.Types.push_back(Flags);
8371 StructBaseCombinedInfo.Types.push_back(Flags);
8377 if (EncounteredME) {
8382 if (!PartialStruct.Base.isValid()) {
8383 PartialStruct.LowestElem = {FieldIndex, LowestElem};
8384 if (IsFinalArraySection && OASE) {
8388 PartialStruct.HighestElem = {FieldIndex, HB};
8390 PartialStruct.HighestElem = {FieldIndex, LowestElem};
8392 PartialStruct.Base = BP;
8393 PartialStruct.LB = BP;
8394 }
else if (FieldIndex < PartialStruct.LowestElem.first) {
8395 PartialStruct.LowestElem = {FieldIndex, LowestElem};
8396 }
else if (FieldIndex > PartialStruct.HighestElem.first) {
8397 if (IsFinalArraySection && OASE) {
8401 PartialStruct.HighestElem = {FieldIndex, HB};
8403 PartialStruct.HighestElem = {FieldIndex, LowestElem};
8409 if (IsFinalArraySection || IsNonContiguous)
8410 PartialStruct.IsArraySection =
true;
8413 if (IsFinalArraySection)
8418 BP = IsMemberReference ? LowestElem : LB;
8419 if (!IsPartialMapped)
8420 IsExpressionFirstInfo =
false;
8421 IsCaptureFirstInfo =
false;
8422 FirstPointerInComplexData =
false;
8423 IsPrevMemberReference = IsMemberReference;
8424 }
else if (FirstPointerInComplexData) {
8425 QualType Ty = Components.rbegin()
8426 ->getAssociatedDeclaration()
8428 .getNonReferenceType();
8430 FirstPointerInComplexData =
false;
8436 PartialStruct.HasCompleteRecord =
true;
8439 if (shouldEmitAttachEntry(AttachPtrExpr, BaseDecl, CGF, CurDir)) {
8440 AttachInfo.AttachPtrAddr = AttachPtrAddr;
8441 AttachInfo.AttachPteeAddr = FinalLowestElem;
8442 AttachInfo.AttachPtrDecl = BaseDecl;
8443 AttachInfo.AttachMapExpr = MapExpr;
8446 if (!IsNonContiguous)
8449 const ASTContext &Context = CGF.
getContext();
8453 MapValuesArrayTy CurOffsets = {llvm::ConstantInt::get(CGF.
CGM.
Int64Ty, 0)};
8454 MapValuesArrayTy CurCounts = {llvm::ConstantInt::get(CGF.
CGM.
Int64Ty, 1)};
8455 MapValuesArrayTy CurStrides;
8456 MapValuesArrayTy DimSizes{llvm::ConstantInt::get(CGF.
CGM.
Int64Ty, 1)};
8462 for (
const OMPClauseMappableExprCommon::MappableComponent &Component :
8464 const Expr *AssocExpr = Component.getAssociatedExpression();
8465 const auto *OASE = dyn_cast<ArraySectionExpr>(AssocExpr);
8475 assert((VAT || CAT || &Component == &*Components.begin()) &&
8476 "Should be either ConstantArray or VariableArray if not the "
8480 if (CurStrides.empty()) {
8481 const Type *ElementType =
nullptr;
8483 ElementType = CAT->getElementType().getTypePtr();
8485 ElementType = VAT->getElementType().getTypePtr();
8486 else if (&Component == &*Components.begin()) {
8493 if (
const auto *PtrType = Ty->
getAs<PointerType>())
8500 "Non-first components should not be raw pointers");
8508 if (&Component != &*Components.begin())
8512 CurStrides.push_back(
8513 llvm::ConstantInt::get(CGF.
Int64Ty, ElementTypeSize));
8518 if (DimSizes.size() < Components.size() - 1) {
8521 llvm::ConstantInt::get(CGF.
Int64Ty, CAT->getZExtSize()));
8523 DimSizes.push_back(CGF.
Builder.CreateIntCast(
8530 auto *DI = DimSizes.begin() + 1;
8532 llvm::Value *DimProd =
8533 llvm::ConstantInt::get(CGF.
CGM.
Int64Ty, ElementTypeSize);
8542 for (
const OMPClauseMappableExprCommon::MappableComponent &Component :
8544 const Expr *AssocExpr = Component.getAssociatedExpression();
8546 if (
const auto *AE = dyn_cast<ArraySubscriptExpr>(AssocExpr)) {
8547 llvm::Value *Offset = CGF.
Builder.CreateIntCast(
8550 CurOffsets.push_back(Offset);
8551 CurCounts.push_back(llvm::ConstantInt::get(CGF.
Int64Ty, 1));
8552 CurStrides.push_back(CurStrides.back());
8556 const auto *OASE = dyn_cast<ArraySectionExpr>(AssocExpr);
8562 const Expr *OffsetExpr = OASE->getLowerBound();
8563 llvm::Value *Offset =
nullptr;
8566 Offset = llvm::ConstantInt::get(CGF.
Int64Ty, 0);
8572 CurOffsets.push_back(Offset);
8575 const Expr *CountExpr = OASE->getLength();
8576 llvm::Value *Count =
nullptr;
8582 if (!OASE->getColonLocFirst().isValid() &&
8583 !OASE->getColonLocSecond().isValid()) {
8584 Count = llvm::ConstantInt::get(CGF.
Int64Ty, 1);
8590 const Expr *StrideExpr = OASE->getStride();
8591 llvm::Value *Stride =
8597 Count = CGF.
Builder.CreateUDiv(
8598 CGF.
Builder.CreateNUWSub(*DI, Offset), Stride);
8600 Count = CGF.
Builder.CreateNUWSub(*DI, Offset);
8606 CurCounts.push_back(Count);
8615 const Expr *StrideExpr = OASE->getStride();
8616 llvm::Value *Stride =
8621 DimProd = CGF.
Builder.CreateNUWMul(DimProd, *(DI - 1));
8623 CurStrides.push_back(CGF.
Builder.CreateNUWMul(DimProd, Stride));
8625 CurStrides.push_back(DimProd);
8626 if (DI != DimSizes.end())
8630 CombinedInfo.NonContigInfo.Offsets.push_back(CurOffsets);
8631 CombinedInfo.NonContigInfo.Counts.push_back(CurCounts);
8632 CombinedInfo.NonContigInfo.Strides.push_back(CurStrides);
8638 OpenMPOffloadMappingFlags
8639 getMapModifiersForPrivateClauses(
const CapturedStmt::Capture &Cap)
const {
8647 return OpenMPOffloadMappingFlags::OMP_MAP_TO |
8648 OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ;
8649 return OpenMPOffloadMappingFlags::OMP_MAP_PRIVATE |
8650 OpenMPOffloadMappingFlags::OMP_MAP_TO;
8653 if (I != LambdasMap.end())
8655 return getMapTypeBits(
8656 I->getSecond()->getMapType(), I->getSecond()->getMapTypeModifiers(),
8657 {}, I->getSecond()->isImplicit(),
8661 return OpenMPOffloadMappingFlags::OMP_MAP_TO |
8662 OpenMPOffloadMappingFlags::OMP_MAP_FROM;
8665 void getPlainLayout(
const CXXRecordDecl *RD,
8666 llvm::SmallVectorImpl<const FieldDecl *> &Layout,
8667 bool AsBase)
const {
8670 llvm::StructType *St =
8673 unsigned NumElements = St->getNumElements();
8675 llvm::PointerUnion<const CXXRecordDecl *, const FieldDecl *>, 4>
8676 RecordLayout(NumElements);
8679 for (
const auto &I : RD->
bases()) {
8683 QualType BaseTy = I.getType();
8694 RecordLayout[FieldIndex] =
Base;
8697 for (
const auto &I : RD->
vbases()) {
8698 QualType BaseTy = I.getType();
8705 if (RecordLayout[FieldIndex])
8707 RecordLayout[FieldIndex] =
Base;
8710 assert(!RD->
isUnion() &&
"Unexpected union.");
8711 for (
const auto *Field : RD->
fields()) {
8714 if (!
Field->isBitField() &&
8717 RecordLayout[FieldIndex] =
Field;
8720 for (
const llvm::PointerUnion<const CXXRecordDecl *, const FieldDecl *>
8721 &
Data : RecordLayout) {
8724 if (
const auto *Base = dyn_cast<const CXXRecordDecl *>(
Data))
8725 getPlainLayout(Base, Layout,
true);
8732 static Address getAttachPtrAddr(
const Expr *PointerExpr,
8733 CodeGenFunction &CGF) {
8734 assert(PointerExpr &&
"Cannot get addr from null attach-ptr expr");
8737 if (
auto *DRE = dyn_cast<DeclRefExpr>(PointerExpr)) {
8740 }
else if (
auto *OASE = dyn_cast<ArraySectionExpr>(PointerExpr)) {
8743 }
else if (
auto *ASE = dyn_cast<ArraySubscriptExpr>(PointerExpr)) {
8745 }
else if (
auto *ME = dyn_cast<MemberExpr>(PointerExpr)) {
8747 }
else if (
auto *UO = dyn_cast<UnaryOperator>(PointerExpr)) {
8748 assert(UO->getOpcode() == UO_Deref &&
8749 "Unexpected unary-operator on attach-ptr-expr");
8752 assert(AttachPtrAddr.
isValid() &&
8753 "Failed to get address for attach pointer expression");
8754 return AttachPtrAddr;
8761 static std::pair<Address, Address>
8762 getAttachPtrAddrAndPteeBaseAddr(
const Expr *AttachPtrExpr,
8763 CodeGenFunction &CGF) {
8768 Address AttachPtrAddr = getAttachPtrAddr(AttachPtrExpr, CGF);
8769 assert(AttachPtrAddr.
isValid() &&
"Invalid attach pointer addr");
8771 QualType AttachPtrType =
8776 AttachPtrAddr, AttachPtrType->
castAs<PointerType>());
8777 assert(AttachPteeBaseAddr.
isValid() &&
"Invalid attach pointee base addr");
8779 return {AttachPtrAddr, AttachPteeBaseAddr};
8785 shouldEmitAttachEntry(
const Expr *PointerExpr,
const ValueDecl *MapBaseDecl,
8786 CodeGenFunction &CGF,
8787 llvm::PointerUnion<
const OMPExecutableDirective *,
8788 const OMPDeclareMapperDecl *>
8798 ->getDirectiveKind());
8807 void collectAttachPtrExprInfo(
8809 llvm::PointerUnion<
const OMPExecutableDirective *,
8810 const OMPDeclareMapperDecl *>
8815 ? OMPD_declare_mapper
8818 const auto &[AttachPtrExpr, Depth] =
8822 AttachPtrComputationOrderMap.try_emplace(
8823 AttachPtrExpr, AttachPtrComputationOrderMap.size());
8824 AttachPtrComponentDepthMap.try_emplace(AttachPtrExpr, Depth);
8825 AttachPtrExprMap.try_emplace(Components, AttachPtrExpr);
8833 void generateAllInfoForClauses(
8834 ArrayRef<const OMPClause *> Clauses, MapCombinedInfoTy &CombinedInfo,
8835 llvm::OpenMPIRBuilder &OMPBuilder,
8836 const llvm::DenseSet<CanonicalDeclPtr<const Decl>> &SkipVarSet =
8837 llvm::DenseSet<CanonicalDeclPtr<const Decl>>())
const {
8842 llvm::MapVector<CanonicalDeclPtr<const Decl>,
8843 SmallVector<SmallVector<MapInfo, 8>, 4>>
8849 [&Info, &SkipVarSet](
8850 const ValueDecl *D, MapKind
Kind,
8853 ArrayRef<OpenMPMapModifierKind> MapModifiers,
8854 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
8855 bool ReturnDevicePointer,
bool IsImplicit,
const ValueDecl *Mapper,
8856 const Expr *VarRef =
nullptr,
bool ForDeviceAddr =
false) {
8857 if (SkipVarSet.contains(D))
8859 auto It = Info.try_emplace(D, Total).first;
8860 It->second[
Kind].emplace_back(
8861 L, MapType, MapModifiers, MotionModifiers, ReturnDevicePointer,
8862 IsImplicit, Mapper, VarRef, ForDeviceAddr);
8865 for (
const auto *
Cl : Clauses) {
8866 const auto *
C = dyn_cast<OMPMapClause>(
Cl);
8870 if (llvm::is_contained(
C->getMapTypeModifiers(),
8871 OMPC_MAP_MODIFIER_present))
8873 else if (
C->getMapType() == OMPC_MAP_alloc)
8875 const auto *EI =
C->getVarRefs().begin();
8876 for (
const auto L :
C->component_lists()) {
8877 const Expr *E = (
C->getMapLoc().isValid()) ? *EI :
nullptr;
8878 InfoGen(std::get<0>(L), Kind, std::get<1>(L),
C->getMapType(),
8879 C->getMapTypeModifiers(), {},
8880 false,
C->isImplicit(), std::get<2>(L),
8885 for (
const auto *
Cl : Clauses) {
8886 const auto *
C = dyn_cast<OMPToClause>(
Cl);
8890 if (llvm::is_contained(
C->getMotionModifiers(),
8891 OMPC_MOTION_MODIFIER_present))
8893 if (llvm::is_contained(
C->getMotionModifiers(),
8894 OMPC_MOTION_MODIFIER_iterator)) {
8895 if (
auto *IteratorExpr = dyn_cast<OMPIteratorExpr>(
8896 C->getIteratorModifier()->IgnoreParenImpCasts())) {
8897 const auto *VD =
cast<VarDecl>(IteratorExpr->getIteratorDecl(0));
8902 const auto *EI =
C->getVarRefs().begin();
8903 for (
const auto L :
C->component_lists()) {
8904 InfoGen(std::get<0>(L), Kind, std::get<1>(L), OMPC_MAP_to, {},
8905 C->getMotionModifiers(),
false,
8906 C->isImplicit(), std::get<2>(L), *EI);
8910 for (
const auto *
Cl : Clauses) {
8911 const auto *
C = dyn_cast<OMPFromClause>(
Cl);
8915 if (llvm::is_contained(
C->getMotionModifiers(),
8916 OMPC_MOTION_MODIFIER_present))
8918 if (llvm::is_contained(
C->getMotionModifiers(),
8919 OMPC_MOTION_MODIFIER_iterator)) {
8920 if (
auto *IteratorExpr = dyn_cast<OMPIteratorExpr>(
8921 C->getIteratorModifier()->IgnoreParenImpCasts())) {
8922 const auto *VD =
cast<VarDecl>(IteratorExpr->getIteratorDecl(0));
8927 const auto *EI =
C->getVarRefs().begin();
8928 for (
const auto L :
C->component_lists()) {
8929 InfoGen(std::get<0>(L), Kind, std::get<1>(L), OMPC_MAP_from, {},
8930 C->getMotionModifiers(),
8931 false,
C->isImplicit(), std::get<2>(L),
8944 MapCombinedInfoTy UseDeviceDataCombinedInfo;
8946 auto &&UseDeviceDataCombinedInfoGen =
8947 [&UseDeviceDataCombinedInfo](
const ValueDecl *VD, llvm::Value *Ptr,
8948 CodeGenFunction &CGF,
bool IsDevAddr,
8949 bool HasUdpFbNullify =
false) {
8950 UseDeviceDataCombinedInfo.Exprs.push_back(VD);
8951 UseDeviceDataCombinedInfo.BasePointers.emplace_back(Ptr);
8952 UseDeviceDataCombinedInfo.DevicePtrDecls.emplace_back(VD);
8953 UseDeviceDataCombinedInfo.DevicePointers.emplace_back(
8954 IsDevAddr ? DeviceInfoTy::Address : DeviceInfoTy::Pointer);
8960 UseDeviceDataCombinedInfo.Pointers.push_back(Ptr);
8961 UseDeviceDataCombinedInfo.Sizes.push_back(
8962 llvm::Constant::getNullValue(CGF.Int64Ty));
8963 OpenMPOffloadMappingFlags Flags =
8964 OpenMPOffloadMappingFlags::OMP_MAP_RETURN_PARAM;
8965 if (HasUdpFbNullify)
8966 Flags |= OpenMPOffloadMappingFlags::OMP_MAP_FB_NULLIFY;
8967 UseDeviceDataCombinedInfo.Types.push_back(Flags);
8968 UseDeviceDataCombinedInfo.Mappers.push_back(
nullptr);
8972 [&UseDeviceDataCombinedInfoGen](
8973 CodeGenFunction &CGF,
const Expr *IE,
const ValueDecl *VD,
8976 bool IsDevAddr,
bool IEIsAttachPtrForDevAddr =
false,
8977 bool HasUdpFbNullify =
false) {
8981 if (IsDevAddr && !IEIsAttachPtrForDevAddr) {
8982 if (IE->isGLValue())
8989 bool TreatDevAddrAsDevPtr = IEIsAttachPtrForDevAddr;
8996 UseDeviceDataCombinedInfoGen(VD, Ptr, CGF, IsDevAddr &&
8997 !TreatDevAddrAsDevPtr,
9001 auto &&IsMapInfoExist =
9002 [&Info,
this](CodeGenFunction &CGF,
const ValueDecl *VD,
const Expr *IE,
9003 const Expr *DesiredAttachPtrExpr,
bool IsDevAddr,
9004 bool HasUdpFbNullify =
false) ->
bool {
9012 if (It != Info.end()) {
9014 for (
auto &
Data : It->second) {
9015 MapInfo *CI =
nullptr;
9019 auto *It = llvm::find_if(
Data, [&](
const MapInfo &MI) {
9020 if (MI.Components.back().getAssociatedDeclaration() != VD)
9023 const Expr *MapAttachPtr = getAttachPtrExpr(MI.Components);
9024 bool Match = AttachPtrComparator.areEqual(MapAttachPtr,
9025 DesiredAttachPtrExpr);
9029 if (It !=
Data.end())
9034 CI->ForDeviceAddr =
true;
9035 CI->ReturnDevicePointer =
true;
9036 CI->HasUdpFbNullify = HasUdpFbNullify;
9040 auto PrevCI = std::next(CI->Components.rbegin());
9041 const auto *VarD = dyn_cast<VarDecl>(VD);
9042 const Expr *AttachPtrExpr = getAttachPtrExpr(CI->Components);
9043 if (CGF.CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory() ||
9045 !VD->getType().getNonReferenceType()->isPointerType() ||
9046 PrevCI == CI->Components.rend() ||
9048 VarD->hasLocalStorage() ||
9049 (isa_and_nonnull<DeclRefExpr>(AttachPtrExpr) &&
9051 CI->ForDeviceAddr = IsDevAddr;
9052 CI->ReturnDevicePointer =
true;
9053 CI->HasUdpFbNullify = HasUdpFbNullify;
9071 for (
const auto *
Cl : Clauses) {
9072 const auto *
C = dyn_cast<OMPUseDevicePtrClause>(
Cl);
9075 bool HasUdpFbNullify =
9076 C->getFallbackModifier() == OMPC_USE_DEVICE_PTR_FALLBACK_fb_nullify;
9077 for (
const auto L :
C->component_lists()) {
9080 assert(!Components.empty() &&
9081 "Not expecting empty list of components!");
9082 const ValueDecl *VD = Components.back().getAssociatedDeclaration();
9084 const Expr *IE = Components.back().getAssociatedExpression();
9092 const Expr *UDPOperandExpr =
9093 Components.front().getAssociatedExpression();
9094 if (IsMapInfoExist(CGF, VD, IE,
9096 false, HasUdpFbNullify))
9098 MapInfoGen(CGF, IE, VD, Components,
false,
9099 false, HasUdpFbNullify);
9103 llvm::SmallDenseSet<CanonicalDeclPtr<const Decl>, 4> Processed;
9104 for (
const auto *
Cl : Clauses) {
9105 const auto *
C = dyn_cast<OMPUseDeviceAddrClause>(
Cl);
9108 for (
const auto L :
C->component_lists()) {
9111 assert(!std::get<1>(L).empty() &&
9112 "Not expecting empty list of components!");
9113 const ValueDecl *VD = std::get<1>(L).back().getAssociatedDeclaration();
9114 if (!Processed.insert(VD).second)
9135 const Expr *UDAAttachPtrExpr = getAttachPtrExpr(Components);
9136 const Expr *IE = std::get<1>(L).back().getAssociatedExpression();
9137 assert((!UDAAttachPtrExpr || UDAAttachPtrExpr == IE) &&
9138 "use_device_addr operand has an attach-ptr, but does not match "
9139 "last component's expr.");
9140 if (IsMapInfoExist(CGF, VD, IE,
9144 MapInfoGen(CGF, IE, VD, Components,
9146 UDAAttachPtrExpr !=
nullptr);
9150 for (
const auto &
Data : Info) {
9151 MapCombinedInfoTy CurInfo;
9153 const ValueDecl *VD = cast_or_null<ValueDecl>(D);
9160 SmallVector<std::pair<const Expr *, MapInfo>, 16> AttachPtrMapInfoPairs;
9163 for (
const auto &M :
Data.second) {
9164 for (
const MapInfo &L : M) {
9165 assert(!L.Components.empty() &&
9166 "Not expecting declaration with no component lists.");
9168 const Expr *AttachPtrExpr = getAttachPtrExpr(L.Components);
9169 AttachPtrMapInfoPairs.emplace_back(AttachPtrExpr, L);
9174 llvm::stable_sort(AttachPtrMapInfoPairs,
9175 [
this](
const auto &LHS,
const auto &RHS) {
9176 return AttachPtrComparator(LHS.first, RHS.first);
9181 auto *It = AttachPtrMapInfoPairs.begin();
9182 while (It != AttachPtrMapInfoPairs.end()) {
9183 const Expr *AttachPtrExpr = It->first;
9185 SmallVector<MapInfo, 8> GroupLists;
9186 while (It != AttachPtrMapInfoPairs.end() &&
9187 (It->first == AttachPtrExpr ||
9188 AttachPtrComparator.areEqual(It->first, AttachPtrExpr))) {
9189 GroupLists.push_back(It->second);
9192 assert(!GroupLists.empty() &&
"GroupLists should not be empty");
9194 StructRangeInfoTy PartialStruct;
9195 AttachInfoTy AttachInfo;
9196 MapCombinedInfoTy GroupCurInfo;
9198 MapCombinedInfoTy GroupStructBaseCurInfo;
9199 for (
const MapInfo &L : GroupLists) {
9201 unsigned CurrentBasePointersIdx = GroupCurInfo.BasePointers.size();
9202 unsigned StructBasePointersIdx =
9203 GroupStructBaseCurInfo.BasePointers.size();
9205 GroupCurInfo.NonContigInfo.IsNonContiguous =
9206 L.Components.back().isNonContiguous();
9207 generateInfoForComponentList(
9208 L.MapType, L.MapModifiers, L.MotionModifiers, L.Components,
9209 GroupCurInfo, GroupStructBaseCurInfo, PartialStruct, AttachInfo,
9210 false, L.IsImplicit,
9211 true, L.Mapper, L.ForDeviceAddr, VD,
9216 if (L.ReturnDevicePointer) {
9220 assert((CurrentBasePointersIdx < GroupCurInfo.BasePointers.size() ||
9221 StructBasePointersIdx <
9222 GroupStructBaseCurInfo.BasePointers.size()) &&
9223 "Unexpected number of mapped base pointers.");
9226 const ValueDecl *RelevantVD =
9227 L.Components.back().getAssociatedDeclaration();
9228 assert(RelevantVD &&
9229 "No relevant declaration related with device pointer??");
9236 auto SetDevicePointerInfo = [&](MapCombinedInfoTy &Info,
9238 Info.DevicePtrDecls[Idx] = RelevantVD;
9239 Info.DevicePointers[Idx] = L.ForDeviceAddr
9240 ? DeviceInfoTy::Address
9241 : DeviceInfoTy::Pointer;
9243 OpenMPOffloadMappingFlags::OMP_MAP_RETURN_PARAM;
9244 if (L.HasUdpFbNullify)
9246 OpenMPOffloadMappingFlags::OMP_MAP_FB_NULLIFY;
9249 if (StructBasePointersIdx <
9250 GroupStructBaseCurInfo.BasePointers.size())
9251 SetDevicePointerInfo(GroupStructBaseCurInfo,
9252 StructBasePointersIdx);
9254 SetDevicePointerInfo(GroupCurInfo, CurrentBasePointersIdx);
9260 MapCombinedInfoTy GroupUnionCurInfo;
9261 GroupUnionCurInfo.append(GroupStructBaseCurInfo);
9262 GroupUnionCurInfo.append(GroupCurInfo);
9266 if (PartialStruct.Base.isValid()) {
9274 GroupUnionCurInfo.NonContigInfo.Dims.insert(
9275 GroupUnionCurInfo.NonContigInfo.Dims.begin(), 1);
9277 CurInfo, GroupUnionCurInfo.Types, PartialStruct, AttachInfo,
9278 !VD, OMPBuilder, VD,
9279 CombinedInfo.BasePointers.size(),
9285 CurInfo.append(GroupUnionCurInfo);
9286 if (AttachInfo.isValid())
9287 emitAttachEntry(CGF, CurInfo, AttachInfo);
9291 CombinedInfo.append(CurInfo);
9294 CombinedInfo.append(UseDeviceDataCombinedInfo);
9298 MappableExprsHandler(
const OMPExecutableDirective &Dir, CodeGenFunction &CGF)
9299 : CurDir(&Dir), CGF(CGF), AttachPtrComparator(*this) {
9301 for (
const auto *
C : Dir.getClausesOfKind<OMPFirstprivateClause>())
9302 for (
const auto *D :
C->varlist())
9303 FirstPrivateDecls.try_emplace(
9306 for (
const auto *
C : Dir.getClausesOfKind<OMPUsesAllocatorsClause>()) {
9307 for (unsigned I = 0, E = C->getNumberOfAllocators(); I < E; ++I) {
9308 OMPUsesAllocatorsClause::Data D = C->getAllocatorData(I);
9309 if (const auto *DRE = dyn_cast_or_null<DeclRefExpr>(D.AllocatorTraits))
9310 FirstPrivateDecls.try_emplace(cast<VarDecl>(DRE->getDecl()),
9312 else if (const auto *VD = dyn_cast<VarDecl>(
9313 cast<DeclRefExpr>(D.Allocator->IgnoreParenImpCasts())
9315 FirstPrivateDecls.try_emplace(VD, true);
9319 for (
const auto *
C : Dir.getClausesOfKind<OMPDefaultmapClause>())
9320 if (
C->getDefaultmapModifier() == OMPC_DEFAULTMAP_MODIFIER_firstprivate)
9321 DefaultmapFirstprivateKinds.insert(
C->getDefaultmapKind());
9323 for (
const auto *
C : Dir.getClausesOfKind<OMPIsDevicePtrClause>())
9324 for (
auto L :
C->component_lists())
9325 DevPointersMap[std::get<0>(L)].push_back(std::get<1>(L));
9327 for (
const auto *
C : Dir.getClausesOfKind<OMPHasDeviceAddrClause>())
9328 for (
auto L :
C->component_lists())
9329 HasDevAddrsMap[std::get<0>(L)].push_back(std::get<1>(L));
9331 for (
const auto *
C : Dir.getClausesOfKind<OMPMapClause>()) {
9332 if (C->getMapType() != OMPC_MAP_to)
9334 for (auto L : C->component_lists()) {
9335 const ValueDecl *VD = std::get<0>(L);
9336 const auto *RD = VD ? VD->getType()
9338 .getNonReferenceType()
9339 ->getAsCXXRecordDecl()
9341 if (RD && RD->isLambda())
9342 LambdasMap.try_emplace(std::get<0>(L), C);
9346 auto CollectAttachPtrExprsForClauseComponents = [
this](
const auto *
C) {
9347 for (
auto L :
C->component_lists()) {
9350 if (!Components.empty())
9351 collectAttachPtrExprInfo(Components, CurDir);
9357 for (
const auto *
C : Dir.getClausesOfKind<OMPMapClause>())
9358 CollectAttachPtrExprsForClauseComponents(
C);
9359 for (
const auto *
C : Dir.getClausesOfKind<OMPToClause>())
9360 CollectAttachPtrExprsForClauseComponents(
C);
9361 for (
const auto *
C : Dir.getClausesOfKind<OMPFromClause>())
9362 CollectAttachPtrExprsForClauseComponents(
C);
9363 for (
const auto *
C : Dir.getClausesOfKind<OMPUseDevicePtrClause>())
9364 CollectAttachPtrExprsForClauseComponents(
C);
9365 for (
const auto *
C : Dir.getClausesOfKind<OMPUseDeviceAddrClause>())
9366 CollectAttachPtrExprsForClauseComponents(
C);
9367 for (
const auto *
C : Dir.getClausesOfKind<OMPIsDevicePtrClause>())
9368 CollectAttachPtrExprsForClauseComponents(
C);
9369 for (
const auto *
C : Dir.getClausesOfKind<OMPHasDeviceAddrClause>())
9370 CollectAttachPtrExprsForClauseComponents(
C);
9374 MappableExprsHandler(
const OMPDeclareMapperDecl &Dir,
CodeGenFunction &CGF)
9375 : CurDir(&Dir), CGF(CGF), AttachPtrComparator(*this) {}
9385 void emitCombinedEntry(MapCombinedInfoTy &CombinedInfo,
9386 MapFlagsArrayTy &CurTypes,
9387 const StructRangeInfoTy &PartialStruct,
9388 AttachInfoTy &AttachInfo,
bool IsMapThis,
9389 llvm::OpenMPIRBuilder &OMPBuilder,
const ValueDecl *VD,
9390 unsigned OffsetForMemberOfFlag,
9391 bool NotTargetParams)
const {
9392 if (CurTypes.size() == 1 &&
9393 ((CurTypes.back() & OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF) !=
9394 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF) &&
9395 !PartialStruct.IsArraySection)
9397 Address LBAddr = PartialStruct.LowestElem.second;
9398 Address HBAddr = PartialStruct.HighestElem.second;
9399 if (PartialStruct.HasCompleteRecord) {
9400 LBAddr = PartialStruct.LB;
9401 HBAddr = PartialStruct.LB;
9403 CombinedInfo.Exprs.push_back(VD);
9405 CombinedInfo.BasePointers.push_back(PartialStruct.Base.emitRawPointer(CGF));
9406 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
9407 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
9410 const CXXMethodDecl *MD =
9412 const CXXRecordDecl *RD = MD ? MD->
getParent() :
nullptr;
9413 bool HasBaseClass = RD && IsMapThis ? RD->
getNumBases() > 0 :
false;
9423 CombinedInfo.Pointers.push_back(PartialStruct.Base.emitRawPointer(CGF));
9428 CombinedInfo.Sizes.push_back(Size);
9430 CombinedInfo.Pointers.push_back(LB);
9433 llvm::Value *HAddr = CGF.
Builder.CreateConstGEP1_32(
9437 llvm::Value *Diff = CGF.
Builder.CreatePtrDiff(CGF.
Int8Ty, CHAddr, CLAddr);
9440 CombinedInfo.Sizes.push_back(Size);
9442 CombinedInfo.Mappers.push_back(
nullptr);
9444 CombinedInfo.Types.push_back(
9445 NotTargetParams ? OpenMPOffloadMappingFlags::OMP_MAP_NONE
9446 : !PartialStruct.PreliminaryMapData.BasePointers.empty()
9447 ? OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ
9448 : OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM);
9451 if (CurTypes.end() !=
9452 llvm::find_if(CurTypes, [](OpenMPOffloadMappingFlags
Type) {
9453 return static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>>(
9454 Type & OpenMPOffloadMappingFlags::OMP_MAP_PRESENT);
9456 CombinedInfo.Types.back() |= OpenMPOffloadMappingFlags::OMP_MAP_PRESENT;
9458 (*CurTypes.begin()) &= ~OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM;
9465 if (CurTypes.end() !=
9466 llvm::find_if(CurTypes, [](OpenMPOffloadMappingFlags
Type) {
9467 return static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>>(
9468 Type & OpenMPOffloadMappingFlags::OMP_MAP_OMPX_HOLD);
9470 CombinedInfo.Types.back() |= OpenMPOffloadMappingFlags::OMP_MAP_OMPX_HOLD;
9471 for (
auto &M : CurTypes)
9472 M |= OpenMPOffloadMappingFlags::OMP_MAP_OMPX_HOLD;
9479 OpenMPOffloadMappingFlags MemberOfFlag = OMPBuilder.getMemberOfFlag(
9480 OffsetForMemberOfFlag + CombinedInfo.BasePointers.size() - 1);
9481 for (
auto &M : CurTypes)
9482 OMPBuilder.setCorrectMemberOfFlag(M, MemberOfFlag);
9499 if (AttachInfo.isValid())
9500 AttachInfo.AttachPteeAddr = LBAddr;
9508 void generateAllInfo(
9509 MapCombinedInfoTy &CombinedInfo, llvm::OpenMPIRBuilder &OMPBuilder,
9510 const llvm::DenseSet<CanonicalDeclPtr<const Decl>> &SkipVarSet =
9511 llvm::DenseSet<CanonicalDeclPtr<const Decl>>())
const {
9513 "Expect a executable directive");
9515 generateAllInfoForClauses(CurExecDir->clauses(), CombinedInfo, OMPBuilder,
9522 void generateAllInfoForMapper(MapCombinedInfoTy &CombinedInfo,
9523 llvm::OpenMPIRBuilder &OMPBuilder)
const {
9525 "Expect a declare mapper directive");
9527 generateAllInfoForClauses(CurMapperDir->clauses(), CombinedInfo,
9532 void generateInfoForLambdaCaptures(
9533 const ValueDecl *VD, llvm::Value *Arg, MapCombinedInfoTy &CombinedInfo,
9534 llvm::DenseMap<llvm::Value *, llvm::Value *> &LambdaPointers)
const {
9542 llvm::DenseMap<const ValueDecl *, FieldDecl *> Captures;
9543 FieldDecl *ThisCapture =
nullptr;
9549 LambdaPointers.try_emplace(ThisLVal.getPointer(CGF),
9550 VDLVal.getPointer(CGF));
9551 CombinedInfo.Exprs.push_back(VD);
9552 CombinedInfo.BasePointers.push_back(ThisLVal.getPointer(CGF));
9553 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
9554 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
9555 CombinedInfo.Pointers.push_back(ThisLValVal.getPointer(CGF));
9556 CombinedInfo.Sizes.push_back(
9559 CombinedInfo.Types.push_back(
9560 OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ |
9561 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL |
9562 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF |
9563 OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT);
9564 CombinedInfo.Mappers.push_back(
nullptr);
9566 for (
const LambdaCapture &LC : RD->
captures()) {
9567 if (!LC.capturesVariable())
9572 auto It = Captures.find(VD);
9573 assert(It != Captures.end() &&
"Found lambda capture without field.");
9577 LambdaPointers.try_emplace(VarLVal.getPointer(CGF),
9578 VDLVal.getPointer(CGF));
9579 CombinedInfo.Exprs.push_back(VD);
9580 CombinedInfo.BasePointers.push_back(VarLVal.getPointer(CGF));
9581 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
9582 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
9583 CombinedInfo.Pointers.push_back(VarLValVal.getPointer(CGF));
9584 CombinedInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
9590 LambdaPointers.try_emplace(VarLVal.getPointer(CGF),
9591 VDLVal.getPointer(CGF));
9592 CombinedInfo.Exprs.push_back(VD);
9593 CombinedInfo.BasePointers.push_back(VarLVal.getPointer(CGF));
9594 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
9595 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
9596 CombinedInfo.Pointers.push_back(VarRVal.
getScalarVal());
9597 CombinedInfo.Sizes.push_back(llvm::ConstantInt::get(CGF.
Int64Ty, 0));
9599 CombinedInfo.Types.push_back(
9600 OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ |
9601 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL |
9602 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF |
9603 OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT);
9604 CombinedInfo.Mappers.push_back(
nullptr);
9609 void adjustMemberOfForLambdaCaptures(
9610 llvm::OpenMPIRBuilder &OMPBuilder,
9611 const llvm::DenseMap<llvm::Value *, llvm::Value *> &LambdaPointers,
9612 MapBaseValuesArrayTy &BasePointers, MapValuesArrayTy &Pointers,
9613 MapFlagsArrayTy &Types)
const {
9614 for (
unsigned I = 0, E = Types.size(); I < E; ++I) {
9616 if (Types[I] != (OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ |
9617 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL |
9618 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF |
9619 OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT))
9621 llvm::Value *BasePtr = LambdaPointers.lookup(BasePointers[I]);
9622 assert(BasePtr &&
"Unable to find base lambda address.");
9624 for (
unsigned J = I; J > 0; --J) {
9625 unsigned Idx = J - 1;
9626 if (Pointers[Idx] != BasePtr)
9631 assert(TgtIdx != -1 &&
"Unable to find parent lambda.");
9635 OpenMPOffloadMappingFlags MemberOfFlag =
9636 OMPBuilder.getMemberOfFlag(TgtIdx);
9637 OMPBuilder.setCorrectMemberOfFlag(Types[I], MemberOfFlag);
9643 void populateComponentListsForNonLambdaCaptureFromClauses(
9644 const ValueDecl *VD, MapDataArrayTy &DeclComponentLists,
9646 SmallVector<OMPClauseMappableExprCommon::MappableComponent, 8>>
9647 &StorageForImplicitlyAddedComponentLists)
const {
9648 if (VD && LambdasMap.count(VD))
9654 auto It = DevPointersMap.find(VD);
9655 if (It != DevPointersMap.end())
9656 for (
const auto &MCL : It->second)
9657 DeclComponentLists.emplace_back(MCL, OMPC_MAP_to,
Unknown,
9660 auto I = HasDevAddrsMap.find(VD);
9661 if (I != HasDevAddrsMap.end())
9662 for (
const auto &MCL : I->second)
9663 DeclComponentLists.emplace_back(MCL, OMPC_MAP_tofrom,
Unknown,
9667 "Expect a executable directive");
9669 for (
const auto *
C : CurExecDir->getClausesOfKind<OMPMapClause>()) {
9670 const auto *EI =
C->getVarRefs().begin();
9671 for (
const auto L :
C->decl_component_lists(VD)) {
9672 const ValueDecl *VDecl, *Mapper;
9674 const Expr *E = (
C->getMapLoc().isValid()) ? *EI :
nullptr;
9676 std::tie(VDecl, Components, Mapper) = L;
9677 assert(VDecl == VD &&
"We got information for the wrong declaration??");
9678 assert(!Components.empty() &&
9679 "Not expecting declaration with no component lists.");
9680 DeclComponentLists.emplace_back(Components,
C->getMapType(),
9681 C->getMapTypeModifiers(),
9682 C->isImplicit(), Mapper, E);
9691 addImplicitMapForAttachPtrBaseIfMemberOfCapturedVD(
9692 VD, DeclComponentLists, StorageForImplicitlyAddedComponentLists);
9694 llvm::stable_sort(DeclComponentLists, [](
const MapData &LHS,
9695 const MapData &RHS) {
9696 ArrayRef<OpenMPMapModifierKind> MapModifiers = std::get<2>(LHS);
9699 llvm::is_contained(MapModifiers, clang::OMPC_MAP_MODIFIER_present);
9700 bool HasAllocs = MapType == OMPC_MAP_alloc;
9701 MapModifiers = std::get<2>(RHS);
9702 MapType = std::get<1>(LHS);
9704 llvm::is_contained(MapModifiers, clang::OMPC_MAP_MODIFIER_present);
9705 bool HasAllocsR = MapType == OMPC_MAP_alloc;
9706 return (HasPresent && !HasPresentR) || (HasAllocs && !HasAllocsR);
9742 void addImplicitMapForAttachPtrBaseIfMemberOfCapturedVD(
9743 const ValueDecl *CapturedVD, MapDataArrayTy &DeclComponentLists,
9745 SmallVector<OMPClauseMappableExprCommon::MappableComponent, 8>>
9746 &ComponentVectorStorage)
const {
9747 bool IsThisCapture = CapturedVD ==
nullptr;
9749 for (
const auto &ComponentsAndAttachPtr : AttachPtrExprMap) {
9751 ComponentsWithAttachPtr = ComponentsAndAttachPtr.first;
9752 const Expr *AttachPtrExpr = ComponentsAndAttachPtr.second;
9756 const auto *ME = dyn_cast<MemberExpr>(AttachPtrExpr);
9760 const Expr *
Base = ME->getBase()->IgnoreParenImpCasts();
9781 bool FoundExistingMap =
false;
9782 for (
const MapData &ExistingL : DeclComponentLists) {
9784 ExistingComponents = std::get<0>(ExistingL);
9786 if (ExistingComponents.empty())
9790 const auto &FirstComponent = ExistingComponents.front();
9791 const Expr *FirstExpr = FirstComponent.getAssociatedExpression();
9797 if (AttachPtrComparator.areEqual(FirstExpr, AttachPtrExpr)) {
9798 FoundExistingMap =
true;
9803 if (IsThisCapture) {
9804 if (
const auto *OASE = dyn_cast<ArraySectionExpr>(FirstExpr)) {
9806 FoundExistingMap =
true;
9815 if (
const auto *DRE = dyn_cast<DeclRefExpr>(FirstExpr)) {
9816 if (DRE->getDecl() == CapturedVD) {
9817 FoundExistingMap =
true;
9823 if (FoundExistingMap)
9829 ComponentVectorStorage.emplace_back();
9830 auto &AttachPtrComponents = ComponentVectorStorage.back();
9833 bool SeenAttachPtrComponent =
false;
9839 for (
size_t i = 0; i < ComponentsWithAttachPtr.size(); ++i) {
9840 const auto &Component = ComponentsWithAttachPtr[i];
9841 const Expr *ComponentExpr = Component.getAssociatedExpression();
9843 if (!SeenAttachPtrComponent && ComponentExpr != AttachPtrExpr)
9845 SeenAttachPtrComponent =
true;
9847 AttachPtrComponents.emplace_back(Component.getAssociatedExpression(),
9848 Component.getAssociatedDeclaration(),
9849 Component.isNonContiguous());
9851 assert(!AttachPtrComponents.empty() &&
9852 "Could not populate component-lists for mapping attach-ptr");
9854 DeclComponentLists.emplace_back(
9855 AttachPtrComponents, OMPC_MAP_tofrom,
Unknown,
9856 true,
nullptr, AttachPtrExpr);
9863 void generateInfoForCaptureFromClauseInfo(
9864 const MapDataArrayTy &DeclComponentListsFromClauses,
9865 const CapturedStmt::Capture *Cap, llvm::Value *Arg,
9866 MapCombinedInfoTy &CurCaptureVarInfo, llvm::OpenMPIRBuilder &OMPBuilder,
9867 unsigned OffsetForMemberOfFlag)
const {
9869 "Not expecting to generate map info for a variable array type!");
9878 if (LambdasMap.count(VD))
9884 if (VD && (DevPointersMap.count(VD) || HasDevAddrsMap.count(VD))) {
9885 CurCaptureVarInfo.Exprs.push_back(VD);
9886 CurCaptureVarInfo.BasePointers.emplace_back(Arg);
9887 CurCaptureVarInfo.DevicePtrDecls.emplace_back(VD);
9888 CurCaptureVarInfo.DevicePointers.emplace_back(DeviceInfoTy::Pointer);
9889 CurCaptureVarInfo.Pointers.push_back(Arg);
9890 CurCaptureVarInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
9893 CurCaptureVarInfo.Types.push_back(
9894 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL |
9895 OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM);
9896 CurCaptureVarInfo.Mappers.push_back(
nullptr);
9900 auto GenerateInfoForComponentLists =
9901 [&](ArrayRef<MapData> DeclComponentListsFromClauses,
9902 bool IsEligibleForTargetParamFlag) {
9903 MapCombinedInfoTy CurInfoForComponentLists;
9904 StructRangeInfoTy PartialStruct;
9905 AttachInfoTy AttachInfo;
9907 if (DeclComponentListsFromClauses.empty())
9910 generateInfoForCaptureFromComponentLists(
9911 VD, DeclComponentListsFromClauses, CurInfoForComponentLists,
9912 PartialStruct, AttachInfo, IsEligibleForTargetParamFlag);
9917 if (PartialStruct.Base.isValid()) {
9918 CurCaptureVarInfo.append(PartialStruct.PreliminaryMapData);
9920 CurCaptureVarInfo, CurInfoForComponentLists.Types,
9921 PartialStruct, AttachInfo, Cap->
capturesThis(), OMPBuilder,
9922 nullptr, OffsetForMemberOfFlag,
9923 !IsEligibleForTargetParamFlag);
9928 CurCaptureVarInfo.append(CurInfoForComponentLists);
9929 if (AttachInfo.isValid())
9930 emitAttachEntry(CGF, CurCaptureVarInfo, AttachInfo);
9954 SmallVector<std::pair<const Expr *, MapData>, 16> AttachPtrMapDataPairs;
9956 for (
const MapData &L : DeclComponentListsFromClauses) {
9959 const Expr *AttachPtrExpr = getAttachPtrExpr(Components);
9960 AttachPtrMapDataPairs.emplace_back(AttachPtrExpr, L);
9964 llvm::stable_sort(AttachPtrMapDataPairs,
9965 [
this](
const auto &LHS,
const auto &RHS) {
9966 return AttachPtrComparator(LHS.first, RHS.first);
9969 bool NoDefaultMappingDoneForVD = CurCaptureVarInfo.BasePointers.empty();
9970 bool IsFirstGroup =
true;
9974 auto *It = AttachPtrMapDataPairs.begin();
9975 while (It != AttachPtrMapDataPairs.end()) {
9976 const Expr *AttachPtrExpr = It->first;
9978 MapDataArrayTy GroupLists;
9979 while (It != AttachPtrMapDataPairs.end() &&
9980 (It->first == AttachPtrExpr ||
9981 AttachPtrComparator.areEqual(It->first, AttachPtrExpr))) {
9982 GroupLists.push_back(It->second);
9985 assert(!GroupLists.empty() &&
"GroupLists should not be empty");
9990 bool IsEligibleForTargetParamFlag =
9991 IsFirstGroup && NoDefaultMappingDoneForVD;
9993 GenerateInfoForComponentLists(GroupLists, IsEligibleForTargetParamFlag);
9994 IsFirstGroup =
false;
10001 void generateInfoForCaptureFromComponentLists(
10002 const ValueDecl *VD, ArrayRef<MapData> DeclComponentLists,
10003 MapCombinedInfoTy &CurComponentListInfo, StructRangeInfoTy &PartialStruct,
10004 AttachInfoTy &AttachInfo,
bool IsListEligibleForTargetParamFlag)
const {
10006 llvm::SmallDenseMap<
10013 for (
const MapData &L : DeclComponentLists) {
10016 ArrayRef<OpenMPMapModifierKind> MapModifiers;
10018 const ValueDecl *Mapper;
10019 const Expr *VarRef;
10020 std::tie(Components, MapType, MapModifiers, IsImplicit, Mapper, VarRef) =
10023 for (
const MapData &L1 : ArrayRef(DeclComponentLists).slice(Count)) {
10025 std::tie(Components1, MapType, MapModifiers, IsImplicit, Mapper,
10027 auto CI = Components.rbegin();
10028 auto CE = Components.rend();
10029 auto SI = Components1.rbegin();
10030 auto SE = Components1.rend();
10031 for (; CI != CE && SI != SE; ++CI, ++SI) {
10032 if (CI->getAssociatedExpression()->getStmtClass() !=
10033 SI->getAssociatedExpression()->getStmtClass())
10036 if (CI->getAssociatedDeclaration() != SI->getAssociatedDeclaration())
10041 if (CI == CE || SI == SE) {
10043 if (CI == CE && SI == SE)
10045 const auto It = (SI == SE) ? CI : SI;
10052 (std::prev(It)->getAssociatedDeclaration() &&
10054 ->getAssociatedDeclaration()
10056 ->isPointerType()) ||
10057 (It->getAssociatedDeclaration() &&
10058 It->getAssociatedDeclaration()->getType()->isPointerType() &&
10059 std::next(It) != CE && std::next(It) != SE))
10061 const MapData &BaseData = CI == CE ? L : L1;
10063 SI == SE ? Components : Components1;
10064 OverlappedData[&BaseData].push_back(SubData);
10069 llvm::SmallVector<const FieldDecl *, 4> Layout;
10070 if (!OverlappedData.empty()) {
10073 while (BaseType != OrigType) {
10079 getPlainLayout(CRD, Layout,
false);
10085 for (
auto &Pair : OverlappedData) {
10092 auto CI = First.rbegin();
10093 auto CE = First.rend();
10094 auto SI = Second.rbegin();
10095 auto SE = Second.rend();
10096 for (; CI != CE && SI != SE; ++CI, ++SI) {
10097 if (CI->getAssociatedExpression()->getStmtClass() !=
10098 SI->getAssociatedExpression()->getStmtClass())
10101 if (CI->getAssociatedDeclaration() !=
10102 SI->getAssociatedDeclaration())
10107 if (CI == CE && SI == SE)
10111 if (CI == CE || SI == SE)
10116 if (FD1->getParent() == FD2->getParent())
10117 return FD1->getFieldIndex() < FD2->getFieldIndex();
10119 llvm::find_if(Layout, [FD1, FD2](
const FieldDecl *FD) {
10120 return FD == FD1 || FD == FD2;
10128 bool AddTargetParamFlag = IsListEligibleForTargetParamFlag;
10129 MapCombinedInfoTy StructBaseCombinedInfo;
10130 for (
const auto &Pair : OverlappedData) {
10131 const MapData &L = *Pair.getFirst();
10134 ArrayRef<OpenMPMapModifierKind> MapModifiers;
10136 const ValueDecl *Mapper;
10137 const Expr *VarRef;
10138 std::tie(Components, MapType, MapModifiers, IsImplicit, Mapper, VarRef) =
10140 ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef>
10141 OverlappedComponents = Pair.getSecond();
10142 generateInfoForComponentList(
10143 MapType, MapModifiers, {}, Components, CurComponentListInfo,
10144 StructBaseCombinedInfo, PartialStruct, AttachInfo, AddTargetParamFlag,
10145 IsImplicit,
false, Mapper,
10146 false, VD, VarRef, OverlappedComponents);
10147 AddTargetParamFlag =
false;
10150 for (
const MapData &L : DeclComponentLists) {
10153 ArrayRef<OpenMPMapModifierKind> MapModifiers;
10155 const ValueDecl *Mapper;
10156 const Expr *VarRef;
10157 std::tie(Components, MapType, MapModifiers, IsImplicit, Mapper, VarRef) =
10159 auto It = OverlappedData.find(&L);
10160 if (It == OverlappedData.end())
10161 generateInfoForComponentList(
10162 MapType, MapModifiers, {}, Components, CurComponentListInfo,
10163 StructBaseCombinedInfo, PartialStruct, AttachInfo,
10164 AddTargetParamFlag, IsImplicit,
false,
10165 Mapper,
false, VD, VarRef,
10167 AddTargetParamFlag =
false;
10173 bool isEffectivelyFirstprivate(
const VarDecl *VD, QualType
Type)
const {
10175 auto I = FirstPrivateDecls.find(VD);
10176 if (I != FirstPrivateDecls.end() && !I->getSecond())
10180 if (DefaultmapFirstprivateKinds.count(OMPC_DEFAULTMAP_scalar)) {
10181 if (
Type->isScalarType())
10186 if (DefaultmapFirstprivateKinds.count(OMPC_DEFAULTMAP_pointer)) {
10187 if (
Type->isAnyPointerType())
10192 if (DefaultmapFirstprivateKinds.count(OMPC_DEFAULTMAP_aggregate)) {
10193 if (
Type->isAggregateType())
10198 return DefaultmapFirstprivateKinds.count(OMPC_DEFAULTMAP_all);
10203 void generateDefaultMapInfo(
const CapturedStmt::Capture &CI,
10204 const FieldDecl &RI, llvm::Value *CV,
10205 MapCombinedInfoTy &CombinedInfo)
const {
10206 bool IsImplicit =
true;
10209 CombinedInfo.Exprs.push_back(
nullptr);
10210 CombinedInfo.BasePointers.push_back(CV);
10211 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
10212 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
10213 CombinedInfo.Pointers.push_back(CV);
10215 CombinedInfo.Sizes.push_back(
10219 CombinedInfo.Types.push_back(OpenMPOffloadMappingFlags::OMP_MAP_TO |
10220 OpenMPOffloadMappingFlags::OMP_MAP_FROM);
10224 CombinedInfo.BasePointers.push_back(CV);
10225 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
10226 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
10227 CombinedInfo.Pointers.push_back(CV);
10228 bool IsFirstprivate =
10234 CombinedInfo.Types.push_back(
10235 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL);
10236 CombinedInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
10238 }
else if (IsFirstprivate) {
10241 CombinedInfo.Types.push_back(
10242 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL);
10244 CombinedInfo.Sizes.push_back(llvm::Constant::getNullValue(CGF.
Int64Ty));
10248 CombinedInfo.Types.push_back(OpenMPOffloadMappingFlags::OMP_MAP_NONE);
10249 CombinedInfo.Sizes.push_back(llvm::Constant::getNullValue(CGF.
Int64Ty));
10251 auto I = FirstPrivateDecls.find(VD);
10252 if (I != FirstPrivateDecls.end())
10253 IsImplicit = I->getSecond();
10259 bool IsFirstprivate = isEffectivelyFirstprivate(VD, ElementType);
10261 CombinedInfo.BasePointers.push_back(CV);
10262 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
10263 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
10268 CombinedInfo.Pointers.push_back(CV);
10270 CombinedInfo.Sizes.push_back(llvm::Constant::getNullValue(CGF.
Int64Ty));
10271 CombinedInfo.Types.push_back(
10272 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL);
10274 CombinedInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
10279 CombinedInfo.Types.push_back(getMapModifiersForPrivateClauses(CI));
10280 CombinedInfo.Pointers.push_back(CV);
10282 auto I = FirstPrivateDecls.find(VD);
10283 if (I != FirstPrivateDecls.end())
10284 IsImplicit = I->getSecond();
10287 CombinedInfo.Types.back() |=
10288 OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM;
10292 CombinedInfo.Types.back() |= OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT;
10295 CombinedInfo.Mappers.push_back(
nullptr);
10307 dyn_cast<MemberExpr>(OASE->getBase()->IgnoreParenImpCasts()))
10308 return ME->getMemberDecl();
10314static llvm::Constant *
10316 MappableExprsHandler::MappingExprInfo &MapExprs) {
10318 uint32_t SrcLocStrSize;
10319 if (!MapExprs.getMapDecl() && !MapExprs.getMapExpr())
10320 return OMPBuilder.getOrCreateDefaultSrcLocStr(SrcLocStrSize);
10323 if (!MapExprs.getMapDecl() && MapExprs.getMapExpr()) {
10327 Loc = MapExprs.getMapExpr()->getExprLoc();
10329 Loc = MapExprs.getMapDecl()->getLocation();
10332 std::string ExprName;
10333 if (MapExprs.getMapExpr()) {
10335 llvm::raw_string_ostream OS(ExprName);
10336 MapExprs.getMapExpr()->printPretty(OS,
nullptr, P);
10338 ExprName = MapExprs.getMapDecl()->getNameAsString();
10347 return OMPBuilder.getOrCreateSrcLocStr(
FileName, ExprName, PLoc.
getLine(),
10354 CodeGenFunction &CGF, MappableExprsHandler::MapCombinedInfoTy &CombinedInfo,
10356 bool IsNonContiguous =
false,
bool ForEndCall =
false) {
10359 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
10362 InsertPointTy CodeGenIP(CGF.
Builder.GetInsertBlock(),
10363 CGF.
Builder.GetInsertPoint());
10365 auto DeviceAddrCB = [&](
unsigned int I, llvm::Value *NewDecl) {
10366 if (
const ValueDecl *DevVD = CombinedInfo.DevicePtrDecls[I]) {
10371 auto CustomMapperCB = [&](
unsigned int I) {
10372 llvm::Function *MFunc =
nullptr;
10373 if (CombinedInfo.Mappers[I]) {
10374 Info.HasMapper =
true;
10380 cantFail(OMPBuilder.emitOffloadingArraysAndArgs(
10381 AllocaIP, CodeGenIP, Info, Info.RTArgs, CombinedInfo, CustomMapperCB,
10382 IsNonContiguous, ForEndCall, DeviceAddrCB));
10386static const OMPExecutableDirective *
10388 const auto *CS = D.getInnermostCapturedStmt();
10391 const Stmt *ChildStmt =
10394 if (
const auto *NestedDir =
10395 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) {
10397 switch (D.getDirectiveKind()) {
10403 if (DKind == OMPD_teams) {
10404 Body = NestedDir->getInnermostCapturedStmt()->IgnoreContainers(
10409 if (
const auto *NND =
10410 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) {
10411 DKind = NND->getDirectiveKind();
10417 case OMPD_target_teams:
10421 case OMPD_target_parallel:
10422 case OMPD_target_simd:
10423 case OMPD_target_parallel_for:
10424 case OMPD_target_parallel_for_simd:
10426 case OMPD_target_teams_distribute:
10427 case OMPD_target_teams_distribute_simd:
10428 case OMPD_target_teams_distribute_parallel_for:
10429 case OMPD_target_teams_distribute_parallel_for_simd:
10430 case OMPD_parallel:
10432 case OMPD_parallel_for:
10433 case OMPD_parallel_master:
10434 case OMPD_parallel_sections:
10435 case OMPD_for_simd:
10436 case OMPD_parallel_for_simd:
10438 case OMPD_cancellation_point:
10440 case OMPD_threadprivate:
10441 case OMPD_allocate:
10446 case OMPD_sections:
10450 case OMPD_critical:
10451 case OMPD_taskyield:
10453 case OMPD_taskwait:
10454 case OMPD_taskgroup:
10460 case OMPD_target_data:
10461 case OMPD_target_exit_data:
10462 case OMPD_target_enter_data:
10463 case OMPD_distribute:
10464 case OMPD_distribute_simd:
10465 case OMPD_distribute_parallel_for:
10466 case OMPD_distribute_parallel_for_simd:
10467 case OMPD_teams_distribute:
10468 case OMPD_teams_distribute_simd:
10469 case OMPD_teams_distribute_parallel_for:
10470 case OMPD_teams_distribute_parallel_for_simd:
10471 case OMPD_target_update:
10472 case OMPD_declare_simd:
10473 case OMPD_declare_variant:
10474 case OMPD_begin_declare_variant:
10475 case OMPD_end_declare_variant:
10476 case OMPD_declare_target:
10477 case OMPD_end_declare_target:
10478 case OMPD_declare_reduction:
10479 case OMPD_declare_mapper:
10480 case OMPD_taskloop:
10481 case OMPD_taskloop_simd:
10482 case OMPD_master_taskloop:
10483 case OMPD_master_taskloop_simd:
10484 case OMPD_parallel_master_taskloop:
10485 case OMPD_parallel_master_taskloop_simd:
10486 case OMPD_requires:
10487 case OMPD_metadirective:
10490 llvm_unreachable(
"Unexpected directive.");
10529 if (
UDMMap.count(D) > 0)
10533 auto *MapperVarDecl =
10535 CharUnits ElementSize =
C.getTypeSizeInChars(Ty);
10536 llvm::Type *ElemTy =
CGM.getTypes().ConvertTypeForMem(Ty);
10539 MappableExprsHandler::MapCombinedInfoTy CombinedInfo;
10540 auto PrivatizeAndGenMapInfoCB =
10541 [&](llvm::OpenMPIRBuilder::InsertPointTy CodeGenIP, llvm::Value *PtrPHI,
10542 llvm::Value *BeginArg) -> llvm::OpenMPIRBuilder::MapInfosTy & {
10543 MapperCGF.
Builder.restoreIP(CodeGenIP);
10553 Scope.addPrivate(MapperVarDecl, PtrCurrent);
10554 (void)
Scope.Privatize();
10557 MappableExprsHandler MEHandler(*D, MapperCGF);
10558 MEHandler.generateAllInfoForMapper(CombinedInfo,
OMPBuilder);
10560 auto FillInfoMap = [&](MappableExprsHandler::MappingExprInfo &MapExpr) {
10563 if (
CGM.getCodeGenOpts().getDebugInfo() !=
10564 llvm::codegenoptions::NoDebugInfo) {
10565 CombinedInfo.Names.resize(CombinedInfo.Exprs.size());
10566 llvm::transform(CombinedInfo.Exprs, CombinedInfo.Names.begin(),
10570 return CombinedInfo;
10573 auto CustomMapperCB = [&](
unsigned I) {
10574 llvm::Function *MapperFunc =
nullptr;
10575 if (CombinedInfo.Mappers[I]) {
10579 assert(MapperFunc &&
"Expect a valid mapper function is available.");
10585 llvm::raw_svector_ostream Out(TyStr);
10586 CGM.getCXXABI().getMangleContext().mangleCanonicalTypeName(Ty, Out);
10587 std::string Name =
getName({
"omp_mapper", TyStr, D->
getName()});
10589 llvm::Function *NewFn = cantFail(
OMPBuilder.emitUserDefinedMapper(
10590 PrivatizeAndGenMapInfoCB, ElemTy, Name, CustomMapperCB));
10591 UDMMap.try_emplace(D, NewFn);
10598 auto I =
UDMMap.find(D);
10602 return UDMMap.lookup(D);
10615 Kind != OMPD_target_teams_loop)
10618 return llvm::ConstantInt::get(CGF.
Int64Ty, 0);
10621 if (llvm::Value *NumIterations = SizeEmitter(CGF, *LD))
10622 return NumIterations;
10623 return llvm::ConstantInt::get(CGF.
Int64Ty, 0);
10632 if (OffloadingMandatory) {
10633 CGF.
Builder.CreateUnreachable();
10635 if (RequiresOuterTask) {
10636 CapturedVars.clear();
10645 llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier>
Device,
10648 llvm::Value *DeviceID;
10649 if (
Device.getPointer()) {
10651 Device.getInt() == OMPC_DEVICE_device_num) &&
10652 "Expected device_num modifier.");
10657 DeviceID = CGF.
Builder.getInt64(OMP_DEVICEID_UNDEF);
10662static std::pair<llvm::Value *, OMPDynGroupprivateFallbackType>
10664 llvm::Value *DynGP = CGF.
Builder.getInt32(0);
10665 auto DynGPFallback = OMPDynGroupprivateFallbackType::Abort;
10669 llvm::Value *DynGPVal =
10673 auto FallbackModifier = DynGPClause->getDynGroupprivateFallbackModifier();
10674 switch (FallbackModifier) {
10675 case OMPC_DYN_GROUPPRIVATE_FALLBACK_abort:
10676 DynGPFallback = OMPDynGroupprivateFallbackType::Abort;
10678 case OMPC_DYN_GROUPPRIVATE_FALLBACK_null:
10679 DynGPFallback = OMPDynGroupprivateFallbackType::Null;
10681 case OMPC_DYN_GROUPPRIVATE_FALLBACK_default_mem:
10684 DynGPFallback = OMPDynGroupprivateFallbackType::DefaultMem;
10687 llvm_unreachable(
"Unknown fallback modifier for OpenMP dyn_groupprivate");
10689 }
else if (
auto *OMPXDynCGClause =
10692 llvm::Value *DynCGMemVal = CGF.
EmitScalarExpr(OMPXDynCGClause->getSize(),
10697 return {DynGP, DynGPFallback};
10703 llvm::OpenMPIRBuilder &OMPBuilder,
10705 MappableExprsHandler::MapCombinedInfoTy &CombinedInfo) {
10707 llvm::DenseMap<llvm::Value *, llvm::Value *> LambdaPointers;
10709 auto *CV = CapturedVars.begin();
10712 CI != CE; ++CI, ++RI, ++CV) {
10713 MappableExprsHandler::MapCombinedInfoTy CurInfo;
10718 CurInfo.Exprs.push_back(
nullptr);
10719 CurInfo.BasePointers.push_back(*CV);
10720 CurInfo.DevicePtrDecls.push_back(
nullptr);
10721 CurInfo.DevicePointers.push_back(
10722 MappableExprsHandler::DeviceInfoTy::None);
10723 CurInfo.Pointers.push_back(*CV);
10724 CurInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
10727 CurInfo.Types.push_back(OpenMPOffloadMappingFlags::OMP_MAP_LITERAL |
10728 OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM |
10729 OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT);
10730 CurInfo.Mappers.push_back(
nullptr);
10735 bool HasEntryWithCVAsAttachPtr =
false;
10737 HasEntryWithCVAsAttachPtr =
10738 MEHandler.hasAttachEntryForCapturedVar(CapturedVD);
10741 MappableExprsHandler::MapDataArrayTy DeclComponentLists;
10744 StorageForImplicitlyAddedComponentLists;
10745 MEHandler.populateComponentListsForNonLambdaCaptureFromClauses(
10746 CapturedVD, DeclComponentLists,
10747 StorageForImplicitlyAddedComponentLists);
10758 bool HasEntryWithoutAttachPtr =
10759 llvm::any_of(DeclComponentLists, [&](
const auto &MapData) {
10761 Components = std::get<0>(MapData);
10762 return !MEHandler.getAttachPtrExpr(Components);
10767 if (DeclComponentLists.empty() ||
10768 (!HasEntryWithCVAsAttachPtr && !HasEntryWithoutAttachPtr))
10769 MEHandler.generateDefaultMapInfo(*CI, **RI, *CV, CurInfo);
10773 MEHandler.generateInfoForCaptureFromClauseInfo(
10774 DeclComponentLists, CI, *CV, CurInfo, OMPBuilder,
10775 CombinedInfo.BasePointers.size());
10780 MappedVarSet.insert(
nullptr);
10785 MEHandler.generateInfoForLambdaCaptures(CI->
getCapturedVar(), *CV,
10786 CurInfo, LambdaPointers);
10789 assert(!CurInfo.BasePointers.empty() &&
10790 "Non-existing map pointer for capture!");
10791 assert(CurInfo.BasePointers.size() == CurInfo.Pointers.size() &&
10792 CurInfo.BasePointers.size() == CurInfo.Sizes.size() &&
10793 CurInfo.BasePointers.size() == CurInfo.Types.size() &&
10794 CurInfo.BasePointers.size() == CurInfo.Mappers.size() &&
10795 "Inconsistent map information sizes!");
10798 CombinedInfo.append(CurInfo);
10801 MEHandler.adjustMemberOfForLambdaCaptures(
10802 OMPBuilder, LambdaPointers, CombinedInfo.BasePointers,
10803 CombinedInfo.Pointers, CombinedInfo.Types);
10807 MappableExprsHandler::MapCombinedInfoTy &CombinedInfo,
10808 llvm::OpenMPIRBuilder &OMPBuilder,
10815 MEHandler.generateAllInfo(CombinedInfo, OMPBuilder, SkippedVarSet);
10817 auto FillInfoMap = [&](MappableExprsHandler::MappingExprInfo &MapExpr) {
10821 llvm::codegenoptions::NoDebugInfo) {
10822 CombinedInfo.Names.resize(CombinedInfo.Exprs.size());
10823 llvm::transform(CombinedInfo.Exprs, CombinedInfo.Names.begin(),
10831 llvm::OpenMPIRBuilder &OMPBuilder,
10832 MappableExprsHandler::MapCombinedInfoTy &CombinedInfo) {
10834 MappableExprsHandler MEHandler(D, CGF);
10835 llvm::DenseSet<CanonicalDeclPtr<const Decl>> MappedVarSet;
10838 MappedVarSet, CombinedInfo);
10839 genMapInfo(MEHandler, CGF, CombinedInfo, OMPBuilder, MappedVarSet);
10842template <
typename ClauseTy>
10847 const auto *
C = D.getSingleClause<ClauseTy>();
10848 assert(!
C->varlist_empty() &&
10849 "ompx_bare requires explicit num_teams and thread_limit");
10851 for (
auto *E :
C->varlist()) {
10863 llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier>
Device,
10865 llvm::Value *&MapTypesArray, llvm::Value *&MapNamesArray,
10870 llvm::OpenMPIRBuilder &OMPBuilder = OMPRuntime->
getOMPBuilder();
10873 MappableExprsHandler::MapCombinedInfoTy CombinedInfo;
10875 genMapInfo(D, CGF, CS, CapturedVars, OMPBuilder, CombinedInfo);
10889 MapTypesArray = Info.RTArgs.MapTypesArray;
10890 MapNamesArray = Info.RTArgs.MapNamesArray;
10892 auto &&ThenGen = [&OMPRuntime, OutlinedFn, &D, &CapturedVars,
10893 RequiresOuterTask, &CS, OffloadingMandatory,
Device,
10894 OutlinedFnID, &InputInfo, &MapTypesArray, &MapNamesArray,
10896 bool IsReverseOffloading =
Device.getInt() == OMPC_DEVICE_ancestor;
10898 if (IsReverseOffloading) {
10904 RequiresOuterTask, CS, OffloadingMandatory, CGF);
10908 bool HasNoWait = D.hasClausesOfKind<OMPNowaitClause>();
10909 unsigned NumTargetItems = InputInfo.NumberOfTargetItems;
10911 llvm::Value *BasePointersArray =
10912 InputInfo.BasePointersArray.emitRawPointer(CGF);
10913 llvm::Value *PointersArray = InputInfo.PointersArray.emitRawPointer(CGF);
10914 llvm::Value *SizesArray = InputInfo.SizesArray.emitRawPointer(CGF);
10915 llvm::Value *MappersArray = InputInfo.MappersArray.emitRawPointer(CGF);
10917 auto &&EmitTargetCallFallbackCB =
10918 [&OMPRuntime, OutlinedFn, &D, &CapturedVars, RequiresOuterTask, &CS,
10919 OffloadingMandatory, &CGF](llvm::OpenMPIRBuilder::InsertPointTy IP)
10920 -> llvm::OpenMPIRBuilder::InsertPointTy {
10923 RequiresOuterTask, CS, OffloadingMandatory, CGF);
10936 NumThreads.push_back(
10942 llvm::Value *NumIterations =
10945 llvm::OpenMPIRBuilder::InsertPointTy AllocaIP(
10948 llvm::OpenMPIRBuilder::TargetDataRTArgs RTArgs(
10949 BasePointersArray, PointersArray, SizesArray, MapTypesArray,
10950 nullptr , MappersArray, MapNamesArray);
10952 llvm::OpenMPIRBuilder::TargetKernelArgs Args(
10953 NumTargetItems, RTArgs, NumIterations, NumTeams, NumThreads,
10954 DynCGroupMem, HasNoWait, DynCGroupMemFallback);
10956 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
10958 CGF.
Builder, OutlinedFnID, EmitTargetCallFallbackCB, Args, DeviceID,
10960 CGF.
Builder.restoreIP(AfterIP);
10963 if (RequiresOuterTask)
10978 [&OMPRuntime, OutlinedFn, &D, &CapturedVars, RequiresOuterTask, &CS,
10981 RequiresOuterTask, CS, OffloadingMandatory, CGF);
10984 if (RequiresOuterTask) {
10994 llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID,
const Expr *IfCond,
10995 llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier>
Device,
11002 const bool OffloadingMandatory = !
CGM.getLangOpts().OpenMPIsTargetDevice &&
11003 CGM.getLangOpts().OpenMPOffloadMandatory;
11005 assert((OffloadingMandatory || OutlinedFn) &&
"Invalid outlined function!");
11007 const bool RequiresOuterTask =
11009 D.hasClausesOfKind<OMPNowaitClause>() ||
11010 D.hasClausesOfKind<OMPInReductionClause>() ||
11011 (
CGM.getLangOpts().OpenMP >= 51 &&
11015 const CapturedStmt &CS = *D.getCapturedStmt(OMPD_target);
11023 llvm::Value *MapTypesArray =
nullptr;
11024 llvm::Value *MapNamesArray =
nullptr;
11026 auto &&TargetThenGen = [
this, OutlinedFn, &D, &CapturedVars,
11027 RequiresOuterTask, &CS, OffloadingMandatory,
Device,
11028 OutlinedFnID, &InputInfo, &MapTypesArray,
11032 RequiresOuterTask, CS, OffloadingMandatory,
11033 Device, OutlinedFnID, InputInfo, MapTypesArray,
11034 MapNamesArray, SizeEmitter, CGF,
CGM);
11037 auto &&TargetElseGen =
11038 [
this, OutlinedFn, &D, &CapturedVars, RequiresOuterTask, &CS,
11041 CS, OffloadingMandatory, CGF);
11048 if (OutlinedFnID) {
11050 emitIfClause(CGF, IfCond, TargetThenGen, TargetElseGen);
11062 StringRef ParentName) {
11069 if (
auto *E = dyn_cast<OMPExecutableDirective>(S);
11078 bool RequiresDeviceCodegen =
11083 if (RequiresDeviceCodegen) {
11091 if (!
OMPBuilder.OffloadInfoManager.hasTargetRegionEntryInfo(EntryInfo))
11094 switch (E.getDirectiveKind()) {
11099 case OMPD_target_parallel:
11103 case OMPD_target_teams:
11107 case OMPD_target_teams_distribute:
11111 case OMPD_target_teams_distribute_simd:
11115 case OMPD_target_parallel_for:
11119 case OMPD_target_parallel_for_simd:
11123 case OMPD_target_simd:
11127 case OMPD_target_teams_distribute_parallel_for:
11132 case OMPD_target_teams_distribute_parallel_for_simd:
11138 case OMPD_target_teams_loop:
11142 case OMPD_target_parallel_loop:
11146 case OMPD_parallel:
11148 case OMPD_parallel_for:
11149 case OMPD_parallel_master:
11150 case OMPD_parallel_sections:
11151 case OMPD_for_simd:
11152 case OMPD_parallel_for_simd:
11154 case OMPD_cancellation_point:
11156 case OMPD_threadprivate:
11157 case OMPD_allocate:
11162 case OMPD_sections:
11166 case OMPD_critical:
11167 case OMPD_taskyield:
11169 case OMPD_taskwait:
11170 case OMPD_taskgroup:
11176 case OMPD_target_data:
11177 case OMPD_target_exit_data:
11178 case OMPD_target_enter_data:
11179 case OMPD_distribute:
11180 case OMPD_distribute_simd:
11181 case OMPD_distribute_parallel_for:
11182 case OMPD_distribute_parallel_for_simd:
11183 case OMPD_teams_distribute:
11184 case OMPD_teams_distribute_simd:
11185 case OMPD_teams_distribute_parallel_for:
11186 case OMPD_teams_distribute_parallel_for_simd:
11187 case OMPD_target_update:
11188 case OMPD_declare_simd:
11189 case OMPD_declare_variant:
11190 case OMPD_begin_declare_variant:
11191 case OMPD_end_declare_variant:
11192 case OMPD_declare_target:
11193 case OMPD_end_declare_target:
11194 case OMPD_declare_reduction:
11195 case OMPD_declare_mapper:
11196 case OMPD_taskloop:
11197 case OMPD_taskloop_simd:
11198 case OMPD_master_taskloop:
11199 case OMPD_master_taskloop_simd:
11200 case OMPD_parallel_master_taskloop:
11201 case OMPD_parallel_master_taskloop_simd:
11202 case OMPD_requires:
11203 case OMPD_metadirective:
11206 llvm_unreachable(
"Unknown target directive for OpenMP device codegen.");
11211 if (
const auto *E = dyn_cast<OMPExecutableDirective>(S)) {
11212 if (!E->hasAssociatedStmt() || !E->getAssociatedStmt())
11220 if (
const auto *L = dyn_cast<LambdaExpr>(S))
11229 std::optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
11230 OMPDeclareTargetDeclAttr::getDeviceType(VD);
11234 if (!IsDevice && DevTy == OMPDeclareTargetDeclAttr::DT_NoHost)
11237 if (IsDevice && DevTy == OMPDeclareTargetDeclAttr::DT_Host)
11245 if (!
CGM.getLangOpts().OpenMPIsTargetDevice) {
11246 if (
const auto *FD = dyn_cast<FunctionDecl>(GD.
getDecl()))
11248 CGM.getLangOpts().OpenMPIsTargetDevice))
11255 if (
const auto *FD = dyn_cast<FunctionDecl>(VD)) {
11256 StringRef Name =
CGM.getMangledName(GD);
11259 CGM.getLangOpts().OpenMPIsTargetDevice))
11264 return !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD) &&
11270 CGM.getLangOpts().OpenMPIsTargetDevice))
11273 if (!
CGM.getLangOpts().OpenMPIsTargetDevice)
11282 StringRef ParentName =
11287 StringRef ParentName =
11294 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
11295 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(
11297 if (!Res || *Res == OMPDeclareTargetDeclAttr::MT_Link ||
11298 ((*Res == OMPDeclareTargetDeclAttr::MT_To ||
11299 *Res == OMPDeclareTargetDeclAttr::MT_Enter) &&
11308 llvm::Constant *
Addr) {
11309 if (
CGM.getLangOpts().OMPTargetTriples.empty() &&
11310 !
CGM.getLangOpts().OpenMPIsTargetDevice)
11313 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
11314 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
11318 if (Res && *Res != OMPDeclareTargetDeclAttr::MT_Link &&
11323 if (
CGM.getLangOpts().OpenMPIsTargetDevice) {
11326 StringRef VarName =
CGM.getMangledName(VD);
11332 auto AddrOfGlobal = [&VD,
this]() {
return CGM.GetAddrOfGlobal(VD); };
11333 auto LinkageForVariable = [&VD,
this]() {
11334 return CGM.getLLVMLinkageVarDefinition(VD);
11337 std::vector<llvm::GlobalVariable *> GeneratedRefs;
11344 CGM.getMangledName(VD), GeneratedRefs,
CGM.getLangOpts().OpenMPSimd,
11345 CGM.getLangOpts().OMPTargetTriples, AddrOfGlobal, LinkageForVariable,
11346 CGM.getTypes().ConvertTypeForMem(
11347 CGM.getContext().getPointerType(VD->
getType())),
11350 for (
auto *ref : GeneratedRefs)
11351 CGM.addCompilerUsedGlobal(ref);
11364 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
11365 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
11368 if ((*Res == OMPDeclareTargetDeclAttr::MT_To ||
11369 *Res == OMPDeclareTargetDeclAttr::MT_Enter) &&
11371 CGM.EmitGlobal(VD);
11373 assert((*Res == OMPDeclareTargetDeclAttr::MT_Link ||
11374 ((*Res == OMPDeclareTargetDeclAttr::MT_To ||
11375 *Res == OMPDeclareTargetDeclAttr::MT_Enter) &&
11377 "Expected link clause or to clause with unified memory.");
11378 (void)
CGM.getOpenMPRuntime().getAddrOfDeclareTargetVar(VD);
11386 " Expected target-based directive.");
11391 if (Clause->getClauseKind() == OMPC_unified_shared_memory) {
11393 OMPBuilder.Config.setHasRequiresUnifiedSharedMemory(
true);
11394 }
else if (
const auto *AC =
11395 dyn_cast<OMPAtomicDefaultMemOrderClause>(Clause)) {
11396 switch (AC->getAtomicDefaultMemOrderKind()) {
11397 case OMPC_ATOMIC_DEFAULT_MEM_ORDER_acq_rel:
11400 case OMPC_ATOMIC_DEFAULT_MEM_ORDER_seq_cst:
11403 case OMPC_ATOMIC_DEFAULT_MEM_ORDER_relaxed:
11419 if (!VD || !VD->
hasAttr<OMPAllocateDeclAttr>())
11421 const auto *A = VD->
getAttr<OMPAllocateDeclAttr>();
11422 switch(A->getAllocatorType()) {
11423 case OMPAllocateDeclAttr::OMPNullMemAlloc:
11424 case OMPAllocateDeclAttr::OMPDefaultMemAlloc:
11426 case OMPAllocateDeclAttr::OMPLargeCapMemAlloc:
11427 case OMPAllocateDeclAttr::OMPCGroupMemAlloc:
11428 case OMPAllocateDeclAttr::OMPHighBWMemAlloc:
11429 case OMPAllocateDeclAttr::OMPLowLatMemAlloc:
11430 case OMPAllocateDeclAttr::OMPThreadMemAlloc:
11431 case OMPAllocateDeclAttr::OMPConstMemAlloc:
11432 case OMPAllocateDeclAttr::OMPPTeamMemAlloc:
11435 case OMPAllocateDeclAttr::OMPUserDefinedMemAlloc:
11436 llvm_unreachable(
"Expected predefined allocator for the variables with the "
11437 "static storage.");
11449 if (CGM.getLangOpts().OpenMPIsTargetDevice) {
11450 SavedShouldMarkAsGlobal = CGM.getOpenMPRuntime().ShouldMarkAsGlobal;
11451 CGM.getOpenMPRuntime().ShouldMarkAsGlobal = false;
11456 if (CGM.getLangOpts().OpenMPIsTargetDevice)
11457 CGM.getOpenMPRuntime().ShouldMarkAsGlobal = SavedShouldMarkAsGlobal;
11467 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(D)) {
11469 if (
auto *F = dyn_cast_or_null<llvm::Function>(
11470 CGM.GetGlobalValue(
CGM.getMangledName(GD))))
11471 return !F->isDeclaration();
11483 llvm::Function *OutlinedFn,
11492 llvm::Value *Args[] = {
11494 CGF.
Builder.getInt32(CapturedVars.size()),
11497 RealArgs.append(std::begin(Args), std::end(Args));
11498 RealArgs.append(CapturedVars.begin(), CapturedVars.end());
11500 llvm::FunctionCallee RTLFn =
OMPBuilder.getOrCreateRuntimeFunction(
11501 CGM.getModule(), OMPRTL___kmpc_fork_teams);
11506 const Expr *NumTeams,
11507 const Expr *ThreadLimit,
11514 llvm::Value *NumTeamsVal =
11520 llvm::Value *ThreadLimitVal =
11527 llvm::Value *PushNumTeamsArgs[] = {RTLoc,
getThreadID(CGF, Loc), NumTeamsVal,
11530 CGM.getModule(), OMPRTL___kmpc_push_num_teams),
11535 const Expr *ThreadLimit,
11538 llvm::Value *ThreadLimitVal =
11545 llvm::Value *ThreadLimitArgs[] = {RTLoc,
getThreadID(CGF, Loc),
11548 CGM.getModule(), OMPRTL___kmpc_set_thread_limit),
11563 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
11565 llvm::Value *IfCondVal =
nullptr;
11570 llvm::Value *DeviceID =
nullptr;
11575 DeviceID = CGF.
Builder.getInt64(OMP_DEVICEID_UNDEF);
11579 MappableExprsHandler::MapCombinedInfoTy CombinedInfo;
11580 auto GenMapInfoCB =
11581 [&](InsertPointTy CodeGenIP) -> llvm::OpenMPIRBuilder::MapInfosTy & {
11582 CGF.
Builder.restoreIP(CodeGenIP);
11584 MappableExprsHandler MEHandler(D, CGF);
11585 MEHandler.generateAllInfo(CombinedInfo,
OMPBuilder);
11587 auto FillInfoMap = [&](MappableExprsHandler::MappingExprInfo &MapExpr) {
11590 if (
CGM.getCodeGenOpts().getDebugInfo() !=
11591 llvm::codegenoptions::NoDebugInfo) {
11592 CombinedInfo.Names.resize(CombinedInfo.Exprs.size());
11593 llvm::transform(CombinedInfo.Exprs, CombinedInfo.Names.begin(),
11597 return CombinedInfo;
11599 using BodyGenTy = llvm::OpenMPIRBuilder::BodyGenTy;
11600 auto BodyCB = [&](InsertPointTy CodeGenIP, BodyGenTy BodyGenType) {
11601 CGF.
Builder.restoreIP(CodeGenIP);
11602 switch (BodyGenType) {
11603 case BodyGenTy::Priv:
11607 case BodyGenTy::DupNoPriv:
11609 CodeGen.setAction(NoPrivAction);
11613 case BodyGenTy::NoPriv:
11615 CodeGen.setAction(NoPrivAction);
11620 return InsertPointTy(CGF.
Builder.GetInsertBlock(),
11621 CGF.
Builder.GetInsertPoint());
11624 auto DeviceAddrCB = [&](
unsigned int I, llvm::Value *NewDecl) {
11625 if (
const ValueDecl *DevVD = CombinedInfo.DevicePtrDecls[I]) {
11630 auto CustomMapperCB = [&](
unsigned int I) {
11631 llvm::Function *MFunc =
nullptr;
11632 if (CombinedInfo.Mappers[I]) {
11633 Info.HasMapper =
true;
11645 InsertPointTy CodeGenIP(CGF.
Builder.GetInsertBlock(),
11646 CGF.
Builder.GetInsertPoint());
11647 llvm::OpenMPIRBuilder::LocationDescription OmpLoc(CodeGenIP);
11648 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
11650 OmpLoc, AllocaIP, CodeGenIP, DeviceID, IfCondVal, Info, GenMapInfoCB,
11652 nullptr, BodyCB, DeviceAddrCB, RTLoc));
11653 CGF.
Builder.restoreIP(AfterIP);
11665 "Expecting either target enter, exit data, or update directives.");
11668 llvm::Value *MapTypesArray =
nullptr;
11669 llvm::Value *MapNamesArray =
nullptr;
11671 auto &&ThenGen = [
this, &D,
Device, &InputInfo, &MapTypesArray,
11674 llvm::Value *DeviceID =
nullptr;
11679 DeviceID = CGF.
Builder.getInt64(OMP_DEVICEID_UNDEF);
11683 llvm::Constant *PointerNum =
11690 {RTLoc, DeviceID, PointerNum,
11698 const bool HasNowait = D.hasClausesOfKind<OMPNowaitClause>();
11699 RuntimeFunction RTLFn;
11700 switch (D.getDirectiveKind()) {
11701 case OMPD_target_enter_data:
11702 RTLFn = HasNowait ? OMPRTL___tgt_target_data_begin_nowait_mapper
11703 : OMPRTL___tgt_target_data_begin_mapper;
11705 case OMPD_target_exit_data:
11706 RTLFn = HasNowait ? OMPRTL___tgt_target_data_end_nowait_mapper
11707 : OMPRTL___tgt_target_data_end_mapper;
11709 case OMPD_target_update:
11710 RTLFn = HasNowait ? OMPRTL___tgt_target_data_update_nowait_mapper
11711 : OMPRTL___tgt_target_data_update_mapper;
11713 case OMPD_parallel:
11715 case OMPD_parallel_for:
11716 case OMPD_parallel_master:
11717 case OMPD_parallel_sections:
11718 case OMPD_for_simd:
11719 case OMPD_parallel_for_simd:
11721 case OMPD_cancellation_point:
11723 case OMPD_threadprivate:
11724 case OMPD_allocate:
11729 case OMPD_sections:
11733 case OMPD_critical:
11734 case OMPD_taskyield:
11736 case OMPD_taskwait:
11737 case OMPD_taskgroup:
11743 case OMPD_target_data:
11744 case OMPD_distribute:
11745 case OMPD_distribute_simd:
11746 case OMPD_distribute_parallel_for:
11747 case OMPD_distribute_parallel_for_simd:
11748 case OMPD_teams_distribute:
11749 case OMPD_teams_distribute_simd:
11750 case OMPD_teams_distribute_parallel_for:
11751 case OMPD_teams_distribute_parallel_for_simd:
11752 case OMPD_declare_simd:
11753 case OMPD_declare_variant:
11754 case OMPD_begin_declare_variant:
11755 case OMPD_end_declare_variant:
11756 case OMPD_declare_target:
11757 case OMPD_end_declare_target:
11758 case OMPD_declare_reduction:
11759 case OMPD_declare_mapper:
11760 case OMPD_taskloop:
11761 case OMPD_taskloop_simd:
11762 case OMPD_master_taskloop:
11763 case OMPD_master_taskloop_simd:
11764 case OMPD_parallel_master_taskloop:
11765 case OMPD_parallel_master_taskloop_simd:
11767 case OMPD_target_simd:
11768 case OMPD_target_teams_distribute:
11769 case OMPD_target_teams_distribute_simd:
11770 case OMPD_target_teams_distribute_parallel_for:
11771 case OMPD_target_teams_distribute_parallel_for_simd:
11772 case OMPD_target_teams:
11773 case OMPD_target_parallel:
11774 case OMPD_target_parallel_for:
11775 case OMPD_target_parallel_for_simd:
11776 case OMPD_requires:
11777 case OMPD_metadirective:
11780 llvm_unreachable(
"Unexpected standalone target data directive.");
11784 OffloadingArgs.push_back(llvm::Constant::getNullValue(CGF.
Int32Ty));
11785 OffloadingArgs.push_back(llvm::Constant::getNullValue(CGF.
VoidPtrTy));
11786 OffloadingArgs.push_back(llvm::Constant::getNullValue(CGF.
Int32Ty));
11787 OffloadingArgs.push_back(llvm::Constant::getNullValue(CGF.
VoidPtrTy));
11790 OMPBuilder.getOrCreateRuntimeFunction(
CGM.getModule(), RTLFn),
11794 auto &&TargetThenGen = [
this, &ThenGen, &D, &InputInfo, &MapTypesArray,
11798 MappableExprsHandler::MapCombinedInfoTy CombinedInfo;
11800 MappableExprsHandler MEHandler(D, CGF);
11806 D.hasClausesOfKind<OMPNowaitClause>();
11812 CGM.getPointerAlign());
11817 MapTypesArray = Info.RTArgs.MapTypesArray;
11818 MapNamesArray = Info.RTArgs.MapNamesArray;
11819 if (RequiresOuterTask)
11845struct ParamAttrTy {
11846 ParamKindTy Kind =
Vector;
11847 llvm::APSInt StrideOrArg;
11848 llvm::APSInt Alignment;
11849 bool HasVarStride =
false;
11882 unsigned Offset = 0;
11883 if (
const auto *MD = dyn_cast<CXXMethodDecl>(FD)) {
11884 if (ParamAttrs[Offset].Kind ==
Vector)
11885 CDT =
C.getPointerType(
C.getCanonicalTagType(MD->
getParent()));
11889 for (
unsigned I = 0, E = FD->
getNumParams(); I < E; ++I) {
11890 if (ParamAttrs[I + Offset].Kind ==
Vector) {
11902 return C.getTypeSize(CDT);
11910 llvm::raw_svector_ostream Out(Buffer);
11911 for (
const auto &ParamAttr : ParamAttrs) {
11912 switch (ParamAttr.Kind) {
11932 if (ParamAttr.HasVarStride)
11933 Out <<
"s" << ParamAttr.StrideOrArg;
11934 else if (ParamAttr.Kind == Linear || ParamAttr.Kind == LinearRef ||
11935 ParamAttr.Kind == LinearUVal || ParamAttr.Kind == LinearVal) {
11938 if (ParamAttr.StrideOrArg < 0)
11939 Out <<
'n' << -ParamAttr.StrideOrArg;
11940 else if (ParamAttr.StrideOrArg != 1)
11941 Out << ParamAttr.StrideOrArg;
11944 if (!!ParamAttr.Alignment)
11945 Out <<
'a' << ParamAttr.Alignment;
11948 return std::string(Out.str());
11953 const llvm::APSInt &VLENVal,
11955 OMPDeclareSimdDeclAttr::BranchStateTy State) {
11958 unsigned VecRegSize;
11960 ISADataTy ISAData[] = {
11976 case OMPDeclareSimdDeclAttr::BS_Undefined:
11977 Masked.push_back(
'N');
11978 Masked.push_back(
'M');
11980 case OMPDeclareSimdDeclAttr::BS_Notinbranch:
11981 Masked.push_back(
'N');
11983 case OMPDeclareSimdDeclAttr::BS_Inbranch:
11984 Masked.push_back(
'M');
11987 for (
char Mask : Masked) {
11988 for (
const ISADataTy &
Data : ISAData) {
11990 llvm::raw_svector_ostream Out(Buffer);
11991 Out <<
"_ZGV" <<
Data.ISA << Mask;
11994 assert(NumElts &&
"Non-zero simdlen/cdtsize expected");
11995 Out << llvm::APSInt::getUnsigned(
Data.VecRegSize / NumElts);
12000 Out <<
'_' << Fn->getName();
12001 Fn->addFnAttr(Out.str());
12019 if (Kind == ParamKindTy::Uniform)
12022 if (Kind == ParamKindTy::LinearUVal || Kind == ParamKindTy::LinearRef)
12025 if ((Kind == ParamKindTy::Linear || Kind == ParamKindTy::LinearVal) &&
12035 unsigned Size =
C.getTypeSize(QT);
12038 if (Size != 8 && Size != 16 && Size != 32 && Size != 64 && Size != 128)
12062 return C.getTypeSize(PTy);
12065 return C.getTypeSize(QT);
12067 return C.getTypeSize(
C.getUIntPtrType());
12073static std::tuple<unsigned, unsigned, bool>
12079 bool OutputBecomesInput =
false;
12083 Sizes.push_back(
getAArch64LS(RetType, ParamKindTy::Vector,
C));
12085 OutputBecomesInput =
true;
12087 for (
unsigned I = 0, E = FD->
getNumParams(); I < E; ++I) {
12092 assert(!Sizes.empty() &&
"Unable to determine NDS and WDS.");
12095 assert(llvm::all_of(Sizes,
12096 [](
unsigned Size) {
12097 return Size == 8 || Size == 16 || Size == 32 ||
12098 Size == 64 || Size == 128;
12102 return std::make_tuple(*llvm::min_element(Sizes), *llvm::max_element(Sizes),
12103 OutputBecomesInput);
12109template <
typename T>
12111 char ISA, StringRef ParSeq,
12112 StringRef MangledName,
bool OutputBecomesInput,
12113 llvm::Function *Fn) {
12115 llvm::raw_svector_ostream Out(Buffer);
12116 Out << Prefix << ISA << LMask << VLEN;
12117 if (OutputBecomesInput)
12119 Out << ParSeq <<
"_" << MangledName;
12120 Fn->addFnAttr(Out.str());
12126 StringRef Prefix,
char ISA,
12127 StringRef ParSeq, StringRef MangledName,
12128 bool OutputBecomesInput,
12129 llvm::Function *Fn) {
12133 OutputBecomesInput, Fn);
12135 OutputBecomesInput, Fn);
12139 OutputBecomesInput, Fn);
12141 OutputBecomesInput, Fn);
12145 OutputBecomesInput, Fn);
12147 OutputBecomesInput, Fn);
12152 OutputBecomesInput, Fn);
12155 llvm_unreachable(
"Scalar type is too wide.");
12163 OMPDeclareSimdDeclAttr::BranchStateTy State, StringRef MangledName,
12164 char ISA,
unsigned VecRegSize, llvm::Function *Fn,
SourceLocation SLoc) {
12168 const unsigned NDS = std::get<0>(
Data);
12169 const unsigned WDS = std::get<1>(
Data);
12170 const bool OutputBecomesInput = std::get<2>(
Data);
12174 if (UserVLEN == 1) {
12181 if (ISA ==
'n' && UserVLEN && !llvm::isPowerOf2_32(UserVLEN)) {
12188 if (ISA ==
's' && UserVLEN != 0) {
12189 if ((UserVLEN * WDS > 2048) || (UserVLEN * WDS % 128 != 0)) {
12197 StringRef Prefix =
"_ZGV";
12203 OutputBecomesInput, Fn);
12205 assert(ISA ==
'n' &&
"Expected ISA either 's' or 'n'.");
12209 case OMPDeclareSimdDeclAttr::BS_Undefined:
12211 OutputBecomesInput, Fn);
12213 OutputBecomesInput, Fn);
12215 case OMPDeclareSimdDeclAttr::BS_Notinbranch:
12217 OutputBecomesInput, Fn);
12219 case OMPDeclareSimdDeclAttr::BS_Inbranch:
12221 OutputBecomesInput, Fn);
12231 OutputBecomesInput, Fn);
12233 assert(ISA ==
'n' &&
"Expected ISA either 's' or 'n'.");
12238 case OMPDeclareSimdDeclAttr::BS_Undefined:
12240 OutputBecomesInput, Fn);
12242 OutputBecomesInput, Fn);
12244 case OMPDeclareSimdDeclAttr::BS_Notinbranch:
12246 OutputBecomesInput, Fn);
12248 case OMPDeclareSimdDeclAttr::BS_Inbranch:
12250 OutputBecomesInput, Fn);
12258 llvm::Function *Fn) {
12263 llvm::DenseMap<const Decl *, unsigned> ParamPositions;
12265 ParamPositions.try_emplace(FD, 0);
12266 unsigned ParamPos = ParamPositions.size();
12268 ParamPositions.try_emplace(P->getCanonicalDecl(), ParamPos);
12274 for (
const Expr *E :
Attr->uniforms()) {
12278 Pos = ParamPositions[FD];
12281 ->getCanonicalDecl();
12282 auto It = ParamPositions.find(PVD);
12283 assert(It != ParamPositions.end() &&
"Function parameter not found");
12286 ParamAttrs[Pos].Kind = Uniform;
12289 auto *NI =
Attr->alignments_begin();
12290 for (
const Expr *E :
Attr->aligneds()) {
12295 Pos = ParamPositions[FD];
12299 ->getCanonicalDecl();
12300 auto It = ParamPositions.find(PVD);
12301 assert(It != ParamPositions.end() &&
"Function parameter not found");
12303 ParmTy = PVD->getType();
12305 ParamAttrs[Pos].Alignment =
12307 ? (*NI)->EvaluateKnownConstInt(
C)
12308 : llvm::APSInt::getUnsigned(
12309 C.toCharUnitsFromBits(
C.getOpenMPDefaultSimdAlign(ParmTy))
12314 auto *SI =
Attr->steps_begin();
12315 auto *MI =
Attr->modifiers_begin();
12316 for (
const Expr *E :
Attr->linears()) {
12319 bool IsReferenceType =
false;
12322 unsigned PtrRescalingFactor = 1;
12324 Pos = ParamPositions[FD];
12326 PtrRescalingFactor =
CGM.getContext()
12327 .getTypeSizeInChars(P->getPointeeType())
12331 ->getCanonicalDecl();
12332 auto It = ParamPositions.find(PVD);
12333 assert(It != ParamPositions.end() &&
"Function parameter not found");
12335 if (
auto *P = dyn_cast<PointerType>(PVD->getType()))
12336 PtrRescalingFactor =
CGM.getContext()
12337 .getTypeSizeInChars(P->getPointeeType())
12339 else if (PVD->getType()->isReferenceType()) {
12340 IsReferenceType =
true;
12341 PtrRescalingFactor =
12343 .getTypeSizeInChars(PVD->getType().getNonReferenceType())
12347 ParamAttrTy &ParamAttr = ParamAttrs[Pos];
12348 if (*MI == OMPC_LINEAR_ref)
12349 ParamAttr.Kind = LinearRef;
12350 else if (*MI == OMPC_LINEAR_uval)
12351 ParamAttr.Kind = LinearUVal;
12352 else if (IsReferenceType)
12353 ParamAttr.Kind = LinearVal;
12355 ParamAttr.Kind = Linear;
12357 ParamAttr.StrideOrArg = llvm::APSInt::getUnsigned(1);
12361 if (
const auto *DRE =
12363 if (
const auto *StridePVD =
12364 dyn_cast<ParmVarDecl>(DRE->getDecl())) {
12365 ParamAttr.HasVarStride =
true;
12366 auto It = ParamPositions.find(StridePVD->getCanonicalDecl());
12367 assert(It != ParamPositions.end() &&
12368 "Function parameter not found");
12369 ParamAttr.StrideOrArg = llvm::APSInt::getUnsigned(It->second);
12373 ParamAttr.StrideOrArg =
Result.Val.getInt();
12379 if (!ParamAttr.HasVarStride &&
12380 (ParamAttr.Kind == Linear || ParamAttr.Kind == LinearRef))
12381 ParamAttr.StrideOrArg = ParamAttr.StrideOrArg * PtrRescalingFactor;
12385 llvm::APSInt VLENVal;
12387 const Expr *VLENExpr =
Attr->getSimdlen();
12392 OMPDeclareSimdDeclAttr::BranchStateTy State =
Attr->getBranchState();
12393 if (
CGM.getTriple().isX86()) {
12395 }
else if (
CGM.getTriple().getArch() == llvm::Triple::aarch64) {
12396 unsigned VLEN = VLENVal.getExtValue();
12397 StringRef MangledName = Fn->getName();
12398 if (
CGM.getTarget().hasFeature(
"sve"))
12400 MangledName,
's', 128, Fn, ExprLoc);
12401 else if (
CGM.getTarget().hasFeature(
"neon"))
12403 MangledName,
'n', 128, Fn, ExprLoc);
12412class DoacrossCleanupTy final :
public EHScopeStack::Cleanup {
12414 static const int DoacrossFinArgs = 2;
12417 llvm::FunctionCallee RTLFn;
12418 llvm::Value *Args[DoacrossFinArgs];
12421 DoacrossCleanupTy(llvm::FunctionCallee RTLFn,
12424 assert(CallArgs.size() == DoacrossFinArgs);
12425 std::copy(CallArgs.begin(), CallArgs.end(), std::begin(Args));
12442 QualType Int64Ty =
C.getIntTypeForBitwidth(64,
true);
12450 RD =
C.buildImplicitRecord(
"kmp_dim");
12458 RD =
KmpDimTy->castAsRecordDecl();
12460 llvm::APInt Size(32, NumIterations.size());
12466 enum { LowerFD = 0, UpperFD, StrideFD };
12468 for (
unsigned I = 0, E = NumIterations.size(); I < E; ++I) {
12473 DimsLVal, *std::next(RD->
field_begin(), UpperFD));
12475 CGF.
EmitScalarExpr(NumIterations[I]), NumIterations[I]->getType(),
12476 Int64Ty, NumIterations[I]->getExprLoc());
12480 DimsLVal, *std::next(RD->
field_begin(), StrideFD));
12487 llvm::Value *Args[] = {
12490 llvm::ConstantInt::getSigned(
CGM.Int32Ty, NumIterations.size()),
12495 llvm::FunctionCallee RTLFn =
OMPBuilder.getOrCreateRuntimeFunction(
12496 CGM.getModule(), OMPRTL___kmpc_doacross_init);
12498 llvm::Value *FiniArgs[DoacrossCleanupTy::DoacrossFinArgs] = {
12500 llvm::FunctionCallee FiniRTLFn =
OMPBuilder.getOrCreateRuntimeFunction(
12501 CGM.getModule(), OMPRTL___kmpc_doacross_fini);
12506template <
typename T>
12508 const T *
C, llvm::Value *ULoc,
12509 llvm::Value *ThreadID) {
12512 llvm::APInt Size(32,
C->getNumLoops());
12516 for (
unsigned I = 0, E =
C->getNumLoops(); I < E; ++I) {
12517 const Expr *CounterVal =
C->getLoopData(I);
12518 assert(CounterVal);
12525 llvm::Value *Args[] = {
12528 llvm::FunctionCallee RTLFn;
12530 OMPDoacrossKind<T> ODK;
12531 if (ODK.isSource(
C)) {
12533 OMPRTL___kmpc_doacross_post);
12535 assert(ODK.isSink(
C) &&
"Expect sink modifier.");
12537 OMPRTL___kmpc_doacross_wait);
12557 llvm::FunctionCallee Callee,
12559 assert(Loc.
isValid() &&
"Outlined function call location must be valid.");
12562 if (
auto *Fn = dyn_cast<llvm::Function>(Callee.getCallee())) {
12563 if (Fn->doesNotThrow()) {
12574 emitCall(CGF, Loc, OutlinedFn, Args);
12578 if (
const auto *FD = dyn_cast<FunctionDecl>(D))
12579 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(FD))
12585 const VarDecl *TargetParam)
const {
12592 const Expr *Allocator) {
12593 llvm::Value *AllocVal;
12603 AllocVal = llvm::Constant::getNullValue(
12613 if (!AllocateAlignment)
12616 return llvm::ConstantInt::get(
CGM.
SizeTy, AllocateAlignment->getQuantity());
12629 auto I = UntiedData.find(VD);
12630 if (I != UntiedData.end()) {
12631 UntiedAddr = I->second.first;
12632 UntiedRealAddr = I->second.second;
12636 if (CVD->
hasAttr<OMPAllocateDeclAttr>()) {
12645 Size = CGF.
Builder.CreateNUWAdd(
12647 Size = CGF.
Builder.CreateUDiv(Size,
CGM.getSize(Align));
12648 Size = CGF.
Builder.CreateNUWMul(Size,
CGM.getSize(Align));
12654 const auto *AA = CVD->
getAttr<OMPAllocateDeclAttr>();
12655 const Expr *Allocator = AA->getAllocator();
12659 Args.push_back(ThreadID);
12661 Args.push_back(Alignment);
12662 Args.push_back(Size);
12663 Args.push_back(AllocVal);
12664 llvm::omp::RuntimeFunction FnID =
12665 Alignment ? OMPRTL___kmpc_aligned_alloc : OMPRTL___kmpc_alloc;
12667 OMPBuilder.getOrCreateRuntimeFunction(
CGM.getModule(), FnID), Args,
12669 llvm::FunctionCallee FiniRTLFn =
OMPBuilder.getOrCreateRuntimeFunction(
12670 CGM.getModule(), OMPRTL___kmpc_free);
12678 class OMPAllocateCleanupTy final :
public EHScopeStack::Cleanup {
12679 llvm::FunctionCallee RTLFn;
12682 const Expr *AllocExpr;
12685 OMPAllocateCleanupTy(llvm::FunctionCallee RTLFn,
12687 const Expr *AllocExpr)
12688 : RTLFn(RTLFn), LocEncoding(LocEncoding),
Addr(
Addr),
12689 AllocExpr(AllocExpr) {}
12693 llvm::Value *Args[3];
12699 Args[2] = AllocVal;
12707 CGF.
EHStack.pushCleanup<OMPAllocateCleanupTy>(
12709 VDAddr, Allocator);
12710 if (UntiedRealAddr.
isValid())
12713 Region->emitUntiedSwitch(CGF);
12730 assert(CGM.getLangOpts().OpenMP &&
"Not in OpenMP mode.");
12734 CGM.getOpenMPRuntime().NontemporalDeclsStack.emplace_back();
12736 for (
const Stmt *Ref :
C->private_refs()) {
12737 const auto *SimpleRefExpr =
cast<Expr>(Ref)->IgnoreParenImpCasts();
12739 if (
const auto *DRE = dyn_cast<DeclRefExpr>(SimpleRefExpr)) {
12740 VD = DRE->getDecl();
12743 assert((ME->isImplicitCXXThis() ||
12745 "Expected member of current class.");
12746 VD = ME->getMemberDecl();
12756 CGM.getOpenMPRuntime().NontemporalDeclsStack.pop_back();
12762 std::pair<Address, Address>> &LocalVars)
12763 : CGM(CGF.CGM), NeedToPush(!LocalVars.empty()) {
12767 CGF.
CurFn, CGM.getOpenMPRuntime().UntiedLocalVarsStack.size());
12768 CGM.getOpenMPRuntime().UntiedLocalVarsStack.push_back(LocalVars);
12774 CGM.getOpenMPRuntime().UntiedLocalVarsStack.pop_back();
12778 assert(
CGM.getLangOpts().OpenMP &&
"Not in OpenMP mode.");
12780 return llvm::any_of(
12781 CGM.getOpenMPRuntime().NontemporalDeclsStack,
12785void CGOpenMPRuntime::LastprivateConditionalRAII::tryToDisableInnerAnalysis(
12789 llvm::DenseSet<CanonicalDeclPtr<const Decl>> NeedToCheckForLPCs;
12795 const CapturedStmt *CS = S.getCapturedStmt(CaptureRegions.front());
12802 for (
const auto *
C : S.getClausesOfKind<OMPPrivateClause>()) {
12803 for (
const Expr *Ref :
C->varlist()) {
12804 if (!Ref->getType()->isScalarType())
12806 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
12809 NeedToCheckForLPCs.insert(DRE->getDecl());
12812 for (
const auto *
C : S.getClausesOfKind<OMPFirstprivateClause>()) {
12813 for (
const Expr *Ref :
C->varlist()) {
12814 if (!Ref->getType()->isScalarType())
12816 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
12819 NeedToCheckForLPCs.insert(DRE->getDecl());
12822 for (
const auto *
C : S.getClausesOfKind<OMPLastprivateClause>()) {
12823 for (
const Expr *Ref :
C->varlist()) {
12824 if (!Ref->getType()->isScalarType())
12826 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
12829 NeedToCheckForLPCs.insert(DRE->getDecl());
12832 for (
const auto *
C : S.getClausesOfKind<OMPReductionClause>()) {
12833 for (
const Expr *Ref :
C->varlist()) {
12834 if (!Ref->getType()->isScalarType())
12836 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
12839 NeedToCheckForLPCs.insert(DRE->getDecl());
12842 for (
const auto *
C : S.getClausesOfKind<OMPLinearClause>()) {
12843 for (
const Expr *Ref :
C->varlist()) {
12844 if (!Ref->getType()->isScalarType())
12846 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
12849 NeedToCheckForLPCs.insert(DRE->getDecl());
12852 for (
const Decl *VD : NeedToCheckForLPCs) {
12854 llvm::reverse(
CGM.getOpenMPRuntime().LastprivateConditionalStack)) {
12855 if (
Data.DeclToUniqueName.count(VD) > 0) {
12856 if (!
Data.Disabled)
12857 NeedToAddForLPCsAsDisabled.insert(VD);
12864CGOpenMPRuntime::LastprivateConditionalRAII::LastprivateConditionalRAII(
12867 Action((CGM.getLangOpts().OpenMP >= 50 &&
12868 llvm::any_of(S.getClausesOfKind<OMPLastprivateClause>(),
12869 [](const OMPLastprivateClause *
C) {
12870 return C->getKind() ==
12871 OMPC_LASTPRIVATE_conditional;
12873 ? ActionToDo::PushAsLastprivateConditional
12874 : ActionToDo::DoNotPush) {
12875 assert(
CGM.getLangOpts().OpenMP &&
"Not in OpenMP mode.");
12876 if (
CGM.getLangOpts().OpenMP < 50 || Action == ActionToDo::DoNotPush)
12878 assert(Action == ActionToDo::PushAsLastprivateConditional &&
12879 "Expected a push action.");
12881 CGM.getOpenMPRuntime().LastprivateConditionalStack.emplace_back();
12882 for (
const auto *
C : S.getClausesOfKind<OMPLastprivateClause>()) {
12883 if (
C->getKind() != OMPC_LASTPRIVATE_conditional)
12886 for (
const Expr *Ref :
C->varlist()) {
12887 Data.DeclToUniqueName.insert(std::make_pair(
12892 Data.IVLVal = IVLVal;
12896CGOpenMPRuntime::LastprivateConditionalRAII::LastprivateConditionalRAII(
12898 :
CGM(CGF.
CGM), Action(ActionToDo::DoNotPush) {
12902 llvm::DenseSet<CanonicalDeclPtr<const Decl>> NeedToAddForLPCsAsDisabled;
12903 tryToDisableInnerAnalysis(S, NeedToAddForLPCsAsDisabled);
12904 if (!NeedToAddForLPCsAsDisabled.empty()) {
12905 Action = ActionToDo::DisableLastprivateConditional;
12906 LastprivateConditionalData &
Data =
12908 for (
const Decl *VD : NeedToAddForLPCsAsDisabled)
12909 Data.DeclToUniqueName.try_emplace(VD);
12911 Data.Disabled =
true;
12915CGOpenMPRuntime::LastprivateConditionalRAII
12918 return LastprivateConditionalRAII(CGF, S);
12922 if (CGM.getLangOpts().OpenMP < 50)
12924 if (Action == ActionToDo::DisableLastprivateConditional) {
12925 assert(CGM.getOpenMPRuntime().LastprivateConditionalStack.back().Disabled &&
12926 "Expected list of disabled private vars.");
12927 CGM.getOpenMPRuntime().LastprivateConditionalStack.pop_back();
12929 if (Action == ActionToDo::PushAsLastprivateConditional) {
12931 !CGM.getOpenMPRuntime().LastprivateConditionalStack.back().Disabled &&
12932 "Expected list of lastprivate conditional vars.");
12933 CGM.getOpenMPRuntime().LastprivateConditionalStack.pop_back();
12945 auto VI = I->getSecond().find(VD);
12946 if (VI == I->getSecond().end()) {
12947 RecordDecl *RD =
C.buildImplicitRecord(
"lasprivate.conditional");
12952 NewType =
C.getCanonicalTagType(RD);
12955 I->getSecond().try_emplace(VD, NewType, VDField, FiredField, BaseLVal);
12957 NewType = std::get<0>(VI->getSecond());
12958 VDField = std::get<1>(VI->getSecond());
12959 FiredField = std::get<2>(VI->getSecond());
12960 BaseLVal = std::get<3>(VI->getSecond());
12972class LastprivateConditionalRefChecker final
12975 const Expr *FoundE =
nullptr;
12976 const Decl *FoundD =
nullptr;
12977 StringRef UniqueDeclName;
12979 llvm::Function *FoundFn =
nullptr;
12985 llvm::reverse(LPM)) {
12986 auto It = D.DeclToUniqueName.find(E->
getDecl());
12987 if (It == D.DeclToUniqueName.end())
12993 UniqueDeclName = It->second;
12998 return FoundE == E;
13004 llvm::reverse(LPM)) {
13006 if (It == D.DeclToUniqueName.end())
13012 UniqueDeclName = It->second;
13017 return FoundE == E;
13019 bool VisitStmt(
const Stmt *S) {
13020 for (
const Stmt *Child : S->
children()) {
13023 if (
const auto *E = dyn_cast<Expr>(Child))
13031 explicit LastprivateConditionalRefChecker(
13032 ArrayRef<CGOpenMPRuntime::LastprivateConditionalData> LPM)
13034 std::tuple<const Expr *, const Decl *, StringRef, LValue, llvm::Function *>
13035 getFoundData()
const {
13036 return std::make_tuple(FoundE, FoundD, UniqueDeclName, IVLVal, FoundFn);
13043 StringRef UniqueDeclName,
13049 llvm::Constant *LastIV =
OMPBuilder.getOrCreateInternalVariable(
13050 LLIVTy,
getName({UniqueDeclName,
"iv"}));
13058 llvm::GlobalVariable *
Last =
OMPBuilder.getOrCreateInternalVariable(
13074 auto &&
CodeGen = [&LastIVLVal, &IVLVal, IVVal, &LVal, &LastLVal,
13080 llvm::Value *CmpRes;
13082 CmpRes = CGF.
Builder.CreateICmpSLE(LastIVVal, IVVal);
13085 "Loop iteration variable must be integer.");
13086 CmpRes = CGF.
Builder.CreateICmpULE(LastIVVal, IVVal);
13090 CGF.
Builder.CreateCondBr(CmpRes, ThenBB, ExitBB);
13111 "Aggregates are not supported in lastprivate conditional.");
13120 if (
CGM.getLangOpts().OpenMPSimd) {
13134 if (!Checker.Visit(LHS))
13136 const Expr *FoundE;
13137 const Decl *FoundD;
13138 StringRef UniqueDeclName;
13140 llvm::Function *FoundFn;
13141 std::tie(FoundE, FoundD, UniqueDeclName, IVLVal, FoundFn) =
13142 Checker.getFoundData();
13143 if (FoundFn != CGF.
CurFn) {
13148 "Lastprivate conditional is not found in outer region.");
13149 QualType StructTy = std::get<0>(It->getSecond());
13150 const FieldDecl* FiredDecl = std::get<2>(It->getSecond());
13161 FiredLVal, llvm::AtomicOrdering::Unordered,
13179 auto It = llvm::find_if(
13181 if (It == Range.end() || It->Fn != CGF.
CurFn)
13185 "Lastprivates must be registered already.");
13188 const CapturedStmt *CS = D.getCapturedStmt(CaptureRegions.back());
13189 for (
const auto &Pair : It->DeclToUniqueName) {
13190 const auto *VD =
cast<VarDecl>(Pair.first->getCanonicalDecl());
13193 auto I = LPCI->getSecond().find(Pair.first);
13194 assert(I != LPCI->getSecond().end() &&
13195 "Lastprivate must be rehistered already.");
13197 LValue BaseLVal = std::get<3>(I->getSecond());
13201 llvm::Value *Cmp = CGF.
Builder.CreateIsNotNull(Res);
13205 CGF.
Builder.CreateCondBr(Cmp, ThenBB, DoneBB);
13230 "Unknown lastprivate conditional variable.");
13231 StringRef UniqueName = It->second;
13232 llvm::GlobalVariable *GV =
CGM.getModule().getNamedGlobal(UniqueName);
13246 llvm_unreachable(
"Not supported in SIMD-only mode");
13253 llvm_unreachable(
"Not supported in SIMD-only mode");
13260 bool Tied,
unsigned &NumberOfParts) {
13261 llvm_unreachable(
"Not supported in SIMD-only mode");
13269 llvm_unreachable(
"Not supported in SIMD-only mode");
13275 const Expr *Hint) {
13276 llvm_unreachable(
"Not supported in SIMD-only mode");
13282 llvm_unreachable(
"Not supported in SIMD-only mode");
13288 const Expr *Filter) {
13289 llvm_unreachable(
"Not supported in SIMD-only mode");
13294 llvm_unreachable(
"Not supported in SIMD-only mode");
13300 llvm_unreachable(
"Not supported in SIMD-only mode");
13308 llvm_unreachable(
"Not supported in SIMD-only mode");
13315 llvm_unreachable(
"Not supported in SIMD-only mode");
13322 bool ForceSimpleCall) {
13323 llvm_unreachable(
"Not supported in SIMD-only mode");
13330 llvm_unreachable(
"Not supported in SIMD-only mode");
13335 llvm_unreachable(
"Not supported in SIMD-only mode");
13341 llvm_unreachable(
"Not supported in SIMD-only mode");
13347 llvm_unreachable(
"Not supported in SIMD-only mode");
13354 llvm_unreachable(
"Not supported in SIMD-only mode");
13360 llvm_unreachable(
"Not supported in SIMD-only mode");
13365 unsigned IVSize,
bool IVSigned,
13368 llvm_unreachable(
"Not supported in SIMD-only mode");
13376 llvm_unreachable(
"Not supported in SIMD-only mode");
13380 ProcBindKind ProcBind,
13382 llvm_unreachable(
"Not supported in SIMD-only mode");
13389 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");
13406 llvm::AtomicOrdering AO) {
13407 llvm_unreachable(
"Not supported in SIMD-only mode");
13412 llvm::Function *TaskFunction,
13414 const Expr *IfCond,
13416 llvm_unreachable(
"Not supported in SIMD-only mode");
13423 llvm_unreachable(
"Not supported in SIMD-only mode");
13430 assert(Options.
SimpleReduction &&
"Only simple reduction is expected.");
13432 ReductionOps, Options);
13438 llvm_unreachable(
"Not supported in SIMD-only mode");
13443 bool IsWorksharingReduction) {
13444 llvm_unreachable(
"Not supported in SIMD-only mode");
13451 llvm_unreachable(
"Not supported in SIMD-only mode");
13456 llvm::Value *ReductionsPtr,
13458 llvm_unreachable(
"Not supported in SIMD-only mode");
13464 llvm_unreachable(
"Not supported in SIMD-only mode");
13470 llvm_unreachable(
"Not supported in SIMD-only mode");
13476 llvm_unreachable(
"Not supported in SIMD-only mode");
13481 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
13483 llvm_unreachable(
"Not supported in SIMD-only mode");
13488 llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID,
const Expr *IfCond,
13489 llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier>
Device,
13493 llvm_unreachable(
"Not supported in SIMD-only mode");
13497 llvm_unreachable(
"Not supported in SIMD-only mode");
13501 llvm_unreachable(
"Not supported in SIMD-only mode");
13511 llvm::Function *OutlinedFn,
13513 llvm_unreachable(
"Not supported in SIMD-only mode");
13517 const Expr *NumTeams,
13518 const Expr *ThreadLimit,
13520 llvm_unreachable(
"Not supported in SIMD-only mode");
13527 llvm_unreachable(
"Not supported in SIMD-only mode");
13533 llvm_unreachable(
"Not supported in SIMD-only mode");
13539 llvm_unreachable(
"Not supported in SIMD-only mode");
13544 llvm_unreachable(
"Not supported in SIMD-only mode");
13549 llvm_unreachable(
"Not supported in SIMD-only mode");
13554 const VarDecl *NativeParam)
const {
13555 llvm_unreachable(
"Not supported in SIMD-only mode");
13561 const VarDecl *TargetParam)
const {
13562 llvm_unreachable(
"Not supported in SIMD-only mode");
static llvm::Value * emitCopyprivateCopyFunction(CodeGenModule &CGM, llvm::Type *ArgsElemType, ArrayRef< const Expr * > CopyprivateVars, ArrayRef< const Expr * > DestExprs, ArrayRef< const Expr * > SrcExprs, ArrayRef< const Expr * > AssignmentOps, SourceLocation Loc)
static StringRef getIdentStringFromSourceLocation(CodeGenFunction &CGF, SourceLocation Loc, SmallString< 128 > &Buffer)
static void emitOffloadingArraysAndArgs(CodeGenFunction &CGF, MappableExprsHandler::MapCombinedInfoTy &CombinedInfo, CGOpenMPRuntime::TargetDataInfo &Info, llvm::OpenMPIRBuilder &OMPBuilder, bool IsNonContiguous=false, bool ForEndCall=false)
Emit the arrays used to pass the captures and map information to the offloading runtime library.
static RecordDecl * createKmpTaskTWithPrivatesRecordDecl(CodeGenModule &CGM, QualType KmpTaskTQTy, ArrayRef< PrivateDataTy > Privates)
static void emitInitWithReductionInitializer(CodeGenFunction &CGF, const OMPDeclareReductionDecl *DRD, const Expr *InitOp, Address Private, Address Original, QualType Ty)
static Address castToBase(CodeGenFunction &CGF, QualType BaseTy, QualType ElTy, Address OriginalBaseAddress, llvm::Value *Addr)
static void emitPrivatesInit(CodeGenFunction &CGF, const OMPExecutableDirective &D, Address KmpTaskSharedsPtr, LValue TDBase, const RecordDecl *KmpTaskTWithPrivatesQTyRD, QualType SharedsTy, QualType SharedsPtrTy, const OMPTaskDataTy &Data, ArrayRef< PrivateDataTy > Privates, bool ForDup)
Emit initialization for private variables in task-based directives.
static void emitClauseForBareTargetDirective(CodeGenFunction &CGF, const OMPExecutableDirective &D, llvm::SmallVectorImpl< llvm::Value * > &Values)
static llvm::Value * emitDestructorsFunction(CodeGenModule &CGM, SourceLocation Loc, QualType KmpInt32Ty, QualType KmpTaskTWithPrivatesPtrQTy, QualType KmpTaskTWithPrivatesQTy)
static unsigned evaluateCDTSize(const FunctionDecl *FD, ArrayRef< ParamAttrTy > ParamAttrs)
static void EmitOMPAggregateReduction(CodeGenFunction &CGF, QualType Type, const VarDecl *LHSVar, const VarDecl *RHSVar, const llvm::function_ref< void(CodeGenFunction &CGF, const Expr *, const Expr *, const Expr *)> &RedOpGen, const Expr *XExpr=nullptr, const Expr *EExpr=nullptr, const Expr *UpExpr=nullptr)
Emit reduction operation for each element of array (required for array sections) LHS op = RHS.
static void emitTargetCallFallback(CGOpenMPRuntime *OMPRuntime, llvm::Function *OutlinedFn, const OMPExecutableDirective &D, llvm::SmallVectorImpl< llvm::Value * > &CapturedVars, bool RequiresOuterTask, const CapturedStmt &CS, bool OffloadingMandatory, CodeGenFunction &CGF)
static llvm::Value * emitReduceInitFunction(CodeGenModule &CGM, SourceLocation Loc, ReductionCodeGen &RCG, unsigned N)
Emits reduction initializer function:
static RTCancelKind getCancellationKind(OpenMPDirectiveKind CancelRegion)
static void emitDependData(CodeGenFunction &CGF, QualType &KmpDependInfoTy, llvm::PointerUnion< unsigned *, LValue * > Pos, const OMPTaskDataTy::DependData &Data, Address DependenciesArray)
static llvm::Value * emitTaskPrivateMappingFunction(CodeGenModule &CGM, SourceLocation Loc, const OMPTaskDataTy &Data, QualType PrivatesQTy, ArrayRef< PrivateDataTy > Privates)
Emit a privates mapping function for correct handling of private and firstprivate variables.
static llvm::Value * emitReduceCombFunction(CodeGenModule &CGM, SourceLocation Loc, ReductionCodeGen &RCG, unsigned N, const Expr *ReductionOp, const Expr *LHS, const Expr *RHS, const Expr *PrivateRef)
Emits reduction combiner function:
static RecordDecl * createPrivatesRecordDecl(CodeGenModule &CGM, ArrayRef< PrivateDataTy > Privates)
static llvm::Value * getAllocatorVal(CodeGenFunction &CGF, const Expr *Allocator)
Return allocator value from expression, or return a null allocator (default when no allocator specifi...
static llvm::Function * emitProxyTaskFunction(CodeGenModule &CGM, SourceLocation Loc, OpenMPDirectiveKind Kind, QualType KmpInt32Ty, QualType KmpTaskTWithPrivatesPtrQTy, QualType KmpTaskTWithPrivatesQTy, QualType KmpTaskTQTy, QualType SharedsPtrTy, llvm::Function *TaskFunction, llvm::Value *TaskPrivatesMap)
Emit a proxy function which accepts kmp_task_t as the second argument.
static void addAArch64VectorName(T VLEN, StringRef LMask, StringRef Prefix, char ISA, StringRef ParSeq, StringRef MangledName, bool OutputBecomesInput, llvm::Function *Fn)
static bool isAllocatableDecl(const VarDecl *VD)
static llvm::Value * getAlignmentValue(CodeGenModule &CGM, const VarDecl *VD)
Return the alignment from an allocate directive if present.
static void emitTargetCallKernelLaunch(CGOpenMPRuntime *OMPRuntime, llvm::Function *OutlinedFn, const OMPExecutableDirective &D, llvm::SmallVectorImpl< llvm::Value * > &CapturedVars, bool RequiresOuterTask, const CapturedStmt &CS, bool OffloadingMandatory, llvm::PointerIntPair< const Expr *, 2, OpenMPDeviceClauseModifier > Device, llvm::Value *OutlinedFnID, CodeGenFunction::OMPTargetDataInfo &InputInfo, llvm::Value *&MapTypesArray, llvm::Value *&MapNamesArray, llvm::function_ref< llvm::Value *(CodeGenFunction &CGF, const OMPLoopDirective &D)> SizeEmitter, CodeGenFunction &CGF, CodeGenModule &CGM)
static llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryKind convertCaptureClause(const VarDecl *VD)
static std::tuple< unsigned, unsigned, bool > getNDSWDS(const FunctionDecl *FD, ArrayRef< ParamAttrTy > ParamAttrs)
static const OMPExecutableDirective * getNestedDistributeDirective(ASTContext &Ctx, const OMPExecutableDirective &D)
Check for inner distribute directive.
static std::pair< llvm::Value *, llvm::Value * > getPointerAndSize(CodeGenFunction &CGF, const Expr *E)
static const VarDecl * getBaseDecl(const Expr *Ref, const DeclRefExpr *&DE)
static bool isTrivial(ASTContext &Ctx, const Expr *E)
Checks if the expression is constant or does not have non-trivial function calls.
static OpenMPSchedType getRuntimeSchedule(OpenMPScheduleClauseKind ScheduleKind, bool Chunked, bool Ordered)
Map the OpenMP loop schedule to the runtime enumeration.
static void getNumThreads(CodeGenFunction &CGF, const CapturedStmt *CS, const Expr **E, int32_t &UpperBound, bool UpperBoundOnly, llvm::Value **CondVal)
Check for a num threads constant value (stored in DefaultVal), or expression (stored in E).
static llvm::Value * emitDeviceID(llvm::PointerIntPair< const Expr *, 2, OpenMPDeviceClauseModifier > Device, CodeGenFunction &CGF)
static const OMPDeclareReductionDecl * getReductionInit(const Expr *ReductionOp)
Check if the combiner is a call to UDR combiner and if it is so return the UDR decl used for reductio...
static bool checkInitIsRequired(CodeGenFunction &CGF, ArrayRef< PrivateDataTy > Privates)
Check if duplication function is required for taskloops.
static bool checkDestructorsRequired(const RecordDecl *KmpTaskTWithPrivatesQTyRD, ArrayRef< PrivateDataTy > Privates)
Checks if destructor function is required to be generated.
static llvm::TargetRegionEntryInfo getEntryInfoFromPresumedLoc(CodeGenModule &CGM, llvm::OpenMPIRBuilder &OMPBuilder, SourceLocation BeginLoc, llvm::StringRef ParentName="")
static void genMapInfo(MappableExprsHandler &MEHandler, CodeGenFunction &CGF, MappableExprsHandler::MapCombinedInfoTy &CombinedInfo, llvm::OpenMPIRBuilder &OMPBuilder, const llvm::DenseSet< CanonicalDeclPtr< const Decl > > &SkippedVarSet=llvm::DenseSet< CanonicalDeclPtr< const Decl > >())
static void emitForStaticInitCall(CodeGenFunction &CGF, llvm::Value *UpdateLocation, llvm::Value *ThreadId, llvm::FunctionCallee ForStaticInitFunction, OpenMPSchedType Schedule, OpenMPScheduleClauseModifier M1, OpenMPScheduleClauseModifier M2, const CGOpenMPRuntime::StaticRTInput &Values)
static LValue loadToBegin(CodeGenFunction &CGF, QualType BaseTy, QualType ElTy, LValue BaseLV)
static void getKmpAffinityType(ASTContext &C, QualType &KmpTaskAffinityInfoTy)
Builds kmp_depend_info, if it is not built yet, and builds flags type.
static llvm::Constant * emitMappingInformation(CodeGenFunction &CGF, llvm::OpenMPIRBuilder &OMPBuilder, MappableExprsHandler::MappingExprInfo &MapExprs)
Emit a string constant containing the names of the values mapped to the offloading runtime library.
static void getDependTypes(ASTContext &C, QualType &KmpDependInfoTy, QualType &FlagsTy)
Builds kmp_depend_info, if it is not built yet, and builds flags type.
static llvm::Value * emitTaskDupFunction(CodeGenModule &CGM, SourceLocation Loc, const OMPExecutableDirective &D, QualType KmpTaskTWithPrivatesPtrQTy, const RecordDecl *KmpTaskTWithPrivatesQTyRD, const RecordDecl *KmpTaskTQTyRD, QualType SharedsTy, QualType SharedsPtrTy, const OMPTaskDataTy &Data, ArrayRef< PrivateDataTy > Privates, bool WithLastIter)
Emit task_dup function (for initialization of private/firstprivate/lastprivate vars and last_iter fla...
static std::pair< llvm::Value *, OMPDynGroupprivateFallbackType > emitDynCGroupMem(const OMPExecutableDirective &D, CodeGenFunction &CGF)
static llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseKind convertDeviceClause(const VarDecl *VD)
static llvm::Value * emitReduceFiniFunction(CodeGenModule &CGM, SourceLocation Loc, ReductionCodeGen &RCG, unsigned N)
Emits reduction finalizer function:
static void EmitOMPAggregateInit(CodeGenFunction &CGF, Address DestAddr, QualType Type, bool EmitDeclareReductionInit, const Expr *Init, const OMPDeclareReductionDecl *DRD, Address SrcAddr=Address::invalid())
Emit initialization of arrays of complex types.
static bool getAArch64PBV(QualType QT, ASTContext &C)
Pass By Value (PBV), as defined in 3.1.2 of the AAVFABI.
static unsigned getAArch64LS(QualType QT, ParamKindTy Kind, ASTContext &C)
Computes the lane size (LS) of a return type or of an input parameter, as defined by LS(P) in 3....
static void EmitDoacrossOrdered(CodeGenFunction &CGF, CodeGenModule &CGM, const T *C, llvm::Value *ULoc, llvm::Value *ThreadID)
static RTLDependenceKindTy translateDependencyKind(OpenMPDependClauseKind K)
Translates internal dependency kind into the runtime kind.
static void emitTargetCallElse(CGOpenMPRuntime *OMPRuntime, llvm::Function *OutlinedFn, const OMPExecutableDirective &D, llvm::SmallVectorImpl< llvm::Value * > &CapturedVars, bool RequiresOuterTask, const CapturedStmt &CS, bool OffloadingMandatory, CodeGenFunction &CGF)
static llvm::Function * emitCombinerOrInitializer(CodeGenModule &CGM, QualType Ty, const Expr *CombinerInitializer, const VarDecl *In, const VarDecl *Out, bool IsCombiner)
static void emitX86DeclareSimdFunction(const FunctionDecl *FD, llvm::Function *Fn, const llvm::APSInt &VLENVal, ArrayRef< ParamAttrTy > ParamAttrs, OMPDeclareSimdDeclAttr::BranchStateTy State)
static void emitReductionCombiner(CodeGenFunction &CGF, const Expr *ReductionOp)
Emit reduction combiner.
static std::string mangleVectorParameters(ArrayRef< ParamAttrTy > ParamAttrs)
Mangle the parameter part of the vector function name according to their OpenMP classification.
static std::string generateUniqueName(CodeGenModule &CGM, llvm::StringRef Prefix, const Expr *Ref)
static llvm::Function * emitParallelOrTeamsOutlinedFunction(CodeGenModule &CGM, const OMPExecutableDirective &D, const CapturedStmt *CS, const VarDecl *ThreadIDVar, OpenMPDirectiveKind InnermostKind, const StringRef OutlinedHelperName, const RegionCodeGenTy &CodeGen)
static void emitAArch64DeclareSimdFunction(CodeGenModule &CGM, const FunctionDecl *FD, unsigned UserVLEN, ArrayRef< ParamAttrTy > ParamAttrs, OMPDeclareSimdDeclAttr::BranchStateTy State, StringRef MangledName, char ISA, unsigned VecRegSize, llvm::Function *Fn, SourceLocation SLoc)
Emit vector function attributes for AArch64, as defined in the AAVFABI.
static Address emitAddrOfVarFromArray(CodeGenFunction &CGF, Address Array, unsigned Index, const VarDecl *Var)
Given an array of pointers to variables, project the address of a given variable.
static bool isAssumedToBeNotEmitted(const ValueDecl *VD, bool IsDevice)
static void addAArch64AdvSIMDNDSNames(unsigned NDS, StringRef Mask, StringRef Prefix, char ISA, StringRef ParSeq, StringRef MangledName, bool OutputBecomesInput, llvm::Function *Fn)
static FieldDecl * addFieldToRecordDecl(ASTContext &C, DeclContext *DC, QualType FieldTy)
static ValueDecl * getDeclFromThisExpr(const Expr *E)
static void genMapInfoForCaptures(MappableExprsHandler &MEHandler, CodeGenFunction &CGF, const CapturedStmt &CS, llvm::SmallVectorImpl< llvm::Value * > &CapturedVars, llvm::OpenMPIRBuilder &OMPBuilder, llvm::DenseSet< CanonicalDeclPtr< const Decl > > &MappedVarSet, MappableExprsHandler::MapCombinedInfoTy &CombinedInfo)
static RecordDecl * createKmpTaskTRecordDecl(CodeGenModule &CGM, OpenMPDirectiveKind Kind, QualType KmpInt32Ty, QualType KmpRoutineEntryPointerQTy)
static int addMonoNonMonoModifier(CodeGenModule &CGM, OpenMPSchedType Schedule, OpenMPScheduleClauseModifier M1, OpenMPScheduleClauseModifier M2)
static bool getAArch64MTV(QualType QT, ParamKindTy Kind)
Maps To Vector (MTV), as defined in 4.1.1 of the AAVFABI (2021Q1).
@ LLVM_MARK_AS_BITMASK_ENUM
This file defines OpenMP AST classes for clauses.
Defines some OpenMP-specific enums and functions.
Defines the SourceManager interface.
This file defines OpenMP AST classes for executable directives and clauses.
__DEVICE__ int max(int __a, int __b)
This represents clause 'affinity' in the 'pragma omp task'-based directives.
ValueDecl * getAssociatedDeclaration() const
Expr * getAssociatedExpression() const
static std::pair< const Expr *, std::optional< size_t > > findAttachPtrExpr(MappableExprComponentListRef Components, OpenMPDirectiveKind CurDirKind)
Find the attach pointer expression from a list of mappable expression components.
static QualType getComponentExprElementType(const Expr *Exp)
Get the type of an element of a ComponentList Expr Exp.
ArrayRef< MappableComponent > MappableExprComponentListRef
This represents implicit clause 'depend' for the 'pragma omp task' directive.
This represents 'detach' clause in the 'pragma omp task' directive.
This represents 'device' clause in the 'pragma omp ...' directive.
This represents the 'doacross' clause for the 'pragma omp ordered' directive.
This represents 'dyn_groupprivate' clause in 'pragma omp target ...' and 'pragma omp teams ....
This represents clause 'map' in the 'pragma omp ...' directives.
This represents clause 'nontemporal' in the 'pragma omp ...' directives.
This represents 'num_teams' clause in the 'pragma omp ...' directive.
This represents 'thread_limit' clause in the 'pragma omp ...' directive.
This represents clause 'uses_allocators' in the 'pragma omp target'-based directives.
This represents 'ompx_attribute' clause in a directive that might generate an outlined function.
This represents 'ompx_bare' clause in the 'pragma omp target teams ...' directive.
This represents 'ompx_dyn_cgroup_mem' clause in the 'pragma omp target ...' directive.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
SourceManager & getSourceManager()
const ConstantArrayType * getAsConstantArrayType(QualType T) const
CharUnits getTypeAlignInChars(QualType T) const
Return the ABI-specified alignment of a (complete) type T, in characters.
const ASTRecordLayout & getASTRecordLayout(const RecordDecl *D) const
Get or compute information about the layout of the specified record (struct/union/class) D,...
QualType getPointerType(QualType T) const
Return the uniqued reference to the type for a pointer to the specified type.
QualType getConstantArrayType(QualType EltTy, const llvm::APInt &ArySize, const Expr *SizeExpr, ArraySizeModifier ASM, unsigned IndexTypeQuals) const
Return the unique reference to the type for a constant array of the specified element type.
const LangOptions & getLangOpts() const
QualType getIntTypeForBitwidth(unsigned DestWidth, unsigned Signed) const
getIntTypeForBitwidth - sets integer QualTy according to specified details: bitwidth,...
CharUnits getDeclAlign(const Decl *D, bool ForAlignof=false) const
Return a conservative estimate of the alignment of the specified decl D.
int64_t toBits(CharUnits CharSize) const
Convert a size in characters to a size in bits.
const ArrayType * getAsArrayType(QualType T) const
Type Query functions.
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
static bool hasSameType(QualType T1, QualType T2)
Determine whether the given types T1 and T2 are equivalent.
const VariableArrayType * getAsVariableArrayType(QualType T) const
QualType getSizeType() const
Return the unique type for "size_t" (C99 7.17), defined in <stddef.h>.
unsigned getTypeAlign(QualType T) const
Return the ABI-specified alignment of a (complete) type T, in bits.
CharUnits getSize() const
getSize - Get the record size in characters.
uint64_t getFieldOffset(unsigned FieldNo) const
getFieldOffset - Get the offset of the given field index, in bits.
CharUnits getNonVirtualSize() const
getNonVirtualSize - Get the non-virtual size (in chars) of an object, which is the size of the object...
static QualType getBaseOriginalType(const Expr *Base)
Return original type of the base expression for array section.
Represents an array type, per C99 6.7.5.2 - Array Declarators.
Attr - This represents one attribute.
Represents a base class of a C++ class.
Represents a C++ constructor within a class.
Represents a C++ destructor within a class.
const CXXRecordDecl * getParent() const
Return the parent of this method declaration, which is the class in which this method is defined.
QualType getFunctionObjectParameterType() const
Represents a C++ struct/union/class.
bool isLambda() const
Determine whether this class describes a lambda function object.
void getCaptureFields(llvm::DenseMap< const ValueDecl *, FieldDecl * > &Captures, FieldDecl *&ThisCapture) const
For a closure type, retrieve the mapping from captured variables and this to the non-static data memb...
unsigned getNumBases() const
Retrieves the number of base classes of this class.
base_class_range vbases()
capture_const_range captures() const
CXXDestructorDecl * getDestructor() const
Returns the destructor decl for this class.
CanProxy< U > castAs() const
A wrapper class around a pointer that always points to its canonical declaration.
Describes the capture of either a variable, or 'this', or variable-length array type.
bool capturesVariableByCopy() const
Determine whether this capture handles a variable by copy.
VarDecl * getCapturedVar() const
Retrieve the declaration of the variable being captured.
bool capturesVariableArrayType() const
Determine whether this capture handles a variable-length array type.
bool capturesThis() const
Determine whether this capture handles the C++ 'this' pointer.
bool capturesVariable() const
Determine whether this capture handles a variable (by reference).
This captures a statement into a function.
const Capture * const_capture_iterator
capture_iterator capture_end() const
Retrieve an iterator pointing past the end of the sequence of captures.
const RecordDecl * getCapturedRecordDecl() const
Retrieve the record declaration for captured variables.
Stmt * getCapturedStmt()
Retrieve the statement being captured.
bool capturesVariable(const VarDecl *Var) const
True if this variable has been captured.
capture_iterator capture_begin()
Retrieve an iterator pointing to the first capture.
CharUnits - This is an opaque type for sizes expressed in character units.
bool isZero() const
isZero - Test whether the quantity equals zero.
llvm::Align getAsAlign() const
getAsAlign - Returns Quantity as a valid llvm::Align, Beware llvm::Align assumes power of two 8-bit b...
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
CharUnits alignmentOfArrayElement(CharUnits elementSize) const
Given that this is the alignment of the first element of an array, return the minimum alignment of an...
static CharUnits fromQuantity(QuantityType Quantity)
fromQuantity - Construct a CharUnits quantity from a raw integer type.
CharUnits alignTo(const CharUnits &Align) const
alignTo - Returns the next integer (mod 2**64) that is greater than or equal to this quantity and is ...
std::string SampleProfileFile
Name of the profile file to use with -fprofile-sample-use.
Like RawAddress, an abstract representation of an aligned address, but the pointer contained in this ...
llvm::Value * emitRawPointer(CodeGenFunction &CGF) const
Return the pointer contained in this class after authenticating it and adding offset to it if necessa...
CharUnits getAlignment() const
llvm::Type * getElementType() const
Return the type of the values stored in this address.
Address withPointer(llvm::Value *NewPointer, KnownNonNull_t IsKnownNonNull) const
Return address with different pointer, but same element type and alignment.
Address withElementType(llvm::Type *ElemTy) const
Return address with different element type, but same pointer and alignment.
llvm::PointerType * getType() const
Return the type of the pointer value.
static ApplyDebugLocation CreateArtificial(CodeGenFunction &CGF)
Apply TemporaryLocation if it is valid.
static ApplyDebugLocation CreateDefaultArtificial(CodeGenFunction &CGF, SourceLocation TemporaryLocation)
Apply TemporaryLocation if it is valid.
static ApplyDebugLocation CreateEmpty(CodeGenFunction &CGF)
Set the IRBuilder to not attach debug locations.
llvm::StoreInst * CreateStore(llvm::Value *Val, Address Addr, bool IsVolatile=false)
Address CreateGEP(CodeGenFunction &CGF, Address Addr, llvm::Value *Index, const llvm::Twine &Name="")
Address CreatePointerBitCastOrAddrSpaceCast(Address Addr, llvm::Type *Ty, llvm::Type *ElementTy, const llvm::Twine &Name="")
Address CreateConstArrayGEP(Address Addr, uint64_t Index, const llvm::Twine &Name="")
Given addr = [n x T]* ... produce name = getelementptr inbounds addr, i64 0, i64 index where i64 is a...
llvm::LoadInst * CreateLoad(Address Addr, const llvm::Twine &Name="")
llvm::CallInst * CreateMemCpy(Address Dest, Address Src, llvm::Value *Size, bool IsVolatile=false)
Address CreateConstGEP(Address Addr, uint64_t Index, const llvm::Twine &Name="")
Given addr = T* ... produce name = getelementptr inbounds addr, i64 index where i64 is actually the t...
Address CreateAddrSpaceCast(Address Addr, llvm::Type *Ty, llvm::Type *ElementTy, const llvm::Twine &Name="")
CGFunctionInfo - Class to encapsulate the information about a function definition.
DisableAutoDeclareTargetRAII(CodeGenModule &CGM)
~DisableAutoDeclareTargetRAII()
~LastprivateConditionalRAII()
static LastprivateConditionalRAII disable(CodeGenFunction &CGF, const OMPExecutableDirective &S)
NontemporalDeclsRAII(CodeGenModule &CGM, const OMPLoopDirective &S)
Struct that keeps all the relevant information that should be kept throughout a 'target data' region.
llvm::DenseMap< const ValueDecl *, llvm::Value * > CaptureDeviceAddrMap
Map between the a declaration of a capture and the corresponding new llvm address where the runtime r...
~UntiedTaskLocalDeclsRAII()
UntiedTaskLocalDeclsRAII(CodeGenFunction &CGF, const llvm::MapVector< CanonicalDeclPtr< const VarDecl >, std::pair< Address, Address > > &LocalVars)
virtual Address emitThreadIDAddress(CodeGenFunction &CGF, SourceLocation Loc)
Emits address of the word in a memory where current thread id is stored.
llvm::StringSet ThreadPrivateWithDefinition
Set of threadprivate variables with the generated initializer.
CGOpenMPRuntime(CodeGenModule &CGM)
virtual void emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc, const OMPExecutableDirective &D, llvm::Function *TaskFunction, QualType SharedsTy, Address Shareds, const Expr *IfCond, const OMPTaskDataTy &Data)
Emit task region for the task directive.
void createOffloadEntriesAndInfoMetadata()
Creates all the offload entries in the current compilation unit along with the associated metadata.
const Expr * getNumTeamsExprForTargetDirective(CodeGenFunction &CGF, const OMPExecutableDirective &D, int32_t &MinTeamsVal, int32_t &MaxTeamsVal)
Emit the number of teams for a target directive.
virtual Address getAddrOfThreadPrivate(CodeGenFunction &CGF, const VarDecl *VD, Address VDAddr, SourceLocation Loc)
Returns address of the threadprivate variable for the current thread.
void emitDeferredTargetDecls() const
Emit deferred declare target variables marked for deferred emission.
virtual llvm::Value * emitForNext(CodeGenFunction &CGF, SourceLocation Loc, unsigned IVSize, bool IVSigned, Address IL, Address LB, Address UB, Address ST)
Call __kmpc_dispatch_next( ident_t *loc, kmp_int32 tid, kmp_int32 *p_lastiter, kmp_int[32|64] *p_lowe...
bool markAsGlobalTarget(GlobalDecl GD)
Marks the declaration as already emitted for the device code and returns true, if it was marked alrea...
virtual void emitParallelCall(CodeGenFunction &CGF, SourceLocation Loc, llvm::Function *OutlinedFn, ArrayRef< llvm::Value * > CapturedVars, const Expr *IfCond, llvm::Value *NumThreads, OpenMPNumThreadsClauseModifier NumThreadsModifier=OMPC_NUMTHREADS_unknown, OpenMPSeverityClauseKind Severity=OMPC_SEVERITY_fatal, const Expr *Message=nullptr)
Emits code for parallel or serial call of the OutlinedFn with variables captured in a record which ad...
llvm::SmallDenseSet< CanonicalDeclPtr< const Decl > > NontemporalDeclsSet
virtual void emitTargetDataStandAloneCall(CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, const Expr *Device)
Emit the data mapping/movement code associated with the directive D that should be of the form 'targe...
virtual void emitNumThreadsClause(CodeGenFunction &CGF, llvm::Value *NumThreads, SourceLocation Loc, OpenMPNumThreadsClauseModifier Modifier=OMPC_NUMTHREADS_unknown, OpenMPSeverityClauseKind Severity=OMPC_SEVERITY_fatal, SourceLocation SeverityLoc=SourceLocation(), const Expr *Message=nullptr, SourceLocation MessageLoc=SourceLocation())
Emits call to void __kmpc_push_num_threads(ident_t *loc, kmp_int32global_tid, kmp_int32 num_threads) ...
QualType SavedKmpTaskloopTQTy
Saved kmp_task_t for taskloop-based directive.
virtual void emitSingleRegion(CodeGenFunction &CGF, const RegionCodeGenTy &SingleOpGen, SourceLocation Loc, ArrayRef< const Expr * > CopyprivateVars, ArrayRef< const Expr * > DestExprs, ArrayRef< const Expr * > SrcExprs, ArrayRef< const Expr * > AssignmentOps)
Emits a single region.
virtual bool emitTargetGlobal(GlobalDecl GD)
Emit the global GD if it is meaningful for the target.
void setLocThreadIdInsertPt(CodeGenFunction &CGF, bool AtCurrentPoint=false)
std::string getOutlinedHelperName(StringRef Name) const
Get the function name of an outlined region.
bool HasEmittedDeclareTargetRegion
Flag for keeping track of weather a device routine has been emitted.
llvm::Constant * getOrCreateThreadPrivateCache(const VarDecl *VD)
If the specified mangled name is not in the module, create and return threadprivate cache object.
virtual Address getTaskReductionItem(CodeGenFunction &CGF, SourceLocation Loc, llvm::Value *ReductionsPtr, LValue SharedLVal)
Get the address of void * type of the privatue copy of the reduction item specified by the SharedLVal...
virtual void emitForDispatchDeinit(CodeGenFunction &CGF, SourceLocation Loc)
This is used for non static scheduled types and when the ordered clause is present on the loop constr...
void emitCall(CodeGenFunction &CGF, SourceLocation Loc, llvm::FunctionCallee Callee, ArrayRef< llvm::Value * > Args={}) const
Emits Callee function call with arguments Args with location Loc.
virtual void getDefaultScheduleAndChunk(CodeGenFunction &CGF, const OMPLoopDirective &S, OpenMPScheduleClauseKind &ScheduleKind, const Expr *&ChunkExpr) const
Choose default schedule type and chunk value for the schedule clause.
virtual std::pair< llvm::Function *, llvm::Function * > getUserDefinedReduction(const OMPDeclareReductionDecl *D)
Get combiner/initializer for the specified user-defined reduction, if any.
virtual bool isGPU() const
Returns true if the current target is a GPU.
static const Stmt * getSingleCompoundChild(ASTContext &Ctx, const Stmt *Body)
Checks if the Body is the CompoundStmt and returns its child statement iff there is only one that is ...
virtual void emitDeclareTargetFunction(const FunctionDecl *FD, llvm::GlobalValue *GV)
Emit code for handling declare target functions in the runtime.
bool HasRequiresUnifiedSharedMemory
Flag for keeping track of weather a requires unified_shared_memory directive is present.
llvm::Value * emitUpdateLocation(CodeGenFunction &CGF, SourceLocation Loc, unsigned Flags=0, bool EmitLoc=false)
Emits object of ident_t type with info for source location.
bool isLocalVarInUntiedTask(CodeGenFunction &CGF, const VarDecl *VD) const
Returns true if the variable is a local variable in untied task.
virtual void emitTeamsCall(CodeGenFunction &CGF, const OMPExecutableDirective &D, SourceLocation Loc, llvm::Function *OutlinedFn, ArrayRef< llvm::Value * > CapturedVars)
Emits code for teams call of the OutlinedFn with variables captured in a record which address is stor...
virtual void emitCancellationPointCall(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind CancelRegion)
Emit code for 'cancellation point' construct.
virtual llvm::Function * emitThreadPrivateVarDefinition(const VarDecl *VD, Address VDAddr, SourceLocation Loc, bool PerformInit, CodeGenFunction *CGF=nullptr)
Emit a code for initialization of threadprivate variable.
FunctionUDMMapTy FunctionUDMMap
virtual ConstantAddress getAddrOfDeclareTargetVar(const VarDecl *VD)
Returns the address of the variable marked as declare target with link clause OR as declare target wi...
llvm::Function * getOrCreateUserDefinedMapperFunc(const OMPDeclareMapperDecl *D)
Get the function for the specified user-defined mapper.
OpenMPLocThreadIDMapTy OpenMPLocThreadIDMap
virtual void functionFinished(CodeGenFunction &CGF)
Cleans up references to the objects in finished function.
virtual llvm::Function * emitTeamsOutlinedFunction(CodeGenFunction &CGF, const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen)
Emits outlined function for the specified OpenMP teams directive D.
QualType KmpTaskTQTy
Type typedef struct kmp_task { void * shareds; /**< pointer to block of pointers to shared vars / k...
llvm::OpenMPIRBuilder OMPBuilder
An OpenMP-IR-Builder instance.
virtual void emitDoacrossInit(CodeGenFunction &CGF, const OMPLoopDirective &D, ArrayRef< Expr * > NumIterations)
Emit initialization for doacross loop nesting support.
virtual void adjustTargetSpecificDataForLambdas(CodeGenFunction &CGF, const OMPExecutableDirective &D) const
Adjust some parameters for the target-based directives, like addresses of the variables captured by r...
FunctionUDRMapTy FunctionUDRMap
virtual void emitTargetDataCalls(CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, const Expr *Device, const RegionCodeGenTy &CodeGen, CGOpenMPRuntime::TargetDataInfo &Info)
Emit the target data mapping code associated with D.
virtual unsigned getDefaultLocationReserved2Flags() const
Returns additional flags that can be stored in reserved_2 field of the default location.
virtual Address getParameterAddress(CodeGenFunction &CGF, const VarDecl *NativeParam, const VarDecl *TargetParam) const
Gets the address of the native argument basing on the address of the target-specific parameter.
void emitUsesAllocatorsFini(CodeGenFunction &CGF, const Expr *Allocator)
Destroys user defined allocators specified in the uses_allocators clause.
QualType KmpTaskAffinityInfoTy
Type typedef struct kmp_task_affinity_info { kmp_intptr_t base_addr; size_t len; struct { bool flag1 ...
void emitPrivateReduction(CodeGenFunction &CGF, SourceLocation Loc, const Expr *Privates, const Expr *LHSExprs, const Expr *RHSExprs, const Expr *ReductionOps)
Emits code for private variable reduction.
llvm::Value * emitNumTeamsForTargetDirective(CodeGenFunction &CGF, const OMPExecutableDirective &D)
virtual void emitTargetOutlinedFunctionHelper(const OMPExecutableDirective &D, StringRef ParentName, llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID, bool IsOffloadEntry, const RegionCodeGenTy &CodeGen)
Helper to emit outlined function for 'target' directive.
void scanForTargetRegionsFunctions(const Stmt *S, StringRef ParentName)
Start scanning from statement S and emit all target regions found along the way.
SmallVector< llvm::Value *, 4 > emitDepobjElementsSizes(CodeGenFunction &CGF, QualType &KmpDependInfoTy, const OMPTaskDataTy::DependData &Data)
virtual llvm::Value * emitMessageClause(CodeGenFunction &CGF, const Expr *Message, SourceLocation Loc)
virtual void emitTaskgroupRegion(CodeGenFunction &CGF, const RegionCodeGenTy &TaskgroupOpGen, SourceLocation Loc)
Emit a taskgroup region.
llvm::DenseMap< llvm::Function *, llvm::DenseMap< CanonicalDeclPtr< const Decl >, std::tuple< QualType, const FieldDecl *, const FieldDecl *, LValue > > > LastprivateConditionalToTypes
Maps local variables marked as lastprivate conditional to their internal types.
virtual bool emitTargetGlobalVariable(GlobalDecl GD)
Emit the global variable if it is a valid device global variable.
virtual void emitNumTeamsClause(CodeGenFunction &CGF, const Expr *NumTeams, const Expr *ThreadLimit, SourceLocation Loc)
Emits call to void __kmpc_push_num_teams(ident_t *loc, kmp_int32global_tid, kmp_int32 num_teams,...
bool hasRequiresUnifiedSharedMemory() const
Return whether the unified_shared_memory has been specified.
virtual Address getAddrOfArtificialThreadPrivate(CodeGenFunction &CGF, QualType VarType, StringRef Name)
Creates artificial threadprivate variable with name Name and type VarType.
void emitUserDefinedMapper(const OMPDeclareMapperDecl *D, CodeGenFunction *CGF=nullptr)
Emit the function for the user defined mapper construct.
bool HasEmittedTargetRegion
Flag for keeping track of weather a target region has been emitted.
void emitDepobjElements(CodeGenFunction &CGF, QualType &KmpDependInfoTy, LValue PosLVal, const OMPTaskDataTy::DependData &Data, Address DependenciesArray)
std::string getReductionFuncName(StringRef Name) const
Get the function name of a reduction function.
virtual void processRequiresDirective(const OMPRequiresDecl *D)
Perform check on requires decl to ensure that target architecture supports unified addressing.
llvm::DenseSet< CanonicalDeclPtr< const Decl > > AlreadyEmittedTargetDecls
List of the emitted declarations.
virtual llvm::Value * emitTaskReductionInit(CodeGenFunction &CGF, SourceLocation Loc, ArrayRef< const Expr * > LHSExprs, ArrayRef< const Expr * > RHSExprs, const OMPTaskDataTy &Data)
Emit a code for initialization of task reduction clause.
llvm::Value * getThreadID(CodeGenFunction &CGF, SourceLocation Loc)
Gets thread id value for the current thread.
void emitUpdateClause(CodeGenFunction &CGF, LValue DepobjLVal, OpenMPDependClauseKind NewDepKind, SourceLocation Loc)
Updates the dependency kind in the specified depobj object.
virtual void emitLastprivateConditionalFinalUpdate(CodeGenFunction &CGF, LValue PrivLVal, const VarDecl *VD, SourceLocation Loc)
Gets the address of the global copy used for lastprivate conditional update, if any.
llvm::MapVector< CanonicalDeclPtr< const VarDecl >, std::pair< Address, Address > > UntiedLocalVarsAddressesMap
virtual void emitErrorCall(CodeGenFunction &CGF, SourceLocation Loc, Expr *ME, bool IsFatal)
Emit __kmpc_error call for error directive extern void __kmpc_error(ident_t *loc, int severity,...
void clearLocThreadIdInsertPt(CodeGenFunction &CGF)
virtual void emitTaskyieldCall(CodeGenFunction &CGF, SourceLocation Loc)
Emits code for a taskyield directive.
std::string getName(ArrayRef< StringRef > Parts) const
Get the platform-specific name separator.
QualType KmpRoutineEntryPtrQTy
void computeMinAndMaxThreadsAndTeams(const OMPExecutableDirective &D, CodeGenFunction &CGF, llvm::OpenMPIRBuilder::TargetKernelDefaultAttrs &Attrs)
Helper to determine the min/max number of threads/teams for D.
virtual void emitFlush(CodeGenFunction &CGF, ArrayRef< const Expr * > Vars, SourceLocation Loc, llvm::AtomicOrdering AO)
Emit flush of the variables specified in 'omp flush' directive.
virtual void emitTaskwaitCall(CodeGenFunction &CGF, SourceLocation Loc, const OMPTaskDataTy &Data)
Emit code for 'taskwait' directive.
virtual void emitProcBindClause(CodeGenFunction &CGF, llvm::omp::ProcBindKind ProcBind, SourceLocation Loc)
Emit call to void __kmpc_push_proc_bind(ident_t *loc, kmp_int32global_tid, int proc_bind) to generate...
void emitLastprivateConditionalUpdate(CodeGenFunction &CGF, LValue IVLVal, StringRef UniqueDeclName, LValue LVal, SourceLocation Loc)
Emit update for lastprivate conditional data.
virtual void emitTaskLoopCall(CodeGenFunction &CGF, SourceLocation Loc, const OMPLoopDirective &D, llvm::Function *TaskFunction, QualType SharedsTy, Address Shareds, const Expr *IfCond, const OMPTaskDataTy &Data)
Emit task region for the taskloop directive.
virtual void emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind Kind, bool EmitChecks=true, bool ForceSimpleCall=false)
Emit an implicit/explicit barrier for OpenMP threads.
static unsigned getDefaultFlagsForBarriers(OpenMPDirectiveKind Kind)
Returns default flags for the barriers depending on the directive, for which this barier is going to ...
virtual bool emitTargetFunctions(GlobalDecl GD)
Emit the target regions enclosed in GD function definition or the function itself in case it is a val...
TaskResultTy emitTaskInit(CodeGenFunction &CGF, SourceLocation Loc, const OMPExecutableDirective &D, llvm::Function *TaskFunction, QualType SharedsTy, Address Shareds, const OMPTaskDataTy &Data)
Emit task region for the task directive.
llvm::Value * emitTargetNumIterationsCall(CodeGenFunction &CGF, const OMPExecutableDirective &D, llvm::function_ref< llvm::Value *(CodeGenFunction &CGF, const OMPLoopDirective &D)> SizeEmitter)
Return the trip count of loops associated with constructs / 'target teams distribute' and 'teams dist...
llvm::StringMap< llvm::AssertingVH< llvm::GlobalVariable >, llvm::BumpPtrAllocator > InternalVars
An ordered map of auto-generated variables to their unique names.
virtual void emitDistributeStaticInit(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDistScheduleClauseKind SchedKind, const StaticRTInput &Values)
llvm::SmallVector< UntiedLocalVarsAddressesMap, 4 > UntiedLocalVarsStack
virtual void emitForStaticFinish(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind DKind)
Call the appropriate runtime routine to notify that we finished all the work with current loop.
virtual void emitThreadLimitClause(CodeGenFunction &CGF, const Expr *ThreadLimit, SourceLocation Loc)
Emits call to void __kmpc_set_thread_limit(ident_t *loc, kmp_int32global_tid, kmp_int32 thread_limit)...
void emitIfClause(CodeGenFunction &CGF, const Expr *Cond, const RegionCodeGenTy &ThenGen, const RegionCodeGenTy &ElseGen)
Emits code for OpenMP 'if' clause using specified CodeGen function.
Address emitDepobjDependClause(CodeGenFunction &CGF, const OMPTaskDataTy::DependData &Dependencies, SourceLocation Loc)
Emits list of dependecies based on the provided data (array of dependence/expression pairs) for depob...
bool isNontemporalDecl(const ValueDecl *VD) const
Checks if the VD variable is marked as nontemporal declaration in current context.
virtual llvm::Function * emitParallelOutlinedFunction(CodeGenFunction &CGF, const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen)
Emits outlined function for the specified OpenMP parallel directive D.
const Expr * getNumThreadsExprForTargetDirective(CodeGenFunction &CGF, const OMPExecutableDirective &D, int32_t &UpperBound, bool UpperBoundOnly, llvm::Value **CondExpr=nullptr, const Expr **ThreadLimitExpr=nullptr)
Check for a number of threads upper bound constant value (stored in UpperBound), or expression (retur...
virtual void registerVTableOffloadEntry(llvm::GlobalVariable *VTable, const VarDecl *VD)
Register VTable to OpenMP offload entry.
virtual llvm::Value * emitSeverityClause(OpenMPSeverityClauseKind Severity, SourceLocation Loc)
llvm::SmallVector< LastprivateConditionalData, 4 > LastprivateConditionalStack
Stack for list of addresses of declarations in current context marked as lastprivate conditional.
virtual void emitForStaticInit(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind DKind, const OpenMPScheduleTy &ScheduleKind, const StaticRTInput &Values)
Call the appropriate runtime routine to initialize it before start of loop.
virtual void emitDeclareSimdFunction(const FunctionDecl *FD, llvm::Function *Fn)
Marks function Fn with properly mangled versions of vector functions.
llvm::AtomicOrdering getDefaultMemoryOrdering() const
Gets default memory ordering as specified in requires directive.
virtual bool isStaticNonchunked(OpenMPScheduleClauseKind ScheduleKind, bool Chunked) const
Check if the specified ScheduleKind is static non-chunked.
virtual void emitAndRegisterVTable(CodeGenModule &CGM, CXXRecordDecl *CXXRecord, const VarDecl *VD)
Emit and register VTable for the C++ class in OpenMP offload entry.
llvm::Value * getCriticalRegionLock(StringRef CriticalName)
Returns corresponding lock object for the specified critical region name.
virtual void emitCancelCall(CodeGenFunction &CGF, SourceLocation Loc, const Expr *IfCond, OpenMPDirectiveKind CancelRegion)
Emit code for 'cancel' construct.
QualType SavedKmpTaskTQTy
Saved kmp_task_t for task directive.
virtual void emitMasterRegion(CodeGenFunction &CGF, const RegionCodeGenTy &MasterOpGen, SourceLocation Loc)
Emits a master region.
virtual llvm::Function * emitTaskOutlinedFunction(const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, const VarDecl *PartIDVar, const VarDecl *TaskTVar, OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen, bool Tied, unsigned &NumberOfParts)
Emits outlined function for the OpenMP task directive D.
llvm::DenseMap< llvm::Function *, unsigned > FunctionToUntiedTaskStackMap
Maps function to the position of the untied task locals stack.
void emitDestroyClause(CodeGenFunction &CGF, LValue DepobjLVal, SourceLocation Loc)
Emits the code to destroy the dependency object provided in depobj directive.
virtual void emitTaskReductionFixups(CodeGenFunction &CGF, SourceLocation Loc, ReductionCodeGen &RCG, unsigned N)
Required to resolve existing problems in the runtime.
llvm::ArrayType * KmpCriticalNameTy
Type kmp_critical_name, originally defined as typedef kmp_int32 kmp_critical_name[8];.
virtual void emitDoacrossOrdered(CodeGenFunction &CGF, const OMPDependClause *C)
Emit code for doacross ordered directive with 'depend' clause.
llvm::DenseMap< const OMPDeclareMapperDecl *, llvm::Function * > UDMMap
Map from the user-defined mapper declaration to its corresponding functions.
virtual void checkAndEmitLastprivateConditional(CodeGenFunction &CGF, const Expr *LHS)
Checks if the provided LVal is lastprivate conditional and emits the code to update the value of the ...
std::pair< llvm::Value *, LValue > getDepobjElements(CodeGenFunction &CGF, LValue DepobjLVal, SourceLocation Loc)
Returns the number of the elements and the address of the depobj dependency array.
llvm::SmallDenseSet< const VarDecl * > DeferredGlobalVariables
List of variables that can become declare target implicitly and, thus, must be emitted.
void emitUsesAllocatorsInit(CodeGenFunction &CGF, const Expr *Allocator, const Expr *AllocatorTraits)
Initializes user defined allocators specified in the uses_allocators clauses.
virtual void registerVTable(const OMPExecutableDirective &D)
Emit code for registering vtable by scanning through map clause in OpenMP target region.
llvm::Type * KmpRoutineEntryPtrTy
Type typedef kmp_int32 (* kmp_routine_entry_t)(kmp_int32, void *);.
llvm::Type * getIdentTyPointerTy()
Returns pointer to ident_t type.
void emitSingleReductionCombiner(CodeGenFunction &CGF, const Expr *ReductionOp, const Expr *PrivateRef, const DeclRefExpr *LHS, const DeclRefExpr *RHS)
Emits single reduction combiner.
llvm::OpenMPIRBuilder & getOMPBuilder()
virtual void emitTargetOutlinedFunction(const OMPExecutableDirective &D, StringRef ParentName, llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID, bool IsOffloadEntry, const RegionCodeGenTy &CodeGen)
Emit outilined function for 'target' directive.
virtual void emitCriticalRegion(CodeGenFunction &CGF, StringRef CriticalName, const RegionCodeGenTy &CriticalOpGen, SourceLocation Loc, const Expr *Hint=nullptr)
Emits a critical region.
virtual void emitForOrderedIterationEnd(CodeGenFunction &CGF, SourceLocation Loc, unsigned IVSize, bool IVSigned)
Call the appropriate runtime routine to notify that we finished iteration of the ordered loop with th...
virtual void emitOutlinedFunctionCall(CodeGenFunction &CGF, SourceLocation Loc, llvm::FunctionCallee OutlinedFn, ArrayRef< llvm::Value * > Args={}) const
Emits call of the outlined function with the provided arguments, translating these arguments to corre...
llvm::Value * emitNumThreadsForTargetDirective(CodeGenFunction &CGF, const OMPExecutableDirective &D)
Emit an expression that denotes the number of threads a target region shall use.
void emitThreadPrivateVarInit(CodeGenFunction &CGF, Address VDAddr, llvm::Value *Ctor, llvm::Value *CopyCtor, llvm::Value *Dtor, SourceLocation Loc)
Emits initialization code for the threadprivate variables.
virtual void emitUserDefinedReduction(CodeGenFunction *CGF, const OMPDeclareReductionDecl *D)
Emit code for the specified user defined reduction construct.
virtual void checkAndEmitSharedLastprivateConditional(CodeGenFunction &CGF, const OMPExecutableDirective &D, const llvm::DenseSet< CanonicalDeclPtr< const VarDecl > > &IgnoredDecls)
Checks if the lastprivate conditional was updated in inner region and writes the value.
QualType KmpDimTy
struct kmp_dim { // loop bounds info casted to kmp_int64 kmp_int64 lo; // lower kmp_int64 up; // uppe...
virtual void emitInlinedDirective(CodeGenFunction &CGF, OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen, bool HasCancel=false)
Emit code for the directive that does not require outlining.
virtual void registerTargetGlobalVariable(const VarDecl *VD, llvm::Constant *Addr)
Checks if the provided global decl GD is a declare target variable and registers it when emitting cod...
virtual void emitFunctionProlog(CodeGenFunction &CGF, const Decl *D)
Emits OpenMP-specific function prolog.
void emitKmpRoutineEntryT(QualType KmpInt32Ty)
Build type kmp_routine_entry_t (if not built yet).
virtual bool isStaticChunked(OpenMPScheduleClauseKind ScheduleKind, bool Chunked) const
Check if the specified ScheduleKind is static chunked.
virtual void emitTargetCall(CodeGenFunction &CGF, const OMPExecutableDirective &D, llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID, const Expr *IfCond, llvm::PointerIntPair< const Expr *, 2, OpenMPDeviceClauseModifier > Device, llvm::function_ref< llvm::Value *(CodeGenFunction &CGF, const OMPLoopDirective &D)> SizeEmitter)
Emit the target offloading code associated with D.
virtual bool hasAllocateAttributeForGlobalVar(const VarDecl *VD, LangAS &AS)
Checks if the variable has associated OMPAllocateDeclAttr attribute with the predefined allocator and...
llvm::AtomicOrdering RequiresAtomicOrdering
Atomic ordering from the omp requires directive.
virtual void emitReduction(CodeGenFunction &CGF, SourceLocation Loc, ArrayRef< const Expr * > Privates, ArrayRef< const Expr * > LHSExprs, ArrayRef< const Expr * > RHSExprs, ArrayRef< const Expr * > ReductionOps, ReductionOptionsTy Options)
Emit a code for reduction clause.
std::pair< llvm::Value *, Address > emitDependClause(CodeGenFunction &CGF, ArrayRef< OMPTaskDataTy::DependData > Dependencies, SourceLocation Loc)
Emits list of dependecies based on the provided data (array of dependence/expression pairs).
llvm::StringMap< llvm::WeakTrackingVH > EmittedNonTargetVariables
List of the global variables with their addresses that should not be emitted for the target.
virtual bool isDynamic(OpenMPScheduleClauseKind ScheduleKind) const
Check if the specified ScheduleKind is dynamic.
Address emitLastprivateConditionalInit(CodeGenFunction &CGF, const VarDecl *VD)
Create specialized alloca to handle lastprivate conditionals.
virtual void emitOrderedRegion(CodeGenFunction &CGF, const RegionCodeGenTy &OrderedOpGen, SourceLocation Loc, bool IsThreads)
Emit an ordered region.
virtual Address getAddressOfLocalVariable(CodeGenFunction &CGF, const VarDecl *VD)
Gets the OpenMP-specific address of the local variable.
virtual void emitTaskReductionFini(CodeGenFunction &CGF, SourceLocation Loc, bool IsWorksharingReduction)
Emits the following code for reduction clause with task modifier:
virtual void emitMaskedRegion(CodeGenFunction &CGF, const RegionCodeGenTy &MaskedOpGen, SourceLocation Loc, const Expr *Filter=nullptr)
Emits a masked region.
QualType KmpDependInfoTy
Type typedef struct kmp_depend_info { kmp_intptr_t base_addr; size_t len; struct { bool in:1; bool ou...
llvm::Function * emitReductionFunction(StringRef ReducerName, SourceLocation Loc, llvm::Type *ArgsElemType, ArrayRef< const Expr * > Privates, ArrayRef< const Expr * > LHSExprs, ArrayRef< const Expr * > RHSExprs, ArrayRef< const Expr * > ReductionOps)
Emits reduction function.
virtual void emitForDispatchInit(CodeGenFunction &CGF, SourceLocation Loc, const OpenMPScheduleTy &ScheduleKind, unsigned IVSize, bool IVSigned, bool Ordered, const DispatchRTInput &DispatchValues)
Call the appropriate runtime routine to initialize it before start of loop.
Address getTaskReductionItem(CodeGenFunction &CGF, SourceLocation Loc, llvm::Value *ReductionsPtr, LValue SharedLVal) override
Get the address of void * type of the privatue copy of the reduction item specified by the SharedLVal...
void emitCriticalRegion(CodeGenFunction &CGF, StringRef CriticalName, const RegionCodeGenTy &CriticalOpGen, SourceLocation Loc, const Expr *Hint=nullptr) override
Emits a critical region.
void emitDistributeStaticInit(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDistScheduleClauseKind SchedKind, const StaticRTInput &Values) override
void emitForStaticInit(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind DKind, const OpenMPScheduleTy &ScheduleKind, const StaticRTInput &Values) override
Call the appropriate runtime routine to initialize it before start of loop.
bool emitTargetGlobalVariable(GlobalDecl GD) override
Emit the global variable if it is a valid device global variable.
llvm::Value * emitForNext(CodeGenFunction &CGF, SourceLocation Loc, unsigned IVSize, bool IVSigned, Address IL, Address LB, Address UB, Address ST) override
Call __kmpc_dispatch_next( ident_t *loc, kmp_int32 tid, kmp_int32 *p_lastiter, kmp_int[32|64] *p_lowe...
llvm::Function * emitThreadPrivateVarDefinition(const VarDecl *VD, Address VDAddr, SourceLocation Loc, bool PerformInit, CodeGenFunction *CGF=nullptr) override
Emit a code for initialization of threadprivate variable.
void emitTargetDataStandAloneCall(CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, const Expr *Device) override
Emit the data mapping/movement code associated with the directive D that should be of the form 'targe...
llvm::Function * emitTeamsOutlinedFunction(CodeGenFunction &CGF, const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) override
Emits outlined function for the specified OpenMP teams directive D.
void emitParallelCall(CodeGenFunction &CGF, SourceLocation Loc, llvm::Function *OutlinedFn, ArrayRef< llvm::Value * > CapturedVars, const Expr *IfCond, llvm::Value *NumThreads, OpenMPNumThreadsClauseModifier NumThreadsModifier=OMPC_NUMTHREADS_unknown, OpenMPSeverityClauseKind Severity=OMPC_SEVERITY_fatal, const Expr *Message=nullptr) override
Emits code for parallel or serial call of the OutlinedFn with variables captured in a record which ad...
void emitReduction(CodeGenFunction &CGF, SourceLocation Loc, ArrayRef< const Expr * > Privates, ArrayRef< const Expr * > LHSExprs, ArrayRef< const Expr * > RHSExprs, ArrayRef< const Expr * > ReductionOps, ReductionOptionsTy Options) override
Emit a code for reduction clause.
void emitFlush(CodeGenFunction &CGF, ArrayRef< const Expr * > Vars, SourceLocation Loc, llvm::AtomicOrdering AO) override
Emit flush of the variables specified in 'omp flush' directive.
void emitDoacrossOrdered(CodeGenFunction &CGF, const OMPDependClause *C) override
Emit code for doacross ordered directive with 'depend' clause.
void emitTaskyieldCall(CodeGenFunction &CGF, SourceLocation Loc) override
Emits a masked region.
Address getAddrOfArtificialThreadPrivate(CodeGenFunction &CGF, QualType VarType, StringRef Name) override
Creates artificial threadprivate variable with name Name and type VarType.
Address getAddrOfThreadPrivate(CodeGenFunction &CGF, const VarDecl *VD, Address VDAddr, SourceLocation Loc) override
Returns address of the threadprivate variable for the current thread.
void emitSingleRegion(CodeGenFunction &CGF, const RegionCodeGenTy &SingleOpGen, SourceLocation Loc, ArrayRef< const Expr * > CopyprivateVars, ArrayRef< const Expr * > DestExprs, ArrayRef< const Expr * > SrcExprs, ArrayRef< const Expr * > AssignmentOps) override
Emits a single region.
void emitTaskReductionFixups(CodeGenFunction &CGF, SourceLocation Loc, ReductionCodeGen &RCG, unsigned N) override
Required to resolve existing problems in the runtime.
llvm::Function * emitParallelOutlinedFunction(CodeGenFunction &CGF, const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) override
Emits outlined function for the specified OpenMP parallel directive D.
void emitCancellationPointCall(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind CancelRegion) override
Emit code for 'cancellation point' construct.
void emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind Kind, bool EmitChecks=true, bool ForceSimpleCall=false) override
Emit an implicit/explicit barrier for OpenMP threads.
Address getParameterAddress(CodeGenFunction &CGF, const VarDecl *NativeParam, const VarDecl *TargetParam) const override
Gets the address of the native argument basing on the address of the target-specific parameter.
void emitTeamsCall(CodeGenFunction &CGF, const OMPExecutableDirective &D, SourceLocation Loc, llvm::Function *OutlinedFn, ArrayRef< llvm::Value * > CapturedVars) override
Emits code for teams call of the OutlinedFn with variables captured in a record which address is stor...
void emitForOrderedIterationEnd(CodeGenFunction &CGF, SourceLocation Loc, unsigned IVSize, bool IVSigned) override
Call the appropriate runtime routine to notify that we finished iteration of the ordered loop with th...
bool emitTargetGlobal(GlobalDecl GD) override
Emit the global GD if it is meaningful for the target.
void emitTaskReductionFini(CodeGenFunction &CGF, SourceLocation Loc, bool IsWorksharingReduction) override
Emits the following code for reduction clause with task modifier:
void emitOrderedRegion(CodeGenFunction &CGF, const RegionCodeGenTy &OrderedOpGen, SourceLocation Loc, bool IsThreads) override
Emit an ordered region.
void emitForStaticFinish(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind DKind) override
Call the appropriate runtime routine to notify that we finished all the work with current loop.
llvm::Value * emitTaskReductionInit(CodeGenFunction &CGF, SourceLocation Loc, ArrayRef< const Expr * > LHSExprs, ArrayRef< const Expr * > RHSExprs, const OMPTaskDataTy &Data) override
Emit a code for initialization of task reduction clause.
void emitProcBindClause(CodeGenFunction &CGF, llvm::omp::ProcBindKind ProcBind, SourceLocation Loc) override
Emit call to void __kmpc_push_proc_bind(ident_t *loc, kmp_int32global_tid, int proc_bind) to generate...
void emitTargetOutlinedFunction(const OMPExecutableDirective &D, StringRef ParentName, llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID, bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) override
Emit outilined function for 'target' directive.
void emitMasterRegion(CodeGenFunction &CGF, const RegionCodeGenTy &MasterOpGen, SourceLocation Loc) override
Emits a master region.
void emitNumTeamsClause(CodeGenFunction &CGF, const Expr *NumTeams, const Expr *ThreadLimit, SourceLocation Loc) override
Emits call to void __kmpc_push_num_teams(ident_t *loc, kmp_int32global_tid, kmp_int32 num_teams,...
void emitForDispatchDeinit(CodeGenFunction &CGF, SourceLocation Loc) override
This is used for non static scheduled types and when the ordered clause is present on the loop constr...
const VarDecl * translateParameter(const FieldDecl *FD, const VarDecl *NativeParam) const override
Translates the native parameter of outlined function if this is required for target.
void emitNumThreadsClause(CodeGenFunction &CGF, llvm::Value *NumThreads, SourceLocation Loc, OpenMPNumThreadsClauseModifier Modifier=OMPC_NUMTHREADS_unknown, OpenMPSeverityClauseKind Severity=OMPC_SEVERITY_fatal, SourceLocation SeverityLoc=SourceLocation(), const Expr *Message=nullptr, SourceLocation MessageLoc=SourceLocation()) override
Emits call to void __kmpc_push_num_threads(ident_t *loc, kmp_int32global_tid, kmp_int32 num_threads) ...
void emitMaskedRegion(CodeGenFunction &CGF, const RegionCodeGenTy &MaskedOpGen, SourceLocation Loc, const Expr *Filter=nullptr) override
Emits a masked region.
void emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc, const OMPExecutableDirective &D, llvm::Function *TaskFunction, QualType SharedsTy, Address Shareds, const Expr *IfCond, const OMPTaskDataTy &Data) override
Emit task region for the task directive.
void emitTargetCall(CodeGenFunction &CGF, const OMPExecutableDirective &D, llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID, const Expr *IfCond, llvm::PointerIntPair< const Expr *, 2, OpenMPDeviceClauseModifier > Device, llvm::function_ref< llvm::Value *(CodeGenFunction &CGF, const OMPLoopDirective &D)> SizeEmitter) override
Emit the target offloading code associated with D.
bool emitTargetFunctions(GlobalDecl GD) override
Emit the target regions enclosed in GD function definition or the function itself in case it is a val...
void emitDoacrossInit(CodeGenFunction &CGF, const OMPLoopDirective &D, ArrayRef< Expr * > NumIterations) override
Emit initialization for doacross loop nesting support.
void emitCancelCall(CodeGenFunction &CGF, SourceLocation Loc, const Expr *IfCond, OpenMPDirectiveKind CancelRegion) override
Emit code for 'cancel' construct.
void emitTaskwaitCall(CodeGenFunction &CGF, SourceLocation Loc, const OMPTaskDataTy &Data) override
Emit code for 'taskwait' directive.
void emitTaskgroupRegion(CodeGenFunction &CGF, const RegionCodeGenTy &TaskgroupOpGen, SourceLocation Loc) override
Emit a taskgroup region.
void emitTargetDataCalls(CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, const Expr *Device, const RegionCodeGenTy &CodeGen, CGOpenMPRuntime::TargetDataInfo &Info) override
Emit the target data mapping code associated with D.
void emitForDispatchInit(CodeGenFunction &CGF, SourceLocation Loc, const OpenMPScheduleTy &ScheduleKind, unsigned IVSize, bool IVSigned, bool Ordered, const DispatchRTInput &DispatchValues) override
This is used for non static scheduled types and when the ordered clause is present on the loop constr...
llvm::Function * emitTaskOutlinedFunction(const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, const VarDecl *PartIDVar, const VarDecl *TaskTVar, OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen, bool Tied, unsigned &NumberOfParts) override
Emits outlined function for the OpenMP task directive D.
void emitTaskLoopCall(CodeGenFunction &CGF, SourceLocation Loc, const OMPLoopDirective &D, llvm::Function *TaskFunction, QualType SharedsTy, Address Shareds, const Expr *IfCond, const OMPTaskDataTy &Data) override
Emit task region for the taskloop directive.
unsigned getNonVirtualBaseLLVMFieldNo(const CXXRecordDecl *RD) const
llvm::StructType * getLLVMType() const
Return the "complete object" LLVM type associated with this record.
llvm::StructType * getBaseSubobjectLLVMType() const
Return the "base subobject" LLVM type associated with this record.
unsigned getLLVMFieldNo(const FieldDecl *FD) const
Return llvm::StructType element number that corresponds to the field FD.
unsigned getVirtualBaseIndex(const CXXRecordDecl *base) const
Return the LLVM field index corresponding to the given virtual base.
API for captured statement code generation.
virtual void EmitBody(CodeGenFunction &CGF, const Stmt *S)
Emit the captured statement body.
virtual const FieldDecl * lookup(const VarDecl *VD) const
Lookup the captured field decl for a variable.
RAII for correct setting/restoring of CapturedStmtInfo.
The scope used to remap some variables as private in the OpenMP loop body (or other captured region e...
bool Privatize()
Privatizes local variables previously registered as private.
bool addPrivate(const VarDecl *LocalVD, Address Addr)
Registers LocalVD variable as a private with Addr as the address of the corresponding private variabl...
An RAII object to set (and then clear) a mapping for an OpaqueValueExpr.
Enters a new scope for capturing cleanups, all of which will be executed once the scope is exited.
CodeGenFunction - This class organizes the per-function state that is used while generating LLVM code...
LValue EmitLoadOfReferenceLValue(LValue RefLVal)
void EmitBranchOnBoolExpr(const Expr *Cond, llvm::BasicBlock *TrueBlock, llvm::BasicBlock *FalseBlock, uint64_t TrueCount, Stmt::Likelihood LH=Stmt::LH_None, const Expr *ConditionalOp=nullptr, const VarDecl *ConditionalDecl=nullptr)
EmitBranchOnBoolExpr - Emit a branch on a boolean condition (e.g.
void emitDestroy(Address addr, QualType type, Destroyer *destroyer, bool useEHCleanupForArray)
emitDestroy - Immediately perform the destruction of the given object.
JumpDest getJumpDestInCurrentScope(llvm::BasicBlock *Target)
The given basic block lies in the current EH scope, but may be a target of a potentially scope-crossi...
static void EmitOMPTargetParallelDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetParallelDirective &S)
void EmitNullInitialization(Address DestPtr, QualType Ty)
EmitNullInitialization - Generate code to set a value of the given type to null, If the type contains...
Address LoadCXXThisAddress()
CGCapturedStmtInfo * CapturedStmtInfo
ComplexPairTy EmitLoadOfComplex(LValue src, SourceLocation loc)
EmitLoadOfComplex - Load a complex number from the specified l-value.
static void EmitOMPTargetDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetDirective &S)
Emit device code for the target directive.
static void EmitOMPTargetTeamsDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsDirective &S)
Emit device code for the target teams directive.
static void EmitOMPTargetTeamsDistributeDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsDistributeDirective &S)
Emit device code for the target teams distribute directive.
llvm::BasicBlock * createBasicBlock(const Twine &name="", llvm::Function *parent=nullptr, llvm::BasicBlock *before=nullptr)
createBasicBlock - Create an LLVM basic block.
const LangOptions & getLangOpts() const
AutoVarEmission EmitAutoVarAlloca(const VarDecl &var)
EmitAutoVarAlloca - Emit the alloca and debug information for a local variable.
void pushDestroy(QualType::DestructionKind dtorKind, Address addr, QualType type)
pushDestroy - Push the standard destructor for the given type as at least a normal cleanup.
Address EmitLoadOfPointer(Address Ptr, const PointerType *PtrTy, LValueBaseInfo *BaseInfo=nullptr, TBAAAccessInfo *TBAAInfo=nullptr)
Load a pointer with type PtrTy stored at address Ptr.
void EmitBranchThroughCleanup(JumpDest Dest)
EmitBranchThroughCleanup - Emit a branch from the current insert block through the normal cleanup han...
const Decl * CurCodeDecl
CurCodeDecl - This is the inner-most code context, which includes blocks.
Destroyer * getDestroyer(QualType::DestructionKind destructionKind)
llvm::AssertingVH< llvm::Instruction > AllocaInsertPt
AllocaInsertPoint - This is an instruction in the entry block before which we prefer to insert alloca...
void EmitAggregateAssign(LValue Dest, LValue Src, QualType EltTy)
Emit an aggregate assignment.
JumpDest ReturnBlock
ReturnBlock - Unified return block.
void EmitAggregateCopy(LValue Dest, LValue Src, QualType EltTy, AggValueSlot::Overlap_t MayOverlap, bool isVolatile=false)
EmitAggregateCopy - Emit an aggregate copy.
LValue EmitLValueForField(LValue Base, const FieldDecl *Field, bool IsInBounds=true)
RawAddress CreateDefaultAlignTempAlloca(llvm::Type *Ty, const Twine &Name="tmp")
CreateDefaultAlignedTempAlloca - This creates an alloca with the default ABI alignment of the given L...
void GenerateOpenMPCapturedVars(const CapturedStmt &S, SmallVectorImpl< llvm::Value * > &CapturedVars)
void EmitIgnoredExpr(const Expr *E)
EmitIgnoredExpr - Emit an expression in a context which ignores the result.
RValue EmitLoadOfLValue(LValue V, SourceLocation Loc)
EmitLoadOfLValue - Given an expression that represents a value lvalue, this method emits the address ...
LValue EmitArraySectionExpr(const ArraySectionExpr *E, bool IsLowerBound=true)
LValue EmitOMPSharedLValue(const Expr *E)
Emits the lvalue for the expression with possibly captured variable.
void StartFunction(GlobalDecl GD, QualType RetTy, llvm::Function *Fn, const CGFunctionInfo &FnInfo, const FunctionArgList &Args, SourceLocation Loc=SourceLocation(), SourceLocation StartLoc=SourceLocation())
Emit code for the start of a function.
void EmitOMPCopy(QualType OriginalType, Address DestAddr, Address SrcAddr, const VarDecl *DestVD, const VarDecl *SrcVD, const Expr *Copy)
Emit proper copying of data from one variable to another.
llvm::Value * EvaluateExprAsBool(const Expr *E)
EvaluateExprAsBool - Perform the usual unary conversions on the specified expression and compare the ...
JumpDest getOMPCancelDestination(OpenMPDirectiveKind Kind)
llvm::Value * emitArrayLength(const ArrayType *arrayType, QualType &baseType, Address &addr)
emitArrayLength - Compute the length of an array, even if it's a VLA, and drill down to the base elem...
void EmitOMPAggregateAssign(Address DestAddr, Address SrcAddr, QualType OriginalType, const llvm::function_ref< void(Address, Address)> CopyGen)
Perform element by element copying of arrays with type OriginalType from SrcAddr to DestAddr using co...
bool HaveInsertPoint() const
HaveInsertPoint - True if an insertion point is defined.
CGDebugInfo * getDebugInfo()
llvm::Value * getTypeSize(QualType Ty)
Returns calculated size of the specified type.
LValue MakeRawAddrLValue(llvm::Value *V, QualType T, CharUnits Alignment, AlignmentSource Source=AlignmentSource::Type)
Same as MakeAddrLValue above except that the pointer is known to be unsigned.
LValue EmitLValueForFieldInitialization(LValue Base, const FieldDecl *Field)
EmitLValueForFieldInitialization - Like EmitLValueForField, except that if the Field is a reference,...
VlaSizePair getVLASize(const VariableArrayType *vla)
Returns an LLVM value that corresponds to the size, in non-variably-sized elements,...
llvm::CallInst * EmitNounwindRuntimeCall(llvm::FunctionCallee callee, const Twine &name="")
ASTContext & getContext() const
llvm::Value * EmitLoadOfScalar(Address Addr, bool Volatile, QualType Ty, SourceLocation Loc, AlignmentSource Source=AlignmentSource::Type, bool isNontemporal=false)
EmitLoadOfScalar - Load a scalar value from an address, taking care to appropriately convert from the...
void EmitStoreOfComplex(ComplexPairTy V, LValue dest, bool isInit)
EmitStoreOfComplex - Store a complex number into the specified l-value.
const Decl * CurFuncDecl
CurFuncDecl - Holds the Decl for the current outermost non-closure context.
void EmitAutoVarCleanups(const AutoVarEmission &emission)
void EmitStoreThroughLValue(RValue Src, LValue Dst, bool isInit=false)
EmitStoreThroughLValue - Store the specified rvalue into the specified lvalue, where both are guarant...
LValue EmitLoadOfPointerLValue(Address Ptr, const PointerType *PtrTy)
void EmitAnyExprToMem(const Expr *E, Address Location, Qualifiers Quals, bool IsInitializer)
EmitAnyExprToMem - Emits the code necessary to evaluate an arbitrary expression into the given memory...
bool needsEHCleanup(QualType::DestructionKind kind)
Determines whether an EH cleanup is required to destroy a type with the given destruction kind.
llvm::DenseMap< const ValueDecl *, FieldDecl * > LambdaCaptureFields
llvm::CallInst * EmitRuntimeCall(llvm::FunctionCallee callee, const Twine &name="")
llvm::Type * ConvertTypeForMem(QualType T)
static void EmitOMPTargetTeamsDistributeParallelForDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsDistributeParallelForDirective &S)
static void EmitOMPTargetParallelForSimdDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetParallelForSimdDirective &S)
Emit device code for the target parallel for simd directive.
CodeGenTypes & getTypes() const
static TypeEvaluationKind getEvaluationKind(QualType T)
getEvaluationKind - Return the TypeEvaluationKind of QualType T.
void EmitOMPTargetTaskBasedDirective(const OMPExecutableDirective &S, const RegionCodeGenTy &BodyGen, OMPTargetDataInfo &InputInfo)
Address EmitPointerWithAlignment(const Expr *Addr, LValueBaseInfo *BaseInfo=nullptr, TBAAAccessInfo *TBAAInfo=nullptr, KnownNonNull_t IsKnownNonNull=NotKnownNonNull)
EmitPointerWithAlignment - Given an expression with a pointer type, emit the value and compute our be...
static void EmitOMPTargetTeamsDistributeParallelForSimdDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsDistributeParallelForSimdDirective &S)
Emit device code for the target teams distribute parallel for simd directive.
void EmitBranch(llvm::BasicBlock *Block)
EmitBranch - Emit a branch to the specified basic block from the current insert block,...
llvm::Function * GenerateOpenMPCapturedStmtFunction(const CapturedStmt &S, const OMPExecutableDirective &D)
RawAddress CreateMemTemp(QualType T, const Twine &Name="tmp", RawAddress *Alloca=nullptr)
CreateMemTemp - Create a temporary memory object of the given type, with appropriate alignmen and cas...
void EmitVarDecl(const VarDecl &D)
EmitVarDecl - Emit a local variable declaration.
llvm::Value * EmitCheckedInBoundsGEP(llvm::Type *ElemTy, llvm::Value *Ptr, ArrayRef< llvm::Value * > IdxList, bool SignedIndices, bool IsSubtraction, SourceLocation Loc, const Twine &Name="")
Same as IRBuilder::CreateInBoundsGEP, but additionally emits a check to detect undefined behavior whe...
static void EmitOMPTargetParallelGenericLoopDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetParallelGenericLoopDirective &S)
Emit device code for the target parallel loop directive.
llvm::Value * EmitScalarExpr(const Expr *E, bool IgnoreResultAssign=false)
EmitScalarExpr - Emit the computation of the specified expression of LLVM scalar type,...
static bool IsWrappedCXXThis(const Expr *E)
Check if E is a C++ "this" pointer wrapped in value-preserving casts.
LValue MakeAddrLValue(Address Addr, QualType T, AlignmentSource Source=AlignmentSource::Type)
void FinishFunction(SourceLocation EndLoc=SourceLocation())
FinishFunction - Complete IR generation of the current function.
void EmitAtomicStore(RValue rvalue, LValue lvalue, bool isInit)
static void EmitOMPTargetSimdDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetSimdDirective &S)
Emit device code for the target simd directive.
static void EmitOMPTargetParallelForDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetParallelForDirective &S)
Emit device code for the target parallel for directive.
Address GetAddrOfLocalVar(const VarDecl *VD)
GetAddrOfLocalVar - Return the address of a local variable.
bool ConstantFoldsToSimpleInteger(const Expr *Cond, bool &Result, bool AllowLabels=false)
ConstantFoldsToSimpleInteger - If the specified expression does not fold to a constant,...
static void EmitOMPTargetTeamsGenericLoopDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsGenericLoopDirective &S)
Emit device code for the target teams loop directive.
LValue EmitMemberExpr(const MemberExpr *E)
std::pair< llvm::Value *, llvm::Value * > ComplexPairTy
Address ReturnValue
ReturnValue - The temporary alloca to hold the return value.
LValue EmitLValue(const Expr *E, KnownNonNull_t IsKnownNonNull=NotKnownNonNull)
EmitLValue - Emit code to compute a designator that specifies the location of the expression.
void incrementProfileCounter(const Stmt *S, llvm::Value *StepV=nullptr)
Increment the profiler's counter for the given statement by StepV.
static void EmitOMPTargetTeamsDistributeSimdDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsDistributeSimdDirective &S)
Emit device code for the target teams distribute simd directive.
llvm::Value * EmitScalarConversion(llvm::Value *Src, QualType SrcTy, QualType DstTy, SourceLocation Loc)
Emit a conversion from the specified type to the specified destination type, both of which are LLVM s...
void EmitVariablyModifiedType(QualType Ty)
EmitVLASize - Capture all the sizes for the VLA expressions in the given variably-modified type and s...
bool isTrivialInitializer(const Expr *Init)
Determine whether the given initializer is trivial in the sense that it requires no code to be genera...
void EmitStoreOfScalar(llvm::Value *Value, Address Addr, bool Volatile, QualType Ty, AlignmentSource Source=AlignmentSource::Type, bool isInit=false, bool isNontemporal=false)
EmitStoreOfScalar - Store a scalar value to an address, taking care to appropriately convert from the...
void EmitBlock(llvm::BasicBlock *BB, bool IsFinished=false)
EmitBlock - Emit the given block.
void EmitExprAsInit(const Expr *init, const ValueDecl *D, LValue lvalue, bool capturedByInit)
EmitExprAsInit - Emits the code necessary to initialize a location in memory with the given initializ...
LValue MakeNaturalAlignRawAddrLValue(llvm::Value *V, QualType T)
This class organizes the cross-function state that is used while generating LLVM code.
void SetInternalFunctionAttributes(GlobalDecl GD, llvm::Function *F, const CGFunctionInfo &FI)
Set the attributes on the LLVM function for the given decl and function info.
llvm::Module & getModule() const
const IntrusiveRefCntPtr< llvm::vfs::FileSystem > & getFileSystem() const
DiagnosticsEngine & getDiags() const
const LangOptions & getLangOpts() const
CharUnits getNaturalTypeAlignment(QualType T, LValueBaseInfo *BaseInfo=nullptr, TBAAAccessInfo *TBAAInfo=nullptr, bool forPointeeType=false)
CodeGenTypes & getTypes()
CGOpenMPRuntime & getOpenMPRuntime()
Return a reference to the configured OpenMP runtime.
TBAAAccessInfo getTBAAInfoForSubobject(LValue Base, QualType AccessType)
getTBAAInfoForSubobject - Get TBAA information for an access with a given base lvalue.
ASTContext & getContext() const
const CodeGenOptions & getCodeGenOpts() const
StringRef getMangledName(GlobalDecl GD)
std::optional< CharUnits > getOMPAllocateAlignment(const VarDecl *VD)
Return the alignment specified in an allocate directive, if present.
llvm::Constant * EmitNullConstant(QualType T)
Return the result of value-initializing the given type, i.e.
llvm::Type * ConvertType(QualType T)
ConvertType - Convert type T into a llvm::Type.
llvm::FunctionType * GetFunctionType(const CGFunctionInfo &Info)
GetFunctionType - Get the LLVM function type for.
const CGFunctionInfo & arrangeBuiltinFunctionDeclaration(QualType resultType, const FunctionArgList &args)
A builtin function is a freestanding function using the default C conventions.
const CGRecordLayout & getCGRecordLayout(const RecordDecl *)
getCGRecordLayout - Return record layout info for the given record decl.
llvm::GlobalVariable * GetAddrOfVTable(const CXXRecordDecl *RD)
GetAddrOfVTable - Get the address of the VTable for the given record decl.
A specialization of Address that requires the address to be an LLVM Constant.
static ConstantAddress invalid()
bool requiresLandingPad() const
void pushTerminate()
Push a terminate handler on the stack.
void popTerminate()
Pops a terminate handler off the stack.
FunctionArgList - Type for representing both the decl and type of parameters to a function.
LValue - This represents an lvalue references.
CharUnits getAlignment() const
llvm::Value * getPointer(CodeGenFunction &CGF) const
const Qualifiers & getQuals() const
Address getAddress() const
LValueBaseInfo getBaseInfo() const
TBAAAccessInfo getTBAAInfo() const
A basic class for pre|post-action for advanced codegen sequence for OpenMP region.
virtual void Enter(CodeGenFunction &CGF)
RValue - This trivial value class is used to represent the result of an expression that is evaluated.
static RValue get(llvm::Value *V)
static RValue getComplex(llvm::Value *V1, llvm::Value *V2)
llvm::Value * getScalarVal() const
getScalarVal() - Return the Value* of this scalar value.
An abstract representation of an aligned address.
llvm::Type * getElementType() const
Return the type of the values stored in this address.
llvm::Value * getPointer() const
static RawAddress invalid()
Class intended to support codegen of all kind of the reduction clauses.
LValue getSharedLValue(unsigned N) const
Returns LValue for the reduction item.
const Expr * getRefExpr(unsigned N) const
Returns the base declaration of the reduction item.
LValue getOrigLValue(unsigned N) const
Returns LValue for the original reduction item.
bool needCleanups(unsigned N)
Returns true if the private copy requires cleanups.
void emitAggregateType(CodeGenFunction &CGF, unsigned N)
Emits the code for the variable-modified type, if required.
const VarDecl * getBaseDecl(unsigned N) const
Returns the base declaration of the reduction item.
QualType getPrivateType(unsigned N) const
Return the type of the private item.
bool usesReductionInitializer(unsigned N) const
Returns true if the initialization of the reduction item uses initializer from declare reduction cons...
void emitSharedOrigLValue(CodeGenFunction &CGF, unsigned N)
Emits lvalue for the shared and original reduction item.
void emitInitialization(CodeGenFunction &CGF, unsigned N, Address PrivateAddr, Address SharedAddr, llvm::function_ref< bool(CodeGenFunction &)> DefaultInit)
Performs initialization of the private copy for the reduction item.
std::pair< llvm::Value *, llvm::Value * > getSizes(unsigned N) const
Returns the size of the reduction item (in chars and total number of elements in the item),...
ReductionCodeGen(ArrayRef< const Expr * > Shareds, ArrayRef< const Expr * > Origs, ArrayRef< const Expr * > Privates, ArrayRef< const Expr * > ReductionOps)
void emitCleanups(CodeGenFunction &CGF, unsigned N, Address PrivateAddr)
Emits cleanup code for the reduction item.
Address adjustPrivateAddress(CodeGenFunction &CGF, unsigned N, Address PrivateAddr)
Adjusts PrivatedAddr for using instead of the original variable address in normal operations.
Class provides a way to call simple version of codegen for OpenMP region, or an advanced with possibl...
void operator()(CodeGenFunction &CGF) const
void setAction(PrePostActionTy &Action) const
ConstStmtVisitor - This class implements a simple visitor for Stmt subclasses.
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
void addDecl(Decl *D)
Add the declaration D into this context.
A reference to a declared variable, function, enum, etc.
Decl - This represents one declaration (or definition), e.g.
ASTContext & getASTContext() const LLVM_READONLY
virtual Stmt * getBody() const
getBody - If this Decl represents a declaration for a body of code, such as a function or method defi...
llvm::iterator_range< specific_attr_iterator< T > > specific_attrs() const
SourceLocation getLocation() const
DeclContext * getDeclContext()
virtual Decl * getCanonicalDecl()
Retrieves the "canonical" declaration of the given declaration.
SourceLocation getBeginLoc() const LLVM_READONLY
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
This represents one expression.
bool isIntegerConstantExpr(const ASTContext &Ctx) const
Expr * IgnoreParenNoopCasts(const ASTContext &Ctx) LLVM_READONLY
Skip past any parentheses and casts which do not change the value (including ptr->int casts of the sa...
@ SE_AllowSideEffects
Allow any unmodeled side effect.
@ SE_AllowUndefinedBehavior
Allow UB that we can give a value, but not arbitrary unmodeled side effects.
Expr * IgnoreParenCasts() LLVM_READONLY
Skip past any parentheses and casts which might surround this expression until reaching a fixed point...
llvm::APSInt EvaluateKnownConstInt(const ASTContext &Ctx) const
EvaluateKnownConstInt - Call EvaluateAsRValue and return the folded integer.
Expr * IgnoreParenImpCasts() LLVM_READONLY
Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...
bool isEvaluatable(const ASTContext &Ctx, SideEffectsKind AllowSideEffects=SE_NoSideEffects) const
isEvaluatable - Call EvaluateAsRValue to see if this expression can be constant folded without side-e...
std::optional< llvm::APSInt > getIntegerConstantExpr(const ASTContext &Ctx) const
isIntegerConstantExpr - Return the value if this expression is a valid integer constant expression.
bool HasSideEffects(const ASTContext &Ctx, bool IncludePossibleEffects=true) const
HasSideEffects - This routine returns true for all those expressions which have any effect other than...
bool EvaluateAsBooleanCondition(bool &Result, const ASTContext &Ctx, bool InConstantContext=false) const
EvaluateAsBooleanCondition - Return true if this is a constant which we can fold and convert to a boo...
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
static bool isSameComparisonOperand(const Expr *E1, const Expr *E2)
Checks that the two Expr's will refer to the same value as a comparison operand.
bool hasNonTrivialCall(const ASTContext &Ctx) const
Determine whether this expression involves a call to any function that is not trivial.
Represents a member of a struct/union/class.
unsigned getFieldIndex() const
Returns the index of this field within its record, as appropriate for passing to ASTRecordLayout::get...
const RecordDecl * getParent() const
Returns the parent of this field declaration, which is the struct in which this field is defined.
static FieldDecl * Create(const ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, const IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, Expr *BW, bool Mutable, InClassInitStyle InitStyle)
Represents a function declaration or definition.
const ParmVarDecl * getParamDecl(unsigned i) const
QualType getReturnType() const
ArrayRef< ParmVarDecl * > parameters() const
FunctionDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
FunctionDecl * getMostRecentDecl()
Returns the most recent (re)declaration of this declaration.
unsigned getNumParams() const
Return the number of parameters this function must have based on its FunctionType.
FunctionDecl * getPreviousDecl()
Return the previous declaration of this declaration or NULL if this is the first declaration.
GlobalDecl - represents a global declaration.
const Decl * getDecl() const
static ImplicitParamDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation IdLoc, IdentifierInfo *Id, QualType T, ImplicitParamKind ParamKind)
Create implicit parameter.
static IntegerLiteral * Create(const ASTContext &C, const llvm::APInt &V, QualType type, SourceLocation l)
Returns a new integer literal with value 'V' and type 'type'.
An lvalue reference type, per C++11 [dcl.ref].
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
ValueDecl * getMemberDecl() const
Retrieve the member declaration to which this expression refers.
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
bool isExternallyVisible() const
const Stmt * getPreInitStmt() const
Get pre-initialization statement for the clause.
This is a basic class for representing single OpenMP clause.
This represents 'pragma omp declare mapper ...' directive.
Expr * getMapperVarRef()
Get the variable declared in the mapper.
This represents 'pragma omp declare reduction ...' directive.
Expr * getInitializer()
Get initializer expression (if specified) of the declare reduction construct.
Expr * getInitPriv()
Get Priv variable of the initializer.
Expr * getCombinerOut()
Get Out variable of the combiner.
Expr * getCombinerIn()
Get In variable of the combiner.
Expr * getCombiner()
Get combiner expression of the declare reduction construct.
Expr * getInitOrig()
Get Orig variable of the initializer.
OMPDeclareReductionInitKind getInitializerKind() const
Get initializer kind.
This represents 'if' clause in the 'pragma omp ...' directive.
Expr * getCondition() const
Returns condition.
OMPIteratorHelperData & getHelper(unsigned I)
Fetches helper data for the specified iteration space.
unsigned numOfIterators() const
Returns number of iterator definitions.
This represents 'num_threads' clause in the 'pragma omp ...' directive.
This represents 'pragma omp requires...' directive.
clauselist_range clauselists()
This represents 'threadset' clause in the 'pragma omp task ...' directive.
OpaqueValueExpr - An expression referring to an opaque object of a fixed type and value class.
Represents a parameter to a function.
PointerType - C99 6.7.5.1 - Pointer Declarators.
Represents an unpacked "presumed" location which can be presented to the user.
unsigned getColumn() const
Return the presumed column number of this location.
const char * getFilename() const
Return the presumed filename of this location.
unsigned getLine() const
Return the presumed line number of this location.
A (possibly-)qualified type.
void addRestrict()
Add the restrict qualifier to this QualType.
QualType withRestrict() const
bool isNull() const
Return true if this QualType doesn't point to a type yet.
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
Qualifiers getQualifiers() const
Retrieve the set of qualifiers applied to this type.
QualType getNonReferenceType() const
If Type is a reference type (e.g., const int&), returns the type that the reference refers to ("const...
QualType getCanonicalType() const
DestructionKind isDestructedType() const
Returns a nonzero value if objects of this type require non-trivial work to clean up after.
Represents a struct/union/class.
field_iterator field_end() const
field_range fields() const
virtual void completeDefinition()
Note that the definition of this type is now complete.
field_iterator field_begin() const
Scope - A scope is a transient data structure that is used while parsing the program.
Encodes a location in the source.
static SourceLocation getFromRawEncoding(UIntTy Encoding)
Turn a raw encoding of a SourceLocation object into a real SourceLocation.
bool isValid() const
Return true if this is a valid SourceLocation object.
UIntTy getRawEncoding() const
When a SourceLocation itself cannot be used, this returns an (opaque) 32-bit integer encoding for it.
This class handles loading and caching of source files into memory.
PresumedLoc getPresumedLoc(SourceLocation Loc, bool UseLineDirectives=true) const
Returns the "presumed" location of a SourceLocation specifies.
Stmt - This represents one statement.
StmtClass getStmtClass() const
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Stmt * IgnoreContainers(bool IgnoreCaptured=false)
Skip no-op (attributed, compound) container stmts and skip captured stmt at the top,...
SourceLocation getBeginLoc() const LLVM_READONLY
void startDefinition()
Starts the definition of this tag declaration.
The base class of the type hierarchy.
const Type * getPointeeOrArrayElementType() const
If this is a pointer type, return the pointee type.
bool isSignedIntegerType() const
Return true if this is an integer type that is signed, according to C99 6.2.5p4 [char,...
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
RecordDecl * getAsRecordDecl() const
Retrieves the RecordDecl this type refers to.
bool isPointerType() const
CanQualType getCanonicalTypeUnqualified() const
bool isIntegerType() const
isIntegerType() does not include complex integers (a GCC extension).
const T * castAs() const
Member-template castAs<specific type>.
bool isReferenceType() const
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
bool isLValueReferenceType() const
bool isAggregateType() const
Determines whether the type is a C++ aggregate type or C aggregate or union type.
RecordDecl * castAsRecordDecl() const
QualType getCanonicalTypeInternal() const
const Type * getBaseElementTypeUnsafe() const
Get the base element type of this type, potentially discarding type qualifiers.
bool isVariablyModifiedType() const
Whether this type is a variably-modified type (C99 6.7.5).
const ArrayType * getAsArrayTypeUnsafe() const
A variant of getAs<> for array types which silently discards qualifiers from the outermost type.
bool isFloatingType() const
bool isUnsignedIntegerType() const
Return true if this is an integer type that is unsigned, according to C99 6.2.5p6 [which returns true...
bool isAnyPointerType() const
const T * getAs() const
Member-template getAs<specific type>'.
bool isRecordType() const
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Represents a variable declaration or definition.
VarDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
VarDecl * getDefinition(ASTContext &)
Get the real (not just tentative) definition for this declaration.
const Expr * getInit() const
bool hasExternalStorage() const
Returns true if a variable has extern or private_extern storage.
@ DeclarationOnly
This declaration is only a declaration.
DefinitionKind hasDefinition(ASTContext &) const
Check whether this variable is defined in this translation unit.
bool isLocalVarDeclOrParm() const
Similar to isLocalVarDecl but also includes parameters.
const Expr * getAnyInitializer() const
Get the initializer for this variable, no matter which declaration it is attached to.
Represents a C array with a specified size that is not an integer-constant-expression.
Expr * getSizeExpr() const
specific_attr_iterator - Iterates over a subrange of an AttrVec, only providing attributes that are o...
bool isEmptyRecordForLayout(const ASTContext &Context, QualType T)
isEmptyRecordForLayout - Return true iff a structure contains only empty base classes (per isEmptyRec...
@ Type
The l-value was considered opaque, so the alignment was determined from a type.
@ Decl
The l-value was an access to a declared entity or something equivalently strong, like the address of ...
bool isEmptyFieldForLayout(const ASTContext &Context, const FieldDecl *FD)
isEmptyFieldForLayout - Return true iff the field is "empty", that is, either a zero-width bit-field ...
ComparisonResult
Indicates the result of a tentative comparison.
The JSON file list parser is used to communicate input to InstallAPI.
bool isOpenMPWorksharingDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a worksharing directive.
CanQual< Type > CanQualType
Represents a canonical, potentially-qualified type.
bool needsTaskBasedThreadLimit(OpenMPDirectiveKind DKind)
Checks if the specified target directive, combined or not, needs task based thread_limit.
@ Match
This is not an overload because the signature exactly matches an existing declaration.
@ Ctor_Complete
Complete object ctor.
Privates[]
This class represents the 'transparent' clause in the 'pragma omp task' directive.
bool isa(CodeGen::Address addr)
if(T->getSizeExpr()) TRY_TO(TraverseStmt(const_cast< Expr * >(T -> getSizeExpr())))
bool isOpenMPTargetDataManagementDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a target data offload directive.
static bool classof(const OMPClause *T)
@ Conditional
A conditional (?:) operator.
@ ICIS_NoInit
No in-class initializer.
bool isOpenMPDistributeDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a distribute directive.
@ LCK_ByRef
Capturing by reference.
LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE()
@ Private
'private' clause, allowed on 'parallel', 'serial', 'loop', 'parallel loop', and 'serial loop' constru...
@ Vector
'vector' clause, allowed on 'loop', Combined, and 'routine' directives.
@ Reduction
'reduction' clause, allowed on Parallel, Serial, Loop, and the combined constructs.
@ Present
'present' clause, allowed on Compute and Combined constructs, plus 'data' and 'declare'.
OpenMPScheduleClauseModifier
OpenMP modifiers for 'schedule' clause.
@ OMPC_SCHEDULE_MODIFIER_last
@ OMPC_SCHEDULE_MODIFIER_unknown
nullptr
This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...
bool isOpenMPParallelDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a parallel-kind directive.
OpenMPDistScheduleClauseKind
OpenMP attributes for 'dist_schedule' clause.
bool isOpenMPTaskingDirective(OpenMPDirectiveKind Kind)
Checks if the specified directive kind is one of tasking directives - task, taskloop,...
bool isOpenMPTargetExecutionDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a target code offload directive.
@ OMPC_DYN_GROUPPRIVATE_FALLBACK_unknown
@ Result
The result type of a method or function.
bool isOpenMPTeamsDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a teams-kind directive.
const FunctionProtoType * T
OpenMPDependClauseKind
OpenMP attributes for 'depend' clause.
@ Dtor_Complete
Complete object dtor.
@ Union
The "union" keyword.
bool isOpenMPTargetMapEnteringDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a map-entering target directive.
@ Type
The name was classified as a type.
bool isOpenMPLoopDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a directive with an associated loop construct.
OpenMPSeverityClauseKind
OpenMP attributes for 'severity' clause.
LangAS
Defines the address space values used by the address space qualifier of QualType.
llvm::omp::Directive OpenMPDirectiveKind
OpenMP directives.
bool isOpenMPSimdDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a simd directive.
@ VK_PRValue
A pr-value expression (in the C++11 taxonomy) produces a temporary value.
@ VK_LValue
An l-value expression is a reference to an object with independent storage.
for(const auto &A :T->param_types())
void getOpenMPCaptureRegions(llvm::SmallVectorImpl< OpenMPDirectiveKind > &CaptureRegions, OpenMPDirectiveKind DKind)
Return the captured regions of an OpenMP directive.
OpenMPNumThreadsClauseModifier
@ OMPC_ATOMIC_DEFAULT_MEM_ORDER_unknown
U cast(CodeGen::Address addr)
OpenMPMapModifierKind
OpenMP modifier kind for 'map' clause.
@ OMPC_MAP_MODIFIER_unknown
@ Other
Other implicit parameter.
OpenMPScheduleClauseKind
OpenMP attributes for 'schedule' clause.
bool isOpenMPTaskLoopDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a taskloop directive.
OpenMPThreadsetKind
OpenMP modifiers for 'threadset' clause.
OpenMPMapClauseKind
OpenMP mapping kind for 'map' clause.
Diagnostic wrappers for TextAPI types for error reporting.
Data for list of allocators.
Expr * AllocatorTraits
Allocator traits.
Expr * Allocator
Allocator.
Maps the expression for the lastprivate variable to the global copy used to store new value because o...
llvm::SmallVector< bool, 8 > IsPrivateVarReduction
A jump destination is an abstract label, branching to which may require a jump out through normal cle...
llvm::BasicBlock * getBlock() const
unsigned NumberOfTargetItems
Address BasePointersArray
llvm::PointerType * VoidPtrTy
llvm::IntegerType * Int64Ty
llvm::IntegerType * Int8Ty
i8, i16, i32, and i64
llvm::CallingConv::ID getRuntimeCC() const
llvm::IntegerType * SizeTy
llvm::PointerType * VoidPtrPtrTy
llvm::IntegerType * Int32Ty
llvm::IntegerType * IntPtrTy
llvm::IntegerType * IntTy
int
CharUnits getPointerAlign() const
OpenMPDependClauseKind DepKind
const Expr * IteratorExpr
SmallVector< const Expr *, 4 > DepExprs
EvalResult is a struct with detailed info about an evaluated expression.
Extra information about a function prototype.
Expr * CounterUpdate
Updater for the internal counter: ++CounterVD;.
Scheduling data for loop-based OpenMP directives.
OpenMPScheduleClauseModifier M2
OpenMPScheduleClauseModifier M1
OpenMPScheduleClauseKind Schedule
Describes how types, statements, expressions, and declarations should be printed.