31#include "llvm/ADT/ArrayRef.h"
32#include "llvm/ADT/SmallSet.h"
33#include "llvm/ADT/SmallVector.h"
34#include "llvm/ADT/StringExtras.h"
35#include "llvm/Bitcode/BitcodeReader.h"
36#include "llvm/IR/Constants.h"
37#include "llvm/IR/DerivedTypes.h"
38#include "llvm/IR/GlobalValue.h"
39#include "llvm/IR/InstrTypes.h"
40#include "llvm/IR/Value.h"
41#include "llvm/Support/AtomicOrdering.h"
42#include "llvm/Support/raw_ostream.h"
50using namespace llvm::omp;
57 enum CGOpenMPRegionKind {
60 ParallelOutlinedRegion,
70 CGOpenMPRegionInfo(
const CapturedStmt &CS,
71 const CGOpenMPRegionKind RegionKind,
74 : CGCapturedStmtInfo(CS,
CR_OpenMP), RegionKind(RegionKind),
75 CodeGen(CodeGen), Kind(Kind), HasCancel(HasCancel) {}
77 CGOpenMPRegionInfo(
const CGOpenMPRegionKind RegionKind,
80 : CGCapturedStmtInfo(
CR_OpenMP), RegionKind(RegionKind), CodeGen(CodeGen),
81 Kind(Kind), HasCancel(HasCancel) {}
85 virtual const VarDecl *getThreadIDVariable()
const = 0;
88 void EmitBody(CodeGenFunction &CGF,
const Stmt *S)
override;
92 virtual LValue getThreadIDVariableLValue(CodeGenFunction &CGF);
94 virtual void emitUntiedSwitch(CodeGenFunction & ) {}
96 CGOpenMPRegionKind getRegionKind()
const {
return RegionKind; }
100 bool hasCancel()
const {
return HasCancel; }
102 static bool classof(
const CGCapturedStmtInfo *Info) {
106 ~CGOpenMPRegionInfo()
override =
default;
109 CGOpenMPRegionKind RegionKind;
110 RegionCodeGenTy CodeGen;
116class CGOpenMPOutlinedRegionInfo final :
public CGOpenMPRegionInfo {
118 CGOpenMPOutlinedRegionInfo(
const CapturedStmt &CS,
const VarDecl *ThreadIDVar,
119 const RegionCodeGenTy &CodeGen,
121 StringRef HelperName)
122 : CGOpenMPRegionInfo(CS, ParallelOutlinedRegion, CodeGen,
Kind,
124 ThreadIDVar(ThreadIDVar), HelperName(HelperName) {
125 assert(ThreadIDVar !=
nullptr &&
"No ThreadID in OpenMP region.");
130 const VarDecl *getThreadIDVariable()
const override {
return ThreadIDVar; }
133 StringRef getHelperName()
const override {
return HelperName; }
135 static bool classof(
const CGCapturedStmtInfo *Info) {
136 return CGOpenMPRegionInfo::classof(Info) &&
138 ParallelOutlinedRegion;
144 const VarDecl *ThreadIDVar;
145 StringRef HelperName;
149class CGOpenMPTaskOutlinedRegionInfo final :
public CGOpenMPRegionInfo {
151 class UntiedTaskActionTy final :
public PrePostActionTy {
153 const VarDecl *PartIDVar;
154 const RegionCodeGenTy UntiedCodeGen;
155 llvm::SwitchInst *UntiedSwitch =
nullptr;
158 UntiedTaskActionTy(
bool Tied,
const VarDecl *PartIDVar,
159 const RegionCodeGenTy &UntiedCodeGen)
160 : Untied(!Tied), PartIDVar(PartIDVar), UntiedCodeGen(UntiedCodeGen) {}
161 void Enter(CodeGenFunction &CGF)
override {
166 PartIDVar->
getType()->castAs<PointerType>());
170 UntiedSwitch = CGF.
Builder.CreateSwitch(Res, DoneBB);
174 UntiedSwitch->addCase(CGF.
Builder.getInt32(0),
176 emitUntiedSwitch(CGF);
179 void emitUntiedSwitch(CodeGenFunction &CGF)
const {
183 PartIDVar->
getType()->castAs<PointerType>());
187 CodeGenFunction::JumpDest CurPoint =
191 UntiedSwitch->addCase(CGF.
Builder.getInt32(UntiedSwitch->getNumCases()),
197 unsigned getNumberOfParts()
const {
return UntiedSwitch->getNumCases(); }
199 CGOpenMPTaskOutlinedRegionInfo(
const CapturedStmt &CS,
200 const VarDecl *ThreadIDVar,
201 const RegionCodeGenTy &CodeGen,
203 const UntiedTaskActionTy &Action)
204 : CGOpenMPRegionInfo(CS, TaskOutlinedRegion, CodeGen,
Kind, HasCancel),
205 ThreadIDVar(ThreadIDVar), Action(Action) {
206 assert(ThreadIDVar !=
nullptr &&
"No ThreadID in OpenMP region.");
211 const VarDecl *getThreadIDVariable()
const override {
return ThreadIDVar; }
214 LValue getThreadIDVariableLValue(CodeGenFunction &CGF)
override;
217 StringRef getHelperName()
const override {
return ".omp_outlined."; }
219 void emitUntiedSwitch(CodeGenFunction &CGF)
override {
220 Action.emitUntiedSwitch(CGF);
223 static bool classof(
const CGCapturedStmtInfo *Info) {
224 return CGOpenMPRegionInfo::classof(Info) &&
232 const VarDecl *ThreadIDVar;
234 const UntiedTaskActionTy &Action;
239class CGOpenMPInlinedRegionInfo :
public CGOpenMPRegionInfo {
241 CGOpenMPInlinedRegionInfo(CodeGenFunction::CGCapturedStmtInfo *OldCSI,
242 const RegionCodeGenTy &CodeGen,
244 : CGOpenMPRegionInfo(InlinedRegion, CodeGen,
Kind, HasCancel),
246 OuterRegionInfo(dyn_cast_or_null<CGOpenMPRegionInfo>(OldCSI)) {}
249 llvm::Value *getContextValue()
const override {
251 return OuterRegionInfo->getContextValue();
252 llvm_unreachable(
"No context value for inlined OpenMP region");
255 void setContextValue(llvm::Value *
V)
override {
256 if (OuterRegionInfo) {
257 OuterRegionInfo->setContextValue(
V);
260 llvm_unreachable(
"No context value for inlined OpenMP region");
264 const FieldDecl *lookup(
const VarDecl *VD)
const override {
266 return OuterRegionInfo->lookup(VD);
272 FieldDecl *getThisFieldDecl()
const override {
274 return OuterRegionInfo->getThisFieldDecl();
280 const VarDecl *getThreadIDVariable()
const override {
282 return OuterRegionInfo->getThreadIDVariable();
287 LValue getThreadIDVariableLValue(CodeGenFunction &CGF)
override {
289 return OuterRegionInfo->getThreadIDVariableLValue(CGF);
290 llvm_unreachable(
"No LValue for inlined OpenMP construct");
294 StringRef getHelperName()
const override {
295 if (
auto *OuterRegionInfo = getOldCSI())
296 return OuterRegionInfo->getHelperName();
297 llvm_unreachable(
"No helper name for inlined OpenMP construct");
300 void emitUntiedSwitch(CodeGenFunction &CGF)
override {
302 OuterRegionInfo->emitUntiedSwitch(CGF);
305 CodeGenFunction::CGCapturedStmtInfo *getOldCSI()
const {
return OldCSI; }
307 static bool classof(
const CGCapturedStmtInfo *Info) {
308 return CGOpenMPRegionInfo::classof(Info) &&
312 ~CGOpenMPInlinedRegionInfo()
override =
default;
316 CodeGenFunction::CGCapturedStmtInfo *OldCSI;
317 CGOpenMPRegionInfo *OuterRegionInfo;
325class CGOpenMPTargetRegionInfo final :
public CGOpenMPRegionInfo {
327 CGOpenMPTargetRegionInfo(
const CapturedStmt &CS,
328 const RegionCodeGenTy &CodeGen, StringRef HelperName)
329 : CGOpenMPRegionInfo(CS, TargetRegion, CodeGen, OMPD_target,
331 HelperName(HelperName) {}
335 const VarDecl *getThreadIDVariable()
const override {
return nullptr; }
338 StringRef getHelperName()
const override {
return HelperName; }
340 static bool classof(
const CGCapturedStmtInfo *Info) {
341 return CGOpenMPRegionInfo::classof(Info) &&
346 StringRef HelperName;
350 llvm_unreachable(
"No codegen for expressions");
354class CGOpenMPInnerExprInfo final :
public CGOpenMPInlinedRegionInfo {
356 CGOpenMPInnerExprInfo(CodeGenFunction &CGF,
const CapturedStmt &CS)
357 : CGOpenMPInlinedRegionInfo(CGF.CapturedStmtInfo, EmptyCodeGen,
365 if (!C.capturesVariable() && !C.capturesVariableByCopy())
368 const VarDecl *VD = C.getCapturedVar();
369 if (VD->isLocalVarDeclOrParm())
372 DeclRefExpr DRE(CGF.getContext(), const_cast<VarDecl *>(VD),
374 VD->getType().getNonReferenceType(), VK_LValue,
376 PrivScope.addPrivate(VD, CGF.EmitLValue(&DRE).getAddress());
378 (
void)PrivScope.Privatize();
382 const FieldDecl *lookup(
const VarDecl *VD)
const override {
383 if (
const FieldDecl *FD = CGOpenMPInlinedRegionInfo::lookup(VD))
389 void EmitBody(CodeGenFunction &CGF,
const Stmt *S)
override {
390 llvm_unreachable(
"No body for expressions");
395 const VarDecl *getThreadIDVariable()
const override {
396 llvm_unreachable(
"No thread id for expressions");
400 StringRef getHelperName()
const override {
401 llvm_unreachable(
"No helper name for expressions");
404 static bool classof(
const CGCapturedStmtInfo *Info) {
return false; }
408 CodeGenFunction::OMPPrivateScope PrivScope;
412class InlinedOpenMPRegionRAII {
413 CodeGenFunction &CGF;
414 llvm::DenseMap<const ValueDecl *, FieldDecl *> LambdaCaptureFields;
415 FieldDecl *LambdaThisCaptureField =
nullptr;
416 const CodeGen::CGBlockInfo *BlockInfo =
nullptr;
417 bool NoInheritance =
false;
424 InlinedOpenMPRegionRAII(CodeGenFunction &CGF,
const RegionCodeGenTy &CodeGen,
426 bool NoInheritance =
true)
427 : CGF(CGF), NoInheritance(NoInheritance) {
429 CGF.CapturedStmtInfo =
new CGOpenMPInlinedRegionInfo(
430 CGF.CapturedStmtInfo, CodeGen, Kind, HasCancel);
432 std::swap(CGF.LambdaCaptureFields, LambdaCaptureFields);
433 LambdaThisCaptureField = CGF.LambdaThisCaptureField;
434 CGF.LambdaThisCaptureField =
nullptr;
435 BlockInfo = CGF.BlockInfo;
436 CGF.BlockInfo =
nullptr;
440 ~InlinedOpenMPRegionRAII() {
444 delete CGF.CapturedStmtInfo;
445 CGF.CapturedStmtInfo = OldCSI;
447 std::swap(CGF.LambdaCaptureFields, LambdaCaptureFields);
448 CGF.LambdaThisCaptureField = LambdaThisCaptureField;
449 CGF.BlockInfo = BlockInfo;
457enum OpenMPLocationFlags :
unsigned {
459 OMP_IDENT_IMD = 0x01,
461 OMP_IDENT_KMPC = 0x02,
463 OMP_ATOMIC_REDUCE = 0x10,
465 OMP_IDENT_BARRIER_EXPL = 0x20,
467 OMP_IDENT_BARRIER_IMPL = 0x40,
469 OMP_IDENT_BARRIER_IMPL_FOR = 0x40,
471 OMP_IDENT_BARRIER_IMPL_SECTIONS = 0xC0,
473 OMP_IDENT_BARRIER_IMPL_SINGLE = 0x140,
475 OMP_IDENT_WORK_LOOP = 0x200,
477 OMP_IDENT_WORK_SECTIONS = 0x400,
479 OMP_IDENT_WORK_DISTRIBUTE = 0x800,
509enum IdentFieldIndex {
511 IdentField_Reserved_1,
515 IdentField_Reserved_2,
517 IdentField_Reserved_3,
526enum OpenMPSchedType {
529 OMP_sch_static_chunked = 33,
531 OMP_sch_dynamic_chunked = 35,
532 OMP_sch_guided_chunked = 36,
533 OMP_sch_runtime = 37,
536 OMP_sch_static_balanced_chunked = 45,
539 OMP_ord_static_chunked = 65,
541 OMP_ord_dynamic_chunked = 67,
542 OMP_ord_guided_chunked = 68,
543 OMP_ord_runtime = 69,
545 OMP_sch_default = OMP_sch_static,
547 OMP_dist_sch_static_chunked = 91,
548 OMP_dist_sch_static = 92,
554 OMP_dist_sch_static_chunked_sch_static_chunkone = 93,
557 OMP_sch_modifier_monotonic = (1 << 29),
559 OMP_sch_modifier_nonmonotonic = (1 << 30),
564class CleanupTy final :
public EHScopeStack::Cleanup {
565 PrePostActionTy *Action;
568 explicit CleanupTy(PrePostActionTy *Action) : Action(Action) {}
569 void Emit(CodeGenFunction &CGF, Flags )
override {
582 Callback(CodeGen, CGF, *PrePostAction);
585 Callback(CodeGen, CGF, Action);
593 if (
const auto *CE = dyn_cast<CallExpr>(ReductionOp))
594 if (
const auto *OVE = dyn_cast<OpaqueValueExpr>(CE->getCallee()))
595 if (
const auto *DRE =
596 dyn_cast<DeclRefExpr>(OVE->getSourceExpr()->IgnoreImpCasts()))
597 if (
const auto *DRD = dyn_cast<OMPDeclareReductionDecl>(DRE->getDecl()))
608 std::pair<llvm::Function *, llvm::Function *>
Reduction =
628 auto *GV =
new llvm::GlobalVariable(
630 llvm::GlobalValue::PrivateLinkage,
Init, Name);
671 llvm::Value *NumElements = CGF.
emitArrayLength(ArrayTy, ElementTy, DestAddr);
675 llvm::Value *SrcBegin =
nullptr;
677 SrcBegin = SrcAddr.emitRawPointer(CGF);
680 llvm::Value *DestEnd =
685 llvm::Value *IsEmpty =
686 CGF.
Builder.CreateICmpEQ(DestBegin, DestEnd,
"omp.arrayinit.isempty");
687 CGF.
Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
690 llvm::BasicBlock *EntryBB = CGF.
Builder.GetInsertBlock();
695 llvm::PHINode *SrcElementPHI =
nullptr;
698 SrcElementPHI = CGF.
Builder.CreatePHI(SrcBegin->getType(), 2,
699 "omp.arraycpy.srcElementPast");
700 SrcElementPHI->addIncoming(SrcBegin, EntryBB);
702 Address(SrcElementPHI, SrcAddr.getElementType(),
703 SrcAddr.getAlignment().alignmentOfArrayElement(ElementSize));
705 llvm::PHINode *DestElementPHI = CGF.
Builder.CreatePHI(
706 DestBegin->getType(), 2,
"omp.arraycpy.destElementPast");
707 DestElementPHI->addIncoming(DestBegin, EntryBB);
715 if (EmitDeclareReductionInit) {
717 SrcElementCurrent, ElementTy);
725 llvm::Value *SrcElementNext = CGF.
Builder.CreateConstGEP1_32(
726 SrcAddr.getElementType(), SrcElementPHI, 1,
727 "omp.arraycpy.dest.element");
728 SrcElementPHI->addIncoming(SrcElementNext, CGF.
Builder.GetInsertBlock());
732 llvm::Value *DestElementNext = CGF.
Builder.CreateConstGEP1_32(
734 "omp.arraycpy.dest.element");
737 CGF.
Builder.CreateICmpEQ(DestElementNext, DestEnd,
"omp.arraycpy.done");
738 CGF.
Builder.CreateCondBr(Done, DoneBB, BodyBB);
739 DestElementPHI->addIncoming(DestElementNext, CGF.
Builder.GetInsertBlock());
751 if (
const auto *OASE = dyn_cast<ArraySectionExpr>(E))
756void ReductionCodeGen::emitAggregateInitialization(
758 const OMPDeclareReductionDecl *DRD) {
762 const auto *PrivateVD =
764 bool EmitDeclareReductionInit =
767 EmitDeclareReductionInit,
768 EmitDeclareReductionInit ? ClausesData[N].ReductionOp
769 : PrivateVD->getInit(),
777 ClausesData.reserve(Shareds.size());
778 SharedAddresses.reserve(Shareds.size());
779 Sizes.reserve(Shareds.size());
780 BaseDecls.reserve(Shareds.size());
781 const auto *IOrig = Origs.begin();
782 const auto *IPriv =
Privates.begin();
783 const auto *IRed = ReductionOps.begin();
784 for (
const Expr *Ref : Shareds) {
785 ClausesData.emplace_back(Ref, *IOrig, *IPriv, *IRed);
786 std::advance(IOrig, 1);
787 std::advance(IPriv, 1);
788 std::advance(IRed, 1);
793 assert(SharedAddresses.size() == N && OrigAddresses.size() == N &&
794 "Number of generated lvalues must be exactly N.");
795 LValue First = emitSharedLValue(CGF, ClausesData[N].Shared);
796 LValue Second = emitSharedLValueUB(CGF, ClausesData[N].Shared);
797 SharedAddresses.emplace_back(
First, Second);
798 if (ClausesData[N].Shared == ClausesData[N].Ref) {
799 OrigAddresses.emplace_back(
First, Second);
801 LValue First = emitSharedLValue(CGF, ClausesData[N].Ref);
802 LValue Second = emitSharedLValueUB(CGF, ClausesData[N].Ref);
803 OrigAddresses.emplace_back(
First, Second);
812 CGF.
getTypeSize(OrigAddresses[N].first.getType().getNonReferenceType()),
817 llvm::Value *SizeInChars;
818 auto *ElemType = OrigAddresses[N].first.getAddress().getElementType();
819 auto *ElemSizeOf = llvm::ConstantExpr::getSizeOf(ElemType);
820 if (AsArraySection) {
821 Size = CGF.
Builder.CreatePtrDiff(ElemType,
822 OrigAddresses[N].second.getPointer(CGF),
823 OrigAddresses[N].first.getPointer(CGF));
824 Size = CGF.
Builder.CreateZExtOrTrunc(Size, ElemSizeOf->getType());
825 Size = CGF.
Builder.CreateNUWAdd(
826 Size, llvm::ConstantInt::get(Size->getType(), 1));
827 SizeInChars = CGF.
Builder.CreateNUWMul(Size, ElemSizeOf);
830 CGF.
getTypeSize(OrigAddresses[N].first.getType().getNonReferenceType());
831 Size = CGF.
Builder.CreateExactUDiv(SizeInChars, ElemSizeOf);
833 Sizes.emplace_back(SizeInChars, Size);
846 assert(!Size && !Sizes[N].second &&
847 "Size should be nullptr for non-variably modified reduction "
862 assert(SharedAddresses.size() > N &&
"No variable was generated");
863 const auto *PrivateVD =
869 (void)DefaultInit(CGF);
870 emitAggregateInitialization(CGF, N, PrivateAddr, SharedAddr, DRD);
871 }
else if (DRD && (DRD->
getInitializer() || !PrivateVD->hasInit())) {
872 (void)DefaultInit(CGF);
873 QualType SharedType = SharedAddresses[N].first.getType();
875 PrivateAddr, SharedAddr, SharedType);
876 }
else if (!DefaultInit(CGF) && PrivateVD->hasInit() &&
879 PrivateVD->
getType().getQualifiers(),
897 CGF.
pushDestroy(DTorKind, PrivateAddr, PrivateType);
916 BaseLV.getType(), BaseLV.getBaseInfo(),
950 const VarDecl *OrigVD =
nullptr;
951 if (
const auto *OASE = dyn_cast<ArraySectionExpr>(Ref)) {
952 const Expr *
Base = OASE->getBase()->IgnoreParenImpCasts();
953 while (
const auto *TempOASE = dyn_cast<ArraySectionExpr>(
Base))
954 Base = TempOASE->getBase()->IgnoreParenImpCasts();
955 while (
const auto *TempASE = dyn_cast<ArraySubscriptExpr>(
Base))
956 Base = TempASE->getBase()->IgnoreParenImpCasts();
959 }
else if (
const auto *ASE = dyn_cast<ArraySubscriptExpr>(Ref)) {
960 const Expr *
Base = ASE->getBase()->IgnoreParenImpCasts();
961 while (
const auto *TempASE = dyn_cast<ArraySubscriptExpr>(
Base))
962 Base = TempASE->getBase()->IgnoreParenImpCasts();
973 BaseDecls.emplace_back(OrigVD);
976 loadToBegin(CGF, OrigVD->getType(), SharedAddresses[N].first.getType(),
978 Address SharedAddr = SharedAddresses[N].first.getAddress();
979 llvm::Value *Adjustment = CGF.
Builder.CreatePtrDiff(
982 llvm::Value *PrivatePointer =
988 SharedAddresses[N].first.getType(),
991 BaseDecls.emplace_back(
1005 getThreadIDVariable()->
getType()->castAs<PointerType>());
1023LValue CGOpenMPTaskOutlinedRegionInfo::getThreadIDVariableLValue(
1026 getThreadIDVariable()->
getType(),
1044 llvm::OpenMPIRBuilderConfig Config(
1045 CGM.getLangOpts().OpenMPIsTargetDevice,
isGPU(),
1046 CGM.getLangOpts().OpenMPOffloadMandatory,
1049 Config.setDefaultTargetAS(
1051 Config.setRuntimeCC(
CGM.getRuntimeCC());
1056 CGM.getLangOpts().OpenMPIsTargetDevice
1057 ?
CGM.getLangOpts().OMPHostIRFile
1062 if (
CGM.getLangOpts().OpenMPForceUSM) {
1064 OMPBuilder.Config.setHasRequiresUnifiedSharedMemory(
true);
1072 if (!
Data.getValue().pointsToAliveValue())
1074 auto *GV = dyn_cast<llvm::GlobalVariable>(
Data.getValue());
1077 if (!GV->isDeclaration() || GV->getNumUses() > 0)
1079 GV->eraseFromParent();
1084 return OMPBuilder.createPlatformSpecificName(Parts);
1087static llvm::Function *
1089 const Expr *CombinerInitializer,
const VarDecl *In,
1090 const VarDecl *Out,
bool IsCombiner) {
1093 QualType PtrTy =
C.getPointerType(Ty).withRestrict();
1095 C,
nullptr, Out->getLocation(),
1098 C,
nullptr, In->getLocation(),
1105 {IsCombiner ?
"omp_combiner" :
"omp_initializer",
""});
1106 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
1110 Fn->addFnAttr(
"sample-profile-suffix-elision-policy",
"selected");
1112 Fn->removeFnAttr(llvm::Attribute::NoInline);
1113 Fn->removeFnAttr(llvm::Attribute::OptimizeNone);
1114 Fn->addFnAttr(llvm::Attribute::AlwaysInline);
1120 Out->getLocation());
1130 (void)
Scope.Privatize();
1131 if (!IsCombiner && Out->hasInit() &&
1134 Out->getType().getQualifiers(),
1137 if (CombinerInitializer)
1139 Scope.ForceCleanup();
1168std::pair<llvm::Function *, llvm::Function *>
1180struct PushAndPopStackRAII {
1181 PushAndPopStackRAII(llvm::OpenMPIRBuilder *OMPBuilder,
CodeGenFunction &CGF,
1182 bool HasCancel, llvm::omp::Directive Kind)
1183 : OMPBuilder(OMPBuilder) {
1199 auto FiniCB = [&CGF](llvm::OpenMPIRBuilder::InsertPointTy IP) {
1200 assert(IP.getBlock()->end() == IP.getPoint() &&
1201 "Clang CG should cause non-terminated block!");
1202 CGBuilderTy::InsertPointGuard IPG(CGF.
Builder);
1207 return llvm::Error::success();
1212 llvm::OpenMPIRBuilder::FinalizationInfo FI({FiniCB, Kind, HasCancel});
1213 OMPBuilder->pushFinalizationCB(std::move(FI));
1215 ~PushAndPopStackRAII() {
1217 OMPBuilder->popFinalizationCB();
1219 llvm::OpenMPIRBuilder *OMPBuilder;
1228 "thread id variable must be of type kmp_int32 *");
1230 bool HasCancel =
false;
1231 if (
const auto *OPD = dyn_cast<OMPParallelDirective>(&D))
1232 HasCancel = OPD->hasCancel();
1233 else if (
const auto *OPD = dyn_cast<OMPTargetParallelDirective>(&D))
1234 HasCancel = OPD->hasCancel();
1235 else if (
const auto *OPSD = dyn_cast<OMPParallelSectionsDirective>(&D))
1236 HasCancel = OPSD->hasCancel();
1237 else if (
const auto *OPFD = dyn_cast<OMPParallelForDirective>(&D))
1238 HasCancel = OPFD->hasCancel();
1239 else if (
const auto *OPFD = dyn_cast<OMPTargetParallelForDirective>(&D))
1240 HasCancel = OPFD->hasCancel();
1241 else if (
const auto *OPFD = dyn_cast<OMPDistributeParallelForDirective>(&D))
1242 HasCancel = OPFD->hasCancel();
1243 else if (
const auto *OPFD =
1244 dyn_cast<OMPTeamsDistributeParallelForDirective>(&D))
1245 HasCancel = OPFD->hasCancel();
1246 else if (
const auto *OPFD =
1247 dyn_cast<OMPTargetTeamsDistributeParallelForDirective>(&D))
1248 HasCancel = OPFD->hasCancel();
1253 PushAndPopStackRAII PSR(&OMPBuilder, CGF, HasCancel, InnermostKind);
1254 CGOpenMPOutlinedRegionInfo CGInfo(*CS, ThreadIDVar,
CodeGen, InnermostKind,
1255 HasCancel, OutlinedHelperName);
1261 std::string Suffix =
getName({
"omp_outlined"});
1262 return (Name + Suffix).str();
1270 std::string Suffix =
getName({
"omp",
"reduction",
"reduction_func"});
1271 return (Name + Suffix).str();
1278 const CapturedStmt *CS = D.getCapturedStmt(OMPD_parallel);
1288 const CapturedStmt *CS = D.getCapturedStmt(OMPD_teams);
1298 bool Tied,
unsigned &NumberOfParts) {
1301 llvm::Value *ThreadID =
getThreadID(CGF, D.getBeginLoc());
1303 llvm::Value *TaskArgs[] = {
1305 CGF.EmitLoadOfPointerLValue(CGF.GetAddrOfLocalVar(TaskTVar),
1308 CGF.EmitRuntimeCall(
OMPBuilder.getOrCreateRuntimeFunction(
1309 CGM.getModule(), OMPRTL___kmpc_omp_task),
1312 CGOpenMPTaskOutlinedRegionInfo::UntiedTaskActionTy Action(Tied, PartIDVar,
1316 "thread id variable must be of type kmp_int32 for tasks");
1321 bool HasCancel =
false;
1322 if (
const auto *TD = dyn_cast<OMPTaskDirective>(&D))
1323 HasCancel = TD->hasCancel();
1324 else if (
const auto *TD = dyn_cast<OMPTaskLoopDirective>(&D))
1325 HasCancel = TD->hasCancel();
1326 else if (
const auto *TD = dyn_cast<OMPMasterTaskLoopDirective>(&D))
1327 HasCancel = TD->hasCancel();
1328 else if (
const auto *TD = dyn_cast<OMPParallelMasterTaskLoopDirective>(&D))
1329 HasCancel = TD->hasCancel();
1332 CGOpenMPTaskOutlinedRegionInfo CGInfo(*CS, ThreadIDVar,
CodeGen,
1333 InnermostKind, HasCancel, Action);
1335 llvm::Function *Res = CGF.GenerateCapturedStmtFunction(*CS);
1337 NumberOfParts = Action.getNumberOfParts();
1342 bool AtCurrentPoint) {
1344 assert(!Elem.ServiceInsertPt &&
"Insert point is set already.");
1346 llvm::Value *Undef = llvm::UndefValue::get(CGF.
Int32Ty);
1347 if (AtCurrentPoint) {
1348 Elem.ServiceInsertPt =
new llvm::BitCastInst(Undef, CGF.
Int32Ty,
"svcpt",
1349 CGF.
Builder.GetInsertBlock());
1351 Elem.ServiceInsertPt =
new llvm::BitCastInst(Undef, CGF.
Int32Ty,
"svcpt");
1352 Elem.ServiceInsertPt->insertAfter(CGF.
AllocaInsertPt->getIterator());
1358 if (Elem.ServiceInsertPt) {
1359 llvm::Instruction *Ptr = Elem.ServiceInsertPt;
1360 Elem.ServiceInsertPt =
nullptr;
1361 Ptr->eraseFromParent();
1368 llvm::raw_svector_ostream OS(Buffer);
1377 if (
const auto *FD = dyn_cast_or_null<FunctionDecl>(CGF.
CurFuncDecl))
1378 OS << FD->getQualifiedNameAsString();
1385 unsigned Flags,
bool EmitLoc) {
1386 uint32_t SrcLocStrSize;
1387 llvm::Constant *SrcLocStr;
1388 if ((!EmitLoc &&
CGM.getCodeGenOpts().getDebugInfo() ==
1389 llvm::codegenoptions::NoDebugInfo) ||
1391 SrcLocStr =
OMPBuilder.getOrCreateDefaultSrcLocStr(SrcLocStrSize);
1393 std::string FunctionName;
1395 if (
const auto *FD = dyn_cast_or_null<FunctionDecl>(CGF.
CurFuncDecl))
1396 FunctionName = FD->getQualifiedNameAsString();
1409 SrcLocStr, SrcLocStrSize, llvm::omp::IdentFlag(Flags), Reserved2Flags);
1414 assert(CGF.
CurFn &&
"No function in current CodeGenFunction.");
1417 if (
CGM.getLangOpts().OpenMPIRBuilder) {
1420 uint32_t SrcLocStrSize;
1421 auto *SrcLocStr =
OMPBuilder.getOrCreateSrcLocStr(
1424 OMPBuilder.getOrCreateIdent(SrcLocStr, SrcLocStrSize));
1427 llvm::Value *ThreadID =
nullptr;
1432 ThreadID = I->second.ThreadID;
1433 if (ThreadID !=
nullptr)
1437 if (
auto *OMPRegionInfo =
1439 if (OMPRegionInfo->getThreadIDVariable()) {
1441 LValue LVal = OMPRegionInfo->getThreadIDVariableLValue(CGF);
1445 CGF.
Builder.GetInsertBlock() == TopBlock ||
1450 CGF.
Builder.GetInsertBlock()) {
1454 if (CGF.
Builder.GetInsertBlock() == TopBlock)
1466 if (!Elem.ServiceInsertPt)
1468 CGBuilderTy::InsertPointGuard IPG(CGF.
Builder);
1469 CGF.
Builder.SetInsertPoint(Elem.ServiceInsertPt);
1473 OMPRTL___kmpc_global_thread_num),
1476 Elem.ThreadID =
Call;
1481 assert(CGF.
CurFn &&
"No function in current CodeGenFunction.");
1487 for (
const auto *D : I->second)
1492 for (
const auto *D : I->second)
1504static llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseKind
1506 std::optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
1507 OMPDeclareTargetDeclAttr::getDeviceType(VD);
1509 return llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseNone;
1511 switch ((
int)*DevTy) {
1512 case OMPDeclareTargetDeclAttr::DT_Host:
1513 return llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseHost;
1515 case OMPDeclareTargetDeclAttr::DT_NoHost:
1516 return llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseNoHost;
1518 case OMPDeclareTargetDeclAttr::DT_Any:
1519 return llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseAny;
1522 return llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseNone;
1527static llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryKind
1529 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> MapType =
1530 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
1532 return llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryNone;
1533 switch ((
int)*MapType) {
1534 case OMPDeclareTargetDeclAttr::MapTypeTy::MT_To:
1535 return llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryTo;
1537 case OMPDeclareTargetDeclAttr::MapTypeTy::MT_Enter:
1538 return llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryEnter;
1539 case OMPDeclareTargetDeclAttr::MapTypeTy::MT_Link:
1540 return llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryLink;
1542 case OMPDeclareTargetDeclAttr::MapTypeTy::MT_Local:
1544 llvm_unreachable(
"MT_Local should not reach convertCaptureClause");
1547 return llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryNone;
1556 auto FileInfoCallBack = [&]() {
1566 return OMPBuilder.getTargetEntryUniqueInfo(FileInfoCallBack,
1571 auto AddrOfGlobal = [&VD,
this]() {
return CGM.GetAddrOfGlobal(VD); };
1573 auto LinkageForVariable = [&VD,
this]() {
1574 return CGM.getLLVMLinkageVarDefinition(VD);
1577 std::vector<llvm::GlobalVariable *> GeneratedRefs;
1579 llvm::Type *LlvmPtrTy =
CGM.getTypes().ConvertTypeForMem(
1580 CGM.getContext().getPointerType(VD->
getType()));
1581 llvm::Constant *addr =
OMPBuilder.getAddrOfDeclareTargetVar(
1587 CGM.getMangledName(VD), GeneratedRefs,
CGM.getLangOpts().OpenMPSimd,
1588 CGM.getLangOpts().OMPTargetTriples, LlvmPtrTy, AddrOfGlobal,
1589 LinkageForVariable);
1598 assert(!
CGM.getLangOpts().OpenMPUseTLS ||
1599 !
CGM.getContext().getTargetInfo().isTLSSupported());
1601 std::string Suffix =
getName({
"cache",
""});
1602 return OMPBuilder.getOrCreateInternalVariable(
1603 CGM.Int8PtrPtrTy, Twine(
CGM.getMangledName(VD)).concat(Suffix).str());
1610 if (
CGM.getLangOpts().OpenMPUseTLS &&
1611 CGM.getContext().getTargetInfo().isTLSSupported())
1615 llvm::Value *Args[] = {
1618 CGM.getSize(
CGM.GetTargetTypeStoreSize(VarTy)),
1623 CGM.getModule(), OMPRTL___kmpc_threadprivate_cached),
1635 CGM.getModule(), OMPRTL___kmpc_global_thread_num),
1639 llvm::Value *Args[] = {
1642 Ctor, CopyCtor, Dtor};
1645 CGM.getModule(), OMPRTL___kmpc_threadprivate_register),
1652 if (
CGM.getLangOpts().OpenMPUseTLS &&
1653 CGM.getContext().getTargetInfo().isTLSSupported())
1660 llvm::Value *Ctor =
nullptr, *CopyCtor =
nullptr, *Dtor =
nullptr;
1662 if (
CGM.getLangOpts().CPlusPlus && PerformInit) {
1667 CGM.getContext(),
nullptr, Loc,
1671 const auto &FI =
CGM.getTypes().arrangeBuiltinFunctionDeclaration(
1672 CGM.getContext().VoidPtrTy, Args);
1673 llvm::FunctionType *FTy =
CGM.getTypes().GetFunctionType(FI);
1674 std::string Name =
getName({
"__kmpc_global_ctor_",
""});
1675 llvm::Function *Fn =
1676 CGM.CreateGlobalInitOrCleanUpFunction(FTy, Name, FI, Loc);
1681 CGM.getContext().VoidPtrTy, Dst->getLocation());
1688 CGM.getContext().VoidPtrTy, Dst->getLocation());
1698 CGM.getContext(),
nullptr, Loc,
1702 const auto &FI =
CGM.getTypes().arrangeBuiltinFunctionDeclaration(
1703 CGM.getContext().VoidTy, Args);
1704 llvm::FunctionType *FTy =
CGM.getTypes().GetFunctionType(FI);
1705 std::string Name =
getName({
"__kmpc_global_dtor_",
""});
1706 llvm::Function *Fn =
1707 CGM.CreateGlobalInitOrCleanUpFunction(FTy, Name, FI, Loc);
1715 false,
CGM.getContext().VoidPtrTy, Dst->getLocation());
1730 CopyCtor = llvm::Constant::getNullValue(
CGM.DefaultPtrTy);
1731 if (Ctor ==
nullptr) {
1732 Ctor = llvm::Constant::getNullValue(
CGM.DefaultPtrTy);
1734 if (Dtor ==
nullptr) {
1735 Dtor = llvm::Constant::getNullValue(
CGM.DefaultPtrTy);
1738 auto *InitFunctionTy =
1739 llvm::FunctionType::get(
CGM.VoidTy,
false);
1740 std::string Name =
getName({
"__omp_threadprivate_init_",
""});
1741 llvm::Function *InitFunction =
CGM.CreateGlobalInitOrCleanUpFunction(
1742 InitFunctionTy, Name,
CGM.getTypes().arrangeNullaryFunction());
1746 CGM.getTypes().arrangeNullaryFunction(), ArgList,
1750 return InitFunction;
1758 llvm::GlobalValue *GV) {
1759 std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr =
1760 OMPDeclareTargetDeclAttr::getActiveAttr(FD);
1763 if (!ActiveAttr || !(*ActiveAttr)->getIndirect())
1770 OMPBuilder.OffloadInfoManager.getTargetRegionEntryFnName(Name, EntryInfo);
1776 llvm::GlobalValue *
Addr = GV;
1777 if (
CGM.getLangOpts().OpenMPIsTargetDevice) {
1778 llvm::PointerType *FnPtrTy = llvm::PointerType::get(
1779 CGM.getLLVMContext(),
1780 CGM.getModule().getDataLayout().getProgramAddressSpace());
1781 Addr =
new llvm::GlobalVariable(
1782 CGM.getModule(), FnPtrTy,
1783 true, llvm::GlobalValue::ExternalLinkage, GV, Name,
1784 nullptr, llvm::GlobalValue::NotThreadLocal,
1785 CGM.getModule().getDataLayout().getDefaultGlobalsAddressSpace());
1786 Addr->setVisibility(llvm::GlobalValue::ProtectedVisibility);
1793 OMPBuilder.OffloadInfoManager.registerDeviceGlobalVarEntryInfo(
1794 Name,
Addr,
CGM.GetTargetTypeStoreSize(
CGM.VoidPtrTy).getQuantity(),
1795 llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryIndirect,
1796 llvm::GlobalValue::WeakODRLinkage);
1809 llvm::OpenMPIRBuilder &
OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
1825 llvm::GlobalVariable *
Addr = VTable;
1827 OMPBuilder.OffloadInfoManager.getTargetRegionEntryFnName(AddrName, EntryInfo);
1828 AddrName.append(
"addr");
1830 if (
CGM.getLangOpts().OpenMPIsTargetDevice) {
1831 Addr =
new llvm::GlobalVariable(
1832 CGM.getModule(), VTable->getType(),
1833 true, llvm::GlobalValue::ExternalLinkage, VTable,
1835 nullptr, llvm::GlobalValue::NotThreadLocal,
1836 CGM.getModule().getDataLayout().getDefaultGlobalsAddressSpace());
1837 Addr->setVisibility(llvm::GlobalValue::ProtectedVisibility);
1839 OMPBuilder.OffloadInfoManager.registerDeviceGlobalVarEntryInfo(
1841 CGM.getDataLayout().getTypeAllocSize(VTable->getInitializer()->getType()),
1842 llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryIndirectVTable,
1843 llvm::GlobalValue::WeakODRLinkage);
1852 !
CGM.getOpenMPRuntime().VTableDeclMap.contains(
CXXRecord)) {
1853 auto Res =
CGM.getOpenMPRuntime().VTableDeclMap.try_emplace(
CXXRecord, VD);
1858 assert(VTablesAddr &&
"Expected non-null VTable address");
1860 if (VTablesAddr->hasExternalLinkage())
1861 VTablesAddr->setLinkage(llvm::GlobalValue::WeakODRLinkage);
1862 CGM.getOpenMPRuntime().registerVTableOffloadEntry(VTablesAddr, VD);
1880 auto GetVTableDecl = [](
const Expr *E) {
1891 if (
auto *DRE = dyn_cast<DeclRefExpr>(E)) {
1893 }
else if (
auto *MRE = dyn_cast<MemberExpr>(E)) {
1894 if (
auto *BaseDRE = dyn_cast<DeclRefExpr>(MRE->getBase())) {
1895 if (
auto *BaseVD = dyn_cast<VarDecl>(BaseDRE->getDecl()))
1899 return std::pair<CXXRecordDecl *, const VarDecl *>(
CXXRecord, VD);
1903 for (
const auto *E :
C->varlist()) {
1904 auto DeclPair = GetVTableDecl(E);
1906 if (DeclPair.second)
1915 std::string Suffix =
getName({
"artificial",
""});
1917 llvm::GlobalVariable *GAddr =
OMPBuilder.getOrCreateInternalVariable(
1918 VarLVType, Twine(Name).concat(Suffix).str());
1919 if (
CGM.getLangOpts().OpenMP &&
CGM.getLangOpts().OpenMPUseTLS &&
1920 CGM.getTarget().isTLSSupported()) {
1921 GAddr->setThreadLocal(
true);
1922 return Address(GAddr, GAddr->getValueType(),
1923 CGM.getContext().getTypeAlignInChars(VarType));
1925 std::string CacheSuffix =
getName({
"cache",
""});
1926 llvm::Value *Args[] = {
1934 Twine(Name).concat(Suffix).concat(CacheSuffix).str())};
1939 CGM.getModule(), OMPRTL___kmpc_threadprivate_cached),
1942 VarLVType,
CGM.getContext().getTypeAlignInChars(VarType));
1992 auto &M =
CGM.getModule();
1993 auto &&ThenGen = [&M, OutlinedFn, CapturedVars, RTLoc,
1996 llvm::Value *Args[] = {
1998 CGF.
Builder.getInt32(CapturedVars.size()),
2001 RealArgs.append(std::begin(Args), std::end(Args));
2002 RealArgs.append(CapturedVars.begin(), CapturedVars.end());
2004 llvm::FunctionCallee RTLFn =
2005 OMPBuilder.getOrCreateRuntimeFunction(M, OMPRTL___kmpc_fork_call);
2008 auto &&ElseGen = [&M, OutlinedFn, CapturedVars, RTLoc, Loc,
2014 llvm::Value *Args[] = {RTLoc, ThreadID};
2016 M, OMPRTL___kmpc_serialized_parallel),
2023 ".bound.zero.addr");
2028 OutlinedFnArgs.push_back(ZeroAddrBound.
getPointer());
2029 OutlinedFnArgs.append(CapturedVars.begin(), CapturedVars.end());
2037 OutlinedFn->removeFnAttr(llvm::Attribute::AlwaysInline);
2038 OutlinedFn->addFnAttr(llvm::Attribute::NoInline);
2044 M, OMPRTL___kmpc_end_serialized_parallel),
2063 if (
auto *OMPRegionInfo =
2065 if (OMPRegionInfo->getThreadIDVariable())
2066 return OMPRegionInfo->getThreadIDVariableLValue(CGF).getAddress();
2076 return ThreadIDTemp;
2080 std::string Prefix = Twine(
"gomp_critical_user_", CriticalName).str();
2081 std::string Name =
getName({Prefix,
"var"});
2082 llvm::GlobalVariable *GV =
2084 CGM.setDSOLocal(GV);
2091 llvm::FunctionCallee EnterCallee;
2093 llvm::FunctionCallee ExitCallee;
2096 llvm::BasicBlock *ContBlock =
nullptr;
2099 CommonActionTy(llvm::FunctionCallee EnterCallee,
2101 llvm::FunctionCallee ExitCallee,
2103 : EnterCallee(EnterCallee), EnterArgs(EnterArgs), ExitCallee(ExitCallee),
2108 llvm::Value *CallBool = CGF.
Builder.CreateIsNotNull(EnterRes);
2112 CGF.
Builder.CreateCondBr(CallBool, ThenBlock, ContBlock);
2116 void Done(CodeGenFunction &CGF) {
2121 void Exit(CodeGenFunction &CGF)
override {
2128 StringRef CriticalName,
2137 llvm::FunctionCallee RuntimeFcn =
OMPBuilder.getOrCreateRuntimeFunction(
2139 Hint ? OMPRTL___kmpc_critical_with_hint : OMPRTL___kmpc_critical);
2141 unsigned LockVarArgIdx = 2;
2143 RuntimeFcn.getFunctionType()
2144 ->getParamType(LockVarArgIdx)
2145 ->getPointerAddressSpace())
2147 LockVar, RuntimeFcn.getFunctionType()->getParamType(LockVarArgIdx));
2153 EnterArgs.push_back(CGF.
Builder.CreateIntCast(
2156 CommonActionTy Action(RuntimeFcn, EnterArgs,
2158 CGM.getModule(), OMPRTL___kmpc_end_critical),
2175 CommonActionTy Action(
OMPBuilder.getOrCreateRuntimeFunction(
2176 CGM.getModule(), OMPRTL___kmpc_master),
2179 CGM.getModule(), OMPRTL___kmpc_end_master),
2197 llvm::Value *FilterVal = Filter
2199 : llvm::ConstantInt::get(
CGM.Int32Ty, 0);
2204 CommonActionTy Action(
OMPBuilder.getOrCreateRuntimeFunction(
2205 CGM.getModule(), OMPRTL___kmpc_masked),
2208 CGM.getModule(), OMPRTL___kmpc_end_masked),
2224 llvm::Value *Args[] = {
2226 llvm::ConstantInt::get(
CGM.IntTy, 0,
true)};
2228 CGM.getModule(), OMPRTL___kmpc_omp_taskyield),
2232 if (
auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.
CapturedStmtInfo))
2233 Region->emitUntiedSwitch(CGF);
2246 CommonActionTy Action(
OMPBuilder.getOrCreateRuntimeFunction(
2247 CGM.getModule(), OMPRTL___kmpc_taskgroup),
2250 CGM.getModule(), OMPRTL___kmpc_end_taskgroup),
2259 unsigned Index,
const VarDecl *Var) {
2288 llvm::GlobalValue::InternalLinkage, Name,
2292 Fn->addFnAttr(
"sample-profile-suffix-elision-policy",
"selected");
2293 Fn->setDoesNotRecurse();
2310 for (
unsigned I = 0, E = AssignmentOps.size(); I < E; ++I) {
2311 const auto *DestVar =
2315 const auto *SrcVar =
2321 CGF.
EmitOMPCopy(
Type, DestAddr, SrcAddr, DestVar, SrcVar, AssignmentOps[I]);
2336 assert(CopyprivateVars.size() == SrcExprs.size() &&
2337 CopyprivateVars.size() == DstExprs.size() &&
2338 CopyprivateVars.size() == AssignmentOps.size());
2350 if (!CopyprivateVars.empty()) {
2353 C.getIntTypeForBitwidth(32, 1);
2359 CommonActionTy Action(
OMPBuilder.getOrCreateRuntimeFunction(
2360 CGM.getModule(), OMPRTL___kmpc_single),
2363 CGM.getModule(), OMPRTL___kmpc_end_single),
2376 llvm::APInt ArraySize(32, CopyprivateVars.size());
2377 QualType CopyprivateArrayTy =
C.getConstantArrayType(
2382 CopyprivateArrayTy,
".omp.copyprivate.cpr_list");
2383 for (
unsigned I = 0, E = CopyprivateVars.size(); I < E; ++I) {
2395 SrcExprs, DstExprs, AssignmentOps, Loc);
2396 llvm::Value *BufSize = CGF.
getTypeSize(CopyprivateArrayTy);
2400 llvm::Value *Args[] = {
2404 CL.emitRawPointer(CGF),
2409 CGM.getModule(), OMPRTL___kmpc_copyprivate),
2425 CommonActionTy Action(
OMPBuilder.getOrCreateRuntimeFunction(
2426 CGM.getModule(), OMPRTL___kmpc_ordered),
2429 CGM.getModule(), OMPRTL___kmpc_end_ordered),
2440 if (Kind == OMPD_for)
2441 Flags = OMP_IDENT_BARRIER_IMPL_FOR;
2442 else if (Kind == OMPD_sections)
2443 Flags = OMP_IDENT_BARRIER_IMPL_SECTIONS;
2444 else if (Kind == OMPD_single)
2445 Flags = OMP_IDENT_BARRIER_IMPL_SINGLE;
2446 else if (Kind == OMPD_barrier)
2447 Flags = OMP_IDENT_BARRIER_EXPL;
2449 Flags = OMP_IDENT_BARRIER_IMPL;
2459 S.getClausesOfKind<OMPOrderedClause>(),
2460 [](
const OMPOrderedClause *
C) { return C->getNumForLoops(); })) {
2461 ScheduleKind = OMPC_SCHEDULE_static;
2463 llvm::APInt ChunkSize(32, 1);
2473 bool ForceSimpleCall) {
2475 auto *OMPRegionInfo =
2478 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
2481 CGF.
Builder.restoreIP(AfterIP);
2494 if (OMPRegionInfo) {
2495 if (!ForceSimpleCall && OMPRegionInfo->hasCancel()) {
2498 OMPRTL___kmpc_cancel_barrier),
2507 CGF.
Builder.CreateCondBr(
Cmp, ExitBB, ContBB);
2519 CGM.getModule(), OMPRTL___kmpc_barrier),
2524 Expr *ME,
bool IsFatal) {
2526 : llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
2529 llvm::Value *Args[] = {
2531 llvm::ConstantInt::get(
CGM.Int32Ty, IsFatal ? 2 : 1),
2532 CGF.
Builder.CreatePointerCast(MVL,
CGM.Int8PtrTy)};
2534 CGM.getModule(), OMPRTL___kmpc_error),
2540 bool Chunked,
bool Ordered) {
2541 switch (ScheduleKind) {
2542 case OMPC_SCHEDULE_static:
2543 return Chunked ? (Ordered ? OMP_ord_static_chunked : OMP_sch_static_chunked)
2544 : (Ordered ? OMP_ord_static : OMP_sch_static);
2545 case OMPC_SCHEDULE_dynamic:
2546 return Ordered ? OMP_ord_dynamic_chunked : OMP_sch_dynamic_chunked;
2547 case OMPC_SCHEDULE_guided:
2548 return Ordered ? OMP_ord_guided_chunked : OMP_sch_guided_chunked;
2549 case OMPC_SCHEDULE_runtime:
2550 return Ordered ? OMP_ord_runtime : OMP_sch_runtime;
2551 case OMPC_SCHEDULE_auto:
2552 return Ordered ? OMP_ord_auto : OMP_sch_auto;
2554 assert(!Chunked &&
"chunk was specified but schedule kind not known");
2555 return Ordered ? OMP_ord_static : OMP_sch_static;
2557 llvm_unreachable(
"Unexpected runtime schedule");
2561static OpenMPSchedType
2564 return Chunked ? OMP_dist_sch_static_chunked : OMP_dist_sch_static;
2568 bool Chunked)
const {
2569 OpenMPSchedType Schedule =
2571 return Schedule == OMP_sch_static;
2577 return Schedule == OMP_dist_sch_static;
2581 bool Chunked)
const {
2582 OpenMPSchedType Schedule =
2584 return Schedule == OMP_sch_static_chunked;
2590 return Schedule == OMP_dist_sch_static_chunked;
2594 OpenMPSchedType Schedule =
2596 assert(Schedule != OMP_sch_static_chunked &&
"cannot be chunked here");
2597 return Schedule != OMP_sch_static;
2605 case OMPC_SCHEDULE_MODIFIER_monotonic:
2606 Modifier = OMP_sch_modifier_monotonic;
2608 case OMPC_SCHEDULE_MODIFIER_nonmonotonic:
2609 Modifier = OMP_sch_modifier_nonmonotonic;
2611 case OMPC_SCHEDULE_MODIFIER_simd:
2612 if (Schedule == OMP_sch_static_chunked)
2613 Schedule = OMP_sch_static_balanced_chunked;
2620 case OMPC_SCHEDULE_MODIFIER_monotonic:
2621 Modifier = OMP_sch_modifier_monotonic;
2623 case OMPC_SCHEDULE_MODIFIER_nonmonotonic:
2624 Modifier = OMP_sch_modifier_nonmonotonic;
2626 case OMPC_SCHEDULE_MODIFIER_simd:
2627 if (Schedule == OMP_sch_static_chunked)
2628 Schedule = OMP_sch_static_balanced_chunked;
2640 if (CGM.
getLangOpts().OpenMP >= 50 && Modifier == 0) {
2641 if (!(Schedule == OMP_sch_static_chunked || Schedule == OMP_sch_static ||
2642 Schedule == OMP_sch_static_balanced_chunked ||
2643 Schedule == OMP_ord_static_chunked || Schedule == OMP_ord_static ||
2644 Schedule == OMP_dist_sch_static_chunked ||
2645 Schedule == OMP_dist_sch_static ||
2646 Schedule == OMP_dist_sch_static_chunked_sch_static_chunkone))
2647 Modifier = OMP_sch_modifier_nonmonotonic;
2649 return Schedule | Modifier;
2659 ScheduleKind.
Schedule, DispatchValues.
Chunk !=
nullptr, Ordered);
2661 (Schedule != OMP_sch_static && Schedule != OMP_sch_static_chunked &&
2662 Schedule != OMP_ord_static && Schedule != OMP_ord_static_chunked &&
2663 Schedule != OMP_sch_static_balanced_chunked));
2670 llvm::Value *Chunk = DispatchValues.
Chunk ? DispatchValues.
Chunk
2671 : CGF.
Builder.getIntN(IVSize, 1);
2672 llvm::Value *Args[] = {
2676 CGM, Schedule, ScheduleKind.
M1, ScheduleKind.
M2)),
2679 CGF.
Builder.getIntN(IVSize, 1),
2696 CodeGenFunction &CGF, llvm::Value *UpdateLocation, llvm::Value *ThreadId,
2697 llvm::FunctionCallee ForStaticInitFunction, OpenMPSchedType Schedule,
2704 assert(Schedule == OMP_sch_static || Schedule == OMP_sch_static_chunked ||
2705 Schedule == OMP_sch_static_balanced_chunked ||
2706 Schedule == OMP_ord_static || Schedule == OMP_ord_static_chunked ||
2707 Schedule == OMP_dist_sch_static ||
2708 Schedule == OMP_dist_sch_static_chunked ||
2709 Schedule == OMP_dist_sch_static_chunked_sch_static_chunkone);
2716 llvm::Value *Chunk = Values.
Chunk;
2717 if (Chunk ==
nullptr) {
2718 assert((Schedule == OMP_sch_static || Schedule == OMP_ord_static ||
2719 Schedule == OMP_dist_sch_static) &&
2720 "expected static non-chunked schedule");
2724 assert((Schedule == OMP_sch_static_chunked ||
2725 Schedule == OMP_sch_static_balanced_chunked ||
2726 Schedule == OMP_ord_static_chunked ||
2727 Schedule == OMP_dist_sch_static_chunked ||
2728 Schedule == OMP_dist_sch_static_chunked_sch_static_chunkone) &&
2729 "expected static chunked schedule");
2731 llvm::Value *Args[] = {
2751 OpenMPSchedType ScheduleNum =
2753 ? OMP_dist_sch_static_chunked_sch_static_chunkone
2757 "Expected loop-based or sections-based directive.");
2760 ? OMP_IDENT_WORK_LOOP
2761 : OMP_IDENT_WORK_SECTIONS);
2763 llvm::FunctionCallee StaticInitFunction =
2768 ScheduleNum, ScheduleKind.
M1, ScheduleKind.
M2, Values);
2775 OpenMPSchedType ScheduleNum =
2777 llvm::Value *UpdatedLocation =
2780 llvm::FunctionCallee StaticInitFunction;
2781 bool isGPUDistribute =
2782 CGM.getLangOpts().OpenMPIsTargetDevice &&
CGM.getTriple().isGPU();
2783 StaticInitFunction =
OMPBuilder.createForStaticInitFunction(
2794 assert((DKind == OMPD_distribute || DKind == OMPD_for ||
2795 DKind == OMPD_sections) &&
2796 "Expected distribute, for, or sections directive kind");
2800 llvm::Value *Args[] = {
2803 (DKind == OMPD_target_teams_loop)
2804 ? OMP_IDENT_WORK_DISTRIBUTE
2806 ? OMP_IDENT_WORK_LOOP
2807 : OMP_IDENT_WORK_SECTIONS),
2811 CGM.getLangOpts().OpenMPIsTargetDevice &&
CGM.getTriple().isGPU())
2814 CGM.getModule(), OMPRTL___kmpc_distribute_static_fini),
2818 CGM.getModule(), OMPRTL___kmpc_for_static_fini),
2843 llvm::Value *Args[] = {
2851 OMPBuilder.createDispatchNextFunction(IVSize, IVSigned), Args);
2858 const Expr *Message,
2861 return llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
2870 return llvm::ConstantInt::get(
CGM.Int32Ty,
2871 Severity == OMPC_SEVERITY_warning ? 1 : 2);
2887 RuntimeFunction FnID = OMPRTL___kmpc_push_num_threads;
2888 if (Modifier == OMPC_NUMTHREADS_strict) {
2889 FnID = OMPRTL___kmpc_push_num_threads_strict;
2894 OMPBuilder.getOrCreateRuntimeFunction(
CGM.getModule(), FnID), Args);
2898 ProcBindKind ProcBind,
2902 assert(ProcBind != OMP_PROC_BIND_unknown &&
"Unsupported proc_bind value.");
2904 llvm::Value *Args[] = {
2906 llvm::ConstantInt::get(
CGM.IntTy,
unsigned(ProcBind),
true)};
2908 CGM.getModule(), OMPRTL___kmpc_push_proc_bind),
2921 CGM.getModule(), OMPRTL___kmpc_flush),
2928enum KmpTaskTFields {
2955 if (
CGM.getLangOpts().OpenMPSimd ||
OMPBuilder.OffloadInfoManager.empty())
2958 llvm::OpenMPIRBuilder::EmitMetadataErrorReportFunctionTy &&ErrorReportFn =
2959 [
this](llvm::OpenMPIRBuilder::EmitMetadataErrorKind Kind,
2960 const llvm::TargetRegionEntryInfo &EntryInfo) ->
void {
2962 if (Kind != llvm::OpenMPIRBuilder::EMIT_MD_GLOBAL_VAR_LINK_ERROR) {
2963 for (
auto I =
CGM.getContext().getSourceManager().fileinfo_begin(),
2964 E =
CGM.getContext().getSourceManager().fileinfo_end();
2966 if (I->getFirst().getUniqueID().getDevice() == EntryInfo.DeviceID &&
2967 I->getFirst().getUniqueID().getFile() == EntryInfo.FileID) {
2968 Loc =
CGM.getContext().getSourceManager().translateFileLineCol(
2969 I->getFirst(), EntryInfo.Line, 1);
2975 case llvm::OpenMPIRBuilder::EMIT_MD_TARGET_REGION_ERROR: {
2976 CGM.getDiags().Report(Loc,
2977 diag::err_target_region_offloading_entry_incorrect)
2978 << EntryInfo.ParentName;
2980 case llvm::OpenMPIRBuilder::EMIT_MD_DECLARE_TARGET_ERROR: {
2981 CGM.getDiags().Report(
2982 Loc, diag::err_target_var_offloading_entry_incorrect_with_parent)
2983 << EntryInfo.ParentName;
2985 case llvm::OpenMPIRBuilder::EMIT_MD_GLOBAL_VAR_LINK_ERROR: {
2986 CGM.getDiags().Report(diag::err_target_var_offloading_entry_incorrect);
2988 case llvm::OpenMPIRBuilder::EMIT_MD_GLOBAL_VAR_INDIRECT_ERROR: {
2989 unsigned DiagID =
CGM.getDiags().getCustomDiagID(
2991 "target variable is incorrect: the "
2992 "address is invalid.");
2993 CGM.getDiags().Report(DiagID);
2998 OMPBuilder.createOffloadEntriesAndInfoMetadata(ErrorReportFn);
3005 QualType KmpRoutineEntryTyArgs[] = {KmpInt32Ty,
C.VoidPtrTy};
3008 C.getFunctionType(KmpInt32Ty, KmpRoutineEntryTyArgs, EPI));
3014struct PrivateHelpersTy {
3015 PrivateHelpersTy(
const Expr *OriginalRef,
const VarDecl *Original,
3017 : OriginalRef(OriginalRef), Original(Original), PrivateCopy(PrivateCopy),
3018 PrivateElemInit(PrivateElemInit) {}
3019 PrivateHelpersTy(
const VarDecl *Original) : Original(Original) {}
3020 const Expr *OriginalRef =
nullptr;
3021 const VarDecl *Original =
nullptr;
3022 const VarDecl *PrivateCopy =
nullptr;
3023 const VarDecl *PrivateElemInit =
nullptr;
3024 bool isLocalPrivate()
const {
3025 return !OriginalRef && !PrivateCopy && !PrivateElemInit;
3028typedef std::pair<CharUnits , PrivateHelpersTy> PrivateDataTy;
3033 if (!CVD->
hasAttr<OMPAllocateDeclAttr>())
3035 const auto *AA = CVD->
getAttr<OMPAllocateDeclAttr>();
3037 return !(AA->getAllocatorType() == OMPAllocateDeclAttr::OMPDefaultMemAlloc &&
3038 !AA->getAllocator());
3048 RecordDecl *RD =
C.buildImplicitRecord(
".kmp_privates.t");
3050 for (
const auto &Pair :
Privates) {
3051 const VarDecl *VD = Pair.second.Original;
3055 if (Pair.second.isLocalPrivate()) {
3078 QualType KmpRoutineEntryPointerQTy) {
3098 CanQualType KmpCmplrdataTy =
C.getCanonicalTagType(UD);
3099 RecordDecl *RD =
C.buildImplicitRecord(
"kmp_task_t");
3129 RecordDecl *RD =
C.buildImplicitRecord(
"kmp_task_t_with_privates");
3149static llvm::Function *
3152 QualType KmpTaskTWithPrivatesPtrQTy,
3154 QualType SharedsPtrTy, llvm::Function *TaskFunction,
3155 llvm::Value *TaskPrivatesMap) {
3161 C,
nullptr, Loc,
nullptr,
3164 const auto &TaskEntryFnInfo =
3166 llvm::FunctionType *TaskEntryTy =
3169 auto *TaskEntry = llvm::Function::Create(
3170 TaskEntryTy, llvm::GlobalValue::InternalLinkage, Name, &CGM.
getModule());
3173 TaskEntry->addFnAttr(
"sample-profile-suffix-elision-policy",
"selected");
3174 TaskEntry->setDoesNotRecurse();
3189 const auto *KmpTaskTWithPrivatesQTyRD =
3194 auto PartIdFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTPartId);
3196 llvm::Value *PartidParam = PartIdLVal.getPointer(CGF);
3198 auto SharedsFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTShareds);
3204 auto PrivatesFI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin(), 1);
3205 llvm::Value *PrivatesParam;
3206 if (PrivatesFI != KmpTaskTWithPrivatesQTyRD->field_end()) {
3209 PrivatesLVal.getPointer(CGF), CGF.
VoidPtrTy);
3211 PrivatesParam = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
3214 llvm::Value *CommonArgs[] = {
3215 GtidParam, PartidParam, PrivatesParam, TaskPrivatesMap,
3221 std::end(CommonArgs));
3223 auto LBFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound);
3226 auto UBFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound);
3229 auto StFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTStride);
3232 auto LIFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLastIter);
3235 auto RFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTReductions);
3238 CallArgs.push_back(LBParam);
3239 CallArgs.push_back(UBParam);
3240 CallArgs.push_back(StParam);
3241 CallArgs.push_back(LIParam);
3242 CallArgs.push_back(RParam);
3244 CallArgs.push_back(SharedsParam);
3257 QualType KmpTaskTWithPrivatesPtrQTy,
3258 QualType KmpTaskTWithPrivatesQTy) {
3264 C,
nullptr, Loc,
nullptr,
3267 const auto &DestructorFnInfo =
3269 llvm::FunctionType *DestructorFnTy =
3273 auto *DestructorFn =
3274 llvm::Function::Create(DestructorFnTy, llvm::GlobalValue::InternalLinkage,
3279 DestructorFn->addFnAttr(
"sample-profile-suffix-elision-policy",
"selected");
3280 DestructorFn->setDoesNotRecurse();
3288 const auto *KmpTaskTWithPrivatesQTyRD =
3290 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin());
3292 for (
const auto *Field : FI->getType()->castAsRecordDecl()->fields()) {
3294 Field->getType().isDestructedType()) {
3296 CGF.
pushDestroy(DtorKind, FieldLValue.getAddress(), Field->getType());
3300 return DestructorFn;
3320 C,
nullptr, Loc,
nullptr,
3321 C.getPointerType(PrivatesQTy).withConst().withRestrict(),
3323 Args.push_back(TaskPrivatesArg);
3324 llvm::DenseMap<CanonicalDeclPtr<const VarDecl>,
unsigned> PrivateVarsPos;
3325 unsigned Counter = 1;
3326 for (
const Expr *E :
Data.PrivateVars) {
3328 C,
nullptr, Loc,
nullptr,
3329 C.getPointerType(
C.getPointerType(E->
getType()))
3334 PrivateVarsPos[VD] = Counter;
3337 for (
const Expr *E :
Data.FirstprivateVars) {
3339 C,
nullptr, Loc,
nullptr,
3340 C.getPointerType(
C.getPointerType(E->
getType()))
3345 PrivateVarsPos[VD] = Counter;
3348 for (
const Expr *E :
Data.LastprivateVars) {
3350 C,
nullptr, Loc,
nullptr,
3351 C.getPointerType(
C.getPointerType(E->
getType()))
3356 PrivateVarsPos[VD] = Counter;
3362 Ty =
C.getPointerType(Ty);
3364 Ty =
C.getPointerType(Ty);
3366 C,
nullptr, Loc,
nullptr,
3367 C.getPointerType(
C.getPointerType(Ty)).withConst().withRestrict(),
3369 PrivateVarsPos[VD] = Counter;
3372 const auto &TaskPrivatesMapFnInfo =
3374 llvm::FunctionType *TaskPrivatesMapTy =
3378 auto *TaskPrivatesMap = llvm::Function::Create(
3379 TaskPrivatesMapTy, llvm::GlobalValue::InternalLinkage, Name,
3382 TaskPrivatesMapFnInfo);
3384 TaskPrivatesMap->addFnAttr(
"sample-profile-suffix-elision-policy",
3387 TaskPrivatesMap->removeFnAttr(llvm::Attribute::NoInline);
3388 TaskPrivatesMap->removeFnAttr(llvm::Attribute::OptimizeNone);
3389 TaskPrivatesMap->addFnAttr(llvm::Attribute::AlwaysInline);
3393 TaskPrivatesMapFnInfo, Args, Loc, Loc);
3401 for (
const FieldDecl *Field : PrivatesQTyRD->fields()) {
3403 const VarDecl *VD = Args[PrivateVarsPos[
Privates[Counter].second.Original]];
3407 RefLVal.getAddress(), RefLVal.getType()->castAs<
PointerType>());
3412 return TaskPrivatesMap;
3418 Address KmpTaskSharedsPtr, LValue TDBase,
3424 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->
field_begin());
3438 if ((!IsTargetTask && !
Data.FirstprivateVars.empty() && ForDup) ||
3439 (IsTargetTask && KmpTaskSharedsPtr.
isValid())) {
3446 FI = FI->getType()->castAsRecordDecl()->field_begin();
3447 for (
const PrivateDataTy &Pair :
Privates) {
3449 if (Pair.second.isLocalPrivate()) {
3453 const VarDecl *VD = Pair.second.PrivateCopy;
3458 if (
const VarDecl *Elem = Pair.second.PrivateElemInit) {
3459 const VarDecl *OriginalVD = Pair.second.Original;
3462 LValue SharedRefLValue;
3465 if (IsTargetTask && !SharedField) {
3469 ->getNumParams() == 0 &&
3472 ->getDeclContext()) &&
3473 "Expected artificial target data variable.");
3476 }
else if (ForDup) {
3479 SharedRefLValue.getAddress().withAlignment(
3480 C.getDeclAlign(OriginalVD)),
3482 SharedRefLValue.getTBAAInfo());
3484 Pair.second.Original->getCanonicalDecl()) > 0 ||
3486 SharedRefLValue = CGF.
EmitLValue(Pair.second.OriginalRef);
3489 InlinedOpenMPRegionRAII Region(
3492 SharedRefLValue = CGF.
EmitLValue(Pair.second.OriginalRef);
3503 PrivateLValue.getAddress(), SharedRefLValue.getAddress(),
Type,
3504 [&CGF, Elem,
Init, &CapturesInfo](
Address DestElement,
3507 CodeGenFunction::OMPPrivateScope InitScope(CGF);
3508 InitScope.addPrivate(Elem, SrcElement);
3509 (void)InitScope.Privatize();
3511 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(
3512 CGF, &CapturesInfo);
3513 CGF.EmitAnyExprToMem(Init, DestElement,
3514 Init->getType().getQualifiers(),
3520 InitScope.addPrivate(Elem, SharedRefLValue.getAddress());
3521 (void)InitScope.Privatize();
3537 bool InitRequired =
false;
3538 for (
const PrivateDataTy &Pair :
Privates) {
3539 if (Pair.second.isLocalPrivate())
3541 const VarDecl *VD = Pair.second.PrivateCopy;
3543 InitRequired = InitRequired || (isa_and_nonnull<CXXConstructExpr>(
Init) &&
3548 return InitRequired;
3565 QualType KmpTaskTWithPrivatesPtrQTy,
3572 C,
nullptr, Loc,
nullptr, KmpTaskTWithPrivatesPtrQTy,
3575 C,
nullptr, Loc,
nullptr, KmpTaskTWithPrivatesPtrQTy,
3581 const auto &TaskDupFnInfo =
3585 auto *TaskDup = llvm::Function::Create(
3586 TaskDupTy, llvm::GlobalValue::InternalLinkage, Name, &CGM.
getModule());
3589 TaskDup->addFnAttr(
"sample-profile-suffix-elision-policy",
"selected");
3590 TaskDup->setDoesNotRecurse();
3600 auto LIFI = std::next(KmpTaskTQTyRD->
field_begin(), KmpTaskTLastIter);
3602 TDBase, *KmpTaskTWithPrivatesQTyRD->
field_begin());
3612 if (!
Data.FirstprivateVars.empty()) {
3617 TDBase, *KmpTaskTWithPrivatesQTyRD->
field_begin());
3625 emitPrivatesInit(CGF, D, KmpTaskSharedsPtr, TDBase, KmpTaskTWithPrivatesQTyRD,
3636 for (
const PrivateDataTy &P :
Privates) {
3637 if (P.second.isLocalPrivate())
3639 QualType Ty = P.second.Original->getType().getNonReferenceType();
3648class OMPIteratorGeneratorScope final
3650 CodeGenFunction &CGF;
3651 const OMPIteratorExpr *E =
nullptr;
3652 SmallVector<CodeGenFunction::JumpDest, 4> ContDests;
3653 SmallVector<CodeGenFunction::JumpDest, 4> ExitDests;
3654 OMPIteratorGeneratorScope() =
delete;
3655 OMPIteratorGeneratorScope(OMPIteratorGeneratorScope &) =
delete;
3658 OMPIteratorGeneratorScope(CodeGenFunction &CGF,
const OMPIteratorExpr *E)
3659 : CodeGenFunction::OMPPrivateScope(CGF), CGF(CGF), E(E) {
3662 SmallVector<llvm::Value *, 4> Uppers;
3664 Uppers.push_back(CGF.EmitScalarExpr(E->getHelper(I).Upper));
3665 const auto *VD = cast<VarDecl>(E->getIteratorDecl(I));
3666 addPrivate(VD, CGF.CreateMemTemp(VD->getType(), VD->getName()));
3667 const OMPIteratorHelperData &HelperData = E->getHelper(I);
3669 HelperData.CounterVD,
3670 CGF.CreateMemTemp(HelperData.CounterVD->getType(),
"counter.addr"));
3675 const OMPIteratorHelperData &HelperData = E->getHelper(I);
3677 CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(HelperData.CounterVD),
3678 HelperData.CounterVD->getType());
3680 CGF.EmitStoreOfScalar(
3681 llvm::ConstantInt::get(CLVal.getAddress().getElementType(), 0),
3683 CodeGenFunction::JumpDest &ContDest =
3684 ContDests.emplace_back(CGF.getJumpDestInCurrentScope(
"iter.cont"));
3685 CodeGenFunction::JumpDest &ExitDest =
3686 ExitDests.emplace_back(CGF.getJumpDestInCurrentScope(
"iter.exit"));
3688 llvm::Value *N = Uppers[I];
3691 CGF.EmitBlock(ContDest.getBlock());
3693 CGF.EmitLoadOfScalar(CLVal, HelperData.CounterVD->getLocation());
3695 HelperData.CounterVD->getType()->isSignedIntegerOrEnumerationType()
3696 ? CGF.Builder.CreateICmpSLT(CVal, N)
3697 : CGF.Builder.CreateICmpULT(CVal, N);
3698 llvm::BasicBlock *BodyBB = CGF.createBasicBlock(
"iter.body");
3699 CGF.Builder.CreateCondBr(Cmp, BodyBB, ExitDest.getBlock());
3701 CGF.EmitBlock(BodyBB);
3703 CGF.EmitIgnoredExpr(HelperData.Update);
3706 ~OMPIteratorGeneratorScope() {
3711 const OMPIteratorHelperData &HelperData = E->
getHelper(I - 1);
3716 CGF.
EmitBlock(ExitDests[I - 1].getBlock(), I == 1);
3722static std::pair<llvm::Value *, llvm::Value *>
3724 const auto *OASE = dyn_cast<OMPArrayShapingExpr>(E);
3727 const Expr *
Base = OASE->getBase();
3732 llvm::Value *SizeVal;
3735 SizeVal = CGF.
getTypeSize(OASE->getBase()->getType()->getPointeeType());
3736 for (
const Expr *SE : OASE->getDimensions()) {
3740 SizeVal = CGF.
Builder.CreateNUWMul(SizeVal, Sz);
3742 }
else if (
const auto *ASE =
3745 Address UpAddrAddress = UpAddrLVal.getAddress();
3746 llvm::Value *UpAddr = CGF.
Builder.CreateConstGEP1_32(
3749 SizeVal = CGF.
Builder.CreatePtrDiff(UpAddr,
Addr,
"",
true);
3753 return std::make_pair(
Addr, SizeVal);
3758 QualType FlagsTy =
C.getIntTypeForBitwidth(32,
false);
3759 if (KmpTaskAffinityInfoTy.
isNull()) {
3761 C.buildImplicitRecord(
"kmp_task_affinity_info_t");
3767 KmpTaskAffinityInfoTy =
C.getCanonicalTagType(KmpAffinityInfoRD);
3774 llvm::Function *TaskFunction,
QualType SharedsTy,
3779 const auto *I =
Data.PrivateCopies.begin();
3780 for (
const Expr *E :
Data.PrivateVars) {
3788 I =
Data.FirstprivateCopies.begin();
3789 const auto *IElemInitRef =
Data.FirstprivateInits.begin();
3790 for (
const Expr *E :
Data.FirstprivateVars) {
3800 I =
Data.LastprivateCopies.begin();
3801 for (
const Expr *E :
Data.LastprivateVars) {
3811 Privates.emplace_back(
CGM.getPointerAlign(), PrivateHelpersTy(VD));
3813 Privates.emplace_back(
C.getDeclAlign(VD), PrivateHelpersTy(VD));
3816 [](
const PrivateDataTy &L,
const PrivateDataTy &R) {
3817 return L.first > R.first;
3819 QualType KmpInt32Ty =
C.getIntTypeForBitwidth(32, 1);
3830 assert((D.getDirectiveKind() == OMPD_task ||
3833 "Expected taskloop, task or target directive");
3840 const auto *KmpTaskTQTyRD =
KmpTaskTQTy->castAsRecordDecl();
3842 const RecordDecl *KmpTaskTWithPrivatesQTyRD =
3845 C.getCanonicalTagType(KmpTaskTWithPrivatesQTyRD);
3846 QualType KmpTaskTWithPrivatesPtrQTy =
3847 C.getPointerType(KmpTaskTWithPrivatesQTy);
3848 llvm::Type *KmpTaskTWithPrivatesPtrTy = CGF.
Builder.getPtrTy(0);
3849 llvm::Value *KmpTaskTWithPrivatesTySize =
3851 QualType SharedsPtrTy =
C.getPointerType(SharedsTy);
3854 llvm::Value *TaskPrivatesMap =
nullptr;
3855 llvm::Type *TaskPrivatesMapTy =
3856 std::next(TaskFunction->arg_begin(), 3)->getType();
3858 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->
field_begin());
3862 TaskPrivatesMap, TaskPrivatesMapTy);
3864 TaskPrivatesMap = llvm::ConstantPointerNull::get(
3870 CGM, Loc, D.getDirectiveKind(), KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy,
3871 KmpTaskTWithPrivatesQTy,
KmpTaskTQTy, SharedsPtrTy, TaskFunction,
3883 DestructorsFlag = 0x8,
3884 PriorityFlag = 0x20,
3885 DetachableFlag = 0x40,
3886 FreeAgentFlag = 0x80,
3887 TransparentFlag = 0x100,
3889 unsigned Flags =
Data.Tied ? TiedFlag : 0;
3890 bool NeedsCleanup =
false;
3895 Flags = Flags | DestructorsFlag;
3899 if (Kind == OMPC_THREADSET_omp_pool)
3900 Flags = Flags | FreeAgentFlag;
3902 if (D.getSingleClause<OMPTransparentClause>())
3903 Flags |= TransparentFlag;
3905 if (
Data.Priority.getInt())
3906 Flags = Flags | PriorityFlag;
3908 Flags = Flags | DetachableFlag;
3909 llvm::Value *TaskFlags =
3910 Data.Final.getPointer()
3911 ? CGF.
Builder.CreateSelect(
Data.Final.getPointer(),
3912 CGF.
Builder.getInt32(FinalFlag),
3914 : CGF.
Builder.getInt32(
Data.Final.getInt() ? FinalFlag : 0);
3915 TaskFlags = CGF.
Builder.CreateOr(TaskFlags, CGF.
Builder.getInt32(Flags));
3916 llvm::Value *SharedsSize =
CGM.getSize(
C.getTypeSizeInChars(SharedsTy));
3918 getThreadID(CGF, Loc), TaskFlags, KmpTaskTWithPrivatesTySize,
3921 llvm::Value *NewTask;
3922 if (D.hasClausesOfKind<OMPNowaitClause>()) {
3928 llvm::Value *DeviceID;
3933 DeviceID = CGF.
Builder.getInt64(OMP_DEVICEID_UNDEF);
3934 AllocArgs.push_back(DeviceID);
3937 CGM.getModule(), OMPRTL___kmpc_omp_target_task_alloc),
3942 CGM.getModule(), OMPRTL___kmpc_omp_task_alloc),
3955 llvm::Value *Tid =
getThreadID(CGF, DC->getBeginLoc());
3956 Tid = CGF.
Builder.CreateIntCast(Tid, CGF.
IntTy,
false);
3959 CGM.getModule(), OMPRTL___kmpc_task_allow_completion_event),
3960 {Loc, Tid, NewTask});
3971 llvm::Value *NumOfElements =
nullptr;
3972 unsigned NumAffinities = 0;
3974 if (
const Expr *Modifier =
C->getModifier()) {
3976 for (
unsigned I = 0, E = IE->numOfIterators(); I < E; ++I) {
3980 NumOfElements ? CGF.
Builder.CreateNUWMul(NumOfElements, Sz) : Sz;
3983 NumAffinities +=
C->varlist_size();
3988 enum RTLAffinityInfoFieldsTy { BaseAddr, Len, Flags };
3990 QualType KmpTaskAffinityInfoArrayTy;
3991 if (NumOfElements) {
3992 NumOfElements = CGF.
Builder.CreateNUWAdd(
3993 llvm::ConstantInt::get(CGF.
SizeTy, NumAffinities), NumOfElements);
3996 C.getIntTypeForBitwidth(
C.getTypeSize(
C.getSizeType()), 0),
4000 KmpTaskAffinityInfoArrayTy =
C.getVariableArrayType(
4008 NumOfElements = CGF.
Builder.CreateIntCast(NumOfElements, CGF.
Int32Ty,
4011 KmpTaskAffinityInfoArrayTy =
C.getConstantArrayType(
4013 llvm::APInt(
C.getTypeSize(
C.getSizeType()), NumAffinities),
nullptr,
4018 NumOfElements = llvm::ConstantInt::get(
CGM.Int32Ty, NumAffinities,
4025 bool HasIterator =
false;
4027 if (
C->getModifier()) {
4031 for (
const Expr *E :
C->varlist()) {
4040 Base, *std::next(KmpAffinityInfoRD->field_begin(), BaseAddr));
4045 Base, *std::next(KmpAffinityInfoRD->field_begin(), Len));
4059 const Expr *Modifier =
C->getModifier();
4062 OMPIteratorGeneratorScope IteratorScope(
4064 for (
const Expr *E :
C->varlist()) {
4074 Base, *std::next(KmpAffinityInfoRD->field_begin(), BaseAddr));
4079 Base, *std::next(KmpAffinityInfoRD->field_begin(), Len));
4081 Idx = CGF.
Builder.CreateNUWAdd(
4082 Idx, llvm::ConstantInt::get(Idx->getType(), 1));
4097 CGM.getModule(), OMPRTL___kmpc_omp_reg_task_with_affinity),
4098 {LocRef, GTid, NewTask, NumOfElements, AffinListPtr});
4100 llvm::Value *NewTaskNewTaskTTy =
4102 NewTask, KmpTaskTWithPrivatesPtrTy);
4104 KmpTaskTWithPrivatesQTy);
4115 *std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTShareds)),
4117 CGF.
Int8Ty,
CGM.getNaturalTypeAlignment(SharedsTy));
4131 CGM, Loc, D, KmpTaskTWithPrivatesPtrQTy, KmpTaskTWithPrivatesQTyRD,
4132 KmpTaskTQTyRD, SharedsTy, SharedsPtrTy,
Data,
Privates,
4133 !
Data.LastprivateVars.empty());
4137 enum { Priority = 0, Destructors = 1 };
4139 auto FI = std::next(KmpTaskTQTyRD->field_begin(), Data1);
4140 const auto *KmpCmplrdataUD = (*FI)->getType()->castAsRecordDecl();
4141 assert(KmpCmplrdataUD->isUnion());
4144 CGM, Loc, KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy,
4145 KmpTaskTWithPrivatesQTy);
4148 Data1LV, *std::next(KmpCmplrdataUD->field_begin(), Destructors));
4154 if (
Data.Priority.getInt()) {
4156 TDBase, *std::next(KmpTaskTQTyRD->field_begin(), Data2));
4158 Data2LV, *std::next(KmpCmplrdataUD->field_begin(), Priority));
4161 Result.NewTask = NewTask;
4162 Result.TaskEntry = TaskEntry;
4163 Result.NewTaskNewTaskTTy = NewTaskNewTaskTTy;
4165 Result.KmpTaskTQTyRD = KmpTaskTQTyRD;
4171 RTLDependenceKindTy DepKind;
4173 case OMPC_DEPEND_in:
4174 DepKind = RTLDependenceKindTy::DepIn;
4177 case OMPC_DEPEND_out:
4178 case OMPC_DEPEND_inout:
4179 DepKind = RTLDependenceKindTy::DepInOut;
4181 case OMPC_DEPEND_mutexinoutset:
4182 DepKind = RTLDependenceKindTy::DepMutexInOutSet;
4184 case OMPC_DEPEND_inoutset:
4185 DepKind = RTLDependenceKindTy::DepInOutSet;
4187 case OMPC_DEPEND_outallmemory:
4188 DepKind = RTLDependenceKindTy::DepOmpAllMem;
4190 case OMPC_DEPEND_source:
4191 case OMPC_DEPEND_sink:
4192 case OMPC_DEPEND_depobj:
4193 case OMPC_DEPEND_inoutallmemory:
4195 llvm_unreachable(
"Unknown task dependence type");
4203 FlagsTy =
C.getIntTypeForBitwidth(
C.getTypeSize(
C.BoolTy),
false);
4204 if (KmpDependInfoTy.
isNull()) {
4205 RecordDecl *KmpDependInfoRD =
C.buildImplicitRecord(
"kmp_depend_info");
4211 KmpDependInfoTy =
C.getCanonicalTagType(KmpDependInfoRD);
4215std::pair<llvm::Value *, LValue>
4228 CGF,
Base.getAddress(),
4229 llvm::ConstantInt::get(CGF.
IntPtrTy, -1,
true));
4235 *std::next(KmpDependInfoRD->field_begin(),
4236 static_cast<unsigned int>(RTLDependInfoFields::BaseAddr)));
4238 return std::make_pair(NumDeps,
Base);
4242 llvm::PointerUnion<unsigned *, LValue *> Pos,
4252 OMPIteratorGeneratorScope IteratorScope(
4253 CGF, cast_or_null<OMPIteratorExpr>(
4254 Data.IteratorExpr ?
Data.IteratorExpr->IgnoreParenImpCasts()
4256 for (
const Expr *E :
Data.DepExprs) {
4266 Size = llvm::ConstantInt::get(CGF.
SizeTy, 0);
4269 if (
unsigned *P = dyn_cast<unsigned *>(Pos)) {
4273 assert(E &&
"Expected a non-null expression");
4282 *std::next(KmpDependInfoRD->field_begin(),
4283 static_cast<unsigned int>(RTLDependInfoFields::BaseAddr)));
4287 Base, *std::next(KmpDependInfoRD->field_begin(),
4288 static_cast<unsigned int>(RTLDependInfoFields::Len)));
4294 *std::next(KmpDependInfoRD->field_begin(),
4295 static_cast<unsigned int>(RTLDependInfoFields::Flags)));
4297 llvm::ConstantInt::get(LLVMFlagsTy,
static_cast<unsigned int>(DepKind)),
4299 if (
unsigned *P = dyn_cast<unsigned *>(Pos)) {
4304 Idx = CGF.
Builder.CreateNUWAdd(Idx,
4305 llvm::ConstantInt::get(Idx->getType(), 1));
4314 assert(
Data.DepKind == OMPC_DEPEND_depobj &&
4315 "Expected depobj dependency kind.");
4320 OMPIteratorGeneratorScope IteratorScope(
4321 CGF, cast_or_null<OMPIteratorExpr>(
4322 Data.IteratorExpr ?
Data.IteratorExpr->IgnoreParenImpCasts()
4324 for (
const Expr *E :
Data.DepExprs) {
4325 llvm::Value *NumDeps;
4328 std::tie(NumDeps,
Base) =
4332 C.getUIntPtrType());
4336 llvm::Value *Add = CGF.
Builder.CreateNUWAdd(PrevVal, NumDeps);
4338 SizeLVals.push_back(NumLVal);
4341 for (
unsigned I = 0, E = SizeLVals.size(); I < E; ++I) {
4344 Sizes.push_back(Size);
4354 assert(
Data.DepKind == OMPC_DEPEND_depobj &&
4355 "Expected depobj dependency kind.");
4358 OMPIteratorGeneratorScope IteratorScope(
4359 CGF, cast_or_null<OMPIteratorExpr>(
4360 Data.IteratorExpr ?
Data.IteratorExpr->IgnoreParenImpCasts()
4362 for (
const Expr *E :
Data.DepExprs) {
4363 llvm::Value *NumDeps;
4366 std::tie(NumDeps,
Base) =
4370 llvm::Value *Size = CGF.
Builder.CreateNUWMul(
4379 llvm::Value *Add = CGF.
Builder.CreateNUWAdd(Pos, NumDeps);
4395 llvm::Value *NumOfElements =
nullptr;
4396 unsigned NumDependencies = std::accumulate(
4397 Dependencies.begin(), Dependencies.end(), 0,
4399 return D.DepKind == OMPC_DEPEND_depobj
4401 : (V + (D.IteratorExpr ? 0 : D.DepExprs.size()));
4405 bool HasDepobjDeps =
false;
4406 bool HasRegularWithIterators =
false;
4407 llvm::Value *NumOfDepobjElements = llvm::ConstantInt::get(CGF.
IntPtrTy, 0);
4408 llvm::Value *NumOfRegularWithIterators =
4409 llvm::ConstantInt::get(CGF.
IntPtrTy, 0);
4413 if (D.
DepKind == OMPC_DEPEND_depobj) {
4416 for (llvm::Value *Size : Sizes) {
4417 NumOfDepobjElements =
4418 CGF.
Builder.CreateNUWAdd(NumOfDepobjElements, Size);
4420 HasDepobjDeps =
true;
4425 if (
const auto *IE = cast_or_null<OMPIteratorExpr>(D.
IteratorExpr)) {
4426 llvm::Value *ClauseIteratorSpace =
4427 llvm::ConstantInt::get(CGF.
IntPtrTy, 1);
4431 ClauseIteratorSpace = CGF.
Builder.CreateNUWMul(Sz, ClauseIteratorSpace);
4433 llvm::Value *NumClauseDeps = CGF.
Builder.CreateNUWMul(
4434 ClauseIteratorSpace,
4436 NumOfRegularWithIterators =
4437 CGF.
Builder.CreateNUWAdd(NumOfRegularWithIterators, NumClauseDeps);
4438 HasRegularWithIterators =
true;
4444 if (HasDepobjDeps || HasRegularWithIterators) {
4445 NumOfElements = llvm::ConstantInt::get(
CGM.IntPtrTy, NumDependencies,
4447 if (HasDepobjDeps) {
4449 CGF.
Builder.CreateNUWAdd(NumOfDepobjElements, NumOfElements);
4451 if (HasRegularWithIterators) {
4453 CGF.
Builder.CreateNUWAdd(NumOfRegularWithIterators, NumOfElements);
4456 Loc,
C.getIntTypeForBitwidth(64, 0),
4460 KmpDependInfoArrayTy =
4469 NumOfElements = CGF.
Builder.CreateIntCast(NumOfElements, CGF.
Int32Ty,
4472 KmpDependInfoArrayTy =
C.getConstantArrayType(
4478 NumOfElements = llvm::ConstantInt::get(
CGM.Int32Ty, NumDependencies,
4483 if (Dep.DepKind == OMPC_DEPEND_depobj || Dep.IteratorExpr)
4493 if (Dep.DepKind == OMPC_DEPEND_depobj || !Dep.IteratorExpr)
4498 if (HasDepobjDeps) {
4500 if (Dep.DepKind != OMPC_DEPEND_depobj)
4507 return std::make_pair(NumOfElements, DependenciesArray);
4518 unsigned NumDependencies = Dependencies.
DepExprs.size();
4528 llvm::Value *NumDepsVal;
4530 if (
const auto *IE =
4531 cast_or_null<OMPIteratorExpr>(Dependencies.
IteratorExpr)) {
4532 NumDepsVal = llvm::ConstantInt::get(CGF.
SizeTy, 1);
4536 NumDepsVal = CGF.
Builder.CreateNUWMul(NumDepsVal, Sz);
4538 Size = CGF.
Builder.CreateNUWAdd(llvm::ConstantInt::get(CGF.
SizeTy, 1),
4542 llvm::Value *RecSize =
CGM.getSize(SizeInBytes);
4543 Size = CGF.
Builder.CreateNUWMul(Size, RecSize);
4547 QualType KmpDependInfoArrayTy =
C.getConstantArrayType(
4550 CharUnits Sz =
C.getTypeSizeInChars(KmpDependInfoArrayTy);
4552 NumDepsVal = llvm::ConstantInt::get(CGF.
IntPtrTy, NumDependencies);
4557 llvm::Value *Allocator = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
4558 llvm::Value *Args[] = {ThreadID, Size, Allocator};
4562 CGM.getModule(), OMPRTL___kmpc_alloc),
4563 Args,
".dep.arr.addr");
4567 DependenciesArray =
Address(
Addr, KmpDependInfoLlvmTy, Align);
4573 *std::next(KmpDependInfoRD->field_begin(),
4574 static_cast<unsigned int>(RTLDependInfoFields::BaseAddr)));
4576 llvm::PointerUnion<unsigned *, LValue *> Pos;
4593 return DependenciesArray;
4608 Addr.getElementType(),
Addr.emitRawPointer(CGF),
4609 llvm::ConstantInt::get(CGF.
IntPtrTy, -1,
true));
4614 llvm::Value *Allocator = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
4615 llvm::Value *Args[] = {ThreadID, DepObjAddr, Allocator};
4619 CGM.getModule(), OMPRTL___kmpc_free),
4631 llvm::Value *NumDeps;
4642 llvm::BasicBlock *EntryBB = CGF.
Builder.GetInsertBlock();
4644 llvm::PHINode *ElementPHI =
4649 Base.getTBAAInfo());
4653 Base, *std::next(KmpDependInfoRD->field_begin(),
4654 static_cast<unsigned int>(RTLDependInfoFields::Flags)));
4656 llvm::ConstantInt::get(LLVMFlagsTy,
static_cast<unsigned int>(DepKind)),
4660 llvm::Value *ElementNext =
4663 ElementPHI->addIncoming(ElementNext, CGF.
Builder.GetInsertBlock());
4664 llvm::Value *IsEmpty =
4665 CGF.
Builder.CreateICmpEQ(ElementNext, End,
"omp.isempty");
4666 CGF.
Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
4673 llvm::Function *TaskFunction,
4682 llvm::Value *NewTask =
Result.NewTask;
4683 llvm::Function *TaskEntry =
Result.TaskEntry;
4684 llvm::Value *NewTaskNewTaskTTy =
Result.NewTaskNewTaskTTy;
4689 llvm::Value *NumOfElements;
4690 std::tie(NumOfElements, DependenciesArray) =
4701 llvm::Value *TaskArgs[] = { UpLoc, ThreadID, NewTask };
4702 llvm::Value *DepTaskArgs[7];
4703 if (!
Data.Dependences.empty()) {
4704 DepTaskArgs[0] = UpLoc;
4705 DepTaskArgs[1] = ThreadID;
4706 DepTaskArgs[2] = NewTask;
4707 DepTaskArgs[3] = NumOfElements;
4709 DepTaskArgs[5] = CGF.
Builder.getInt32(0);
4710 DepTaskArgs[6] = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
4712 auto &&ThenCodeGen = [
this, &
Data, TDBase, KmpTaskTQTyRD, &TaskArgs,
4715 auto PartIdFI = std::next(KmpTaskTQTyRD->
field_begin(), KmpTaskTPartId);
4719 if (!
Data.Dependences.empty()) {
4722 CGM.getModule(), OMPRTL___kmpc_omp_task_with_deps),
4726 CGM.getModule(), OMPRTL___kmpc_omp_task),
4732 Region->emitUntiedSwitch(CGF);
4735 llvm::Value *DepWaitTaskArgs[7];
4736 if (!
Data.Dependences.empty()) {
4737 DepWaitTaskArgs[0] = UpLoc;
4738 DepWaitTaskArgs[1] = ThreadID;
4739 DepWaitTaskArgs[2] = NumOfElements;
4741 DepWaitTaskArgs[4] = CGF.
Builder.getInt32(0);
4742 DepWaitTaskArgs[5] = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
4743 DepWaitTaskArgs[6] =
4744 llvm::ConstantInt::get(CGF.
Int32Ty,
Data.HasNowaitClause);
4746 auto &M =
CGM.getModule();
4747 auto &&ElseCodeGen = [
this, &M, &TaskArgs, ThreadID, NewTaskNewTaskTTy,
4748 TaskEntry, &
Data, &DepWaitTaskArgs,
4755 if (!
Data.Dependences.empty())
4757 M, OMPRTL___kmpc_omp_taskwait_deps_51),
4760 auto &&
CodeGen = [TaskEntry, ThreadID, NewTaskNewTaskTTy,
4763 llvm::Value *OutlinedFnArgs[] = {ThreadID, NewTaskNewTaskTTy};
4764 CGF.CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, Loc, TaskEntry,
4773 CommonActionTy Action(
OMPBuilder.getOrCreateRuntimeFunction(
4774 M, OMPRTL___kmpc_omp_task_begin_if0),
4777 M, OMPRTL___kmpc_omp_task_complete_if0),
4793 llvm::Function *TaskFunction,
4813 IfVal = llvm::ConstantInt::getSigned(CGF.
IntTy, 1);
4818 *std::next(
Result.KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound));
4825 *std::next(
Result.KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound));
4832 *std::next(
Result.KmpTaskTQTyRD->field_begin(), KmpTaskTStride));
4840 *std::next(
Result.KmpTaskTQTyRD->field_begin(), KmpTaskTReductions));
4841 if (
Data.Reductions) {
4847 enum { NoSchedule = 0, Grainsize = 1, NumTasks = 2 };
4856 llvm::ConstantInt::getSigned(
4858 llvm::ConstantInt::getSigned(
4860 ?
Data.Schedule.getInt() ? NumTasks : Grainsize
4862 Data.Schedule.getPointer()
4865 : llvm::ConstantInt::get(CGF.
Int64Ty, 0)};
4866 if (
Data.HasModifier)
4867 TaskArgs.push_back(llvm::ConstantInt::get(CGF.
Int32Ty, 1));
4869 TaskArgs.push_back(
Result.TaskDupFn
4872 : llvm::ConstantPointerNull::get(CGF.
VoidPtrTy));
4874 CGM.getModule(),
Data.HasModifier
4875 ? OMPRTL___kmpc_taskloop_5
4876 : OMPRTL___kmpc_taskloop),
4893 const Expr *,
const Expr *)> &RedOpGen,
4894 const Expr *XExpr =
nullptr,
const Expr *EExpr =
nullptr,
4895 const Expr *UpExpr =
nullptr) {
4903 llvm::Value *NumElements = CGF.
emitArrayLength(ArrayTy, ElementTy, LHSAddr);
4908 llvm::Value *LHSEnd =
4913 llvm::Value *IsEmpty =
4914 CGF.
Builder.CreateICmpEQ(LHSBegin, LHSEnd,
"omp.arraycpy.isempty");
4915 CGF.
Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
4918 llvm::BasicBlock *EntryBB = CGF.
Builder.GetInsertBlock();
4923 llvm::PHINode *RHSElementPHI = CGF.
Builder.CreatePHI(
4924 RHSBegin->getType(), 2,
"omp.arraycpy.srcElementPast");
4925 RHSElementPHI->addIncoming(RHSBegin, EntryBB);
4930 llvm::PHINode *LHSElementPHI = CGF.
Builder.CreatePHI(
4931 LHSBegin->getType(), 2,
"omp.arraycpy.destElementPast");
4932 LHSElementPHI->addIncoming(LHSBegin, EntryBB);
4939 Scope.addPrivate(LHSVar, LHSElementCurrent);
4940 Scope.addPrivate(RHSVar, RHSElementCurrent);
4942 RedOpGen(CGF, XExpr, EExpr, UpExpr);
4943 Scope.ForceCleanup();
4946 llvm::Value *LHSElementNext = CGF.
Builder.CreateConstGEP1_32(
4948 "omp.arraycpy.dest.element");
4949 llvm::Value *RHSElementNext = CGF.
Builder.CreateConstGEP1_32(
4951 "omp.arraycpy.src.element");
4954 CGF.
Builder.CreateICmpEQ(LHSElementNext, LHSEnd,
"omp.arraycpy.done");
4955 CGF.
Builder.CreateCondBr(Done, DoneBB, BodyBB);
4956 LHSElementPHI->addIncoming(LHSElementNext, CGF.
Builder.GetInsertBlock());
4957 RHSElementPHI->addIncoming(RHSElementNext, CGF.
Builder.GetInsertBlock());
4967 const Expr *ReductionOp) {
4968 if (
const auto *CE = dyn_cast<CallExpr>(ReductionOp))
4969 if (
const auto *OVE = dyn_cast<OpaqueValueExpr>(CE->getCallee()))
4970 if (
const auto *DRE =
4971 dyn_cast<DeclRefExpr>(OVE->getSourceExpr()->IgnoreImpCasts()))
4972 if (
const auto *DRD =
4973 dyn_cast<OMPDeclareReductionDecl>(DRE->getDecl())) {
4974 std::pair<llvm::Function *, llvm::Function *>
Reduction =
4985 StringRef ReducerName,
SourceLocation Loc, llvm::Type *ArgsElemType,
4999 CGM.getTypes().arrangeBuiltinFunctionDeclaration(
C.VoidTy, Args);
5001 auto *Fn = llvm::Function::Create(
CGM.getTypes().GetFunctionType(CGFI),
5002 llvm::GlobalValue::InternalLinkage, Name,
5005 if (!
CGM.getCodeGenOpts().SampleProfileFile.empty())
5006 Fn->addFnAttr(
"sample-profile-suffix-elision-policy",
"selected");
5007 Fn->setDoesNotRecurse();
5026 const auto *IPriv =
Privates.begin();
5028 for (
unsigned I = 0, E = ReductionOps.size(); I < E; ++I, ++IPriv, ++Idx) {
5029 const auto *RHSVar =
5032 const auto *LHSVar =
5035 QualType PrivTy = (*IPriv)->getType();
5051 const auto *ILHS = LHSExprs.begin();
5052 const auto *IRHS = RHSExprs.begin();
5053 for (
const Expr *E : ReductionOps) {
5054 if ((*IPriv)->getType()->isArrayType()) {
5059 CGF, (*IPriv)->getType(), LHSVar, RHSVar,
5061 emitReductionCombiner(CGF, E);
5071 Scope.ForceCleanup();
5077 const Expr *ReductionOp,
5078 const Expr *PrivateRef,
5086 CGF, PrivateRef->
getType(), LHSVar, RHSVar,
5088 emitReductionCombiner(CGF, ReductionOp);
5097 llvm::StringRef Prefix,
const Expr *Ref);
5101 const Expr *LHSExprs,
const Expr *RHSExprs,
const Expr *ReductionOps) {
5128 std::string ReductionVarNameStr;
5129 if (
const auto *DRE = dyn_cast<DeclRefExpr>(
Privates->IgnoreParenCasts()))
5130 ReductionVarNameStr =
5133 ReductionVarNameStr =
"unnamed_priv_var";
5136 std::string SharedName =
5137 CGM.getOpenMPRuntime().getName({
"internal_pivate_", ReductionVarNameStr});
5138 llvm::GlobalVariable *SharedVar =
OMPBuilder.getOrCreateInternalVariable(
5139 LLVMType,
".omp.reduction." + SharedName);
5141 SharedVar->setAlignment(
5149 llvm::Value *BarrierArgs[] = {BarrierLoc, ThreadId};
5154 llvm::Value *IsWorker = CGF.
Builder.CreateICmpEQ(
5155 ThreadId, llvm::ConstantInt::get(ThreadId->getType(), 0));
5156 CGF.
Builder.CreateCondBr(IsWorker, InitBB, InitEndBB);
5160 auto EmitSharedInit = [&]() {
5163 std::pair<llvm::Function *, llvm::Function *> FnPair =
5165 llvm::Function *InitializerFn = FnPair.second;
5166 if (InitializerFn) {
5167 if (
const auto *CE =
5168 dyn_cast<CallExpr>(UDRInitExpr->IgnoreParenImpCasts())) {
5175 LocalScope.addPrivate(OutVD, SharedResult);
5177 (void)LocalScope.Privatize();
5178 if (
const auto *OVE = dyn_cast<OpaqueValueExpr>(
5179 CE->getCallee()->IgnoreParenImpCasts())) {
5205 if (
const auto *DRE = dyn_cast<DeclRefExpr>(
Privates)) {
5206 if (
const auto *VD = dyn_cast<VarDecl>(DRE->getDecl())) {
5217 CGF.
Builder.CreateBr(InitEndBB);
5221 CGM.getModule(), OMPRTL___kmpc_barrier),
5224 const Expr *ReductionOp = ReductionOps;
5229 auto EmitCriticalReduction = [&](
auto ReductionGen) {
5230 std::string CriticalName =
getName({
"reduction_critical"});
5238 std::pair<llvm::Function *, llvm::Function *> FnPair =
5241 if (
const auto *CE = dyn_cast<CallExpr>(ReductionOp)) {
5253 (void)LocalScope.Privatize();
5258 EmitCriticalReduction(ReductionGen);
5263 if (
const auto *Cleanup = dyn_cast<ExprWithCleanups>(ReductionClauseExpr))
5266 const Expr *AssignRHS =
nullptr;
5267 if (
const auto *BinOp = dyn_cast<BinaryOperator>(ReductionClauseExpr)) {
5268 if (BinOp->getOpcode() == BO_Assign)
5269 AssignRHS = BinOp->getRHS();
5270 }
else if (
const auto *OpCall =
5271 dyn_cast<CXXOperatorCallExpr>(ReductionClauseExpr)) {
5272 if (OpCall->getOperator() == OO_Equal)
5273 AssignRHS = OpCall->getArg(1);
5277 "Private Variable Reduction : Invalid ReductionOp expression");
5282 const auto *OmpOutDRE =
5284 const auto *OmpInDRE =
5287 OmpOutDRE && OmpInDRE &&
5288 "Private Variable Reduction : LHSExpr/RHSExpr must be DeclRefExprs");
5292 LocalScope.addPrivate(OmpOutVD, SharedLV.
getAddress());
5293 LocalScope.addPrivate(OmpInVD, LHSLV.
getAddress());
5294 (void)LocalScope.Privatize();
5298 EmitCriticalReduction(ReductionGen);
5302 CGM.getModule(), OMPRTL___kmpc_barrier),
5308 llvm::Value *FinalResultVal =
nullptr;
5312 FinalResultAddr = SharedResult;
5326 CGM.getModule(), OMPRTL___kmpc_barrier),
5337 EmitCriticalReduction(OriginalListCombiner);
5389 if (SimpleReduction) {
5391 const auto *IPriv = OrgPrivates.begin();
5392 const auto *ILHS = OrgLHSExprs.begin();
5393 const auto *IRHS = OrgRHSExprs.begin();
5394 for (
const Expr *E : OrgReductionOps) {
5407 FilteredRHSExprs, FilteredReductionOps;
5408 for (
unsigned I : llvm::seq<unsigned>(
5409 std::min(OrgReductionOps.size(), OrgLHSExprs.size()))) {
5411 FilteredPrivates.emplace_back(OrgPrivates[I]);
5412 FilteredLHSExprs.emplace_back(OrgLHSExprs[I]);
5413 FilteredRHSExprs.emplace_back(OrgRHSExprs[I]);
5414 FilteredReductionOps.emplace_back(OrgReductionOps[I]);
5426 auto Size = RHSExprs.size();
5432 llvm::APInt ArraySize(32, Size);
5433 QualType ReductionArrayTy =
C.getConstantArrayType(
5437 CGF.
CreateMemTemp(ReductionArrayTy,
".omp.reduction.red_list");
5438 const auto *IPriv =
Privates.begin();
5440 for (
unsigned I = 0, E = RHSExprs.size(); I < E; ++I, ++IPriv, ++Idx) {
5446 if ((*IPriv)->getType()->isVariablyModifiedType()) {
5450 llvm::Value *Size = CGF.
Builder.CreateIntCast(
5463 Privates, LHSExprs, RHSExprs, ReductionOps);
5466 std::string Name =
getName({
"reduction"});
5473 llvm::Value *ReductionArrayTySize = CGF.
getTypeSize(ReductionArrayTy);
5476 llvm::Value *Args[] = {
5479 CGF.
Builder.getInt32(RHSExprs.size()),
5480 ReductionArrayTySize,
5488 WithNowait ? OMPRTL___kmpc_reduce_nowait : OMPRTL___kmpc_reduce),
5492 llvm::BasicBlock *DefaultBB = CGF.
createBasicBlock(
".omp.reduction.default");
5493 llvm::SwitchInst *SwInst =
5494 CGF.
Builder.CreateSwitch(Res, DefaultBB, 2);
5503 SwInst->addCase(CGF.
Builder.getInt32(1), Case1BB);
5507 llvm::Value *EndArgs[] = {
5515 const auto *IPriv =
Privates.begin();
5516 const auto *ILHS = LHSExprs.begin();
5517 const auto *IRHS = RHSExprs.begin();
5518 for (
const Expr *E : ReductionOps) {
5527 CommonActionTy Action(
5530 CGM.getModule(), WithNowait ? OMPRTL___kmpc_end_reduce_nowait
5531 : OMPRTL___kmpc_end_reduce),
5544 SwInst->addCase(CGF.
Builder.getInt32(2), Case2BB);
5547 auto &&AtomicCodeGen = [Loc,
Privates, LHSExprs, RHSExprs, ReductionOps](
5549 const auto *ILHS = LHSExprs.begin();
5550 const auto *IRHS = RHSExprs.begin();
5551 const auto *IPriv =
Privates.begin();
5552 for (
const Expr *E : ReductionOps) {
5553 const Expr *XExpr =
nullptr;
5554 const Expr *EExpr =
nullptr;
5555 const Expr *UpExpr =
nullptr;
5557 if (
const auto *BO = dyn_cast<BinaryOperator>(E)) {
5558 if (BO->getOpcode() == BO_Assign) {
5559 XExpr = BO->getLHS();
5560 UpExpr = BO->getRHS();
5564 const Expr *RHSExpr = UpExpr;
5567 if (
const auto *ACO = dyn_cast<AbstractConditionalOperator>(
5571 RHSExpr = ACO->getCond();
5573 if (
const auto *BORHS =
5575 EExpr = BORHS->getRHS();
5576 BO = BORHS->getOpcode();
5581 auto &&AtomicRedGen = [BO, VD,
5583 const Expr *EExpr,
const Expr *UpExpr) {
5584 LValue X = CGF.EmitLValue(XExpr);
5587 E = CGF.EmitAnyExpr(EExpr);
5588 CGF.EmitOMPAtomicSimpleUpdateExpr(
5590 llvm::AtomicOrdering::Monotonic, Loc,
5591 [&CGF, UpExpr, VD, Loc](
RValue XRValue) {
5593 Address LHSTemp = CGF.CreateMemTemp(VD->getType());
5594 CGF.emitOMPSimpleStore(
5595 CGF.MakeAddrLValue(LHSTemp, VD->
getType()), XRValue,
5596 VD->getType().getNonReferenceType(), Loc);
5599 return CGF.EmitAnyExpr(UpExpr);
5602 if ((*IPriv)->getType()->isArrayType()) {
5604 const auto *RHSVar =
5607 AtomicRedGen, XExpr, EExpr, UpExpr);
5610 AtomicRedGen(CGF, XExpr, EExpr, UpExpr);
5617 std::string Name = RT.
getName({
"atomic_reduction"});
5626 if ((*IPriv)->getType()->isArrayType()) {
5627 const auto *LHSVar =
5629 const auto *RHSVar =
5634 CritRedGen(CGF,
nullptr,
nullptr,
nullptr);
5645 llvm::Value *EndArgs[] = {
5650 CommonActionTy Action(
nullptr, {},
5652 CGM.getModule(), OMPRTL___kmpc_end_reduce),
5662 assert(OrgLHSExprs.size() == OrgPrivates.size() &&
5663 "PrivateVarReduction: Privates size mismatch");
5664 assert(OrgLHSExprs.size() == OrgReductionOps.size() &&
5665 "PrivateVarReduction: ReductionOps size mismatch");
5666 for (
unsigned I : llvm::seq<unsigned>(
5667 std::min(OrgReductionOps.size(), OrgLHSExprs.size()))) {
5670 OrgRHSExprs[I], OrgReductionOps[I]);
5679 llvm::raw_svector_ostream Out(Buffer);
5687 Out << Prefix << Name <<
"_"
5689 return std::string(Out.str());
5713 Args.emplace_back(Param);
5714 Args.emplace_back(ParamOrig);
5715 const auto &FnInfo =
5719 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
5723 Fn->addFnAttr(
"sample-profile-suffix-elision-policy",
"selected");
5724 Fn->setDoesNotRecurse();
5731 llvm::Value *Size =
nullptr;
5774 const Expr *ReductionOp,
5776 const Expr *PrivateRef) {
5787 Args.emplace_back(ParamInOut);
5788 Args.emplace_back(ParamIn);
5789 const auto &FnInfo =
5793 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
5797 Fn->addFnAttr(
"sample-profile-suffix-elision-policy",
"selected");
5798 Fn->setDoesNotRecurse();
5801 llvm::Value *Size =
nullptr;
5822 C.getPointerType(LHSVD->getType())->castAs<
PointerType>()));
5829 C.getPointerType(RHSVD->getType())->castAs<
PointerType>()));
5859 Args.emplace_back(Param);
5860 const auto &FnInfo =
5864 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
5868 Fn->addFnAttr(
"sample-profile-suffix-elision-policy",
"selected");
5869 Fn->setDoesNotRecurse();
5874 llvm::Value *Size =
nullptr;
5909 RecordDecl *RD =
C.buildImplicitRecord(
"kmp_taskred_input_t");
5918 C, RD,
C.getIntTypeForBitwidth(32,
false));
5921 unsigned Size =
Data.ReductionVars.size();
5922 llvm::APInt ArraySize(64, Size);
5924 C.getConstantArrayType(RDType, ArraySize,
nullptr,
5929 Data.ReductionCopies,
Data.ReductionOps);
5930 for (
unsigned Cnt = 0; Cnt < Size; ++Cnt) {
5932 llvm::Value *Idxs[] = {llvm::ConstantInt::get(
CGM.SizeTy, 0),
5933 llvm::ConstantInt::get(
CGM.SizeTy, Cnt)};
5949 llvm::Value *SizeValInChars;
5950 llvm::Value *SizeVal;
5951 std::tie(SizeValInChars, SizeVal) = RCG.
getSizes(Cnt);
5957 bool DelayedCreation = !!SizeVal;
5958 SizeValInChars = CGF.
Builder.CreateIntCast(SizeValInChars,
CGM.SizeTy,
5969 llvm::Value *FiniAddr =
5970 Fini ? Fini : llvm::ConstantPointerNull::get(
CGM.VoidPtrTy);
5975 CGM, Loc, RCG, Cnt,
Data.ReductionOps[Cnt], LHSExprs[Cnt],
5976 RHSExprs[Cnt],
Data.ReductionCopies[Cnt]);
5980 if (DelayedCreation) {
5982 llvm::ConstantInt::get(
CGM.Int32Ty, 1,
true),
5987 if (
Data.IsReductionWithTaskMod) {
5993 llvm::Value *Args[] = {
5995 llvm::ConstantInt::get(
CGM.IntTy,
Data.IsWorksharingReduction ? 1 : 0,
5997 llvm::ConstantInt::get(
CGM.IntTy, Size,
true),
6002 CGM.getModule(), OMPRTL___kmpc_taskred_modifier_init),
6006 llvm::Value *Args[] = {
6009 llvm::ConstantInt::get(
CGM.IntTy, Size,
true),
6013 CGM.getModule(), OMPRTL___kmpc_taskred_init),
6019 bool IsWorksharingReduction) {
6025 llvm::Value *Args[] = {IdentTLoc, GTid,
6026 llvm::ConstantInt::get(
CGM.IntTy,
6027 IsWorksharingReduction ? 1 : 0,
6031 CGM.getModule(), OMPRTL___kmpc_task_reduction_modifier_fini),
6043 llvm::Value *SizeVal = CGF.
Builder.CreateIntCast(Sizes.second,
CGM.SizeTy,
6046 CGF,
CGM.getContext().getSizeType(),
6054 llvm::Value *ReductionsPtr,
6067 CGM.getModule(), OMPRTL___kmpc_task_reduction_get_th_data),
6083 auto &M =
CGM.getModule();
6085 llvm::Value *NumOfElements;
6086 std::tie(NumOfElements, DependenciesArray) =
6088 if (!
Data.Dependences.empty()) {
6089 llvm::Value *DepWaitTaskArgs[7];
6090 DepWaitTaskArgs[0] = UpLoc;
6091 DepWaitTaskArgs[1] = ThreadID;
6092 DepWaitTaskArgs[2] = NumOfElements;
6094 DepWaitTaskArgs[4] = CGF.
Builder.getInt32(0);
6095 DepWaitTaskArgs[5] = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
6096 DepWaitTaskArgs[6] =
6097 llvm::ConstantInt::get(CGF.
Int32Ty,
Data.HasNowaitClause);
6106 M, OMPRTL___kmpc_omp_taskwait_deps_51),
6113 llvm::Value *Args[] = {UpLoc, ThreadID};
6116 OMPBuilder.getOrCreateRuntimeFunction(M, OMPRTL___kmpc_omp_taskwait),
6121 if (
auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.
CapturedStmtInfo))
6122 Region->emitUntiedSwitch(CGF);
6131 InlinedOpenMPRegionRAII Region(CGF,
CodeGen, InnerKind, HasCancel,
6132 InnerKind != OMPD_critical &&
6133 InnerKind != OMPD_master &&
6134 InnerKind != OMPD_masked);
6149 RTCancelKind CancelKind = CancelNoreq;
6150 if (CancelRegion == OMPD_parallel)
6151 CancelKind = CancelParallel;
6152 else if (CancelRegion == OMPD_for)
6153 CancelKind = CancelLoop;
6154 else if (CancelRegion == OMPD_sections)
6155 CancelKind = CancelSections;
6157 assert(CancelRegion == OMPD_taskgroup);
6158 CancelKind = CancelTaskgroup;
6170 if (
auto *OMPRegionInfo =
6174 if (CancelRegion == OMPD_taskgroup || OMPRegionInfo->hasCancel()) {
6175 llvm::Value *Args[] = {
6181 CGM.getModule(), OMPRTL___kmpc_cancellationpoint),
6190 CGF.
Builder.CreateCondBr(
Cmp, ExitBB, ContBB);
6192 if (CancelRegion == OMPD_parallel)
6210 auto &M =
CGM.getModule();
6211 if (
auto *OMPRegionInfo =
6213 auto &&ThenGen = [
this, &M, Loc, CancelRegion,
6216 llvm::Value *Args[] = {
6220 llvm::Value *
Result = CGF.EmitRuntimeCall(
6221 OMPBuilder.getOrCreateRuntimeFunction(M, OMPRTL___kmpc_cancel), Args);
6226 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(
".cancel.exit");
6227 llvm::BasicBlock *ContBB = CGF.createBasicBlock(
".cancel.continue");
6228 llvm::Value *
Cmp = CGF.Builder.CreateIsNotNull(
Result);
6229 CGF.Builder.CreateCondBr(
Cmp, ExitBB, ContBB);
6230 CGF.EmitBlock(ExitBB);
6231 if (CancelRegion == OMPD_parallel)
6235 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind());
6236 CGF.EmitBranchThroughCleanup(CancelDest);
6237 CGF.EmitBlock(ContBB,
true);
6255 OMPUsesAllocatorsActionTy(
6256 ArrayRef<std::pair<const Expr *, const Expr *>> Allocators)
6257 : Allocators(Allocators) {}
6261 for (
const auto &AllocatorData : Allocators) {
6263 CGF, AllocatorData.first, AllocatorData.second);
6266 void Exit(CodeGenFunction &CGF)
override {
6269 for (
const auto &AllocatorData : Allocators) {
6271 AllocatorData.first);
6279 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
6281 assert(!ParentName.empty() &&
"Invalid target entry parent name!");
6285 for (
unsigned I = 0, E =
C->getNumberOfAllocators(); I < E; ++I) {
6292 OMPUsesAllocatorsActionTy UsesAllocatorAction(Allocators);
6293 CodeGen.setAction(UsesAllocatorAction);
6299 const Expr *Allocator,
6300 const Expr *AllocatorTraits) {
6302 ThreadId = CGF.
Builder.CreateIntCast(ThreadId, CGF.
IntTy,
true);
6304 llvm::Value *MemSpaceHandle = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
6305 llvm::Value *NumTraits = llvm::ConstantInt::get(
6309 .getLimitedValue());
6316 llvm::Value *Traits =
Addr.emitRawPointer(CGF);
6318 llvm::Value *AllocatorVal =
6320 CGM.getModule(), OMPRTL___kmpc_init_allocator),
6321 {ThreadId, MemSpaceHandle, NumTraits, Traits});
6333 const Expr *Allocator) {
6335 ThreadId = CGF.
Builder.CreateIntCast(ThreadId, CGF.
IntTy,
true);
6337 llvm::Value *AllocatorVal =
6344 OMPRTL___kmpc_destroy_allocator),
6345 {ThreadId, AllocatorVal});
6350 llvm::OpenMPIRBuilder::TargetKernelDefaultAttrs &Attrs) {
6351 assert(Attrs.MaxTeams.size() == 1 && Attrs.MaxThreads.size() == 1 &&
6352 "invalid default attrs structure");
6353 int32_t &MaxTeamsVal = Attrs.MaxTeams.front();
6354 int32_t &MaxThreadsVal = Attrs.MaxThreads.front();
6361 for (
auto *A :
C->getAttrs()) {
6362 int32_t AttrMinThreadsVal = 1, AttrMaxThreadsVal = -1;
6363 int32_t AttrMinBlocksVal = 1, AttrMaxBlocksVal = -1;
6364 if (
auto *
Attr = dyn_cast<CUDALaunchBoundsAttr>(A))
6365 CGM.handleCUDALaunchBoundsAttr(
nullptr,
Attr, &AttrMaxThreadsVal,
6366 &AttrMinBlocksVal, &AttrMaxBlocksVal);
6367 else if (
auto *
Attr = dyn_cast<AMDGPUFlatWorkGroupSizeAttr>(A))
6368 CGM.handleAMDGPUFlatWorkGroupSizeAttr(
6369 nullptr,
Attr,
nullptr, &AttrMinThreadsVal,
6370 &AttrMaxThreadsVal);
6374 Attrs.MinThreads = std::max(Attrs.MinThreads, AttrMinThreadsVal);
6375 if (AttrMaxThreadsVal > 0)
6376 MaxThreadsVal = MaxThreadsVal > 0
6377 ? std::min(MaxThreadsVal, AttrMaxThreadsVal)
6378 : AttrMaxThreadsVal;
6379 Attrs.MinTeams = std::max(Attrs.MinTeams, AttrMinBlocksVal);
6380 if (AttrMaxBlocksVal > 0)
6381 MaxTeamsVal = MaxTeamsVal > 0 ? std::min(MaxTeamsVal, AttrMaxBlocksVal)
6389 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
6392 llvm::TargetRegionEntryInfo EntryInfo =
6396 llvm::OpenMPIRBuilder::FunctionGenCallback &&GenerateOutlinedFunction =
6397 [&CGF, &D, &
CodeGen,
this](StringRef EntryFnName) {
6398 const CapturedStmt &CS = *D.getCapturedStmt(OMPD_target);
6400 CGOpenMPTargetRegionInfo CGInfo(CS,
CodeGen, EntryFnName);
6402 if (
CGM.getLangOpts().OpenMPIsTargetDevice && !
isGPU())
6407 cantFail(
OMPBuilder.emitTargetRegionFunction(
6408 EntryInfo, GenerateOutlinedFunction, IsOffloadEntry, OutlinedFn,
6414 CGM.getTargetCodeGenInfo().setTargetAttributes(
nullptr, OutlinedFn,
CGM);
6417 for (
auto *A :
C->getAttrs()) {
6418 if (
auto *
Attr = dyn_cast<AMDGPUWavesPerEUAttr>(A))
6419 CGM.handleAMDGPUWavesPerEUAttr(OutlinedFn,
Attr);
6438 while (
const auto *
C = dyn_cast_or_null<CompoundStmt>(Child)) {
6440 for (
const Stmt *S :
C->body()) {
6441 if (
const auto *E = dyn_cast<Expr>(S)) {
6450 if (
const auto *DS = dyn_cast<DeclStmt>(S)) {
6451 if (llvm::all_of(DS->decls(), [](
const Decl *D) {
6452 if (isa<EmptyDecl>(D) || isa<DeclContext>(D) ||
6453 isa<TypeDecl>(D) || isa<PragmaCommentDecl>(D) ||
6454 isa<PragmaDetectMismatchDecl>(D) || isa<UsingDecl>(D) ||
6455 isa<UsingDirectiveDecl>(D) ||
6456 isa<OMPDeclareReductionDecl>(D) ||
6457 isa<OMPThreadPrivateDecl>(D) || isa<OMPAllocateDecl>(D))
6459 const auto *VD = dyn_cast<VarDecl>(D);
6462 return VD->hasGlobalStorage() || !VD->isUsed();
6472 Child = Child->IgnoreContainers();
6479 int32_t &MaxTeamsVal) {
6483 "Expected target-based executable directive.");
6484 switch (DirectiveKind) {
6486 const auto *CS = D.getInnermostCapturedStmt();
6489 const Stmt *ChildStmt =
6491 if (
const auto *NestedDir =
6492 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) {
6501 MinTeamsVal = MaxTeamsVal =
Constant->getExtValue();
6504 MinTeamsVal = MaxTeamsVal = 0;
6507 MinTeamsVal = MaxTeamsVal = 1;
6511 MinTeamsVal = MaxTeamsVal = -1;
6514 case OMPD_target_teams_loop:
6515 case OMPD_target_teams:
6516 case OMPD_target_teams_distribute:
6517 case OMPD_target_teams_distribute_simd:
6518 case OMPD_target_teams_distribute_parallel_for:
6519 case OMPD_target_teams_distribute_parallel_for_simd: {
6521 const Expr *NumTeams =
6525 MinTeamsVal = MaxTeamsVal =
Constant->getExtValue();
6528 MinTeamsVal = MaxTeamsVal = 0;
6531 case OMPD_target_parallel:
6532 case OMPD_target_parallel_for:
6533 case OMPD_target_parallel_for_simd:
6534 case OMPD_target_parallel_loop:
6535 case OMPD_target_simd:
6536 MinTeamsVal = MaxTeamsVal = 1;
6540 case OMPD_parallel_for:
6541 case OMPD_parallel_loop:
6542 case OMPD_parallel_master:
6543 case OMPD_parallel_sections:
6545 case OMPD_parallel_for_simd:
6547 case OMPD_cancellation_point:
6549 case OMPD_threadprivate:
6560 case OMPD_taskyield:
6563 case OMPD_taskgroup:
6569 case OMPD_target_data:
6570 case OMPD_target_exit_data:
6571 case OMPD_target_enter_data:
6572 case OMPD_distribute:
6573 case OMPD_distribute_simd:
6574 case OMPD_distribute_parallel_for:
6575 case OMPD_distribute_parallel_for_simd:
6576 case OMPD_teams_distribute:
6577 case OMPD_teams_distribute_simd:
6578 case OMPD_teams_distribute_parallel_for:
6579 case OMPD_teams_distribute_parallel_for_simd:
6580 case OMPD_target_update:
6581 case OMPD_declare_simd:
6582 case OMPD_declare_variant:
6583 case OMPD_begin_declare_variant:
6584 case OMPD_end_declare_variant:
6585 case OMPD_declare_target:
6586 case OMPD_end_declare_target:
6587 case OMPD_declare_reduction:
6588 case OMPD_declare_mapper:
6590 case OMPD_taskloop_simd:
6591 case OMPD_master_taskloop:
6592 case OMPD_master_taskloop_simd:
6593 case OMPD_parallel_master_taskloop:
6594 case OMPD_parallel_master_taskloop_simd:
6596 case OMPD_metadirective:
6602 llvm_unreachable(
"Unexpected directive kind.");
6608 "Clauses associated with the teams directive expected to be emitted "
6609 "only for the host!");
6611 int32_t MinNT = -1, MaxNT = -1;
6612 const Expr *NumTeams =
6614 if (NumTeams !=
nullptr) {
6617 switch (DirectiveKind) {
6619 const auto *CS = D.getInnermostCapturedStmt();
6620 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6624 return Bld.CreateIntCast(NumTeamsVal, CGF.
Int32Ty,
6627 case OMPD_target_teams:
6628 case OMPD_target_teams_distribute:
6629 case OMPD_target_teams_distribute_simd:
6630 case OMPD_target_teams_distribute_parallel_for:
6631 case OMPD_target_teams_distribute_parallel_for_simd: {
6635 return Bld.CreateIntCast(NumTeamsVal, CGF.
Int32Ty,
6643 assert(MinNT == MaxNT &&
"Num threads ranges require handling here.");
6644 return llvm::ConstantInt::getSigned(CGF.
Int32Ty, MinNT);
6653 bool UpperBoundOnly, llvm::Value **CondVal) {
6656 const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child);
6663 if (CondVal && Dir->hasClausesOfKind<
OMPIfClause>()) {
6664 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6667 for (
const auto *
C : Dir->getClausesOfKind<
OMPIfClause>()) {
6668 if (
C->getNameModifier() == OMPD_unknown ||
6669 C->getNameModifier() == OMPD_parallel) {
6684 if (
const auto *PreInit =
6686 for (
const auto *I : PreInit->decls()) {
6687 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
6703 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6705 const auto *NumThreadsClause =
6707 const Expr *NTExpr = NumThreadsClause->getNumThreads();
6708 if (NTExpr->isIntegerConstantExpr(CGF.
getContext()))
6713 : std::min(UpperBound,
6717 if (UpperBound == -1)
6722 if (
const auto *PreInit =
6723 cast_or_null<DeclStmt>(NumThreadsClause->getPreInitStmt())) {
6724 for (
const auto *I : PreInit->decls()) {
6725 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
6744 bool UpperBoundOnly, llvm::Value **CondVal,
const Expr **ThreadLimitExpr) {
6745 assert((!CGF.
getLangOpts().OpenMPIsTargetDevice || UpperBoundOnly) &&
6746 "Clauses associated with the teams directive expected to be emitted "
6747 "only for the host!");
6750 "Expected target-based executable directive.");
6752 const Expr *NT =
nullptr;
6753 const Expr **NTPtr = UpperBoundOnly ?
nullptr : &NT;
6755 auto CheckForConstExpr = [&](
const Expr *E,
const Expr **EPtr) {
6758 UpperBound = UpperBound ?
Constant->getZExtValue()
6759 : std::min(UpperBound,
6764 if (UpperBound == -1)
6770 auto ReturnSequential = [&]() {
6775 switch (DirectiveKind) {
6778 getNumThreads(CGF, CS, NTPtr, UpperBound, UpperBoundOnly, CondVal);
6784 if (
const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) {
6786 ThreadLimitClause = TLC;
6787 if (ThreadLimitExpr) {
6788 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6792 ThreadLimitClause->getThreadLimit().front()->getSourceRange());
6793 if (
const auto *PreInit =
6794 cast_or_null<DeclStmt>(ThreadLimitClause->getPreInitStmt())) {
6795 for (
const auto *I : PreInit->decls()) {
6796 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
6808 if (ThreadLimitClause)
6809 CheckForConstExpr(ThreadLimitClause->getThreadLimit().front(),
6811 if (
const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) {
6814 CS = Dir->getInnermostCapturedStmt();
6817 Dir = dyn_cast_or_null<OMPExecutableDirective>(Child);
6820 CS = Dir->getInnermostCapturedStmt();
6821 getNumThreads(CGF, CS, NTPtr, UpperBound, UpperBoundOnly, CondVal);
6823 return ReturnSequential();
6827 case OMPD_target_teams: {
6831 CheckForConstExpr(ThreadLimitClause->getThreadLimit().front(),
6835 getNumThreads(CGF, CS, NTPtr, UpperBound, UpperBoundOnly, CondVal);
6838 if (
const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) {
6839 if (Dir->getDirectiveKind() == OMPD_distribute) {
6840 CS = Dir->getInnermostCapturedStmt();
6841 getNumThreads(CGF, CS, NTPtr, UpperBound, UpperBoundOnly, CondVal);
6846 case OMPD_target_teams_distribute:
6850 CheckForConstExpr(ThreadLimitClause->getThreadLimit().front(),
6853 getNumThreads(CGF, D.getInnermostCapturedStmt(), NTPtr, UpperBound,
6854 UpperBoundOnly, CondVal);
6856 case OMPD_target_teams_loop:
6857 case OMPD_target_parallel_loop:
6858 case OMPD_target_parallel:
6859 case OMPD_target_parallel_for:
6860 case OMPD_target_parallel_for_simd:
6861 case OMPD_target_teams_distribute_parallel_for:
6862 case OMPD_target_teams_distribute_parallel_for_simd: {
6863 if (CondVal && D.hasClausesOfKind<
OMPIfClause>()) {
6865 for (
const auto *
C : D.getClausesOfKind<
OMPIfClause>()) {
6866 if (
C->getNameModifier() == OMPD_unknown ||
6867 C->getNameModifier() == OMPD_parallel) {
6877 return ReturnSequential();
6887 CheckForConstExpr(ThreadLimitClause->getThreadLimit().front(),
6893 CheckForConstExpr(NumThreadsClause->getNumThreads(),
nullptr);
6894 return NumThreadsClause->getNumThreads();
6898 case OMPD_target_teams_distribute_simd:
6899 case OMPD_target_simd:
6900 return ReturnSequential();
6904 llvm_unreachable(
"Unsupported directive kind.");
6909 llvm::Value *NumThreadsVal =
nullptr;
6910 llvm::Value *CondVal =
nullptr;
6911 llvm::Value *ThreadLimitVal =
nullptr;
6912 const Expr *ThreadLimitExpr =
nullptr;
6913 int32_t UpperBound = -1;
6916 CGF, D, UpperBound,
false, &CondVal,
6920 if (ThreadLimitExpr) {
6923 ThreadLimitVal = CGF.
Builder.CreateIntCast(ThreadLimitVal, CGF.
Int32Ty,
6928 if (UpperBound == 1) {
6929 NumThreadsVal = CGF.
Builder.getInt32(UpperBound);
6932 NumThreadsVal = CGF.
Builder.CreateIntCast(NumThreadsVal, CGF.
Int32Ty,
6934 }
else if (ThreadLimitVal) {
6937 NumThreadsVal = ThreadLimitVal;
6938 ThreadLimitVal =
nullptr;
6941 assert(!ThreadLimitVal &&
"Default not applicable with thread limit value");
6942 NumThreadsVal = CGF.
Builder.getInt32(0);
6949 NumThreadsVal = CGF.
Builder.CreateSelect(CondVal, NumThreadsVal,
6955 if (ThreadLimitVal) {
6956 NumThreadsVal = CGF.
Builder.CreateSelect(
6957 CGF.
Builder.CreateICmpULT(ThreadLimitVal, NumThreadsVal),
6958 ThreadLimitVal, NumThreadsVal);
6961 return NumThreadsVal;
6971class MappableExprsHandler {
6977 struct AttachPtrExprComparator {
6978 const MappableExprsHandler &Handler;
6980 mutable llvm::DenseMap<std::pair<const Expr *, const Expr *>,
bool>
6981 CachedEqualityComparisons;
6983 AttachPtrExprComparator(
const MappableExprsHandler &H) : Handler(H) {}
6984 AttachPtrExprComparator() =
delete;
6987 bool operator()(
const Expr *LHS,
const Expr *RHS)
const {
6992 const auto ItLHS = Handler.AttachPtrComponentDepthMap.find(LHS);
6993 const auto ItRHS = Handler.AttachPtrComponentDepthMap.find(RHS);
6995 std::optional<size_t> DepthLHS =
6996 (ItLHS != Handler.AttachPtrComponentDepthMap.end()) ? ItLHS->second
6998 std::optional<size_t> DepthRHS =
6999 (ItRHS != Handler.AttachPtrComponentDepthMap.end()) ? ItRHS->second
7003 if (!DepthLHS.has_value() && !DepthRHS.has_value()) {
7005 if (areEqual(LHS, RHS))
7008 return wasComputedBefore(LHS, RHS);
7010 if (!DepthLHS.has_value())
7012 if (!DepthRHS.has_value())
7016 if (DepthLHS.value() != DepthRHS.value())
7017 return DepthLHS.value() < DepthRHS.value();
7020 if (areEqual(LHS, RHS))
7023 return wasComputedBefore(LHS, RHS);
7029 bool areEqual(
const Expr *LHS,
const Expr *RHS)
const {
7031 const auto CachedResultIt = CachedEqualityComparisons.find({LHS, RHS});
7032 if (CachedResultIt != CachedEqualityComparisons.end())
7033 return CachedResultIt->second;
7047 bool wasComputedBefore(
const Expr *LHS,
const Expr *RHS)
const {
7048 const size_t &OrderLHS = Handler.AttachPtrComputationOrderMap.at(LHS);
7049 const size_t &OrderRHS = Handler.AttachPtrComputationOrderMap.at(RHS);
7051 return OrderLHS < OrderRHS;
7060 bool areSemanticallyEqual(
const Expr *LHS,
const Expr *RHS)
const {
7082 if (
const auto *LD = dyn_cast<DeclRefExpr>(LHS)) {
7083 const auto *RD = dyn_cast<DeclRefExpr>(RHS);
7086 return LD->getDecl()->getCanonicalDecl() ==
7087 RD->getDecl()->getCanonicalDecl();
7091 if (
const auto *LA = dyn_cast<ArraySubscriptExpr>(LHS)) {
7092 const auto *RA = dyn_cast<ArraySubscriptExpr>(RHS);
7095 return areSemanticallyEqual(LA->getBase(), RA->getBase()) &&
7096 areSemanticallyEqual(LA->getIdx(), RA->getIdx());
7100 if (
const auto *LM = dyn_cast<MemberExpr>(LHS)) {
7101 const auto *RM = dyn_cast<MemberExpr>(RHS);
7104 if (LM->getMemberDecl()->getCanonicalDecl() !=
7105 RM->getMemberDecl()->getCanonicalDecl())
7107 return areSemanticallyEqual(LM->getBase(), RM->getBase());
7111 if (
const auto *LU = dyn_cast<UnaryOperator>(LHS)) {
7112 const auto *RU = dyn_cast<UnaryOperator>(RHS);
7115 if (LU->getOpcode() != RU->getOpcode())
7117 return areSemanticallyEqual(LU->getSubExpr(), RU->getSubExpr());
7121 if (
const auto *LB = dyn_cast<BinaryOperator>(LHS)) {
7122 const auto *RB = dyn_cast<BinaryOperator>(RHS);
7125 if (LB->getOpcode() != RB->getOpcode())
7127 return areSemanticallyEqual(LB->getLHS(), RB->getLHS()) &&
7128 areSemanticallyEqual(LB->getRHS(), RB->getRHS());
7134 if (
const auto *LAS = dyn_cast<ArraySectionExpr>(LHS)) {
7135 const auto *RAS = dyn_cast<ArraySectionExpr>(RHS);
7138 return areSemanticallyEqual(LAS->getBase(), RAS->getBase()) &&
7139 areSemanticallyEqual(LAS->getLowerBound(),
7140 RAS->getLowerBound()) &&
7141 areSemanticallyEqual(LAS->getLength(), RAS->getLength());
7145 if (
const auto *LC = dyn_cast<CastExpr>(LHS)) {
7146 const auto *RC = dyn_cast<CastExpr>(RHS);
7149 if (LC->getCastKind() != RC->getCastKind())
7151 return areSemanticallyEqual(LC->getSubExpr(), RC->getSubExpr());
7159 if (
const auto *LI = dyn_cast<IntegerLiteral>(LHS)) {
7160 const auto *RI = dyn_cast<IntegerLiteral>(RHS);
7163 return LI->getValue() == RI->getValue();
7167 if (
const auto *LC = dyn_cast<CharacterLiteral>(LHS)) {
7168 const auto *RC = dyn_cast<CharacterLiteral>(RHS);
7171 return LC->getValue() == RC->getValue();
7175 if (
const auto *LF = dyn_cast<FloatingLiteral>(LHS)) {
7176 const auto *RF = dyn_cast<FloatingLiteral>(RHS);
7180 return LF->getValue().bitwiseIsEqual(RF->getValue());
7184 if (
const auto *LS = dyn_cast<StringLiteral>(LHS)) {
7185 const auto *RS = dyn_cast<StringLiteral>(RHS);
7188 return LS->getString() == RS->getString();
7196 if (
const auto *LB = dyn_cast<CXXBoolLiteralExpr>(LHS)) {
7197 const auto *RB = dyn_cast<CXXBoolLiteralExpr>(RHS);
7200 return LB->getValue() == RB->getValue();
7209 static unsigned getFlagMemberOffset() {
7210 unsigned Offset = 0;
7211 for (uint64_t Remain =
7212 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
7213 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF);
7214 !(Remain & 1); Remain = Remain >> 1)
7221 class MappingExprInfo {
7223 const ValueDecl *MapDecl =
nullptr;
7226 const Expr *MapExpr =
nullptr;
7229 MappingExprInfo(
const ValueDecl *MapDecl,
const Expr *MapExpr =
nullptr)
7230 : MapDecl(MapDecl), MapExpr(MapExpr) {}
7232 const ValueDecl *getMapDecl()
const {
return MapDecl; }
7233 const Expr *getMapExpr()
const {
return MapExpr; }
7236 using DeviceInfoTy = llvm::OpenMPIRBuilder::DeviceInfoTy;
7237 using MapBaseValuesArrayTy = llvm::OpenMPIRBuilder::MapValuesArrayTy;
7238 using MapValuesArrayTy = llvm::OpenMPIRBuilder::MapValuesArrayTy;
7239 using MapFlagsArrayTy = llvm::OpenMPIRBuilder::MapFlagsArrayTy;
7240 using MapDimArrayTy = llvm::OpenMPIRBuilder::MapDimArrayTy;
7241 using MapNonContiguousArrayTy =
7242 llvm::OpenMPIRBuilder::MapNonContiguousArrayTy;
7243 using MapExprsArrayTy = SmallVector<MappingExprInfo, 4>;
7244 using MapValueDeclsArrayTy = SmallVector<const ValueDecl *, 4>;
7248 bool ,
const ValueDecl *,
const Expr *>;
7249 using MapDataArrayTy = SmallVector<MapData, 4>;
7254 struct MapCombinedInfoTy : llvm::OpenMPIRBuilder::MapInfosTy {
7255 MapExprsArrayTy Exprs;
7256 MapValueDeclsArrayTy Mappers;
7257 MapValueDeclsArrayTy DevicePtrDecls;
7260 void append(MapCombinedInfoTy &CurInfo) {
7261 Exprs.append(CurInfo.Exprs.begin(), CurInfo.Exprs.end());
7262 DevicePtrDecls.append(CurInfo.DevicePtrDecls.begin(),
7263 CurInfo.DevicePtrDecls.end());
7264 Mappers.append(CurInfo.Mappers.begin(), CurInfo.Mappers.end());
7265 llvm::OpenMPIRBuilder::MapInfosTy::append(CurInfo);
7273 struct StructRangeInfoTy {
7274 MapCombinedInfoTy PreliminaryMapData;
7275 std::pair<
unsigned ,
Address > LowestElem = {
7277 std::pair<
unsigned ,
Address > HighestElem = {
7281 bool IsArraySection =
false;
7282 bool HasCompleteRecord =
false;
7287 struct AttachInfoTy {
7290 const ValueDecl *AttachPtrDecl =
nullptr;
7291 const Expr *AttachMapExpr =
nullptr;
7293 bool isValid()
const {
7300 bool hasAttachEntryForCapturedVar(
const ValueDecl *VD)
const {
7301 for (
const auto &AttachEntry : AttachPtrExprMap) {
7302 if (AttachEntry.second) {
7305 if (
const auto *DRE = dyn_cast<DeclRefExpr>(AttachEntry.second))
7306 if (DRE->getDecl() == VD)
7314 const Expr *getAttachPtrExpr(
7317 const auto It = AttachPtrExprMap.find(Components);
7318 if (It != AttachPtrExprMap.end())
7329 ArrayRef<OpenMPMapModifierKind> MapModifiers;
7330 ArrayRef<OpenMPMotionModifierKind> MotionModifiers;
7331 bool ReturnDevicePointer =
false;
7332 bool IsImplicit =
false;
7333 const ValueDecl *Mapper =
nullptr;
7334 const Expr *VarRef =
nullptr;
7335 bool ForDeviceAddr =
false;
7336 bool HasUdpFbNullify =
false;
7338 MapInfo() =
default;
7342 ArrayRef<OpenMPMapModifierKind> MapModifiers,
7343 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
7344 bool ReturnDevicePointer,
bool IsImplicit,
7345 const ValueDecl *Mapper =
nullptr,
const Expr *VarRef =
nullptr,
7346 bool ForDeviceAddr =
false,
bool HasUdpFbNullify =
false)
7347 : Components(Components), MapType(MapType), MapModifiers(MapModifiers),
7348 MotionModifiers(MotionModifiers),
7349 ReturnDevicePointer(ReturnDevicePointer), IsImplicit(IsImplicit),
7350 Mapper(Mapper), VarRef(VarRef), ForDeviceAddr(ForDeviceAddr),
7351 HasUdpFbNullify(HasUdpFbNullify) {}
7356 llvm::PointerUnion<
const OMPExecutableDirective *,
7357 const OMPDeclareMapperDecl *>
7361 CodeGenFunction &CGF;
7366 llvm::DenseMap<CanonicalDeclPtr<const VarDecl>,
bool> FirstPrivateDecls;
7369 llvm::SmallSet<OpenMPDefaultmapClauseKind, 4> DefaultmapFirstprivateKinds;
7375 SmallVector<OMPClauseMappableExprCommon::MappableExprComponentListRef, 4>>
7382 SmallVector<OMPClauseMappableExprCommon::MappableExprComponentListRef, 4>>
7386 llvm::DenseMap<const ValueDecl *, const OMPMapClause *> LambdasMap;
7401 llvm::DenseMap<const Expr *, std::optional<size_t>>
7402 AttachPtrComponentDepthMap = {{
nullptr, std::nullopt}};
7406 llvm::DenseMap<const Expr *, size_t> AttachPtrComputationOrderMap = {
7411 AttachPtrExprComparator AttachPtrComparator;
7413 llvm::Value *getExprTypeSize(
const Expr *E)
const {
7417 if (
const auto *OAE = dyn_cast<OMPArrayShapingExpr>(E)) {
7419 CGF.
getTypeSize(OAE->getBase()->getType()->getPointeeType());
7420 for (
const Expr *SE : OAE->getDimensions()) {
7431 if (
const auto *RefTy = ExprTy->
getAs<ReferenceType>())
7437 if (
const auto *OAE = dyn_cast<ArraySectionExpr>(E)) {
7439 OAE->getBase()->IgnoreParenImpCasts())
7445 if (!OAE->getLength() && OAE->getColonLocFirst().isValid() &&
7446 !OAE->getLowerBound())
7449 llvm::Value *ElemSize;
7450 if (
const auto *PTy = BaseTy->
getAs<PointerType>()) {
7451 ElemSize = CGF.
getTypeSize(PTy->getPointeeType().getCanonicalType());
7454 assert(ATy &&
"Expecting array type if not a pointer type.");
7455 ElemSize = CGF.
getTypeSize(ATy->getElementType().getCanonicalType());
7460 if (!OAE->getLength() && OAE->getColonLocFirst().isInvalid())
7463 if (
const Expr *LenExpr = OAE->getLength()) {
7467 LenExpr->getExprLoc());
7468 return CGF.
Builder.CreateNUWMul(LengthVal, ElemSize);
7470 assert(!OAE->getLength() && OAE->getColonLocFirst().isValid() &&
7471 OAE->getLowerBound() &&
"expected array_section[lb:].");
7477 OAE->getLowerBound()->getExprLoc());
7478 LBVal = CGF.
Builder.CreateNUWMul(LBVal, ElemSize);
7479 llvm::Value *
Cmp = CGF.
Builder.CreateICmpUGT(LengthVal, LBVal);
7480 llvm::Value *TrueVal = CGF.
Builder.CreateNUWSub(LengthVal, LBVal);
7481 LengthVal = CGF.
Builder.CreateSelect(
7482 Cmp, TrueVal, llvm::ConstantInt::get(CGF.
SizeTy, 0));
7492 OpenMPOffloadMappingFlags getMapTypeBits(
7494 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
bool IsImplicit,
7495 bool AddPtrFlag,
bool AddIsTargetParamFlag,
bool IsNonContiguous)
const {
7496 OpenMPOffloadMappingFlags Bits =
7497 IsImplicit ? OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT
7498 : OpenMPOffloadMappingFlags::OMP_MAP_NONE;
7500 case OMPC_MAP_alloc:
7501 case OMPC_MAP_release:
7508 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_TO;
7511 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_FROM;
7513 case OMPC_MAP_tofrom:
7514 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_TO |
7515 OpenMPOffloadMappingFlags::OMP_MAP_FROM;
7517 case OMPC_MAP_delete:
7518 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_DELETE;
7521 llvm_unreachable(
"Unexpected map type!");
7524 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ;
7525 if (AddIsTargetParamFlag)
7526 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM;
7527 if (llvm::is_contained(MapModifiers, OMPC_MAP_MODIFIER_always))
7528 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_ALWAYS;
7529 if (llvm::is_contained(MapModifiers, OMPC_MAP_MODIFIER_close))
7530 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_CLOSE;
7531 if (llvm::is_contained(MapModifiers, OMPC_MAP_MODIFIER_present) ||
7532 llvm::is_contained(MotionModifiers, OMPC_MOTION_MODIFIER_present))
7533 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_PRESENT;
7534 if (llvm::is_contained(MapModifiers, OMPC_MAP_MODIFIER_ompx_hold))
7535 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_OMPX_HOLD;
7536 if (IsNonContiguous)
7537 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_NON_CONTIG;
7543 bool isFinalArraySectionExpression(
const Expr *E)
const {
7544 const auto *OASE = dyn_cast<ArraySectionExpr>(E);
7551 if (OASE->getColonLocFirst().isInvalid())
7554 const Expr *Length = OASE->getLength();
7561 OASE->getBase()->IgnoreParenImpCasts())
7563 if (
const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.
getTypePtr()))
7564 return ATy->getSExtSize() != 1;
7576 llvm::APSInt ConstLength =
Result.Val.getInt();
7577 return ConstLength.getSExtValue() != 1;
7584 void emitAttachEntry(CodeGenFunction &CGF, MapCombinedInfoTy &CombinedInfo,
7585 const AttachInfoTy &AttachInfo)
const {
7586 assert(AttachInfo.isValid() &&
7587 "Expected valid attach pointer/pointee information!");
7591 llvm::Value *PointerSize = CGF.
Builder.CreateIntCast(
7592 llvm::ConstantInt::get(
7598 CombinedInfo.Exprs.emplace_back(AttachInfo.AttachPtrDecl,
7599 AttachInfo.AttachMapExpr);
7600 CombinedInfo.BasePointers.push_back(
7601 AttachInfo.AttachPtrAddr.emitRawPointer(CGF));
7602 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
7603 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
7604 CombinedInfo.Pointers.push_back(
7605 AttachInfo.AttachPteeAddr.emitRawPointer(CGF));
7606 CombinedInfo.Sizes.push_back(PointerSize);
7607 CombinedInfo.Types.push_back(OpenMPOffloadMappingFlags::OMP_MAP_ATTACH);
7609 CombinedInfo.HasAttachPtr.push_back(
false);
7610 CombinedInfo.Mappers.push_back(
nullptr);
7611 CombinedInfo.NonContigInfo.Dims.push_back(1);
7618 class CopyOverlappedEntryGaps {
7619 CodeGenFunction &CGF;
7620 MapCombinedInfoTy &CombinedInfo;
7621 OpenMPOffloadMappingFlags Flags = OpenMPOffloadMappingFlags::OMP_MAP_NONE;
7622 const ValueDecl *MapDecl =
nullptr;
7623 const Expr *MapExpr =
nullptr;
7625 bool IsNonContiguous =
false;
7629 const RecordDecl *LastParent =
nullptr;
7631 unsigned LastIndex = -1u;
7635 CopyOverlappedEntryGaps(CodeGenFunction &CGF,
7636 MapCombinedInfoTy &CombinedInfo,
7637 OpenMPOffloadMappingFlags Flags,
7638 const ValueDecl *MapDecl,
const Expr *MapExpr,
7639 Address BP, Address LB,
bool IsNonContiguous,
7641 : CGF(CGF), CombinedInfo(CombinedInfo), Flags(Flags), MapDecl(MapDecl),
7642 MapExpr(MapExpr), BP(BP), IsNonContiguous(IsNonContiguous),
7643 DimSize(DimSize), LB(LB) {}
7646 const OMPClauseMappableExprCommon::MappableComponent &MC,
7647 const FieldDecl *FD,
7648 llvm::function_ref<LValue(CodeGenFunction &,
const MemberExpr *)>
7649 EmitMemberExprBase) {
7659 LValue BaseLVal = EmitMemberExprBase(CGF, ME);
7671 copyUntilField(FD, ComponentLB);
7674 if (((int64_t)FieldOffset - (int64_t)Cursor) > 0)
7675 copyUntilField(FD, ComponentLB);
7677 Cursor = FieldOffset + FieldSize;
7682 void copyUntilField(
const FieldDecl *FD, Address ComponentLB) {
7685 llvm::Value *
Size = CGF.
Builder.CreatePtrDiff(ComponentLBPtr, LBPtr);
7686 copySizedChunk(LBPtr, Size);
7689 void copyUntilEnd(Address HB) {
7691 const ASTRecordLayout &RL =
7699 copySizedChunk(LBPtr, Size);
7702 void copySizedChunk(llvm::Value *Base, llvm::Value *Size) {
7703 CombinedInfo.Exprs.emplace_back(MapDecl, MapExpr);
7705 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
7706 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
7707 CombinedInfo.Pointers.push_back(Base);
7708 CombinedInfo.Sizes.push_back(
7710 CombinedInfo.Types.push_back(Flags);
7711 CombinedInfo.HasAttachPtr.push_back(
false);
7712 CombinedInfo.Mappers.push_back(
nullptr);
7713 CombinedInfo.NonContigInfo.Dims.push_back(IsNonContiguous ? DimSize : 1);
7722 void generateInfoForComponentList(
7724 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
7726 MapCombinedInfoTy &CombinedInfo,
7727 MapCombinedInfoTy &StructBaseCombinedInfo,
7728 StructRangeInfoTy &PartialStruct, AttachInfoTy &AttachInfo,
7729 bool IsFirstComponentList,
bool IsImplicit,
7730 bool GenerateAllInfoForClauses,
const ValueDecl *Mapper =
nullptr,
7731 bool ForDeviceAddr =
false,
const ValueDecl *BaseDecl =
nullptr,
7732 const Expr *MapExpr =
nullptr,
7733 ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef>
7734 OverlappedElements = {})
const {
7952 bool IsCaptureFirstInfo = IsFirstComponentList;
7956 bool RequiresReference =
false;
7959 auto CI = Components.rbegin();
7960 auto CE = Components.rend();
7965 bool IsExpressionFirstInfo =
true;
7966 bool FirstPointerInComplexData =
false;
7969 const Expr *AssocExpr = I->getAssociatedExpression();
7970 const auto *AE = dyn_cast<ArraySubscriptExpr>(AssocExpr);
7971 const auto *OASE = dyn_cast<ArraySectionExpr>(AssocExpr);
7972 const auto *OAShE = dyn_cast<OMPArrayShapingExpr>(AssocExpr);
7975 const Expr *AttachPtrExpr = getAttachPtrExpr(Components);
7976 auto [AttachPtrAddr, AttachPteeBaseAddr] =
7977 getAttachPtrAddrAndPteeBaseAddr(AttachPtrExpr, CGF);
7979 bool HasAttachPtr = AttachPtrExpr !=
nullptr;
7980 bool FirstComponentIsForAttachPtr = AssocExpr == AttachPtrExpr;
7981 bool SeenAttachPtr = FirstComponentIsForAttachPtr;
7983 if (FirstComponentIsForAttachPtr) {
7991 }
else if ((AE &&
isa<CXXThisExpr>(AE->getBase()->IgnoreParenImpCasts())) ||
8005 if (
const auto *VD =
8006 dyn_cast_or_null<VarDecl>(I->getAssociatedDeclaration())) {
8007 if (std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
8008 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD)) {
8009 if ((*Res == OMPDeclareTargetDeclAttr::MT_Link) ||
8010 ((*Res == OMPDeclareTargetDeclAttr::MT_To ||
8011 *Res == OMPDeclareTargetDeclAttr::MT_Enter) &&
8013 RequiresReference =
true;
8023 I->getAssociatedDeclaration()->
getType().getNonReferenceType();
8028 const auto *VD = dyn_cast<VarDecl>(I->getAssociatedDeclaration());
8030 !VD || VD->hasLocalStorage() || HasAttachPtr)
8033 FirstPointerInComplexData =
true;
8052 bool ShouldBeMemberOf =
false;
8061 const MemberExpr *EncounteredME =
nullptr;
8073 bool IsNonContiguous =
8074 CombinedInfo.NonContigInfo.IsNonContiguous ||
8075 any_of(Components, [&](
const auto &Component) {
8077 dyn_cast<ArraySectionExpr>(Component.getAssociatedExpression());
8081 const Expr *StrideExpr = OASE->getStride();
8086 "Stride expression must be of integer type");
8099 bool IsPrevMemberReference =
false;
8101 bool IsPartialMapped =
8102 !PartialStruct.PreliminaryMapData.BasePointers.empty();
8109 bool IsMappingWholeStruct =
true;
8110 if (!GenerateAllInfoForClauses) {
8111 IsMappingWholeStruct =
false;
8113 for (
auto TempI = I; TempI != CE; ++TempI) {
8114 const MemberExpr *PossibleME =
8115 dyn_cast<MemberExpr>(TempI->getAssociatedExpression());
8117 IsMappingWholeStruct =
false;
8123 bool SeenFirstNonBinOpExprAfterAttachPtr =
false;
8124 for (; I != CE; ++I) {
8127 if (HasAttachPtr && !SeenAttachPtr) {
8128 SeenAttachPtr = I->getAssociatedExpression() == AttachPtrExpr;
8135 if (HasAttachPtr && !SeenFirstNonBinOpExprAfterAttachPtr) {
8136 const auto *BO = dyn_cast<BinaryOperator>(I->getAssociatedExpression());
8141 SeenFirstNonBinOpExprAfterAttachPtr =
true;
8142 BP = AttachPteeBaseAddr;
8146 if (!EncounteredME) {
8147 EncounteredME = dyn_cast<MemberExpr>(I->getAssociatedExpression());
8150 if (EncounteredME) {
8151 ShouldBeMemberOf =
true;
8154 if (FirstPointerInComplexData) {
8155 QualType Ty = std::prev(I)
8156 ->getAssociatedDeclaration()
8158 .getNonReferenceType();
8160 FirstPointerInComplexData =
false;
8165 auto Next = std::next(I);
8175 bool IsFinalArraySection =
8177 isFinalArraySectionExpression(I->getAssociatedExpression());
8181 const ValueDecl *MapDecl = (I->getAssociatedDeclaration())
8182 ? I->getAssociatedDeclaration()
8184 MapExpr = (I->getAssociatedExpression()) ? I->getAssociatedExpression()
8191 dyn_cast<ArraySectionExpr>(I->getAssociatedExpression());
8193 dyn_cast<OMPArrayShapingExpr>(I->getAssociatedExpression());
8194 const auto *UO = dyn_cast<UnaryOperator>(I->getAssociatedExpression());
8195 const auto *BO = dyn_cast<BinaryOperator>(I->getAssociatedExpression());
8201 I->getAssociatedExpression()->getType()->isAnyPointerType();
8202 bool IsMemberReference =
isa<MemberExpr>(I->getAssociatedExpression()) &&
8205 bool IsNonDerefPointer = IsPointer &&
8206 !(UO && UO->getOpcode() != UO_Deref) && !BO &&
8212 if (
Next == CE || IsMemberReference || IsNonDerefPointer ||
8213 IsFinalArraySection) {
8216 assert((
Next == CE ||
8223 "Unexpected expression");
8227 auto &&EmitMemberExprBase = [](CodeGenFunction &CGF,
8228 const MemberExpr *E) {
8229 const Expr *BaseExpr = E->getBase();
8234 LValueBaseInfo BaseInfo;
8235 TBAAAccessInfo TBAAInfo;
8249 OAShE->getBase()->getType()->getPointeeType()),
8251 OAShE->getBase()->getType()));
8252 }
else if (IsMemberReference) {
8254 LValue BaseLVal = EmitMemberExprBase(CGF, ME);
8269 FinalLowestElem = LowestElem;
8274 bool IsMemberPointerOrAddr =
8276 (((IsPointer || ForDeviceAddr) &&
8277 I->getAssociatedExpression() == EncounteredME) ||
8278 (IsPrevMemberReference && !IsPointer) ||
8279 (IsMemberReference &&
Next != CE &&
8280 !
Next->getAssociatedExpression()->getType()->isPointerType()));
8281 if (!OverlappedElements.empty() &&
Next == CE) {
8283 assert(!PartialStruct.Base.isValid() &&
"The base element is set.");
8284 assert(!IsPointer &&
8285 "Unexpected base element with the pointer type.");
8288 PartialStruct.LowestElem = {0, LowestElem};
8290 I->getAssociatedExpression()->getType());
8295 PartialStruct.HighestElem = {
8296 std::numeric_limits<
decltype(
8297 PartialStruct.HighestElem.first)>
::max(),
8299 PartialStruct.Base = BP;
8300 PartialStruct.LB = LB;
8302 PartialStruct.PreliminaryMapData.BasePointers.empty() &&
8303 "Overlapped elements must be used only once for the variable.");
8304 std::swap(PartialStruct.PreliminaryMapData, CombinedInfo);
8306 OpenMPOffloadMappingFlags Flags =
8307 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF |
8308 getMapTypeBits(MapType, MapModifiers, MotionModifiers, IsImplicit,
8310 false, IsNonContiguous);
8311 CopyOverlappedEntryGaps CopyGaps(CGF, CombinedInfo, Flags, MapDecl,
8312 MapExpr, BP, LB, IsNonContiguous,
8316 Component : OverlappedElements) {
8317 for (
const OMPClauseMappableExprCommon::MappableComponent &MC :
8320 if (
const auto *FD = dyn_cast<FieldDecl>(VD)) {
8321 CopyGaps.processField(MC, FD, EmitMemberExprBase);
8326 CopyGaps.copyUntilEnd(HB);
8329 llvm::Value *
Size = getExprTypeSize(I->getAssociatedExpression());
8336 if ((!IsMemberPointerOrAddr && !IsPartialMapped) ||
8338 if (!IsMappingWholeStruct) {
8339 CombinedInfo.Exprs.emplace_back(MapDecl, MapExpr);
8341 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
8342 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
8344 CombinedInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
8346 CombinedInfo.NonContigInfo.Dims.push_back(IsNonContiguous ? DimSize
8349 StructBaseCombinedInfo.Exprs.emplace_back(MapDecl, MapExpr);
8350 StructBaseCombinedInfo.BasePointers.push_back(
8352 StructBaseCombinedInfo.DevicePtrDecls.push_back(
nullptr);
8353 StructBaseCombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
8354 StructBaseCombinedInfo.Pointers.push_back(LB.
emitRawPointer(CGF));
8355 StructBaseCombinedInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
8357 StructBaseCombinedInfo.NonContigInfo.Dims.push_back(
8358 IsNonContiguous ? DimSize : 1);
8362 bool HasMapper = Mapper &&
Next == CE;
8363 if (!IsMappingWholeStruct)
8364 CombinedInfo.Mappers.push_back(HasMapper ? Mapper :
nullptr);
8366 StructBaseCombinedInfo.Mappers.push_back(HasMapper ? Mapper
8373 OpenMPOffloadMappingFlags Flags = getMapTypeBits(
8374 MapType, MapModifiers, MotionModifiers, IsImplicit,
8375 !IsExpressionFirstInfo || RequiresReference ||
8376 FirstPointerInComplexData || IsMemberReference,
8377 IsCaptureFirstInfo && !RequiresReference, IsNonContiguous);
8379 if (!IsExpressionFirstInfo || IsMemberReference) {
8382 if (IsPointer || (IsMemberReference &&
Next != CE))
8383 Flags &= ~(OpenMPOffloadMappingFlags::OMP_MAP_TO |
8384 OpenMPOffloadMappingFlags::OMP_MAP_FROM |
8385 OpenMPOffloadMappingFlags::OMP_MAP_ALWAYS |
8386 OpenMPOffloadMappingFlags::OMP_MAP_DELETE |
8387 OpenMPOffloadMappingFlags::OMP_MAP_CLOSE);
8389 if (ShouldBeMemberOf) {
8392 Flags |= OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF;
8395 ShouldBeMemberOf =
false;
8399 if (!IsMappingWholeStruct) {
8400 CombinedInfo.Types.push_back(Flags);
8402 CombinedInfo.HasAttachPtr.push_back(HasAttachPtr);
8404 StructBaseCombinedInfo.Types.push_back(Flags);
8405 StructBaseCombinedInfo.HasAttachPtr.push_back(HasAttachPtr);
8412 if (EncounteredME) {
8417 if (!PartialStruct.Base.isValid()) {
8418 PartialStruct.LowestElem = {FieldIndex, LowestElem};
8419 if (IsFinalArraySection && OASE) {
8423 PartialStruct.HighestElem = {FieldIndex, HB};
8425 PartialStruct.HighestElem = {FieldIndex, LowestElem};
8427 PartialStruct.Base = BP;
8428 PartialStruct.LB = BP;
8429 }
else if (FieldIndex < PartialStruct.LowestElem.first) {
8430 PartialStruct.LowestElem = {FieldIndex, LowestElem};
8431 }
else if (FieldIndex > PartialStruct.HighestElem.first) {
8432 if (IsFinalArraySection && OASE) {
8436 PartialStruct.HighestElem = {FieldIndex, HB};
8438 PartialStruct.HighestElem = {FieldIndex, LowestElem};
8444 if (IsFinalArraySection || IsNonContiguous)
8445 PartialStruct.IsArraySection =
true;
8448 if (IsFinalArraySection)
8453 BP = IsMemberReference ? LowestElem : LB;
8454 if (!IsPartialMapped)
8455 IsExpressionFirstInfo =
false;
8456 IsCaptureFirstInfo =
false;
8457 FirstPointerInComplexData =
false;
8458 IsPrevMemberReference = IsMemberReference;
8459 }
else if (FirstPointerInComplexData) {
8460 QualType Ty = Components.rbegin()
8461 ->getAssociatedDeclaration()
8463 .getNonReferenceType();
8465 FirstPointerInComplexData =
false;
8471 PartialStruct.HasCompleteRecord =
true;
8474 if (shouldEmitAttachEntry(AttachPtrExpr, BaseDecl, CGF, CurDir)) {
8475 AttachInfo.AttachPtrAddr = AttachPtrAddr;
8476 AttachInfo.AttachPteeAddr = FinalLowestElem;
8477 AttachInfo.AttachPtrDecl = BaseDecl;
8478 AttachInfo.AttachMapExpr = MapExpr;
8481 if (!IsNonContiguous)
8484 const ASTContext &Context = CGF.
getContext();
8488 MapValuesArrayTy CurOffsets = {llvm::ConstantInt::get(CGF.
CGM.
Int64Ty, 0)};
8489 MapValuesArrayTy CurCounts;
8490 MapValuesArrayTy CurStrides = {llvm::ConstantInt::get(CGF.
CGM.
Int64Ty, 1)};
8491 MapValuesArrayTy DimSizes{llvm::ConstantInt::get(CGF.
CGM.
Int64Ty, 1)};
8497 for (
const OMPClauseMappableExprCommon::MappableComponent &Component :
8499 const Expr *AssocExpr = Component.getAssociatedExpression();
8500 const auto *OASE = dyn_cast<ArraySectionExpr>(AssocExpr);
8510 assert((VAT || CAT || &Component == &*Components.begin()) &&
8511 "Should be either ConstantArray or VariableArray if not the "
8515 if (CurCounts.empty()) {
8516 const Type *ElementType =
nullptr;
8518 ElementType = CAT->getElementType().getTypePtr();
8520 ElementType = VAT->getElementType().getTypePtr();
8521 else if (&Component == &*Components.begin()) {
8528 if (
const auto *PtrType = Ty->
getAs<PointerType>())
8535 "Non-first components should not be raw pointers");
8543 if (&Component != &*Components.begin())
8547 CurCounts.push_back(
8548 llvm::ConstantInt::get(CGF.
Int64Ty, ElementTypeSize));
8553 if (DimSizes.size() < Components.size() - 1) {
8556 llvm::ConstantInt::get(CGF.
Int64Ty, CAT->getZExtSize()));
8558 DimSizes.push_back(CGF.
Builder.CreateIntCast(
8565 auto *DI = DimSizes.begin() + 1;
8567 llvm::Value *DimProd =
8568 llvm::ConstantInt::get(CGF.
CGM.
Int64Ty, ElementTypeSize);
8577 for (
const OMPClauseMappableExprCommon::MappableComponent &Component :
8579 const Expr *AssocExpr = Component.getAssociatedExpression();
8581 if (
const auto *AE = dyn_cast<ArraySubscriptExpr>(AssocExpr)) {
8582 llvm::Value *Offset = CGF.
Builder.CreateIntCast(
8585 CurOffsets.push_back(Offset);
8586 CurCounts.push_back(llvm::ConstantInt::get(CGF.
Int64Ty, 1));
8587 CurStrides.push_back(CurStrides.back());
8591 const auto *OASE = dyn_cast<ArraySectionExpr>(AssocExpr);
8597 const Expr *OffsetExpr = OASE->getLowerBound();
8598 llvm::Value *Offset =
nullptr;
8601 Offset = llvm::ConstantInt::get(CGF.
Int64Ty, 0);
8609 const Expr *CountExpr = OASE->getLength();
8610 llvm::Value *Count =
nullptr;
8616 if (!OASE->getColonLocFirst().isValid() &&
8617 !OASE->getColonLocSecond().isValid()) {
8618 Count = llvm::ConstantInt::get(CGF.
Int64Ty, 1);
8624 const Expr *StrideExpr = OASE->getStride();
8625 llvm::Value *Stride =
8631 Count = CGF.
Builder.CreateUDiv(
8632 CGF.
Builder.CreateNUWSub(*DI, Offset), Stride);
8634 Count = CGF.
Builder.CreateNUWSub(*DI, Offset);
8640 CurCounts.push_back(Count);
8650 const Expr *StrideExpr = OASE->getStride();
8651 llvm::Value *Stride =
8656 DimProd = CGF.
Builder.CreateNUWMul(DimProd, *(DI - 1));
8658 CurStrides.push_back(CGF.
Builder.CreateNUWMul(DimProd, Stride));
8660 CurStrides.push_back(DimProd);
8662 Offset = CGF.
Builder.CreateNUWMul(DimProd, Offset);
8663 CurOffsets.push_back(Offset);
8665 if (DI != DimSizes.end())
8669 CombinedInfo.NonContigInfo.Offsets.push_back(CurOffsets);
8670 CombinedInfo.NonContigInfo.Counts.push_back(CurCounts);
8671 CombinedInfo.NonContigInfo.Strides.push_back(CurStrides);
8677 OpenMPOffloadMappingFlags
8678 getMapModifiersForPrivateClauses(
const CapturedStmt::Capture &Cap)
const {
8686 return OpenMPOffloadMappingFlags::OMP_MAP_TO |
8687 OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ;
8688 return OpenMPOffloadMappingFlags::OMP_MAP_PRIVATE |
8689 OpenMPOffloadMappingFlags::OMP_MAP_TO;
8692 if (I != LambdasMap.end())
8694 return getMapTypeBits(
8695 I->getSecond()->getMapType(), I->getSecond()->getMapTypeModifiers(),
8696 {}, I->getSecond()->isImplicit(),
8700 return OpenMPOffloadMappingFlags::OMP_MAP_TO |
8701 OpenMPOffloadMappingFlags::OMP_MAP_FROM;
8704 void getPlainLayout(
const CXXRecordDecl *RD,
8705 llvm::SmallVectorImpl<const FieldDecl *> &Layout,
8706 bool AsBase)
const {
8709 llvm::StructType *St =
8712 unsigned NumElements = St->getNumElements();
8714 llvm::PointerUnion<const CXXRecordDecl *, const FieldDecl *>, 4>
8715 RecordLayout(NumElements);
8718 for (
const auto &I : RD->
bases()) {
8722 QualType BaseTy = I.getType();
8733 RecordLayout[FieldIndex] =
Base;
8736 for (
const auto &I : RD->
vbases()) {
8737 QualType BaseTy = I.getType();
8744 if (RecordLayout[FieldIndex])
8746 RecordLayout[FieldIndex] =
Base;
8749 assert(!RD->
isUnion() &&
"Unexpected union.");
8750 for (
const auto *Field : RD->
fields()) {
8753 if (!
Field->isBitField() &&
8756 RecordLayout[FieldIndex] =
Field;
8759 for (
const llvm::PointerUnion<const CXXRecordDecl *, const FieldDecl *>
8760 &
Data : RecordLayout) {
8763 if (
const auto *Base = dyn_cast<const CXXRecordDecl *>(
Data))
8764 getPlainLayout(Base, Layout,
true);
8771 static Address getAttachPtrAddr(
const Expr *PointerExpr,
8772 CodeGenFunction &CGF) {
8773 assert(PointerExpr &&
"Cannot get addr from null attach-ptr expr");
8776 if (
auto *DRE = dyn_cast<DeclRefExpr>(PointerExpr)) {
8779 }
else if (
auto *OASE = dyn_cast<ArraySectionExpr>(PointerExpr)) {
8782 }
else if (
auto *ASE = dyn_cast<ArraySubscriptExpr>(PointerExpr)) {
8784 }
else if (
auto *ME = dyn_cast<MemberExpr>(PointerExpr)) {
8786 }
else if (
auto *UO = dyn_cast<UnaryOperator>(PointerExpr)) {
8787 assert(UO->getOpcode() == UO_Deref &&
8788 "Unexpected unary-operator on attach-ptr-expr");
8791 assert(AttachPtrAddr.
isValid() &&
8792 "Failed to get address for attach pointer expression");
8793 return AttachPtrAddr;
8800 static std::pair<Address, Address>
8801 getAttachPtrAddrAndPteeBaseAddr(
const Expr *AttachPtrExpr,
8802 CodeGenFunction &CGF) {
8807 Address AttachPtrAddr = getAttachPtrAddr(AttachPtrExpr, CGF);
8808 assert(AttachPtrAddr.
isValid() &&
"Invalid attach pointer addr");
8810 QualType AttachPtrType =
8815 AttachPtrAddr, AttachPtrType->
castAs<PointerType>());
8816 assert(AttachPteeBaseAddr.
isValid() &&
"Invalid attach pointee base addr");
8818 return {AttachPtrAddr, AttachPteeBaseAddr};
8824 shouldEmitAttachEntry(
const Expr *PointerExpr,
const ValueDecl *MapBaseDecl,
8825 CodeGenFunction &CGF,
8826 llvm::PointerUnion<
const OMPExecutableDirective *,
8827 const OMPDeclareMapperDecl *>
8837 ->getDirectiveKind());
8846 void collectAttachPtrExprInfo(
8848 llvm::PointerUnion<
const OMPExecutableDirective *,
8849 const OMPDeclareMapperDecl *>
8854 ? OMPD_declare_mapper
8857 const auto &[AttachPtrExpr, Depth] =
8861 AttachPtrComputationOrderMap.try_emplace(
8862 AttachPtrExpr, AttachPtrComputationOrderMap.size());
8863 AttachPtrComponentDepthMap.try_emplace(AttachPtrExpr, Depth);
8864 AttachPtrExprMap.try_emplace(Components, AttachPtrExpr);
8872 void generateAllInfoForClauses(
8873 ArrayRef<const OMPClause *> Clauses, MapCombinedInfoTy &CombinedInfo,
8874 llvm::OpenMPIRBuilder &OMPBuilder,
8875 const llvm::DenseSet<CanonicalDeclPtr<const Decl>> &SkipVarSet =
8876 llvm::DenseSet<CanonicalDeclPtr<const Decl>>())
const {
8881 llvm::MapVector<CanonicalDeclPtr<const Decl>,
8882 SmallVector<SmallVector<MapInfo, 8>, 4>>
8888 [&Info, &SkipVarSet](
8889 const ValueDecl *D, MapKind
Kind,
8892 ArrayRef<OpenMPMapModifierKind> MapModifiers,
8893 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
8894 bool ReturnDevicePointer,
bool IsImplicit,
const ValueDecl *Mapper,
8895 const Expr *VarRef =
nullptr,
bool ForDeviceAddr =
false) {
8896 if (SkipVarSet.contains(D))
8898 auto It = Info.try_emplace(D, Total).first;
8899 It->second[
Kind].emplace_back(
8900 L, MapType, MapModifiers, MotionModifiers, ReturnDevicePointer,
8901 IsImplicit, Mapper, VarRef, ForDeviceAddr);
8904 for (
const auto *
Cl : Clauses) {
8905 const auto *
C = dyn_cast<OMPMapClause>(
Cl);
8909 if (llvm::is_contained(
C->getMapTypeModifiers(),
8910 OMPC_MAP_MODIFIER_present))
8912 else if (
C->getMapType() == OMPC_MAP_alloc)
8914 const auto *EI =
C->getVarRefs().begin();
8915 for (
const auto L :
C->component_lists()) {
8916 const Expr *E = (
C->getMapLoc().isValid()) ? *EI :
nullptr;
8917 InfoGen(std::get<0>(L), Kind, std::get<1>(L),
C->getMapType(),
8918 C->getMapTypeModifiers(), {},
8919 false,
C->isImplicit(), std::get<2>(L),
8924 for (
const auto *
Cl : Clauses) {
8925 const auto *
C = dyn_cast<OMPToClause>(
Cl);
8929 if (llvm::is_contained(
C->getMotionModifiers(),
8930 OMPC_MOTION_MODIFIER_present))
8932 if (llvm::is_contained(
C->getMotionModifiers(),
8933 OMPC_MOTION_MODIFIER_iterator)) {
8934 if (
auto *IteratorExpr = dyn_cast<OMPIteratorExpr>(
8935 C->getIteratorModifier()->IgnoreParenImpCasts())) {
8936 const auto *VD =
cast<VarDecl>(IteratorExpr->getIteratorDecl(0));
8941 const auto *EI =
C->getVarRefs().begin();
8942 for (
const auto L :
C->component_lists()) {
8943 InfoGen(std::get<0>(L), Kind, std::get<1>(L), OMPC_MAP_to, {},
8944 C->getMotionModifiers(),
false,
8945 C->isImplicit(), std::get<2>(L), *EI);
8949 for (
const auto *
Cl : Clauses) {
8950 const auto *
C = dyn_cast<OMPFromClause>(
Cl);
8954 if (llvm::is_contained(
C->getMotionModifiers(),
8955 OMPC_MOTION_MODIFIER_present))
8957 if (llvm::is_contained(
C->getMotionModifiers(),
8958 OMPC_MOTION_MODIFIER_iterator)) {
8959 if (
auto *IteratorExpr = dyn_cast<OMPIteratorExpr>(
8960 C->getIteratorModifier()->IgnoreParenImpCasts())) {
8961 const auto *VD =
cast<VarDecl>(IteratorExpr->getIteratorDecl(0));
8966 const auto *EI =
C->getVarRefs().begin();
8967 for (
const auto L :
C->component_lists()) {
8968 InfoGen(std::get<0>(L), Kind, std::get<1>(L), OMPC_MAP_from, {},
8969 C->getMotionModifiers(),
8970 false,
C->isImplicit(), std::get<2>(L),
8983 MapCombinedInfoTy UseDeviceDataCombinedInfo;
8985 auto &&UseDeviceDataCombinedInfoGen =
8986 [&UseDeviceDataCombinedInfo](
const ValueDecl *VD, llvm::Value *Ptr,
8987 CodeGenFunction &CGF,
bool IsDevAddr,
8988 bool HasUdpFbNullify =
false) {
8989 UseDeviceDataCombinedInfo.Exprs.push_back(VD);
8990 UseDeviceDataCombinedInfo.BasePointers.emplace_back(Ptr);
8991 UseDeviceDataCombinedInfo.DevicePtrDecls.emplace_back(VD);
8992 UseDeviceDataCombinedInfo.DevicePointers.emplace_back(
8993 IsDevAddr ? DeviceInfoTy::Address : DeviceInfoTy::Pointer);
8999 UseDeviceDataCombinedInfo.Pointers.push_back(Ptr);
9000 UseDeviceDataCombinedInfo.Sizes.push_back(
9001 llvm::Constant::getNullValue(CGF.Int64Ty));
9002 OpenMPOffloadMappingFlags Flags =
9003 OpenMPOffloadMappingFlags::OMP_MAP_RETURN_PARAM;
9004 if (HasUdpFbNullify)
9005 Flags |= OpenMPOffloadMappingFlags::OMP_MAP_FB_NULLIFY;
9006 UseDeviceDataCombinedInfo.Types.push_back(Flags);
9007 UseDeviceDataCombinedInfo.HasAttachPtr.push_back(
false);
9008 UseDeviceDataCombinedInfo.Mappers.push_back(
nullptr);
9012 [&UseDeviceDataCombinedInfoGen](
9013 CodeGenFunction &CGF,
const Expr *IE,
const ValueDecl *VD,
9016 bool IsDevAddr,
bool IEIsAttachPtrForDevAddr =
false,
9017 bool HasUdpFbNullify =
false) {
9021 if (IsDevAddr && !IEIsAttachPtrForDevAddr) {
9022 if (IE->isGLValue())
9029 bool TreatDevAddrAsDevPtr = IEIsAttachPtrForDevAddr;
9036 UseDeviceDataCombinedInfoGen(VD, Ptr, CGF, IsDevAddr &&
9037 !TreatDevAddrAsDevPtr,
9041 auto &&IsMapInfoExist =
9042 [&Info,
this](CodeGenFunction &CGF,
const ValueDecl *VD,
const Expr *IE,
9043 const Expr *DesiredAttachPtrExpr,
bool IsDevAddr,
9044 bool HasUdpFbNullify =
false) ->
bool {
9052 if (It != Info.end()) {
9054 for (
auto &
Data : It->second) {
9055 MapInfo *CI =
nullptr;
9059 auto *It = llvm::find_if(
Data, [&](
const MapInfo &MI) {
9060 if (MI.Components.back().getAssociatedDeclaration() != VD)
9063 const Expr *MapAttachPtr = getAttachPtrExpr(MI.Components);
9064 bool Match = AttachPtrComparator.areEqual(MapAttachPtr,
9065 DesiredAttachPtrExpr);
9069 if (It !=
Data.end())
9074 CI->ForDeviceAddr =
true;
9075 CI->ReturnDevicePointer =
true;
9076 CI->HasUdpFbNullify = HasUdpFbNullify;
9080 auto PrevCI = std::next(CI->Components.rbegin());
9081 const auto *VarD = dyn_cast<VarDecl>(VD);
9082 const Expr *AttachPtrExpr = getAttachPtrExpr(CI->Components);
9083 if (CGF.CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory() ||
9085 !VD->getType().getNonReferenceType()->isPointerType() ||
9086 PrevCI == CI->Components.rend() ||
9088 VarD->hasLocalStorage() ||
9089 (isa_and_nonnull<DeclRefExpr>(AttachPtrExpr) &&
9091 CI->ForDeviceAddr = IsDevAddr;
9092 CI->ReturnDevicePointer =
true;
9093 CI->HasUdpFbNullify = HasUdpFbNullify;
9111 for (
const auto *
Cl : Clauses) {
9112 const auto *
C = dyn_cast<OMPUseDevicePtrClause>(
Cl);
9115 bool HasUdpFbNullify =
9116 C->getFallbackModifier() == OMPC_USE_DEVICE_PTR_FALLBACK_fb_nullify;
9117 for (
const auto L :
C->component_lists()) {
9120 assert(!Components.empty() &&
9121 "Not expecting empty list of components!");
9122 const ValueDecl *VD = Components.back().getAssociatedDeclaration();
9124 const Expr *IE = Components.back().getAssociatedExpression();
9132 const Expr *UDPOperandExpr =
9133 Components.front().getAssociatedExpression();
9134 if (IsMapInfoExist(CGF, VD, IE,
9136 false, HasUdpFbNullify))
9138 MapInfoGen(CGF, IE, VD, Components,
false,
9139 false, HasUdpFbNullify);
9143 llvm::SmallDenseSet<CanonicalDeclPtr<const Decl>, 4> Processed;
9144 for (
const auto *
Cl : Clauses) {
9145 const auto *
C = dyn_cast<OMPUseDeviceAddrClause>(
Cl);
9148 for (
const auto L :
C->component_lists()) {
9151 assert(!std::get<1>(L).empty() &&
9152 "Not expecting empty list of components!");
9153 const ValueDecl *VD = std::get<1>(L).back().getAssociatedDeclaration();
9154 if (!Processed.insert(VD).second)
9175 const Expr *UDAAttachPtrExpr = getAttachPtrExpr(Components);
9176 const Expr *IE = std::get<1>(L).back().getAssociatedExpression();
9177 assert((!UDAAttachPtrExpr || UDAAttachPtrExpr == IE) &&
9178 "use_device_addr operand has an attach-ptr, but does not match "
9179 "last component's expr.");
9180 if (IsMapInfoExist(CGF, VD, IE,
9184 MapInfoGen(CGF, IE, VD, Components,
9186 UDAAttachPtrExpr !=
nullptr);
9190 for (
const auto &
Data : Info) {
9191 MapCombinedInfoTy CurInfo;
9193 const ValueDecl *VD = cast_or_null<ValueDecl>(D);
9200 SmallVector<std::pair<const Expr *, MapInfo>, 16> AttachPtrMapInfoPairs;
9203 for (
const auto &M :
Data.second) {
9204 for (
const MapInfo &L : M) {
9205 assert(!L.Components.empty() &&
9206 "Not expecting declaration with no component lists.");
9208 const Expr *AttachPtrExpr = getAttachPtrExpr(L.Components);
9209 AttachPtrMapInfoPairs.emplace_back(AttachPtrExpr, L);
9214 llvm::stable_sort(AttachPtrMapInfoPairs,
9215 [
this](
const auto &LHS,
const auto &RHS) {
9216 return AttachPtrComparator(LHS.first, RHS.first);
9221 auto *It = AttachPtrMapInfoPairs.begin();
9222 while (It != AttachPtrMapInfoPairs.end()) {
9223 const Expr *AttachPtrExpr = It->first;
9225 SmallVector<MapInfo, 8> GroupLists;
9226 while (It != AttachPtrMapInfoPairs.end() &&
9227 (It->first == AttachPtrExpr ||
9228 AttachPtrComparator.areEqual(It->first, AttachPtrExpr))) {
9229 GroupLists.push_back(It->second);
9232 assert(!GroupLists.empty() &&
"GroupLists should not be empty");
9234 StructRangeInfoTy PartialStruct;
9235 AttachInfoTy AttachInfo;
9236 MapCombinedInfoTy GroupCurInfo;
9238 MapCombinedInfoTy GroupStructBaseCurInfo;
9239 for (
const MapInfo &L : GroupLists) {
9241 unsigned CurrentBasePointersIdx = GroupCurInfo.BasePointers.size();
9242 unsigned StructBasePointersIdx =
9243 GroupStructBaseCurInfo.BasePointers.size();
9245 GroupCurInfo.NonContigInfo.IsNonContiguous =
9246 L.Components.back().isNonContiguous();
9247 generateInfoForComponentList(
9248 L.MapType, L.MapModifiers, L.MotionModifiers, L.Components,
9249 GroupCurInfo, GroupStructBaseCurInfo, PartialStruct, AttachInfo,
9250 false, L.IsImplicit,
9251 true, L.Mapper, L.ForDeviceAddr, VD,
9256 if (L.ReturnDevicePointer) {
9260 assert((CurrentBasePointersIdx < GroupCurInfo.BasePointers.size() ||
9261 StructBasePointersIdx <
9262 GroupStructBaseCurInfo.BasePointers.size()) &&
9263 "Unexpected number of mapped base pointers.");
9266 const ValueDecl *RelevantVD =
9267 L.Components.back().getAssociatedDeclaration();
9268 assert(RelevantVD &&
9269 "No relevant declaration related with device pointer??");
9276 auto SetDevicePointerInfo = [&](MapCombinedInfoTy &Info,
9278 Info.DevicePtrDecls[Idx] = RelevantVD;
9279 Info.DevicePointers[Idx] = L.ForDeviceAddr
9280 ? DeviceInfoTy::Address
9281 : DeviceInfoTy::Pointer;
9283 OpenMPOffloadMappingFlags::OMP_MAP_RETURN_PARAM;
9284 if (L.HasUdpFbNullify)
9286 OpenMPOffloadMappingFlags::OMP_MAP_FB_NULLIFY;
9289 if (StructBasePointersIdx <
9290 GroupStructBaseCurInfo.BasePointers.size())
9291 SetDevicePointerInfo(GroupStructBaseCurInfo,
9292 StructBasePointersIdx);
9294 SetDevicePointerInfo(GroupCurInfo, CurrentBasePointersIdx);
9300 MapCombinedInfoTy GroupUnionCurInfo;
9301 GroupUnionCurInfo.append(GroupStructBaseCurInfo);
9302 GroupUnionCurInfo.append(GroupCurInfo);
9306 if (PartialStruct.Base.isValid()) {
9314 GroupUnionCurInfo.NonContigInfo.Dims.insert(
9315 GroupUnionCurInfo.NonContigInfo.Dims.begin(), 1);
9317 CurInfo, GroupUnionCurInfo.Types, PartialStruct, AttachInfo,
9318 !VD, OMPBuilder, VD,
9319 CombinedInfo.BasePointers.size(),
9325 CurInfo.append(GroupUnionCurInfo);
9326 if (AttachInfo.isValid())
9327 emitAttachEntry(CGF, CurInfo, AttachInfo);
9331 CombinedInfo.append(CurInfo);
9334 CombinedInfo.append(UseDeviceDataCombinedInfo);
9338 MappableExprsHandler(
const OMPExecutableDirective &Dir, CodeGenFunction &CGF)
9339 : CurDir(&Dir), CGF(CGF), AttachPtrComparator(*this) {
9341 for (
const auto *
C : Dir.getClausesOfKind<OMPFirstprivateClause>())
9342 for (
const auto *D :
C->varlist())
9343 FirstPrivateDecls.try_emplace(
9346 for (
const auto *
C : Dir.getClausesOfKind<OMPUsesAllocatorsClause>()) {
9347 for (unsigned I = 0, E = C->getNumberOfAllocators(); I < E; ++I) {
9348 OMPUsesAllocatorsClause::Data D = C->getAllocatorData(I);
9349 if (const auto *DRE = dyn_cast_or_null<DeclRefExpr>(D.AllocatorTraits))
9350 FirstPrivateDecls.try_emplace(cast<VarDecl>(DRE->getDecl()),
9352 else if (const auto *VD = dyn_cast<VarDecl>(
9353 cast<DeclRefExpr>(D.Allocator->IgnoreParenImpCasts())
9355 FirstPrivateDecls.try_emplace(VD, true);
9359 for (
const auto *
C : Dir.getClausesOfKind<OMPDefaultmapClause>())
9360 if (
C->getDefaultmapModifier() == OMPC_DEFAULTMAP_MODIFIER_firstprivate)
9361 DefaultmapFirstprivateKinds.insert(
C->getDefaultmapKind());
9363 for (
const auto *
C : Dir.getClausesOfKind<OMPIsDevicePtrClause>())
9364 for (
auto L :
C->component_lists())
9365 DevPointersMap[std::get<0>(L)].push_back(std::get<1>(L));
9367 for (
const auto *
C : Dir.getClausesOfKind<OMPHasDeviceAddrClause>())
9368 for (
auto L :
C->component_lists())
9369 HasDevAddrsMap[std::get<0>(L)].push_back(std::get<1>(L));
9371 for (
const auto *
C : Dir.getClausesOfKind<OMPMapClause>()) {
9372 if (C->getMapType() != OMPC_MAP_to)
9374 for (auto L : C->component_lists()) {
9375 const ValueDecl *VD = std::get<0>(L);
9376 const auto *RD = VD ? VD->getType()
9378 .getNonReferenceType()
9379 ->getAsCXXRecordDecl()
9381 if (RD && RD->isLambda())
9382 LambdasMap.try_emplace(std::get<0>(L), C);
9386 auto CollectAttachPtrExprsForClauseComponents = [
this](
const auto *
C) {
9387 for (
auto L :
C->component_lists()) {
9390 if (!Components.empty())
9391 collectAttachPtrExprInfo(Components, CurDir);
9397 for (
const auto *
C : Dir.getClausesOfKind<OMPMapClause>())
9398 CollectAttachPtrExprsForClauseComponents(
C);
9399 for (
const auto *
C : Dir.getClausesOfKind<OMPToClause>())
9400 CollectAttachPtrExprsForClauseComponents(
C);
9401 for (
const auto *
C : Dir.getClausesOfKind<OMPFromClause>())
9402 CollectAttachPtrExprsForClauseComponents(
C);
9403 for (
const auto *
C : Dir.getClausesOfKind<OMPUseDevicePtrClause>())
9404 CollectAttachPtrExprsForClauseComponents(
C);
9405 for (
const auto *
C : Dir.getClausesOfKind<OMPUseDeviceAddrClause>())
9406 CollectAttachPtrExprsForClauseComponents(
C);
9407 for (
const auto *
C : Dir.getClausesOfKind<OMPIsDevicePtrClause>())
9408 CollectAttachPtrExprsForClauseComponents(
C);
9409 for (
const auto *
C : Dir.getClausesOfKind<OMPHasDeviceAddrClause>())
9410 CollectAttachPtrExprsForClauseComponents(
C);
9414 MappableExprsHandler(
const OMPDeclareMapperDecl &Dir,
CodeGenFunction &CGF)
9415 : CurDir(&Dir), CGF(CGF), AttachPtrComparator(*this) {
9416 auto CollectAttachPtrExprsForClauseComponents = [
this](
const auto *
C) {
9417 for (
auto L :
C->component_lists()) {
9420 if (!Components.empty())
9421 collectAttachPtrExprInfo(Components, CurDir);
9429 if (const auto *C = dyn_cast<OMPMapClause>(Cl))
9430 CollectAttachPtrExprsForClauseComponents(C);
9431 else if (const auto *C = dyn_cast<OMPToClause>(Cl))
9432 CollectAttachPtrExprsForClauseComponents(C);
9433 else if (const auto *C = dyn_cast<OMPFromClause>(Cl))
9434 CollectAttachPtrExprsForClauseComponents(C);
9446 void emitCombinedEntry(MapCombinedInfoTy &CombinedInfo,
9447 MapFlagsArrayTy &CurTypes,
9448 const StructRangeInfoTy &PartialStruct,
9449 AttachInfoTy &AttachInfo,
bool IsMapThis,
9450 llvm::OpenMPIRBuilder &OMPBuilder,
const ValueDecl *VD,
9451 unsigned OffsetForMemberOfFlag,
9452 bool NotTargetParams)
const {
9453 if (CurTypes.size() == 1 &&
9454 ((CurTypes.back() & OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF) !=
9455 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF) &&
9456 !PartialStruct.IsArraySection)
9458 Address LBAddr = PartialStruct.LowestElem.second;
9459 Address HBAddr = PartialStruct.HighestElem.second;
9460 if (PartialStruct.HasCompleteRecord) {
9461 LBAddr = PartialStruct.LB;
9462 HBAddr = PartialStruct.LB;
9464 CombinedInfo.Exprs.push_back(VD);
9466 CombinedInfo.BasePointers.push_back(PartialStruct.Base.emitRawPointer(CGF));
9467 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
9468 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
9471 const CXXMethodDecl *MD =
9473 const CXXRecordDecl *RD = MD ? MD->
getParent() :
nullptr;
9474 bool HasBaseClass = RD && IsMapThis ? RD->
getNumBases() > 0 :
false;
9484 CombinedInfo.Pointers.push_back(PartialStruct.Base.emitRawPointer(CGF));
9489 CombinedInfo.Sizes.push_back(Size);
9491 CombinedInfo.Pointers.push_back(LB);
9494 llvm::Value *HAddr = CGF.
Builder.CreateConstGEP1_32(
9498 llvm::Value *Diff = CGF.
Builder.CreatePtrDiff(CHAddr, CLAddr);
9501 CombinedInfo.Sizes.push_back(Size);
9503 CombinedInfo.Mappers.push_back(
nullptr);
9505 CombinedInfo.Types.push_back(
9506 NotTargetParams ? OpenMPOffloadMappingFlags::OMP_MAP_NONE
9507 : !PartialStruct.PreliminaryMapData.BasePointers.empty()
9508 ? OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ
9509 : OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM);
9517 CombinedInfo.HasAttachPtr.push_back(AttachInfo.isValid());
9520 if (CurTypes.end() !=
9521 llvm::find_if(CurTypes, [](OpenMPOffloadMappingFlags
Type) {
9522 return static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>>(
9523 Type & OpenMPOffloadMappingFlags::OMP_MAP_PRESENT);
9525 CombinedInfo.Types.back() |= OpenMPOffloadMappingFlags::OMP_MAP_PRESENT;
9527 (*CurTypes.begin()) &= ~OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM;
9534 if (CurTypes.end() !=
9535 llvm::find_if(CurTypes, [](OpenMPOffloadMappingFlags
Type) {
9536 return static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>>(
9537 Type & OpenMPOffloadMappingFlags::OMP_MAP_OMPX_HOLD);
9539 CombinedInfo.Types.back() |= OpenMPOffloadMappingFlags::OMP_MAP_OMPX_HOLD;
9540 for (
auto &M : CurTypes)
9541 M |= OpenMPOffloadMappingFlags::OMP_MAP_OMPX_HOLD;
9548 OpenMPOffloadMappingFlags MemberOfFlag = OMPBuilder.getMemberOfFlag(
9549 OffsetForMemberOfFlag + CombinedInfo.BasePointers.size() - 1);
9550 for (
auto &M : CurTypes)
9551 OMPBuilder.setCorrectMemberOfFlag(M, MemberOfFlag);
9568 if (AttachInfo.isValid())
9569 AttachInfo.AttachPteeAddr = LBAddr;
9577 void generateAllInfo(
9578 MapCombinedInfoTy &CombinedInfo, llvm::OpenMPIRBuilder &OMPBuilder,
9579 const llvm::DenseSet<CanonicalDeclPtr<const Decl>> &SkipVarSet =
9580 llvm::DenseSet<CanonicalDeclPtr<const Decl>>())
const {
9582 "Expect a executable directive");
9584 generateAllInfoForClauses(CurExecDir->clauses(), CombinedInfo, OMPBuilder,
9591 void generateAllInfoForMapper(MapCombinedInfoTy &CombinedInfo,
9592 llvm::OpenMPIRBuilder &OMPBuilder)
const {
9594 "Expect a declare mapper directive");
9596 generateAllInfoForClauses(CurMapperDir->clauses(), CombinedInfo,
9601 void generateInfoForLambdaCaptures(
9602 const ValueDecl *VD, llvm::Value *Arg, MapCombinedInfoTy &CombinedInfo,
9603 llvm::DenseMap<llvm::Value *, llvm::Value *> &LambdaPointers)
const {
9611 llvm::DenseMap<const ValueDecl *, FieldDecl *> Captures;
9612 FieldDecl *ThisCapture =
nullptr;
9618 LambdaPointers.try_emplace(ThisLVal.getPointer(CGF),
9619 VDLVal.getPointer(CGF));
9620 CombinedInfo.Exprs.push_back(VD);
9621 CombinedInfo.BasePointers.push_back(ThisLVal.getPointer(CGF));
9622 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
9623 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
9624 CombinedInfo.Pointers.push_back(ThisLValVal.getPointer(CGF));
9625 CombinedInfo.Sizes.push_back(
9628 CombinedInfo.Types.push_back(
9629 OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ |
9630 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL |
9631 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF |
9632 OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT);
9633 CombinedInfo.HasAttachPtr.push_back(
false);
9634 CombinedInfo.Mappers.push_back(
nullptr);
9636 for (
const LambdaCapture &LC : RD->
captures()) {
9637 if (!LC.capturesVariable())
9642 auto It = Captures.find(VD);
9643 assert(It != Captures.end() &&
"Found lambda capture without field.");
9647 LambdaPointers.try_emplace(VarLVal.getPointer(CGF),
9648 VDLVal.getPointer(CGF));
9649 CombinedInfo.Exprs.push_back(VD);
9650 CombinedInfo.BasePointers.push_back(VarLVal.getPointer(CGF));
9651 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
9652 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
9653 CombinedInfo.Pointers.push_back(VarLValVal.getPointer(CGF));
9654 CombinedInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
9660 LambdaPointers.try_emplace(VarLVal.getPointer(CGF),
9661 VDLVal.getPointer(CGF));
9662 CombinedInfo.Exprs.push_back(VD);
9663 CombinedInfo.BasePointers.push_back(VarLVal.getPointer(CGF));
9664 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
9665 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
9666 CombinedInfo.Pointers.push_back(VarRVal.
getScalarVal());
9667 CombinedInfo.Sizes.push_back(llvm::ConstantInt::get(CGF.
Int64Ty, 0));
9669 CombinedInfo.Types.push_back(
9670 OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ |
9671 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL |
9672 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF |
9673 OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT);
9674 CombinedInfo.HasAttachPtr.push_back(
false);
9675 CombinedInfo.Mappers.push_back(
nullptr);
9680 void adjustMemberOfForLambdaCaptures(
9681 llvm::OpenMPIRBuilder &OMPBuilder,
9682 const llvm::DenseMap<llvm::Value *, llvm::Value *> &LambdaPointers,
9683 MapBaseValuesArrayTy &BasePointers, MapValuesArrayTy &Pointers,
9684 MapFlagsArrayTy &Types)
const {
9685 for (
unsigned I = 0, E = Types.size(); I < E; ++I) {
9687 if (Types[I] != (OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ |
9688 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL |
9689 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF |
9690 OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT))
9692 llvm::Value *BasePtr = LambdaPointers.lookup(BasePointers[I]);
9693 assert(BasePtr &&
"Unable to find base lambda address.");
9695 for (
unsigned J = I; J > 0; --J) {
9696 unsigned Idx = J - 1;
9697 if (Pointers[Idx] != BasePtr)
9702 assert(TgtIdx != -1 &&
"Unable to find parent lambda.");
9706 OpenMPOffloadMappingFlags MemberOfFlag =
9707 OMPBuilder.getMemberOfFlag(TgtIdx);
9708 OMPBuilder.setCorrectMemberOfFlag(Types[I], MemberOfFlag);
9714 void populateComponentListsForNonLambdaCaptureFromClauses(
9715 const ValueDecl *VD, MapDataArrayTy &DeclComponentLists,
9717 SmallVector<OMPClauseMappableExprCommon::MappableComponent, 8>>
9718 &StorageForImplicitlyAddedComponentLists)
const {
9719 if (VD && LambdasMap.count(VD))
9725 auto It = DevPointersMap.find(VD);
9726 if (It != DevPointersMap.end())
9727 for (
const auto &MCL : It->second)
9728 DeclComponentLists.emplace_back(MCL, OMPC_MAP_to,
Unknown,
9731 auto I = HasDevAddrsMap.find(VD);
9732 if (I != HasDevAddrsMap.end())
9733 for (
const auto &MCL : I->second)
9734 DeclComponentLists.emplace_back(MCL, OMPC_MAP_tofrom,
Unknown,
9738 "Expect a executable directive");
9740 for (
const auto *
C : CurExecDir->getClausesOfKind<OMPMapClause>()) {
9741 const auto *EI =
C->getVarRefs().begin();
9742 for (
const auto L :
C->decl_component_lists(VD)) {
9743 const ValueDecl *VDecl, *Mapper;
9745 const Expr *E = (
C->getMapLoc().isValid()) ? *EI :
nullptr;
9747 std::tie(VDecl, Components, Mapper) = L;
9748 assert(VDecl == VD &&
"We got information for the wrong declaration??");
9749 assert(!Components.empty() &&
9750 "Not expecting declaration with no component lists.");
9751 DeclComponentLists.emplace_back(Components,
C->getMapType(),
9752 C->getMapTypeModifiers(),
9753 C->isImplicit(), Mapper, E);
9762 addImplicitMapForAttachPtrBaseIfMemberOfCapturedVD(
9763 VD, DeclComponentLists, StorageForImplicitlyAddedComponentLists);
9765 llvm::stable_sort(DeclComponentLists, [](
const MapData &LHS,
9766 const MapData &RHS) {
9767 ArrayRef<OpenMPMapModifierKind> MapModifiers = std::get<2>(LHS);
9770 llvm::is_contained(MapModifiers, clang::OMPC_MAP_MODIFIER_present);
9771 bool HasAllocs = MapType == OMPC_MAP_alloc;
9772 MapModifiers = std::get<2>(RHS);
9773 MapType = std::get<1>(LHS);
9775 llvm::is_contained(MapModifiers, clang::OMPC_MAP_MODIFIER_present);
9776 bool HasAllocsR = MapType == OMPC_MAP_alloc;
9777 return (HasPresent && !HasPresentR) || (HasAllocs && !HasAllocsR);
9813 void addImplicitMapForAttachPtrBaseIfMemberOfCapturedVD(
9814 const ValueDecl *CapturedVD, MapDataArrayTy &DeclComponentLists,
9816 SmallVector<OMPClauseMappableExprCommon::MappableComponent, 8>>
9817 &ComponentVectorStorage)
const {
9818 bool IsThisCapture = CapturedVD ==
nullptr;
9820 for (
const auto &ComponentsAndAttachPtr : AttachPtrExprMap) {
9822 ComponentsWithAttachPtr = ComponentsAndAttachPtr.first;
9823 const Expr *AttachPtrExpr = ComponentsAndAttachPtr.second;
9827 const auto *ME = dyn_cast<MemberExpr>(AttachPtrExpr);
9831 const Expr *
Base = ME->getBase()->IgnoreParenImpCasts();
9852 bool FoundExistingMap =
false;
9853 for (
const MapData &ExistingL : DeclComponentLists) {
9855 ExistingComponents = std::get<0>(ExistingL);
9857 if (ExistingComponents.empty())
9861 const auto &FirstComponent = ExistingComponents.front();
9862 const Expr *FirstExpr = FirstComponent.getAssociatedExpression();
9868 if (AttachPtrComparator.areEqual(FirstExpr, AttachPtrExpr)) {
9869 FoundExistingMap =
true;
9874 if (IsThisCapture) {
9875 if (
const auto *OASE = dyn_cast<ArraySectionExpr>(FirstExpr)) {
9877 FoundExistingMap =
true;
9886 if (
const auto *DRE = dyn_cast<DeclRefExpr>(FirstExpr)) {
9887 if (DRE->getDecl() == CapturedVD) {
9888 FoundExistingMap =
true;
9894 if (FoundExistingMap)
9900 ComponentVectorStorage.emplace_back();
9901 auto &AttachPtrComponents = ComponentVectorStorage.back();
9904 bool SeenAttachPtrComponent =
false;
9910 for (
size_t i = 0; i < ComponentsWithAttachPtr.size(); ++i) {
9911 const auto &Component = ComponentsWithAttachPtr[i];
9912 const Expr *ComponentExpr = Component.getAssociatedExpression();
9914 if (!SeenAttachPtrComponent && ComponentExpr != AttachPtrExpr)
9916 SeenAttachPtrComponent =
true;
9918 AttachPtrComponents.emplace_back(Component.getAssociatedExpression(),
9919 Component.getAssociatedDeclaration(),
9920 Component.isNonContiguous());
9922 assert(!AttachPtrComponents.empty() &&
9923 "Could not populate component-lists for mapping attach-ptr");
9925 DeclComponentLists.emplace_back(
9926 AttachPtrComponents, OMPC_MAP_tofrom,
Unknown,
9927 true,
nullptr, AttachPtrExpr);
9934 void generateInfoForCaptureFromClauseInfo(
9935 const MapDataArrayTy &DeclComponentListsFromClauses,
9936 const CapturedStmt::Capture *Cap, llvm::Value *Arg,
9937 MapCombinedInfoTy &CurCaptureVarInfo, llvm::OpenMPIRBuilder &OMPBuilder,
9938 unsigned OffsetForMemberOfFlag)
const {
9940 "Not expecting to generate map info for a variable array type!");
9949 if (LambdasMap.count(VD))
9955 if (VD && (DevPointersMap.count(VD) || HasDevAddrsMap.count(VD))) {
9956 CurCaptureVarInfo.Exprs.push_back(VD);
9957 CurCaptureVarInfo.BasePointers.emplace_back(Arg);
9958 CurCaptureVarInfo.DevicePtrDecls.emplace_back(VD);
9959 CurCaptureVarInfo.DevicePointers.emplace_back(DeviceInfoTy::Pointer);
9960 CurCaptureVarInfo.Pointers.push_back(Arg);
9961 CurCaptureVarInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
9964 CurCaptureVarInfo.Types.push_back(
9965 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL |
9966 OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM);
9967 CurCaptureVarInfo.HasAttachPtr.push_back(
false);
9968 CurCaptureVarInfo.Mappers.push_back(
nullptr);
9972 auto GenerateInfoForComponentLists =
9973 [&](ArrayRef<MapData> DeclComponentListsFromClauses,
9974 bool IsEligibleForTargetParamFlag) {
9975 MapCombinedInfoTy CurInfoForComponentLists;
9976 StructRangeInfoTy PartialStruct;
9977 AttachInfoTy AttachInfo;
9979 if (DeclComponentListsFromClauses.empty())
9982 generateInfoForCaptureFromComponentLists(
9983 VD, DeclComponentListsFromClauses, CurInfoForComponentLists,
9984 PartialStruct, AttachInfo, IsEligibleForTargetParamFlag);
9989 if (PartialStruct.Base.isValid()) {
9990 CurCaptureVarInfo.append(PartialStruct.PreliminaryMapData);
9992 CurCaptureVarInfo, CurInfoForComponentLists.Types,
9993 PartialStruct, AttachInfo, Cap->
capturesThis(), OMPBuilder,
9994 nullptr, OffsetForMemberOfFlag,
9995 !IsEligibleForTargetParamFlag);
10000 CurCaptureVarInfo.append(CurInfoForComponentLists);
10001 if (AttachInfo.isValid())
10002 emitAttachEntry(CGF, CurCaptureVarInfo, AttachInfo);
10026 SmallVector<std::pair<const Expr *, MapData>, 16> AttachPtrMapDataPairs;
10028 for (
const MapData &L : DeclComponentListsFromClauses) {
10031 const Expr *AttachPtrExpr = getAttachPtrExpr(Components);
10032 AttachPtrMapDataPairs.emplace_back(AttachPtrExpr, L);
10036 llvm::stable_sort(AttachPtrMapDataPairs,
10037 [
this](
const auto &LHS,
const auto &RHS) {
10038 return AttachPtrComparator(LHS.first, RHS.first);
10041 bool NoDefaultMappingDoneForVD = CurCaptureVarInfo.BasePointers.empty();
10042 bool IsFirstGroup =
true;
10046 auto *It = AttachPtrMapDataPairs.begin();
10047 while (It != AttachPtrMapDataPairs.end()) {
10048 const Expr *AttachPtrExpr = It->first;
10050 MapDataArrayTy GroupLists;
10051 while (It != AttachPtrMapDataPairs.end() &&
10052 (It->first == AttachPtrExpr ||
10053 AttachPtrComparator.areEqual(It->first, AttachPtrExpr))) {
10054 GroupLists.push_back(It->second);
10057 assert(!GroupLists.empty() &&
"GroupLists should not be empty");
10062 bool IsEligibleForTargetParamFlag =
10063 IsFirstGroup && NoDefaultMappingDoneForVD;
10065 GenerateInfoForComponentLists(GroupLists, IsEligibleForTargetParamFlag);
10066 IsFirstGroup =
false;
10073 void generateInfoForCaptureFromComponentLists(
10074 const ValueDecl *VD, ArrayRef<MapData> DeclComponentLists,
10075 MapCombinedInfoTy &CurComponentListInfo, StructRangeInfoTy &PartialStruct,
10076 AttachInfoTy &AttachInfo,
bool IsListEligibleForTargetParamFlag)
const {
10078 llvm::SmallDenseMap<
10085 for (
const MapData &L : DeclComponentLists) {
10088 ArrayRef<OpenMPMapModifierKind> MapModifiers;
10090 const ValueDecl *Mapper;
10091 const Expr *VarRef;
10092 std::tie(Components, MapType, MapModifiers, IsImplicit, Mapper, VarRef) =
10095 for (
const MapData &L1 : ArrayRef(DeclComponentLists).slice(Count)) {
10097 std::tie(Components1, MapType, MapModifiers, IsImplicit, Mapper,
10099 auto CI = Components.rbegin();
10100 auto CE = Components.rend();
10101 auto SI = Components1.rbegin();
10102 auto SE = Components1.rend();
10103 for (; CI != CE && SI != SE; ++CI, ++SI) {
10104 if (CI->getAssociatedExpression()->getStmtClass() !=
10105 SI->getAssociatedExpression()->getStmtClass())
10108 if (CI->getAssociatedDeclaration() != SI->getAssociatedDeclaration())
10113 if (CI == CE || SI == SE) {
10115 if (CI == CE && SI == SE)
10117 const auto It = (SI == SE) ? CI : SI;
10124 (std::prev(It)->getAssociatedDeclaration() &&
10126 ->getAssociatedDeclaration()
10128 ->isPointerType()) ||
10129 (It->getAssociatedDeclaration() &&
10130 It->getAssociatedDeclaration()->getType()->isPointerType() &&
10131 std::next(It) != CE && std::next(It) != SE))
10133 const MapData &BaseData = CI == CE ? L : L1;
10135 SI == SE ? Components : Components1;
10136 OverlappedData[&BaseData].push_back(SubData);
10141 llvm::SmallVector<const FieldDecl *, 4> Layout;
10142 if (!OverlappedData.empty()) {
10145 while (BaseType != OrigType) {
10151 getPlainLayout(CRD, Layout,
false);
10157 for (
auto &Pair : OverlappedData) {
10164 auto CI = First.rbegin();
10165 auto CE = First.rend();
10166 auto SI = Second.rbegin();
10167 auto SE = Second.rend();
10168 for (; CI != CE && SI != SE; ++CI, ++SI) {
10169 if (CI->getAssociatedExpression()->getStmtClass() !=
10170 SI->getAssociatedExpression()->getStmtClass())
10173 if (CI->getAssociatedDeclaration() !=
10174 SI->getAssociatedDeclaration())
10179 if (CI == CE && SI == SE)
10183 if (CI == CE || SI == SE)
10188 if (FD1->getParent() == FD2->getParent())
10189 return FD1->getFieldIndex() < FD2->getFieldIndex();
10191 llvm::find_if(Layout, [FD1, FD2](
const FieldDecl *FD) {
10192 return FD == FD1 || FD == FD2;
10200 bool AddTargetParamFlag = IsListEligibleForTargetParamFlag;
10201 MapCombinedInfoTy StructBaseCombinedInfo;
10202 for (
const auto &Pair : OverlappedData) {
10203 const MapData &L = *Pair.getFirst();
10206 ArrayRef<OpenMPMapModifierKind> MapModifiers;
10208 const ValueDecl *Mapper;
10209 const Expr *VarRef;
10210 std::tie(Components, MapType, MapModifiers, IsImplicit, Mapper, VarRef) =
10212 ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef>
10213 OverlappedComponents = Pair.getSecond();
10214 generateInfoForComponentList(
10215 MapType, MapModifiers, {}, Components, CurComponentListInfo,
10216 StructBaseCombinedInfo, PartialStruct, AttachInfo, AddTargetParamFlag,
10217 IsImplicit,
false, Mapper,
10218 false, VD, VarRef, OverlappedComponents);
10219 AddTargetParamFlag =
false;
10222 for (
const MapData &L : DeclComponentLists) {
10225 ArrayRef<OpenMPMapModifierKind> MapModifiers;
10227 const ValueDecl *Mapper;
10228 const Expr *VarRef;
10229 std::tie(Components, MapType, MapModifiers, IsImplicit, Mapper, VarRef) =
10231 auto It = OverlappedData.find(&L);
10232 if (It == OverlappedData.end())
10233 generateInfoForComponentList(
10234 MapType, MapModifiers, {}, Components, CurComponentListInfo,
10235 StructBaseCombinedInfo, PartialStruct, AttachInfo,
10236 AddTargetParamFlag, IsImplicit,
false,
10237 Mapper,
false, VD, VarRef,
10239 AddTargetParamFlag =
false;
10245 bool isEffectivelyFirstprivate(
const VarDecl *VD, QualType
Type)
const {
10247 auto I = FirstPrivateDecls.find(VD);
10248 if (I != FirstPrivateDecls.end() && !I->getSecond())
10252 if (DefaultmapFirstprivateKinds.count(OMPC_DEFAULTMAP_scalar)) {
10253 if (
Type->isScalarType())
10258 if (DefaultmapFirstprivateKinds.count(OMPC_DEFAULTMAP_pointer)) {
10259 if (
Type->isAnyPointerType())
10264 if (DefaultmapFirstprivateKinds.count(OMPC_DEFAULTMAP_aggregate)) {
10265 if (
Type->isAggregateType())
10270 return DefaultmapFirstprivateKinds.count(OMPC_DEFAULTMAP_all);
10275 void generateDefaultMapInfo(
const CapturedStmt::Capture &CI,
10276 const FieldDecl &RI, llvm::Value *CV,
10277 MapCombinedInfoTy &CombinedInfo)
const {
10278 bool IsImplicit =
true;
10281 CombinedInfo.Exprs.push_back(
nullptr);
10282 CombinedInfo.BasePointers.push_back(CV);
10283 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
10284 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
10285 CombinedInfo.Pointers.push_back(CV);
10287 CombinedInfo.Sizes.push_back(
10291 CombinedInfo.Types.push_back(OpenMPOffloadMappingFlags::OMP_MAP_TO |
10292 OpenMPOffloadMappingFlags::OMP_MAP_FROM);
10296 CombinedInfo.BasePointers.push_back(CV);
10297 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
10298 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
10299 CombinedInfo.Pointers.push_back(CV);
10300 bool IsFirstprivate =
10306 CombinedInfo.Types.push_back(
10307 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL);
10308 CombinedInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
10310 }
else if (IsFirstprivate) {
10313 CombinedInfo.Types.push_back(
10314 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL);
10316 CombinedInfo.Sizes.push_back(llvm::Constant::getNullValue(CGF.
Int64Ty));
10320 CombinedInfo.Types.push_back(OpenMPOffloadMappingFlags::OMP_MAP_NONE);
10321 CombinedInfo.Sizes.push_back(llvm::Constant::getNullValue(CGF.
Int64Ty));
10323 auto I = FirstPrivateDecls.find(VD);
10324 if (I != FirstPrivateDecls.end())
10325 IsImplicit = I->getSecond();
10331 bool IsFirstprivate = isEffectivelyFirstprivate(VD, ElementType);
10333 CombinedInfo.BasePointers.push_back(CV);
10334 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
10335 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
10340 CombinedInfo.Pointers.push_back(CV);
10342 CombinedInfo.Sizes.push_back(llvm::Constant::getNullValue(CGF.
Int64Ty));
10343 CombinedInfo.Types.push_back(
10344 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL);
10346 CombinedInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
10351 CombinedInfo.Types.push_back(getMapModifiersForPrivateClauses(CI));
10352 CombinedInfo.Pointers.push_back(CV);
10354 auto I = FirstPrivateDecls.find(VD);
10355 if (I != FirstPrivateDecls.end())
10356 IsImplicit = I->getSecond();
10359 CombinedInfo.Types.back() |=
10360 OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM;
10364 CombinedInfo.Types.back() |= OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT;
10366 CombinedInfo.HasAttachPtr.push_back(
false);
10368 CombinedInfo.Mappers.push_back(
nullptr);
10380 dyn_cast<MemberExpr>(OASE->getBase()->IgnoreParenImpCasts()))
10381 return ME->getMemberDecl();
10387static llvm::Constant *
10389 MappableExprsHandler::MappingExprInfo &MapExprs) {
10392 if (!MapExprs.getMapDecl() && !MapExprs.getMapExpr())
10393 return OMPBuilder.getOrCreateDefaultSrcLocStr(SrcLocStrSize);
10396 if (!MapExprs.getMapDecl() && MapExprs.getMapExpr()) {
10400 Loc = MapExprs.getMapExpr()->getExprLoc();
10402 Loc = MapExprs.getMapDecl()->getLocation();
10405 std::string ExprName;
10406 if (MapExprs.getMapExpr()) {
10408 llvm::raw_string_ostream OS(ExprName);
10409 MapExprs.getMapExpr()->printPretty(OS,
nullptr, P);
10411 ExprName = MapExprs.getMapDecl()->getNameAsString();
10420 return OMPBuilder.getOrCreateSrcLocStr(
FileName, ExprName, PLoc.
getLine(),
10427 CodeGenFunction &CGF, MappableExprsHandler::MapCombinedInfoTy &CombinedInfo,
10429 bool IsNonContiguous =
false,
bool ForEndCall =
false) {
10432 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
10435 InsertPointTy CodeGenIP(CGF.
Builder.GetInsertBlock(),
10436 CGF.
Builder.GetInsertPoint());
10438 auto DeviceAddrCB = [&](
unsigned int I, llvm::Value *NewDecl) {
10439 if (
const ValueDecl *DevVD = CombinedInfo.DevicePtrDecls[I]) {
10444 auto CustomMapperCB = [&](
unsigned int I) {
10445 llvm::Function *MFunc =
nullptr;
10446 if (CombinedInfo.Mappers[I]) {
10447 Info.HasMapper =
true;
10453 cantFail(OMPBuilder.emitOffloadingArraysAndArgs(
10454 AllocaIP, CodeGenIP, Info, Info.RTArgs, CombinedInfo, CustomMapperCB,
10455 IsNonContiguous, ForEndCall, DeviceAddrCB));
10459static const OMPExecutableDirective *
10461 const auto *CS = D.getInnermostCapturedStmt();
10464 const Stmt *ChildStmt =
10467 if (
const auto *NestedDir =
10468 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) {
10470 switch (D.getDirectiveKind()) {
10476 if (DKind == OMPD_teams) {
10477 Body = NestedDir->getInnermostCapturedStmt()->IgnoreContainers(
10482 if (
const auto *NND =
10483 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) {
10484 DKind = NND->getDirectiveKind();
10490 case OMPD_target_teams:
10494 case OMPD_target_parallel:
10495 case OMPD_target_simd:
10496 case OMPD_target_parallel_for:
10497 case OMPD_target_parallel_for_simd:
10499 case OMPD_target_teams_distribute:
10500 case OMPD_target_teams_distribute_simd:
10501 case OMPD_target_teams_distribute_parallel_for:
10502 case OMPD_target_teams_distribute_parallel_for_simd:
10503 case OMPD_parallel:
10505 case OMPD_parallel_for:
10506 case OMPD_parallel_master:
10507 case OMPD_parallel_sections:
10508 case OMPD_for_simd:
10509 case OMPD_parallel_for_simd:
10511 case OMPD_cancellation_point:
10513 case OMPD_threadprivate:
10514 case OMPD_allocate:
10519 case OMPD_sections:
10523 case OMPD_critical:
10524 case OMPD_taskyield:
10526 case OMPD_taskwait:
10527 case OMPD_taskgroup:
10533 case OMPD_target_data:
10534 case OMPD_target_exit_data:
10535 case OMPD_target_enter_data:
10536 case OMPD_distribute:
10537 case OMPD_distribute_simd:
10538 case OMPD_distribute_parallel_for:
10539 case OMPD_distribute_parallel_for_simd:
10540 case OMPD_teams_distribute:
10541 case OMPD_teams_distribute_simd:
10542 case OMPD_teams_distribute_parallel_for:
10543 case OMPD_teams_distribute_parallel_for_simd:
10544 case OMPD_target_update:
10545 case OMPD_declare_simd:
10546 case OMPD_declare_variant:
10547 case OMPD_begin_declare_variant:
10548 case OMPD_end_declare_variant:
10549 case OMPD_declare_target:
10550 case OMPD_end_declare_target:
10551 case OMPD_declare_reduction:
10552 case OMPD_declare_mapper:
10553 case OMPD_taskloop:
10554 case OMPD_taskloop_simd:
10555 case OMPD_master_taskloop:
10556 case OMPD_master_taskloop_simd:
10557 case OMPD_parallel_master_taskloop:
10558 case OMPD_parallel_master_taskloop_simd:
10559 case OMPD_requires:
10560 case OMPD_metadirective:
10563 llvm_unreachable(
"Unexpected directive.");
10623 if (
UDMMap.count(D) > 0)
10627 auto *MapperVarDecl =
10629 CharUnits ElementSize =
C.getTypeSizeInChars(Ty);
10630 llvm::Type *ElemTy =
CGM.getTypes().ConvertTypeForMem(Ty);
10633 MappableExprsHandler::MapCombinedInfoTy CombinedInfo;
10634 auto PrivatizeAndGenMapInfoCB =
10635 [&](llvm::OpenMPIRBuilder::InsertPointTy CodeGenIP, llvm::Value *PtrPHI,
10636 llvm::Value *BeginArg) -> llvm::OpenMPIRBuilder::MapInfosTy & {
10637 MapperCGF.
Builder.restoreIP(CodeGenIP);
10647 Scope.addPrivate(MapperVarDecl, PtrCurrent);
10648 (void)
Scope.Privatize();
10651 MappableExprsHandler MEHandler(*D, MapperCGF);
10652 MEHandler.generateAllInfoForMapper(CombinedInfo,
OMPBuilder);
10654 auto FillInfoMap = [&](MappableExprsHandler::MappingExprInfo &MapExpr) {
10657 if (
CGM.getCodeGenOpts().getDebugInfo() !=
10658 llvm::codegenoptions::NoDebugInfo) {
10659 CombinedInfo.Names.resize(CombinedInfo.Exprs.size());
10660 llvm::transform(CombinedInfo.Exprs, CombinedInfo.Names.begin(),
10664 return CombinedInfo;
10667 auto CustomMapperCB = [&](
unsigned I) {
10668 llvm::Function *MapperFunc =
nullptr;
10669 if (CombinedInfo.Mappers[I]) {
10673 assert(MapperFunc &&
"Expect a valid mapper function is available.");
10679 llvm::raw_svector_ostream Out(TyStr);
10680 CGM.getCXXABI().getMangleContext().mangleCanonicalTypeName(Ty, Out);
10681 std::string Name =
getName({
"omp_mapper", TyStr, D->
getName()});
10687 bool PropagatePresentToPointee =
CGM.getLangOpts().OpenMP >= 60;
10688 llvm::Function *NewFn = cantFail(
OMPBuilder.emitUserDefinedMapper(
10689 PrivatizeAndGenMapInfoCB, ElemTy, Name, CustomMapperCB,
10690 false, PropagatePresentToPointee));
10691 UDMMap.try_emplace(D, NewFn);
10698 auto I =
UDMMap.find(D);
10702 return UDMMap.lookup(D);
10715 Kind != OMPD_target_teams_loop)
10718 return llvm::ConstantInt::get(CGF.
Int64Ty, 0);
10721 if (llvm::Value *NumIterations = SizeEmitter(CGF, *LD))
10722 return NumIterations;
10723 return llvm::ConstantInt::get(CGF.
Int64Ty, 0);
10732 if (OffloadingMandatory) {
10733 CGF.
Builder.CreateUnreachable();
10735 if (RequiresOuterTask) {
10736 CapturedVars.clear();
10740 CapturedVars.end());
10741 Args.push_back(llvm::Constant::getNullValue(CGF.
Builder.getPtrTy()));
10748 llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier>
Device,
10751 llvm::Value *DeviceID;
10752 if (
Device.getPointer()) {
10754 Device.getInt() == OMPC_DEVICE_device_num) &&
10755 "Expected device_num modifier.");
10760 DeviceID = CGF.
Builder.getInt64(OMP_DEVICEID_UNDEF);
10765static std::pair<llvm::Value *, OMPDynGroupprivateFallbackType>
10767 llvm::Value *DynGP = CGF.
Builder.getInt32(0);
10768 auto DynGPFallback = OMPDynGroupprivateFallbackType::Abort;
10772 llvm::Value *DynGPVal =
10776 auto FallbackModifier = DynGPClause->getDynGroupprivateFallbackModifier();
10777 switch (FallbackModifier) {
10778 case OMPC_DYN_GROUPPRIVATE_FALLBACK_abort:
10779 DynGPFallback = OMPDynGroupprivateFallbackType::Abort;
10781 case OMPC_DYN_GROUPPRIVATE_FALLBACK_null:
10782 DynGPFallback = OMPDynGroupprivateFallbackType::Null;
10784 case OMPC_DYN_GROUPPRIVATE_FALLBACK_default_mem:
10787 DynGPFallback = OMPDynGroupprivateFallbackType::DefaultMem;
10790 llvm_unreachable(
"Unknown fallback modifier for OpenMP dyn_groupprivate");
10792 }
else if (
auto *OMPXDynCGClause =
10795 llvm::Value *DynCGMemVal = CGF.
EmitScalarExpr(OMPXDynCGClause->getSize(),
10800 return {DynGP, DynGPFallback};
10806 llvm::OpenMPIRBuilder &OMPBuilder,
10808 MappableExprsHandler::MapCombinedInfoTy &CombinedInfo) {
10810 llvm::DenseMap<llvm::Value *, llvm::Value *> LambdaPointers;
10812 auto *CV = CapturedVars.begin();
10815 CI != CE; ++CI, ++RI, ++CV) {
10816 MappableExprsHandler::MapCombinedInfoTy CurInfo;
10821 CurInfo.Exprs.push_back(
nullptr);
10822 CurInfo.BasePointers.push_back(*CV);
10823 CurInfo.DevicePtrDecls.push_back(
nullptr);
10824 CurInfo.DevicePointers.push_back(
10825 MappableExprsHandler::DeviceInfoTy::None);
10826 CurInfo.Pointers.push_back(*CV);
10827 CurInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
10830 CurInfo.Types.push_back(OpenMPOffloadMappingFlags::OMP_MAP_LITERAL |
10831 OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM |
10832 OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT);
10833 CurInfo.HasAttachPtr.push_back(
false);
10834 CurInfo.Mappers.push_back(
nullptr);
10839 bool HasEntryWithCVAsAttachPtr =
false;
10841 HasEntryWithCVAsAttachPtr =
10842 MEHandler.hasAttachEntryForCapturedVar(CapturedVD);
10845 MappableExprsHandler::MapDataArrayTy DeclComponentLists;
10848 StorageForImplicitlyAddedComponentLists;
10849 MEHandler.populateComponentListsForNonLambdaCaptureFromClauses(
10850 CapturedVD, DeclComponentLists,
10851 StorageForImplicitlyAddedComponentLists);
10862 bool HasEntryWithoutAttachPtr =
10863 llvm::any_of(DeclComponentLists, [&](
const auto &MapData) {
10865 Components = std::get<0>(MapData);
10866 return !MEHandler.getAttachPtrExpr(Components);
10871 if (DeclComponentLists.empty() ||
10872 (!HasEntryWithCVAsAttachPtr && !HasEntryWithoutAttachPtr))
10873 MEHandler.generateDefaultMapInfo(*CI, **RI, *CV, CurInfo);
10877 MEHandler.generateInfoForCaptureFromClauseInfo(
10878 DeclComponentLists, CI, *CV, CurInfo, OMPBuilder,
10879 CombinedInfo.BasePointers.size());
10884 MappedVarSet.insert(
nullptr);
10889 MEHandler.generateInfoForLambdaCaptures(CI->
getCapturedVar(), *CV,
10890 CurInfo, LambdaPointers);
10893 assert(!CurInfo.BasePointers.empty() &&
10894 "Non-existing map pointer for capture!");
10895 assert(CurInfo.BasePointers.size() == CurInfo.Pointers.size() &&
10896 CurInfo.BasePointers.size() == CurInfo.Sizes.size() &&
10897 CurInfo.BasePointers.size() == CurInfo.Types.size() &&
10898 CurInfo.BasePointers.size() == CurInfo.Mappers.size() &&
10899 "Inconsistent map information sizes!");
10902 CombinedInfo.append(CurInfo);
10905 MEHandler.adjustMemberOfForLambdaCaptures(
10906 OMPBuilder, LambdaPointers, CombinedInfo.BasePointers,
10907 CombinedInfo.Pointers, CombinedInfo.Types);
10911 MappableExprsHandler::MapCombinedInfoTy &CombinedInfo,
10912 llvm::OpenMPIRBuilder &OMPBuilder,
10919 MEHandler.generateAllInfo(CombinedInfo, OMPBuilder, SkippedVarSet);
10921 auto FillInfoMap = [&](MappableExprsHandler::MappingExprInfo &MapExpr) {
10925 llvm::codegenoptions::NoDebugInfo) {
10926 CombinedInfo.Names.resize(CombinedInfo.Exprs.size());
10927 llvm::transform(CombinedInfo.Exprs, CombinedInfo.Names.begin(),
10935 llvm::OpenMPIRBuilder &OMPBuilder,
10936 MappableExprsHandler::MapCombinedInfoTy &CombinedInfo) {
10938 MappableExprsHandler MEHandler(D, CGF);
10939 llvm::DenseSet<CanonicalDeclPtr<const Decl>> MappedVarSet;
10942 MappedVarSet, CombinedInfo);
10943 genMapInfo(MEHandler, CGF, CombinedInfo, OMPBuilder, MappedVarSet);
10946template <
typename ClauseTy>
10951 const auto *
C = D.getSingleClause<ClauseTy>();
10952 assert(!
C->varlist_empty() &&
10953 "ompx_bare requires explicit num_teams and thread_limit");
10955 for (
auto *E :
C->varlist()) {
10967 llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier>
Device,
10969 llvm::Value *&MapTypesArray, llvm::Value *&MapNamesArray,
10974 llvm::OpenMPIRBuilder &OMPBuilder = OMPRuntime->
getOMPBuilder();
10977 MappableExprsHandler::MapCombinedInfoTy CombinedInfo;
10979 genMapInfo(D, CGF, CS, CapturedVars, OMPBuilder, CombinedInfo);
10982 using OpenMPOffloadMappingFlags = llvm::omp::OpenMPOffloadMappingFlags;
10983 auto *NullPtr = llvm::Constant::getNullValue(CGF.
Builder.getPtrTy());
10984 CombinedInfo.BasePointers.push_back(NullPtr);
10985 CombinedInfo.Pointers.push_back(NullPtr);
10986 CombinedInfo.DevicePointers.push_back(
10987 llvm::OpenMPIRBuilder::DeviceInfoTy::None);
10988 CombinedInfo.Sizes.push_back(CGF.
Builder.getInt64(0));
10989 CombinedInfo.Types.push_back(OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM |
10990 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL);
10991 CombinedInfo.HasAttachPtr.push_back(
false);
10992 if (!CombinedInfo.Names.empty())
10993 CombinedInfo.Names.push_back(NullPtr);
10994 CombinedInfo.Exprs.push_back(
nullptr);
10995 CombinedInfo.Mappers.push_back(
nullptr);
10996 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
11010 MapTypesArray = Info.RTArgs.MapTypesArray;
11011 MapNamesArray = Info.RTArgs.MapNamesArray;
11013 auto &&ThenGen = [&OMPRuntime, OutlinedFn, &D, &CapturedVars,
11014 RequiresOuterTask, &CS, OffloadingMandatory,
Device,
11015 OutlinedFnID, &InputInfo, &MapTypesArray, &MapNamesArray,
11017 bool IsReverseOffloading =
Device.getInt() == OMPC_DEVICE_ancestor;
11019 if (IsReverseOffloading) {
11025 RequiresOuterTask, CS, OffloadingMandatory, CGF);
11029 bool HasNoWait = D.hasClausesOfKind<OMPNowaitClause>();
11030 unsigned NumTargetItems = InputInfo.NumberOfTargetItems;
11032 llvm::Value *BasePointersArray =
11033 InputInfo.BasePointersArray.emitRawPointer(CGF);
11034 llvm::Value *PointersArray = InputInfo.PointersArray.emitRawPointer(CGF);
11035 llvm::Value *SizesArray = InputInfo.SizesArray.emitRawPointer(CGF);
11036 llvm::Value *MappersArray = InputInfo.MappersArray.emitRawPointer(CGF);
11038 auto &&EmitTargetCallFallbackCB =
11039 [&OMPRuntime, OutlinedFn, &D, &CapturedVars, RequiresOuterTask, &CS,
11040 OffloadingMandatory, &CGF](llvm::OpenMPIRBuilder::InsertPointTy IP)
11041 -> llvm::OpenMPIRBuilder::InsertPointTy {
11044 RequiresOuterTask, CS, OffloadingMandatory, CGF);
11057 NumThreads.push_back(
11063 llvm::Value *NumIterations =
11066 llvm::OpenMPIRBuilder::InsertPointTy AllocaIP(
11069 llvm::OpenMPIRBuilder::TargetDataRTArgs RTArgs(
11070 BasePointersArray, PointersArray, SizesArray, MapTypesArray,
11071 nullptr , MappersArray, MapNamesArray);
11073 llvm::OpenMPIRBuilder::TargetKernelArgs Args(
11074 NumTargetItems, RTArgs, NumIterations, NumTeams, NumThreads,
11075 DynCGroupMem, HasNoWait, IsBare,
11076 DynCGroupMemFallback);
11078 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
11080 CGF.
Builder, OutlinedFnID, EmitTargetCallFallbackCB, Args, DeviceID,
11082 CGF.
Builder.restoreIP(AfterIP);
11085 if (RequiresOuterTask)
11100 [&OMPRuntime, OutlinedFn, &D, &CapturedVars, RequiresOuterTask, &CS,
11103 RequiresOuterTask, CS, OffloadingMandatory, CGF);
11106 if (RequiresOuterTask) {
11116 llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID,
const Expr *IfCond,
11117 llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier>
Device,
11124 const bool OffloadingMandatory = !
CGM.getLangOpts().OpenMPIsTargetDevice &&
11125 CGM.getLangOpts().OpenMPOffloadMandatory;
11127 assert((OffloadingMandatory || OutlinedFn) &&
"Invalid outlined function!");
11129 const bool RequiresOuterTask =
11131 D.hasClausesOfKind<OMPNowaitClause>() ||
11132 D.hasClausesOfKind<OMPInReductionClause>() ||
11133 (
CGM.getLangOpts().OpenMP >= 51 &&
11137 const CapturedStmt &CS = *D.getCapturedStmt(OMPD_target);
11145 llvm::Value *MapTypesArray =
nullptr;
11146 llvm::Value *MapNamesArray =
nullptr;
11148 auto &&TargetThenGen = [
this, OutlinedFn, &D, &CapturedVars,
11149 RequiresOuterTask, &CS, OffloadingMandatory,
Device,
11150 OutlinedFnID, &InputInfo, &MapTypesArray,
11154 RequiresOuterTask, CS, OffloadingMandatory,
11155 Device, OutlinedFnID, InputInfo, MapTypesArray,
11156 MapNamesArray, SizeEmitter, CGF,
CGM);
11159 auto &&TargetElseGen =
11160 [
this, OutlinedFn, &D, &CapturedVars, RequiresOuterTask, &CS,
11163 CS, OffloadingMandatory, CGF);
11170 if (OutlinedFnID) {
11172 emitIfClause(CGF, IfCond, TargetThenGen, TargetElseGen);
11184 StringRef ParentName) {
11191 if (
auto *E = dyn_cast<OMPExecutableDirective>(S);
11200 bool RequiresDeviceCodegen =
11205 if (RequiresDeviceCodegen) {
11213 if (!
OMPBuilder.OffloadInfoManager.hasTargetRegionEntryInfo(EntryInfo))
11216 switch (E.getDirectiveKind()) {
11221 case OMPD_target_parallel:
11225 case OMPD_target_teams:
11229 case OMPD_target_teams_distribute:
11233 case OMPD_target_teams_distribute_simd:
11237 case OMPD_target_parallel_for:
11241 case OMPD_target_parallel_for_simd:
11245 case OMPD_target_simd:
11249 case OMPD_target_teams_distribute_parallel_for:
11254 case OMPD_target_teams_distribute_parallel_for_simd:
11260 case OMPD_target_teams_loop:
11264 case OMPD_target_parallel_loop:
11268 case OMPD_parallel:
11270 case OMPD_parallel_for:
11271 case OMPD_parallel_master:
11272 case OMPD_parallel_sections:
11273 case OMPD_for_simd:
11274 case OMPD_parallel_for_simd:
11276 case OMPD_cancellation_point:
11278 case OMPD_threadprivate:
11279 case OMPD_allocate:
11284 case OMPD_sections:
11288 case OMPD_critical:
11289 case OMPD_taskyield:
11291 case OMPD_taskwait:
11292 case OMPD_taskgroup:
11298 case OMPD_target_data:
11299 case OMPD_target_exit_data:
11300 case OMPD_target_enter_data:
11301 case OMPD_distribute:
11302 case OMPD_distribute_simd:
11303 case OMPD_distribute_parallel_for:
11304 case OMPD_distribute_parallel_for_simd:
11305 case OMPD_teams_distribute:
11306 case OMPD_teams_distribute_simd:
11307 case OMPD_teams_distribute_parallel_for:
11308 case OMPD_teams_distribute_parallel_for_simd:
11309 case OMPD_target_update:
11310 case OMPD_declare_simd:
11311 case OMPD_declare_variant:
11312 case OMPD_begin_declare_variant:
11313 case OMPD_end_declare_variant:
11314 case OMPD_declare_target:
11315 case OMPD_end_declare_target:
11316 case OMPD_declare_reduction:
11317 case OMPD_declare_mapper:
11318 case OMPD_taskloop:
11319 case OMPD_taskloop_simd:
11320 case OMPD_master_taskloop:
11321 case OMPD_master_taskloop_simd:
11322 case OMPD_parallel_master_taskloop:
11323 case OMPD_parallel_master_taskloop_simd:
11324 case OMPD_requires:
11325 case OMPD_metadirective:
11328 llvm_unreachable(
"Unknown target directive for OpenMP device codegen.");
11333 if (
const auto *E = dyn_cast<OMPExecutableDirective>(S)) {
11334 if (!E->hasAssociatedStmt() || !E->getAssociatedStmt())
11342 if (
const auto *L = dyn_cast<LambdaExpr>(S))
11351 std::optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
11352 OMPDeclareTargetDeclAttr::getDeviceType(VD);
11356 if (!IsDevice && DevTy == OMPDeclareTargetDeclAttr::DT_NoHost)
11359 if (IsDevice && DevTy == OMPDeclareTargetDeclAttr::DT_Host)
11367 if (!
CGM.getLangOpts().OpenMPIsTargetDevice) {
11368 if (
const auto *FD = dyn_cast<FunctionDecl>(GD.
getDecl()))
11370 CGM.getLangOpts().OpenMPIsTargetDevice))
11377 if (
const auto *FD = dyn_cast<FunctionDecl>(VD)) {
11378 StringRef Name =
CGM.getMangledName(GD);
11381 CGM.getLangOpts().OpenMPIsTargetDevice))
11386 return !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD) &&
11392 CGM.getLangOpts().OpenMPIsTargetDevice))
11395 if (!
CGM.getLangOpts().OpenMPIsTargetDevice)
11404 StringRef ParentName =
11409 StringRef ParentName =
11416 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
11417 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(
11419 if (!Res || *Res == OMPDeclareTargetDeclAttr::MT_Link ||
11420 ((*Res == OMPDeclareTargetDeclAttr::MT_To ||
11421 *Res == OMPDeclareTargetDeclAttr::MT_Enter) &&
11430 llvm::Constant *
Addr) {
11431 if (
CGM.getLangOpts().OMPTargetTriples.empty() &&
11432 !
CGM.getLangOpts().OpenMPIsTargetDevice)
11435 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
11436 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
11440 if (Res && *Res != OMPDeclareTargetDeclAttr::MT_Link &&
11446 if (Res && *Res == OMPDeclareTargetDeclAttr::MT_Local)
11450 if (
CGM.getLangOpts().OpenMPIsTargetDevice) {
11453 StringRef VarName =
CGM.getMangledName(VD);
11459 auto AddrOfGlobal = [&VD,
this]() {
return CGM.GetAddrOfGlobal(VD); };
11460 auto LinkageForVariable = [&VD,
this]() {
11461 return CGM.getLLVMLinkageVarDefinition(VD);
11464 std::vector<llvm::GlobalVariable *> GeneratedRefs;
11471 CGM.getMangledName(VD), GeneratedRefs,
CGM.getLangOpts().OpenMPSimd,
11472 CGM.getLangOpts().OMPTargetTriples, AddrOfGlobal, LinkageForVariable,
11473 CGM.getTypes().ConvertTypeForMem(
11474 CGM.getContext().getPointerType(VD->
getType())),
11477 for (
auto *ref : GeneratedRefs)
11478 CGM.addCompilerUsedGlobal(ref);
11491 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
11492 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
11496 if (*Res == OMPDeclareTargetDeclAttr::MT_Local ||
11497 ((*Res == OMPDeclareTargetDeclAttr::MT_To ||
11498 *Res == OMPDeclareTargetDeclAttr::MT_Enter) &&
11500 CGM.EmitGlobal(VD);
11502 assert((*Res == OMPDeclareTargetDeclAttr::MT_Link ||
11503 ((*Res == OMPDeclareTargetDeclAttr::MT_To ||
11504 *Res == OMPDeclareTargetDeclAttr::MT_Enter ||
11505 *Res == OMPDeclareTargetDeclAttr::MT_Local) &&
11507 "Expected link clause or to clause with unified memory.");
11508 (void)
CGM.getOpenMPRuntime().getAddrOfDeclareTargetVar(VD);
11516 " Expected target-based directive.");
11521 if (Clause->getClauseKind() == OMPC_unified_shared_memory) {
11523 OMPBuilder.Config.setHasRequiresUnifiedSharedMemory(
true);
11524 }
else if (
const auto *AC =
11525 dyn_cast<OMPAtomicDefaultMemOrderClause>(Clause)) {
11526 switch (AC->getAtomicDefaultMemOrderKind()) {
11527 case OMPC_ATOMIC_DEFAULT_MEM_ORDER_acq_rel:
11530 case OMPC_ATOMIC_DEFAULT_MEM_ORDER_seq_cst:
11533 case OMPC_ATOMIC_DEFAULT_MEM_ORDER_relaxed:
11549 if (!VD || !VD->
hasAttr<OMPAllocateDeclAttr>())
11551 const auto *A = VD->
getAttr<OMPAllocateDeclAttr>();
11552 switch(A->getAllocatorType()) {
11553 case OMPAllocateDeclAttr::OMPNullMemAlloc:
11554 case OMPAllocateDeclAttr::OMPDefaultMemAlloc:
11556 case OMPAllocateDeclAttr::OMPLargeCapMemAlloc:
11557 case OMPAllocateDeclAttr::OMPCGroupMemAlloc:
11558 case OMPAllocateDeclAttr::OMPHighBWMemAlloc:
11559 case OMPAllocateDeclAttr::OMPLowLatMemAlloc:
11560 case OMPAllocateDeclAttr::OMPThreadMemAlloc:
11561 case OMPAllocateDeclAttr::OMPConstMemAlloc:
11562 case OMPAllocateDeclAttr::OMPPTeamMemAlloc:
11565 case OMPAllocateDeclAttr::OMPUserDefinedMemAlloc:
11566 llvm_unreachable(
"Expected predefined allocator for the variables with the "
11567 "static storage.");
11579 if (CGM.getLangOpts().OpenMPIsTargetDevice) {
11580 SavedShouldMarkAsGlobal = CGM.getOpenMPRuntime().ShouldMarkAsGlobal;
11581 CGM.getOpenMPRuntime().ShouldMarkAsGlobal = false;
11586 if (CGM.getLangOpts().OpenMPIsTargetDevice)
11587 CGM.getOpenMPRuntime().ShouldMarkAsGlobal = SavedShouldMarkAsGlobal;
11597 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(D)) {
11599 if (
auto *F = dyn_cast_or_null<llvm::Function>(
11600 CGM.GetGlobalValue(
CGM.getMangledName(GD))))
11601 return !F->isDeclaration();
11613 llvm::Function *OutlinedFn,
11622 llvm::Value *Args[] = {
11624 CGF.
Builder.getInt32(CapturedVars.size()),
11627 RealArgs.append(std::begin(Args), std::end(Args));
11628 RealArgs.append(CapturedVars.begin(), CapturedVars.end());
11630 llvm::FunctionCallee RTLFn =
OMPBuilder.getOrCreateRuntimeFunction(
11631 CGM.getModule(), OMPRTL___kmpc_fork_teams);
11636 const Expr *NumTeams,
11637 const Expr *ThreadLimit,
11644 llvm::Value *NumTeamsVal =
11650 llvm::Value *ThreadLimitVal =
11657 llvm::Value *PushNumTeamsArgs[] = {RTLoc,
getThreadID(CGF, Loc), NumTeamsVal,
11660 CGM.getModule(), OMPRTL___kmpc_push_num_teams),
11665 const Expr *ThreadLimit,
11668 llvm::Value *ThreadLimitVal =
11675 llvm::Value *ThreadLimitArgs[] = {RTLoc,
getThreadID(CGF, Loc),
11678 CGM.getModule(), OMPRTL___kmpc_set_thread_limit),
11693 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
11695 llvm::Value *IfCondVal =
nullptr;
11700 llvm::Value *DeviceID =
nullptr;
11705 DeviceID = CGF.
Builder.getInt64(OMP_DEVICEID_UNDEF);
11709 MappableExprsHandler::MapCombinedInfoTy CombinedInfo;
11710 auto GenMapInfoCB =
11711 [&](InsertPointTy CodeGenIP) -> llvm::OpenMPIRBuilder::MapInfosTy & {
11712 CGF.
Builder.restoreIP(CodeGenIP);
11714 MappableExprsHandler MEHandler(D, CGF);
11715 MEHandler.generateAllInfo(CombinedInfo,
OMPBuilder);
11717 auto FillInfoMap = [&](MappableExprsHandler::MappingExprInfo &MapExpr) {
11720 if (
CGM.getCodeGenOpts().getDebugInfo() !=
11721 llvm::codegenoptions::NoDebugInfo) {
11722 CombinedInfo.Names.resize(CombinedInfo.Exprs.size());
11723 llvm::transform(CombinedInfo.Exprs, CombinedInfo.Names.begin(),
11727 return CombinedInfo;
11729 using BodyGenTy = llvm::OpenMPIRBuilder::BodyGenTy;
11730 auto BodyCB = [&](InsertPointTy CodeGenIP, BodyGenTy BodyGenType) {
11731 CGF.
Builder.restoreIP(CodeGenIP);
11732 switch (BodyGenType) {
11733 case BodyGenTy::Priv:
11737 case BodyGenTy::DupNoPriv:
11739 CodeGen.setAction(NoPrivAction);
11743 case BodyGenTy::NoPriv:
11745 CodeGen.setAction(NoPrivAction);
11750 return InsertPointTy(CGF.
Builder.GetInsertBlock(),
11751 CGF.
Builder.GetInsertPoint());
11754 auto DeviceAddrCB = [&](
unsigned int I, llvm::Value *NewDecl) {
11755 if (
const ValueDecl *DevVD = CombinedInfo.DevicePtrDecls[I]) {
11760 auto CustomMapperCB = [&](
unsigned int I) {
11761 llvm::Function *MFunc =
nullptr;
11762 if (CombinedInfo.Mappers[I]) {
11763 Info.HasMapper =
true;
11775 InsertPointTy CodeGenIP(CGF.
Builder.GetInsertBlock(),
11776 CGF.
Builder.GetInsertPoint());
11777 llvm::OpenMPIRBuilder::LocationDescription OmpLoc(CodeGenIP);
11778 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
11780 OmpLoc, AllocaIP, CodeGenIP, {}, DeviceID,
11781 IfCondVal, Info, GenMapInfoCB, CustomMapperCB,
11782 nullptr, BodyCB, DeviceAddrCB, RTLoc));
11783 CGF.
Builder.restoreIP(AfterIP);
11795 "Expecting either target enter, exit data, or update directives.");
11798 llvm::Value *MapTypesArray =
nullptr;
11799 llvm::Value *MapNamesArray =
nullptr;
11801 auto &&ThenGen = [
this, &D,
Device, &InputInfo, &MapTypesArray,
11804 llvm::Value *DeviceID =
nullptr;
11809 DeviceID = CGF.
Builder.getInt64(OMP_DEVICEID_UNDEF);
11813 llvm::Constant *PointerNum =
11820 {RTLoc, DeviceID, PointerNum,
11828 const bool HasNowait = D.hasClausesOfKind<OMPNowaitClause>();
11829 RuntimeFunction RTLFn;
11830 switch (D.getDirectiveKind()) {
11831 case OMPD_target_enter_data:
11832 RTLFn = HasNowait ? OMPRTL___tgt_target_data_begin_nowait_mapper
11833 : OMPRTL___tgt_target_data_begin_mapper;
11835 case OMPD_target_exit_data:
11836 RTLFn = HasNowait ? OMPRTL___tgt_target_data_end_nowait_mapper
11837 : OMPRTL___tgt_target_data_end_mapper;
11839 case OMPD_target_update:
11840 RTLFn = HasNowait ? OMPRTL___tgt_target_data_update_nowait_mapper
11841 : OMPRTL___tgt_target_data_update_mapper;
11843 case OMPD_parallel:
11845 case OMPD_parallel_for:
11846 case OMPD_parallel_master:
11847 case OMPD_parallel_sections:
11848 case OMPD_for_simd:
11849 case OMPD_parallel_for_simd:
11851 case OMPD_cancellation_point:
11853 case OMPD_threadprivate:
11854 case OMPD_allocate:
11859 case OMPD_sections:
11863 case OMPD_critical:
11864 case OMPD_taskyield:
11866 case OMPD_taskwait:
11867 case OMPD_taskgroup:
11873 case OMPD_target_data:
11874 case OMPD_distribute:
11875 case OMPD_distribute_simd:
11876 case OMPD_distribute_parallel_for:
11877 case OMPD_distribute_parallel_for_simd:
11878 case OMPD_teams_distribute:
11879 case OMPD_teams_distribute_simd:
11880 case OMPD_teams_distribute_parallel_for:
11881 case OMPD_teams_distribute_parallel_for_simd:
11882 case OMPD_declare_simd:
11883 case OMPD_declare_variant:
11884 case OMPD_begin_declare_variant:
11885 case OMPD_end_declare_variant:
11886 case OMPD_declare_target:
11887 case OMPD_end_declare_target:
11888 case OMPD_declare_reduction:
11889 case OMPD_declare_mapper:
11890 case OMPD_taskloop:
11891 case OMPD_taskloop_simd:
11892 case OMPD_master_taskloop:
11893 case OMPD_master_taskloop_simd:
11894 case OMPD_parallel_master_taskloop:
11895 case OMPD_parallel_master_taskloop_simd:
11897 case OMPD_target_simd:
11898 case OMPD_target_teams_distribute:
11899 case OMPD_target_teams_distribute_simd:
11900 case OMPD_target_teams_distribute_parallel_for:
11901 case OMPD_target_teams_distribute_parallel_for_simd:
11902 case OMPD_target_teams:
11903 case OMPD_target_parallel:
11904 case OMPD_target_parallel_for:
11905 case OMPD_target_parallel_for_simd:
11906 case OMPD_requires:
11907 case OMPD_metadirective:
11910 llvm_unreachable(
"Unexpected standalone target data directive.");
11914 OffloadingArgs.push_back(llvm::Constant::getNullValue(CGF.
Int32Ty));
11915 OffloadingArgs.push_back(llvm::Constant::getNullValue(CGF.
VoidPtrTy));
11916 OffloadingArgs.push_back(llvm::Constant::getNullValue(CGF.
Int32Ty));
11917 OffloadingArgs.push_back(llvm::Constant::getNullValue(CGF.
VoidPtrTy));
11920 OMPBuilder.getOrCreateRuntimeFunction(
CGM.getModule(), RTLFn),
11924 auto &&TargetThenGen = [
this, &ThenGen, &D, &InputInfo, &MapTypesArray,
11928 MappableExprsHandler::MapCombinedInfoTy CombinedInfo;
11930 MappableExprsHandler MEHandler(D, CGF);
11936 D.hasClausesOfKind<OMPNowaitClause>();
11942 CGM.getPointerAlign());
11947 MapTypesArray = Info.RTArgs.MapTypesArray;
11948 MapNamesArray = Info.RTArgs.MapNamesArray;
11949 if (RequiresOuterTask)
11994 unsigned Offset = 0;
11995 if (
const auto *MD = dyn_cast<CXXMethodDecl>(FD)) {
11996 if (ParamAttrs[Offset].Kind ==
11997 llvm::OpenMPIRBuilder::DeclareSimdKindTy::Vector)
11998 CDT =
C.getPointerType(
C.getCanonicalTagType(MD->
getParent()));
12002 for (
unsigned I = 0, E = FD->
getNumParams(); I < E; ++I) {
12003 if (ParamAttrs[I + Offset].Kind ==
12004 llvm::OpenMPIRBuilder::DeclareSimdKindTy::Vector) {
12016 return C.getTypeSize(CDT);
12027 llvm::OpenMPIRBuilder::DeclareSimdKindTy Kind) {
12033 if (Kind == llvm::OpenMPIRBuilder::DeclareSimdKindTy::Uniform)
12036 if (Kind == llvm::OpenMPIRBuilder::DeclareSimdKindTy::LinearUVal ||
12037 Kind == llvm::OpenMPIRBuilder::DeclareSimdKindTy::LinearRef)
12040 if ((Kind == llvm::OpenMPIRBuilder::DeclareSimdKindTy::Linear ||
12041 Kind == llvm::OpenMPIRBuilder::DeclareSimdKindTy::LinearVal) &&
12051 unsigned Size =
C.getTypeSize(QT);
12054 if (Size != 8 && Size != 16 && Size != 32 && Size != 64 && Size != 128)
12075 llvm::OpenMPIRBuilder::DeclareSimdKindTy Kind,
12080 return C.getTypeSize(PTy);
12083 return C.getTypeSize(QT);
12085 return C.getTypeSize(
C.getUIntPtrType());
12091static std::tuple<unsigned, unsigned, bool>
12098 bool OutputBecomesInput =
false;
12103 RetType, llvm::OpenMPIRBuilder::DeclareSimdKindTy::Vector,
C));
12105 OutputBecomesInput =
true;
12107 for (
unsigned I = 0, E = FD->
getNumParams(); I < E; ++I) {
12112 assert(!Sizes.empty() &&
"Unable to determine NDS and WDS.");
12115 assert(llvm::all_of(Sizes,
12116 [](
unsigned Size) {
12117 return Size == 8 || Size == 16 || Size == 32 ||
12118 Size == 64 || Size == 128;
12122 return std::make_tuple(*llvm::min_element(Sizes), *llvm::max_element(Sizes),
12123 OutputBecomesInput);
12126static llvm::OpenMPIRBuilder::DeclareSimdBranch
12129 case OMPDeclareSimdDeclAttr::BS_Undefined:
12130 return llvm::OpenMPIRBuilder::DeclareSimdBranch::Undefined;
12131 case OMPDeclareSimdDeclAttr::BS_Inbranch:
12132 return llvm::OpenMPIRBuilder::DeclareSimdBranch::Inbranch;
12133 case OMPDeclareSimdDeclAttr::BS_Notinbranch:
12134 return llvm::OpenMPIRBuilder::DeclareSimdBranch::Notinbranch;
12136 llvm_unreachable(
"unexpected declare simd branch state");
12141 unsigned UserVLEN,
unsigned WDS,
char ISA) {
12143 if (UserVLEN == 1) {
12150 if (ISA ==
'n' && UserVLEN && !llvm::isPowerOf2_32(UserVLEN)) {
12156 if (ISA ==
's' && UserVLEN != 0 &&
12157 ((UserVLEN * WDS > 2048) || (UserVLEN * WDS % 128 != 0))) {
12166 llvm::Function *Fn) {
12171 llvm::DenseMap<const Decl *, unsigned> ParamPositions;
12173 ParamPositions.try_emplace(FD, 0);
12174 unsigned ParamPos = ParamPositions.size();
12176 ParamPositions.try_emplace(P->getCanonicalDecl(), ParamPos);
12181 ParamPositions.size());
12183 for (
const Expr *E :
Attr->uniforms()) {
12187 Pos = ParamPositions[FD];
12190 ->getCanonicalDecl();
12191 auto It = ParamPositions.find(PVD);
12192 assert(It != ParamPositions.end() &&
"Function parameter not found");
12195 ParamAttrs[Pos].Kind =
12196 llvm::OpenMPIRBuilder::DeclareSimdKindTy::Uniform;
12199 auto *NI =
Attr->alignments_begin();
12200 for (
const Expr *E :
Attr->aligneds()) {
12205 Pos = ParamPositions[FD];
12209 ->getCanonicalDecl();
12210 auto It = ParamPositions.find(PVD);
12211 assert(It != ParamPositions.end() &&
"Function parameter not found");
12213 ParmTy = PVD->getType();
12215 ParamAttrs[Pos].Alignment =
12217 ? (*NI)->EvaluateKnownConstInt(
C)
12218 : llvm::APSInt::getUnsigned(
12219 C.toCharUnitsFromBits(
C.getOpenMPDefaultSimdAlign(ParmTy))
12224 auto *SI =
Attr->steps_begin();
12225 auto *MI =
Attr->modifiers_begin();
12226 for (
const Expr *E :
Attr->linears()) {
12229 bool IsReferenceType =
false;
12232 unsigned PtrRescalingFactor = 1;
12234 Pos = ParamPositions[FD];
12236 PtrRescalingFactor =
CGM.getContext()
12237 .getTypeSizeInChars(P->getPointeeType())
12241 ->getCanonicalDecl();
12242 auto It = ParamPositions.find(PVD);
12243 assert(It != ParamPositions.end() &&
"Function parameter not found");
12245 if (
auto *P = dyn_cast<PointerType>(PVD->getType()))
12246 PtrRescalingFactor =
CGM.getContext()
12247 .getTypeSizeInChars(P->getPointeeType())
12249 else if (PVD->getType()->isReferenceType()) {
12250 IsReferenceType =
true;
12251 PtrRescalingFactor =
12253 .getTypeSizeInChars(PVD->getType().getNonReferenceType())
12257 llvm::OpenMPIRBuilder::DeclareSimdAttrTy &ParamAttr = ParamAttrs[Pos];
12258 if (*MI == OMPC_LINEAR_ref)
12259 ParamAttr.Kind = llvm::OpenMPIRBuilder::DeclareSimdKindTy::LinearRef;
12260 else if (*MI == OMPC_LINEAR_uval)
12261 ParamAttr.Kind = llvm::OpenMPIRBuilder::DeclareSimdKindTy::LinearUVal;
12262 else if (IsReferenceType)
12263 ParamAttr.Kind = llvm::OpenMPIRBuilder::DeclareSimdKindTy::LinearVal;
12265 ParamAttr.Kind = llvm::OpenMPIRBuilder::DeclareSimdKindTy::Linear;
12267 ParamAttr.StrideOrArg = llvm::APSInt::getUnsigned(1);
12271 if (
const auto *DRE =
12273 if (
const auto *StridePVD =
12274 dyn_cast<ParmVarDecl>(DRE->getDecl())) {
12275 ParamAttr.HasVarStride =
true;
12276 auto It = ParamPositions.find(StridePVD->getCanonicalDecl());
12277 assert(It != ParamPositions.end() &&
12278 "Function parameter not found");
12279 ParamAttr.StrideOrArg = llvm::APSInt::getUnsigned(It->second);
12283 ParamAttr.StrideOrArg =
Result.Val.getInt();
12289 if (!ParamAttr.HasVarStride &&
12291 llvm::OpenMPIRBuilder::DeclareSimdKindTy::Linear ||
12293 llvm::OpenMPIRBuilder::DeclareSimdKindTy::LinearRef))
12294 ParamAttr.StrideOrArg = ParamAttr.StrideOrArg * PtrRescalingFactor;
12298 llvm::APSInt VLENVal;
12300 const Expr *VLENExpr =
Attr->getSimdlen();
12305 llvm::OpenMPIRBuilder::DeclareSimdBranch State =
12307 if (
CGM.getTriple().isX86()) {
12309 assert(NumElts &&
"Non-zero simdlen/cdtsize expected");
12310 OMPBuilder.emitX86DeclareSimdFunction(Fn, NumElts, VLENVal, ParamAttrs,
12312 }
else if (
CGM.getTriple().getArch() == llvm::Triple::aarch64) {
12313 unsigned VLEN = VLENVal.getExtValue();
12316 const unsigned NDS = std::get<0>(
Data);
12317 const unsigned WDS = std::get<1>(
Data);
12318 const bool OutputBecomesInput = std::get<2>(
Data);
12319 if (
CGM.getTarget().hasFeature(
"sve")) {
12322 Fn, VLEN, ParamAttrs, State,
's', NDS, OutputBecomesInput);
12323 }
else if (
CGM.getTarget().hasFeature(
"neon")) {
12326 Fn, VLEN, ParamAttrs, State,
'n', NDS, OutputBecomesInput);
12336class DoacrossCleanupTy final :
public EHScopeStack::Cleanup {
12338 static const int DoacrossFinArgs = 2;
12341 llvm::FunctionCallee RTLFn;
12342 llvm::Value *Args[DoacrossFinArgs];
12345 DoacrossCleanupTy(llvm::FunctionCallee RTLFn,
12348 assert(CallArgs.size() == DoacrossFinArgs);
12349 std::copy(CallArgs.begin(), CallArgs.end(), std::begin(Args));
12366 QualType Int64Ty =
C.getIntTypeForBitwidth(64,
true);
12374 RD =
C.buildImplicitRecord(
"kmp_dim");
12382 RD =
KmpDimTy->castAsRecordDecl();
12384 llvm::APInt Size(32, NumIterations.size());
12390 enum { LowerFD = 0, UpperFD, StrideFD };
12392 for (
unsigned I = 0, E = NumIterations.size(); I < E; ++I) {
12397 DimsLVal, *std::next(RD->
field_begin(), UpperFD));
12399 CGF.
EmitScalarExpr(NumIterations[I]), NumIterations[I]->getType(),
12400 Int64Ty, NumIterations[I]->getExprLoc());
12404 DimsLVal, *std::next(RD->
field_begin(), StrideFD));
12411 llvm::Value *Args[] = {
12414 llvm::ConstantInt::getSigned(
CGM.Int32Ty, NumIterations.size()),
12419 llvm::FunctionCallee RTLFn =
OMPBuilder.getOrCreateRuntimeFunction(
12420 CGM.getModule(), OMPRTL___kmpc_doacross_init);
12422 llvm::Value *FiniArgs[DoacrossCleanupTy::DoacrossFinArgs] = {
12424 llvm::FunctionCallee FiniRTLFn =
OMPBuilder.getOrCreateRuntimeFunction(
12425 CGM.getModule(), OMPRTL___kmpc_doacross_fini);
12430template <
typename T>
12432 const T *
C, llvm::Value *ULoc,
12433 llvm::Value *ThreadID) {
12436 llvm::APInt Size(32,
C->getNumLoops());
12440 for (
unsigned I = 0, E =
C->getNumLoops(); I < E; ++I) {
12441 const Expr *CounterVal =
C->getLoopData(I);
12442 assert(CounterVal);
12449 llvm::Value *Args[] = {
12452 llvm::FunctionCallee RTLFn;
12454 OMPDoacrossKind<T> ODK;
12455 if (ODK.isSource(
C)) {
12457 OMPRTL___kmpc_doacross_post);
12459 assert(ODK.isSink(
C) &&
"Expect sink modifier.");
12461 OMPRTL___kmpc_doacross_wait);
12481 llvm::FunctionCallee Callee,
12483 assert(Loc.
isValid() &&
"Outlined function call location must be valid.");
12486 if (
auto *Fn = dyn_cast<llvm::Function>(Callee.getCallee())) {
12487 if (Fn->doesNotThrow()) {
12498 emitCall(CGF, Loc, OutlinedFn, Args);
12502 if (
const auto *FD = dyn_cast<FunctionDecl>(D))
12503 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(FD))
12509 const VarDecl *TargetParam)
const {
12516 const Expr *Allocator) {
12517 llvm::Value *AllocVal;
12527 AllocVal = llvm::Constant::getNullValue(
12537 if (!AllocateAlignment)
12540 return llvm::ConstantInt::get(
CGM.
SizeTy, AllocateAlignment->getQuantity());
12553 auto I = UntiedData.find(VD);
12554 if (I != UntiedData.end()) {
12555 UntiedAddr = I->second.first;
12556 UntiedRealAddr = I->second.second;
12560 if (CVD->
hasAttr<OMPAllocateDeclAttr>()) {
12569 Size = CGF.
Builder.CreateNUWAdd(
12571 Size = CGF.
Builder.CreateUDiv(Size,
CGM.getSize(Align));
12572 Size = CGF.
Builder.CreateNUWMul(Size,
CGM.getSize(Align));
12578 const auto *AA = CVD->
getAttr<OMPAllocateDeclAttr>();
12579 const Expr *Allocator = AA->getAllocator();
12583 Args.push_back(ThreadID);
12585 Args.push_back(Alignment);
12586 Args.push_back(Size);
12587 Args.push_back(AllocVal);
12588 llvm::omp::RuntimeFunction FnID =
12589 Alignment ? OMPRTL___kmpc_aligned_alloc : OMPRTL___kmpc_alloc;
12591 OMPBuilder.getOrCreateRuntimeFunction(
CGM.getModule(), FnID), Args,
12593 llvm::FunctionCallee FiniRTLFn =
OMPBuilder.getOrCreateRuntimeFunction(
12594 CGM.getModule(), OMPRTL___kmpc_free);
12602 class OMPAllocateCleanupTy final :
public EHScopeStack::Cleanup {
12603 llvm::FunctionCallee RTLFn;
12606 const Expr *AllocExpr;
12609 OMPAllocateCleanupTy(llvm::FunctionCallee RTLFn,
12611 const Expr *AllocExpr)
12612 : RTLFn(RTLFn), LocEncoding(LocEncoding),
Addr(
Addr),
12613 AllocExpr(AllocExpr) {}
12617 llvm::Value *Args[3];
12623 Args[2] = AllocVal;
12631 CGF.
EHStack.pushCleanup<OMPAllocateCleanupTy>(
12633 VDAddr, Allocator);
12634 if (UntiedRealAddr.
isValid())
12637 Region->emitUntiedSwitch(CGF);
12654 assert(CGM.getLangOpts().OpenMP &&
"Not in OpenMP mode.");
12658 CGM.getOpenMPRuntime().NontemporalDeclsStack.emplace_back();
12660 for (
const Stmt *Ref :
C->private_refs()) {
12661 const auto *SimpleRefExpr =
cast<Expr>(Ref)->IgnoreParenImpCasts();
12663 if (
const auto *DRE = dyn_cast<DeclRefExpr>(SimpleRefExpr)) {
12664 VD = DRE->getDecl();
12667 assert((ME->isImplicitCXXThis() ||
12669 "Expected member of current class.");
12670 VD = ME->getMemberDecl();
12680 CGM.getOpenMPRuntime().NontemporalDeclsStack.pop_back();
12686 std::pair<Address, Address>> &LocalVars)
12687 : CGM(CGF.CGM), NeedToPush(!LocalVars.empty()) {
12691 CGF.
CurFn, CGM.getOpenMPRuntime().UntiedLocalVarsStack.size());
12692 CGM.getOpenMPRuntime().UntiedLocalVarsStack.push_back(LocalVars);
12698 CGM.getOpenMPRuntime().UntiedLocalVarsStack.pop_back();
12702 assert(
CGM.getLangOpts().OpenMP &&
"Not in OpenMP mode.");
12704 return llvm::any_of(
12705 CGM.getOpenMPRuntime().NontemporalDeclsStack,
12709void CGOpenMPRuntime::LastprivateConditionalRAII::tryToDisableInnerAnalysis(
12713 llvm::DenseSet<CanonicalDeclPtr<const Decl>> NeedToCheckForLPCs;
12719 const CapturedStmt *CS = S.getCapturedStmt(CaptureRegions.front());
12726 for (
const auto *
C : S.getClausesOfKind<OMPPrivateClause>()) {
12727 for (
const Expr *Ref :
C->varlist()) {
12728 if (!Ref->getType()->isScalarType())
12730 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
12733 NeedToCheckForLPCs.insert(DRE->getDecl());
12736 for (
const auto *
C : S.getClausesOfKind<OMPFirstprivateClause>()) {
12737 for (
const Expr *Ref :
C->varlist()) {
12738 if (!Ref->getType()->isScalarType())
12740 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
12743 NeedToCheckForLPCs.insert(DRE->getDecl());
12746 for (
const auto *
C : S.getClausesOfKind<OMPLastprivateClause>()) {
12747 for (
const Expr *Ref :
C->varlist()) {
12748 if (!Ref->getType()->isScalarType())
12750 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
12753 NeedToCheckForLPCs.insert(DRE->getDecl());
12756 for (
const auto *
C : S.getClausesOfKind<OMPReductionClause>()) {
12757 for (
const Expr *Ref :
C->varlist()) {
12758 if (!Ref->getType()->isScalarType())
12760 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
12763 NeedToCheckForLPCs.insert(DRE->getDecl());
12766 for (
const auto *
C : S.getClausesOfKind<OMPLinearClause>()) {
12767 for (
const Expr *Ref :
C->varlist()) {
12768 if (!Ref->getType()->isScalarType())
12770 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
12773 NeedToCheckForLPCs.insert(DRE->getDecl());
12776 for (
const Decl *VD : NeedToCheckForLPCs) {
12778 llvm::reverse(
CGM.getOpenMPRuntime().LastprivateConditionalStack)) {
12779 if (
Data.DeclToUniqueName.count(VD) > 0) {
12780 if (!
Data.Disabled)
12781 NeedToAddForLPCsAsDisabled.insert(VD);
12788CGOpenMPRuntime::LastprivateConditionalRAII::LastprivateConditionalRAII(
12791 Action((CGM.getLangOpts().OpenMP >= 50 &&
12792 llvm::any_of(S.getClausesOfKind<OMPLastprivateClause>(),
12793 [](const OMPLastprivateClause *
C) {
12794 return C->getKind() ==
12795 OMPC_LASTPRIVATE_conditional;
12797 ? ActionToDo::PushAsLastprivateConditional
12798 : ActionToDo::DoNotPush) {
12799 assert(
CGM.getLangOpts().OpenMP &&
"Not in OpenMP mode.");
12800 if (
CGM.getLangOpts().OpenMP < 50 || Action == ActionToDo::DoNotPush)
12802 assert(Action == ActionToDo::PushAsLastprivateConditional &&
12803 "Expected a push action.");
12805 CGM.getOpenMPRuntime().LastprivateConditionalStack.emplace_back();
12806 for (
const auto *
C : S.getClausesOfKind<OMPLastprivateClause>()) {
12807 if (
C->getKind() != OMPC_LASTPRIVATE_conditional)
12810 for (
const Expr *Ref :
C->varlist()) {
12811 Data.DeclToUniqueName.insert(std::make_pair(
12816 Data.IVLVal = IVLVal;
12820CGOpenMPRuntime::LastprivateConditionalRAII::LastprivateConditionalRAII(
12822 :
CGM(CGF.
CGM), Action(ActionToDo::DoNotPush) {
12826 llvm::DenseSet<CanonicalDeclPtr<const Decl>> NeedToAddForLPCsAsDisabled;
12827 tryToDisableInnerAnalysis(S, NeedToAddForLPCsAsDisabled);
12828 if (!NeedToAddForLPCsAsDisabled.empty()) {
12829 Action = ActionToDo::DisableLastprivateConditional;
12830 LastprivateConditionalData &
Data =
12832 for (
const Decl *VD : NeedToAddForLPCsAsDisabled)
12833 Data.DeclToUniqueName.try_emplace(VD);
12835 Data.Disabled =
true;
12839CGOpenMPRuntime::LastprivateConditionalRAII
12842 return LastprivateConditionalRAII(CGF, S);
12846 if (CGM.getLangOpts().OpenMP < 50)
12848 if (Action == ActionToDo::DisableLastprivateConditional) {
12849 assert(CGM.getOpenMPRuntime().LastprivateConditionalStack.back().Disabled &&
12850 "Expected list of disabled private vars.");
12851 CGM.getOpenMPRuntime().LastprivateConditionalStack.pop_back();
12853 if (Action == ActionToDo::PushAsLastprivateConditional) {
12855 !CGM.getOpenMPRuntime().LastprivateConditionalStack.back().Disabled &&
12856 "Expected list of lastprivate conditional vars.");
12857 CGM.getOpenMPRuntime().LastprivateConditionalStack.pop_back();
12869 auto VI = I->getSecond().find(VD);
12870 if (VI == I->getSecond().end()) {
12871 RecordDecl *RD =
C.buildImplicitRecord(
"lasprivate.conditional");
12876 NewType =
C.getCanonicalTagType(RD);
12879 I->getSecond().try_emplace(VD, NewType, VDField, FiredField, BaseLVal);
12881 NewType = std::get<0>(VI->getSecond());
12882 VDField = std::get<1>(VI->getSecond());
12883 FiredField = std::get<2>(VI->getSecond());
12884 BaseLVal = std::get<3>(VI->getSecond());
12896class LastprivateConditionalRefChecker final
12899 const Expr *FoundE =
nullptr;
12900 const Decl *FoundD =
nullptr;
12901 StringRef UniqueDeclName;
12903 llvm::Function *FoundFn =
nullptr;
12909 llvm::reverse(LPM)) {
12910 auto It = D.DeclToUniqueName.find(E->
getDecl());
12911 if (It == D.DeclToUniqueName.end())
12917 UniqueDeclName = It->second;
12922 return FoundE == E;
12928 llvm::reverse(LPM)) {
12930 if (It == D.DeclToUniqueName.end())
12936 UniqueDeclName = It->second;
12941 return FoundE == E;
12943 bool VisitStmt(
const Stmt *S) {
12944 for (
const Stmt *Child : S->
children()) {
12947 if (
const auto *E = dyn_cast<Expr>(Child))
12955 explicit LastprivateConditionalRefChecker(
12956 ArrayRef<CGOpenMPRuntime::LastprivateConditionalData> LPM)
12958 std::tuple<const Expr *, const Decl *, StringRef, LValue, llvm::Function *>
12959 getFoundData()
const {
12960 return std::make_tuple(FoundE, FoundD, UniqueDeclName, IVLVal, FoundFn);
12967 StringRef UniqueDeclName,
12973 llvm::Constant *LastIV =
OMPBuilder.getOrCreateInternalVariable(
12974 LLIVTy,
getName({UniqueDeclName,
"iv"}));
12982 llvm::GlobalVariable *
Last =
OMPBuilder.getOrCreateInternalVariable(
12998 auto &&
CodeGen = [&LastIVLVal, &IVLVal, IVVal, &LVal, &LastLVal,
13004 llvm::Value *CmpRes;
13006 CmpRes = CGF.
Builder.CreateICmpSLE(LastIVVal, IVVal);
13009 "Loop iteration variable must be integer.");
13010 CmpRes = CGF.
Builder.CreateICmpULE(LastIVVal, IVVal);
13014 CGF.
Builder.CreateCondBr(CmpRes, ThenBB, ExitBB);
13035 "Aggregates are not supported in lastprivate conditional.");
13044 if (
CGM.getLangOpts().OpenMPSimd) {
13058 if (!Checker.Visit(LHS))
13060 const Expr *FoundE;
13061 const Decl *FoundD;
13062 StringRef UniqueDeclName;
13064 llvm::Function *FoundFn;
13065 std::tie(FoundE, FoundD, UniqueDeclName, IVLVal, FoundFn) =
13066 Checker.getFoundData();
13067 if (FoundFn != CGF.
CurFn) {
13072 "Lastprivate conditional is not found in outer region.");
13073 QualType StructTy = std::get<0>(It->getSecond());
13074 const FieldDecl* FiredDecl = std::get<2>(It->getSecond());
13085 FiredLVal, llvm::AtomicOrdering::Unordered,
13103 auto It = llvm::find_if(
13105 if (It == Range.end() || It->Fn != CGF.
CurFn)
13109 "Lastprivates must be registered already.");
13112 const CapturedStmt *CS = D.getCapturedStmt(CaptureRegions.back());
13113 for (
const auto &Pair : It->DeclToUniqueName) {
13114 const auto *VD =
cast<VarDecl>(Pair.first->getCanonicalDecl());
13117 auto I = LPCI->getSecond().find(Pair.first);
13118 assert(I != LPCI->getSecond().end() &&
13119 "Lastprivate must be rehistered already.");
13121 LValue BaseLVal = std::get<3>(I->getSecond());
13125 llvm::Value *
Cmp = CGF.
Builder.CreateIsNotNull(Res);
13129 CGF.
Builder.CreateCondBr(
Cmp, ThenBB, DoneBB);
13154 "Unknown lastprivate conditional variable.");
13155 StringRef UniqueName = It->second;
13156 llvm::GlobalVariable *GV =
CGM.getModule().getNamedGlobal(UniqueName);
13170 llvm_unreachable(
"Not supported in SIMD-only mode");
13177 llvm_unreachable(
"Not supported in SIMD-only mode");
13184 bool Tied,
unsigned &NumberOfParts) {
13185 llvm_unreachable(
"Not supported in SIMD-only mode");
13193 llvm_unreachable(
"Not supported in SIMD-only mode");
13199 const Expr *Hint) {
13200 llvm_unreachable(
"Not supported in SIMD-only mode");
13206 llvm_unreachable(
"Not supported in SIMD-only mode");
13212 const Expr *Filter) {
13213 llvm_unreachable(
"Not supported in SIMD-only mode");
13218 llvm_unreachable(
"Not supported in SIMD-only mode");
13224 llvm_unreachable(
"Not supported in SIMD-only mode");
13232 llvm_unreachable(
"Not supported in SIMD-only mode");
13239 llvm_unreachable(
"Not supported in SIMD-only mode");
13246 bool ForceSimpleCall) {
13247 llvm_unreachable(
"Not supported in SIMD-only mode");
13254 llvm_unreachable(
"Not supported in SIMD-only mode");
13259 llvm_unreachable(
"Not supported in SIMD-only mode");
13265 llvm_unreachable(
"Not supported in SIMD-only mode");
13271 llvm_unreachable(
"Not supported in SIMD-only mode");
13278 llvm_unreachable(
"Not supported in SIMD-only mode");
13284 llvm_unreachable(
"Not supported in SIMD-only mode");
13289 unsigned IVSize,
bool IVSigned,
13292 llvm_unreachable(
"Not supported in SIMD-only mode");
13300 llvm_unreachable(
"Not supported in SIMD-only mode");
13304 ProcBindKind ProcBind,
13306 llvm_unreachable(
"Not supported in SIMD-only mode");
13313 llvm_unreachable(
"Not supported in SIMD-only mode");
13319 llvm_unreachable(
"Not supported in SIMD-only mode");
13324 llvm_unreachable(
"Not supported in SIMD-only mode");
13330 llvm::AtomicOrdering AO) {
13331 llvm_unreachable(
"Not supported in SIMD-only mode");
13336 llvm::Function *TaskFunction,
13338 const Expr *IfCond,
13340 llvm_unreachable(
"Not supported in SIMD-only mode");
13347 llvm_unreachable(
"Not supported in SIMD-only mode");
13354 assert(Options.
SimpleReduction &&
"Only simple reduction is expected.");
13356 ReductionOps, Options);
13362 llvm_unreachable(
"Not supported in SIMD-only mode");
13367 bool IsWorksharingReduction) {
13368 llvm_unreachable(
"Not supported in SIMD-only mode");
13375 llvm_unreachable(
"Not supported in SIMD-only mode");
13380 llvm::Value *ReductionsPtr,
13382 llvm_unreachable(
"Not supported in SIMD-only mode");
13388 llvm_unreachable(
"Not supported in SIMD-only mode");
13394 llvm_unreachable(
"Not supported in SIMD-only mode");
13400 llvm_unreachable(
"Not supported in SIMD-only mode");
13405 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
13407 llvm_unreachable(
"Not supported in SIMD-only mode");
13412 llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID,
const Expr *IfCond,
13413 llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier>
Device,
13417 llvm_unreachable(
"Not supported in SIMD-only mode");
13421 llvm_unreachable(
"Not supported in SIMD-only mode");
13425 llvm_unreachable(
"Not supported in SIMD-only mode");
13435 llvm::Function *OutlinedFn,
13437 llvm_unreachable(
"Not supported in SIMD-only mode");
13441 const Expr *NumTeams,
13442 const Expr *ThreadLimit,
13444 llvm_unreachable(
"Not supported in SIMD-only mode");
13451 llvm_unreachable(
"Not supported in SIMD-only mode");
13457 llvm_unreachable(
"Not supported in SIMD-only mode");
13463 llvm_unreachable(
"Not supported in SIMD-only mode");
13468 llvm_unreachable(
"Not supported in SIMD-only mode");
13473 llvm_unreachable(
"Not supported in SIMD-only mode");
13478 const VarDecl *NativeParam)
const {
13479 llvm_unreachable(
"Not supported in SIMD-only mode");
13485 const VarDecl *TargetParam)
const {
13486 llvm_unreachable(
"Not supported in SIMD-only mode");
static llvm::Value * emitCopyprivateCopyFunction(CodeGenModule &CGM, llvm::Type *ArgsElemType, ArrayRef< const Expr * > CopyprivateVars, ArrayRef< const Expr * > DestExprs, ArrayRef< const Expr * > SrcExprs, ArrayRef< const Expr * > AssignmentOps, SourceLocation Loc)
static StringRef getIdentStringFromSourceLocation(CodeGenFunction &CGF, SourceLocation Loc, SmallString< 128 > &Buffer)
static void emitOffloadingArraysAndArgs(CodeGenFunction &CGF, MappableExprsHandler::MapCombinedInfoTy &CombinedInfo, CGOpenMPRuntime::TargetDataInfo &Info, llvm::OpenMPIRBuilder &OMPBuilder, bool IsNonContiguous=false, bool ForEndCall=false)
Emit the arrays used to pass the captures and map information to the offloading runtime library.
static RecordDecl * createKmpTaskTWithPrivatesRecordDecl(CodeGenModule &CGM, QualType KmpTaskTQTy, ArrayRef< PrivateDataTy > Privates)
static void emitInitWithReductionInitializer(CodeGenFunction &CGF, const OMPDeclareReductionDecl *DRD, const Expr *InitOp, Address Private, Address Original, QualType Ty)
static Address castToBase(CodeGenFunction &CGF, QualType BaseTy, QualType ElTy, Address OriginalBaseAddress, llvm::Value *Addr)
static void emitPrivatesInit(CodeGenFunction &CGF, const OMPExecutableDirective &D, Address KmpTaskSharedsPtr, LValue TDBase, const RecordDecl *KmpTaskTWithPrivatesQTyRD, QualType SharedsTy, QualType SharedsPtrTy, const OMPTaskDataTy &Data, ArrayRef< PrivateDataTy > Privates, bool ForDup)
Emit initialization for private variables in task-based directives.
static void emitClauseForBareTargetDirective(CodeGenFunction &CGF, const OMPExecutableDirective &D, llvm::SmallVectorImpl< llvm::Value * > &Values)
static llvm::Value * emitDestructorsFunction(CodeGenModule &CGM, SourceLocation Loc, QualType KmpInt32Ty, QualType KmpTaskTWithPrivatesPtrQTy, QualType KmpTaskTWithPrivatesQTy)
static void EmitOMPAggregateReduction(CodeGenFunction &CGF, QualType Type, const VarDecl *LHSVar, const VarDecl *RHSVar, const llvm::function_ref< void(CodeGenFunction &CGF, const Expr *, const Expr *, const Expr *)> &RedOpGen, const Expr *XExpr=nullptr, const Expr *EExpr=nullptr, const Expr *UpExpr=nullptr)
Emit reduction operation for each element of array (required for array sections) LHS op = RHS.
static void emitTargetCallFallback(CGOpenMPRuntime *OMPRuntime, llvm::Function *OutlinedFn, const OMPExecutableDirective &D, llvm::SmallVectorImpl< llvm::Value * > &CapturedVars, bool RequiresOuterTask, const CapturedStmt &CS, bool OffloadingMandatory, CodeGenFunction &CGF)
static llvm::Value * emitReduceInitFunction(CodeGenModule &CGM, SourceLocation Loc, ReductionCodeGen &RCG, unsigned N)
Emits reduction initializer function:
static RTCancelKind getCancellationKind(OpenMPDirectiveKind CancelRegion)
static void emitDependData(CodeGenFunction &CGF, QualType &KmpDependInfoTy, llvm::PointerUnion< unsigned *, LValue * > Pos, const OMPTaskDataTy::DependData &Data, Address DependenciesArray)
static llvm::Value * emitTaskPrivateMappingFunction(CodeGenModule &CGM, SourceLocation Loc, const OMPTaskDataTy &Data, QualType PrivatesQTy, ArrayRef< PrivateDataTy > Privates)
Emit a privates mapping function for correct handling of private and firstprivate variables.
static llvm::Value * emitReduceCombFunction(CodeGenModule &CGM, SourceLocation Loc, ReductionCodeGen &RCG, unsigned N, const Expr *ReductionOp, const Expr *LHS, const Expr *RHS, const Expr *PrivateRef)
Emits reduction combiner function:
static RecordDecl * createPrivatesRecordDecl(CodeGenModule &CGM, ArrayRef< PrivateDataTy > Privates)
static llvm::Value * getAllocatorVal(CodeGenFunction &CGF, const Expr *Allocator)
Return allocator value from expression, or return a null allocator (default when no allocator specifi...
static llvm::Function * emitProxyTaskFunction(CodeGenModule &CGM, SourceLocation Loc, OpenMPDirectiveKind Kind, QualType KmpInt32Ty, QualType KmpTaskTWithPrivatesPtrQTy, QualType KmpTaskTWithPrivatesQTy, QualType KmpTaskTQTy, QualType SharedsPtrTy, llvm::Function *TaskFunction, llvm::Value *TaskPrivatesMap)
Emit a proxy function which accepts kmp_task_t as the second argument.
static bool isAllocatableDecl(const VarDecl *VD)
static llvm::Value * getAlignmentValue(CodeGenModule &CGM, const VarDecl *VD)
Return the alignment from an allocate directive if present.
static void emitTargetCallKernelLaunch(CGOpenMPRuntime *OMPRuntime, llvm::Function *OutlinedFn, const OMPExecutableDirective &D, llvm::SmallVectorImpl< llvm::Value * > &CapturedVars, bool RequiresOuterTask, const CapturedStmt &CS, bool OffloadingMandatory, llvm::PointerIntPair< const Expr *, 2, OpenMPDeviceClauseModifier > Device, llvm::Value *OutlinedFnID, CodeGenFunction::OMPTargetDataInfo &InputInfo, llvm::Value *&MapTypesArray, llvm::Value *&MapNamesArray, llvm::function_ref< llvm::Value *(CodeGenFunction &CGF, const OMPLoopDirective &D)> SizeEmitter, CodeGenFunction &CGF, CodeGenModule &CGM)
static const OMPExecutableDirective * getNestedDistributeDirective(ASTContext &Ctx, const OMPExecutableDirective &D)
Check for inner distribute directive.
static std::pair< llvm::Value *, llvm::Value * > getPointerAndSize(CodeGenFunction &CGF, const Expr *E)
static const VarDecl * getBaseDecl(const Expr *Ref, const DeclRefExpr *&DE)
static bool getAArch64MTV(QualType QT, llvm::OpenMPIRBuilder::DeclareSimdKindTy Kind)
Maps To Vector (MTV), as defined in 4.1.1 of the AAVFABI (2021Q1).
static bool isTrivial(ASTContext &Ctx, const Expr *E)
Checks if the expression is constant or does not have non-trivial function calls.
static OpenMPSchedType getRuntimeSchedule(OpenMPScheduleClauseKind ScheduleKind, bool Chunked, bool Ordered)
Map the OpenMP loop schedule to the runtime enumeration.
static void getNumThreads(CodeGenFunction &CGF, const CapturedStmt *CS, const Expr **E, int32_t &UpperBound, bool UpperBoundOnly, llvm::Value **CondVal)
Check for a num threads constant value (stored in DefaultVal), or expression (stored in E).
static llvm::Value * emitDeviceID(llvm::PointerIntPair< const Expr *, 2, OpenMPDeviceClauseModifier > Device, CodeGenFunction &CGF)
static const OMPDeclareReductionDecl * getReductionInit(const Expr *ReductionOp)
Check if the combiner is a call to UDR combiner and if it is so return the UDR decl used for reductio...
static bool checkInitIsRequired(CodeGenFunction &CGF, ArrayRef< PrivateDataTy > Privates)
Check if duplication function is required for taskloops.
static bool validateAArch64Simdlen(CodeGenModule &CGM, SourceLocation SLoc, unsigned UserVLEN, unsigned WDS, char ISA)
static bool checkDestructorsRequired(const RecordDecl *KmpTaskTWithPrivatesQTyRD, ArrayRef< PrivateDataTy > Privates)
Checks if destructor function is required to be generated.
static llvm::TargetRegionEntryInfo getEntryInfoFromPresumedLoc(CodeGenModule &CGM, llvm::OpenMPIRBuilder &OMPBuilder, SourceLocation BeginLoc, llvm::StringRef ParentName="")
static void genMapInfo(MappableExprsHandler &MEHandler, CodeGenFunction &CGF, MappableExprsHandler::MapCombinedInfoTy &CombinedInfo, llvm::OpenMPIRBuilder &OMPBuilder, const llvm::DenseSet< CanonicalDeclPtr< const Decl > > &SkippedVarSet=llvm::DenseSet< CanonicalDeclPtr< const Decl > >())
static unsigned getAArch64LS(QualType QT, llvm::OpenMPIRBuilder::DeclareSimdKindTy Kind, ASTContext &C)
Computes the lane size (LS) of a return type or of an input parameter, as defined by LS(P) in 3....
static llvm::OpenMPIRBuilder::DeclareSimdBranch convertDeclareSimdBranch(OMPDeclareSimdDeclAttr::BranchStateTy State)
static void emitForStaticInitCall(CodeGenFunction &CGF, llvm::Value *UpdateLocation, llvm::Value *ThreadId, llvm::FunctionCallee ForStaticInitFunction, OpenMPSchedType Schedule, OpenMPScheduleClauseModifier M1, OpenMPScheduleClauseModifier M2, const CGOpenMPRuntime::StaticRTInput &Values)
static LValue loadToBegin(CodeGenFunction &CGF, QualType BaseTy, QualType ElTy, LValue BaseLV)
static void getKmpAffinityType(ASTContext &C, QualType &KmpTaskAffinityInfoTy)
Builds kmp_depend_info, if it is not built yet, and builds flags type.
static llvm::Constant * emitMappingInformation(CodeGenFunction &CGF, llvm::OpenMPIRBuilder &OMPBuilder, MappableExprsHandler::MappingExprInfo &MapExprs)
Emit a string constant containing the names of the values mapped to the offloading runtime library.
static void getDependTypes(ASTContext &C, QualType &KmpDependInfoTy, QualType &FlagsTy)
Builds kmp_depend_info, if it is not built yet, and builds flags type.
static llvm::Value * emitTaskDupFunction(CodeGenModule &CGM, SourceLocation Loc, const OMPExecutableDirective &D, QualType KmpTaskTWithPrivatesPtrQTy, const RecordDecl *KmpTaskTWithPrivatesQTyRD, const RecordDecl *KmpTaskTQTyRD, QualType SharedsTy, QualType SharedsPtrTy, const OMPTaskDataTy &Data, ArrayRef< PrivateDataTy > Privates, bool WithLastIter)
Emit task_dup function (for initialization of private/firstprivate/lastprivate vars and last_iter fla...
static std::pair< llvm::Value *, OMPDynGroupprivateFallbackType > emitDynCGroupMem(const OMPExecutableDirective &D, CodeGenFunction &CGF)
static llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseKind convertDeviceClause(const VarDecl *VD)
static llvm::Value * emitReduceFiniFunction(CodeGenModule &CGM, SourceLocation Loc, ReductionCodeGen &RCG, unsigned N)
Emits reduction finalizer function:
static void EmitOMPAggregateInit(CodeGenFunction &CGF, Address DestAddr, QualType Type, bool EmitDeclareReductionInit, const Expr *Init, const OMPDeclareReductionDecl *DRD, Address SrcAddr=Address::invalid())
Emit initialization of arrays of complex types.
static bool getAArch64PBV(QualType QT, ASTContext &C)
Pass By Value (PBV), as defined in 3.1.2 of the AAVFABI.
static void EmitDoacrossOrdered(CodeGenFunction &CGF, CodeGenModule &CGM, const T *C, llvm::Value *ULoc, llvm::Value *ThreadID)
static RTLDependenceKindTy translateDependencyKind(OpenMPDependClauseKind K)
Translates internal dependency kind into the runtime kind.
static void emitTargetCallElse(CGOpenMPRuntime *OMPRuntime, llvm::Function *OutlinedFn, const OMPExecutableDirective &D, llvm::SmallVectorImpl< llvm::Value * > &CapturedVars, bool RequiresOuterTask, const CapturedStmt &CS, bool OffloadingMandatory, CodeGenFunction &CGF)
static llvm::Function * emitCombinerOrInitializer(CodeGenModule &CGM, QualType Ty, const Expr *CombinerInitializer, const VarDecl *In, const VarDecl *Out, bool IsCombiner)
static void emitReductionCombiner(CodeGenFunction &CGF, const Expr *ReductionOp)
Emit reduction combiner.
static std::tuple< unsigned, unsigned, bool > getNDSWDS(const FunctionDecl *FD, ArrayRef< llvm::OpenMPIRBuilder::DeclareSimdAttrTy > ParamAttrs)
static std::string generateUniqueName(CodeGenModule &CGM, llvm::StringRef Prefix, const Expr *Ref)
static llvm::Function * emitParallelOrTeamsOutlinedFunction(CodeGenModule &CGM, const OMPExecutableDirective &D, const CapturedStmt *CS, const VarDecl *ThreadIDVar, OpenMPDirectiveKind InnermostKind, const StringRef OutlinedHelperName, const RegionCodeGenTy &CodeGen)
static Address emitAddrOfVarFromArray(CodeGenFunction &CGF, Address Array, unsigned Index, const VarDecl *Var)
Given an array of pointers to variables, project the address of a given variable.
static FieldDecl * addFieldToRecordDecl(ASTContext &C, DeclContext *DC, QualType FieldTy)
static unsigned evaluateCDTSize(const FunctionDecl *FD, ArrayRef< llvm::OpenMPIRBuilder::DeclareSimdAttrTy > ParamAttrs)
static ValueDecl * getDeclFromThisExpr(const Expr *E)
static void genMapInfoForCaptures(MappableExprsHandler &MEHandler, CodeGenFunction &CGF, const CapturedStmt &CS, llvm::SmallVectorImpl< llvm::Value * > &CapturedVars, llvm::OpenMPIRBuilder &OMPBuilder, llvm::DenseSet< CanonicalDeclPtr< const Decl > > &MappedVarSet, MappableExprsHandler::MapCombinedInfoTy &CombinedInfo)
static RecordDecl * createKmpTaskTRecordDecl(CodeGenModule &CGM, OpenMPDirectiveKind Kind, QualType KmpInt32Ty, QualType KmpRoutineEntryPointerQTy)
static int addMonoNonMonoModifier(CodeGenModule &CGM, OpenMPSchedType Schedule, OpenMPScheduleClauseModifier M1, OpenMPScheduleClauseModifier M2)
static mlir::omp::DeclareTargetCaptureClause convertCaptureClause(OMPDeclareTargetDeclAttr::MapTypeTy mapTy)
static bool isAssumedToBeNotEmitted(const ValueDecl *vd, bool isDevice)
Returns true if the declaration should be skipped based on its device_type attribute and the current ...
@ LLVM_MARK_AS_BITMASK_ENUM
Result
Implement __builtin_bit_cast and related operations.
This file defines OpenMP AST classes for clauses.
Defines some OpenMP-specific enums and functions.
Defines the SourceManager interface.
This file defines OpenMP AST classes for executable directives and clauses.
__DEVICE__ int max(int __a, int __b)
This represents clause 'affinity' in the 'pragma omp task'-based directives.
ValueDecl * getAssociatedDeclaration() const
Expr * getAssociatedExpression() const
static std::pair< const Expr *, std::optional< size_t > > findAttachPtrExpr(MappableExprComponentListRef Components, OpenMPDirectiveKind CurDirKind)
Find the attach pointer expression from a list of mappable expression components.
static QualType getComponentExprElementType(const Expr *Exp)
Get the type of an element of a ComponentList Expr Exp.
ArrayRef< MappableComponent > MappableExprComponentListRef
This represents implicit clause 'depend' for the 'pragma omp task' directive.
This represents 'detach' clause in the 'pragma omp task' directive.
This represents 'device' clause in the 'pragma omp ...' directive.
This represents the 'doacross' clause for the 'pragma omp ordered' directive.
This represents 'dyn_groupprivate' clause in 'pragma omp target ...' and 'pragma omp teams ....
This represents clause 'map' in the 'pragma omp ...' directives.
This represents clause 'nontemporal' in the 'pragma omp ...' directives.
This represents 'num_teams' clause in the 'pragma omp ...' directive.
This represents 'thread_limit' clause in the 'pragma omp ...' directive.
This represents clause 'uses_allocators' in the 'pragma omp target'-based directives.
This represents 'ompx_attribute' clause in a directive that might generate an outlined function.
This represents 'ompx_bare' clause in the 'pragma omp target teams ...' directive.
This represents 'ompx_dyn_cgroup_mem' clause in the 'pragma omp target ...' directive.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
SourceManager & getSourceManager()
const ConstantArrayType * getAsConstantArrayType(QualType T) const
CharUnits getTypeAlignInChars(QualType T) const
Return the ABI-specified alignment of a (complete) type T, in characters.
const ASTRecordLayout & getASTRecordLayout(const RecordDecl *D) const
Get or compute information about the layout of the specified record (struct/union/class) D,...
QualType getPointerType(QualType T) const
Return the uniqued reference to the type for a pointer to the specified type.
QualType getConstantArrayType(QualType EltTy, const llvm::APInt &ArySize, const Expr *SizeExpr, ArraySizeModifier ASM, unsigned IndexTypeQuals) const
Return the unique reference to the type for a constant array of the specified element type.
const LangOptions & getLangOpts() const
QualType getIntTypeForBitwidth(unsigned DestWidth, unsigned Signed) const
getIntTypeForBitwidth - sets integer QualTy according to specified details: bitwidth,...
CharUnits getDeclAlign(const Decl *D, bool ForAlignof=false) const
Return a conservative estimate of the alignment of the specified decl D.
int64_t toBits(CharUnits CharSize) const
Convert a size in characters to a size in bits.
const ArrayType * getAsArrayType(QualType T) const
Type Query functions.
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
static bool hasSameType(QualType T1, QualType T2)
Determine whether the given types T1 and T2 are equivalent.
const VariableArrayType * getAsVariableArrayType(QualType T) const
QualType getSizeType() const
Return the unique type for "size_t" (C99 7.17), defined in <stddef.h>.
unsigned getTypeAlign(QualType T) const
Return the ABI-specified alignment of a (complete) type T, in bits.
CharUnits getSize() const
getSize - Get the record size in characters.
uint64_t getFieldOffset(unsigned FieldNo) const
getFieldOffset - Get the offset of the given field index, in bits.
CharUnits getNonVirtualSize() const
getNonVirtualSize - Get the non-virtual size (in chars) of an object, which is the size of the object...
static QualType getBaseOriginalType(const Expr *Base)
Return original type of the base expression for array section.
Represents an array type, per C99 6.7.5.2 - Array Declarators.
Attr - This represents one attribute.
Represents a base class of a C++ class.
Represents a C++ constructor within a class.
Represents a C++ destructor within a class.
const CXXRecordDecl * getParent() const
Return the parent of this method declaration, which is the class in which this method is defined.
QualType getFunctionObjectParameterType() const
Represents a C++ struct/union/class.
bool isLambda() const
Determine whether this class describes a lambda function object.
void getCaptureFields(llvm::DenseMap< const ValueDecl *, FieldDecl * > &Captures, FieldDecl *&ThisCapture) const
For a closure type, retrieve the mapping from captured variables and this to the non-static data memb...
unsigned getNumBases() const
Retrieves the number of base classes of this class.
base_class_range vbases()
capture_const_range captures() const
CXXDestructorDecl * getDestructor() const
Returns the destructor decl for this class.
CanProxy< U > castAs() const
A wrapper class around a pointer that always points to its canonical declaration.
Describes the capture of either a variable, or 'this', or variable-length array type.
bool capturesVariableByCopy() const
Determine whether this capture handles a variable by copy.
VarDecl * getCapturedVar() const
Retrieve the declaration of the variable being captured.
bool capturesVariableArrayType() const
Determine whether this capture handles a variable-length array type.
bool capturesThis() const
Determine whether this capture handles the C++ 'this' pointer.
bool capturesVariable() const
Determine whether this capture handles a variable (by reference).
This captures a statement into a function.
const Capture * const_capture_iterator
capture_iterator capture_end() const
Retrieve an iterator pointing past the end of the sequence of captures.
const RecordDecl * getCapturedRecordDecl() const
Retrieve the record declaration for captured variables.
Stmt * getCapturedStmt()
Retrieve the statement being captured.
bool capturesVariable(const VarDecl *Var) const
True if this variable has been captured.
capture_iterator capture_begin()
Retrieve an iterator pointing to the first capture.
CharUnits - This is an opaque type for sizes expressed in character units.
bool isZero() const
isZero - Test whether the quantity equals zero.
llvm::Align getAsAlign() const
getAsAlign - Returns Quantity as a valid llvm::Align, Beware llvm::Align assumes power of two 8-bit b...
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
CharUnits alignmentOfArrayElement(CharUnits elementSize) const
Given that this is the alignment of the first element of an array, return the minimum alignment of an...
static CharUnits fromQuantity(QuantityType Quantity)
fromQuantity - Construct a CharUnits quantity from a raw integer type.
CharUnits alignTo(const CharUnits &Align) const
alignTo - Returns the next integer (mod 2**64) that is greater than or equal to this quantity and is ...
std::string SampleProfileFile
Name of the profile file to use with -fprofile-sample-use.
Like RawAddress, an abstract representation of an aligned address, but the pointer contained in this ...
llvm::Value * emitRawPointer(CodeGenFunction &CGF) const
Return the pointer contained in this class after authenticating it and adding offset to it if necessa...
CharUnits getAlignment() const
llvm::Type * getElementType() const
Return the type of the values stored in this address.
Address withPointer(llvm::Value *NewPointer, KnownNonNull_t IsKnownNonNull) const
Return address with different pointer, but same element type and alignment.
Address withElementType(llvm::Type *ElemTy) const
Return address with different element type, but same pointer and alignment.
llvm::PointerType * getType() const
Return the type of the pointer value.
static ApplyDebugLocation CreateArtificial(CodeGenFunction &CGF)
Apply TemporaryLocation if it is valid.
static ApplyDebugLocation CreateDefaultArtificial(CodeGenFunction &CGF, SourceLocation TemporaryLocation)
Apply TemporaryLocation if it is valid.
static ApplyDebugLocation CreateEmpty(CodeGenFunction &CGF)
Set the IRBuilder to not attach debug locations.
llvm::StoreInst * CreateStore(llvm::Value *Val, Address Addr, bool IsVolatile=false)
Address CreateGEP(CodeGenFunction &CGF, Address Addr, llvm::Value *Index, const llvm::Twine &Name="")
Address CreatePointerBitCastOrAddrSpaceCast(Address Addr, llvm::Type *Ty, llvm::Type *ElementTy, const llvm::Twine &Name="")
Address CreateConstArrayGEP(Address Addr, uint64_t Index, const llvm::Twine &Name="")
Given addr = [n x T]* ... produce name = getelementptr inbounds addr, i64 0, i64 index where i64 is a...
llvm::LoadInst * CreateLoad(Address Addr, const llvm::Twine &Name="")
llvm::CallInst * CreateMemCpy(Address Dest, Address Src, llvm::Value *Size, bool IsVolatile=false)
Address CreateConstGEP(Address Addr, uint64_t Index, const llvm::Twine &Name="")
Given addr = T* ... produce name = getelementptr inbounds addr, i64 index where i64 is actually the t...
Address CreateAddrSpaceCast(Address Addr, llvm::Type *Ty, llvm::Type *ElementTy, const llvm::Twine &Name="")
CGFunctionInfo - Class to encapsulate the information about a function definition.
DisableAutoDeclareTargetRAII(CodeGenModule &CGM)
~DisableAutoDeclareTargetRAII()
~LastprivateConditionalRAII()
static LastprivateConditionalRAII disable(CodeGenFunction &CGF, const OMPExecutableDirective &S)
NontemporalDeclsRAII(CodeGenModule &CGM, const OMPLoopDirective &S)
Struct that keeps all the relevant information that should be kept throughout a 'target data' region.
llvm::DenseMap< const ValueDecl *, llvm::Value * > CaptureDeviceAddrMap
Map between the a declaration of a capture and the corresponding new llvm address where the runtime r...
~UntiedTaskLocalDeclsRAII()
UntiedTaskLocalDeclsRAII(CodeGenFunction &CGF, const llvm::MapVector< CanonicalDeclPtr< const VarDecl >, std::pair< Address, Address > > &LocalVars)
virtual Address emitThreadIDAddress(CodeGenFunction &CGF, SourceLocation Loc)
Emits address of the word in a memory where current thread id is stored.
llvm::StringSet ThreadPrivateWithDefinition
Set of threadprivate variables with the generated initializer.
CGOpenMPRuntime(CodeGenModule &CGM)
void emitUpdateDependObjectsClause(CodeGenFunction &CGF, LValue DepobjLVal, OpenMPDependClauseKind NewDepKind, SourceLocation Loc)
Updates the dependency kind in the specified depobj object.
virtual void emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc, const OMPExecutableDirective &D, llvm::Function *TaskFunction, QualType SharedsTy, Address Shareds, const Expr *IfCond, const OMPTaskDataTy &Data)
Emit task region for the task directive.
void createOffloadEntriesAndInfoMetadata()
Creates all the offload entries in the current compilation unit along with the associated metadata.
const Expr * getNumTeamsExprForTargetDirective(CodeGenFunction &CGF, const OMPExecutableDirective &D, int32_t &MinTeamsVal, int32_t &MaxTeamsVal)
Emit the number of teams for a target directive.
virtual Address getAddrOfThreadPrivate(CodeGenFunction &CGF, const VarDecl *VD, Address VDAddr, SourceLocation Loc)
Returns address of the threadprivate variable for the current thread.
void emitDeferredTargetDecls() const
Emit deferred declare target variables marked for deferred emission.
virtual llvm::Value * emitForNext(CodeGenFunction &CGF, SourceLocation Loc, unsigned IVSize, bool IVSigned, Address IL, Address LB, Address UB, Address ST)
Call __kmpc_dispatch_next( ident_t *loc, kmp_int32 tid, kmp_int32 *p_lastiter, kmp_int[32|64] *p_lowe...
bool markAsGlobalTarget(GlobalDecl GD)
Marks the declaration as already emitted for the device code and returns true, if it was marked alrea...
virtual void emitParallelCall(CodeGenFunction &CGF, SourceLocation Loc, llvm::Function *OutlinedFn, ArrayRef< llvm::Value * > CapturedVars, const Expr *IfCond, llvm::Value *NumThreads, OpenMPNumThreadsClauseModifier NumThreadsModifier=OMPC_NUMTHREADS_unknown, OpenMPSeverityClauseKind Severity=OMPC_SEVERITY_fatal, const Expr *Message=nullptr)
Emits code for parallel or serial call of the OutlinedFn with variables captured in a record which ad...
llvm::SmallDenseSet< CanonicalDeclPtr< const Decl > > NontemporalDeclsSet
virtual void emitTargetDataStandAloneCall(CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, const Expr *Device)
Emit the data mapping/movement code associated with the directive D that should be of the form 'targe...
virtual void emitNumThreadsClause(CodeGenFunction &CGF, llvm::Value *NumThreads, SourceLocation Loc, OpenMPNumThreadsClauseModifier Modifier=OMPC_NUMTHREADS_unknown, OpenMPSeverityClauseKind Severity=OMPC_SEVERITY_fatal, SourceLocation SeverityLoc=SourceLocation(), const Expr *Message=nullptr, SourceLocation MessageLoc=SourceLocation())
Emits call to void __kmpc_push_num_threads(ident_t *loc, kmp_int32global_tid, kmp_int32 num_threads) ...
QualType SavedKmpTaskloopTQTy
Saved kmp_task_t for taskloop-based directive.
virtual void emitSingleRegion(CodeGenFunction &CGF, const RegionCodeGenTy &SingleOpGen, SourceLocation Loc, ArrayRef< const Expr * > CopyprivateVars, ArrayRef< const Expr * > DestExprs, ArrayRef< const Expr * > SrcExprs, ArrayRef< const Expr * > AssignmentOps)
Emits a single region.
virtual bool emitTargetGlobal(GlobalDecl GD)
Emit the global GD if it is meaningful for the target.
void setLocThreadIdInsertPt(CodeGenFunction &CGF, bool AtCurrentPoint=false)
std::string getOutlinedHelperName(StringRef Name) const
Get the function name of an outlined region.
bool HasEmittedDeclareTargetRegion
Flag for keeping track of weather a device routine has been emitted.
llvm::Constant * getOrCreateThreadPrivateCache(const VarDecl *VD)
If the specified mangled name is not in the module, create and return threadprivate cache object.
virtual Address getTaskReductionItem(CodeGenFunction &CGF, SourceLocation Loc, llvm::Value *ReductionsPtr, LValue SharedLVal)
Get the address of void * type of the privatue copy of the reduction item specified by the SharedLVal...
virtual void emitForDispatchDeinit(CodeGenFunction &CGF, SourceLocation Loc)
This is used for non static scheduled types and when the ordered clause is present on the loop constr...
void emitCall(CodeGenFunction &CGF, SourceLocation Loc, llvm::FunctionCallee Callee, ArrayRef< llvm::Value * > Args={}) const
Emits Callee function call with arguments Args with location Loc.
virtual void getDefaultScheduleAndChunk(CodeGenFunction &CGF, const OMPLoopDirective &S, OpenMPScheduleClauseKind &ScheduleKind, const Expr *&ChunkExpr) const
Choose default schedule type and chunk value for the schedule clause.
virtual std::pair< llvm::Function *, llvm::Function * > getUserDefinedReduction(const OMPDeclareReductionDecl *D)
Get combiner/initializer for the specified user-defined reduction, if any.
virtual bool isGPU() const
Returns true if the current target is a GPU.
static const Stmt * getSingleCompoundChild(ASTContext &Ctx, const Stmt *Body)
Checks if the Body is the CompoundStmt and returns its child statement iff there is only one that is ...
virtual void emitDeclareTargetFunction(const FunctionDecl *FD, llvm::GlobalValue *GV)
Emit code for handling declare target functions in the runtime.
bool HasRequiresUnifiedSharedMemory
Flag for keeping track of weather a requires unified_shared_memory directive is present.
llvm::Value * emitUpdateLocation(CodeGenFunction &CGF, SourceLocation Loc, unsigned Flags=0, bool EmitLoc=false)
Emits object of ident_t type with info for source location.
bool isLocalVarInUntiedTask(CodeGenFunction &CGF, const VarDecl *VD) const
Returns true if the variable is a local variable in untied task.
virtual void emitTeamsCall(CodeGenFunction &CGF, const OMPExecutableDirective &D, SourceLocation Loc, llvm::Function *OutlinedFn, ArrayRef< llvm::Value * > CapturedVars)
Emits code for teams call of the OutlinedFn with variables captured in a record which address is stor...
virtual void emitCancellationPointCall(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind CancelRegion)
Emit code for 'cancellation point' construct.
virtual llvm::Function * emitThreadPrivateVarDefinition(const VarDecl *VD, Address VDAddr, SourceLocation Loc, bool PerformInit, CodeGenFunction *CGF=nullptr)
Emit a code for initialization of threadprivate variable.
FunctionUDMMapTy FunctionUDMMap
virtual ConstantAddress getAddrOfDeclareTargetVar(const VarDecl *VD)
Returns the address of the variable marked as declare target with link clause OR as declare target wi...
llvm::Function * getOrCreateUserDefinedMapperFunc(const OMPDeclareMapperDecl *D)
Get the function for the specified user-defined mapper.
OpenMPLocThreadIDMapTy OpenMPLocThreadIDMap
virtual void functionFinished(CodeGenFunction &CGF)
Cleans up references to the objects in finished function.
virtual llvm::Function * emitTeamsOutlinedFunction(CodeGenFunction &CGF, const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen)
Emits outlined function for the specified OpenMP teams directive D.
QualType KmpTaskTQTy
Type typedef struct kmp_task { void * shareds; /**< pointer to block of pointers to shared vars / k...
llvm::OpenMPIRBuilder OMPBuilder
An OpenMP-IR-Builder instance.
virtual void emitDoacrossInit(CodeGenFunction &CGF, const OMPLoopDirective &D, ArrayRef< Expr * > NumIterations)
Emit initialization for doacross loop nesting support.
virtual void adjustTargetSpecificDataForLambdas(CodeGenFunction &CGF, const OMPExecutableDirective &D) const
Adjust some parameters for the target-based directives, like addresses of the variables captured by r...
FunctionUDRMapTy FunctionUDRMap
virtual void emitTargetDataCalls(CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, const Expr *Device, const RegionCodeGenTy &CodeGen, CGOpenMPRuntime::TargetDataInfo &Info)
Emit the target data mapping code associated with D.
virtual unsigned getDefaultLocationReserved2Flags() const
Returns additional flags that can be stored in reserved_2 field of the default location.
virtual Address getParameterAddress(CodeGenFunction &CGF, const VarDecl *NativeParam, const VarDecl *TargetParam) const
Gets the address of the native argument basing on the address of the target-specific parameter.
void emitUsesAllocatorsFini(CodeGenFunction &CGF, const Expr *Allocator)
Destroys user defined allocators specified in the uses_allocators clause.
QualType KmpTaskAffinityInfoTy
Type typedef struct kmp_task_affinity_info { kmp_intptr_t base_addr; size_t len; struct { bool flag1 ...
void emitPrivateReduction(CodeGenFunction &CGF, SourceLocation Loc, const Expr *Privates, const Expr *LHSExprs, const Expr *RHSExprs, const Expr *ReductionOps)
Emits code for private variable reduction.
llvm::Value * emitNumTeamsForTargetDirective(CodeGenFunction &CGF, const OMPExecutableDirective &D)
virtual void emitTargetOutlinedFunctionHelper(const OMPExecutableDirective &D, StringRef ParentName, llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID, bool IsOffloadEntry, const RegionCodeGenTy &CodeGen)
Helper to emit outlined function for 'target' directive.
void scanForTargetRegionsFunctions(const Stmt *S, StringRef ParentName)
Start scanning from statement S and emit all target regions found along the way.
SmallVector< llvm::Value *, 4 > emitDepobjElementsSizes(CodeGenFunction &CGF, QualType &KmpDependInfoTy, const OMPTaskDataTy::DependData &Data)
virtual llvm::Value * emitMessageClause(CodeGenFunction &CGF, const Expr *Message, SourceLocation Loc)
virtual void emitTaskgroupRegion(CodeGenFunction &CGF, const RegionCodeGenTy &TaskgroupOpGen, SourceLocation Loc)
Emit a taskgroup region.
llvm::DenseMap< llvm::Function *, llvm::DenseMap< CanonicalDeclPtr< const Decl >, std::tuple< QualType, const FieldDecl *, const FieldDecl *, LValue > > > LastprivateConditionalToTypes
Maps local variables marked as lastprivate conditional to their internal types.
virtual bool emitTargetGlobalVariable(GlobalDecl GD)
Emit the global variable if it is a valid device global variable.
virtual void emitNumTeamsClause(CodeGenFunction &CGF, const Expr *NumTeams, const Expr *ThreadLimit, SourceLocation Loc)
Emits call to void __kmpc_push_num_teams(ident_t *loc, kmp_int32global_tid, kmp_int32 num_teams,...
bool hasRequiresUnifiedSharedMemory() const
Return whether the unified_shared_memory has been specified.
virtual Address getAddrOfArtificialThreadPrivate(CodeGenFunction &CGF, QualType VarType, StringRef Name)
Creates artificial threadprivate variable with name Name and type VarType.
void emitUserDefinedMapper(const OMPDeclareMapperDecl *D, CodeGenFunction *CGF=nullptr)
Emit the function for the user defined mapper construct.
bool HasEmittedTargetRegion
Flag for keeping track of weather a target region has been emitted.
void emitDepobjElements(CodeGenFunction &CGF, QualType &KmpDependInfoTy, LValue PosLVal, const OMPTaskDataTy::DependData &Data, Address DependenciesArray)
std::string getReductionFuncName(StringRef Name) const
Get the function name of a reduction function.
virtual void processRequiresDirective(const OMPRequiresDecl *D)
Perform check on requires decl to ensure that target architecture supports unified addressing.
llvm::DenseSet< CanonicalDeclPtr< const Decl > > AlreadyEmittedTargetDecls
List of the emitted declarations.
virtual llvm::Value * emitTaskReductionInit(CodeGenFunction &CGF, SourceLocation Loc, ArrayRef< const Expr * > LHSExprs, ArrayRef< const Expr * > RHSExprs, const OMPTaskDataTy &Data)
Emit a code for initialization of task reduction clause.
llvm::Value * getThreadID(CodeGenFunction &CGF, SourceLocation Loc)
Gets thread id value for the current thread.
virtual void emitLastprivateConditionalFinalUpdate(CodeGenFunction &CGF, LValue PrivLVal, const VarDecl *VD, SourceLocation Loc)
Gets the address of the global copy used for lastprivate conditional update, if any.
llvm::MapVector< CanonicalDeclPtr< const VarDecl >, std::pair< Address, Address > > UntiedLocalVarsAddressesMap
virtual void emitErrorCall(CodeGenFunction &CGF, SourceLocation Loc, Expr *ME, bool IsFatal)
Emit __kmpc_error call for error directive extern void __kmpc_error(ident_t *loc, int severity,...
void clearLocThreadIdInsertPt(CodeGenFunction &CGF)
virtual void emitTaskyieldCall(CodeGenFunction &CGF, SourceLocation Loc)
Emits code for a taskyield directive.
std::string getName(ArrayRef< StringRef > Parts) const
Get the platform-specific name separator.
QualType KmpRoutineEntryPtrQTy
void computeMinAndMaxThreadsAndTeams(const OMPExecutableDirective &D, CodeGenFunction &CGF, llvm::OpenMPIRBuilder::TargetKernelDefaultAttrs &Attrs)
Helper to determine the min/max number of threads/teams for D.
virtual void emitFlush(CodeGenFunction &CGF, ArrayRef< const Expr * > Vars, SourceLocation Loc, llvm::AtomicOrdering AO)
Emit flush of the variables specified in 'omp flush' directive.
virtual void emitTaskwaitCall(CodeGenFunction &CGF, SourceLocation Loc, const OMPTaskDataTy &Data)
Emit code for 'taskwait' directive.
virtual void emitProcBindClause(CodeGenFunction &CGF, llvm::omp::ProcBindKind ProcBind, SourceLocation Loc)
Emit call to void __kmpc_push_proc_bind(ident_t *loc, kmp_int32global_tid, int proc_bind) to generate...
void emitLastprivateConditionalUpdate(CodeGenFunction &CGF, LValue IVLVal, StringRef UniqueDeclName, LValue LVal, SourceLocation Loc)
Emit update for lastprivate conditional data.
virtual void emitTaskLoopCall(CodeGenFunction &CGF, SourceLocation Loc, const OMPLoopDirective &D, llvm::Function *TaskFunction, QualType SharedsTy, Address Shareds, const Expr *IfCond, const OMPTaskDataTy &Data)
Emit task region for the taskloop directive.
virtual void emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind Kind, bool EmitChecks=true, bool ForceSimpleCall=false)
Emit an implicit/explicit barrier for OpenMP threads.
static unsigned getDefaultFlagsForBarriers(OpenMPDirectiveKind Kind)
Returns default flags for the barriers depending on the directive, for which this barier is going to ...
virtual bool emitTargetFunctions(GlobalDecl GD)
Emit the target regions enclosed in GD function definition or the function itself in case it is a val...
TaskResultTy emitTaskInit(CodeGenFunction &CGF, SourceLocation Loc, const OMPExecutableDirective &D, llvm::Function *TaskFunction, QualType SharedsTy, Address Shareds, const OMPTaskDataTy &Data)
Emit task region for the task directive.
llvm::Value * emitTargetNumIterationsCall(CodeGenFunction &CGF, const OMPExecutableDirective &D, llvm::function_ref< llvm::Value *(CodeGenFunction &CGF, const OMPLoopDirective &D)> SizeEmitter)
Return the trip count of loops associated with constructs / 'target teams distribute' and 'teams dist...
llvm::StringMap< llvm::AssertingVH< llvm::GlobalVariable >, llvm::BumpPtrAllocator > InternalVars
An ordered map of auto-generated variables to their unique names.
virtual void emitDistributeStaticInit(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDistScheduleClauseKind SchedKind, const StaticRTInput &Values)
llvm::SmallVector< UntiedLocalVarsAddressesMap, 4 > UntiedLocalVarsStack
virtual void emitForStaticFinish(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind DKind)
Call the appropriate runtime routine to notify that we finished all the work with current loop.
virtual void emitThreadLimitClause(CodeGenFunction &CGF, const Expr *ThreadLimit, SourceLocation Loc)
Emits call to void __kmpc_set_thread_limit(ident_t *loc, kmp_int32global_tid, kmp_int32 thread_limit)...
void emitIfClause(CodeGenFunction &CGF, const Expr *Cond, const RegionCodeGenTy &ThenGen, const RegionCodeGenTy &ElseGen)
Emits code for OpenMP 'if' clause using specified CodeGen function.
Address emitDepobjDependClause(CodeGenFunction &CGF, const OMPTaskDataTy::DependData &Dependencies, SourceLocation Loc)
Emits list of dependecies based on the provided data (array of dependence/expression pairs) for depob...
bool isNontemporalDecl(const ValueDecl *VD) const
Checks if the VD variable is marked as nontemporal declaration in current context.
virtual llvm::Function * emitParallelOutlinedFunction(CodeGenFunction &CGF, const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen)
Emits outlined function for the specified OpenMP parallel directive D.
const Expr * getNumThreadsExprForTargetDirective(CodeGenFunction &CGF, const OMPExecutableDirective &D, int32_t &UpperBound, bool UpperBoundOnly, llvm::Value **CondExpr=nullptr, const Expr **ThreadLimitExpr=nullptr)
Check for a number of threads upper bound constant value (stored in UpperBound), or expression (retur...
virtual void registerVTableOffloadEntry(llvm::GlobalVariable *VTable, const VarDecl *VD)
Register VTable to OpenMP offload entry.
virtual llvm::Value * emitSeverityClause(OpenMPSeverityClauseKind Severity, SourceLocation Loc)
llvm::SmallVector< LastprivateConditionalData, 4 > LastprivateConditionalStack
Stack for list of addresses of declarations in current context marked as lastprivate conditional.
virtual void emitForStaticInit(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind DKind, const OpenMPScheduleTy &ScheduleKind, const StaticRTInput &Values)
Call the appropriate runtime routine to initialize it before start of loop.
virtual void emitDeclareSimdFunction(const FunctionDecl *FD, llvm::Function *Fn)
Marks function Fn with properly mangled versions of vector functions.
llvm::AtomicOrdering getDefaultMemoryOrdering() const
Gets default memory ordering as specified in requires directive.
virtual bool isStaticNonchunked(OpenMPScheduleClauseKind ScheduleKind, bool Chunked) const
Check if the specified ScheduleKind is static non-chunked.
virtual void emitAndRegisterVTable(CodeGenModule &CGM, CXXRecordDecl *CXXRecord, const VarDecl *VD)
Emit and register VTable for the C++ class in OpenMP offload entry.
llvm::Value * getCriticalRegionLock(StringRef CriticalName)
Returns corresponding lock object for the specified critical region name.
virtual void emitCancelCall(CodeGenFunction &CGF, SourceLocation Loc, const Expr *IfCond, OpenMPDirectiveKind CancelRegion)
Emit code for 'cancel' construct.
QualType SavedKmpTaskTQTy
Saved kmp_task_t for task directive.
virtual void emitMasterRegion(CodeGenFunction &CGF, const RegionCodeGenTy &MasterOpGen, SourceLocation Loc)
Emits a master region.
virtual llvm::Function * emitTaskOutlinedFunction(const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, const VarDecl *PartIDVar, const VarDecl *TaskTVar, OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen, bool Tied, unsigned &NumberOfParts)
Emits outlined function for the OpenMP task directive D.
llvm::DenseMap< llvm::Function *, unsigned > FunctionToUntiedTaskStackMap
Maps function to the position of the untied task locals stack.
void emitDestroyClause(CodeGenFunction &CGF, LValue DepobjLVal, SourceLocation Loc)
Emits the code to destroy the dependency object provided in depobj directive.
virtual void emitTaskReductionFixups(CodeGenFunction &CGF, SourceLocation Loc, ReductionCodeGen &RCG, unsigned N)
Required to resolve existing problems in the runtime.
llvm::ArrayType * KmpCriticalNameTy
Type kmp_critical_name, originally defined as typedef kmp_int32 kmp_critical_name[8];.
virtual void emitDoacrossOrdered(CodeGenFunction &CGF, const OMPDependClause *C)
Emit code for doacross ordered directive with 'depend' clause.
llvm::DenseMap< const OMPDeclareMapperDecl *, llvm::Function * > UDMMap
Map from the user-defined mapper declaration to its corresponding functions.
virtual void checkAndEmitLastprivateConditional(CodeGenFunction &CGF, const Expr *LHS)
Checks if the provided LVal is lastprivate conditional and emits the code to update the value of the ...
std::pair< llvm::Value *, LValue > getDepobjElements(CodeGenFunction &CGF, LValue DepobjLVal, SourceLocation Loc)
Returns the number of the elements and the address of the depobj dependency array.
llvm::SmallDenseSet< const VarDecl * > DeferredGlobalVariables
List of variables that can become declare target implicitly and, thus, must be emitted.
void emitUsesAllocatorsInit(CodeGenFunction &CGF, const Expr *Allocator, const Expr *AllocatorTraits)
Initializes user defined allocators specified in the uses_allocators clauses.
virtual void registerVTable(const OMPExecutableDirective &D)
Emit code for registering vtable by scanning through map clause in OpenMP target region.
llvm::Type * KmpRoutineEntryPtrTy
Type typedef kmp_int32 (* kmp_routine_entry_t)(kmp_int32, void *);.
llvm::Type * getIdentTyPointerTy()
Returns pointer to ident_t type.
void emitSingleReductionCombiner(CodeGenFunction &CGF, const Expr *ReductionOp, const Expr *PrivateRef, const DeclRefExpr *LHS, const DeclRefExpr *RHS)
Emits single reduction combiner.
llvm::OpenMPIRBuilder & getOMPBuilder()
virtual void emitTargetOutlinedFunction(const OMPExecutableDirective &D, StringRef ParentName, llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID, bool IsOffloadEntry, const RegionCodeGenTy &CodeGen)
Emit outilined function for 'target' directive.
virtual void emitCriticalRegion(CodeGenFunction &CGF, StringRef CriticalName, const RegionCodeGenTy &CriticalOpGen, SourceLocation Loc, const Expr *Hint=nullptr)
Emits a critical region.
virtual void emitForOrderedIterationEnd(CodeGenFunction &CGF, SourceLocation Loc, unsigned IVSize, bool IVSigned)
Call the appropriate runtime routine to notify that we finished iteration of the ordered loop with th...
virtual void emitOutlinedFunctionCall(CodeGenFunction &CGF, SourceLocation Loc, llvm::FunctionCallee OutlinedFn, ArrayRef< llvm::Value * > Args={}) const
Emits call of the outlined function with the provided arguments, translating these arguments to corre...
llvm::Value * emitNumThreadsForTargetDirective(CodeGenFunction &CGF, const OMPExecutableDirective &D)
Emit an expression that denotes the number of threads a target region shall use.
void emitThreadPrivateVarInit(CodeGenFunction &CGF, Address VDAddr, llvm::Value *Ctor, llvm::Value *CopyCtor, llvm::Value *Dtor, SourceLocation Loc)
Emits initialization code for the threadprivate variables.
virtual void emitUserDefinedReduction(CodeGenFunction *CGF, const OMPDeclareReductionDecl *D)
Emit code for the specified user defined reduction construct.
virtual void checkAndEmitSharedLastprivateConditional(CodeGenFunction &CGF, const OMPExecutableDirective &D, const llvm::DenseSet< CanonicalDeclPtr< const VarDecl > > &IgnoredDecls)
Checks if the lastprivate conditional was updated in inner region and writes the value.
QualType KmpDimTy
struct kmp_dim { // loop bounds info casted to kmp_int64 kmp_int64 lo; // lower kmp_int64 up; // uppe...
virtual void emitInlinedDirective(CodeGenFunction &CGF, OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen, bool HasCancel=false)
Emit code for the directive that does not require outlining.
virtual void registerTargetGlobalVariable(const VarDecl *VD, llvm::Constant *Addr)
Checks if the provided global decl GD is a declare target variable and registers it when emitting cod...
virtual void emitFunctionProlog(CodeGenFunction &CGF, const Decl *D)
Emits OpenMP-specific function prolog.
void emitKmpRoutineEntryT(QualType KmpInt32Ty)
Build type kmp_routine_entry_t (if not built yet).
virtual bool isStaticChunked(OpenMPScheduleClauseKind ScheduleKind, bool Chunked) const
Check if the specified ScheduleKind is static chunked.
virtual void emitTargetCall(CodeGenFunction &CGF, const OMPExecutableDirective &D, llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID, const Expr *IfCond, llvm::PointerIntPair< const Expr *, 2, OpenMPDeviceClauseModifier > Device, llvm::function_ref< llvm::Value *(CodeGenFunction &CGF, const OMPLoopDirective &D)> SizeEmitter)
Emit the target offloading code associated with D.
virtual bool hasAllocateAttributeForGlobalVar(const VarDecl *VD, LangAS &AS)
Checks if the variable has associated OMPAllocateDeclAttr attribute with the predefined allocator and...
llvm::AtomicOrdering RequiresAtomicOrdering
Atomic ordering from the omp requires directive.
virtual void emitReduction(CodeGenFunction &CGF, SourceLocation Loc, ArrayRef< const Expr * > Privates, ArrayRef< const Expr * > LHSExprs, ArrayRef< const Expr * > RHSExprs, ArrayRef< const Expr * > ReductionOps, ReductionOptionsTy Options)
Emit a code for reduction clause.
std::pair< llvm::Value *, Address > emitDependClause(CodeGenFunction &CGF, ArrayRef< OMPTaskDataTy::DependData > Dependencies, SourceLocation Loc)
Emits list of dependecies based on the provided data (array of dependence/expression pairs).
llvm::StringMap< llvm::WeakTrackingVH > EmittedNonTargetVariables
List of the global variables with their addresses that should not be emitted for the target.
virtual bool isDynamic(OpenMPScheduleClauseKind ScheduleKind) const
Check if the specified ScheduleKind is dynamic.
Address emitLastprivateConditionalInit(CodeGenFunction &CGF, const VarDecl *VD)
Create specialized alloca to handle lastprivate conditionals.
virtual void emitOrderedRegion(CodeGenFunction &CGF, const RegionCodeGenTy &OrderedOpGen, SourceLocation Loc, bool IsThreads)
Emit an ordered region.
virtual Address getAddressOfLocalVariable(CodeGenFunction &CGF, const VarDecl *VD)
Gets the OpenMP-specific address of the local variable.
virtual void emitTaskReductionFini(CodeGenFunction &CGF, SourceLocation Loc, bool IsWorksharingReduction)
Emits the following code for reduction clause with task modifier:
virtual void emitMaskedRegion(CodeGenFunction &CGF, const RegionCodeGenTy &MaskedOpGen, SourceLocation Loc, const Expr *Filter=nullptr)
Emits a masked region.
QualType KmpDependInfoTy
Type typedef struct kmp_depend_info { kmp_intptr_t base_addr; size_t len; struct { bool in:1; bool ou...
llvm::Function * emitReductionFunction(StringRef ReducerName, SourceLocation Loc, llvm::Type *ArgsElemType, ArrayRef< const Expr * > Privates, ArrayRef< const Expr * > LHSExprs, ArrayRef< const Expr * > RHSExprs, ArrayRef< const Expr * > ReductionOps)
Emits reduction function.
virtual void emitForDispatchInit(CodeGenFunction &CGF, SourceLocation Loc, const OpenMPScheduleTy &ScheduleKind, unsigned IVSize, bool IVSigned, bool Ordered, const DispatchRTInput &DispatchValues)
Call the appropriate runtime routine to initialize it before start of loop.
Address getTaskReductionItem(CodeGenFunction &CGF, SourceLocation Loc, llvm::Value *ReductionsPtr, LValue SharedLVal) override
Get the address of void * type of the privatue copy of the reduction item specified by the SharedLVal...
void emitCriticalRegion(CodeGenFunction &CGF, StringRef CriticalName, const RegionCodeGenTy &CriticalOpGen, SourceLocation Loc, const Expr *Hint=nullptr) override
Emits a critical region.
void emitDistributeStaticInit(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDistScheduleClauseKind SchedKind, const StaticRTInput &Values) override
void emitForStaticInit(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind DKind, const OpenMPScheduleTy &ScheduleKind, const StaticRTInput &Values) override
Call the appropriate runtime routine to initialize it before start of loop.
bool emitTargetGlobalVariable(GlobalDecl GD) override
Emit the global variable if it is a valid device global variable.
llvm::Value * emitForNext(CodeGenFunction &CGF, SourceLocation Loc, unsigned IVSize, bool IVSigned, Address IL, Address LB, Address UB, Address ST) override
Call __kmpc_dispatch_next( ident_t *loc, kmp_int32 tid, kmp_int32 *p_lastiter, kmp_int[32|64] *p_lowe...
llvm::Function * emitThreadPrivateVarDefinition(const VarDecl *VD, Address VDAddr, SourceLocation Loc, bool PerformInit, CodeGenFunction *CGF=nullptr) override
Emit a code for initialization of threadprivate variable.
void emitTargetDataStandAloneCall(CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, const Expr *Device) override
Emit the data mapping/movement code associated with the directive D that should be of the form 'targe...
llvm::Function * emitTeamsOutlinedFunction(CodeGenFunction &CGF, const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) override
Emits outlined function for the specified OpenMP teams directive D.
void emitParallelCall(CodeGenFunction &CGF, SourceLocation Loc, llvm::Function *OutlinedFn, ArrayRef< llvm::Value * > CapturedVars, const Expr *IfCond, llvm::Value *NumThreads, OpenMPNumThreadsClauseModifier NumThreadsModifier=OMPC_NUMTHREADS_unknown, OpenMPSeverityClauseKind Severity=OMPC_SEVERITY_fatal, const Expr *Message=nullptr) override
Emits code for parallel or serial call of the OutlinedFn with variables captured in a record which ad...
void emitReduction(CodeGenFunction &CGF, SourceLocation Loc, ArrayRef< const Expr * > Privates, ArrayRef< const Expr * > LHSExprs, ArrayRef< const Expr * > RHSExprs, ArrayRef< const Expr * > ReductionOps, ReductionOptionsTy Options) override
Emit a code for reduction clause.
void emitFlush(CodeGenFunction &CGF, ArrayRef< const Expr * > Vars, SourceLocation Loc, llvm::AtomicOrdering AO) override
Emit flush of the variables specified in 'omp flush' directive.
void emitDoacrossOrdered(CodeGenFunction &CGF, const OMPDependClause *C) override
Emit code for doacross ordered directive with 'depend' clause.
void emitTaskyieldCall(CodeGenFunction &CGF, SourceLocation Loc) override
Emits a masked region.
Address getAddrOfArtificialThreadPrivate(CodeGenFunction &CGF, QualType VarType, StringRef Name) override
Creates artificial threadprivate variable with name Name and type VarType.
Address getAddrOfThreadPrivate(CodeGenFunction &CGF, const VarDecl *VD, Address VDAddr, SourceLocation Loc) override
Returns address of the threadprivate variable for the current thread.
void emitSingleRegion(CodeGenFunction &CGF, const RegionCodeGenTy &SingleOpGen, SourceLocation Loc, ArrayRef< const Expr * > CopyprivateVars, ArrayRef< const Expr * > DestExprs, ArrayRef< const Expr * > SrcExprs, ArrayRef< const Expr * > AssignmentOps) override
Emits a single region.
void emitTaskReductionFixups(CodeGenFunction &CGF, SourceLocation Loc, ReductionCodeGen &RCG, unsigned N) override
Required to resolve existing problems in the runtime.
llvm::Function * emitParallelOutlinedFunction(CodeGenFunction &CGF, const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) override
Emits outlined function for the specified OpenMP parallel directive D.
void emitCancellationPointCall(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind CancelRegion) override
Emit code for 'cancellation point' construct.
void emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind Kind, bool EmitChecks=true, bool ForceSimpleCall=false) override
Emit an implicit/explicit barrier for OpenMP threads.
Address getParameterAddress(CodeGenFunction &CGF, const VarDecl *NativeParam, const VarDecl *TargetParam) const override
Gets the address of the native argument basing on the address of the target-specific parameter.
void emitTeamsCall(CodeGenFunction &CGF, const OMPExecutableDirective &D, SourceLocation Loc, llvm::Function *OutlinedFn, ArrayRef< llvm::Value * > CapturedVars) override
Emits code for teams call of the OutlinedFn with variables captured in a record which address is stor...
void emitForOrderedIterationEnd(CodeGenFunction &CGF, SourceLocation Loc, unsigned IVSize, bool IVSigned) override
Call the appropriate runtime routine to notify that we finished iteration of the ordered loop with th...
bool emitTargetGlobal(GlobalDecl GD) override
Emit the global GD if it is meaningful for the target.
void emitTaskReductionFini(CodeGenFunction &CGF, SourceLocation Loc, bool IsWorksharingReduction) override
Emits the following code for reduction clause with task modifier:
void emitOrderedRegion(CodeGenFunction &CGF, const RegionCodeGenTy &OrderedOpGen, SourceLocation Loc, bool IsThreads) override
Emit an ordered region.
void emitForStaticFinish(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind DKind) override
Call the appropriate runtime routine to notify that we finished all the work with current loop.
llvm::Value * emitTaskReductionInit(CodeGenFunction &CGF, SourceLocation Loc, ArrayRef< const Expr * > LHSExprs, ArrayRef< const Expr * > RHSExprs, const OMPTaskDataTy &Data) override
Emit a code for initialization of task reduction clause.
void emitProcBindClause(CodeGenFunction &CGF, llvm::omp::ProcBindKind ProcBind, SourceLocation Loc) override
Emit call to void __kmpc_push_proc_bind(ident_t *loc, kmp_int32global_tid, int proc_bind) to generate...
void emitTargetOutlinedFunction(const OMPExecutableDirective &D, StringRef ParentName, llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID, bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) override
Emit outilined function for 'target' directive.
void emitMasterRegion(CodeGenFunction &CGF, const RegionCodeGenTy &MasterOpGen, SourceLocation Loc) override
Emits a master region.
void emitNumTeamsClause(CodeGenFunction &CGF, const Expr *NumTeams, const Expr *ThreadLimit, SourceLocation Loc) override
Emits call to void __kmpc_push_num_teams(ident_t *loc, kmp_int32global_tid, kmp_int32 num_teams,...
void emitForDispatchDeinit(CodeGenFunction &CGF, SourceLocation Loc) override
This is used for non static scheduled types and when the ordered clause is present on the loop constr...
const VarDecl * translateParameter(const FieldDecl *FD, const VarDecl *NativeParam) const override
Translates the native parameter of outlined function if this is required for target.
void emitNumThreadsClause(CodeGenFunction &CGF, llvm::Value *NumThreads, SourceLocation Loc, OpenMPNumThreadsClauseModifier Modifier=OMPC_NUMTHREADS_unknown, OpenMPSeverityClauseKind Severity=OMPC_SEVERITY_fatal, SourceLocation SeverityLoc=SourceLocation(), const Expr *Message=nullptr, SourceLocation MessageLoc=SourceLocation()) override
Emits call to void __kmpc_push_num_threads(ident_t *loc, kmp_int32global_tid, kmp_int32 num_threads) ...
void emitMaskedRegion(CodeGenFunction &CGF, const RegionCodeGenTy &MaskedOpGen, SourceLocation Loc, const Expr *Filter=nullptr) override
Emits a masked region.
void emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc, const OMPExecutableDirective &D, llvm::Function *TaskFunction, QualType SharedsTy, Address Shareds, const Expr *IfCond, const OMPTaskDataTy &Data) override
Emit task region for the task directive.
void emitTargetCall(CodeGenFunction &CGF, const OMPExecutableDirective &D, llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID, const Expr *IfCond, llvm::PointerIntPair< const Expr *, 2, OpenMPDeviceClauseModifier > Device, llvm::function_ref< llvm::Value *(CodeGenFunction &CGF, const OMPLoopDirective &D)> SizeEmitter) override
Emit the target offloading code associated with D.
bool emitTargetFunctions(GlobalDecl GD) override
Emit the target regions enclosed in GD function definition or the function itself in case it is a val...
void emitDoacrossInit(CodeGenFunction &CGF, const OMPLoopDirective &D, ArrayRef< Expr * > NumIterations) override
Emit initialization for doacross loop nesting support.
void emitCancelCall(CodeGenFunction &CGF, SourceLocation Loc, const Expr *IfCond, OpenMPDirectiveKind CancelRegion) override
Emit code for 'cancel' construct.
void emitTaskwaitCall(CodeGenFunction &CGF, SourceLocation Loc, const OMPTaskDataTy &Data) override
Emit code for 'taskwait' directive.
void emitTaskgroupRegion(CodeGenFunction &CGF, const RegionCodeGenTy &TaskgroupOpGen, SourceLocation Loc) override
Emit a taskgroup region.
void emitTargetDataCalls(CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, const Expr *Device, const RegionCodeGenTy &CodeGen, CGOpenMPRuntime::TargetDataInfo &Info) override
Emit the target data mapping code associated with D.
void emitForDispatchInit(CodeGenFunction &CGF, SourceLocation Loc, const OpenMPScheduleTy &ScheduleKind, unsigned IVSize, bool IVSigned, bool Ordered, const DispatchRTInput &DispatchValues) override
This is used for non static scheduled types and when the ordered clause is present on the loop constr...
llvm::Function * emitTaskOutlinedFunction(const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, const VarDecl *PartIDVar, const VarDecl *TaskTVar, OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen, bool Tied, unsigned &NumberOfParts) override
Emits outlined function for the OpenMP task directive D.
void emitTaskLoopCall(CodeGenFunction &CGF, SourceLocation Loc, const OMPLoopDirective &D, llvm::Function *TaskFunction, QualType SharedsTy, Address Shareds, const Expr *IfCond, const OMPTaskDataTy &Data) override
Emit task region for the taskloop directive.
unsigned getNonVirtualBaseLLVMFieldNo(const CXXRecordDecl *RD) const
llvm::StructType * getLLVMType() const
Return the "complete object" LLVM type associated with this record.
llvm::StructType * getBaseSubobjectLLVMType() const
Return the "base subobject" LLVM type associated with this record.
unsigned getLLVMFieldNo(const FieldDecl *FD) const
Return llvm::StructType element number that corresponds to the field FD.
unsigned getVirtualBaseIndex(const CXXRecordDecl *base) const
Return the LLVM field index corresponding to the given virtual base.
API for captured statement code generation.
virtual void EmitBody(CodeGenFunction &CGF, const Stmt *S)
Emit the captured statement body.
virtual const FieldDecl * lookup(const VarDecl *VD) const
Lookup the captured field decl for a variable.
RAII for correct setting/restoring of CapturedStmtInfo.
The scope used to remap some variables as private in the OpenMP loop body (or other captured region e...
bool Privatize()
Privatizes local variables previously registered as private.
bool addPrivate(const VarDecl *LocalVD, Address Addr)
Registers LocalVD variable as a private with Addr as the address of the corresponding private variabl...
An RAII object to set (and then clear) a mapping for an OpaqueValueExpr.
Enters a new scope for capturing cleanups, all of which will be executed once the scope is exited.
CodeGenFunction - This class organizes the per-function state that is used while generating LLVM code...
LValue EmitLoadOfReferenceLValue(LValue RefLVal)
void EmitBranchOnBoolExpr(const Expr *Cond, llvm::BasicBlock *TrueBlock, llvm::BasicBlock *FalseBlock, uint64_t TrueCount, Stmt::Likelihood LH=Stmt::LH_None, const Expr *ConditionalOp=nullptr, const VarDecl *ConditionalDecl=nullptr)
EmitBranchOnBoolExpr - Emit a branch on a boolean condition (e.g.
void emitDestroy(Address addr, QualType type, Destroyer *destroyer, bool useEHCleanupForArray)
emitDestroy - Immediately perform the destruction of the given object.
JumpDest getJumpDestInCurrentScope(llvm::BasicBlock *Target)
The given basic block lies in the current EH scope, but may be a target of a potentially scope-crossi...
static void EmitOMPTargetParallelDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetParallelDirective &S)
void EmitNullInitialization(Address DestPtr, QualType Ty)
EmitNullInitialization - Generate code to set a value of the given type to null, If the type contains...
Address LoadCXXThisAddress()
CGCapturedStmtInfo * CapturedStmtInfo
ComplexPairTy EmitLoadOfComplex(LValue src, SourceLocation loc)
EmitLoadOfComplex - Load a complex number from the specified l-value.
static void EmitOMPTargetDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetDirective &S)
Emit device code for the target directive.
static void EmitOMPTargetTeamsDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsDirective &S)
Emit device code for the target teams directive.
static void EmitOMPTargetTeamsDistributeDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsDistributeDirective &S)
Emit device code for the target teams distribute directive.
llvm::Function * GenerateOpenMPCapturedStmtFunctionAggregate(const CapturedStmt &S, const OMPExecutableDirective &D)
llvm::BasicBlock * createBasicBlock(const Twine &name="", llvm::Function *parent=nullptr, llvm::BasicBlock *before=nullptr)
createBasicBlock - Create an LLVM basic block.
const LangOptions & getLangOpts() const
AutoVarEmission EmitAutoVarAlloca(const VarDecl &var)
EmitAutoVarAlloca - Emit the alloca and debug information for a local variable.
void pushDestroy(QualType::DestructionKind dtorKind, Address addr, QualType type)
pushDestroy - Push the standard destructor for the given type as at least a normal cleanup.
Address EmitLoadOfPointer(Address Ptr, const PointerType *PtrTy, LValueBaseInfo *BaseInfo=nullptr, TBAAAccessInfo *TBAAInfo=nullptr)
Load a pointer with type PtrTy stored at address Ptr.
void EmitBranchThroughCleanup(JumpDest Dest)
EmitBranchThroughCleanup - Emit a branch from the current insert block through the normal cleanup han...
const Decl * CurCodeDecl
CurCodeDecl - This is the inner-most code context, which includes blocks.
Destroyer * getDestroyer(QualType::DestructionKind destructionKind)
llvm::AssertingVH< llvm::Instruction > AllocaInsertPt
AllocaInsertPoint - This is an instruction in the entry block before which we prefer to insert alloca...
void EmitAggregateAssign(LValue Dest, LValue Src, QualType EltTy)
Emit an aggregate assignment.
JumpDest ReturnBlock
ReturnBlock - Unified return block.
void EmitAggregateCopy(LValue Dest, LValue Src, QualType EltTy, AggValueSlot::Overlap_t MayOverlap, bool isVolatile=false)
EmitAggregateCopy - Emit an aggregate copy.
LValue EmitLValueForField(LValue Base, const FieldDecl *Field, bool IsInBounds=true)
RawAddress CreateDefaultAlignTempAlloca(llvm::Type *Ty, const Twine &Name="tmp")
CreateDefaultAlignedTempAlloca - This creates an alloca with the default ABI alignment of the given L...
void GenerateOpenMPCapturedVars(const CapturedStmt &S, SmallVectorImpl< llvm::Value * > &CapturedVars)
void EmitIgnoredExpr(const Expr *E)
EmitIgnoredExpr - Emit an expression in a context which ignores the result.
RValue EmitLoadOfLValue(LValue V, SourceLocation Loc)
EmitLoadOfLValue - Given an expression that represents a value lvalue, this method emits the address ...
LValue EmitArraySectionExpr(const ArraySectionExpr *E, bool IsLowerBound=true)
LValue EmitOMPSharedLValue(const Expr *E)
Emits the lvalue for the expression with possibly captured variable.
void StartFunction(GlobalDecl GD, QualType RetTy, llvm::Function *Fn, const CGFunctionInfo &FnInfo, const FunctionArgList &Args, SourceLocation Loc=SourceLocation(), SourceLocation StartLoc=SourceLocation())
Emit code for the start of a function.
void EmitOMPCopy(QualType OriginalType, Address DestAddr, Address SrcAddr, const VarDecl *DestVD, const VarDecl *SrcVD, const Expr *Copy)
Emit proper copying of data from one variable to another.
llvm::Value * EvaluateExprAsBool(const Expr *E)
EvaluateExprAsBool - Perform the usual unary conversions on the specified expression and compare the ...
JumpDest getOMPCancelDestination(OpenMPDirectiveKind Kind)
llvm::Value * emitArrayLength(const ArrayType *arrayType, QualType &baseType, Address &addr)
emitArrayLength - Compute the length of an array, even if it's a VLA, and drill down to the base elem...
void EmitOMPAggregateAssign(Address DestAddr, Address SrcAddr, QualType OriginalType, const llvm::function_ref< void(Address, Address)> CopyGen)
Perform element by element copying of arrays with type OriginalType from SrcAddr to DestAddr using co...
bool HaveInsertPoint() const
HaveInsertPoint - True if an insertion point is defined.
CGDebugInfo * getDebugInfo()
llvm::Value * getTypeSize(QualType Ty)
Returns calculated size of the specified type.
LValue MakeRawAddrLValue(llvm::Value *V, QualType T, CharUnits Alignment, AlignmentSource Source=AlignmentSource::Type)
Same as MakeAddrLValue above except that the pointer is known to be unsigned.
LValue EmitLValueForFieldInitialization(LValue Base, const FieldDecl *Field)
EmitLValueForFieldInitialization - Like EmitLValueForField, except that if the Field is a reference,...
RawAddress CreateMemTempWithoutCast(QualType T, const Twine &Name="tmp")
CreateMemTemp - Create a temporary memory object of the given type, with appropriate alignmen without...
VlaSizePair getVLASize(const VariableArrayType *vla)
Returns an LLVM value that corresponds to the size, in non-variably-sized elements,...
llvm::CallInst * EmitNounwindRuntimeCall(llvm::FunctionCallee callee, const Twine &name="")
ASTContext & getContext() const
llvm::Value * EmitLoadOfScalar(Address Addr, bool Volatile, QualType Ty, SourceLocation Loc, AlignmentSource Source=AlignmentSource::Type, bool isNontemporal=false)
EmitLoadOfScalar - Load a scalar value from an address, taking care to appropriately convert from the...
void EmitStoreOfComplex(ComplexPairTy V, LValue dest, bool isInit)
EmitStoreOfComplex - Store a complex number into the specified l-value.
const Decl * CurFuncDecl
CurFuncDecl - Holds the Decl for the current outermost non-closure context.
void EmitAutoVarCleanups(const AutoVarEmission &emission)
void EmitStoreThroughLValue(RValue Src, LValue Dst, bool isInit=false)
EmitStoreThroughLValue - Store the specified rvalue into the specified lvalue, where both are guarant...
LValue EmitLoadOfPointerLValue(Address Ptr, const PointerType *PtrTy)
void EmitAnyExprToMem(const Expr *E, Address Location, Qualifiers Quals, bool IsInitializer)
EmitAnyExprToMem - Emits the code necessary to evaluate an arbitrary expression into the given memory...
bool needsEHCleanup(QualType::DestructionKind kind)
Determines whether an EH cleanup is required to destroy a type with the given destruction kind.
llvm::DenseMap< const ValueDecl *, FieldDecl * > LambdaCaptureFields
llvm::CallInst * EmitRuntimeCall(llvm::FunctionCallee callee, const Twine &name="")
llvm::Type * ConvertTypeForMem(QualType T)
static void EmitOMPTargetTeamsDistributeParallelForDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsDistributeParallelForDirective &S)
static void EmitOMPTargetParallelForSimdDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetParallelForSimdDirective &S)
Emit device code for the target parallel for simd directive.
CodeGenTypes & getTypes() const
static TypeEvaluationKind getEvaluationKind(QualType T)
getEvaluationKind - Return the TypeEvaluationKind of QualType T.
void EmitOMPTargetTaskBasedDirective(const OMPExecutableDirective &S, const RegionCodeGenTy &BodyGen, OMPTargetDataInfo &InputInfo)
Address EmitPointerWithAlignment(const Expr *Addr, LValueBaseInfo *BaseInfo=nullptr, TBAAAccessInfo *TBAAInfo=nullptr, KnownNonNull_t IsKnownNonNull=NotKnownNonNull)
EmitPointerWithAlignment - Given an expression with a pointer type, emit the value and compute our be...
static void EmitOMPTargetTeamsDistributeParallelForSimdDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsDistributeParallelForSimdDirective &S)
Emit device code for the target teams distribute parallel for simd directive.
void EmitBranch(llvm::BasicBlock *Block)
EmitBranch - Emit a branch to the specified basic block from the current insert block,...
llvm::Function * GenerateOpenMPCapturedStmtFunction(const CapturedStmt &S, const OMPExecutableDirective &D)
RawAddress CreateMemTemp(QualType T, const Twine &Name="tmp", RawAddress *Alloca=nullptr)
CreateMemTemp - Create a temporary memory object of the given type, with appropriate alignmen and cas...
void EmitVarDecl(const VarDecl &D)
EmitVarDecl - Emit a local variable declaration.
llvm::Value * EmitCheckedInBoundsGEP(llvm::Type *ElemTy, llvm::Value *Ptr, ArrayRef< llvm::Value * > IdxList, bool SignedIndices, bool IsSubtraction, SourceLocation Loc, const Twine &Name="")
Same as IRBuilder::CreateInBoundsGEP, but additionally emits a check to detect undefined behavior whe...
static void EmitOMPTargetParallelGenericLoopDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetParallelGenericLoopDirective &S)
Emit device code for the target parallel loop directive.
llvm::Value * EmitScalarExpr(const Expr *E, bool IgnoreResultAssign=false)
EmitScalarExpr - Emit the computation of the specified expression of LLVM scalar type,...
static bool IsWrappedCXXThis(const Expr *E)
Check if E is a C++ "this" pointer wrapped in value-preserving casts.
LValue MakeAddrLValue(Address Addr, QualType T, AlignmentSource Source=AlignmentSource::Type)
void FinishFunction(SourceLocation EndLoc=SourceLocation())
FinishFunction - Complete IR generation of the current function.
void EmitAtomicStore(RValue rvalue, LValue lvalue, bool isInit)
static void EmitOMPTargetSimdDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetSimdDirective &S)
Emit device code for the target simd directive.
static void EmitOMPTargetParallelForDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetParallelForDirective &S)
Emit device code for the target parallel for directive.
Address GetAddrOfLocalVar(const VarDecl *VD)
GetAddrOfLocalVar - Return the address of a local variable.
bool ConstantFoldsToSimpleInteger(const Expr *Cond, bool &Result, bool AllowLabels=false)
ConstantFoldsToSimpleInteger - If the specified expression does not fold to a constant,...
static void EmitOMPTargetTeamsGenericLoopDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsGenericLoopDirective &S)
Emit device code for the target teams loop directive.
LValue EmitMemberExpr(const MemberExpr *E)
std::pair< llvm::Value *, llvm::Value * > ComplexPairTy
Address ReturnValue
ReturnValue - The temporary alloca to hold the return value.
LValue EmitLValue(const Expr *E, KnownNonNull_t IsKnownNonNull=NotKnownNonNull)
EmitLValue - Emit code to compute a designator that specifies the location of the expression.
void incrementProfileCounter(const Stmt *S, llvm::Value *StepV=nullptr)
Increment the profiler's counter for the given statement by StepV.
static void EmitOMPTargetTeamsDistributeSimdDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsDistributeSimdDirective &S)
Emit device code for the target teams distribute simd directive.
llvm::Value * EmitScalarConversion(llvm::Value *Src, QualType SrcTy, QualType DstTy, SourceLocation Loc)
Emit a conversion from the specified type to the specified destination type, both of which are LLVM s...
void EmitVariablyModifiedType(QualType Ty)
EmitVLASize - Capture all the sizes for the VLA expressions in the given variably-modified type and s...
bool isTrivialInitializer(const Expr *Init)
Determine whether the given initializer is trivial in the sense that it requires no code to be genera...
void EmitStoreOfScalar(llvm::Value *Value, Address Addr, bool Volatile, QualType Ty, AlignmentSource Source=AlignmentSource::Type, bool isInit=false, bool isNontemporal=false)
EmitStoreOfScalar - Store a scalar value to an address, taking care to appropriately convert from the...
void EmitBlock(llvm::BasicBlock *BB, bool IsFinished=false)
EmitBlock - Emit the given block.
void EmitExprAsInit(const Expr *init, const ValueDecl *D, LValue lvalue, bool capturedByInit)
EmitExprAsInit - Emits the code necessary to initialize a location in memory with the given initializ...
LValue MakeNaturalAlignRawAddrLValue(llvm::Value *V, QualType T)
This class organizes the cross-function state that is used while generating LLVM code.
void SetInternalFunctionAttributes(GlobalDecl GD, llvm::Function *F, const CGFunctionInfo &FI)
Set the attributes on the LLVM function for the given decl and function info.
llvm::Module & getModule() const
const IntrusiveRefCntPtr< llvm::vfs::FileSystem > & getFileSystem() const
DiagnosticsEngine & getDiags() const
const LangOptions & getLangOpts() const
CharUnits getNaturalTypeAlignment(QualType T, LValueBaseInfo *BaseInfo=nullptr, TBAAAccessInfo *TBAAInfo=nullptr, bool forPointeeType=false)
CodeGenTypes & getTypes()
CGOpenMPRuntime & getOpenMPRuntime()
Return a reference to the configured OpenMP runtime.
TBAAAccessInfo getTBAAInfoForSubobject(LValue Base, QualType AccessType)
getTBAAInfoForSubobject - Get TBAA information for an access with a given base lvalue.
ASTContext & getContext() const
const CodeGenOptions & getCodeGenOpts() const
StringRef getMangledName(GlobalDecl GD)
std::optional< CharUnits > getOMPAllocateAlignment(const VarDecl *VD)
Return the alignment specified in an allocate directive, if present.
llvm::Constant * EmitNullConstant(QualType T)
Return the result of value-initializing the given type, i.e.
llvm::Type * ConvertType(QualType T)
ConvertType - Convert type T into a llvm::Type.
llvm::FunctionType * GetFunctionType(const CGFunctionInfo &Info)
GetFunctionType - Get the LLVM function type for.
const CGFunctionInfo & arrangeBuiltinFunctionDeclaration(QualType resultType, const FunctionArgList &args)
A builtin function is a freestanding function using the default C conventions.
const CGRecordLayout & getCGRecordLayout(const RecordDecl *)
getCGRecordLayout - Return record layout info for the given record decl.
llvm::GlobalVariable * GetAddrOfVTable(const CXXRecordDecl *RD)
GetAddrOfVTable - Get the address of the VTable for the given record decl.
A specialization of Address that requires the address to be an LLVM Constant.
static ConstantAddress invalid()
bool requiresLandingPad() const
void pushTerminate()
Push a terminate handler on the stack.
void popTerminate()
Pops a terminate handler off the stack.
FunctionArgList - Type for representing both the decl and type of parameters to a function.
LValue - This represents an lvalue references.
CharUnits getAlignment() const
llvm::Value * getPointer(CodeGenFunction &CGF) const
const Qualifiers & getQuals() const
Address getAddress() const
LValueBaseInfo getBaseInfo() const
TBAAAccessInfo getTBAAInfo() const
A basic class for pre|post-action for advanced codegen sequence for OpenMP region.
virtual void Enter(CodeGenFunction &CGF)
RValue - This trivial value class is used to represent the result of an expression that is evaluated.
static RValue get(llvm::Value *V)
static RValue getComplex(llvm::Value *V1, llvm::Value *V2)
llvm::Value * getScalarVal() const
getScalarVal() - Return the Value* of this scalar value.
An abstract representation of an aligned address.
llvm::Type * getElementType() const
Return the type of the values stored in this address.
llvm::Value * getPointer() const
static RawAddress invalid()
Class intended to support codegen of all kind of the reduction clauses.
LValue getSharedLValue(unsigned N) const
Returns LValue for the reduction item.
const Expr * getRefExpr(unsigned N) const
Returns the base declaration of the reduction item.
LValue getOrigLValue(unsigned N) const
Returns LValue for the original reduction item.
bool needCleanups(unsigned N)
Returns true if the private copy requires cleanups.
void emitAggregateType(CodeGenFunction &CGF, unsigned N)
Emits the code for the variable-modified type, if required.
const VarDecl * getBaseDecl(unsigned N) const
Returns the base declaration of the reduction item.
QualType getPrivateType(unsigned N) const
Return the type of the private item.
bool usesReductionInitializer(unsigned N) const
Returns true if the initialization of the reduction item uses initializer from declare reduction cons...
void emitSharedOrigLValue(CodeGenFunction &CGF, unsigned N)
Emits lvalue for the shared and original reduction item.
void emitInitialization(CodeGenFunction &CGF, unsigned N, Address PrivateAddr, Address SharedAddr, llvm::function_ref< bool(CodeGenFunction &)> DefaultInit)
Performs initialization of the private copy for the reduction item.
std::pair< llvm::Value *, llvm::Value * > getSizes(unsigned N) const
Returns the size of the reduction item (in chars and total number of elements in the item),...
ReductionCodeGen(ArrayRef< const Expr * > Shareds, ArrayRef< const Expr * > Origs, ArrayRef< const Expr * > Privates, ArrayRef< const Expr * > ReductionOps)
void emitCleanups(CodeGenFunction &CGF, unsigned N, Address PrivateAddr)
Emits cleanup code for the reduction item.
Address adjustPrivateAddress(CodeGenFunction &CGF, unsigned N, Address PrivateAddr)
Adjusts PrivatedAddr for using instead of the original variable address in normal operations.
Class provides a way to call simple version of codegen for OpenMP region, or an advanced with possibl...
void operator()(CodeGenFunction &CGF) const
void setAction(PrePostActionTy &Action) const
ConstStmtVisitor - This class implements a simple visitor for Stmt subclasses.
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
void addDecl(Decl *D)
Add the declaration D into this context.
A reference to a declared variable, function, enum, etc.
Decl - This represents one declaration (or definition), e.g.
ASTContext & getASTContext() const LLVM_READONLY
virtual Stmt * getBody() const
getBody - If this Decl represents a declaration for a body of code, such as a function or method defi...
llvm::iterator_range< specific_attr_iterator< T > > specific_attrs() const
SourceLocation getLocation() const
DeclContext * getDeclContext()
virtual Decl * getCanonicalDecl()
Retrieves the "canonical" declaration of the given declaration.
SourceLocation getBeginLoc() const LLVM_READONLY
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
This represents one expression.
bool isIntegerConstantExpr(const ASTContext &Ctx) const
Expr * IgnoreParenNoopCasts(const ASTContext &Ctx) LLVM_READONLY
Skip past any parentheses and casts which do not change the value (including ptr->int casts of the sa...
@ SE_AllowSideEffects
Allow any unmodeled side effect.
@ SE_AllowUndefinedBehavior
Allow UB that we can give a value, but not arbitrary unmodeled side effects.
Expr * IgnoreParenCasts() LLVM_READONLY
Skip past any parentheses and casts which might surround this expression until reaching a fixed point...
llvm::APSInt EvaluateKnownConstInt(const ASTContext &Ctx) const
EvaluateKnownConstInt - Call EvaluateAsRValue and return the folded integer.
Expr * IgnoreParenImpCasts() LLVM_READONLY
Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...
bool isEvaluatable(const ASTContext &Ctx, SideEffectsKind AllowSideEffects=SE_NoSideEffects) const
isEvaluatable - Call EvaluateAsRValue to see if this expression can be constant folded without side-e...
std::optional< llvm::APSInt > getIntegerConstantExpr(const ASTContext &Ctx) const
isIntegerConstantExpr - Return the value if this expression is a valid integer constant expression.
bool HasSideEffects(const ASTContext &Ctx, bool IncludePossibleEffects=true) const
HasSideEffects - This routine returns true for all those expressions which have any effect other than...
bool EvaluateAsBooleanCondition(bool &Result, const ASTContext &Ctx, bool InConstantContext=false) const
EvaluateAsBooleanCondition - Return true if this is a constant which we can fold and convert to a boo...
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
static bool isSameComparisonOperand(const Expr *E1, const Expr *E2)
Checks that the two Expr's will refer to the same value as a comparison operand.
bool hasNonTrivialCall(const ASTContext &Ctx) const
Determine whether this expression involves a call to any function that is not trivial.
Represents a member of a struct/union/class.
unsigned getFieldIndex() const
Returns the index of this field within its record, as appropriate for passing to ASTRecordLayout::get...
const RecordDecl * getParent() const
Returns the parent of this field declaration, which is the struct in which this field is defined.
static FieldDecl * Create(const ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, const IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, Expr *BW, bool Mutable, InClassInitStyle InitStyle)
Represents a function declaration or definition.
const ParmVarDecl * getParamDecl(unsigned i) const
QualType getReturnType() const
ArrayRef< ParmVarDecl * > parameters() const
FunctionDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
FunctionDecl * getMostRecentDecl()
Returns the most recent (re)declaration of this declaration.
unsigned getNumParams() const
Return the number of parameters this function must have based on its FunctionType.
FunctionDecl * getPreviousDecl()
Return the previous declaration of this declaration or NULL if this is the first declaration.
GlobalDecl - represents a global declaration.
const Decl * getDecl() const
static ImplicitParamDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation IdLoc, const IdentifierInfo *Id, QualType T, ImplicitParamKind ParamKind)
Create implicit parameter.
static IntegerLiteral * Create(const ASTContext &C, const llvm::APInt &V, QualType type, SourceLocation l)
Returns a new integer literal with value 'V' and type 'type'.
An lvalue reference type, per C++11 [dcl.ref].
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
ValueDecl * getMemberDecl() const
Retrieve the member declaration to which this expression refers.
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
bool isExternallyVisible() const
const Stmt * getPreInitStmt() const
Get pre-initialization statement for the clause.
This is a basic class for representing single OpenMP clause.
ArrayRef< OMPClause * > clauses() const
This represents 'pragma omp declare mapper ...' directive.
Expr * getMapperVarRef()
Get the variable declared in the mapper.
This represents 'pragma omp declare reduction ...' directive.
Expr * getInitializer()
Get initializer expression (if specified) of the declare reduction construct.
Expr * getInitPriv()
Get Priv variable of the initializer.
Expr * getCombinerOut()
Get Out variable of the combiner.
Expr * getCombinerIn()
Get In variable of the combiner.
Expr * getCombiner()
Get combiner expression of the declare reduction construct.
Expr * getInitOrig()
Get Orig variable of the initializer.
OMPDeclareReductionInitKind getInitializerKind() const
Get initializer kind.
This represents 'if' clause in the 'pragma omp ...' directive.
Expr * getCondition() const
Returns condition.
OMPIteratorHelperData & getHelper(unsigned I)
Fetches helper data for the specified iteration space.
unsigned numOfIterators() const
Returns number of iterator definitions.
This represents 'num_threads' clause in the 'pragma omp ...' directive.
This represents 'pragma omp requires...' directive.
clauselist_range clauselists()
This represents 'threadset' clause in the 'pragma omp task ...' directive.
OpaqueValueExpr - An expression referring to an opaque object of a fixed type and value class.
Represents a parameter to a function.
PointerType - C99 6.7.5.1 - Pointer Declarators.
Represents an unpacked "presumed" location which can be presented to the user.
unsigned getColumn() const
Return the presumed column number of this location.
const char * getFilename() const
Return the presumed filename of this location.
unsigned getLine() const
Return the presumed line number of this location.
A (possibly-)qualified type.
void addRestrict()
Add the restrict qualifier to this QualType.
QualType withRestrict() const
bool isNull() const
Return true if this QualType doesn't point to a type yet.
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
Qualifiers getQualifiers() const
Retrieve the set of qualifiers applied to this type.
QualType getNonReferenceType() const
If Type is a reference type (e.g., const int&), returns the type that the reference refers to ("const...
QualType getCanonicalType() const
DestructionKind isDestructedType() const
Returns a nonzero value if objects of this type require non-trivial work to clean up after.
Represents a struct/union/class.
field_iterator field_end() const
field_range fields() const
virtual void completeDefinition()
Note that the definition of this type is now complete.
field_iterator field_begin() const
Scope - A scope is a transient data structure that is used while parsing the program.
Encodes a location in the source.
static SourceLocation getFromRawEncoding(UIntTy Encoding)
Turn a raw encoding of a SourceLocation object into a real SourceLocation.
bool isValid() const
Return true if this is a valid SourceLocation object.
UIntTy getRawEncoding() const
When a SourceLocation itself cannot be used, this returns an (opaque) 32-bit integer encoding for it.
This class handles loading and caching of source files into memory.
PresumedLoc getPresumedLoc(SourceLocation Loc, bool UseLineDirectives=true) const
Returns the "presumed" location of a SourceLocation specifies.
Stmt - This represents one statement.
StmtClass getStmtClass() const
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Stmt * IgnoreContainers(bool IgnoreCaptured=false)
Skip no-op (attributed, compound) container stmts and skip captured stmt at the top,...
SourceLocation getBeginLoc() const LLVM_READONLY
void startDefinition()
Starts the definition of this tag declaration.
The base class of the type hierarchy.
const Type * getPointeeOrArrayElementType() const
If this is a pointer type, return the pointee type.
bool isSignedIntegerType() const
Return true if this is an integer type that is signed, according to C99 6.2.5p4 [char,...
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
RecordDecl * getAsRecordDecl() const
Retrieves the RecordDecl this type refers to.
bool isPointerType() const
CanQualType getCanonicalTypeUnqualified() const
bool isIntegerType() const
isIntegerType() does not include complex integers (a GCC extension).
const T * castAs() const
Member-template castAs<specific type>.
bool isReferenceType() const
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
bool isLValueReferenceType() const
bool isAggregateType() const
Determines whether the type is a C++ aggregate type or C aggregate or union type.
RecordDecl * castAsRecordDecl() const
QualType getCanonicalTypeInternal() const
const Type * getBaseElementTypeUnsafe() const
Get the base element type of this type, potentially discarding type qualifiers.
bool isVariablyModifiedType() const
Whether this type is a variably-modified type (C99 6.7.5).
const ArrayType * getAsArrayTypeUnsafe() const
A variant of getAs<> for array types which silently discards qualifiers from the outermost type.
bool isFloatingType() const
bool isUnsignedIntegerType() const
Return true if this is an integer type that is unsigned, according to C99 6.2.5p6 [which returns true...
bool isAnyPointerType() const
const T * getAs() const
Member-template getAs<specific type>'.
bool isRecordType() const
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Represents a variable declaration or definition.
VarDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
VarDecl * getDefinition(ASTContext &)
Get the real (not just tentative) definition for this declaration.
const Expr * getInit() const
bool hasExternalStorage() const
Returns true if a variable has extern or private_extern storage.
@ DeclarationOnly
This declaration is only a declaration.
DefinitionKind hasDefinition(ASTContext &) const
Check whether this variable is defined in this translation unit.
bool isLocalVarDeclOrParm() const
Similar to isLocalVarDecl but also includes parameters.
const Expr * getAnyInitializer() const
Get the initializer for this variable, no matter which declaration it is attached to.
Represents a C array with a specified size that is not an integer-constant-expression.
Expr * getSizeExpr() const
specific_attr_iterator - Iterates over a subrange of an AttrVec, only providing attributes that are o...
bool isEmptyRecordForLayout(const ASTContext &Context, QualType T)
isEmptyRecordForLayout - Return true iff a structure contains only empty base classes (per isEmptyRec...
@ Type
The l-value was considered opaque, so the alignment was determined from a type.
@ Decl
The l-value was an access to a declared entity or something equivalently strong, like the address of ...
bool isEmptyFieldForLayout(const ASTContext &Context, const FieldDecl *FD)
isEmptyFieldForLayout - Return true iff the field is "empty", that is, either a zero-width bit-field ...
ComparisonResult
Indicates the result of a tentative comparison.
@ Address
A pointer to a ValueDecl.
The JSON file list parser is used to communicate input to InstallAPI.
bool isOpenMPWorksharingDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a worksharing directive.
CanQual< Type > CanQualType
Represents a canonical, potentially-qualified type.
bool needsTaskBasedThreadLimit(OpenMPDirectiveKind DKind)
Checks if the specified target directive, combined or not, needs task based thread_limit.
@ Match
This is not an overload because the signature exactly matches an existing declaration.
@ Ctor_Complete
Complete object ctor.
Privates[]
This class represents the 'transparent' clause in the 'pragma omp task' directive.
bool isa(CodeGen::Address addr)
if(T->getSizeExpr()) TRY_TO(TraverseStmt(const_cast< Expr * >(T -> getSizeExpr())))
bool isOpenMPTargetDataManagementDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a target data offload directive.
static bool classof(const OMPClause *T)
@ Conditional
A conditional (?:) operator.
@ ICIS_NoInit
No in-class initializer.
bool isOpenMPDistributeDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a distribute directive.
@ LCK_ByRef
Capturing by reference.
LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE()
@ Private
'private' clause, allowed on 'parallel', 'serial', 'loop', 'parallel loop', and 'serial loop' constru...
@ Reduction
'reduction' clause, allowed on Parallel, Serial, Loop, and the combined constructs.
@ Present
'present' clause, allowed on Compute and Combined constructs, plus 'data' and 'declare'.
OpenMPScheduleClauseModifier
OpenMP modifiers for 'schedule' clause.
@ OMPC_SCHEDULE_MODIFIER_last
@ OMPC_SCHEDULE_MODIFIER_unknown
nullptr
This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...
bool isOpenMPParallelDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a parallel-kind directive.
OpenMPDistScheduleClauseKind
OpenMP attributes for 'dist_schedule' clause.
bool isOpenMPTaskingDirective(OpenMPDirectiveKind Kind)
Checks if the specified directive kind is one of tasking directives - task, taskloop,...
bool isOpenMPTargetExecutionDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a target code offload directive.
@ OMPC_DYN_GROUPPRIVATE_FALLBACK_unknown
@ Result
The result type of a method or function.
bool isOpenMPTeamsDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a teams-kind directive.
const FunctionProtoType * T
OpenMPDependClauseKind
OpenMP attributes for 'depend' clause.
@ Dtor_Complete
Complete object dtor.
@ Union
The "union" keyword.
bool isOpenMPTargetMapEnteringDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a map-entering target directive.
@ Type
The name was classified as a type.
bool isOpenMPLoopDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a directive with an associated loop construct.
OpenMPSeverityClauseKind
OpenMP attributes for 'severity' clause.
LangAS
Defines the address space values used by the address space qualifier of QualType.
llvm::omp::Directive OpenMPDirectiveKind
OpenMP directives.
bool isOpenMPSimdDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a simd directive.
@ VK_PRValue
A pr-value expression (in the C++11 taxonomy) produces a temporary value.
@ VK_LValue
An l-value expression is a reference to an object with independent storage.
for(const auto &A :T->param_types())
void getOpenMPCaptureRegions(llvm::SmallVectorImpl< OpenMPDirectiveKind > &CaptureRegions, OpenMPDirectiveKind DKind)
Return the captured regions of an OpenMP directive.
OpenMPNumThreadsClauseModifier
@ OMPC_ATOMIC_DEFAULT_MEM_ORDER_unknown
U cast(CodeGen::Address addr)
OpenMPMapModifierKind
OpenMP modifier kind for 'map' clause.
@ OMPC_MAP_MODIFIER_unknown
@ Other
Other implicit parameter.
OpenMPScheduleClauseKind
OpenMP attributes for 'schedule' clause.
bool isOpenMPTaskLoopDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a taskloop directive.
OpenMPThreadsetKind
OpenMP modifiers for 'threadset' clause.
OpenMPMapClauseKind
OpenMP mapping kind for 'map' clause.
Diagnostic wrappers for TextAPI types for error reporting.
__packed_splat4 __packed_splat2 __packed_splat8 __packed_splat4 int32_t
__packed_splat4 __packed_splat2 __packed_splat8 __packed_splat4 __packed_splat2 __packed_splat4 __packed_splat2 __packed_splat8 __packed_splat4 uint32_t
Data for list of allocators.
Expr * AllocatorTraits
Allocator traits.
Expr * Allocator
Allocator.
Maps the expression for the lastprivate variable to the global copy used to store new value because o...
llvm::SmallVector< bool, 8 > IsPrivateVarReduction
A jump destination is an abstract label, branching to which may require a jump out through normal cle...
llvm::BasicBlock * getBlock() const
unsigned NumberOfTargetItems
Address BasePointersArray
llvm::PointerType * VoidPtrTy
llvm::IntegerType * Int64Ty
llvm::IntegerType * Int8Ty
i8, i16, i32, and i64
llvm::CallingConv::ID getRuntimeCC() const
llvm::IntegerType * SizeTy
llvm::PointerType * VoidPtrPtrTy
llvm::IntegerType * Int32Ty
llvm::IntegerType * IntPtrTy
llvm::IntegerType * IntTy
int
CharUnits getPointerAlign() const
OpenMPDependClauseKind DepKind
const Expr * IteratorExpr
SmallVector< const Expr *, 4 > DepExprs
EvalResult is a struct with detailed info about an evaluated expression.
Extra information about a function prototype.
Expr * CounterUpdate
Updater for the internal counter: ++CounterVD;.
Scheduling data for loop-based OpenMP directives.
bool UseFusedDistChunkSchedule
Request the fused distr_static_chunk + static_chunkone runtime schedule in for_static_init.
OpenMPScheduleClauseModifier M2
OpenMPScheduleClauseModifier M1
OpenMPScheduleClauseKind Schedule
Describes how types, statements, expressions, and declarations should be printed.