32#include "llvm/ADT/ArrayRef.h"
33#include "llvm/ADT/STLExtras.h"
34#include "llvm/ADT/SmallSet.h"
35#include "llvm/ADT/SmallVector.h"
36#include "llvm/ADT/StringExtras.h"
37#include "llvm/Analysis/ValueTracking.h"
38#include "llvm/Bitcode/BitcodeReader.h"
39#include "llvm/IR/Constants.h"
40#include "llvm/IR/DerivedTypes.h"
41#include "llvm/IR/GlobalValue.h"
42#include "llvm/IR/InstrTypes.h"
43#include "llvm/IR/Value.h"
44#include "llvm/Support/AtomicOrdering.h"
45#include "llvm/Support/VirtualFileSystem.h"
46#include "llvm/Support/raw_ostream.h"
54using namespace llvm::omp;
61 enum CGOpenMPRegionKind {
64 ParallelOutlinedRegion,
74 CGOpenMPRegionInfo(
const CapturedStmt &CS,
75 const CGOpenMPRegionKind RegionKind,
78 : CGCapturedStmtInfo(CS,
CR_OpenMP), RegionKind(RegionKind),
79 CodeGen(CodeGen), Kind(Kind), HasCancel(HasCancel) {}
81 CGOpenMPRegionInfo(
const CGOpenMPRegionKind RegionKind,
84 : CGCapturedStmtInfo(
CR_OpenMP), RegionKind(RegionKind), CodeGen(CodeGen),
85 Kind(Kind), HasCancel(HasCancel) {}
89 virtual const VarDecl *getThreadIDVariable()
const = 0;
92 void EmitBody(CodeGenFunction &CGF,
const Stmt *S)
override;
96 virtual LValue getThreadIDVariableLValue(CodeGenFunction &CGF);
98 virtual void emitUntiedSwitch(CodeGenFunction & ) {}
100 CGOpenMPRegionKind getRegionKind()
const {
return RegionKind; }
104 bool hasCancel()
const {
return HasCancel; }
106 static bool classof(
const CGCapturedStmtInfo *Info) {
110 ~CGOpenMPRegionInfo()
override =
default;
113 CGOpenMPRegionKind RegionKind;
114 RegionCodeGenTy CodeGen;
120class CGOpenMPOutlinedRegionInfo final :
public CGOpenMPRegionInfo {
122 CGOpenMPOutlinedRegionInfo(
const CapturedStmt &CS,
const VarDecl *ThreadIDVar,
123 const RegionCodeGenTy &CodeGen,
125 StringRef HelperName)
126 : CGOpenMPRegionInfo(CS, ParallelOutlinedRegion, CodeGen,
Kind,
128 ThreadIDVar(ThreadIDVar), HelperName(HelperName) {
129 assert(ThreadIDVar !=
nullptr &&
"No ThreadID in OpenMP region.");
134 const VarDecl *getThreadIDVariable()
const override {
return ThreadIDVar; }
137 StringRef getHelperName()
const override {
return HelperName; }
139 static bool classof(
const CGCapturedStmtInfo *Info) {
140 return CGOpenMPRegionInfo::classof(Info) &&
142 ParallelOutlinedRegion;
148 const VarDecl *ThreadIDVar;
149 StringRef HelperName;
153class CGOpenMPTaskOutlinedRegionInfo final :
public CGOpenMPRegionInfo {
155 class UntiedTaskActionTy final :
public PrePostActionTy {
157 const VarDecl *PartIDVar;
158 const RegionCodeGenTy UntiedCodeGen;
159 llvm::SwitchInst *UntiedSwitch =
nullptr;
162 UntiedTaskActionTy(
bool Tied,
const VarDecl *PartIDVar,
163 const RegionCodeGenTy &UntiedCodeGen)
164 : Untied(!Tied), PartIDVar(PartIDVar), UntiedCodeGen(UntiedCodeGen) {}
165 void Enter(CodeGenFunction &CGF)
override {
170 PartIDVar->
getType()->castAs<PointerType>());
174 UntiedSwitch = CGF.
Builder.CreateSwitch(Res, DoneBB);
178 UntiedSwitch->addCase(CGF.
Builder.getInt32(0),
180 emitUntiedSwitch(CGF);
183 void emitUntiedSwitch(CodeGenFunction &CGF)
const {
187 PartIDVar->
getType()->castAs<PointerType>());
191 CodeGenFunction::JumpDest CurPoint =
195 UntiedSwitch->addCase(CGF.
Builder.getInt32(UntiedSwitch->getNumCases()),
201 unsigned getNumberOfParts()
const {
return UntiedSwitch->getNumCases(); }
203 CGOpenMPTaskOutlinedRegionInfo(
const CapturedStmt &CS,
204 const VarDecl *ThreadIDVar,
205 const RegionCodeGenTy &CodeGen,
207 const UntiedTaskActionTy &Action)
208 : CGOpenMPRegionInfo(CS, TaskOutlinedRegion, CodeGen,
Kind, HasCancel),
209 ThreadIDVar(ThreadIDVar), Action(Action) {
210 assert(ThreadIDVar !=
nullptr &&
"No ThreadID in OpenMP region.");
215 const VarDecl *getThreadIDVariable()
const override {
return ThreadIDVar; }
218 LValue getThreadIDVariableLValue(CodeGenFunction &CGF)
override;
221 StringRef getHelperName()
const override {
return ".omp_outlined."; }
223 void emitUntiedSwitch(CodeGenFunction &CGF)
override {
224 Action.emitUntiedSwitch(CGF);
227 static bool classof(
const CGCapturedStmtInfo *Info) {
228 return CGOpenMPRegionInfo::classof(Info) &&
236 const VarDecl *ThreadIDVar;
238 const UntiedTaskActionTy &Action;
243class CGOpenMPInlinedRegionInfo :
public CGOpenMPRegionInfo {
245 CGOpenMPInlinedRegionInfo(CodeGenFunction::CGCapturedStmtInfo *OldCSI,
246 const RegionCodeGenTy &CodeGen,
248 : CGOpenMPRegionInfo(InlinedRegion, CodeGen,
Kind, HasCancel),
250 OuterRegionInfo(dyn_cast_or_null<CGOpenMPRegionInfo>(OldCSI)) {}
253 llvm::Value *getContextValue()
const override {
255 return OuterRegionInfo->getContextValue();
256 llvm_unreachable(
"No context value for inlined OpenMP region");
259 void setContextValue(llvm::Value *
V)
override {
260 if (OuterRegionInfo) {
261 OuterRegionInfo->setContextValue(
V);
264 llvm_unreachable(
"No context value for inlined OpenMP region");
268 const FieldDecl *lookup(
const VarDecl *VD)
const override {
270 return OuterRegionInfo->lookup(VD);
276 FieldDecl *getThisFieldDecl()
const override {
278 return OuterRegionInfo->getThisFieldDecl();
284 const VarDecl *getThreadIDVariable()
const override {
286 return OuterRegionInfo->getThreadIDVariable();
291 LValue getThreadIDVariableLValue(CodeGenFunction &CGF)
override {
293 return OuterRegionInfo->getThreadIDVariableLValue(CGF);
294 llvm_unreachable(
"No LValue for inlined OpenMP construct");
298 StringRef getHelperName()
const override {
299 if (
auto *OuterRegionInfo = getOldCSI())
300 return OuterRegionInfo->getHelperName();
301 llvm_unreachable(
"No helper name for inlined OpenMP construct");
304 void emitUntiedSwitch(CodeGenFunction &CGF)
override {
306 OuterRegionInfo->emitUntiedSwitch(CGF);
309 CodeGenFunction::CGCapturedStmtInfo *getOldCSI()
const {
return OldCSI; }
311 static bool classof(
const CGCapturedStmtInfo *Info) {
312 return CGOpenMPRegionInfo::classof(Info) &&
316 ~CGOpenMPInlinedRegionInfo()
override =
default;
320 CodeGenFunction::CGCapturedStmtInfo *OldCSI;
321 CGOpenMPRegionInfo *OuterRegionInfo;
329class CGOpenMPTargetRegionInfo final :
public CGOpenMPRegionInfo {
331 CGOpenMPTargetRegionInfo(
const CapturedStmt &CS,
332 const RegionCodeGenTy &CodeGen, StringRef HelperName)
333 : CGOpenMPRegionInfo(CS, TargetRegion, CodeGen, OMPD_target,
335 HelperName(HelperName) {}
339 const VarDecl *getThreadIDVariable()
const override {
return nullptr; }
342 StringRef getHelperName()
const override {
return HelperName; }
344 static bool classof(
const CGCapturedStmtInfo *Info) {
345 return CGOpenMPRegionInfo::classof(Info) &&
350 StringRef HelperName;
354 llvm_unreachable(
"No codegen for expressions");
358class CGOpenMPInnerExprInfo final :
public CGOpenMPInlinedRegionInfo {
360 CGOpenMPInnerExprInfo(CodeGenFunction &CGF,
const CapturedStmt &CS)
361 : CGOpenMPInlinedRegionInfo(CGF.CapturedStmtInfo, EmptyCodeGen,
369 if (!C.capturesVariable() && !C.capturesVariableByCopy())
372 const VarDecl *VD = C.getCapturedVar();
373 if (VD->isLocalVarDeclOrParm())
376 DeclRefExpr DRE(CGF.getContext(), const_cast<VarDecl *>(VD),
378 VD->getType().getNonReferenceType(), VK_LValue,
380 PrivScope.addPrivate(VD, CGF.EmitLValue(&DRE).getAddress());
382 (
void)PrivScope.Privatize();
386 const FieldDecl *lookup(
const VarDecl *VD)
const override {
387 if (
const FieldDecl *FD = CGOpenMPInlinedRegionInfo::lookup(VD))
393 void EmitBody(CodeGenFunction &CGF,
const Stmt *S)
override {
394 llvm_unreachable(
"No body for expressions");
399 const VarDecl *getThreadIDVariable()
const override {
400 llvm_unreachable(
"No thread id for expressions");
404 StringRef getHelperName()
const override {
405 llvm_unreachable(
"No helper name for expressions");
408 static bool classof(
const CGCapturedStmtInfo *Info) {
return false; }
412 CodeGenFunction::OMPPrivateScope PrivScope;
416class InlinedOpenMPRegionRAII {
417 CodeGenFunction &CGF;
418 llvm::DenseMap<const ValueDecl *, FieldDecl *> LambdaCaptureFields;
419 FieldDecl *LambdaThisCaptureField =
nullptr;
420 const CodeGen::CGBlockInfo *BlockInfo =
nullptr;
421 bool NoInheritance =
false;
428 InlinedOpenMPRegionRAII(CodeGenFunction &CGF,
const RegionCodeGenTy &CodeGen,
430 bool NoInheritance =
true)
431 : CGF(CGF), NoInheritance(NoInheritance) {
433 CGF.CapturedStmtInfo =
new CGOpenMPInlinedRegionInfo(
434 CGF.CapturedStmtInfo, CodeGen, Kind, HasCancel);
436 std::swap(CGF.LambdaCaptureFields, LambdaCaptureFields);
437 LambdaThisCaptureField = CGF.LambdaThisCaptureField;
438 CGF.LambdaThisCaptureField =
nullptr;
439 BlockInfo = CGF.BlockInfo;
440 CGF.BlockInfo =
nullptr;
444 ~InlinedOpenMPRegionRAII() {
448 delete CGF.CapturedStmtInfo;
449 CGF.CapturedStmtInfo = OldCSI;
451 std::swap(CGF.LambdaCaptureFields, LambdaCaptureFields);
452 CGF.LambdaThisCaptureField = LambdaThisCaptureField;
453 CGF.BlockInfo = BlockInfo;
461enum OpenMPLocationFlags :
unsigned {
463 OMP_IDENT_IMD = 0x01,
465 OMP_IDENT_KMPC = 0x02,
467 OMP_ATOMIC_REDUCE = 0x10,
469 OMP_IDENT_BARRIER_EXPL = 0x20,
471 OMP_IDENT_BARRIER_IMPL = 0x40,
473 OMP_IDENT_BARRIER_IMPL_FOR = 0x40,
475 OMP_IDENT_BARRIER_IMPL_SECTIONS = 0xC0,
477 OMP_IDENT_BARRIER_IMPL_SINGLE = 0x140,
479 OMP_IDENT_WORK_LOOP = 0x200,
481 OMP_IDENT_WORK_SECTIONS = 0x400,
483 OMP_IDENT_WORK_DISTRIBUTE = 0x800,
513enum IdentFieldIndex {
515 IdentField_Reserved_1,
519 IdentField_Reserved_2,
521 IdentField_Reserved_3,
530enum OpenMPSchedType {
533 OMP_sch_static_chunked = 33,
535 OMP_sch_dynamic_chunked = 35,
536 OMP_sch_guided_chunked = 36,
537 OMP_sch_runtime = 37,
540 OMP_sch_static_balanced_chunked = 45,
543 OMP_ord_static_chunked = 65,
545 OMP_ord_dynamic_chunked = 67,
546 OMP_ord_guided_chunked = 68,
547 OMP_ord_runtime = 69,
549 OMP_sch_default = OMP_sch_static,
551 OMP_dist_sch_static_chunked = 91,
552 OMP_dist_sch_static = 92,
558 OMP_dist_sch_static_chunked_sch_static_chunkone = 93,
561 OMP_sch_modifier_monotonic = (1 << 29),
563 OMP_sch_modifier_nonmonotonic = (1 << 30),
568class CleanupTy final :
public EHScopeStack::Cleanup {
569 PrePostActionTy *Action;
572 explicit CleanupTy(PrePostActionTy *Action) : Action(Action) {}
573 void Emit(CodeGenFunction &CGF, Flags )
override {
586 Callback(CodeGen, CGF, *PrePostAction);
597 if (
const auto *CE = dyn_cast<CallExpr>(ReductionOp))
598 if (
const auto *OVE = dyn_cast<OpaqueValueExpr>(CE->getCallee()))
599 if (
const auto *DRE =
600 dyn_cast<DeclRefExpr>(OVE->getSourceExpr()->IgnoreImpCasts()))
601 if (
const auto *DRD = dyn_cast<OMPDeclareReductionDecl>(DRE->getDecl()))
612 std::pair<llvm::Function *, llvm::Function *>
Reduction =
632 auto *GV =
new llvm::GlobalVariable(
634 llvm::GlobalValue::PrivateLinkage,
Init, Name);
675 llvm::Value *NumElements = CGF.
emitArrayLength(ArrayTy, ElementTy, DestAddr);
679 llvm::Value *SrcBegin =
nullptr;
681 SrcBegin = SrcAddr.emitRawPointer(CGF);
684 llvm::Value *DestEnd =
689 llvm::Value *IsEmpty =
690 CGF.
Builder.CreateICmpEQ(DestBegin, DestEnd,
"omp.arrayinit.isempty");
691 CGF.
Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
694 llvm::BasicBlock *EntryBB = CGF.
Builder.GetInsertBlock();
699 llvm::PHINode *SrcElementPHI =
nullptr;
702 SrcElementPHI = CGF.
Builder.CreatePHI(SrcBegin->getType(), 2,
703 "omp.arraycpy.srcElementPast");
704 SrcElementPHI->addIncoming(SrcBegin, EntryBB);
706 Address(SrcElementPHI, SrcAddr.getElementType(),
707 SrcAddr.getAlignment().alignmentOfArrayElement(ElementSize));
709 llvm::PHINode *DestElementPHI = CGF.
Builder.CreatePHI(
710 DestBegin->getType(), 2,
"omp.arraycpy.destElementPast");
711 DestElementPHI->addIncoming(DestBegin, EntryBB);
719 if (EmitDeclareReductionInit) {
721 SrcElementCurrent, ElementTy);
729 llvm::Value *SrcElementNext = CGF.
Builder.CreateConstGEP1_32(
730 SrcAddr.getElementType(), SrcElementPHI, 1,
731 "omp.arraycpy.dest.element");
732 SrcElementPHI->addIncoming(SrcElementNext, CGF.
Builder.GetInsertBlock());
736 llvm::Value *DestElementNext = CGF.
Builder.CreateConstGEP1_32(
738 "omp.arraycpy.dest.element");
741 CGF.
Builder.CreateICmpEQ(DestElementNext, DestEnd,
"omp.arraycpy.done");
742 CGF.
Builder.CreateCondBr(Done, DoneBB, BodyBB);
743 DestElementPHI->addIncoming(DestElementNext, CGF.
Builder.GetInsertBlock());
755 if (
const auto *OASE = dyn_cast<ArraySectionExpr>(E))
760void ReductionCodeGen::emitAggregateInitialization(
762 const OMPDeclareReductionDecl *DRD) {
766 const auto *PrivateVD =
768 bool EmitDeclareReductionInit =
771 EmitDeclareReductionInit,
772 EmitDeclareReductionInit ? ClausesData[N].ReductionOp
773 : PrivateVD->getInit(),
781 ClausesData.reserve(Shareds.size());
782 SharedAddresses.reserve(Shareds.size());
783 Sizes.reserve(Shareds.size());
784 BaseDecls.reserve(Shareds.size());
785 const auto *IOrig = Origs.begin();
786 const auto *IPriv =
Privates.begin();
787 const auto *IRed = ReductionOps.begin();
788 for (
const Expr *Ref : Shareds) {
789 ClausesData.emplace_back(Ref, *IOrig, *IPriv, *IRed);
790 std::advance(IOrig, 1);
791 std::advance(IPriv, 1);
792 std::advance(IRed, 1);
797 assert(SharedAddresses.size() == N && OrigAddresses.size() == N &&
798 "Number of generated lvalues must be exactly N.");
799 LValue First = emitSharedLValue(CGF, ClausesData[N].Shared);
800 LValue Second = emitSharedLValueUB(CGF, ClausesData[N].Shared);
801 SharedAddresses.emplace_back(
First, Second);
802 if (ClausesData[N].Shared == ClausesData[N].Ref) {
803 OrigAddresses.emplace_back(
First, Second);
805 LValue First = emitSharedLValue(CGF, ClausesData[N].Ref);
806 LValue Second = emitSharedLValueUB(CGF, ClausesData[N].Ref);
807 OrigAddresses.emplace_back(
First, Second);
816 CGF.
getTypeSize(OrigAddresses[N].first.getType().getNonReferenceType()),
821 llvm::Value *SizeInChars;
822 auto *ElemType = OrigAddresses[N].first.getAddress().getElementType();
823 auto *ElemSizeOf = llvm::ConstantInt::get(
825 if (AsArraySection) {
827 CGF.
Builder.CreatePtrDiff(OrigAddresses[N].second.getPointer(CGF),
828 OrigAddresses[N].first.getPointer(CGF));
829 SizeInChars = CGF.
Builder.CreateNUWAdd(SizeInChars, ElemSizeOf);
832 CGF.
getTypeSize(OrigAddresses[N].first.getType().getNonReferenceType());
834 Size = ElemSizeOf->isOne()
836 : CGF.
Builder.CreateExactUDiv(SizeInChars, ElemSizeOf);
837 Sizes.emplace_back(SizeInChars, Size);
850 assert(!Size && !Sizes[N].second &&
851 "Size should be nullptr for non-variably modified reduction "
866 assert(SharedAddresses.size() > N &&
"No variable was generated");
867 const auto *PrivateVD =
873 (void)DefaultInit(CGF);
874 emitAggregateInitialization(CGF, N, PrivateAddr, SharedAddr, DRD);
875 }
else if (DRD && (DRD->
getInitializer() || !PrivateVD->hasInit())) {
876 (void)DefaultInit(CGF);
877 QualType SharedType = SharedAddresses[N].first.getType();
879 PrivateAddr, SharedAddr, SharedType);
880 }
else if (!DefaultInit(CGF) && PrivateVD->hasInit() &&
883 PrivateVD->
getType().getQualifiers(),
901 CGF.
pushDestroy(DTorKind, PrivateAddr, PrivateType);
920 BaseLV.getType(), BaseLV.getBaseInfo(),
954 const VarDecl *OrigVD =
nullptr;
955 if (
const auto *OASE = dyn_cast<ArraySectionExpr>(Ref)) {
956 const Expr *
Base = OASE->getBase()->IgnoreParenImpCasts();
957 while (
const auto *TempOASE = dyn_cast<ArraySectionExpr>(
Base))
958 Base = TempOASE->getBase()->IgnoreParenImpCasts();
959 while (
const auto *TempASE = dyn_cast<ArraySubscriptExpr>(
Base))
960 Base = TempASE->getBase()->IgnoreParenImpCasts();
963 }
else if (
const auto *ASE = dyn_cast<ArraySubscriptExpr>(Ref)) {
964 const Expr *
Base = ASE->getBase()->IgnoreParenImpCasts();
965 while (
const auto *TempASE = dyn_cast<ArraySubscriptExpr>(
Base))
966 Base = TempASE->getBase()->IgnoreParenImpCasts();
977 BaseDecls.emplace_back(OrigVD);
980 loadToBegin(CGF, OrigVD->getType(), SharedAddresses[N].first.getType(),
982 Address SharedAddr = SharedAddresses[N].first.getAddress();
983 llvm::Value *Adjustment = CGF.
Builder.CreatePtrDiff(
986 llvm::Value *PrivatePointer =
992 SharedAddresses[N].first.getType(),
995 BaseDecls.emplace_back(
1009 getThreadIDVariable()->
getType()->castAs<PointerType>());
1027LValue CGOpenMPTaskOutlinedRegionInfo::getThreadIDVariableLValue(
1030 getThreadIDVariable()->
getType(),
1048 llvm::OpenMPIRBuilderConfig Config(
1049 CGM.getLangOpts().OpenMPIsTargetDevice,
isGPU(),
1050 CGM.getLangOpts().OpenMPOffloadMandatory,
1053 Config.setDefaultTargetAS(
1055 Config.setRuntimeCC(
CGM.getRuntimeCC());
1060 CGM.getLangOpts().OpenMPIsTargetDevice
1061 ?
CGM.getLangOpts().OMPHostIRFile
1066 if (
CGM.getLangOpts().OpenMPForceUSM) {
1068 OMPBuilder.Config.setHasRequiresUnifiedSharedMemory(
true);
1076 if (!
Data.getValue().pointsToAliveValue())
1078 auto *GV = dyn_cast<llvm::GlobalVariable>(
Data.getValue());
1081 if (!GV->isDeclaration() || GV->getNumUses() > 0)
1083 GV->eraseFromParent();
1088 return OMPBuilder.createPlatformSpecificName(Parts);
1091static llvm::Function *
1093 const Expr *CombinerInitializer,
const VarDecl *In,
1094 const VarDecl *Out,
bool IsCombiner) {
1097 QualType PtrTy =
C.getPointerType(Ty).withRestrict();
1099 C,
nullptr, Out->getLocation(),
1102 C,
nullptr, In->getLocation(),
1109 {IsCombiner ?
"omp_combiner" :
"omp_initializer",
""});
1110 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
1114 Fn->addFnAttr(
"sample-profile-suffix-elision-policy",
"selected");
1116 Fn->removeFnAttr(llvm::Attribute::NoInline);
1117 Fn->removeFnAttr(llvm::Attribute::OptimizeNone);
1118 Fn->addFnAttr(llvm::Attribute::AlwaysInline);
1124 Out->getLocation());
1134 (void)
Scope.Privatize();
1135 if (!IsCombiner && Out->hasInit() &&
1138 Out->getType().getQualifiers(),
1141 if (CombinerInitializer)
1143 Scope.ForceCleanup();
1172std::pair<llvm::Function *, llvm::Function *>
1184struct PushAndPopStackRAII {
1185 PushAndPopStackRAII(llvm::OpenMPIRBuilder *OMPBuilder,
CodeGenFunction &CGF,
1186 bool HasCancel, llvm::omp::Directive Kind)
1187 : OMPBuilder(OMPBuilder) {
1203 auto FiniCB = [&CGF](llvm::OpenMPIRBuilder::InsertPointTy IP) {
1204 assert(IP == IP.getNodeParent()->end() &&
1205 "Clang CG should cause non-terminated block!");
1206 CGBuilderTy::InsertPointGuard IPG(CGF.
Builder);
1211 return llvm::Error::success();
1216 llvm::OpenMPIRBuilder::FinalizationInfo FI({FiniCB, Kind, HasCancel});
1217 OMPBuilder->pushFinalizationCB(std::move(FI));
1219 ~PushAndPopStackRAII() {
1221 OMPBuilder->popFinalizationCB();
1223 llvm::OpenMPIRBuilder *OMPBuilder;
1232 "thread id variable must be of type kmp_int32 *");
1234 bool HasCancel =
false;
1235 if (
const auto *OPD = dyn_cast<OMPParallelDirective>(&D))
1236 HasCancel = OPD->hasCancel();
1237 else if (
const auto *OPD = dyn_cast<OMPTargetParallelDirective>(&D))
1238 HasCancel = OPD->hasCancel();
1239 else if (
const auto *OPSD = dyn_cast<OMPParallelSectionsDirective>(&D))
1240 HasCancel = OPSD->hasCancel();
1241 else if (
const auto *OPFD = dyn_cast<OMPParallelForDirective>(&D))
1242 HasCancel = OPFD->hasCancel();
1243 else if (
const auto *OPFD = dyn_cast<OMPTargetParallelForDirective>(&D))
1244 HasCancel = OPFD->hasCancel();
1245 else if (
const auto *OPFD = dyn_cast<OMPDistributeParallelForDirective>(&D))
1246 HasCancel = OPFD->hasCancel();
1247 else if (
const auto *OPFD =
1248 dyn_cast<OMPTeamsDistributeParallelForDirective>(&D))
1249 HasCancel = OPFD->hasCancel();
1250 else if (
const auto *OPFD =
1251 dyn_cast<OMPTargetTeamsDistributeParallelForDirective>(&D))
1252 HasCancel = OPFD->hasCancel();
1257 PushAndPopStackRAII PSR(&OMPBuilder, CGF, HasCancel, InnermostKind);
1258 CGOpenMPOutlinedRegionInfo CGInfo(*CS, ThreadIDVar,
CodeGen, InnermostKind,
1259 HasCancel, OutlinedHelperName);
1265 std::string Suffix =
getName({
"omp_outlined"});
1266 return (Name + Suffix).str();
1274 std::string Suffix =
getName({
"omp",
"reduction",
"reduction_func"});
1275 return (Name + Suffix).str();
1282 const CapturedStmt *CS = D.getCapturedStmt(OMPD_parallel);
1292 const CapturedStmt *CS = D.getCapturedStmt(OMPD_teams);
1299 OutlinedFn->setDoesNotRecurse();
1307 bool Tied,
unsigned &NumberOfParts) {
1310 llvm::Value *ThreadID =
getThreadID(CGF, D.getBeginLoc());
1312 llvm::Value *TaskArgs[] = {
1314 CGF.EmitLoadOfPointerLValue(CGF.GetAddrOfLocalVar(TaskTVar),
1317 CGF.EmitRuntimeCall(
OMPBuilder.getOrCreateRuntimeFunction(
1318 CGM.getModule(), OMPRTL___kmpc_omp_task),
1321 CGOpenMPTaskOutlinedRegionInfo::UntiedTaskActionTy Action(Tied, PartIDVar,
1325 "thread id variable must be of type kmp_int32 for tasks");
1330 bool HasCancel =
false;
1331 if (
const auto *TD = dyn_cast<OMPTaskDirective>(&D))
1332 HasCancel = TD->hasCancel();
1333 else if (
const auto *TD = dyn_cast<OMPTaskLoopDirective>(&D))
1334 HasCancel = TD->hasCancel();
1335 else if (
const auto *TD = dyn_cast<OMPMasterTaskLoopDirective>(&D))
1336 HasCancel = TD->hasCancel();
1337 else if (
const auto *TD = dyn_cast<OMPParallelMasterTaskLoopDirective>(&D))
1338 HasCancel = TD->hasCancel();
1341 CGOpenMPTaskOutlinedRegionInfo CGInfo(*CS, ThreadIDVar,
CodeGen,
1342 InnermostKind, HasCancel, Action);
1344 llvm::Function *Res = CGF.GenerateCapturedStmtFunction(*CS);
1346 NumberOfParts = Action.getNumberOfParts();
1351 bool AtCurrentPoint) {
1353 assert(!Elem.ServiceInsertPt &&
"Insert point is set already.");
1355 llvm::Value *Undef = llvm::UndefValue::get(CGF.
Int32Ty);
1356 if (AtCurrentPoint) {
1357 Elem.ServiceInsertPt =
new llvm::BitCastInst(Undef, CGF.
Int32Ty,
"svcpt",
1358 CGF.
Builder.GetInsertBlock());
1360 Elem.ServiceInsertPt =
new llvm::BitCastInst(Undef, CGF.
Int32Ty,
"svcpt");
1361 Elem.ServiceInsertPt->insertAfter(CGF.
AllocaInsertPt->getIterator());
1367 if (Elem.ServiceInsertPt) {
1368 llvm::Instruction *Ptr = Elem.ServiceInsertPt;
1369 Elem.ServiceInsertPt =
nullptr;
1370 Ptr->eraseFromParent();
1377 llvm::raw_svector_ostream OS(Buffer);
1386 if (
const auto *FD = dyn_cast_or_null<FunctionDecl>(CGF.
CurFuncDecl))
1387 OS << FD->getQualifiedNameAsString();
1394 unsigned Flags,
bool EmitLoc) {
1395 uint32_t SrcLocStrSize;
1396 llvm::Constant *SrcLocStr;
1397 if ((!EmitLoc &&
CGM.getCodeGenOpts().getDebugInfo() ==
1398 llvm::codegenoptions::NoDebugInfo) ||
1400 SrcLocStr =
OMPBuilder.getOrCreateDefaultSrcLocStr(SrcLocStrSize);
1402 std::string FunctionName;
1404 if (
const auto *FD = dyn_cast_or_null<FunctionDecl>(CGF.
CurFuncDecl))
1405 FunctionName = FD->getQualifiedNameAsString();
1418 SrcLocStr, SrcLocStrSize, llvm::omp::IdentFlag(Flags), Reserved2Flags);
1423 assert(CGF.
CurFn &&
"No function in current CodeGenFunction.");
1426 if (
CGM.getLangOpts().OpenMPIRBuilder) {
1429 uint32_t SrcLocStrSize;
1430 auto *SrcLocStr =
OMPBuilder.getOrCreateSrcLocStr(
1433 OMPBuilder.getOrCreateIdent(SrcLocStr, SrcLocStrSize));
1436 llvm::Value *ThreadID =
nullptr;
1441 ThreadID = I->second.ThreadID;
1442 if (ThreadID !=
nullptr)
1446 if (
auto *OMPRegionInfo =
1448 if (OMPRegionInfo->getThreadIDVariable()) {
1450 LValue LVal = OMPRegionInfo->getThreadIDVariableLValue(CGF);
1454 CGF.
Builder.GetInsertBlock() == TopBlock ||
1459 CGF.
Builder.GetInsertBlock()) {
1463 if (CGF.
Builder.GetInsertBlock() == TopBlock)
1475 if (!Elem.ServiceInsertPt)
1477 CGBuilderTy::InsertPointGuard IPG(CGF.
Builder);
1478 CGF.
Builder.SetInsertPoint(Elem.ServiceInsertPt);
1482 OMPRTL___kmpc_global_thread_num),
1485 Elem.ThreadID =
Call;
1490 assert(CGF.
CurFn &&
"No function in current CodeGenFunction.");
1496 for (
const auto *D : I->second)
1501 for (
const auto *D : I->second)
1513static llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseKind
1515 std::optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
1516 OMPDeclareTargetDeclAttr::getDeviceType(VD);
1518 return llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseNone;
1520 switch ((
int)*DevTy) {
1521 case OMPDeclareTargetDeclAttr::DT_Host:
1522 return llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseHost;
1524 case OMPDeclareTargetDeclAttr::DT_NoHost:
1525 return llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseNoHost;
1527 case OMPDeclareTargetDeclAttr::DT_Any:
1528 return llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseAny;
1531 return llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseNone;
1536static llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryKind
1538 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> MapType =
1539 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
1541 return llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryNone;
1542 switch ((
int)*MapType) {
1543 case OMPDeclareTargetDeclAttr::MapTypeTy::MT_To:
1544 return llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryTo;
1546 case OMPDeclareTargetDeclAttr::MapTypeTy::MT_Enter:
1547 return llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryEnter;
1548 case OMPDeclareTargetDeclAttr::MapTypeTy::MT_Link:
1549 return llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryLink;
1551 case OMPDeclareTargetDeclAttr::MapTypeTy::MT_Local:
1553 llvm_unreachable(
"MT_Local should not reach convertCaptureClause");
1556 return llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryNone;
1565 auto FileInfoCallBack = [&]() {
1575 return OMPBuilder.getTargetEntryUniqueInfo(FileInfoCallBack,
1580 auto AddrOfGlobal = [&VD,
this]() {
return CGM.GetAddrOfGlobal(VD); };
1582 auto LinkageForVariable = [&VD,
this]() {
1583 return CGM.getLLVMLinkageVarDefinition(VD);
1586 std::vector<llvm::GlobalVariable *> GeneratedRefs;
1588 llvm::Type *LlvmPtrTy =
CGM.getTypes().ConvertTypeForMem(
1589 CGM.getContext().getPointerType(VD->
getType()));
1590 llvm::Constant *addr =
OMPBuilder.getAddrOfDeclareTargetVar(
1596 CGM.getMangledName(VD), GeneratedRefs,
CGM.getLangOpts().OpenMPSimd,
1597 CGM.getLangOpts().OMPTargetTriples, LlvmPtrTy, AddrOfGlobal,
1598 LinkageForVariable);
1607 assert(!
CGM.getLangOpts().OpenMPUseTLS ||
1608 !
CGM.getContext().getTargetInfo().isTLSSupported());
1610 std::string Suffix =
getName({
"cache",
""});
1611 return OMPBuilder.getOrCreateInternalVariable(
1612 CGM.Int8PtrPtrTy, Twine(
CGM.getMangledName(VD)).concat(Suffix).str());
1619 if (
CGM.getLangOpts().OpenMPUseTLS &&
1620 CGM.getContext().getTargetInfo().isTLSSupported())
1624 llvm::Value *Args[] = {
1627 CGM.getSize(
CGM.GetTargetTypeStoreSize(VarTy)),
1632 CGM.getModule(), OMPRTL___kmpc_threadprivate_cached),
1644 CGM.getModule(), OMPRTL___kmpc_global_thread_num),
1648 llvm::Value *Args[] = {
1651 Ctor, CopyCtor, Dtor};
1654 CGM.getModule(), OMPRTL___kmpc_threadprivate_register),
1661 if (
CGM.getLangOpts().OpenMPUseTLS &&
1662 CGM.getContext().getTargetInfo().isTLSSupported())
1669 llvm::Value *Ctor =
nullptr, *CopyCtor =
nullptr, *Dtor =
nullptr;
1671 if (
CGM.getLangOpts().CPlusPlus && PerformInit) {
1676 CGM.getContext(),
nullptr, Loc,
1680 const auto &FI =
CGM.getTypes().arrangeBuiltinFunctionDeclaration(
1681 CGM.getContext().VoidPtrTy, Args);
1682 llvm::FunctionType *FTy =
CGM.getTypes().GetFunctionType(FI);
1683 std::string Name =
getName({
"__kmpc_global_ctor_",
""});
1684 llvm::Function *Fn =
1685 CGM.CreateGlobalInitOrCleanUpFunction(FTy, Name, FI, Loc);
1690 CGM.getContext().VoidPtrTy, Dst->getLocation());
1697 CGM.getContext().VoidPtrTy, Dst->getLocation());
1707 CGM.getContext(),
nullptr, Loc,
1711 const auto &FI =
CGM.getTypes().arrangeBuiltinFunctionDeclaration(
1712 CGM.getContext().VoidTy, Args);
1713 llvm::FunctionType *FTy =
CGM.getTypes().GetFunctionType(FI);
1714 std::string Name =
getName({
"__kmpc_global_dtor_",
""});
1715 llvm::Function *Fn =
1716 CGM.CreateGlobalInitOrCleanUpFunction(FTy, Name, FI, Loc);
1724 false,
CGM.getContext().VoidPtrTy, Dst->getLocation());
1739 CopyCtor = llvm::Constant::getNullValue(
CGM.DefaultPtrTy);
1740 if (Ctor ==
nullptr) {
1741 Ctor = llvm::Constant::getNullValue(
CGM.DefaultPtrTy);
1743 if (Dtor ==
nullptr) {
1744 Dtor = llvm::Constant::getNullValue(
CGM.DefaultPtrTy);
1747 auto *InitFunctionTy =
1748 llvm::FunctionType::get(
CGM.VoidTy,
false);
1749 std::string Name =
getName({
"__omp_threadprivate_init_",
""});
1750 llvm::Function *InitFunction =
CGM.CreateGlobalInitOrCleanUpFunction(
1751 InitFunctionTy, Name,
CGM.getTypes().arrangeNullaryFunction());
1755 CGM.getTypes().arrangeNullaryFunction(), ArgList,
1759 return InitFunction;
1767 llvm::GlobalValue *GV) {
1768 std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr =
1769 OMPDeclareTargetDeclAttr::getActiveAttr(FD);
1772 if (!ActiveAttr || !(*ActiveAttr)->getIndirect())
1779 OMPBuilder.OffloadInfoManager.getTargetRegionEntryFnName(Name, EntryInfo);
1785 llvm::GlobalValue *
Addr = GV;
1786 if (
CGM.getLangOpts().OpenMPIsTargetDevice) {
1787 llvm::PointerType *FnPtrTy = llvm::PointerType::get(
1788 CGM.getLLVMContext(),
1789 CGM.getModule().getDataLayout().getProgramAddressSpace());
1790 Addr =
new llvm::GlobalVariable(
1791 CGM.getModule(), FnPtrTy,
1792 true, llvm::GlobalValue::ExternalLinkage, GV, Name,
1793 nullptr, llvm::GlobalValue::NotThreadLocal,
1794 CGM.getModule().getDataLayout().getDefaultGlobalsAddressSpace());
1795 Addr->setVisibility(llvm::GlobalValue::ProtectedVisibility);
1802 OMPBuilder.OffloadInfoManager.registerDeviceGlobalVarEntryInfo(
1803 Name,
Addr,
CGM.GetTargetTypeStoreSize(
CGM.VoidPtrTy).getQuantity(),
1804 llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryIndirect,
1805 llvm::GlobalValue::WeakODRLinkage);
1818 llvm::OpenMPIRBuilder &
OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
1834 llvm::GlobalVariable *
Addr = VTable;
1836 OMPBuilder.OffloadInfoManager.getTargetRegionEntryFnName(AddrName, EntryInfo);
1837 AddrName.append(
"addr");
1839 if (
CGM.getLangOpts().OpenMPIsTargetDevice) {
1840 Addr =
new llvm::GlobalVariable(
1841 CGM.getModule(), VTable->getType(),
1842 true, llvm::GlobalValue::ExternalLinkage, VTable,
1844 nullptr, llvm::GlobalValue::NotThreadLocal,
1845 CGM.getModule().getDataLayout().getDefaultGlobalsAddressSpace());
1846 Addr->setVisibility(llvm::GlobalValue::ProtectedVisibility);
1848 OMPBuilder.OffloadInfoManager.registerDeviceGlobalVarEntryInfo(
1850 CGM.getDataLayout().getTypeAllocSize(VTable->getInitializer()->getType()),
1851 llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryIndirectVTable,
1852 llvm::GlobalValue::WeakODRLinkage);
1861 !
CGM.getOpenMPRuntime().VTableDeclMap.contains(
CXXRecord)) {
1862 auto Res =
CGM.getOpenMPRuntime().VTableDeclMap.try_emplace(
CXXRecord, VD);
1867 assert(VTablesAddr &&
"Expected non-null VTable address");
1869 if (VTablesAddr->hasExternalLinkage())
1870 VTablesAddr->setLinkage(llvm::GlobalValue::WeakODRLinkage);
1871 CGM.getOpenMPRuntime().registerVTableOffloadEntry(VTablesAddr, VD);
1889 auto GetVTableDecl = [](
const Expr *E) {
1900 if (
auto *DRE = dyn_cast<DeclRefExpr>(E)) {
1902 if (
auto *BD = dyn_cast<BindingDecl>(DRE->getDecl()))
1906 }
else if (
auto *MRE = dyn_cast<MemberExpr>(E)) {
1907 if (
auto *BaseDRE = dyn_cast<DeclRefExpr>(MRE->getBase())) {
1908 if (
auto *BaseVD = dyn_cast<VarDecl>(BaseDRE->getDecl()))
1912 return std::pair<CXXRecordDecl *, const VarDecl *>(
CXXRecord, VD);
1916 for (
const auto *E :
C->varlist()) {
1917 auto DeclPair = GetVTableDecl(E);
1919 if (DeclPair.second)
1928 std::string Suffix =
getName({
"artificial",
""});
1930 llvm::GlobalVariable *GAddr =
OMPBuilder.getOrCreateInternalVariable(
1931 VarLVType, Twine(Name).concat(Suffix).str());
1932 if (
CGM.getLangOpts().OpenMP &&
CGM.getLangOpts().OpenMPUseTLS &&
1933 CGM.getTarget().isTLSSupported()) {
1934 GAddr->setThreadLocal(
true);
1935 return Address(GAddr, GAddr->getValueType(),
1936 CGM.getContext().getTypeAlignInChars(VarType));
1938 std::string CacheSuffix =
getName({
"cache",
""});
1939 llvm::Value *Args[] = {
1947 Twine(Name).concat(Suffix).concat(CacheSuffix).str())};
1952 CGM.getModule(), OMPRTL___kmpc_threadprivate_cached),
1955 VarLVType,
CGM.getContext().getTypeAlignInChars(VarType));
2012 if (!
CGM.getLangOpts().OpenMPIsTargetDevice) {
2013 assert(OutlinedFn->arg_size() == CapturedVars.size() + 2 &&
2014 "Expected tid and bound tid before the captured arguments");
2015 for (
auto [I, Captured] : llvm::enumerate(CapturedVars)) {
2016 if (Captured->getType()->isPointerTy() &&
2017 llvm::isa<llvm::AllocaInst, llvm::GlobalVariable>(
2018 llvm::getUnderlyingObject(Captured)))
2019 OutlinedFn->addParamAttr(I + 2, llvm::Attribute::NoFreeObj);
2024 auto &M =
CGM.getModule();
2025 auto &&ThenGen = [&M, OutlinedFn, CapturedVars, RTLoc,
2028 llvm::Value *Args[] = {
2030 CGF.
Builder.getInt32(CapturedVars.size()),
2033 RealArgs.append(std::begin(Args), std::end(Args));
2034 RealArgs.append(CapturedVars.begin(), CapturedVars.end());
2036 llvm::FunctionCallee RTLFn =
2037 OMPBuilder.getOrCreateRuntimeFunction(M, OMPRTL___kmpc_fork_call);
2040 auto &&ElseGen = [&M, OutlinedFn, CapturedVars, RTLoc, Loc,
2046 llvm::Value *Args[] = {RTLoc, ThreadID};
2048 M, OMPRTL___kmpc_serialized_parallel),
2055 ".bound.zero.addr");
2060 OutlinedFnArgs.push_back(ZeroAddrBound.
getPointer());
2061 OutlinedFnArgs.append(CapturedVars.begin(), CapturedVars.end());
2069 OutlinedFn->removeFnAttr(llvm::Attribute::AlwaysInline);
2070 OutlinedFn->addFnAttr(llvm::Attribute::NoInline);
2076 M, OMPRTL___kmpc_end_serialized_parallel),
2095 if (
auto *OMPRegionInfo =
2097 if (OMPRegionInfo->getThreadIDVariable())
2098 return OMPRegionInfo->getThreadIDVariableLValue(CGF).getAddress();
2108 return ThreadIDTemp;
2112 std::string Prefix = Twine(
"gomp_critical_user_", CriticalName).str();
2113 std::string Name =
getName({Prefix,
"var"});
2114 llvm::GlobalVariable *GV =
2116 CGM.setDSOLocal(GV);
2123 llvm::FunctionCallee EnterCallee;
2125 llvm::FunctionCallee ExitCallee;
2128 llvm::BasicBlock *ContBlock =
nullptr;
2131 CommonActionTy(llvm::FunctionCallee EnterCallee,
2133 llvm::FunctionCallee ExitCallee,
2135 : EnterCallee(EnterCallee), EnterArgs(EnterArgs), ExitCallee(ExitCallee),
2140 llvm::Value *CallBool = CGF.
Builder.CreateIsNotNull(EnterRes);
2144 CGF.
Builder.CreateCondBr(CallBool, ThenBlock, ContBlock);
2148 void Done(CodeGenFunction &CGF) {
2153 void Exit(CodeGenFunction &CGF)
override {
2160 StringRef CriticalName,
2169 llvm::FunctionCallee RuntimeFcn =
OMPBuilder.getOrCreateRuntimeFunction(
2171 Hint ? OMPRTL___kmpc_critical_with_hint : OMPRTL___kmpc_critical);
2173 unsigned LockVarArgIdx = 2;
2175 RuntimeFcn.getFunctionType()
2176 ->getParamType(LockVarArgIdx)
2177 ->getPointerAddressSpace())
2179 LockVar, RuntimeFcn.getFunctionType()->getParamType(LockVarArgIdx));
2185 EnterArgs.push_back(CGF.
Builder.CreateIntCast(
2188 CommonActionTy Action(RuntimeFcn, EnterArgs,
2190 CGM.getModule(), OMPRTL___kmpc_end_critical),
2207 CommonActionTy Action(
OMPBuilder.getOrCreateRuntimeFunction(
2208 CGM.getModule(), OMPRTL___kmpc_master),
2211 CGM.getModule(), OMPRTL___kmpc_end_master),
2229 llvm::Value *FilterVal = Filter
2231 : llvm::ConstantInt::get(
CGM.Int32Ty, 0);
2236 CommonActionTy Action(
OMPBuilder.getOrCreateRuntimeFunction(
2237 CGM.getModule(), OMPRTL___kmpc_masked),
2240 CGM.getModule(), OMPRTL___kmpc_end_masked),
2256 llvm::Value *Args[] = {
2258 llvm::ConstantInt::get(
CGM.IntTy, 0,
true)};
2260 CGM.getModule(), OMPRTL___kmpc_omp_taskyield),
2264 if (
auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.
CapturedStmtInfo))
2265 Region->emitUntiedSwitch(CGF);
2278 CommonActionTy Action(
OMPBuilder.getOrCreateRuntimeFunction(
2279 CGM.getModule(), OMPRTL___kmpc_taskgroup),
2282 CGM.getModule(), OMPRTL___kmpc_end_taskgroup),
2291 unsigned Index,
const VarDecl *Var) {
2320 llvm::GlobalValue::InternalLinkage, Name,
2324 Fn->addFnAttr(
"sample-profile-suffix-elision-policy",
"selected");
2325 Fn->setDoesNotRecurse();
2342 for (
unsigned I = 0, E = AssignmentOps.size(); I < E; ++I) {
2343 const auto *DestVar =
2347 const auto *SrcVar =
2353 CGF.
EmitOMPCopy(
Type, DestAddr, SrcAddr, DestVar, SrcVar, AssignmentOps[I]);
2368 assert(CopyprivateVars.size() == SrcExprs.size() &&
2369 CopyprivateVars.size() == DstExprs.size() &&
2370 CopyprivateVars.size() == AssignmentOps.size());
2382 if (!CopyprivateVars.empty()) {
2385 C.getIntTypeForBitwidth(32, 1);
2391 CommonActionTy Action(
OMPBuilder.getOrCreateRuntimeFunction(
2392 CGM.getModule(), OMPRTL___kmpc_single),
2395 CGM.getModule(), OMPRTL___kmpc_end_single),
2408 llvm::APInt ArraySize(32, CopyprivateVars.size());
2409 QualType CopyprivateArrayTy =
C.getConstantArrayType(
2414 CopyprivateArrayTy,
".omp.copyprivate.cpr_list");
2415 for (
unsigned I = 0, E = CopyprivateVars.size(); I < E; ++I) {
2427 SrcExprs, DstExprs, AssignmentOps, Loc);
2428 llvm::Value *BufSize = CGF.
getTypeSize(CopyprivateArrayTy);
2432 llvm::Value *Args[] = {
2436 CL.emitRawPointer(CGF),
2441 CGM.getModule(), OMPRTL___kmpc_copyprivate),
2457 CommonActionTy Action(
OMPBuilder.getOrCreateRuntimeFunction(
2458 CGM.getModule(), OMPRTL___kmpc_ordered),
2461 CGM.getModule(), OMPRTL___kmpc_end_ordered),
2472 if (Kind == OMPD_for)
2473 Flags = OMP_IDENT_BARRIER_IMPL_FOR;
2474 else if (Kind == OMPD_sections)
2475 Flags = OMP_IDENT_BARRIER_IMPL_SECTIONS;
2476 else if (Kind == OMPD_single)
2477 Flags = OMP_IDENT_BARRIER_IMPL_SINGLE;
2478 else if (Kind == OMPD_barrier)
2479 Flags = OMP_IDENT_BARRIER_EXPL;
2481 Flags = OMP_IDENT_BARRIER_IMPL;
2491 S.getClausesOfKind<OMPOrderedClause>(),
2492 [](
const OMPOrderedClause *
C) { return C->getNumForLoops(); })) {
2493 ScheduleKind = OMPC_SCHEDULE_static;
2495 llvm::APInt ChunkSize(32, 1);
2505 bool ForceSimpleCall) {
2507 auto *OMPRegionInfo =
2510 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
2513 CGF.
Builder.restoreIP(AfterIP);
2526 if (OMPRegionInfo) {
2527 if (!ForceSimpleCall && OMPRegionInfo->hasCancel()) {
2530 OMPRTL___kmpc_cancel_barrier),
2539 CGF.
Builder.CreateCondBr(
Cmp, ExitBB, ContBB);
2551 CGM.getModule(), OMPRTL___kmpc_barrier),
2556 Expr *ME,
bool IsFatal) {
2558 : llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
2561 llvm::Value *Args[] = {
2563 llvm::ConstantInt::get(
CGM.Int32Ty, IsFatal ? 2 : 1),
2564 CGF.
Builder.CreatePointerCast(MVL,
CGM.Int8PtrTy)};
2566 CGM.getModule(), OMPRTL___kmpc_error),
2572 bool Chunked,
bool Ordered) {
2573 switch (ScheduleKind) {
2574 case OMPC_SCHEDULE_static:
2575 return Chunked ? (Ordered ? OMP_ord_static_chunked : OMP_sch_static_chunked)
2576 : (Ordered ? OMP_ord_static : OMP_sch_static);
2577 case OMPC_SCHEDULE_dynamic:
2578 return Ordered ? OMP_ord_dynamic_chunked : OMP_sch_dynamic_chunked;
2579 case OMPC_SCHEDULE_guided:
2580 return Ordered ? OMP_ord_guided_chunked : OMP_sch_guided_chunked;
2581 case OMPC_SCHEDULE_runtime:
2582 return Ordered ? OMP_ord_runtime : OMP_sch_runtime;
2583 case OMPC_SCHEDULE_auto:
2584 return Ordered ? OMP_ord_auto : OMP_sch_auto;
2586 assert(!Chunked &&
"chunk was specified but schedule kind not known");
2587 return Ordered ? OMP_ord_static : OMP_sch_static;
2589 llvm_unreachable(
"Unexpected runtime schedule");
2593static OpenMPSchedType
2596 return Chunked ? OMP_dist_sch_static_chunked : OMP_dist_sch_static;
2600 bool Chunked)
const {
2601 OpenMPSchedType Schedule =
2603 return Schedule == OMP_sch_static;
2609 return Schedule == OMP_dist_sch_static;
2613 bool Chunked)
const {
2614 OpenMPSchedType Schedule =
2616 return Schedule == OMP_sch_static_chunked;
2622 return Schedule == OMP_dist_sch_static_chunked;
2626 OpenMPSchedType Schedule =
2628 assert(Schedule != OMP_sch_static_chunked &&
"cannot be chunked here");
2629 return Schedule != OMP_sch_static;
2637 case OMPC_SCHEDULE_MODIFIER_monotonic:
2638 Modifier = OMP_sch_modifier_monotonic;
2640 case OMPC_SCHEDULE_MODIFIER_nonmonotonic:
2641 Modifier = OMP_sch_modifier_nonmonotonic;
2643 case OMPC_SCHEDULE_MODIFIER_simd:
2644 if (Schedule == OMP_sch_static_chunked)
2645 Schedule = OMP_sch_static_balanced_chunked;
2652 case OMPC_SCHEDULE_MODIFIER_monotonic:
2653 Modifier = OMP_sch_modifier_monotonic;
2655 case OMPC_SCHEDULE_MODIFIER_nonmonotonic:
2656 Modifier = OMP_sch_modifier_nonmonotonic;
2658 case OMPC_SCHEDULE_MODIFIER_simd:
2659 if (Schedule == OMP_sch_static_chunked)
2660 Schedule = OMP_sch_static_balanced_chunked;
2672 if (CGM.
getLangOpts().OpenMP >= 50 && Modifier == 0) {
2673 if (!(Schedule == OMP_sch_static_chunked || Schedule == OMP_sch_static ||
2674 Schedule == OMP_sch_static_balanced_chunked ||
2675 Schedule == OMP_ord_static_chunked || Schedule == OMP_ord_static ||
2676 Schedule == OMP_dist_sch_static_chunked ||
2677 Schedule == OMP_dist_sch_static ||
2678 Schedule == OMP_dist_sch_static_chunked_sch_static_chunkone))
2679 Modifier = OMP_sch_modifier_nonmonotonic;
2681 return Schedule | Modifier;
2691 ScheduleKind.
Schedule, DispatchValues.
Chunk !=
nullptr, Ordered);
2693 (Schedule != OMP_sch_static && Schedule != OMP_sch_static_chunked &&
2694 Schedule != OMP_ord_static && Schedule != OMP_ord_static_chunked &&
2695 Schedule != OMP_sch_static_balanced_chunked));
2702 llvm::Value *Chunk = DispatchValues.
Chunk ? DispatchValues.
Chunk
2703 : CGF.
Builder.getIntN(IVSize, 1);
2704 llvm::Value *Args[] = {
2708 CGM, Schedule, ScheduleKind.
M1, ScheduleKind.
M2)),
2711 CGF.
Builder.getIntN(IVSize, 1),
2728 CodeGenFunction &CGF, llvm::Value *UpdateLocation, llvm::Value *ThreadId,
2729 llvm::FunctionCallee ForStaticInitFunction, OpenMPSchedType Schedule,
2736 assert(Schedule == OMP_sch_static || Schedule == OMP_sch_static_chunked ||
2737 Schedule == OMP_sch_static_balanced_chunked ||
2738 Schedule == OMP_ord_static || Schedule == OMP_ord_static_chunked ||
2739 Schedule == OMP_dist_sch_static ||
2740 Schedule == OMP_dist_sch_static_chunked ||
2741 Schedule == OMP_dist_sch_static_chunked_sch_static_chunkone);
2748 llvm::Value *Chunk = Values.
Chunk;
2749 if (Chunk ==
nullptr) {
2750 assert((Schedule == OMP_sch_static || Schedule == OMP_ord_static ||
2751 Schedule == OMP_dist_sch_static) &&
2752 "expected static non-chunked schedule");
2756 assert((Schedule == OMP_sch_static_chunked ||
2757 Schedule == OMP_sch_static_balanced_chunked ||
2758 Schedule == OMP_ord_static_chunked ||
2759 Schedule == OMP_dist_sch_static_chunked ||
2760 Schedule == OMP_dist_sch_static_chunked_sch_static_chunkone) &&
2761 "expected static chunked schedule");
2763 llvm::Value *Args[] = {
2783 OpenMPSchedType ScheduleNum =
2785 ? OMP_dist_sch_static_chunked_sch_static_chunkone
2789 "Expected loop-based or sections-based directive.");
2792 ? OMP_IDENT_WORK_LOOP
2793 : OMP_IDENT_WORK_SECTIONS);
2795 llvm::FunctionCallee StaticInitFunction =
2800 ScheduleNum, ScheduleKind.
M1, ScheduleKind.
M2, Values);
2807 OpenMPSchedType ScheduleNum =
2809 llvm::Value *UpdatedLocation =
2812 llvm::FunctionCallee StaticInitFunction;
2813 bool isGPUDistribute =
2814 CGM.getLangOpts().OpenMPIsTargetDevice &&
CGM.getTriple().isGPU();
2815 StaticInitFunction =
OMPBuilder.createForStaticInitFunction(
2826 assert((DKind == OMPD_distribute || DKind == OMPD_for ||
2827 DKind == OMPD_sections) &&
2828 "Expected distribute, for, or sections directive kind");
2832 llvm::Value *Args[] = {
2835 (DKind == OMPD_target_teams_loop)
2836 ? OMP_IDENT_WORK_DISTRIBUTE
2838 ? OMP_IDENT_WORK_LOOP
2839 : OMP_IDENT_WORK_SECTIONS),
2843 CGM.getLangOpts().OpenMPIsTargetDevice &&
CGM.getTriple().isGPU())
2846 CGM.getModule(), OMPRTL___kmpc_distribute_static_fini),
2850 CGM.getModule(), OMPRTL___kmpc_for_static_fini),
2875 llvm::Value *Args[] = {
2883 OMPBuilder.createDispatchNextFunction(IVSize, IVSigned), Args);
2890 const Expr *Message,
2893 return llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
2902 return llvm::ConstantInt::get(
CGM.Int32Ty,
2903 Severity == OMPC_SEVERITY_warning ? 1 : 2);
2919 RuntimeFunction FnID = OMPRTL___kmpc_push_num_threads;
2920 if (Modifier == OMPC_NUMTHREADS_strict) {
2921 FnID = OMPRTL___kmpc_push_num_threads_strict;
2926 OMPBuilder.getOrCreateRuntimeFunction(
CGM.getModule(), FnID), Args);
2930 ProcBindKind ProcBind,
2934 assert(ProcBind != OMP_PROC_BIND_unknown &&
"Unsupported proc_bind value.");
2936 llvm::Value *Args[] = {
2938 llvm::ConstantInt::get(
CGM.IntTy,
unsigned(ProcBind),
true)};
2940 CGM.getModule(), OMPRTL___kmpc_push_proc_bind),
2953 CGM.getModule(), OMPRTL___kmpc_flush),
2960enum KmpTaskTFields {
2987 if (
CGM.getLangOpts().OpenMPSimd ||
OMPBuilder.OffloadInfoManager.empty())
2990 llvm::OpenMPIRBuilder::EmitMetadataErrorReportFunctionTy &&ErrorReportFn =
2991 [
this](llvm::OpenMPIRBuilder::EmitMetadataErrorKind Kind,
2992 const llvm::TargetRegionEntryInfo &EntryInfo) ->
void {
2994 if (Kind != llvm::OpenMPIRBuilder::EMIT_MD_GLOBAL_VAR_LINK_ERROR) {
2995 for (
auto I =
CGM.getContext().getSourceManager().fileinfo_begin(),
2996 E =
CGM.getContext().getSourceManager().fileinfo_end();
2998 if (I->getFirst().getUniqueID().getDevice() == EntryInfo.DeviceID &&
2999 I->getFirst().getUniqueID().getFile() == EntryInfo.FileID) {
3000 Loc =
CGM.getContext().getSourceManager().translateFileLineCol(
3001 I->getFirst(), EntryInfo.Line, 1);
3007 case llvm::OpenMPIRBuilder::EMIT_MD_TARGET_REGION_ERROR: {
3008 CGM.getDiags().Report(Loc,
3009 diag::err_target_region_offloading_entry_incorrect)
3010 << EntryInfo.ParentName;
3012 case llvm::OpenMPIRBuilder::EMIT_MD_DECLARE_TARGET_ERROR: {
3013 CGM.getDiags().Report(
3014 Loc, diag::err_target_var_offloading_entry_incorrect_with_parent)
3015 << EntryInfo.ParentName;
3017 case llvm::OpenMPIRBuilder::EMIT_MD_GLOBAL_VAR_LINK_ERROR: {
3018 CGM.getDiags().Report(diag::err_target_var_offloading_entry_incorrect);
3020 case llvm::OpenMPIRBuilder::EMIT_MD_GLOBAL_VAR_INDIRECT_ERROR: {
3021 unsigned DiagID =
CGM.getDiags().getCustomDiagID(
3023 "target variable is incorrect: the "
3024 "address is invalid.");
3025 CGM.getDiags().Report(DiagID);
3030 OMPBuilder.createOffloadEntriesAndInfoMetadata(ErrorReportFn);
3037 QualType KmpRoutineEntryTyArgs[] = {KmpInt32Ty,
C.VoidPtrTy};
3040 C.getFunctionType(KmpInt32Ty, KmpRoutineEntryTyArgs, EPI));
3046struct PrivateHelpersTy {
3047 PrivateHelpersTy(
const Expr *OriginalRef,
const VarDecl *Original,
3049 : OriginalRef(OriginalRef), Original(Original), PrivateCopy(PrivateCopy),
3050 PrivateElemInit(PrivateElemInit) {}
3051 PrivateHelpersTy(
const VarDecl *Original) : Original(Original) {}
3052 const Expr *OriginalRef =
nullptr;
3053 const VarDecl *Original =
nullptr;
3054 const VarDecl *PrivateCopy =
nullptr;
3055 const VarDecl *PrivateElemInit =
nullptr;
3056 bool isLocalPrivate()
const {
3057 return !OriginalRef && !PrivateCopy && !PrivateElemInit;
3060typedef std::pair<CharUnits , PrivateHelpersTy> PrivateDataTy;
3066 if (
const auto *BD = dyn_cast<BindingDecl>(
Decl))
3073 if (!CVD->
hasAttr<OMPAllocateDeclAttr>())
3075 const auto *AA = CVD->
getAttr<OMPAllocateDeclAttr>();
3077 return !(AA->getAllocatorType() == OMPAllocateDeclAttr::OMPDefaultMemAlloc &&
3078 !AA->getAllocator());
3088 RecordDecl *RD =
C.buildImplicitRecord(
".kmp_privates.t");
3090 for (
const auto &Pair :
Privates) {
3091 const VarDecl *VD = Pair.second.Original;
3092 const VarDecl *PrivateCopy = Pair.second.PrivateCopy;
3098 Pair.second.OriginalRef &&
3106 if (Pair.second.isLocalPrivate()) {
3129 QualType KmpRoutineEntryPointerQTy) {
3149 CanQualType KmpCmplrdataTy =
C.getCanonicalTagType(UD);
3150 RecordDecl *RD =
C.buildImplicitRecord(
"kmp_task_t");
3180 RecordDecl *RD =
C.buildImplicitRecord(
"kmp_task_t_with_privates");
3200static llvm::Function *
3203 QualType KmpTaskTWithPrivatesPtrQTy,
3205 QualType SharedsPtrTy, llvm::Function *TaskFunction,
3206 llvm::Value *TaskPrivatesMap) {
3212 C,
nullptr, Loc,
nullptr,
3215 const auto &TaskEntryFnInfo =
3217 llvm::FunctionType *TaskEntryTy =
3220 auto *TaskEntry = llvm::Function::Create(
3221 TaskEntryTy, llvm::GlobalValue::InternalLinkage, Name, &CGM.
getModule());
3224 TaskEntry->addFnAttr(
"sample-profile-suffix-elision-policy",
"selected");
3225 TaskEntry->setDoesNotRecurse();
3240 const auto *KmpTaskTWithPrivatesQTyRD =
3245 auto PartIdFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTPartId);
3247 llvm::Value *PartidParam = PartIdLVal.getPointer(CGF);
3249 auto SharedsFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTShareds);
3255 auto PrivatesFI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin(), 1);
3256 llvm::Value *PrivatesParam;
3257 if (PrivatesFI != KmpTaskTWithPrivatesQTyRD->field_end()) {
3260 PrivatesLVal.getPointer(CGF), CGF.
VoidPtrTy);
3262 PrivatesParam = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
3265 llvm::Value *CommonArgs[] = {
3266 GtidParam, PartidParam, PrivatesParam, TaskPrivatesMap,
3272 std::end(CommonArgs));
3274 auto LBFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound);
3277 auto UBFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound);
3280 auto StFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTStride);
3283 auto LIFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLastIter);
3286 auto RFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTReductions);
3289 CallArgs.push_back(LBParam);
3290 CallArgs.push_back(UBParam);
3291 CallArgs.push_back(StParam);
3292 CallArgs.push_back(LIParam);
3293 CallArgs.push_back(RParam);
3295 CallArgs.push_back(SharedsParam);
3308 QualType KmpTaskTWithPrivatesPtrQTy,
3309 QualType KmpTaskTWithPrivatesQTy) {
3315 C,
nullptr, Loc,
nullptr,
3318 const auto &DestructorFnInfo =
3320 llvm::FunctionType *DestructorFnTy =
3324 auto *DestructorFn =
3325 llvm::Function::Create(DestructorFnTy, llvm::GlobalValue::InternalLinkage,
3330 DestructorFn->addFnAttr(
"sample-profile-suffix-elision-policy",
"selected");
3331 DestructorFn->setDoesNotRecurse();
3339 const auto *KmpTaskTWithPrivatesQTyRD =
3341 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin());
3343 for (
const auto *Field : FI->getType()->castAsRecordDecl()->fields()) {
3345 Field->getType().isDestructedType()) {
3347 CGF.
pushDestroy(DtorKind, FieldLValue.getAddress(), Field->getType());
3351 return DestructorFn;
3371 C,
nullptr, Loc,
nullptr,
3372 C.getPointerType(PrivatesQTy).withConst().withRestrict(),
3374 Args.push_back(TaskPrivatesArg);
3375 llvm::SmallDenseMap<CanonicalDeclPtr<const VarDecl>,
unsigned> PrivateVarsPos;
3377 llvm::SmallDenseMap<const BindingDecl *, unsigned> BindingDeclPos;
3378 unsigned Counter = 1;
3379 for (
const Expr *E :
Data.PrivateVars) {
3381 C,
nullptr, Loc,
nullptr,
3382 C.getPointerType(
C.getPointerType(E->
getType()))
3387 if (
const auto *BD = dyn_cast<BindingDecl>(VD))
3393 for (
const Expr *E :
Data.FirstprivateVars) {
3395 C,
nullptr, Loc,
nullptr,
3396 C.getPointerType(
C.getPointerType(E->
getType()))
3401 if (
const auto *BD = dyn_cast<BindingDecl>(VD))
3407 for (
const Expr *E :
Data.LastprivateVars) {
3409 C,
nullptr, Loc,
nullptr,
3410 C.getPointerType(
C.getPointerType(E->
getType()))
3415 if (
const auto *BD = dyn_cast<BindingDecl>(VD))
3424 Ty =
C.getPointerType(Ty);
3426 Ty =
C.getPointerType(Ty);
3428 C,
nullptr, Loc,
nullptr,
3429 C.getPointerType(
C.getPointerType(Ty)).withConst().withRestrict(),
3431 PrivateVarsPos[VD] = Counter;
3434 const auto &TaskPrivatesMapFnInfo =
3436 llvm::FunctionType *TaskPrivatesMapTy =
3440 auto *TaskPrivatesMap = llvm::Function::Create(
3441 TaskPrivatesMapTy, llvm::GlobalValue::InternalLinkage, Name,
3444 TaskPrivatesMapFnInfo);
3446 TaskPrivatesMap->addFnAttr(
"sample-profile-suffix-elision-policy",
3449 TaskPrivatesMap->removeFnAttr(llvm::Attribute::NoInline);
3450 TaskPrivatesMap->removeFnAttr(llvm::Attribute::OptimizeNone);
3451 TaskPrivatesMap->addFnAttr(llvm::Attribute::AlwaysInline);
3455 TaskPrivatesMapFnInfo, Args, Loc, Loc);
3463 for (
const FieldDecl *Field : PrivatesQTyRD->fields()) {
3467 if (
Privates[Counter].second.OriginalRef) {
3471 LookupVD =
Privates[Counter].second.Original;
3479 if (
const auto *BD = dyn_cast<BindingDecl>(LookupVD)) {
3482 assert(Position &&
"binding not in privates mapping");
3486 const VarDecl *VD = Args[Position];
3490 RefLVal.getAddress(), RefLVal.getType()->castAs<
PointerType>());
3495 return TaskPrivatesMap;
3501 Address KmpTaskSharedsPtr, LValue TDBase,
3507 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->
field_begin());
3521 if ((!IsTargetTask && !
Data.FirstprivateVars.empty() && ForDup) ||
3522 (IsTargetTask && KmpTaskSharedsPtr.
isValid())) {
3529 FI = FI->getType()->castAsRecordDecl()->field_begin();
3530 for (
const PrivateDataTy &Pair :
Privates) {
3532 if (Pair.second.isLocalPrivate()) {
3536 const VarDecl *VD = Pair.second.PrivateCopy;
3541 if (
const VarDecl *Elem = Pair.second.PrivateElemInit) {
3542 const VarDecl *OriginalVD = Pair.second.Original;
3545 LValue SharedRefLValue;
3548 if (IsTargetTask && !SharedField) {
3552 ->getNumParams() == 0 &&
3555 ->getDeclContext()) &&
3556 "Expected artificial target data variable.");
3559 }
else if (ForDup) {
3563 if (Pair.second.OriginalRef) {
3564 if (
const auto *DRE =
3565 dyn_cast<DeclRefExpr>(Pair.second.OriginalRef)) {
3566 if (
const auto *BD = dyn_cast<BindingDecl>(DRE->getDecl())) {
3574 It->second = SharedRefLValue.getAddress();
3577 SharedRefLValue = CGF.
EmitLValue(BD->getBinding());
3580 RestoreIt->second = Saved;
3588 Pair.second.OriginalRef &&
3592 SharedRefLValue.getAddress().withAlignment(
3593 IsBinding ?
C.toCharUnitsFromBits(
3594 C.getTypeAlign(SharedRefLValue.getType()))
3595 :
C.getDeclAlign(OriginalVD)),
3597 SharedRefLValue.getTBAAInfo());
3599 Pair.second.Original->getCanonicalDecl()) > 0 ||
3601 SharedRefLValue = CGF.
EmitLValue(Pair.second.OriginalRef);
3604 InlinedOpenMPRegionRAII Region(
3607 SharedRefLValue = CGF.
EmitLValue(Pair.second.OriginalRef);
3618 PrivateLValue.getAddress(), SharedRefLValue.getAddress(),
Type,
3619 [&CGF, Elem,
Init, &CapturesInfo](
Address DestElement,
3622 CodeGenFunction::OMPPrivateScope InitScope(CGF);
3623 InitScope.addPrivate(Elem, SrcElement);
3624 (void)InitScope.Privatize();
3626 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(
3627 CGF, &CapturesInfo);
3628 CGF.EmitAnyExprToMem(Init, DestElement,
3629 Init->getType().getQualifiers(),
3635 InitScope.
addPrivate(Elem, SharedRefLValue.getAddress());
3644 }
else if (
const VarDecl *OriginalVD = Pair.second.Original) {
3649 if (Pair.second.OriginalRef) {
3650 if (
const auto *DRE = dyn_cast<DeclRefExpr>(Pair.second.OriginalRef)) {
3651 BD = dyn_cast<BindingDecl>(DRE->getDecl());
3661 auto EmitBindingWithTempMap = [&CGF](
const BindingDecl *BD,
3668 It->second = DDAddr;
3677 RestoreIt->second = Saved;
3685 LValue SharedRefLValue;
3689 EmitBindingWithTempMap(BD, SharedRefLValue.getAddress());
3691 SharedRefLValue.getAddress().withAlignment(
3692 C.getDeclAlign(OriginalVD)),
3694 SharedRefLValue.getTBAAInfo());
3698 InlinedOpenMPRegionRAII Region(
3705 SharedRefLValue = EmitBindingWithTempMap(BD, DDAddr);
3718 bool InitRequired =
false;
3719 for (
const PrivateDataTy &Pair :
Privates) {
3720 if (Pair.second.isLocalPrivate())
3722 const VarDecl *VD = Pair.second.PrivateCopy;
3724 InitRequired = InitRequired || (isa_and_nonnull<CXXConstructExpr>(
Init) &&
3729 return InitRequired;
3746 QualType KmpTaskTWithPrivatesPtrQTy,
3753 C,
nullptr, Loc,
nullptr, KmpTaskTWithPrivatesPtrQTy,
3756 C,
nullptr, Loc,
nullptr, KmpTaskTWithPrivatesPtrQTy,
3762 const auto &TaskDupFnInfo =
3766 auto *TaskDup = llvm::Function::Create(
3767 TaskDupTy, llvm::GlobalValue::InternalLinkage, Name, &CGM.
getModule());
3770 TaskDup->addFnAttr(
"sample-profile-suffix-elision-policy",
"selected");
3771 TaskDup->setDoesNotRecurse();
3781 auto LIFI = std::next(KmpTaskTQTyRD->
field_begin(), KmpTaskTLastIter);
3783 TDBase, *KmpTaskTWithPrivatesQTyRD->
field_begin());
3793 if (!
Data.FirstprivateVars.empty()) {
3798 TDBase, *KmpTaskTWithPrivatesQTyRD->
field_begin());
3806 emitPrivatesInit(CGF, D, KmpTaskSharedsPtr, TDBase, KmpTaskTWithPrivatesQTyRD,
3817 for (
const PrivateDataTy &P :
Privates) {
3818 if (P.second.isLocalPrivate())
3820 QualType Ty = P.second.Original->getType().getNonReferenceType();
3829class OMPIteratorGeneratorScope final
3831 CodeGenFunction &CGF;
3832 const OMPIteratorExpr *E =
nullptr;
3833 SmallVector<CodeGenFunction::JumpDest, 4> ContDests;
3834 SmallVector<CodeGenFunction::JumpDest, 4> ExitDests;
3835 OMPIteratorGeneratorScope() =
delete;
3836 OMPIteratorGeneratorScope(OMPIteratorGeneratorScope &) =
delete;
3839 OMPIteratorGeneratorScope(CodeGenFunction &CGF,
const OMPIteratorExpr *E)
3840 : CodeGenFunction::OMPPrivateScope(CGF), CGF(CGF), E(E) {
3843 SmallVector<llvm::Value *, 4> Uppers;
3845 Uppers.push_back(CGF.EmitScalarExpr(E->getHelper(I).Upper));
3846 const auto *VD = cast<VarDecl>(E->getIteratorDecl(I));
3847 addPrivate(VD, CGF.CreateMemTemp(VD->getType(), VD->getName()));
3848 const OMPIteratorHelperData &HelperData = E->getHelper(I);
3850 HelperData.CounterVD,
3851 CGF.CreateMemTemp(HelperData.CounterVD->getType(),
"counter.addr"));
3856 const OMPIteratorHelperData &HelperData = E->getHelper(I);
3858 CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(HelperData.CounterVD),
3859 HelperData.CounterVD->getType());
3861 CGF.EmitStoreOfScalar(
3862 llvm::ConstantInt::get(CLVal.getAddress().getElementType(), 0),
3864 CodeGenFunction::JumpDest &ContDest =
3865 ContDests.emplace_back(CGF.getJumpDestInCurrentScope(
"iter.cont"));
3866 CodeGenFunction::JumpDest &ExitDest =
3867 ExitDests.emplace_back(CGF.getJumpDestInCurrentScope(
"iter.exit"));
3869 llvm::Value *N = Uppers[I];
3872 CGF.EmitBlock(ContDest.getBlock());
3874 CGF.EmitLoadOfScalar(CLVal, HelperData.CounterVD->getLocation());
3876 HelperData.CounterVD->getType()->isSignedIntegerOrEnumerationType()
3877 ? CGF.Builder.CreateICmpSLT(CVal, N)
3878 : CGF.Builder.CreateICmpULT(CVal, N);
3879 llvm::BasicBlock *BodyBB = CGF.createBasicBlock(
"iter.body");
3880 CGF.Builder.CreateCondBr(Cmp, BodyBB, ExitDest.getBlock());
3882 CGF.EmitBlock(BodyBB);
3884 CGF.EmitIgnoredExpr(HelperData.Update);
3887 ~OMPIteratorGeneratorScope() {
3892 const OMPIteratorHelperData &HelperData = E->
getHelper(I - 1);
3897 CGF.
EmitBlock(ExitDests[I - 1].getBlock(), I == 1);
3903static std::pair<llvm::Value *, llvm::Value *>
3905 const auto *OASE = dyn_cast<OMPArrayShapingExpr>(E);
3908 const Expr *
Base = OASE->getBase();
3913 llvm::Value *SizeVal;
3916 SizeVal = CGF.
getTypeSize(OASE->getBase()->getType()->getPointeeType());
3917 for (
const Expr *SE : OASE->getDimensions()) {
3921 SizeVal = CGF.
Builder.CreateNUWMul(SizeVal, Sz);
3923 }
else if (
const auto *ASE =
3926 Address UpAddrAddress = UpAddrLVal.getAddress();
3927 llvm::Value *UpAddr = CGF.
Builder.CreateConstGEP1_32(
3930 SizeVal = CGF.
Builder.CreatePtrDiff(UpAddr,
Addr,
"",
true);
3934 return std::make_pair(
Addr, SizeVal);
3939 QualType FlagsTy =
C.getIntTypeForBitwidth(32,
false);
3940 if (KmpTaskAffinityInfoTy.
isNull()) {
3942 C.buildImplicitRecord(
"kmp_task_affinity_info_t");
3948 KmpTaskAffinityInfoTy =
C.getCanonicalTagType(KmpAffinityInfoRD);
3955 llvm::Function *TaskFunction,
QualType SharedsTy,
3960 const auto *I =
Data.PrivateCopies.begin();
3961 for (
const Expr *E :
Data.PrivateVars) {
3965 Privates.emplace_back(
C.getDeclAlign(VD),
3966 PrivateHelpersTy(E, VD, CopyVD,
3970 I =
Data.FirstprivateCopies.begin();
3971 const auto *IElemInitRef =
Data.FirstprivateInits.begin();
3972 for (
const Expr *E :
Data.FirstprivateVars) {
3976 const auto *InitVD =
3978 Privates.emplace_back(
C.getDeclAlign(VD),
3979 PrivateHelpersTy(E, VD, CopyVD, InitVD));
3983 I =
Data.LastprivateCopies.begin();
3984 for (
const Expr *E :
Data.LastprivateVars) {
3988 Privates.emplace_back(
C.getDeclAlign(VD),
3989 PrivateHelpersTy(E, VD, CopyVD,
3995 Privates.emplace_back(
CGM.getPointerAlign(), PrivateHelpersTy(VD));
3997 Privates.emplace_back(
C.getDeclAlign(VD), PrivateHelpersTy(VD));
4000 [](
const PrivateDataTy &L,
const PrivateDataTy &R) {
4001 return L.first > R.first;
4003 QualType KmpInt32Ty =
C.getIntTypeForBitwidth(32, 1);
4014 assert((D.getDirectiveKind() == OMPD_task ||
4017 "Expected taskloop, task or target directive");
4024 const auto *KmpTaskTQTyRD =
KmpTaskTQTy->castAsRecordDecl();
4026 const RecordDecl *KmpTaskTWithPrivatesQTyRD =
4029 C.getCanonicalTagType(KmpTaskTWithPrivatesQTyRD);
4030 QualType KmpTaskTWithPrivatesPtrQTy =
4031 C.getPointerType(KmpTaskTWithPrivatesQTy);
4032 llvm::Type *KmpTaskTWithPrivatesPtrTy = CGF.
Builder.getPtrTy(0);
4033 llvm::Value *KmpTaskTWithPrivatesTySize =
4035 QualType SharedsPtrTy =
C.getPointerType(SharedsTy);
4038 llvm::Value *TaskPrivatesMap =
nullptr;
4039 llvm::Type *TaskPrivatesMapTy =
4040 std::next(TaskFunction->arg_begin(), 3)->getType();
4042 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->
field_begin());
4046 TaskPrivatesMap, TaskPrivatesMapTy);
4048 TaskPrivatesMap = llvm::ConstantPointerNull::get(
4054 CGM, Loc, D.getDirectiveKind(), KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy,
4055 KmpTaskTWithPrivatesQTy,
KmpTaskTQTy, SharedsPtrTy, TaskFunction,
4067 DestructorsFlag = 0x8,
4068 PriorityFlag = 0x20,
4069 DetachableFlag = 0x40,
4070 FreeAgentFlag = 0x80,
4071 TransparentFlag = 0x100,
4073 unsigned Flags =
Data.Tied ? TiedFlag : 0;
4074 bool NeedsCleanup =
false;
4079 Flags = Flags | DestructorsFlag;
4083 if (Kind == OMPC_THREADSET_omp_pool)
4084 Flags = Flags | FreeAgentFlag;
4086 if (D.getSingleClause<OMPTransparentClause>())
4087 Flags |= TransparentFlag;
4089 if (
Data.Priority.getInt())
4090 Flags = Flags | PriorityFlag;
4092 Flags = Flags | DetachableFlag;
4093 llvm::Value *TaskFlags =
4094 Data.Final.getPointer()
4095 ? CGF.
Builder.CreateSelect(
Data.Final.getPointer(),
4096 CGF.
Builder.getInt32(FinalFlag),
4098 : CGF.
Builder.getInt32(
Data.Final.getInt() ? FinalFlag : 0);
4099 TaskFlags = CGF.
Builder.CreateOr(TaskFlags, CGF.
Builder.getInt32(Flags));
4100 llvm::Value *SharedsSize =
CGM.getSize(
C.getTypeSizeInChars(SharedsTy));
4102 getThreadID(CGF, Loc), TaskFlags, KmpTaskTWithPrivatesTySize,
4105 llvm::Value *NewTask;
4106 if (D.hasClausesOfKind<OMPNowaitClause>()) {
4112 llvm::Value *DeviceID;
4117 DeviceID = CGF.
Builder.getInt64(OMP_DEVICEID_UNDEF);
4118 AllocArgs.push_back(DeviceID);
4121 CGM.getModule(), OMPRTL___kmpc_omp_target_task_alloc),
4126 CGM.getModule(), OMPRTL___kmpc_omp_task_alloc),
4139 llvm::Value *Tid =
getThreadID(CGF, DC->getBeginLoc());
4140 Tid = CGF.
Builder.CreateIntCast(Tid, CGF.
IntTy,
false);
4143 CGM.getModule(), OMPRTL___kmpc_task_allow_completion_event),
4144 {Loc, Tid, NewTask});
4155 llvm::Value *NumOfElements =
nullptr;
4156 unsigned NumAffinities = 0;
4158 if (
const Expr *Modifier =
C->getModifier()) {
4160 for (
unsigned I = 0, E = IE->numOfIterators(); I < E; ++I) {
4164 NumOfElements ? CGF.
Builder.CreateNUWMul(NumOfElements, Sz) : Sz;
4167 NumAffinities +=
C->varlist_size();
4172 enum RTLAffinityInfoFieldsTy { BaseAddr, Len, Flags };
4174 QualType KmpTaskAffinityInfoArrayTy;
4175 if (NumOfElements) {
4176 NumOfElements = CGF.
Builder.CreateNUWAdd(
4177 llvm::ConstantInt::get(CGF.
SizeTy, NumAffinities), NumOfElements);
4180 C.getIntTypeForBitwidth(
C.getTypeSize(
C.getSizeType()), 0),
4184 KmpTaskAffinityInfoArrayTy =
C.getVariableArrayType(
4192 NumOfElements = CGF.
Builder.CreateIntCast(NumOfElements, CGF.
Int32Ty,
4195 KmpTaskAffinityInfoArrayTy =
C.getConstantArrayType(
4197 llvm::APInt(
C.getTypeSize(
C.getSizeType()), NumAffinities),
nullptr,
4202 NumOfElements = llvm::ConstantInt::get(
CGM.Int32Ty, NumAffinities,
4209 bool HasIterator =
false;
4211 if (
C->getModifier()) {
4215 for (
const Expr *E :
C->varlist()) {
4224 Base, *std::next(KmpAffinityInfoRD->field_begin(), BaseAddr));
4229 Base, *std::next(KmpAffinityInfoRD->field_begin(), Len));
4243 const Expr *Modifier =
C->getModifier();
4246 OMPIteratorGeneratorScope IteratorScope(
4248 for (
const Expr *E :
C->varlist()) {
4258 Base, *std::next(KmpAffinityInfoRD->field_begin(), BaseAddr));
4263 Base, *std::next(KmpAffinityInfoRD->field_begin(), Len));
4265 Idx = CGF.
Builder.CreateNUWAdd(
4266 Idx, llvm::ConstantInt::get(Idx->getType(), 1));
4281 CGM.getModule(), OMPRTL___kmpc_omp_reg_task_with_affinity),
4282 {LocRef, GTid, NewTask, NumOfElements, AffinListPtr});
4284 llvm::Value *NewTaskNewTaskTTy =
4286 NewTask, KmpTaskTWithPrivatesPtrTy);
4288 KmpTaskTWithPrivatesQTy);
4299 *std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTShareds)),
4301 CGF.
Int8Ty,
CGM.getNaturalTypeAlignment(SharedsTy));
4315 CGM, Loc, D, KmpTaskTWithPrivatesPtrQTy, KmpTaskTWithPrivatesQTyRD,
4316 KmpTaskTQTyRD, SharedsTy, SharedsPtrTy,
Data,
Privates,
4317 !
Data.LastprivateVars.empty());
4321 enum { Priority = 0, Destructors = 1 };
4323 auto FI = std::next(KmpTaskTQTyRD->field_begin(), Data1);
4324 const auto *KmpCmplrdataUD = (*FI)->getType()->castAsRecordDecl();
4325 assert(KmpCmplrdataUD->isUnion());
4328 CGM, Loc, KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy,
4329 KmpTaskTWithPrivatesQTy);
4332 Data1LV, *std::next(KmpCmplrdataUD->field_begin(), Destructors));
4338 if (
Data.Priority.getInt()) {
4340 TDBase, *std::next(KmpTaskTQTyRD->field_begin(), Data2));
4342 Data2LV, *std::next(KmpCmplrdataUD->field_begin(), Priority));
4345 Result.NewTask = NewTask;
4346 Result.TaskEntry = TaskEntry;
4347 Result.NewTaskNewTaskTTy = NewTaskNewTaskTTy;
4349 Result.KmpTaskTQTyRD = KmpTaskTQTyRD;
4355 RTLDependenceKindTy DepKind;
4357 case OMPC_DEPEND_in:
4358 DepKind = RTLDependenceKindTy::DepIn;
4361 case OMPC_DEPEND_out:
4362 case OMPC_DEPEND_inout:
4363 DepKind = RTLDependenceKindTy::DepInOut;
4365 case OMPC_DEPEND_mutexinoutset:
4366 DepKind = RTLDependenceKindTy::DepMutexInOutSet;
4368 case OMPC_DEPEND_inoutset:
4369 DepKind = RTLDependenceKindTy::DepInOutSet;
4371 case OMPC_DEPEND_outallmemory:
4372 DepKind = RTLDependenceKindTy::DepOmpAllMem;
4374 case OMPC_DEPEND_source:
4375 case OMPC_DEPEND_sink:
4376 case OMPC_DEPEND_depobj:
4377 case OMPC_DEPEND_inoutallmemory:
4379 llvm_unreachable(
"Unknown task dependence type");
4387 FlagsTy =
C.getIntTypeForBitwidth(
C.getTypeSize(
C.BoolTy),
false);
4388 if (KmpDependInfoTy.
isNull()) {
4389 RecordDecl *KmpDependInfoRD =
C.buildImplicitRecord(
"kmp_depend_info");
4395 KmpDependInfoTy =
C.getCanonicalTagType(KmpDependInfoRD);
4399std::pair<llvm::Value *, LValue>
4412 CGF,
Base.getAddress(),
4413 llvm::ConstantInt::get(CGF.
IntPtrTy, -1,
true));
4419 *std::next(KmpDependInfoRD->field_begin(),
4420 static_cast<unsigned int>(RTLDependInfoFields::BaseAddr)));
4422 return std::make_pair(NumDeps,
Base);
4426 llvm::PointerUnion<unsigned *, LValue *> Pos,
4436 OMPIteratorGeneratorScope IteratorScope(
4437 CGF, cast_or_null<OMPIteratorExpr>(
4438 Data.IteratorExpr ?
Data.IteratorExpr->IgnoreParenImpCasts()
4440 for (
const Expr *E :
Data.DepExprs) {
4450 Size = llvm::ConstantInt::get(CGF.
SizeTy, 0);
4453 if (
unsigned *P = dyn_cast<unsigned *>(Pos)) {
4457 assert(E &&
"Expected a non-null expression");
4466 *std::next(KmpDependInfoRD->field_begin(),
4467 static_cast<unsigned int>(RTLDependInfoFields::BaseAddr)));
4471 Base, *std::next(KmpDependInfoRD->field_begin(),
4472 static_cast<unsigned int>(RTLDependInfoFields::Len)));
4478 *std::next(KmpDependInfoRD->field_begin(),
4479 static_cast<unsigned int>(RTLDependInfoFields::Flags)));
4481 llvm::ConstantInt::get(LLVMFlagsTy,
static_cast<unsigned int>(DepKind)),
4483 if (
unsigned *P = dyn_cast<unsigned *>(Pos)) {
4488 Idx = CGF.
Builder.CreateNUWAdd(Idx,
4489 llvm::ConstantInt::get(Idx->getType(), 1));
4498 assert(
Data.DepKind == OMPC_DEPEND_depobj &&
4499 "Expected depobj dependency kind.");
4504 OMPIteratorGeneratorScope IteratorScope(
4505 CGF, cast_or_null<OMPIteratorExpr>(
4506 Data.IteratorExpr ?
Data.IteratorExpr->IgnoreParenImpCasts()
4508 for (
const Expr *E :
Data.DepExprs) {
4509 llvm::Value *NumDeps;
4512 std::tie(NumDeps,
Base) =
4516 C.getUIntPtrType());
4520 llvm::Value *Add = CGF.
Builder.CreateNUWAdd(PrevVal, NumDeps);
4522 SizeLVals.push_back(NumLVal);
4525 for (
unsigned I = 0, E = SizeLVals.size(); I < E; ++I) {
4528 Sizes.push_back(Size);
4538 assert(
Data.DepKind == OMPC_DEPEND_depobj &&
4539 "Expected depobj dependency kind.");
4542 OMPIteratorGeneratorScope IteratorScope(
4543 CGF, cast_or_null<OMPIteratorExpr>(
4544 Data.IteratorExpr ?
Data.IteratorExpr->IgnoreParenImpCasts()
4546 for (
const Expr *E :
Data.DepExprs) {
4547 llvm::Value *NumDeps;
4550 std::tie(NumDeps,
Base) =
4554 llvm::Value *Size = CGF.
Builder.CreateNUWMul(
4563 llvm::Value *Add = CGF.
Builder.CreateNUWAdd(Pos, NumDeps);
4579 llvm::Value *NumOfElements =
nullptr;
4580 unsigned NumDependencies = std::accumulate(
4581 Dependencies.begin(), Dependencies.end(), 0,
4583 return D.DepKind == OMPC_DEPEND_depobj
4585 : (V + (D.IteratorExpr ? 0 : D.DepExprs.size()));
4589 bool HasDepobjDeps =
false;
4590 bool HasRegularWithIterators =
false;
4591 llvm::Value *NumOfDepobjElements = llvm::ConstantInt::get(CGF.
IntPtrTy, 0);
4592 llvm::Value *NumOfRegularWithIterators =
4593 llvm::ConstantInt::get(CGF.
IntPtrTy, 0);
4597 if (D.
DepKind == OMPC_DEPEND_depobj) {
4600 for (llvm::Value *Size : Sizes) {
4601 NumOfDepobjElements =
4602 CGF.
Builder.CreateNUWAdd(NumOfDepobjElements, Size);
4604 HasDepobjDeps =
true;
4609 if (
const auto *IE = cast_or_null<OMPIteratorExpr>(D.
IteratorExpr)) {
4610 llvm::Value *ClauseIteratorSpace =
4611 llvm::ConstantInt::get(CGF.
IntPtrTy, 1);
4615 ClauseIteratorSpace = CGF.
Builder.CreateNUWMul(Sz, ClauseIteratorSpace);
4617 llvm::Value *NumClauseDeps = CGF.
Builder.CreateNUWMul(
4618 ClauseIteratorSpace,
4620 NumOfRegularWithIterators =
4621 CGF.
Builder.CreateNUWAdd(NumOfRegularWithIterators, NumClauseDeps);
4622 HasRegularWithIterators =
true;
4628 if (HasDepobjDeps || HasRegularWithIterators) {
4629 NumOfElements = llvm::ConstantInt::get(
CGM.IntPtrTy, NumDependencies,
4631 if (HasDepobjDeps) {
4633 CGF.
Builder.CreateNUWAdd(NumOfDepobjElements, NumOfElements);
4635 if (HasRegularWithIterators) {
4637 CGF.
Builder.CreateNUWAdd(NumOfRegularWithIterators, NumOfElements);
4640 Loc,
C.getIntTypeForBitwidth(64, 0),
4644 KmpDependInfoArrayTy =
4653 NumOfElements = CGF.
Builder.CreateIntCast(NumOfElements, CGF.
Int32Ty,
4656 KmpDependInfoArrayTy =
C.getConstantArrayType(
4662 NumOfElements = llvm::ConstantInt::get(
CGM.Int32Ty, NumDependencies,
4667 if (Dep.DepKind == OMPC_DEPEND_depobj || Dep.IteratorExpr)
4677 if (Dep.DepKind == OMPC_DEPEND_depobj || !Dep.IteratorExpr)
4682 if (HasDepobjDeps) {
4684 if (Dep.DepKind != OMPC_DEPEND_depobj)
4691 return std::make_pair(NumOfElements, DependenciesArray);
4702 unsigned NumDependencies = Dependencies.
DepExprs.size();
4712 llvm::Value *NumDepsVal;
4714 if (
const auto *IE =
4715 cast_or_null<OMPIteratorExpr>(Dependencies.
IteratorExpr)) {
4716 NumDepsVal = llvm::ConstantInt::get(CGF.
SizeTy, 1);
4720 NumDepsVal = CGF.
Builder.CreateNUWMul(NumDepsVal, Sz);
4722 Size = CGF.
Builder.CreateNUWAdd(llvm::ConstantInt::get(CGF.
SizeTy, 1),
4726 llvm::Value *RecSize =
CGM.getSize(SizeInBytes);
4727 Size = CGF.
Builder.CreateNUWMul(Size, RecSize);
4731 QualType KmpDependInfoArrayTy =
C.getConstantArrayType(
4734 CharUnits Sz =
C.getTypeSizeInChars(KmpDependInfoArrayTy);
4736 NumDepsVal = llvm::ConstantInt::get(CGF.
IntPtrTy, NumDependencies);
4741 llvm::Value *Allocator = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
4742 llvm::Value *Args[] = {ThreadID, Size, Allocator};
4746 CGM.getModule(), OMPRTL___kmpc_alloc),
4747 Args,
".dep.arr.addr");
4751 DependenciesArray =
Address(
Addr, KmpDependInfoLlvmTy, Align);
4757 *std::next(KmpDependInfoRD->field_begin(),
4758 static_cast<unsigned int>(RTLDependInfoFields::BaseAddr)));
4760 llvm::PointerUnion<unsigned *, LValue *> Pos;
4777 return DependenciesArray;
4792 Addr.getElementType(),
Addr.emitRawPointer(CGF),
4793 llvm::ConstantInt::get(CGF.
IntPtrTy, -1,
true));
4798 llvm::Value *Allocator = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
4799 llvm::Value *Args[] = {ThreadID, DepObjAddr, Allocator};
4803 CGM.getModule(), OMPRTL___kmpc_free),
4815 llvm::Value *NumDeps;
4826 llvm::BasicBlock *EntryBB = CGF.
Builder.GetInsertBlock();
4828 llvm::PHINode *ElementPHI =
4833 Base.getTBAAInfo());
4837 Base, *std::next(KmpDependInfoRD->field_begin(),
4838 static_cast<unsigned int>(RTLDependInfoFields::Flags)));
4840 llvm::ConstantInt::get(LLVMFlagsTy,
static_cast<unsigned int>(DepKind)),
4844 llvm::Value *ElementNext =
4847 ElementPHI->addIncoming(ElementNext, CGF.
Builder.GetInsertBlock());
4848 llvm::Value *IsEmpty =
4849 CGF.
Builder.CreateICmpEQ(ElementNext, End,
"omp.isempty");
4850 CGF.
Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
4857 llvm::Function *TaskFunction,
4866 llvm::Value *NewTask =
Result.NewTask;
4867 llvm::Function *TaskEntry =
Result.TaskEntry;
4868 llvm::Value *NewTaskNewTaskTTy =
Result.NewTaskNewTaskTTy;
4873 llvm::Value *NumOfElements;
4874 std::tie(NumOfElements, DependenciesArray) =
4885 llvm::Value *TaskArgs[] = { UpLoc, ThreadID, NewTask };
4886 llvm::Value *DepTaskArgs[7];
4887 if (!
Data.Dependences.empty()) {
4888 DepTaskArgs[0] = UpLoc;
4889 DepTaskArgs[1] = ThreadID;
4890 DepTaskArgs[2] = NewTask;
4891 DepTaskArgs[3] = NumOfElements;
4893 DepTaskArgs[5] = CGF.
Builder.getInt32(0);
4894 DepTaskArgs[6] = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
4896 auto &&ThenCodeGen = [
this, &
Data, TDBase, KmpTaskTQTyRD, &TaskArgs,
4899 auto PartIdFI = std::next(KmpTaskTQTyRD->
field_begin(), KmpTaskTPartId);
4903 if (!
Data.Dependences.empty()) {
4906 CGM.getModule(), OMPRTL___kmpc_omp_task_with_deps),
4910 CGM.getModule(), OMPRTL___kmpc_omp_task),
4916 Region->emitUntiedSwitch(CGF);
4919 llvm::Value *DepWaitTaskArgs[7];
4920 if (!
Data.Dependences.empty()) {
4921 DepWaitTaskArgs[0] = UpLoc;
4922 DepWaitTaskArgs[1] = ThreadID;
4923 DepWaitTaskArgs[2] = NumOfElements;
4925 DepWaitTaskArgs[4] = CGF.
Builder.getInt32(0);
4926 DepWaitTaskArgs[5] = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
4927 DepWaitTaskArgs[6] =
4928 llvm::ConstantInt::get(CGF.
Int32Ty,
Data.HasNowaitClause);
4930 auto &M =
CGM.getModule();
4931 auto &&ElseCodeGen = [
this, &M, &TaskArgs, ThreadID, NewTaskNewTaskTTy,
4932 TaskEntry, &
Data, &DepWaitTaskArgs,
4939 if (!
Data.Dependences.empty())
4941 M, OMPRTL___kmpc_omp_taskwait_deps_51),
4944 auto &&
CodeGen = [TaskEntry, ThreadID, NewTaskNewTaskTTy,
4947 llvm::Value *OutlinedFnArgs[] = {ThreadID, NewTaskNewTaskTTy};
4948 CGF.CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, Loc, TaskEntry,
4957 CommonActionTy Action(
OMPBuilder.getOrCreateRuntimeFunction(
4958 M, OMPRTL___kmpc_omp_task_begin_if0),
4961 M, OMPRTL___kmpc_omp_task_complete_if0),
4977 llvm::Function *TaskFunction,
4997 IfVal = llvm::ConstantInt::getSigned(CGF.
IntTy, 1);
5002 *std::next(
Result.KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound));
5009 *std::next(
Result.KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound));
5016 *std::next(
Result.KmpTaskTQTyRD->field_begin(), KmpTaskTStride));
5024 *std::next(
Result.KmpTaskTQTyRD->field_begin(), KmpTaskTReductions));
5025 if (
Data.Reductions) {
5031 enum { NoSchedule = 0, Grainsize = 1, NumTasks = 2 };
5040 llvm::ConstantInt::getSigned(
5042 llvm::ConstantInt::getSigned(
5044 ?
Data.Schedule.getInt() ? NumTasks : Grainsize
5046 Data.Schedule.getPointer()
5049 : llvm::ConstantInt::get(CGF.
Int64Ty, 0)};
5050 if (
Data.HasModifier)
5051 TaskArgs.push_back(llvm::ConstantInt::get(CGF.
Int32Ty, 1));
5053 TaskArgs.push_back(
Result.TaskDupFn
5056 : llvm::ConstantPointerNull::get(CGF.
VoidPtrTy));
5058 CGM.getModule(),
Data.HasModifier
5059 ? OMPRTL___kmpc_taskloop_5
5060 : OMPRTL___kmpc_taskloop),
5077 const Expr *,
const Expr *)> &RedOpGen,
5078 const Expr *XExpr =
nullptr,
const Expr *EExpr =
nullptr,
5079 const Expr *UpExpr =
nullptr) {
5087 llvm::Value *NumElements = CGF.
emitArrayLength(ArrayTy, ElementTy, LHSAddr);
5092 llvm::Value *LHSEnd =
5097 llvm::Value *IsEmpty =
5098 CGF.
Builder.CreateICmpEQ(LHSBegin, LHSEnd,
"omp.arraycpy.isempty");
5099 CGF.
Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
5102 llvm::BasicBlock *EntryBB = CGF.
Builder.GetInsertBlock();
5107 llvm::PHINode *RHSElementPHI = CGF.
Builder.CreatePHI(
5108 RHSBegin->getType(), 2,
"omp.arraycpy.srcElementPast");
5109 RHSElementPHI->addIncoming(RHSBegin, EntryBB);
5114 llvm::PHINode *LHSElementPHI = CGF.
Builder.CreatePHI(
5115 LHSBegin->getType(), 2,
"omp.arraycpy.destElementPast");
5116 LHSElementPHI->addIncoming(LHSBegin, EntryBB);
5123 Scope.addPrivate(LHSVar, LHSElementCurrent);
5124 Scope.addPrivate(RHSVar, RHSElementCurrent);
5126 RedOpGen(CGF, XExpr, EExpr, UpExpr);
5127 Scope.ForceCleanup();
5130 llvm::Value *LHSElementNext = CGF.
Builder.CreateConstGEP1_32(
5132 "omp.arraycpy.dest.element");
5133 llvm::Value *RHSElementNext = CGF.
Builder.CreateConstGEP1_32(
5135 "omp.arraycpy.src.element");
5138 CGF.
Builder.CreateICmpEQ(LHSElementNext, LHSEnd,
"omp.arraycpy.done");
5139 CGF.
Builder.CreateCondBr(Done, DoneBB, BodyBB);
5140 LHSElementPHI->addIncoming(LHSElementNext, CGF.
Builder.GetInsertBlock());
5141 RHSElementPHI->addIncoming(RHSElementNext, CGF.
Builder.GetInsertBlock());
5151 const Expr *ReductionOp) {
5152 if (
const auto *CE = dyn_cast<CallExpr>(ReductionOp))
5153 if (
const auto *OVE = dyn_cast<OpaqueValueExpr>(CE->getCallee()))
5154 if (
const auto *DRE =
5155 dyn_cast<DeclRefExpr>(OVE->getSourceExpr()->IgnoreImpCasts()))
5156 if (
const auto *DRD =
5157 dyn_cast<OMPDeclareReductionDecl>(DRE->getDecl())) {
5158 std::pair<llvm::Function *, llvm::Function *>
Reduction =
5169 StringRef ReducerName,
SourceLocation Loc, llvm::Type *ArgsElemType,
5183 CGM.getTypes().arrangeBuiltinFunctionDeclaration(
C.VoidTy, Args);
5185 auto *Fn = llvm::Function::Create(
CGM.getTypes().GetFunctionType(CGFI),
5186 llvm::GlobalValue::InternalLinkage, Name,
5189 if (!
CGM.getCodeGenOpts().SampleProfileFile.empty())
5190 Fn->addFnAttr(
"sample-profile-suffix-elision-policy",
"selected");
5191 Fn->setDoesNotRecurse();
5210 const auto *IPriv =
Privates.begin();
5212 for (
unsigned I = 0, E = ReductionOps.size(); I < E; ++I, ++IPriv, ++Idx) {
5213 const auto *RHSVar =
5216 const auto *LHSVar =
5219 QualType PrivTy = (*IPriv)->getType();
5235 const auto *ILHS = LHSExprs.begin();
5236 const auto *IRHS = RHSExprs.begin();
5237 for (
const Expr *E : ReductionOps) {
5238 if ((*IPriv)->getType()->isArrayType()) {
5243 CGF, (*IPriv)->getType(), LHSVar, RHSVar,
5245 emitReductionCombiner(CGF, E);
5255 Scope.ForceCleanup();
5261 const Expr *ReductionOp,
5262 const Expr *PrivateRef,
5270 CGF, PrivateRef->
getType(), LHSVar, RHSVar,
5272 emitReductionCombiner(CGF, ReductionOp);
5281 llvm::StringRef Prefix,
const Expr *Ref);
5285 const Expr *LHSExprs,
const Expr *RHSExprs,
const Expr *ReductionOps) {
5312 std::string ReductionVarNameStr;
5313 if (
const auto *DRE = dyn_cast<DeclRefExpr>(
Privates->IgnoreParenCasts()))
5314 ReductionVarNameStr =
5317 ReductionVarNameStr =
"unnamed_priv_var";
5320 std::string SharedName =
5321 CGM.getOpenMPRuntime().getName({
"internal_pivate_", ReductionVarNameStr});
5322 llvm::GlobalVariable *SharedVar =
OMPBuilder.getOrCreateInternalVariable(
5323 LLVMType,
".omp.reduction." + SharedName);
5325 SharedVar->setAlignment(
5333 llvm::Value *BarrierArgs[] = {BarrierLoc, ThreadId};
5338 llvm::Value *IsWorker = CGF.
Builder.CreateICmpEQ(
5339 ThreadId, llvm::ConstantInt::get(ThreadId->getType(), 0));
5340 CGF.
Builder.CreateCondBr(IsWorker, InitBB, InitEndBB);
5344 auto EmitSharedInit = [&]() {
5347 std::pair<llvm::Function *, llvm::Function *> FnPair =
5349 llvm::Function *InitializerFn = FnPair.second;
5350 if (InitializerFn) {
5351 if (
const auto *CE =
5352 dyn_cast<CallExpr>(UDRInitExpr->IgnoreParenImpCasts())) {
5359 LocalScope.addPrivate(OutVD, SharedResult);
5361 (void)LocalScope.Privatize();
5362 if (
const auto *OVE = dyn_cast<OpaqueValueExpr>(
5363 CE->getCallee()->IgnoreParenImpCasts())) {
5389 if (
const auto *DRE = dyn_cast<DeclRefExpr>(
Privates)) {
5390 if (
const auto *VD = dyn_cast<VarDecl>(DRE->getDecl())) {
5401 CGF.
Builder.CreateBr(InitEndBB);
5405 CGM.getModule(), OMPRTL___kmpc_barrier),
5408 const Expr *ReductionOp = ReductionOps;
5413 auto EmitCriticalReduction = [&](
auto ReductionGen) {
5414 std::string CriticalName =
getName({
"reduction_critical"});
5422 std::pair<llvm::Function *, llvm::Function *> FnPair =
5425 if (
const auto *CE = dyn_cast<CallExpr>(ReductionOp)) {
5437 (void)LocalScope.Privatize();
5442 EmitCriticalReduction(ReductionGen);
5447 if (
const auto *Cleanup = dyn_cast<ExprWithCleanups>(ReductionClauseExpr))
5450 const Expr *AssignRHS =
nullptr;
5451 if (
const auto *BinOp = dyn_cast<BinaryOperator>(ReductionClauseExpr)) {
5452 if (BinOp->getOpcode() == BO_Assign)
5453 AssignRHS = BinOp->getRHS();
5454 }
else if (
const auto *OpCall =
5455 dyn_cast<CXXOperatorCallExpr>(ReductionClauseExpr)) {
5456 if (OpCall->getOperator() == OO_Equal)
5457 AssignRHS = OpCall->getArg(1);
5461 "Private Variable Reduction : Invalid ReductionOp expression");
5466 const auto *OmpOutDRE =
5468 const auto *OmpInDRE =
5471 OmpOutDRE && OmpInDRE &&
5472 "Private Variable Reduction : LHSExpr/RHSExpr must be DeclRefExprs");
5476 LocalScope.addPrivate(OmpOutVD, SharedLV.
getAddress());
5477 LocalScope.addPrivate(OmpInVD, LHSLV.
getAddress());
5478 (void)LocalScope.Privatize();
5482 EmitCriticalReduction(ReductionGen);
5486 CGM.getModule(), OMPRTL___kmpc_barrier),
5492 llvm::Value *FinalResultVal =
nullptr;
5496 FinalResultAddr = SharedResult;
5510 CGM.getModule(), OMPRTL___kmpc_barrier),
5521 EmitCriticalReduction(OriginalListCombiner);
5573 if (SimpleReduction) {
5575 const auto *IPriv = OrgPrivates.begin();
5576 const auto *ILHS = OrgLHSExprs.begin();
5577 const auto *IRHS = OrgRHSExprs.begin();
5578 for (
const Expr *E : OrgReductionOps) {
5591 FilteredRHSExprs, FilteredReductionOps;
5592 for (
unsigned I : llvm::seq<unsigned>(
5593 std::min(OrgReductionOps.size(), OrgLHSExprs.size()))) {
5595 FilteredPrivates.emplace_back(OrgPrivates[I]);
5596 FilteredLHSExprs.emplace_back(OrgLHSExprs[I]);
5597 FilteredRHSExprs.emplace_back(OrgRHSExprs[I]);
5598 FilteredReductionOps.emplace_back(OrgReductionOps[I]);
5610 auto Size = RHSExprs.size();
5616 llvm::APInt ArraySize(32, Size);
5617 QualType ReductionArrayTy =
C.getConstantArrayType(
5621 CGF.
CreateMemTemp(ReductionArrayTy,
".omp.reduction.red_list");
5622 const auto *IPriv =
Privates.begin();
5624 for (
unsigned I = 0, E = RHSExprs.size(); I < E; ++I, ++IPriv, ++Idx) {
5630 if ((*IPriv)->getType()->isVariablyModifiedType()) {
5634 llvm::Value *Size = CGF.
Builder.CreateIntCast(
5647 Privates, LHSExprs, RHSExprs, ReductionOps);
5650 std::string Name =
getName({
"reduction"});
5657 llvm::Value *ReductionArrayTySize = CGF.
getTypeSize(ReductionArrayTy);
5660 llvm::Value *Args[] = {
5663 CGF.
Builder.getInt32(RHSExprs.size()),
5664 ReductionArrayTySize,
5672 WithNowait ? OMPRTL___kmpc_reduce_nowait : OMPRTL___kmpc_reduce),
5676 llvm::BasicBlock *DefaultBB = CGF.
createBasicBlock(
".omp.reduction.default");
5677 llvm::SwitchInst *SwInst =
5678 CGF.
Builder.CreateSwitch(Res, DefaultBB, 2);
5687 SwInst->addCase(CGF.
Builder.getInt32(1), Case1BB);
5691 llvm::Value *EndArgs[] = {
5699 const auto *IPriv =
Privates.begin();
5700 const auto *ILHS = LHSExprs.begin();
5701 const auto *IRHS = RHSExprs.begin();
5702 for (
const Expr *E : ReductionOps) {
5711 CommonActionTy Action(
5714 CGM.getModule(), WithNowait ? OMPRTL___kmpc_end_reduce_nowait
5715 : OMPRTL___kmpc_end_reduce),
5728 SwInst->addCase(CGF.
Builder.getInt32(2), Case2BB);
5731 auto &&AtomicCodeGen = [Loc,
Privates, LHSExprs, RHSExprs, ReductionOps](
5733 const auto *ILHS = LHSExprs.begin();
5734 const auto *IRHS = RHSExprs.begin();
5735 const auto *IPriv =
Privates.begin();
5736 for (
const Expr *E : ReductionOps) {
5737 const Expr *XExpr =
nullptr;
5738 const Expr *EExpr =
nullptr;
5739 const Expr *UpExpr =
nullptr;
5741 if (
const auto *BO = dyn_cast<BinaryOperator>(E)) {
5742 if (BO->getOpcode() == BO_Assign) {
5743 XExpr = BO->getLHS();
5744 UpExpr = BO->getRHS();
5748 const Expr *RHSExpr = UpExpr;
5751 if (
const auto *ACO = dyn_cast<AbstractConditionalOperator>(
5755 RHSExpr = ACO->getCond();
5757 if (
const auto *BORHS =
5759 EExpr = BORHS->getRHS();
5760 BO = BORHS->getOpcode();
5765 auto &&AtomicRedGen = [BO, VD,
5767 const Expr *EExpr,
const Expr *UpExpr) {
5768 LValue X = CGF.EmitLValue(XExpr);
5771 E = CGF.EmitAnyExpr(EExpr);
5772 CGF.EmitOMPAtomicSimpleUpdateExpr(
5774 llvm::AtomicOrdering::Monotonic, Loc,
5775 [&CGF, UpExpr, VD, Loc](
RValue XRValue) {
5777 Address LHSTemp = CGF.CreateMemTemp(VD->getType());
5778 CGF.emitOMPSimpleStore(
5779 CGF.MakeAddrLValue(LHSTemp, VD->
getType()), XRValue,
5780 VD->getType().getNonReferenceType(), Loc);
5783 return CGF.EmitAnyExpr(UpExpr);
5786 if ((*IPriv)->getType()->isArrayType()) {
5788 const auto *RHSVar =
5791 AtomicRedGen, XExpr, EExpr, UpExpr);
5794 AtomicRedGen(CGF, XExpr, EExpr, UpExpr);
5801 std::string Name = RT.
getName({
"atomic_reduction"});
5810 if ((*IPriv)->getType()->isArrayType()) {
5811 const auto *LHSVar =
5813 const auto *RHSVar =
5818 CritRedGen(CGF,
nullptr,
nullptr,
nullptr);
5829 llvm::Value *EndArgs[] = {
5834 CommonActionTy Action(
nullptr, {},
5836 CGM.getModule(), OMPRTL___kmpc_end_reduce),
5846 assert(OrgLHSExprs.size() == OrgPrivates.size() &&
5847 "PrivateVarReduction: Privates size mismatch");
5848 assert(OrgLHSExprs.size() == OrgReductionOps.size() &&
5849 "PrivateVarReduction: ReductionOps size mismatch");
5850 for (
unsigned I : llvm::seq<unsigned>(
5851 std::min(OrgReductionOps.size(), OrgLHSExprs.size()))) {
5854 OrgRHSExprs[I], OrgReductionOps[I]);
5863 llvm::raw_svector_ostream Out(Buffer);
5868 if (
const auto *BD = dyn_cast<BindingDecl>(DRE->getDecl())) {
5878 Out << Prefix << Name <<
"_"
5880 return std::string(Out.str());
5904 Args.emplace_back(Param);
5905 Args.emplace_back(ParamOrig);
5906 const auto &FnInfo =
5910 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
5914 Fn->addFnAttr(
"sample-profile-suffix-elision-policy",
"selected");
5915 Fn->setDoesNotRecurse();
5922 llvm::Value *Size =
nullptr;
5965 const Expr *ReductionOp,
5967 const Expr *PrivateRef) {
5978 Args.emplace_back(ParamInOut);
5979 Args.emplace_back(ParamIn);
5980 const auto &FnInfo =
5984 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
5988 Fn->addFnAttr(
"sample-profile-suffix-elision-policy",
"selected");
5989 Fn->setDoesNotRecurse();
5992 llvm::Value *Size =
nullptr;
6013 C.getPointerType(LHSVD->getType())->castAs<
PointerType>()));
6020 C.getPointerType(RHSVD->getType())->castAs<
PointerType>()));
6050 Args.emplace_back(Param);
6051 const auto &FnInfo =
6055 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
6059 Fn->addFnAttr(
"sample-profile-suffix-elision-policy",
"selected");
6060 Fn->setDoesNotRecurse();
6065 llvm::Value *Size =
nullptr;
6100 RecordDecl *RD =
C.buildImplicitRecord(
"kmp_taskred_input_t");
6109 C, RD,
C.getIntTypeForBitwidth(32,
false));
6112 unsigned Size =
Data.ReductionVars.size();
6113 llvm::APInt ArraySize(64, Size);
6115 C.getConstantArrayType(RDType, ArraySize,
nullptr,
6120 Data.ReductionCopies,
Data.ReductionOps);
6121 for (
unsigned Cnt = 0; Cnt < Size; ++Cnt) {
6123 llvm::Value *Idxs[] = {llvm::ConstantInt::get(
CGM.SizeTy, 0),
6124 llvm::ConstantInt::get(
CGM.SizeTy, Cnt)};
6140 llvm::Value *SizeValInChars;
6141 llvm::Value *SizeVal;
6142 std::tie(SizeValInChars, SizeVal) = RCG.
getSizes(Cnt);
6148 bool DelayedCreation = !!SizeVal;
6149 SizeValInChars = CGF.
Builder.CreateIntCast(SizeValInChars,
CGM.SizeTy,
6160 llvm::Value *FiniAddr =
6161 Fini ? Fini : llvm::ConstantPointerNull::get(
CGM.VoidPtrTy);
6166 CGM, Loc, RCG, Cnt,
Data.ReductionOps[Cnt], LHSExprs[Cnt],
6167 RHSExprs[Cnt],
Data.ReductionCopies[Cnt]);
6171 if (DelayedCreation) {
6173 llvm::ConstantInt::get(
CGM.Int32Ty, 1,
true),
6178 if (
Data.IsReductionWithTaskMod) {
6184 llvm::Value *Args[] = {
6186 llvm::ConstantInt::get(
CGM.IntTy,
Data.IsWorksharingReduction ? 1 : 0,
6188 llvm::ConstantInt::get(
CGM.IntTy, Size,
true),
6193 CGM.getModule(), OMPRTL___kmpc_taskred_modifier_init),
6197 llvm::Value *Args[] = {
6200 llvm::ConstantInt::get(
CGM.IntTy, Size,
true),
6204 CGM.getModule(), OMPRTL___kmpc_taskred_init),
6210 bool IsWorksharingReduction) {
6216 llvm::Value *Args[] = {IdentTLoc, GTid,
6217 llvm::ConstantInt::get(
CGM.IntTy,
6218 IsWorksharingReduction ? 1 : 0,
6222 CGM.getModule(), OMPRTL___kmpc_task_reduction_modifier_fini),
6234 llvm::Value *SizeVal = CGF.
Builder.CreateIntCast(Sizes.second,
CGM.SizeTy,
6237 CGF,
CGM.getContext().getSizeType(),
6245 llvm::Value *ReductionsPtr,
6258 CGM.getModule(), OMPRTL___kmpc_task_reduction_get_th_data),
6274 auto &M =
CGM.getModule();
6276 llvm::Value *NumOfElements;
6277 std::tie(NumOfElements, DependenciesArray) =
6279 if (!
Data.Dependences.empty()) {
6280 llvm::Value *DepWaitTaskArgs[7];
6281 DepWaitTaskArgs[0] = UpLoc;
6282 DepWaitTaskArgs[1] = ThreadID;
6283 DepWaitTaskArgs[2] = NumOfElements;
6285 DepWaitTaskArgs[4] = CGF.
Builder.getInt32(0);
6286 DepWaitTaskArgs[5] = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
6287 DepWaitTaskArgs[6] =
6288 llvm::ConstantInt::get(CGF.
Int32Ty,
Data.HasNowaitClause);
6297 M, OMPRTL___kmpc_omp_taskwait_deps_51),
6304 llvm::Value *Args[] = {UpLoc, ThreadID};
6307 OMPBuilder.getOrCreateRuntimeFunction(M, OMPRTL___kmpc_omp_taskwait),
6312 if (
auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.
CapturedStmtInfo))
6313 Region->emitUntiedSwitch(CGF);
6322 InlinedOpenMPRegionRAII Region(CGF,
CodeGen, InnerKind, HasCancel,
6323 InnerKind != OMPD_critical &&
6324 InnerKind != OMPD_master &&
6325 InnerKind != OMPD_masked);
6340 RTCancelKind CancelKind = CancelNoreq;
6341 if (CancelRegion == OMPD_parallel)
6342 CancelKind = CancelParallel;
6343 else if (CancelRegion == OMPD_for)
6344 CancelKind = CancelLoop;
6345 else if (CancelRegion == OMPD_sections)
6346 CancelKind = CancelSections;
6348 assert(CancelRegion == OMPD_taskgroup);
6349 CancelKind = CancelTaskgroup;
6361 if (
auto *OMPRegionInfo =
6365 if (CancelRegion == OMPD_taskgroup || OMPRegionInfo->hasCancel()) {
6366 llvm::Value *Args[] = {
6372 CGM.getModule(), OMPRTL___kmpc_cancellationpoint),
6381 CGF.
Builder.CreateCondBr(
Cmp, ExitBB, ContBB);
6383 if (CancelRegion == OMPD_parallel)
6401 auto &M =
CGM.getModule();
6402 if (
auto *OMPRegionInfo =
6404 auto &&ThenGen = [
this, &M, Loc, CancelRegion,
6407 llvm::Value *Args[] = {
6411 llvm::Value *
Result = CGF.EmitRuntimeCall(
6412 OMPBuilder.getOrCreateRuntimeFunction(M, OMPRTL___kmpc_cancel), Args);
6417 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(
".cancel.exit");
6418 llvm::BasicBlock *ContBB = CGF.createBasicBlock(
".cancel.continue");
6419 llvm::Value *
Cmp = CGF.Builder.CreateIsNotNull(
Result);
6420 CGF.Builder.CreateCondBr(
Cmp, ExitBB, ContBB);
6421 CGF.EmitBlock(ExitBB);
6422 if (CancelRegion == OMPD_parallel)
6426 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind());
6427 CGF.EmitBranchThroughCleanup(CancelDest);
6428 CGF.EmitBlock(ContBB,
true);
6445 bool IsOffloadEntry;
6448 OMPUsesAllocatorsActionTy(
6449 ArrayRef<std::pair<const Expr *, const Expr *>> Allocators,
6451 : Allocators(Allocators), D(D), IsOffloadEntry(IsOffloadEntry) {}
6455 for (
const auto &AllocatorData : Allocators) {
6457 CGF, AllocatorData.first, AllocatorData.second);
6466 void Exit(CodeGenFunction &CGF)
override {
6469 for (
const auto &AllocatorData : Allocators) {
6471 AllocatorData.first);
6479 llvm::OpenMPIRBuilder::TargetKernelDefaultAttrs Attrs;
6480 Attrs.ExecFlags = llvm::omp::OMPTgtExecModeFlags::OMP_TGT_EXEC_MODE_GENERIC;
6487 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
6489 assert(!ParentName.empty() &&
"Invalid target entry parent name!");
6493 for (
unsigned I = 0, E =
C->getNumberOfAllocators(); I < E; ++I) {
6500 OMPUsesAllocatorsActionTy UsesAllocatorAction(Allocators, D, IsOffloadEntry);
6501 CodeGen.setAction(UsesAllocatorAction);
6507 const Expr *Allocator,
6508 const Expr *AllocatorTraits) {
6510 ThreadId = CGF.
Builder.CreateIntCast(ThreadId, CGF.
IntTy,
true);
6512 llvm::Value *MemSpaceHandle = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
6513 llvm::Value *NumTraits = llvm::ConstantInt::get(
6517 .getLimitedValue());
6524 llvm::Value *Traits =
Addr.emitRawPointer(CGF);
6526 llvm::Value *AllocatorVal =
6528 CGM.getModule(), OMPRTL___kmpc_init_allocator),
6529 {ThreadId, MemSpaceHandle, NumTraits, Traits});
6541 const Expr *Allocator) {
6543 ThreadId = CGF.
Builder.CreateIntCast(ThreadId, CGF.
IntTy,
true);
6545 llvm::Value *AllocatorVal =
6552 OMPRTL___kmpc_destroy_allocator),
6553 {ThreadId, AllocatorVal});
6558 llvm::OpenMPIRBuilder::TargetKernelDefaultAttrs &Attrs) {
6559 assert(Attrs.MaxTeams.size() == 1 && Attrs.MaxThreads.size() == 1 &&
6560 "invalid default attrs structure");
6561 int32_t &MaxTeamsVal = Attrs.MaxTeams.front();
6562 int32_t &MaxThreadsVal = Attrs.MaxThreads.front();
6570 for (
auto *A :
C->getAttrs()) {
6571 int32_t AttrMinThreadsVal = 1, AttrMaxThreadsVal = -1;
6572 int32_t AttrMinBlocksVal = 1, AttrMaxBlocksVal = -1;
6573 if (
auto *
Attr = dyn_cast<CUDALaunchBoundsAttr>(A))
6574 CGM.handleCUDALaunchBoundsAttr(
nullptr,
Attr, &AttrMaxThreadsVal,
6575 &AttrMinBlocksVal, &AttrMaxBlocksVal);
6576 else if (
auto *
Attr = dyn_cast<AMDGPUFlatWorkGroupSizeAttr>(A))
6577 CGM.handleAMDGPUFlatWorkGroupSizeAttr(
6578 nullptr,
Attr,
nullptr, &AttrMinThreadsVal,
6579 &AttrMaxThreadsVal);
6583 Attrs.MinThreads.front() =
6584 std::max(Attrs.MinThreads.front(), AttrMinThreadsVal);
6585 if (AttrMaxThreadsVal > 0)
6586 MaxThreadsVal = MaxThreadsVal > 0
6587 ? std::min(MaxThreadsVal, AttrMaxThreadsVal)
6588 : AttrMaxThreadsVal;
6589 Attrs.MinTeams.front() =
6590 std::max(Attrs.MinTeams.front(), AttrMinBlocksVal);
6591 if (AttrMaxBlocksVal > 0)
6592 MaxTeamsVal = MaxTeamsVal > 0 ? std::min(MaxTeamsVal, AttrMaxBlocksVal)
6600 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
6603 llvm::TargetRegionEntryInfo EntryInfo =
6607 llvm::OpenMPIRBuilder::FunctionGenCallback &&GenerateOutlinedFunction =
6608 [&CGF, &D, &
CodeGen,
this](StringRef EntryFnName) {
6609 const CapturedStmt &CS = *D.getCapturedStmt(OMPD_target);
6611 CGOpenMPTargetRegionInfo CGInfo(CS,
CodeGen, EntryFnName);
6613 if (
CGM.getLangOpts().OpenMPIsTargetDevice && !
isGPU())
6618 cantFail(
OMPBuilder.emitTargetRegionFunction(
6619 EntryInfo, GenerateOutlinedFunction, IsOffloadEntry, OutlinedFn,
6627 OutlinedFn->setDoesNotRecurse();
6629 CGM.getTargetCodeGenInfo().setTargetAttributes(
nullptr, OutlinedFn,
CGM);
6632 for (
auto *A :
C->getAttrs()) {
6633 if (
auto *
Attr = dyn_cast<AMDGPUWavesPerEUAttr>(A))
6634 CGM.handleAMDGPUWavesPerEUAttr(OutlinedFn,
Attr);
6653 while (
const auto *
C = dyn_cast_or_null<CompoundStmt>(Child)) {
6655 for (
const Stmt *S :
C->body()) {
6656 if (
const auto *E = dyn_cast<Expr>(S)) {
6665 if (
const auto *DS = dyn_cast<DeclStmt>(S)) {
6666 if (llvm::all_of(DS->decls(), [](
const Decl *D) {
6667 if (isa<EmptyDecl>(D) || isa<DeclContext>(D) ||
6668 isa<TypeDecl>(D) || isa<PragmaCommentDecl>(D) ||
6669 isa<PragmaDetectMismatchDecl>(D) || isa<UsingDecl>(D) ||
6670 isa<UsingDirectiveDecl>(D) ||
6671 isa<OMPDeclareReductionDecl>(D) ||
6672 isa<OMPThreadPrivateDecl>(D) || isa<OMPAllocateDecl>(D))
6674 const auto *VD = dyn_cast<VarDecl>(D);
6677 return VD->hasGlobalStorage() || !VD->isUsed();
6687 Child = Child->IgnoreContainers();
6694 int32_t &MaxTeamsVal) {
6698 "Expected target-based executable directive.");
6699 switch (DirectiveKind) {
6701 const auto *CS = D.getInnermostCapturedStmt();
6704 const Stmt *ChildStmt =
6706 if (
const auto *NestedDir =
6707 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) {
6716 MinTeamsVal = MaxTeamsVal =
Constant->getExtValue();
6719 MinTeamsVal = MaxTeamsVal = 0;
6722 MinTeamsVal = MaxTeamsVal = 1;
6726 MinTeamsVal = MaxTeamsVal = -1;
6729 case OMPD_target_teams_loop:
6730 case OMPD_target_teams:
6731 case OMPD_target_teams_distribute:
6732 case OMPD_target_teams_distribute_simd:
6733 case OMPD_target_teams_distribute_parallel_for:
6734 case OMPD_target_teams_distribute_parallel_for_simd: {
6736 const Expr *NumTeams =
6740 MinTeamsVal = MaxTeamsVal =
Constant->getExtValue();
6743 MinTeamsVal = MaxTeamsVal = 0;
6746 case OMPD_target_parallel:
6747 case OMPD_target_parallel_for:
6748 case OMPD_target_parallel_for_simd:
6749 case OMPD_target_parallel_loop:
6750 case OMPD_target_simd:
6751 MinTeamsVal = MaxTeamsVal = 1;
6755 case OMPD_parallel_for:
6756 case OMPD_parallel_loop:
6757 case OMPD_parallel_master:
6758 case OMPD_parallel_sections:
6760 case OMPD_parallel_for_simd:
6762 case OMPD_cancellation_point:
6763 case OMPD_ordered_standalone:
6764 case OMPD_ordered_blockassoc:
6765 case OMPD_threadprivate:
6776 case OMPD_taskyield:
6779 case OMPD_taskgroup:
6785 case OMPD_target_data:
6786 case OMPD_target_exit_data:
6787 case OMPD_target_enter_data:
6788 case OMPD_distribute:
6789 case OMPD_distribute_simd:
6790 case OMPD_distribute_parallel_for:
6791 case OMPD_distribute_parallel_for_simd:
6792 case OMPD_teams_distribute:
6793 case OMPD_teams_distribute_simd:
6794 case OMPD_teams_distribute_parallel_for:
6795 case OMPD_teams_distribute_parallel_for_simd:
6796 case OMPD_target_update:
6797 case OMPD_declare_simd:
6798 case OMPD_declare_variant:
6799 case OMPD_begin_declare_variant:
6800 case OMPD_end_declare_variant:
6801 case OMPD_declare_target:
6802 case OMPD_end_declare_target:
6803 case OMPD_declare_reduction:
6804 case OMPD_declare_mapper:
6806 case OMPD_taskloop_simd:
6807 case OMPD_master_taskloop:
6808 case OMPD_master_taskloop_simd:
6809 case OMPD_parallel_master_taskloop:
6810 case OMPD_parallel_master_taskloop_simd:
6812 case OMPD_metadirective:
6818 llvm_unreachable(
"Unexpected directive kind.");
6824 "Clauses associated with the teams directive expected to be emitted "
6825 "only for the host!");
6827 int32_t MinNT = -1, MaxNT = -1;
6828 const Expr *NumTeams =
6830 if (NumTeams !=
nullptr) {
6833 switch (DirectiveKind) {
6835 const auto *CS = D.getInnermostCapturedStmt();
6836 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6840 return Bld.CreateIntCast(NumTeamsVal, CGF.
Int32Ty,
6843 case OMPD_target_teams:
6844 case OMPD_target_teams_distribute:
6845 case OMPD_target_teams_distribute_simd:
6846 case OMPD_target_teams_distribute_parallel_for:
6847 case OMPD_target_teams_distribute_parallel_for_simd: {
6851 return Bld.CreateIntCast(NumTeamsVal, CGF.
Int32Ty,
6859 assert(MinNT == MaxNT &&
"Num threads ranges require handling here.");
6860 return llvm::ConstantInt::getSigned(CGF.
Int32Ty, MinNT);
6874 UpperBound = UpperBound > 0 ? std::min(UpperBound, Val) : Val;
6883 bool UpperBoundOnly, llvm::Value **CondVal) {
6886 const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child);
6893 if (CondVal && Dir->hasClausesOfKind<
OMPIfClause>()) {
6894 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6897 for (
const auto *
C : Dir->getClausesOfKind<
OMPIfClause>()) {
6898 if (
C->getNameModifier() == OMPD_unknown ||
6899 C->getNameModifier() == OMPD_parallel) {
6914 if (
const auto *PreInit =
6916 for (
const auto *I : PreInit->decls()) {
6917 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
6933 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6935 const auto *NumThreadsClause =
6937 const Expr *NTExpr = NumThreadsClause->getNumThreads().front();
6938 if (NTExpr->isIntegerConstantExpr(CGF.
getContext()))
6944 if (UpperBound == -1)
6949 if (
const auto *PreInit =
6950 cast_or_null<DeclStmt>(NumThreadsClause->getPreInitStmt())) {
6951 for (
const auto *I : PreInit->decls()) {
6952 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
6971 bool UpperBoundOnly, llvm::Value **CondVal,
const Expr **ThreadLimitExpr) {
6972 assert((!CGF.
getLangOpts().OpenMPIsTargetDevice || UpperBoundOnly) &&
6973 "Clauses associated with the teams directive expected to be emitted "
6974 "only for the host!");
6977 "Expected target-based executable directive.");
6979 const Expr *NT =
nullptr;
6980 const Expr **NTPtr = UpperBoundOnly ?
nullptr : &NT;
6982 auto CheckForConstExpr = [&](
const Expr *E,
const Expr **EPtr) {
6986 UpperBound,
static_cast<int32_t
>(
Constant->getZExtValue()));
6990 if (UpperBound == -1)
6996 auto ReturnSequential = [&]() {
7001 switch (DirectiveKind) {
7004 getNumThreads(CGF, CS, NTPtr, UpperBound, UpperBoundOnly, CondVal);
7010 if (
const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) {
7012 ThreadLimitClause = TLC;
7013 if (ThreadLimitExpr) {
7014 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
7018 ThreadLimitClause->getThreadLimit().front()->getSourceRange());
7019 if (
const auto *PreInit =
7020 cast_or_null<DeclStmt>(ThreadLimitClause->getPreInitStmt())) {
7021 for (
const auto *I : PreInit->decls()) {
7022 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
7034 if (ThreadLimitClause)
7035 CheckForConstExpr(ThreadLimitClause->getThreadLimit().front(),
7037 if (
const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) {
7040 CS = Dir->getInnermostCapturedStmt();
7054 Dir = dyn_cast_or_null<OMPExecutableDirective>(Child);
7057 CS = Dir->getInnermostCapturedStmt();
7058 getNumThreads(CGF, CS, NTPtr, UpperBound, UpperBoundOnly, CondVal);
7060 return ReturnSequential();
7064 case OMPD_target_teams: {
7068 CheckForConstExpr(ThreadLimitClause->getThreadLimit().front(),
7072 getNumThreads(CGF, CS, NTPtr, UpperBound, UpperBoundOnly, CondVal);
7075 if (
const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) {
7076 if (Dir->getDirectiveKind() == OMPD_distribute) {
7077 CS = Dir->getInnermostCapturedStmt();
7078 getNumThreads(CGF, CS, NTPtr, UpperBound, UpperBoundOnly, CondVal);
7083 case OMPD_target_teams_distribute:
7087 CheckForConstExpr(ThreadLimitClause->getThreadLimit().front(),
7090 getNumThreads(CGF, D.getInnermostCapturedStmt(), NTPtr, UpperBound,
7091 UpperBoundOnly, CondVal);
7093 case OMPD_target_teams_loop:
7094 case OMPD_target_parallel_loop:
7095 case OMPD_target_parallel:
7096 case OMPD_target_parallel_for:
7097 case OMPD_target_parallel_for_simd:
7098 case OMPD_target_teams_distribute_parallel_for:
7099 case OMPD_target_teams_distribute_parallel_for_simd: {
7100 if (CondVal && D.hasClausesOfKind<
OMPIfClause>()) {
7102 for (
const auto *
C : D.getClausesOfKind<
OMPIfClause>()) {
7103 if (
C->getNameModifier() == OMPD_unknown ||
7104 C->getNameModifier() == OMPD_parallel) {
7114 return ReturnSequential();
7124 CheckForConstExpr(ThreadLimitClause->getThreadLimit().front(),
7130 CheckForConstExpr(NumThreadsClause->getNumThreads().front(),
nullptr);
7131 return NumThreadsClause->getNumThreads().front();
7135 case OMPD_target_teams_distribute_simd:
7136 case OMPD_target_simd:
7137 return ReturnSequential();
7141 llvm_unreachable(
"Unsupported directive kind.");
7146 llvm::Value *NumThreadsVal =
nullptr;
7147 llvm::Value *CondVal =
nullptr;
7148 llvm::Value *ThreadLimitVal =
nullptr;
7149 const Expr *ThreadLimitExpr =
nullptr;
7150 int32_t UpperBound = -1;
7153 CGF, D, UpperBound,
false, &CondVal,
7157 if (ThreadLimitExpr) {
7160 ThreadLimitVal = CGF.
Builder.CreateIntCast(ThreadLimitVal, CGF.
Int32Ty,
7165 if (UpperBound == 1) {
7166 NumThreadsVal = CGF.
Builder.getInt32(UpperBound);
7169 NumThreadsVal = CGF.
Builder.CreateIntCast(NumThreadsVal, CGF.
Int32Ty,
7171 }
else if (ThreadLimitVal) {
7174 NumThreadsVal = ThreadLimitVal;
7175 ThreadLimitVal =
nullptr;
7178 assert(!ThreadLimitVal &&
"Default not applicable with thread limit value");
7179 NumThreadsVal = CGF.
Builder.getInt32(0);
7186 NumThreadsVal = CGF.
Builder.CreateSelect(CondVal, NumThreadsVal,
7192 if (ThreadLimitVal) {
7193 NumThreadsVal = CGF.
Builder.CreateSelect(
7194 CGF.
Builder.CreateICmpULT(ThreadLimitVal, NumThreadsVal),
7195 ThreadLimitVal, NumThreadsVal);
7198 return NumThreadsVal;
7208class MappableExprsHandler {
7214 struct AttachPtrExprComparator {
7215 const MappableExprsHandler &Handler;
7217 mutable llvm::DenseMap<std::pair<const Expr *, const Expr *>,
bool>
7218 CachedEqualityComparisons;
7220 AttachPtrExprComparator(
const MappableExprsHandler &H) : Handler(H) {}
7221 AttachPtrExprComparator() =
delete;
7224 bool operator()(
const Expr *LHS,
const Expr *RHS)
const {
7229 const auto ItLHS = Handler.AttachPtrComponentDepthMap.find(LHS);
7230 const auto ItRHS = Handler.AttachPtrComponentDepthMap.find(RHS);
7232 std::optional<size_t> DepthLHS =
7233 (ItLHS != Handler.AttachPtrComponentDepthMap.end()) ? ItLHS->second
7235 std::optional<size_t> DepthRHS =
7236 (ItRHS != Handler.AttachPtrComponentDepthMap.end()) ? ItRHS->second
7240 if (!DepthLHS.has_value() && !DepthRHS.has_value()) {
7242 if (areEqual(LHS, RHS))
7245 return wasComputedBefore(LHS, RHS);
7247 if (!DepthLHS.has_value())
7249 if (!DepthRHS.has_value())
7253 if (DepthLHS.value() != DepthRHS.value())
7254 return DepthLHS.value() < DepthRHS.value();
7257 if (areEqual(LHS, RHS))
7260 return wasComputedBefore(LHS, RHS);
7266 bool areEqual(
const Expr *LHS,
const Expr *RHS)
const {
7268 const auto CachedResultIt = CachedEqualityComparisons.find({LHS, RHS});
7269 if (CachedResultIt != CachedEqualityComparisons.end())
7270 return CachedResultIt->second;
7284 bool wasComputedBefore(
const Expr *LHS,
const Expr *RHS)
const {
7285 const size_t &OrderLHS = Handler.AttachPtrComputationOrderMap.at(LHS);
7286 const size_t &OrderRHS = Handler.AttachPtrComputationOrderMap.at(RHS);
7288 return OrderLHS < OrderRHS;
7297 bool areSemanticallyEqual(
const Expr *LHS,
const Expr *RHS)
const {
7319 if (
const auto *LD = dyn_cast<DeclRefExpr>(LHS)) {
7320 const auto *RD = dyn_cast<DeclRefExpr>(RHS);
7323 return LD->getDecl()->getCanonicalDecl() ==
7324 RD->getDecl()->getCanonicalDecl();
7328 if (
const auto *LA = dyn_cast<ArraySubscriptExpr>(LHS)) {
7329 const auto *RA = dyn_cast<ArraySubscriptExpr>(RHS);
7332 return areSemanticallyEqual(LA->getBase(), RA->getBase()) &&
7333 areSemanticallyEqual(LA->getIdx(), RA->getIdx());
7337 if (
const auto *LM = dyn_cast<MemberExpr>(LHS)) {
7338 const auto *RM = dyn_cast<MemberExpr>(RHS);
7341 if (LM->getMemberDecl()->getCanonicalDecl() !=
7342 RM->getMemberDecl()->getCanonicalDecl())
7344 return areSemanticallyEqual(LM->getBase(), RM->getBase());
7348 if (
const auto *LU = dyn_cast<UnaryOperator>(LHS)) {
7349 const auto *RU = dyn_cast<UnaryOperator>(RHS);
7352 if (LU->getOpcode() != RU->getOpcode())
7354 return areSemanticallyEqual(LU->getSubExpr(), RU->getSubExpr());
7358 if (
const auto *LB = dyn_cast<BinaryOperator>(LHS)) {
7359 const auto *RB = dyn_cast<BinaryOperator>(RHS);
7362 if (LB->getOpcode() != RB->getOpcode())
7364 return areSemanticallyEqual(LB->getLHS(), RB->getLHS()) &&
7365 areSemanticallyEqual(LB->getRHS(), RB->getRHS());
7371 if (
const auto *LAS = dyn_cast<ArraySectionExpr>(LHS)) {
7372 const auto *RAS = dyn_cast<ArraySectionExpr>(RHS);
7375 return areSemanticallyEqual(LAS->getBase(), RAS->getBase()) &&
7376 areSemanticallyEqual(LAS->getLowerBound(),
7377 RAS->getLowerBound()) &&
7378 areSemanticallyEqual(LAS->getLength(), RAS->getLength());
7382 if (
const auto *LC = dyn_cast<CastExpr>(LHS)) {
7383 const auto *RC = dyn_cast<CastExpr>(RHS);
7386 if (LC->getCastKind() != RC->getCastKind())
7388 return areSemanticallyEqual(LC->getSubExpr(), RC->getSubExpr());
7396 if (
const auto *LI = dyn_cast<IntegerLiteral>(LHS)) {
7397 const auto *RI = dyn_cast<IntegerLiteral>(RHS);
7400 return LI->getValue() == RI->getValue();
7404 if (
const auto *LC = dyn_cast<CharacterLiteral>(LHS)) {
7405 const auto *RC = dyn_cast<CharacterLiteral>(RHS);
7408 return LC->getValue() == RC->getValue();
7412 if (
const auto *LF = dyn_cast<FloatingLiteral>(LHS)) {
7413 const auto *RF = dyn_cast<FloatingLiteral>(RHS);
7417 return LF->getValue().bitwiseIsEqual(RF->getValue());
7421 if (
const auto *LS = dyn_cast<StringLiteral>(LHS)) {
7422 const auto *RS = dyn_cast<StringLiteral>(RHS);
7425 return LS->getString() == RS->getString();
7433 if (
const auto *LB = dyn_cast<CXXBoolLiteralExpr>(LHS)) {
7434 const auto *RB = dyn_cast<CXXBoolLiteralExpr>(RHS);
7437 return LB->getValue() == RB->getValue();
7446 static unsigned getFlagMemberOffset() {
7447 unsigned Offset = 0;
7448 for (uint64_t Remain =
7449 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
7450 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF);
7451 !(Remain & 1); Remain = Remain >> 1)
7458 class MappingExprInfo {
7460 const ValueDecl *MapDecl =
nullptr;
7463 const Expr *MapExpr =
nullptr;
7466 MappingExprInfo(
const ValueDecl *MapDecl,
const Expr *MapExpr =
nullptr)
7467 : MapDecl(MapDecl), MapExpr(MapExpr) {}
7469 const ValueDecl *getMapDecl()
const {
return MapDecl; }
7470 const Expr *getMapExpr()
const {
return MapExpr; }
7473 using DeviceInfoTy = llvm::OpenMPIRBuilder::DeviceInfoTy;
7474 using MapBaseValuesArrayTy = llvm::OpenMPIRBuilder::MapValuesArrayTy;
7475 using MapValuesArrayTy = llvm::OpenMPIRBuilder::MapValuesArrayTy;
7476 using MapFlagsArrayTy = llvm::OpenMPIRBuilder::MapFlagsArrayTy;
7477 using MapDimArrayTy = llvm::OpenMPIRBuilder::MapDimArrayTy;
7478 using MapNonContiguousArrayTy =
7479 llvm::OpenMPIRBuilder::MapNonContiguousArrayTy;
7480 using MapExprsArrayTy = SmallVector<MappingExprInfo, 4>;
7481 using MapValueDeclsArrayTy = SmallVector<const ValueDecl *, 4>;
7485 bool ,
const ValueDecl *,
const Expr *>;
7486 using MapDataArrayTy = SmallVector<MapData, 4>;
7491 struct MapCombinedInfoTy : llvm::OpenMPIRBuilder::MapInfosTy {
7492 MapExprsArrayTy Exprs;
7493 MapValueDeclsArrayTy Mappers;
7494 MapValueDeclsArrayTy DevicePtrDecls;
7497 void append(MapCombinedInfoTy &CurInfo) {
7498 Exprs.append(CurInfo.Exprs.begin(), CurInfo.Exprs.end());
7499 DevicePtrDecls.append(CurInfo.DevicePtrDecls.begin(),
7500 CurInfo.DevicePtrDecls.end());
7501 Mappers.append(CurInfo.Mappers.begin(), CurInfo.Mappers.end());
7502 llvm::OpenMPIRBuilder::MapInfosTy::append(CurInfo);
7510 struct StructRangeInfoTy {
7511 MapCombinedInfoTy PreliminaryMapData;
7512 std::pair<
unsigned ,
Address > LowestElem = {
7514 std::pair<
unsigned ,
Address > HighestElem = {
7518 bool IsArraySection =
false;
7519 bool HasCompleteRecord =
false;
7524 struct AttachInfoTy {
7527 const ValueDecl *AttachPtrDecl =
nullptr;
7528 const Expr *AttachMapExpr =
nullptr;
7530 bool isValid()
const {
7537 bool hasAttachEntryForCapturedVar(
const ValueDecl *VD)
const {
7538 for (
const auto &AttachEntry : AttachPtrExprMap) {
7539 if (AttachEntry.second) {
7542 if (
const auto *DRE = dyn_cast<DeclRefExpr>(AttachEntry.second))
7543 if (DRE->getDecl() == VD)
7551 const Expr *getAttachPtrExpr(
7554 const auto It = AttachPtrExprMap.find(Components);
7555 if (It != AttachPtrExprMap.end())
7566 ArrayRef<OpenMPMapModifierKind> MapModifiers;
7567 ArrayRef<OpenMPMotionModifierKind> MotionModifiers;
7568 bool ReturnDevicePointer =
false;
7569 bool IsImplicit =
false;
7570 const ValueDecl *Mapper =
nullptr;
7571 const Expr *VarRef =
nullptr;
7572 bool ForDeviceAddr =
false;
7573 bool HasUdpFbNullify =
false;
7575 MapInfo() =
default;
7579 ArrayRef<OpenMPMapModifierKind> MapModifiers,
7580 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
7581 bool ReturnDevicePointer,
bool IsImplicit,
7582 const ValueDecl *Mapper =
nullptr,
const Expr *VarRef =
nullptr,
7583 bool ForDeviceAddr =
false,
bool HasUdpFbNullify =
false)
7584 : Components(Components), MapType(MapType), MapModifiers(MapModifiers),
7585 MotionModifiers(MotionModifiers),
7586 ReturnDevicePointer(ReturnDevicePointer), IsImplicit(IsImplicit),
7587 Mapper(Mapper), VarRef(VarRef), ForDeviceAddr(ForDeviceAddr),
7588 HasUdpFbNullify(HasUdpFbNullify) {}
7593 llvm::PointerUnion<
const OMPExecutableDirective *,
7594 const OMPDeclareMapperDecl *>
7598 CodeGenFunction &CGF;
7603 llvm::DenseMap<CanonicalDeclPtr<const VarDecl>,
bool> FirstPrivateDecls;
7606 llvm::SmallSet<OpenMPDefaultmapClauseKind, 4> DefaultmapFirstprivateKinds;
7612 SmallVector<OMPClauseMappableExprCommon::MappableExprComponentListRef, 4>>
7619 SmallVector<OMPClauseMappableExprCommon::MappableExprComponentListRef, 4>>
7623 llvm::DenseMap<const ValueDecl *, const OMPMapClause *> LambdasMap;
7638 llvm::DenseMap<const Expr *, std::optional<size_t>>
7639 AttachPtrComponentDepthMap = {{
nullptr, std::nullopt}};
7643 llvm::DenseMap<const Expr *, size_t> AttachPtrComputationOrderMap = {
7648 AttachPtrExprComparator AttachPtrComparator;
7650 llvm::Value *getExprTypeSize(
const Expr *E)
const {
7654 if (
const auto *OAE = dyn_cast<OMPArrayShapingExpr>(E)) {
7656 CGF.
getTypeSize(OAE->getBase()->getType()->getPointeeType());
7657 for (
const Expr *SE : OAE->getDimensions()) {
7668 if (
const auto *RefTy =
ExprTy->getAs<ReferenceType>())
7669 ExprTy = RefTy->getPointeeType().getCanonicalType();
7674 if (
const auto *OAE = dyn_cast<ArraySectionExpr>(E)) {
7676 OAE->getBase()->IgnoreParenImpCasts())
7682 if (!OAE->getLength() && OAE->getColonLocFirst().isValid() &&
7683 !OAE->getLowerBound())
7686 llvm::Value *ElemSize;
7687 if (
const auto *PTy = BaseTy->
getAs<PointerType>()) {
7688 ElemSize = CGF.
getTypeSize(PTy->getPointeeType().getCanonicalType());
7691 assert(ATy &&
"Expecting array type if not a pointer type.");
7692 ElemSize = CGF.
getTypeSize(ATy->getElementType().getCanonicalType());
7697 if (!OAE->getLength() && OAE->getColonLocFirst().isInvalid())
7700 if (
const Expr *LenExpr = OAE->getLength()) {
7704 LenExpr->getExprLoc());
7705 return CGF.
Builder.CreateNUWMul(LengthVal, ElemSize);
7707 assert(!OAE->getLength() && OAE->getColonLocFirst().isValid() &&
7708 OAE->getLowerBound() &&
"expected array_section[lb:].");
7714 OAE->getLowerBound()->getExprLoc());
7715 LBVal = CGF.
Builder.CreateNUWMul(LBVal, ElemSize);
7716 llvm::Value *
Cmp = CGF.
Builder.CreateICmpUGT(LengthVal, LBVal);
7717 llvm::Value *TrueVal = CGF.
Builder.CreateNUWSub(LengthVal, LBVal);
7718 LengthVal = CGF.
Builder.CreateSelect(
7719 Cmp, TrueVal, llvm::ConstantInt::get(CGF.
SizeTy, 0));
7729 OpenMPOffloadMappingFlags getMapTypeBits(
7731 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
bool IsImplicit,
7732 bool AddPtrFlag,
bool AddIsTargetParamFlag,
bool IsNonContiguous)
const {
7733 OpenMPOffloadMappingFlags Bits =
7734 IsImplicit ? OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT
7735 : OpenMPOffloadMappingFlags::OMP_MAP_NONE;
7737 case OMPC_MAP_alloc:
7738 case OMPC_MAP_release:
7745 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_TO;
7748 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_FROM;
7750 case OMPC_MAP_tofrom:
7751 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_TO |
7752 OpenMPOffloadMappingFlags::OMP_MAP_FROM;
7754 case OMPC_MAP_delete:
7755 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_DELETE;
7758 llvm_unreachable(
"Unexpected map type!");
7761 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ;
7762 if (AddIsTargetParamFlag)
7763 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM;
7764 if (llvm::is_contained(MapModifiers, OMPC_MAP_MODIFIER_always))
7765 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_ALWAYS;
7766 if (llvm::is_contained(MapModifiers, OMPC_MAP_MODIFIER_close))
7767 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_CLOSE;
7768 if (llvm::is_contained(MapModifiers, OMPC_MAP_MODIFIER_present) ||
7769 llvm::is_contained(MotionModifiers, OMPC_MOTION_MODIFIER_present))
7770 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_PRESENT;
7771 if (llvm::is_contained(MapModifiers, OMPC_MAP_MODIFIER_ompx_hold))
7772 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_OMPX_HOLD;
7773 if (IsNonContiguous)
7774 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_NON_CONTIG;
7780 bool isFinalArraySectionExpression(
const Expr *E)
const {
7781 const auto *OASE = dyn_cast<ArraySectionExpr>(E);
7788 if (OASE->getColonLocFirst().isInvalid())
7791 const Expr *Length = OASE->getLength();
7798 OASE->getBase()->IgnoreParenImpCasts())
7800 if (
const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.
getTypePtr()))
7801 return ATy->getSExtSize() != 1;
7813 llvm::APSInt ConstLength =
Result.Val.getInt();
7814 return ConstLength.getSExtValue() != 1;
7821 void emitAttachEntry(CodeGenFunction &CGF, MapCombinedInfoTy &CombinedInfo,
7822 const AttachInfoTy &AttachInfo)
const {
7823 assert(AttachInfo.isValid() &&
7824 "Expected valid attach pointer/pointee information!");
7828 llvm::Value *PointerSize = CGF.
Builder.CreateIntCast(
7829 llvm::ConstantInt::get(
7835 CombinedInfo.Exprs.emplace_back(AttachInfo.AttachPtrDecl,
7836 AttachInfo.AttachMapExpr);
7837 CombinedInfo.BasePointers.push_back(
7838 AttachInfo.AttachPtrAddr.emitRawPointer(CGF));
7839 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
7840 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
7841 CombinedInfo.Pointers.push_back(
7842 AttachInfo.AttachPteeAddr.emitRawPointer(CGF));
7843 CombinedInfo.Sizes.push_back(PointerSize);
7844 CombinedInfo.Types.push_back(OpenMPOffloadMappingFlags::OMP_MAP_ATTACH);
7846 CombinedInfo.HasAttachPtr.push_back(
false);
7847 CombinedInfo.Mappers.push_back(
nullptr);
7848 CombinedInfo.NonContigInfo.Dims.push_back(1);
7855 class CopyOverlappedEntryGaps {
7856 CodeGenFunction &CGF;
7857 MapCombinedInfoTy &CombinedInfo;
7858 OpenMPOffloadMappingFlags Flags = OpenMPOffloadMappingFlags::OMP_MAP_NONE;
7859 const ValueDecl *MapDecl =
nullptr;
7860 const Expr *MapExpr =
nullptr;
7862 bool IsNonContiguous =
false;
7866 const RecordDecl *LastParent =
nullptr;
7868 unsigned LastIndex = -1u;
7872 CopyOverlappedEntryGaps(CodeGenFunction &CGF,
7873 MapCombinedInfoTy &CombinedInfo,
7874 OpenMPOffloadMappingFlags Flags,
7875 const ValueDecl *MapDecl,
const Expr *MapExpr,
7876 Address BP, Address LB,
bool IsNonContiguous,
7878 : CGF(CGF), CombinedInfo(CombinedInfo), Flags(Flags), MapDecl(MapDecl),
7879 MapExpr(MapExpr), BP(BP), IsNonContiguous(IsNonContiguous),
7880 DimSize(DimSize), LB(LB) {}
7883 const OMPClauseMappableExprCommon::MappableComponent &MC,
7884 const FieldDecl *FD,
7885 llvm::function_ref<LValue(CodeGenFunction &,
const MemberExpr *)>
7886 EmitMemberExprBase) {
7896 LValue BaseLVal = EmitMemberExprBase(CGF, ME);
7908 copyUntilField(FD, ComponentLB);
7912 copyUntilField(FD, ComponentLB);
7914 Cursor = FieldOffset + FieldSize;
7919 void copyUntilField(
const FieldDecl *FD, Address ComponentLB) {
7922 llvm::Value *
Size = CGF.
Builder.CreatePtrDiff(ComponentLBPtr, LBPtr);
7923 copySizedChunk(LBPtr, Size);
7926 void copyUntilEnd(Address HB) {
7928 const ASTRecordLayout &RL =
7936 copySizedChunk(LBPtr, Size);
7939 void copySizedChunk(llvm::Value *Base, llvm::Value *Size) {
7940 CombinedInfo.Exprs.emplace_back(MapDecl, MapExpr);
7942 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
7943 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
7944 CombinedInfo.Pointers.push_back(Base);
7945 CombinedInfo.Sizes.push_back(
7947 CombinedInfo.Types.push_back(Flags);
7948 CombinedInfo.HasAttachPtr.push_back(
false);
7949 CombinedInfo.Mappers.push_back(
nullptr);
7950 CombinedInfo.NonContigInfo.Dims.push_back(IsNonContiguous ? DimSize : 1);
7959 void generateInfoForComponentList(
7961 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
7963 MapCombinedInfoTy &CombinedInfo,
7964 MapCombinedInfoTy &StructBaseCombinedInfo,
7965 StructRangeInfoTy &PartialStruct, AttachInfoTy &AttachInfo,
7966 bool IsFirstComponentList,
bool IsImplicit,
7967 bool GenerateAllInfoForClauses,
const ValueDecl *Mapper =
nullptr,
7968 bool ForDeviceAddr =
false,
const ValueDecl *BaseDecl =
nullptr,
7969 const Expr *MapExpr =
nullptr,
7970 ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef>
7971 OverlappedElements = {})
const {
8189 bool IsCaptureFirstInfo = IsFirstComponentList;
8193 bool RequiresReference =
false;
8196 auto CI = Components.rbegin();
8197 auto CE = Components.rend();
8202 bool IsExpressionFirstInfo =
true;
8203 bool FirstPointerInComplexData =
false;
8206 const Expr *AssocExpr = I->getAssociatedExpression();
8207 const auto *AE = dyn_cast<ArraySubscriptExpr>(AssocExpr);
8208 const auto *OASE = dyn_cast<ArraySectionExpr>(AssocExpr);
8209 const auto *OAShE = dyn_cast<OMPArrayShapingExpr>(AssocExpr);
8212 const Expr *AttachPtrExpr = getAttachPtrExpr(Components);
8213 auto [AttachPtrAddr, AttachPteeBaseAddr] =
8214 getAttachPtrAddrAndPteeBaseAddr(AttachPtrExpr, CGF);
8216 bool HasAttachPtr = AttachPtrExpr !=
nullptr;
8217 bool FirstComponentIsForAttachPtr = AssocExpr == AttachPtrExpr;
8218 bool SeenAttachPtr = FirstComponentIsForAttachPtr;
8220 if (FirstComponentIsForAttachPtr) {
8228 }
else if ((AE &&
isa<CXXThisExpr>(AE->getBase()->IgnoreParenImpCasts())) ||
8242 if (
const auto *VD =
8243 dyn_cast_or_null<VarDecl>(I->getAssociatedDeclaration())) {
8244 if (std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
8245 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD)) {
8246 if ((*Res == OMPDeclareTargetDeclAttr::MT_Link) ||
8247 ((*Res == OMPDeclareTargetDeclAttr::MT_To ||
8248 *Res == OMPDeclareTargetDeclAttr::MT_Enter) &&
8250 RequiresReference =
true;
8260 I->getAssociatedDeclaration()->
getType().getNonReferenceType();
8265 const auto *VD = dyn_cast<VarDecl>(I->getAssociatedDeclaration());
8267 !VD || VD->hasLocalStorage() || HasAttachPtr)
8270 FirstPointerInComplexData =
true;
8289 bool ShouldBeMemberOf =
false;
8298 const MemberExpr *EncounteredME =
nullptr;
8310 bool IsNonContiguous =
8311 CombinedInfo.NonContigInfo.IsNonContiguous ||
8312 any_of(Components, [&](
const auto &Component) {
8314 dyn_cast<ArraySectionExpr>(Component.getAssociatedExpression());
8318 const Expr *StrideExpr = OASE->getStride();
8323 "Stride expression must be of integer type");
8336 bool IsPrevMemberReference =
false;
8338 bool IsPartialMapped =
8339 !PartialStruct.PreliminaryMapData.BasePointers.empty();
8346 bool IsMappingWholeStruct =
true;
8347 if (!GenerateAllInfoForClauses) {
8348 IsMappingWholeStruct =
false;
8350 for (
auto TempI = I; TempI != CE; ++TempI) {
8351 const MemberExpr *PossibleME =
8352 dyn_cast<MemberExpr>(TempI->getAssociatedExpression());
8354 IsMappingWholeStruct =
false;
8360 bool SeenFirstNonBinOpExprAfterAttachPtr =
false;
8361 for (; I != CE; ++I) {
8364 if (HasAttachPtr && !SeenAttachPtr) {
8365 SeenAttachPtr = I->getAssociatedExpression() == AttachPtrExpr;
8372 if (HasAttachPtr && !SeenFirstNonBinOpExprAfterAttachPtr) {
8373 const auto *BO = dyn_cast<BinaryOperator>(I->getAssociatedExpression());
8378 SeenFirstNonBinOpExprAfterAttachPtr =
true;
8379 BP = AttachPteeBaseAddr;
8383 if (!EncounteredME) {
8384 EncounteredME = dyn_cast<MemberExpr>(I->getAssociatedExpression());
8387 if (EncounteredME) {
8388 ShouldBeMemberOf =
true;
8391 if (FirstPointerInComplexData) {
8392 QualType Ty = std::prev(I)
8393 ->getAssociatedDeclaration()
8395 .getNonReferenceType();
8397 FirstPointerInComplexData =
false;
8402 auto Next = std::next(I);
8412 bool IsFinalArraySection =
8414 isFinalArraySectionExpression(I->getAssociatedExpression());
8418 const ValueDecl *MapDecl = (I->getAssociatedDeclaration())
8419 ? I->getAssociatedDeclaration()
8421 MapExpr = (I->getAssociatedExpression()) ? I->getAssociatedExpression()
8428 dyn_cast<ArraySectionExpr>(I->getAssociatedExpression());
8430 dyn_cast<OMPArrayShapingExpr>(I->getAssociatedExpression());
8431 const auto *UO = dyn_cast<UnaryOperator>(I->getAssociatedExpression());
8432 const auto *BO = dyn_cast<BinaryOperator>(I->getAssociatedExpression());
8438 I->getAssociatedExpression()->getType()->isAnyPointerType();
8439 bool IsMemberReference =
isa<MemberExpr>(I->getAssociatedExpression()) &&
8442 bool IsNonDerefPointer = IsPointer &&
8443 !(UO && UO->getOpcode() != UO_Deref) && !BO &&
8449 if (
Next == CE || IsMemberReference || IsNonDerefPointer ||
8450 IsFinalArraySection) {
8453 assert((
Next == CE ||
8460 "Unexpected expression");
8464 auto &&EmitMemberExprBase = [](CodeGenFunction &CGF,
8465 const MemberExpr *E) {
8466 const Expr *BaseExpr = E->getBase();
8471 LValueBaseInfo BaseInfo;
8472 TBAAAccessInfo TBAAInfo;
8486 OAShE->getBase()->getType()->getPointeeType()),
8488 OAShE->getBase()->getType()));
8489 }
else if (IsMemberReference) {
8491 LValue BaseLVal = EmitMemberExprBase(CGF, ME);
8506 FinalLowestElem = LowestElem;
8511 bool IsMemberPointerOrAddr =
8513 (((IsPointer || ForDeviceAddr) &&
8514 I->getAssociatedExpression() == EncounteredME) ||
8515 (IsPrevMemberReference && !IsPointer) ||
8516 (IsMemberReference &&
Next != CE &&
8517 !
Next->getAssociatedExpression()->getType()->isPointerType()));
8518 if (!OverlappedElements.empty() &&
Next == CE) {
8520 assert(!PartialStruct.Base.isValid() &&
"The base element is set.");
8521 assert(!IsPointer &&
8522 "Unexpected base element with the pointer type.");
8525 PartialStruct.LowestElem = {0, LowestElem};
8527 I->getAssociatedExpression()->getType());
8532 PartialStruct.HighestElem = {
8533 std::numeric_limits<
decltype(
8534 PartialStruct.HighestElem.first)>
::max(),
8536 PartialStruct.Base = BP;
8537 PartialStruct.LB = LB;
8539 PartialStruct.PreliminaryMapData.BasePointers.empty() &&
8540 "Overlapped elements must be used only once for the variable.");
8541 std::swap(PartialStruct.PreliminaryMapData, CombinedInfo);
8543 OpenMPOffloadMappingFlags Flags =
8544 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF |
8545 getMapTypeBits(MapType, MapModifiers, MotionModifiers, IsImplicit,
8547 false, IsNonContiguous);
8548 CopyOverlappedEntryGaps CopyGaps(CGF, CombinedInfo, Flags, MapDecl,
8549 MapExpr, BP, LB, IsNonContiguous,
8553 Component : OverlappedElements) {
8554 for (
const OMPClauseMappableExprCommon::MappableComponent &MC :
8557 if (
const auto *FD = dyn_cast<FieldDecl>(VD)) {
8558 CopyGaps.processField(MC, FD, EmitMemberExprBase);
8563 CopyGaps.copyUntilEnd(HB);
8566 llvm::Value *
Size = getExprTypeSize(I->getAssociatedExpression());
8573 if ((!IsMemberPointerOrAddr && !IsPartialMapped) ||
8575 if (!IsMappingWholeStruct) {
8576 CombinedInfo.Exprs.emplace_back(MapDecl, MapExpr);
8578 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
8579 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
8581 CombinedInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
8583 CombinedInfo.NonContigInfo.Dims.push_back(IsNonContiguous ? DimSize
8586 StructBaseCombinedInfo.Exprs.emplace_back(MapDecl, MapExpr);
8587 StructBaseCombinedInfo.BasePointers.push_back(
8589 StructBaseCombinedInfo.DevicePtrDecls.push_back(
nullptr);
8590 StructBaseCombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
8591 StructBaseCombinedInfo.Pointers.push_back(LB.
emitRawPointer(CGF));
8592 StructBaseCombinedInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
8594 StructBaseCombinedInfo.NonContigInfo.Dims.push_back(
8595 IsNonContiguous ? DimSize : 1);
8599 bool HasMapper = Mapper &&
Next == CE;
8600 if (!IsMappingWholeStruct)
8601 CombinedInfo.Mappers.push_back(HasMapper ? Mapper :
nullptr);
8603 StructBaseCombinedInfo.Mappers.push_back(HasMapper ? Mapper
8610 OpenMPOffloadMappingFlags Flags = getMapTypeBits(
8611 MapType, MapModifiers, MotionModifiers, IsImplicit,
8612 !IsExpressionFirstInfo || RequiresReference ||
8613 FirstPointerInComplexData || IsMemberReference,
8614 IsCaptureFirstInfo && !RequiresReference, IsNonContiguous);
8616 if (!IsExpressionFirstInfo || IsMemberReference) {
8619 if (IsPointer || (IsMemberReference &&
Next != CE))
8620 Flags &= ~(OpenMPOffloadMappingFlags::OMP_MAP_TO |
8621 OpenMPOffloadMappingFlags::OMP_MAP_FROM |
8622 OpenMPOffloadMappingFlags::OMP_MAP_ALWAYS |
8623 OpenMPOffloadMappingFlags::OMP_MAP_DELETE |
8624 OpenMPOffloadMappingFlags::OMP_MAP_CLOSE);
8626 if (ShouldBeMemberOf) {
8629 Flags |= OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF;
8632 ShouldBeMemberOf =
false;
8636 if (!IsMappingWholeStruct) {
8637 CombinedInfo.Types.push_back(Flags);
8639 CombinedInfo.HasAttachPtr.push_back(HasAttachPtr);
8641 StructBaseCombinedInfo.Types.push_back(Flags);
8642 StructBaseCombinedInfo.HasAttachPtr.push_back(HasAttachPtr);
8649 if (EncounteredME) {
8654 if (!PartialStruct.Base.isValid()) {
8655 PartialStruct.LowestElem = {FieldIndex, LowestElem};
8656 if (IsFinalArraySection && OASE) {
8660 PartialStruct.HighestElem = {FieldIndex, HB};
8662 PartialStruct.HighestElem = {FieldIndex, LowestElem};
8664 PartialStruct.Base = BP;
8665 PartialStruct.LB = BP;
8666 }
else if (FieldIndex < PartialStruct.LowestElem.first) {
8667 PartialStruct.LowestElem = {FieldIndex, LowestElem};
8668 }
else if (FieldIndex > PartialStruct.HighestElem.first) {
8669 if (IsFinalArraySection && OASE) {
8673 PartialStruct.HighestElem = {FieldIndex, HB};
8675 PartialStruct.HighestElem = {FieldIndex, LowestElem};
8681 if (IsFinalArraySection || IsNonContiguous)
8682 PartialStruct.IsArraySection =
true;
8685 if (IsFinalArraySection)
8690 BP = IsMemberReference ? LowestElem : LB;
8691 if (!IsPartialMapped)
8692 IsExpressionFirstInfo =
false;
8693 IsCaptureFirstInfo =
false;
8694 FirstPointerInComplexData =
false;
8695 IsPrevMemberReference = IsMemberReference;
8696 }
else if (FirstPointerInComplexData) {
8697 QualType Ty = Components.rbegin()
8698 ->getAssociatedDeclaration()
8700 .getNonReferenceType();
8702 FirstPointerInComplexData =
false;
8708 PartialStruct.HasCompleteRecord =
true;
8711 if (shouldEmitAttachEntry(AttachPtrExpr, BaseDecl, CGF, CurDir)) {
8712 AttachInfo.AttachPtrAddr = AttachPtrAddr;
8713 AttachInfo.AttachPteeAddr = FinalLowestElem;
8714 AttachInfo.AttachPtrDecl = BaseDecl;
8715 AttachInfo.AttachMapExpr = MapExpr;
8718 if (!IsNonContiguous)
8721 const ASTContext &Context = CGF.
getContext();
8725 MapValuesArrayTy CurOffsets = {llvm::ConstantInt::get(CGF.
CGM.
Int64Ty, 0)};
8726 MapValuesArrayTy CurCounts;
8727 MapValuesArrayTy CurStrides = {llvm::ConstantInt::get(CGF.
CGM.
Int64Ty, 1)};
8728 MapValuesArrayTy DimSizes{llvm::ConstantInt::get(CGF.
CGM.
Int64Ty, 1)};
8734 for (
const OMPClauseMappableExprCommon::MappableComponent &Component :
8736 const Expr *AssocExpr = Component.getAssociatedExpression();
8737 const auto *OASE = dyn_cast<ArraySectionExpr>(AssocExpr);
8747 assert((VAT || CAT || &Component == &*Components.begin()) &&
8748 "Should be either ConstantArray or VariableArray if not the "
8752 if (CurCounts.empty()) {
8753 const Type *ElementType =
nullptr;
8755 ElementType = CAT->getElementType().getTypePtr();
8757 ElementType = VAT->getElementType().getTypePtr();
8758 else if (&Component == &*Components.begin()) {
8765 if (
const auto *PtrType = Ty->
getAs<PointerType>())
8766 ElementType = PtrType->getPointeeType().getTypePtr();
8772 "Non-first components should not be raw pointers");
8780 if (&Component != &*Components.begin())
8781 ElementType = ElementType->getPointeeOrArrayElementType();
8784 CurCounts.push_back(
8785 llvm::ConstantInt::get(CGF.
Int64Ty, ElementTypeSize));
8790 if (DimSizes.size() < Components.size() - 1) {
8793 llvm::ConstantInt::get(CGF.
Int64Ty, CAT->getZExtSize()));
8795 DimSizes.push_back(CGF.
Builder.CreateIntCast(
8802 auto *DI = DimSizes.begin() + 1;
8804 llvm::Value *DimProd =
8805 llvm::ConstantInt::get(CGF.
CGM.
Int64Ty, ElementTypeSize);
8814 for (
const OMPClauseMappableExprCommon::MappableComponent &Component :
8816 const Expr *AssocExpr = Component.getAssociatedExpression();
8818 if (
const auto *AE = dyn_cast<ArraySubscriptExpr>(AssocExpr)) {
8819 llvm::Value *Offset = CGF.
Builder.CreateIntCast(
8822 CurOffsets.push_back(Offset);
8823 CurCounts.push_back(llvm::ConstantInt::get(CGF.
Int64Ty, 1));
8824 CurStrides.push_back(CurStrides.back());
8828 const auto *OASE = dyn_cast<ArraySectionExpr>(AssocExpr);
8834 const Expr *OffsetExpr = OASE->getLowerBound();
8835 llvm::Value *Offset =
nullptr;
8838 Offset = llvm::ConstantInt::get(CGF.
Int64Ty, 0);
8846 const Expr *CountExpr = OASE->getLength();
8847 llvm::Value *Count =
nullptr;
8853 if (!OASE->getColonLocFirst().isValid() &&
8854 !OASE->getColonLocSecond().isValid()) {
8855 Count = llvm::ConstantInt::get(CGF.
Int64Ty, 1);
8861 const Expr *StrideExpr = OASE->getStride();
8862 llvm::Value *Stride =
8868 Count = CGF.
Builder.CreateUDiv(
8869 CGF.
Builder.CreateNUWSub(*DI, Offset), Stride);
8871 Count = CGF.
Builder.CreateNUWSub(*DI, Offset);
8877 CurCounts.push_back(Count);
8887 const Expr *StrideExpr = OASE->getStride();
8888 llvm::Value *Stride =
8893 DimProd = CGF.
Builder.CreateNUWMul(DimProd, *(DI - 1));
8895 CurStrides.push_back(CGF.
Builder.CreateNUWMul(DimProd, Stride));
8897 CurStrides.push_back(DimProd);
8899 Offset = CGF.
Builder.CreateNUWMul(DimProd, Offset);
8900 CurOffsets.push_back(Offset);
8902 if (DI != DimSizes.end())
8906 CombinedInfo.NonContigInfo.Offsets.push_back(CurOffsets);
8907 CombinedInfo.NonContigInfo.Counts.push_back(CurCounts);
8908 CombinedInfo.NonContigInfo.Strides.push_back(CurStrides);
8914 OpenMPOffloadMappingFlags
8915 getMapModifiersForPrivateClauses(
const CapturedStmt::Capture &Cap)
const {
8923 return OpenMPOffloadMappingFlags::OMP_MAP_TO |
8924 OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ;
8925 return OpenMPOffloadMappingFlags::OMP_MAP_PRIVATE |
8926 OpenMPOffloadMappingFlags::OMP_MAP_TO;
8929 if (I != LambdasMap.end())
8931 return getMapTypeBits(
8932 I->getSecond()->getMapType(), I->getSecond()->getMapTypeModifiers(),
8933 {}, I->getSecond()->isImplicit(),
8937 return OpenMPOffloadMappingFlags::OMP_MAP_TO |
8938 OpenMPOffloadMappingFlags::OMP_MAP_FROM;
8941 void getPlainLayout(
const CXXRecordDecl *RD,
8942 llvm::SmallVectorImpl<const FieldDecl *> &Layout,
8943 bool AsBase)
const {
8946 llvm::StructType *St =
8949 unsigned NumElements = St->getNumElements();
8951 llvm::PointerUnion<const CXXRecordDecl *, const FieldDecl *>, 4>
8952 RecordLayout(NumElements);
8955 for (
const auto &I : RD->
bases()) {
8959 QualType BaseTy = I.getType();
8970 RecordLayout[FieldIndex] =
Base;
8973 for (
const auto &I : RD->
vbases()) {
8974 QualType BaseTy = I.getType();
8981 if (RecordLayout[FieldIndex])
8983 RecordLayout[FieldIndex] =
Base;
8986 assert(!RD->
isUnion() &&
"Unexpected union.");
8987 for (
const auto *Field : RD->
fields()) {
8990 if (!
Field->isBitField() &&
8993 RecordLayout[FieldIndex] =
Field;
8996 for (
const llvm::PointerUnion<const CXXRecordDecl *, const FieldDecl *>
8997 &
Data : RecordLayout) {
9000 if (
const auto *Base = dyn_cast<const CXXRecordDecl *>(
Data))
9001 getPlainLayout(Base, Layout,
true);
9008 static Address getAttachPtrAddr(
const Expr *PointerExpr,
9009 CodeGenFunction &CGF) {
9010 assert(PointerExpr &&
"Cannot get addr from null attach-ptr expr");
9013 if (
auto *DRE = dyn_cast<DeclRefExpr>(PointerExpr)) {
9016 }
else if (
auto *OASE = dyn_cast<ArraySectionExpr>(PointerExpr)) {
9019 }
else if (
auto *ASE = dyn_cast<ArraySubscriptExpr>(PointerExpr)) {
9021 }
else if (
auto *ME = dyn_cast<MemberExpr>(PointerExpr)) {
9023 }
else if (
auto *UO = dyn_cast<UnaryOperator>(PointerExpr)) {
9024 assert(UO->getOpcode() == UO_Deref &&
9025 "Unexpected unary-operator on attach-ptr-expr");
9028 assert(AttachPtrAddr.
isValid() &&
9029 "Failed to get address for attach pointer expression");
9030 return AttachPtrAddr;
9037 static std::pair<Address, Address>
9038 getAttachPtrAddrAndPteeBaseAddr(
const Expr *AttachPtrExpr,
9039 CodeGenFunction &CGF) {
9044 Address AttachPtrAddr = getAttachPtrAddr(AttachPtrExpr, CGF);
9045 assert(AttachPtrAddr.
isValid() &&
"Invalid attach pointer addr");
9047 QualType AttachPtrType =
9052 AttachPtrAddr, AttachPtrType->
castAs<PointerType>());
9053 assert(AttachPteeBaseAddr.
isValid() &&
"Invalid attach pointee base addr");
9055 return {AttachPtrAddr, AttachPteeBaseAddr};
9061 shouldEmitAttachEntry(
const Expr *PointerExpr,
const ValueDecl *MapBaseDecl,
9062 CodeGenFunction &CGF,
9063 llvm::PointerUnion<
const OMPExecutableDirective *,
9064 const OMPDeclareMapperDecl *>
9074 ->getDirectiveKind());
9083 void collectAttachPtrExprInfo(
9085 llvm::PointerUnion<
const OMPExecutableDirective *,
9086 const OMPDeclareMapperDecl *>
9091 ? OMPD_declare_mapper
9094 const auto &[AttachPtrExpr, Depth] =
9098 AttachPtrComputationOrderMap.try_emplace(
9099 AttachPtrExpr, AttachPtrComputationOrderMap.size());
9100 AttachPtrComponentDepthMap.try_emplace(AttachPtrExpr, Depth);
9101 AttachPtrExprMap.try_emplace(Components, AttachPtrExpr);
9109 void generateAllInfoForClauses(
9110 ArrayRef<const OMPClause *> Clauses, MapCombinedInfoTy &CombinedInfo,
9111 llvm::OpenMPIRBuilder &OMPBuilder,
9112 const llvm::DenseSet<CanonicalDeclPtr<const Decl>> &SkipVarSet =
9113 llvm::DenseSet<CanonicalDeclPtr<const Decl>>())
const {
9118 llvm::MapVector<CanonicalDeclPtr<const Decl>,
9119 SmallVector<SmallVector<MapInfo, 8>, 4>>
9125 [&Info, &SkipVarSet](
9126 const ValueDecl *D, MapKind
Kind,
9129 ArrayRef<OpenMPMapModifierKind> MapModifiers,
9130 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
9131 bool ReturnDevicePointer,
bool IsImplicit,
const ValueDecl *Mapper,
9132 const Expr *VarRef =
nullptr,
bool ForDeviceAddr =
false) {
9133 if (SkipVarSet.contains(D))
9135 auto It = Info.try_emplace(D, Total).first;
9136 It->second[
Kind].emplace_back(
9137 L, MapType, MapModifiers, MotionModifiers, ReturnDevicePointer,
9138 IsImplicit, Mapper, VarRef, ForDeviceAddr);
9141 for (
const auto *
Cl : Clauses) {
9142 const auto *
C = dyn_cast<OMPMapClause>(
Cl);
9146 if (llvm::is_contained(
C->getMapTypeModifiers(),
9147 OMPC_MAP_MODIFIER_present))
9149 else if (
C->getMapType() == OMPC_MAP_alloc)
9151 const auto *EI =
C->getVarRefs().begin();
9152 for (
const auto L :
C->component_lists()) {
9153 const Expr *E = (
C->getMapLoc().isValid()) ? *EI :
nullptr;
9154 InfoGen(std::get<0>(L), Kind, std::get<1>(L),
C->getMapType(),
9155 C->getMapTypeModifiers(), {},
9156 false,
C->isImplicit(), std::get<2>(L),
9161 for (
const auto *
Cl : Clauses) {
9162 const auto *
C = dyn_cast<OMPToClause>(
Cl);
9166 if (llvm::is_contained(
C->getMotionModifiers(),
9167 OMPC_MOTION_MODIFIER_present))
9169 if (llvm::is_contained(
C->getMotionModifiers(),
9170 OMPC_MOTION_MODIFIER_iterator)) {
9171 if (
auto *IteratorExpr = dyn_cast<OMPIteratorExpr>(
9172 C->getIteratorModifier()->IgnoreParenImpCasts())) {
9173 const auto *VD =
cast<VarDecl>(IteratorExpr->getIteratorDecl(0));
9178 const auto *EI =
C->getVarRefs().begin();
9179 for (
const auto L :
C->component_lists()) {
9180 InfoGen(std::get<0>(L), Kind, std::get<1>(L), OMPC_MAP_to, {},
9181 C->getMotionModifiers(),
false,
9182 C->isImplicit(), std::get<2>(L), *EI);
9186 for (
const auto *
Cl : Clauses) {
9187 const auto *
C = dyn_cast<OMPFromClause>(
Cl);
9191 if (llvm::is_contained(
C->getMotionModifiers(),
9192 OMPC_MOTION_MODIFIER_present))
9194 if (llvm::is_contained(
C->getMotionModifiers(),
9195 OMPC_MOTION_MODIFIER_iterator)) {
9196 if (
auto *IteratorExpr = dyn_cast<OMPIteratorExpr>(
9197 C->getIteratorModifier()->IgnoreParenImpCasts())) {
9198 const auto *VD =
cast<VarDecl>(IteratorExpr->getIteratorDecl(0));
9203 const auto *EI =
C->getVarRefs().begin();
9204 for (
const auto L :
C->component_lists()) {
9205 InfoGen(std::get<0>(L), Kind, std::get<1>(L), OMPC_MAP_from, {},
9206 C->getMotionModifiers(),
9207 false,
C->isImplicit(), std::get<2>(L),
9220 MapCombinedInfoTy UseDeviceDataCombinedInfo;
9222 auto &&UseDeviceDataCombinedInfoGen =
9223 [&UseDeviceDataCombinedInfo](
const ValueDecl *VD, llvm::Value *
Ptr,
9224 CodeGenFunction &CGF,
bool IsDevAddr,
9225 bool HasUdpFbNullify =
false) {
9226 UseDeviceDataCombinedInfo.Exprs.push_back(VD);
9227 UseDeviceDataCombinedInfo.BasePointers.emplace_back(Ptr);
9228 UseDeviceDataCombinedInfo.DevicePtrDecls.emplace_back(VD);
9229 UseDeviceDataCombinedInfo.DevicePointers.emplace_back(
9230 IsDevAddr ? DeviceInfoTy::Address : DeviceInfoTy::Pointer);
9236 UseDeviceDataCombinedInfo.Pointers.push_back(Ptr);
9237 UseDeviceDataCombinedInfo.Sizes.push_back(
9238 llvm::Constant::getNullValue(CGF.Int64Ty));
9239 OpenMPOffloadMappingFlags Flags =
9240 OpenMPOffloadMappingFlags::OMP_MAP_RETURN_PARAM;
9241 if (HasUdpFbNullify)
9242 Flags |= OpenMPOffloadMappingFlags::OMP_MAP_FB_NULLIFY;
9243 UseDeviceDataCombinedInfo.Types.push_back(Flags);
9244 UseDeviceDataCombinedInfo.HasAttachPtr.push_back(
false);
9245 UseDeviceDataCombinedInfo.Mappers.push_back(
nullptr);
9249 [&UseDeviceDataCombinedInfoGen](
9250 CodeGenFunction &CGF,
const Expr *IE,
const ValueDecl *VD,
9253 bool IsDevAddr,
bool IEIsAttachPtrForDevAddr =
false,
9254 bool HasUdpFbNullify =
false) {
9258 if (IsDevAddr && !IEIsAttachPtrForDevAddr) {
9259 if (IE->isGLValue())
9266 bool TreatDevAddrAsDevPtr = IEIsAttachPtrForDevAddr;
9273 UseDeviceDataCombinedInfoGen(VD, Ptr, CGF, IsDevAddr &&
9274 !TreatDevAddrAsDevPtr,
9278 auto &&IsMapInfoExist =
9279 [&Info,
this](CodeGenFunction &CGF,
const ValueDecl *VD,
const Expr *IE,
9280 const Expr *DesiredAttachPtrExpr,
bool IsDevAddr,
9281 bool HasUdpFbNullify =
false) ->
bool {
9289 if (It != Info.end()) {
9291 for (
auto &
Data : It->second) {
9292 MapInfo *CI =
nullptr;
9296 auto *It = llvm::find_if(
Data, [&](
const MapInfo &MI) {
9297 if (MI.Components.back().getAssociatedDeclaration() != VD)
9300 const Expr *MapAttachPtr = getAttachPtrExpr(MI.Components);
9301 bool Match = AttachPtrComparator.areEqual(MapAttachPtr,
9302 DesiredAttachPtrExpr);
9306 if (It !=
Data.end())
9311 CI->ForDeviceAddr =
true;
9312 CI->ReturnDevicePointer =
true;
9313 CI->HasUdpFbNullify = HasUdpFbNullify;
9317 auto PrevCI = std::next(CI->Components.rbegin());
9318 const auto *VarD = dyn_cast<VarDecl>(VD);
9319 const Expr *AttachPtrExpr = getAttachPtrExpr(CI->Components);
9320 if (CGF.CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory() ||
9322 !VD->getType().getNonReferenceType()->isPointerType() ||
9323 PrevCI == CI->Components.rend() ||
9325 VarD->hasLocalStorage() ||
9326 (isa_and_nonnull<DeclRefExpr>(AttachPtrExpr) &&
9328 CI->ForDeviceAddr = IsDevAddr;
9329 CI->ReturnDevicePointer =
true;
9330 CI->HasUdpFbNullify = HasUdpFbNullify;
9348 for (
const auto *
Cl : Clauses) {
9349 const auto *
C = dyn_cast<OMPUseDevicePtrClause>(
Cl);
9352 bool HasUdpFbNullify =
9353 C->getFallbackModifier() == OMPC_USE_DEVICE_PTR_FALLBACK_fb_nullify;
9354 for (
const auto L :
C->component_lists()) {
9357 assert(!Components.empty() &&
9358 "Not expecting empty list of components!");
9359 const ValueDecl *VD = Components.back().getAssociatedDeclaration();
9361 const Expr *IE = Components.back().getAssociatedExpression();
9369 const Expr *UDPOperandExpr =
9370 Components.front().getAssociatedExpression();
9371 if (IsMapInfoExist(CGF, VD, IE,
9373 false, HasUdpFbNullify))
9375 MapInfoGen(CGF, IE, VD, Components,
false,
9376 false, HasUdpFbNullify);
9380 llvm::SmallDenseSet<CanonicalDeclPtr<const Decl>, 4> Processed;
9381 for (
const auto *
Cl : Clauses) {
9382 const auto *
C = dyn_cast<OMPUseDeviceAddrClause>(
Cl);
9385 for (
const auto L :
C->component_lists()) {
9388 assert(!std::get<1>(L).empty() &&
9389 "Not expecting empty list of components!");
9390 const ValueDecl *VD = std::get<1>(L).back().getAssociatedDeclaration();
9391 if (!Processed.insert(VD).second)
9412 const Expr *UDAAttachPtrExpr = getAttachPtrExpr(Components);
9413 const Expr *IE = std::get<1>(L).back().getAssociatedExpression();
9414 assert((!UDAAttachPtrExpr || UDAAttachPtrExpr == IE) &&
9415 "use_device_addr operand has an attach-ptr, but does not match "
9416 "last component's expr.");
9417 if (IsMapInfoExist(CGF, VD, IE,
9421 MapInfoGen(CGF, IE, VD, Components,
9423 UDAAttachPtrExpr !=
nullptr);
9427 for (
const auto &
Data : Info) {
9428 MapCombinedInfoTy CurInfo;
9430 const ValueDecl *VD = cast_or_null<ValueDecl>(D);
9437 SmallVector<std::pair<const Expr *, MapInfo>, 16> AttachPtrMapInfoPairs;
9440 for (
const auto &M :
Data.second) {
9441 for (
const MapInfo &L : M) {
9442 assert(!L.Components.empty() &&
9443 "Not expecting declaration with no component lists.");
9445 const Expr *AttachPtrExpr = getAttachPtrExpr(L.Components);
9446 AttachPtrMapInfoPairs.emplace_back(AttachPtrExpr, L);
9451 llvm::stable_sort(AttachPtrMapInfoPairs,
9452 [
this](
const auto &LHS,
const auto &RHS) {
9453 return AttachPtrComparator(LHS.first, RHS.first);
9458 auto *It = AttachPtrMapInfoPairs.begin();
9459 while (It != AttachPtrMapInfoPairs.end()) {
9460 const Expr *AttachPtrExpr = It->first;
9462 SmallVector<MapInfo, 8> GroupLists;
9463 while (It != AttachPtrMapInfoPairs.end() &&
9464 (It->first == AttachPtrExpr ||
9465 AttachPtrComparator.areEqual(It->first, AttachPtrExpr))) {
9466 GroupLists.push_back(It->second);
9469 assert(!GroupLists.empty() &&
"GroupLists should not be empty");
9471 StructRangeInfoTy PartialStruct;
9472 AttachInfoTy AttachInfo;
9473 MapCombinedInfoTy GroupCurInfo;
9475 MapCombinedInfoTy GroupStructBaseCurInfo;
9476 for (
const MapInfo &L : GroupLists) {
9478 unsigned CurrentBasePointersIdx = GroupCurInfo.BasePointers.size();
9479 unsigned StructBasePointersIdx =
9480 GroupStructBaseCurInfo.BasePointers.size();
9482 GroupCurInfo.NonContigInfo.IsNonContiguous =
9483 L.Components.back().isNonContiguous();
9484 generateInfoForComponentList(
9485 L.MapType, L.MapModifiers, L.MotionModifiers, L.Components,
9486 GroupCurInfo, GroupStructBaseCurInfo, PartialStruct, AttachInfo,
9487 false, L.IsImplicit,
9488 true, L.Mapper, L.ForDeviceAddr, VD,
9493 if (L.ReturnDevicePointer) {
9497 assert((CurrentBasePointersIdx < GroupCurInfo.BasePointers.size() ||
9498 StructBasePointersIdx <
9499 GroupStructBaseCurInfo.BasePointers.size()) &&
9500 "Unexpected number of mapped base pointers.");
9503 const ValueDecl *RelevantVD =
9504 L.Components.back().getAssociatedDeclaration();
9505 assert(RelevantVD &&
9506 "No relevant declaration related with device pointer??");
9513 auto SetDevicePointerInfo = [&](MapCombinedInfoTy &Info,
9515 Info.DevicePtrDecls[Idx] = RelevantVD;
9516 Info.DevicePointers[Idx] = L.ForDeviceAddr
9517 ? DeviceInfoTy::Address
9518 : DeviceInfoTy::Pointer;
9520 OpenMPOffloadMappingFlags::OMP_MAP_RETURN_PARAM;
9521 if (L.HasUdpFbNullify)
9523 OpenMPOffloadMappingFlags::OMP_MAP_FB_NULLIFY;
9526 if (StructBasePointersIdx <
9527 GroupStructBaseCurInfo.BasePointers.size())
9528 SetDevicePointerInfo(GroupStructBaseCurInfo,
9529 StructBasePointersIdx);
9531 SetDevicePointerInfo(GroupCurInfo, CurrentBasePointersIdx);
9537 MapCombinedInfoTy GroupUnionCurInfo;
9538 GroupUnionCurInfo.append(GroupStructBaseCurInfo);
9539 GroupUnionCurInfo.append(GroupCurInfo);
9543 if (PartialStruct.Base.isValid()) {
9551 GroupUnionCurInfo.NonContigInfo.Dims.insert(
9552 GroupUnionCurInfo.NonContigInfo.Dims.begin(), 1);
9554 CurInfo, GroupUnionCurInfo.Types, PartialStruct, AttachInfo,
9555 !VD, OMPBuilder, VD,
9556 CombinedInfo.BasePointers.size(),
9562 CurInfo.append(GroupUnionCurInfo);
9563 if (AttachInfo.isValid())
9564 emitAttachEntry(CGF, CurInfo, AttachInfo);
9568 CombinedInfo.append(CurInfo);
9571 CombinedInfo.append(UseDeviceDataCombinedInfo);
9575 MappableExprsHandler(
const OMPExecutableDirective &Dir, CodeGenFunction &CGF)
9576 : CurDir(&Dir), CGF(CGF), AttachPtrComparator(*this) {
9578 for (
const auto *
C : Dir.getClausesOfKind<OMPFirstprivateClause>())
9579 for (
const auto *D :
C->varlist()) {
9580 const ValueDecl *VD = cast<DeclRefExpr>(D)->getDecl();
9581 if (const auto *BD = dyn_cast<BindingDecl>(VD))
9582 VD = cast<VarDecl>(BD->getDecomposedDecl());
9583 FirstPrivateDecls.try_emplace(cast<VarDecl>(VD), C->isImplicit());
9586 for (
const auto *
C : Dir.getClausesOfKind<OMPUsesAllocatorsClause>()) {
9587 for (unsigned I = 0, E = C->getNumberOfAllocators(); I < E; ++I) {
9588 OMPUsesAllocatorsClause::Data D = C->getAllocatorData(I);
9589 if (const auto *DRE = dyn_cast_or_null<DeclRefExpr>(D.AllocatorTraits))
9590 FirstPrivateDecls.try_emplace(cast<VarDecl>(DRE->getDecl()),
9592 else if (const auto *VD = dyn_cast<VarDecl>(
9593 cast<DeclRefExpr>(D.Allocator->IgnoreParenImpCasts())
9595 FirstPrivateDecls.try_emplace(VD, true);
9599 for (
const auto *
C : Dir.getClausesOfKind<OMPDefaultmapClause>())
9600 if (
C->getDefaultmapModifier() == OMPC_DEFAULTMAP_MODIFIER_firstprivate)
9601 DefaultmapFirstprivateKinds.insert(
C->getDefaultmapKind());
9603 for (
const auto *
C : Dir.getClausesOfKind<OMPIsDevicePtrClause>())
9604 for (
auto L :
C->component_lists())
9605 DevPointersMap[std::get<0>(L)].push_back(std::get<1>(L));
9607 for (
const auto *
C : Dir.getClausesOfKind<OMPHasDeviceAddrClause>())
9608 for (
auto L :
C->component_lists())
9609 HasDevAddrsMap[std::get<0>(L)].push_back(std::get<1>(L));
9611 for (
const auto *
C : Dir.getClausesOfKind<OMPMapClause>()) {
9612 if (C->getMapType() != OMPC_MAP_to)
9614 for (auto L : C->component_lists()) {
9615 const ValueDecl *VD = std::get<0>(L);
9616 const auto *RD = VD ? VD->getType()
9618 .getNonReferenceType()
9619 ->getAsCXXRecordDecl()
9621 if (RD && RD->isLambda())
9622 LambdasMap.try_emplace(std::get<0>(L), C);
9626 auto CollectAttachPtrExprsForClauseComponents = [
this](
const auto *
C) {
9627 for (
auto L :
C->component_lists()) {
9630 if (!Components.empty())
9631 collectAttachPtrExprInfo(Components, CurDir);
9637 for (
const auto *
C : Dir.getClausesOfKind<OMPMapClause>())
9638 CollectAttachPtrExprsForClauseComponents(
C);
9639 for (
const auto *
C : Dir.getClausesOfKind<OMPToClause>())
9640 CollectAttachPtrExprsForClauseComponents(
C);
9641 for (
const auto *
C : Dir.getClausesOfKind<OMPFromClause>())
9642 CollectAttachPtrExprsForClauseComponents(
C);
9643 for (
const auto *
C : Dir.getClausesOfKind<OMPUseDevicePtrClause>())
9644 CollectAttachPtrExprsForClauseComponents(
C);
9645 for (
const auto *
C : Dir.getClausesOfKind<OMPUseDeviceAddrClause>())
9646 CollectAttachPtrExprsForClauseComponents(
C);
9647 for (
const auto *
C : Dir.getClausesOfKind<OMPIsDevicePtrClause>())
9648 CollectAttachPtrExprsForClauseComponents(
C);
9649 for (
const auto *
C : Dir.getClausesOfKind<OMPHasDeviceAddrClause>())
9650 CollectAttachPtrExprsForClauseComponents(
C);
9654 MappableExprsHandler(
const OMPDeclareMapperDecl &Dir,
CodeGenFunction &CGF)
9655 : CurDir(&Dir), CGF(CGF), AttachPtrComparator(*this) {
9656 auto CollectAttachPtrExprsForClauseComponents = [
this](
const auto *
C) {
9657 for (
auto L :
C->component_lists()) {
9660 if (!Components.empty())
9661 collectAttachPtrExprInfo(Components, CurDir);
9669 if (const auto *C = dyn_cast<OMPMapClause>(Cl))
9670 CollectAttachPtrExprsForClauseComponents(C);
9671 else if (const auto *C = dyn_cast<OMPToClause>(Cl))
9672 CollectAttachPtrExprsForClauseComponents(C);
9673 else if (const auto *C = dyn_cast<OMPFromClause>(Cl))
9674 CollectAttachPtrExprsForClauseComponents(C);
9686 void emitCombinedEntry(MapCombinedInfoTy &CombinedInfo,
9687 MapFlagsArrayTy &CurTypes,
9688 const StructRangeInfoTy &PartialStruct,
9689 AttachInfoTy &AttachInfo,
bool IsMapThis,
9690 llvm::OpenMPIRBuilder &OMPBuilder,
const ValueDecl *VD,
9691 unsigned OffsetForMemberOfFlag,
9692 bool NotTargetParams)
const {
9693 if (CurTypes.size() == 1 &&
9694 ((CurTypes.back() & OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF) !=
9695 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF) &&
9696 !PartialStruct.IsArraySection)
9698 Address LBAddr = PartialStruct.LowestElem.second;
9699 Address HBAddr = PartialStruct.HighestElem.second;
9700 if (PartialStruct.HasCompleteRecord) {
9701 LBAddr = PartialStruct.LB;
9702 HBAddr = PartialStruct.LB;
9704 CombinedInfo.Exprs.push_back(VD);
9706 CombinedInfo.BasePointers.push_back(PartialStruct.Base.emitRawPointer(CGF));
9707 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
9708 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
9711 const CXXMethodDecl *MD =
9713 const CXXRecordDecl *RD = MD ? MD->
getParent() :
nullptr;
9714 bool HasBaseClass = RD && IsMapThis ? RD->
getNumBases() > 0 :
false;
9724 CombinedInfo.Pointers.push_back(PartialStruct.Base.emitRawPointer(CGF));
9729 CombinedInfo.Sizes.push_back(Size);
9731 CombinedInfo.Pointers.push_back(LB);
9734 llvm::Value *HAddr = CGF.
Builder.CreateConstGEP1_32(
9738 llvm::Value *Diff = CGF.
Builder.CreatePtrDiff(CHAddr, CLAddr);
9741 CombinedInfo.Sizes.push_back(Size);
9743 CombinedInfo.Mappers.push_back(
nullptr);
9745 CombinedInfo.Types.push_back(
9746 NotTargetParams ? OpenMPOffloadMappingFlags::OMP_MAP_NONE
9747 : !PartialStruct.PreliminaryMapData.BasePointers.empty()
9748 ? OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ
9749 : OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM);
9757 CombinedInfo.HasAttachPtr.push_back(AttachInfo.isValid());
9760 if (CurTypes.end() !=
9761 llvm::find_if(CurTypes, [](OpenMPOffloadMappingFlags
Type) {
9762 return static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>>(
9763 Type & OpenMPOffloadMappingFlags::OMP_MAP_PRESENT);
9765 CombinedInfo.Types.back() |= OpenMPOffloadMappingFlags::OMP_MAP_PRESENT;
9767 (*CurTypes.begin()) &= ~OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM;
9774 if (CurTypes.end() !=
9775 llvm::find_if(CurTypes, [](OpenMPOffloadMappingFlags
Type) {
9776 return static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>>(
9777 Type & OpenMPOffloadMappingFlags::OMP_MAP_OMPX_HOLD);
9779 CombinedInfo.Types.back() |= OpenMPOffloadMappingFlags::OMP_MAP_OMPX_HOLD;
9780 for (
auto &M : CurTypes)
9781 M |= OpenMPOffloadMappingFlags::OMP_MAP_OMPX_HOLD;
9788 OpenMPOffloadMappingFlags MemberOfFlag = OMPBuilder.getMemberOfFlag(
9789 OffsetForMemberOfFlag + CombinedInfo.BasePointers.size() - 1);
9790 for (
auto &M : CurTypes)
9791 OMPBuilder.setCorrectMemberOfFlag(M, MemberOfFlag);
9808 if (AttachInfo.isValid())
9809 AttachInfo.AttachPteeAddr = LBAddr;
9817 void generateAllInfo(
9818 MapCombinedInfoTy &CombinedInfo, llvm::OpenMPIRBuilder &OMPBuilder,
9819 const llvm::DenseSet<CanonicalDeclPtr<const Decl>> &SkipVarSet =
9820 llvm::DenseSet<CanonicalDeclPtr<const Decl>>())
const {
9822 "Expect a executable directive");
9824 generateAllInfoForClauses(CurExecDir->clauses(), CombinedInfo, OMPBuilder,
9831 void generateAllInfoForMapper(MapCombinedInfoTy &CombinedInfo,
9832 llvm::OpenMPIRBuilder &OMPBuilder)
const {
9834 "Expect a declare mapper directive");
9836 generateAllInfoForClauses(CurMapperDir->clauses(), CombinedInfo,
9841 void generateInfoForLambdaCaptures(
9842 const ValueDecl *VD, llvm::Value *Arg, MapCombinedInfoTy &CombinedInfo,
9843 llvm::DenseMap<llvm::Value *, llvm::Value *> &LambdaPointers)
const {
9851 llvm::DenseMap<const ValueDecl *, FieldDecl *> Captures;
9852 FieldDecl *ThisCapture =
nullptr;
9858 LambdaPointers.try_emplace(ThisLVal.getPointer(CGF),
9859 VDLVal.getPointer(CGF));
9860 CombinedInfo.Exprs.push_back(VD);
9861 CombinedInfo.BasePointers.push_back(ThisLVal.getPointer(CGF));
9862 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
9863 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
9864 CombinedInfo.Pointers.push_back(ThisLValVal.getPointer(CGF));
9865 CombinedInfo.Sizes.push_back(
9868 CombinedInfo.Types.push_back(
9869 OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ |
9870 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL |
9871 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF |
9872 OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT);
9873 CombinedInfo.HasAttachPtr.push_back(
false);
9874 CombinedInfo.Mappers.push_back(
nullptr);
9876 for (
const LambdaCapture &LC : RD->
captures()) {
9877 if (!LC.capturesVariable())
9882 auto It = Captures.find(VD);
9883 assert(It != Captures.end() &&
"Found lambda capture without field.");
9887 LambdaPointers.try_emplace(VarLVal.getPointer(CGF),
9888 VDLVal.getPointer(CGF));
9889 CombinedInfo.Exprs.push_back(VD);
9890 CombinedInfo.BasePointers.push_back(VarLVal.getPointer(CGF));
9891 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
9892 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
9893 CombinedInfo.Pointers.push_back(VarLValVal.getPointer(CGF));
9894 CombinedInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
9900 LambdaPointers.try_emplace(VarLVal.getPointer(CGF),
9901 VDLVal.getPointer(CGF));
9902 CombinedInfo.Exprs.push_back(VD);
9903 CombinedInfo.BasePointers.push_back(VarLVal.getPointer(CGF));
9904 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
9905 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
9906 CombinedInfo.Pointers.push_back(VarRVal.
getScalarVal());
9907 CombinedInfo.Sizes.push_back(llvm::ConstantInt::get(CGF.
Int64Ty, 0));
9909 CombinedInfo.Types.push_back(
9910 OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ |
9911 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL |
9912 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF |
9913 OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT);
9914 CombinedInfo.HasAttachPtr.push_back(
false);
9915 CombinedInfo.Mappers.push_back(
nullptr);
9920 void adjustMemberOfForLambdaCaptures(
9921 llvm::OpenMPIRBuilder &OMPBuilder,
9922 const llvm::DenseMap<llvm::Value *, llvm::Value *> &LambdaPointers,
9923 MapBaseValuesArrayTy &BasePointers, MapValuesArrayTy &Pointers,
9924 MapFlagsArrayTy &Types)
const {
9925 for (
unsigned I = 0, E = Types.size(); I < E; ++I) {
9927 if (Types[I] != (OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ |
9928 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL |
9929 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF |
9930 OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT))
9932 llvm::Value *BasePtr = LambdaPointers.lookup(BasePointers[I]);
9933 assert(BasePtr &&
"Unable to find base lambda address.");
9935 for (
unsigned J = I; J > 0; --J) {
9936 unsigned Idx = J - 1;
9937 if (Pointers[Idx] != BasePtr)
9942 assert(TgtIdx != -1 &&
"Unable to find parent lambda.");
9946 OpenMPOffloadMappingFlags MemberOfFlag =
9947 OMPBuilder.getMemberOfFlag(TgtIdx);
9948 OMPBuilder.setCorrectMemberOfFlag(Types[I], MemberOfFlag);
9954 void populateComponentListsForNonLambdaCaptureFromClauses(
9955 const ValueDecl *VD, MapDataArrayTy &DeclComponentLists,
9957 SmallVector<OMPClauseMappableExprCommon::MappableComponent, 8>>
9958 &StorageForImplicitlyAddedComponentLists)
const {
9959 if (VD && LambdasMap.count(VD))
9965 auto It = DevPointersMap.find(VD);
9966 if (It != DevPointersMap.end())
9967 for (
const auto &MCL : It->second)
9968 DeclComponentLists.emplace_back(MCL, OMPC_MAP_to,
Unknown,
9971 auto I = HasDevAddrsMap.find(VD);
9972 if (I != HasDevAddrsMap.end())
9973 for (
const auto &MCL : I->second)
9974 DeclComponentLists.emplace_back(MCL, OMPC_MAP_tofrom,
Unknown,
9978 "Expect a executable directive");
9980 for (
const auto *
C : CurExecDir->getClausesOfKind<OMPMapClause>()) {
9981 const auto *EI =
C->getVarRefs().begin();
9982 for (
const auto L :
C->decl_component_lists(VD)) {
9983 const ValueDecl *VDecl, *Mapper;
9985 const Expr *E = (
C->getMapLoc().isValid()) ? *EI :
nullptr;
9987 std::tie(VDecl, Components, Mapper) = L;
9988 assert(VDecl == VD &&
"We got information for the wrong declaration??");
9989 assert(!Components.empty() &&
9990 "Not expecting declaration with no component lists.");
9991 DeclComponentLists.emplace_back(Components,
C->getMapType(),
9992 C->getMapTypeModifiers(),
9993 C->isImplicit(), Mapper, E);
10002 addImplicitMapForAttachPtrBaseIfMemberOfCapturedVD(
10003 VD, DeclComponentLists, StorageForImplicitlyAddedComponentLists);
10005 llvm::stable_sort(DeclComponentLists, [](
const MapData &LHS,
10006 const MapData &RHS) {
10007 ArrayRef<OpenMPMapModifierKind> MapModifiers = std::get<2>(LHS);
10010 llvm::is_contained(MapModifiers, clang::OMPC_MAP_MODIFIER_present);
10011 bool HasAllocs = MapType == OMPC_MAP_alloc;
10012 MapModifiers = std::get<2>(RHS);
10013 MapType = std::get<1>(LHS);
10015 llvm::is_contained(MapModifiers, clang::OMPC_MAP_MODIFIER_present);
10016 bool HasAllocsR = MapType == OMPC_MAP_alloc;
10017 return (HasPresent && !HasPresentR) || (HasAllocs && !HasAllocsR);
10053 void addImplicitMapForAttachPtrBaseIfMemberOfCapturedVD(
10054 const ValueDecl *CapturedVD, MapDataArrayTy &DeclComponentLists,
10056 SmallVector<OMPClauseMappableExprCommon::MappableComponent, 8>>
10057 &ComponentVectorStorage)
const {
10058 bool IsThisCapture = CapturedVD ==
nullptr;
10060 for (
const auto &ComponentsAndAttachPtr : AttachPtrExprMap) {
10062 ComponentsWithAttachPtr = ComponentsAndAttachPtr.first;
10063 const Expr *AttachPtrExpr = ComponentsAndAttachPtr.second;
10064 if (!AttachPtrExpr)
10067 const auto *ME = dyn_cast<MemberExpr>(AttachPtrExpr);
10071 const Expr *
Base = ME->getBase()->IgnoreParenImpCasts();
10092 bool FoundExistingMap =
false;
10093 for (
const MapData &ExistingL : DeclComponentLists) {
10095 ExistingComponents = std::get<0>(ExistingL);
10097 if (ExistingComponents.empty())
10101 const auto &FirstComponent = ExistingComponents.front();
10102 const Expr *FirstExpr = FirstComponent.getAssociatedExpression();
10108 if (AttachPtrComparator.areEqual(FirstExpr, AttachPtrExpr)) {
10109 FoundExistingMap =
true;
10114 if (IsThisCapture) {
10115 if (
const auto *OASE = dyn_cast<ArraySectionExpr>(FirstExpr)) {
10117 FoundExistingMap =
true;
10126 if (
const auto *DRE = dyn_cast<DeclRefExpr>(FirstExpr)) {
10127 if (DRE->getDecl() == CapturedVD) {
10128 FoundExistingMap =
true;
10134 if (FoundExistingMap)
10140 ComponentVectorStorage.emplace_back();
10141 auto &AttachPtrComponents = ComponentVectorStorage.back();
10144 bool SeenAttachPtrComponent =
false;
10150 for (
size_t i = 0; i < ComponentsWithAttachPtr.size(); ++i) {
10151 const auto &Component = ComponentsWithAttachPtr[i];
10152 const Expr *ComponentExpr = Component.getAssociatedExpression();
10154 if (!SeenAttachPtrComponent && ComponentExpr != AttachPtrExpr)
10156 SeenAttachPtrComponent =
true;
10158 AttachPtrComponents.emplace_back(Component.getAssociatedExpression(),
10159 Component.getAssociatedDeclaration(),
10160 Component.isNonContiguous());
10162 assert(!AttachPtrComponents.empty() &&
10163 "Could not populate component-lists for mapping attach-ptr");
10165 DeclComponentLists.emplace_back(
10166 AttachPtrComponents, OMPC_MAP_tofrom,
Unknown,
10167 true,
nullptr, AttachPtrExpr);
10174 void generateInfoForCaptureFromClauseInfo(
10175 const MapDataArrayTy &DeclComponentListsFromClauses,
10176 const CapturedStmt::Capture *Cap, llvm::Value *Arg,
10177 MapCombinedInfoTy &CurCaptureVarInfo, llvm::OpenMPIRBuilder &OMPBuilder,
10178 unsigned OffsetForMemberOfFlag)
const {
10180 "Not expecting to generate map info for a variable array type!");
10189 if (LambdasMap.count(VD))
10195 if (VD && (DevPointersMap.count(VD) || HasDevAddrsMap.count(VD))) {
10196 CurCaptureVarInfo.Exprs.push_back(VD);
10197 CurCaptureVarInfo.BasePointers.emplace_back(Arg);
10198 CurCaptureVarInfo.DevicePtrDecls.emplace_back(VD);
10199 CurCaptureVarInfo.DevicePointers.emplace_back(DeviceInfoTy::Pointer);
10200 CurCaptureVarInfo.Pointers.push_back(Arg);
10201 CurCaptureVarInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
10204 CurCaptureVarInfo.Types.push_back(
10205 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL |
10206 OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM);
10207 CurCaptureVarInfo.HasAttachPtr.push_back(
false);
10208 CurCaptureVarInfo.Mappers.push_back(
nullptr);
10212 auto GenerateInfoForComponentLists =
10213 [&](ArrayRef<MapData> DeclComponentListsFromClauses,
10214 bool IsEligibleForTargetParamFlag) {
10215 MapCombinedInfoTy CurInfoForComponentLists;
10216 StructRangeInfoTy PartialStruct;
10217 AttachInfoTy AttachInfo;
10219 if (DeclComponentListsFromClauses.empty())
10222 generateInfoForCaptureFromComponentLists(
10223 VD, DeclComponentListsFromClauses, CurInfoForComponentLists,
10224 PartialStruct, AttachInfo, IsEligibleForTargetParamFlag);
10229 if (PartialStruct.Base.isValid()) {
10230 CurCaptureVarInfo.append(PartialStruct.PreliminaryMapData);
10232 CurCaptureVarInfo, CurInfoForComponentLists.Types,
10233 PartialStruct, AttachInfo, Cap->
capturesThis(), OMPBuilder,
10234 nullptr, OffsetForMemberOfFlag,
10235 !IsEligibleForTargetParamFlag);
10240 CurCaptureVarInfo.append(CurInfoForComponentLists);
10241 if (AttachInfo.isValid())
10242 emitAttachEntry(CGF, CurCaptureVarInfo, AttachInfo);
10266 SmallVector<std::pair<const Expr *, MapData>, 16> AttachPtrMapDataPairs;
10268 for (
const MapData &L : DeclComponentListsFromClauses) {
10271 const Expr *AttachPtrExpr = getAttachPtrExpr(Components);
10272 AttachPtrMapDataPairs.emplace_back(AttachPtrExpr, L);
10276 llvm::stable_sort(AttachPtrMapDataPairs,
10277 [
this](
const auto &LHS,
const auto &RHS) {
10278 return AttachPtrComparator(LHS.first, RHS.first);
10281 bool NoDefaultMappingDoneForVD = CurCaptureVarInfo.BasePointers.empty();
10282 bool IsFirstGroup =
true;
10286 auto *It = AttachPtrMapDataPairs.begin();
10287 while (It != AttachPtrMapDataPairs.end()) {
10288 const Expr *AttachPtrExpr = It->first;
10290 MapDataArrayTy GroupLists;
10291 while (It != AttachPtrMapDataPairs.end() &&
10292 (It->first == AttachPtrExpr ||
10293 AttachPtrComparator.areEqual(It->first, AttachPtrExpr))) {
10294 GroupLists.push_back(It->second);
10297 assert(!GroupLists.empty() &&
"GroupLists should not be empty");
10302 bool IsEligibleForTargetParamFlag =
10303 IsFirstGroup && NoDefaultMappingDoneForVD;
10305 GenerateInfoForComponentLists(GroupLists, IsEligibleForTargetParamFlag);
10306 IsFirstGroup =
false;
10313 void generateInfoForCaptureFromComponentLists(
10314 const ValueDecl *VD, ArrayRef<MapData> DeclComponentLists,
10315 MapCombinedInfoTy &CurComponentListInfo, StructRangeInfoTy &PartialStruct,
10316 AttachInfoTy &AttachInfo,
bool IsListEligibleForTargetParamFlag)
const {
10318 llvm::SmallDenseMap<
10325 for (
const MapData &L : DeclComponentLists) {
10328 ArrayRef<OpenMPMapModifierKind> MapModifiers;
10330 const ValueDecl *Mapper;
10331 const Expr *VarRef;
10332 std::tie(Components, MapType, MapModifiers, IsImplicit, Mapper, VarRef) =
10335 for (
const MapData &L1 : ArrayRef(DeclComponentLists).slice(Count)) {
10337 std::tie(Components1, MapType, MapModifiers, IsImplicit, Mapper,
10339 auto CI = Components.rbegin();
10340 auto CE = Components.rend();
10341 auto SI = Components1.rbegin();
10342 auto SE = Components1.rend();
10343 for (; CI != CE && SI != SE; ++CI, ++SI) {
10344 if (CI->getAssociatedExpression()->getStmtClass() !=
10345 SI->getAssociatedExpression()->getStmtClass())
10348 if (CI->getAssociatedDeclaration() != SI->getAssociatedDeclaration())
10353 if (CI == CE || SI == SE) {
10355 if (CI == CE && SI == SE)
10357 const auto It = (SI == SE) ? CI : SI;
10364 (std::prev(It)->getAssociatedDeclaration() &&
10366 ->getAssociatedDeclaration()
10368 ->isPointerType()) ||
10369 (It->getAssociatedDeclaration() &&
10370 It->getAssociatedDeclaration()->getType()->isPointerType() &&
10371 std::next(It) != CE && std::next(It) != SE))
10373 const MapData &BaseData = CI == CE ? L : L1;
10375 SI == SE ? Components : Components1;
10376 OverlappedData[&BaseData].push_back(SubData);
10381 llvm::SmallVector<const FieldDecl *, 4> Layout;
10382 if (!OverlappedData.empty()) {
10385 while (BaseType != OrigType) {
10391 getPlainLayout(CRD, Layout,
false);
10397 for (
auto &Pair : OverlappedData) {
10404 auto CI = First.rbegin();
10405 auto CE = First.rend();
10406 auto SI = Second.rbegin();
10407 auto SE = Second.rend();
10408 for (; CI != CE && SI != SE; ++CI, ++SI) {
10409 if (CI->getAssociatedExpression()->getStmtClass() !=
10410 SI->getAssociatedExpression()->getStmtClass())
10413 if (CI->getAssociatedDeclaration() !=
10414 SI->getAssociatedDeclaration())
10419 if (CI == CE && SI == SE)
10423 if (CI == CE || SI == SE)
10428 if (FD1->getParent() == FD2->getParent())
10429 return FD1->getFieldIndex() < FD2->getFieldIndex();
10431 llvm::find_if(Layout, [FD1, FD2](
const FieldDecl *FD) {
10432 return FD == FD1 || FD == FD2;
10440 bool AddTargetParamFlag = IsListEligibleForTargetParamFlag;
10441 MapCombinedInfoTy StructBaseCombinedInfo;
10442 for (
const auto &Pair : OverlappedData) {
10443 const MapData &L = *Pair.getFirst();
10446 ArrayRef<OpenMPMapModifierKind> MapModifiers;
10448 const ValueDecl *Mapper;
10449 const Expr *VarRef;
10450 std::tie(Components, MapType, MapModifiers, IsImplicit, Mapper, VarRef) =
10452 ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef>
10453 OverlappedComponents = Pair.getSecond();
10454 generateInfoForComponentList(
10455 MapType, MapModifiers, {}, Components, CurComponentListInfo,
10456 StructBaseCombinedInfo, PartialStruct, AttachInfo, AddTargetParamFlag,
10457 IsImplicit,
false, Mapper,
10458 false, VD, VarRef, OverlappedComponents);
10459 AddTargetParamFlag =
false;
10462 for (
const MapData &L : DeclComponentLists) {
10465 ArrayRef<OpenMPMapModifierKind> MapModifiers;
10467 const ValueDecl *Mapper;
10468 const Expr *VarRef;
10469 std::tie(Components, MapType, MapModifiers, IsImplicit, Mapper, VarRef) =
10471 auto It = OverlappedData.find(&L);
10472 if (It == OverlappedData.end())
10473 generateInfoForComponentList(
10474 MapType, MapModifiers, {}, Components, CurComponentListInfo,
10475 StructBaseCombinedInfo, PartialStruct, AttachInfo,
10476 AddTargetParamFlag, IsImplicit,
false,
10477 Mapper,
false, VD, VarRef,
10479 AddTargetParamFlag =
false;
10485 bool isEffectivelyFirstprivate(
const VarDecl *VD, QualType
Type)
const {
10487 auto I = FirstPrivateDecls.find(VD);
10488 if (I != FirstPrivateDecls.end() && !I->getSecond())
10492 if (DefaultmapFirstprivateKinds.count(OMPC_DEFAULTMAP_scalar)) {
10493 if (
Type->isScalarType())
10498 if (DefaultmapFirstprivateKinds.count(OMPC_DEFAULTMAP_pointer)) {
10499 if (
Type->isAnyPointerType())
10504 if (DefaultmapFirstprivateKinds.count(OMPC_DEFAULTMAP_aggregate)) {
10505 if (
Type->isAggregateType())
10510 return DefaultmapFirstprivateKinds.count(OMPC_DEFAULTMAP_all);
10515 void generateDefaultMapInfo(
const CapturedStmt::Capture &CI,
10516 const FieldDecl &RI, llvm::Value *CV,
10517 MapCombinedInfoTy &CombinedInfo)
const {
10518 bool IsImplicit =
true;
10521 CombinedInfo.Exprs.push_back(
nullptr);
10522 CombinedInfo.BasePointers.push_back(CV);
10523 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
10524 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
10525 CombinedInfo.Pointers.push_back(CV);
10527 CombinedInfo.Sizes.push_back(
10531 CombinedInfo.Types.push_back(OpenMPOffloadMappingFlags::OMP_MAP_TO |
10532 OpenMPOffloadMappingFlags::OMP_MAP_FROM);
10536 CombinedInfo.BasePointers.push_back(CV);
10537 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
10538 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
10539 CombinedInfo.Pointers.push_back(CV);
10540 bool IsFirstprivate =
10546 CombinedInfo.Types.push_back(
10547 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL);
10548 CombinedInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
10550 }
else if (IsFirstprivate) {
10553 CombinedInfo.Types.push_back(
10554 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL);
10556 CombinedInfo.Sizes.push_back(llvm::Constant::getNullValue(CGF.
Int64Ty));
10560 CombinedInfo.Types.push_back(OpenMPOffloadMappingFlags::OMP_MAP_NONE);
10561 CombinedInfo.Sizes.push_back(llvm::Constant::getNullValue(CGF.
Int64Ty));
10563 auto I = FirstPrivateDecls.find(VD);
10564 if (I != FirstPrivateDecls.end())
10565 IsImplicit = I->getSecond();
10571 bool IsFirstprivate = isEffectivelyFirstprivate(VD, ElementType);
10573 CombinedInfo.BasePointers.push_back(CV);
10574 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
10575 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
10578 if (IsFirstprivate && ElementType->isAnyPointerType()) {
10580 CombinedInfo.Pointers.push_back(CV);
10582 CombinedInfo.Sizes.push_back(llvm::Constant::getNullValue(CGF.
Int64Ty));
10583 CombinedInfo.Types.push_back(
10584 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL);
10586 CombinedInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
10591 CombinedInfo.Types.push_back(getMapModifiersForPrivateClauses(CI));
10592 CombinedInfo.Pointers.push_back(CV);
10594 auto I = FirstPrivateDecls.find(VD);
10595 if (I != FirstPrivateDecls.end())
10596 IsImplicit = I->getSecond();
10599 CombinedInfo.Types.back() |=
10600 OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM;
10604 CombinedInfo.Types.back() |= OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT;
10606 CombinedInfo.HasAttachPtr.push_back(
false);
10608 CombinedInfo.Mappers.push_back(
nullptr);
10620 dyn_cast<MemberExpr>(OASE->getBase()->IgnoreParenImpCasts()))
10621 return ME->getMemberDecl();
10627static llvm::Constant *
10629 MappableExprsHandler::MappingExprInfo &MapExprs) {
10632 if (!MapExprs.getMapDecl() && !MapExprs.getMapExpr())
10633 return OMPBuilder.getOrCreateDefaultSrcLocStr(SrcLocStrSize);
10636 if (!MapExprs.getMapDecl() && MapExprs.getMapExpr()) {
10640 Loc = MapExprs.getMapExpr()->getExprLoc();
10642 Loc = MapExprs.getMapDecl()->getLocation();
10645 std::string ExprName;
10646 if (MapExprs.getMapExpr()) {
10648 llvm::raw_string_ostream OS(ExprName);
10649 MapExprs.getMapExpr()->printPretty(OS,
nullptr, P);
10651 ExprName = MapExprs.getMapDecl()->getNameAsString();
10660 return OMPBuilder.getOrCreateSrcLocStr(
FileName, ExprName, PLoc.
getLine(),
10667 CodeGenFunction &CGF, MappableExprsHandler::MapCombinedInfoTy &CombinedInfo,
10669 bool IsNonContiguous =
false,
bool ForEndCall =
false) {
10672 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
10674 InsertPointTy CodeGenIP(CGF.
Builder.GetInsertPoint());
10676 auto DeviceAddrCB = [&](
unsigned int I, llvm::Value *NewDecl) {
10677 if (
const ValueDecl *DevVD = CombinedInfo.DevicePtrDecls[I]) {
10682 auto CustomMapperCB = [&](
unsigned int I) {
10683 llvm::Function *MFunc =
nullptr;
10684 if (CombinedInfo.Mappers[I]) {
10685 Info.HasMapper =
true;
10691 cantFail(OMPBuilder.emitOffloadingArraysAndArgs(
10692 AllocaIP, CodeGenIP, Info, Info.RTArgs, CombinedInfo, CustomMapperCB,
10693 IsNonContiguous, ForEndCall, DeviceAddrCB));
10697static const OMPExecutableDirective *
10699 const auto *CS = D.getInnermostCapturedStmt();
10702 const Stmt *ChildStmt =
10705 if (
const auto *NestedDir =
10706 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) {
10708 switch (D.getDirectiveKind()) {
10714 if (DKind == OMPD_teams) {
10715 Body = NestedDir->getInnermostCapturedStmt()->IgnoreContainers(
10720 if (
const auto *NND =
10721 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) {
10722 DKind = NND->getDirectiveKind();
10728 case OMPD_target_teams:
10732 case OMPD_target_parallel:
10733 case OMPD_target_simd:
10734 case OMPD_target_parallel_for:
10735 case OMPD_target_parallel_for_simd:
10737 case OMPD_target_teams_distribute:
10738 case OMPD_target_teams_distribute_simd:
10739 case OMPD_target_teams_distribute_parallel_for:
10740 case OMPD_target_teams_distribute_parallel_for_simd:
10741 case OMPD_parallel:
10743 case OMPD_parallel_for:
10744 case OMPD_parallel_master:
10745 case OMPD_parallel_sections:
10746 case OMPD_for_simd:
10747 case OMPD_parallel_for_simd:
10749 case OMPD_cancellation_point:
10750 case OMPD_ordered_standalone:
10751 case OMPD_ordered_blockassoc:
10752 case OMPD_threadprivate:
10753 case OMPD_allocate:
10758 case OMPD_sections:
10762 case OMPD_critical:
10763 case OMPD_taskyield:
10765 case OMPD_taskwait:
10766 case OMPD_taskgroup:
10772 case OMPD_target_data:
10773 case OMPD_target_exit_data:
10774 case OMPD_target_enter_data:
10775 case OMPD_distribute:
10776 case OMPD_distribute_simd:
10777 case OMPD_distribute_parallel_for:
10778 case OMPD_distribute_parallel_for_simd:
10779 case OMPD_teams_distribute:
10780 case OMPD_teams_distribute_simd:
10781 case OMPD_teams_distribute_parallel_for:
10782 case OMPD_teams_distribute_parallel_for_simd:
10783 case OMPD_target_update:
10784 case OMPD_declare_simd:
10785 case OMPD_declare_variant:
10786 case OMPD_begin_declare_variant:
10787 case OMPD_end_declare_variant:
10788 case OMPD_declare_target:
10789 case OMPD_end_declare_target:
10790 case OMPD_declare_reduction:
10791 case OMPD_declare_mapper:
10792 case OMPD_taskloop:
10793 case OMPD_taskloop_simd:
10794 case OMPD_master_taskloop:
10795 case OMPD_master_taskloop_simd:
10796 case OMPD_parallel_master_taskloop:
10797 case OMPD_parallel_master_taskloop_simd:
10798 case OMPD_requires:
10799 case OMPD_metadirective:
10802 llvm_unreachable(
"Unexpected directive.");
10862 if (
UDMMap.count(D) > 0)
10866 auto *MapperVarDecl =
10868 CharUnits ElementSize =
C.getTypeSizeInChars(Ty);
10869 llvm::Type *ElemTy =
CGM.getTypes().ConvertTypeForMem(Ty);
10872 MappableExprsHandler::MapCombinedInfoTy CombinedInfo;
10873 auto PrivatizeAndGenMapInfoCB =
10874 [&](llvm::OpenMPIRBuilder::InsertPointTy CodeGenIP, llvm::Value *PtrPHI,
10875 llvm::Value *BeginArg) -> llvm::OpenMPIRBuilder::MapInfosTy & {
10876 MapperCGF.
Builder.restoreIP(CodeGenIP);
10886 Scope.addPrivate(MapperVarDecl, PtrCurrent);
10887 (void)
Scope.Privatize();
10890 MappableExprsHandler MEHandler(*D, MapperCGF);
10891 MEHandler.generateAllInfoForMapper(CombinedInfo,
OMPBuilder);
10893 auto FillInfoMap = [&](MappableExprsHandler::MappingExprInfo &MapExpr) {
10896 if (
CGM.getCodeGenOpts().getDebugInfo() !=
10897 llvm::codegenoptions::NoDebugInfo) {
10898 CombinedInfo.Names.resize(CombinedInfo.Exprs.size());
10899 llvm::transform(CombinedInfo.Exprs, CombinedInfo.Names.begin(),
10903 return CombinedInfo;
10906 auto CustomMapperCB = [&](
unsigned I) {
10907 llvm::Function *MapperFunc =
nullptr;
10908 if (CombinedInfo.Mappers[I]) {
10912 assert(MapperFunc &&
"Expect a valid mapper function is available.");
10918 llvm::raw_svector_ostream Out(TyStr);
10919 CGM.getCXXABI().getMangleContext().mangleCanonicalTypeName(Ty, Out);
10920 std::string Name =
getName({
"omp_mapper", TyStr, D->
getName()});
10926 bool PropagatePresentToPointee =
CGM.getLangOpts().OpenMP >= 60;
10927 llvm::Function *NewFn = cantFail(
OMPBuilder.emitUserDefinedMapper(
10928 PrivatizeAndGenMapInfoCB, ElemTy, Name, CustomMapperCB,
10929 false, PropagatePresentToPointee));
10930 UDMMap.try_emplace(D, NewFn);
10937 auto I =
UDMMap.find(D);
10941 return UDMMap.lookup(D);
10954 Kind != OMPD_target_teams_loop)
10957 return llvm::ConstantInt::get(CGF.
Int64Ty, 0);
10960 if (llvm::Value *NumIterations = SizeEmitter(CGF, *LD))
10961 return NumIterations;
10962 return llvm::ConstantInt::get(CGF.
Int64Ty, 0);
10971 if (OffloadingMandatory) {
10972 CGF.
Builder.CreateUnreachable();
10974 if (RequiresOuterTask) {
10975 CapturedVars.clear();
10979 CapturedVars.end());
10980 Args.push_back(llvm::Constant::getNullValue(CGF.
Builder.getPtrTy()));
10987 llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier>
Device,
10990 llvm::Value *DeviceID;
10991 if (
Device.getPointer()) {
10993 Device.getInt() == OMPC_DEVICE_device_num) &&
10994 "Expected device_num modifier.");
10999 DeviceID = CGF.
Builder.getInt64(OMP_DEVICEID_UNDEF);
11004static std::pair<llvm::Value *, OMPDynGroupprivateFallbackType>
11006 llvm::Value *DynGP = CGF.
Builder.getInt32(0);
11007 auto DynGPFallback = OMPDynGroupprivateFallbackType::Abort;
11011 llvm::Value *DynGPVal =
11015 auto FallbackModifier = DynGPClause->getDynGroupprivateFallbackModifier();
11016 switch (FallbackModifier) {
11017 case OMPC_DYN_GROUPPRIVATE_FALLBACK_abort:
11018 DynGPFallback = OMPDynGroupprivateFallbackType::Abort;
11020 case OMPC_DYN_GROUPPRIVATE_FALLBACK_null:
11021 DynGPFallback = OMPDynGroupprivateFallbackType::Null;
11023 case OMPC_DYN_GROUPPRIVATE_FALLBACK_default_mem:
11026 DynGPFallback = OMPDynGroupprivateFallbackType::DefaultMem;
11029 llvm_unreachable(
"Unknown fallback modifier for OpenMP dyn_groupprivate");
11031 }
else if (
auto *OMPXDynCGClause =
11034 llvm::Value *DynCGMemVal = CGF.
EmitScalarExpr(OMPXDynCGClause->getSize(),
11039 return {DynGP, DynGPFallback};
11045 llvm::OpenMPIRBuilder &OMPBuilder,
11047 MappableExprsHandler::MapCombinedInfoTy &CombinedInfo) {
11049 llvm::DenseMap<llvm::Value *, llvm::Value *> LambdaPointers;
11051 auto *CV = CapturedVars.begin();
11054 CI != CE; ++CI, ++RI, ++CV) {
11055 MappableExprsHandler::MapCombinedInfoTy CurInfo;
11060 CurInfo.Exprs.push_back(
nullptr);
11061 CurInfo.BasePointers.push_back(*CV);
11062 CurInfo.DevicePtrDecls.push_back(
nullptr);
11063 CurInfo.DevicePointers.push_back(
11064 MappableExprsHandler::DeviceInfoTy::None);
11065 CurInfo.Pointers.push_back(*CV);
11066 CurInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
11069 CurInfo.Types.push_back(OpenMPOffloadMappingFlags::OMP_MAP_LITERAL |
11070 OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM |
11071 OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT);
11072 CurInfo.HasAttachPtr.push_back(
false);
11073 CurInfo.Mappers.push_back(
nullptr);
11078 bool HasEntryWithCVAsAttachPtr =
false;
11080 HasEntryWithCVAsAttachPtr =
11081 MEHandler.hasAttachEntryForCapturedVar(CapturedVD);
11084 MappableExprsHandler::MapDataArrayTy DeclComponentLists;
11087 StorageForImplicitlyAddedComponentLists;
11088 MEHandler.populateComponentListsForNonLambdaCaptureFromClauses(
11089 CapturedVD, DeclComponentLists,
11090 StorageForImplicitlyAddedComponentLists);
11101 bool HasEntryWithoutAttachPtr =
11102 llvm::any_of(DeclComponentLists, [&](
const auto &MapData) {
11104 Components = std::get<0>(MapData);
11105 return !MEHandler.getAttachPtrExpr(Components);
11110 if (DeclComponentLists.empty() ||
11111 (!HasEntryWithCVAsAttachPtr && !HasEntryWithoutAttachPtr))
11112 MEHandler.generateDefaultMapInfo(*CI, **RI, *CV, CurInfo);
11116 MEHandler.generateInfoForCaptureFromClauseInfo(
11117 DeclComponentLists, CI, *CV, CurInfo, OMPBuilder,
11118 CombinedInfo.BasePointers.size());
11123 MappedVarSet.insert(
nullptr);
11128 MEHandler.generateInfoForLambdaCaptures(CI->
getCapturedVar(), *CV,
11129 CurInfo, LambdaPointers);
11132 assert(!CurInfo.BasePointers.empty() &&
11133 "Non-existing map pointer for capture!");
11134 assert(CurInfo.BasePointers.size() == CurInfo.Pointers.size() &&
11135 CurInfo.BasePointers.size() == CurInfo.Sizes.size() &&
11136 CurInfo.BasePointers.size() == CurInfo.Types.size() &&
11137 CurInfo.BasePointers.size() == CurInfo.Mappers.size() &&
11138 "Inconsistent map information sizes!");
11141 CombinedInfo.append(CurInfo);
11144 MEHandler.adjustMemberOfForLambdaCaptures(
11145 OMPBuilder, LambdaPointers, CombinedInfo.BasePointers,
11146 CombinedInfo.Pointers, CombinedInfo.Types);
11150 MappableExprsHandler::MapCombinedInfoTy &CombinedInfo,
11151 llvm::OpenMPIRBuilder &OMPBuilder,
11158 MEHandler.generateAllInfo(CombinedInfo, OMPBuilder, SkippedVarSet);
11160 auto FillInfoMap = [&](MappableExprsHandler::MappingExprInfo &MapExpr) {
11164 llvm::codegenoptions::NoDebugInfo) {
11165 CombinedInfo.Names.resize(CombinedInfo.Exprs.size());
11166 llvm::transform(CombinedInfo.Exprs, CombinedInfo.Names.begin(),
11174 llvm::OpenMPIRBuilder &OMPBuilder,
11175 MappableExprsHandler::MapCombinedInfoTy &CombinedInfo) {
11177 MappableExprsHandler MEHandler(D, CGF);
11178 llvm::DenseSet<CanonicalDeclPtr<const Decl>> MappedVarSet;
11181 MappedVarSet, CombinedInfo);
11182 genMapInfo(MEHandler, CGF, CombinedInfo, OMPBuilder, MappedVarSet);
11185template <
typename ClauseTy>
11190 const auto *
C = D.getSingleClause<ClauseTy>();
11191 assert(!
C->varlist_empty() &&
11192 "ompx_bare requires explicit num_teams and thread_limit");
11194 for (
auto *E :
C->varlist()) {
11206 llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier>
Device,
11208 llvm::Value *&MapTypesArray, llvm::Value *&MapNamesArray,
11213 llvm::OpenMPIRBuilder &OMPBuilder = OMPRuntime->
getOMPBuilder();
11216 MappableExprsHandler::MapCombinedInfoTy CombinedInfo;
11218 genMapInfo(D, CGF, CS, CapturedVars, OMPBuilder, CombinedInfo);
11221 using OpenMPOffloadMappingFlags = llvm::omp::OpenMPOffloadMappingFlags;
11222 auto *NullPtr = llvm::Constant::getNullValue(CGF.
Builder.getPtrTy());
11223 CombinedInfo.BasePointers.push_back(NullPtr);
11224 CombinedInfo.Pointers.push_back(NullPtr);
11225 CombinedInfo.DevicePointers.push_back(
11226 llvm::OpenMPIRBuilder::DeviceInfoTy::None);
11227 CombinedInfo.Sizes.push_back(CGF.
Builder.getInt64(0));
11228 CombinedInfo.Types.push_back(OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM |
11229 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL);
11230 CombinedInfo.HasAttachPtr.push_back(
false);
11231 if (!CombinedInfo.Names.empty())
11232 CombinedInfo.Names.push_back(NullPtr);
11233 CombinedInfo.Exprs.push_back(
nullptr);
11234 CombinedInfo.Mappers.push_back(
nullptr);
11235 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
11249 MapTypesArray = Info.RTArgs.MapTypesArray;
11250 MapNamesArray = Info.RTArgs.MapNamesArray;
11252 auto &&ThenGen = [&OMPRuntime, OutlinedFn, &D, &CapturedVars,
11253 RequiresOuterTask, &CS, OffloadingMandatory,
Device,
11254 OutlinedFnID, &InputInfo, &MapTypesArray, &MapNamesArray,
11256 bool IsReverseOffloading =
Device.getInt() == OMPC_DEVICE_ancestor;
11258 if (IsReverseOffloading) {
11264 RequiresOuterTask, CS, OffloadingMandatory, CGF);
11268 bool HasNoWait = D.hasClausesOfKind<OMPNowaitClause>();
11269 unsigned NumTargetItems = InputInfo.NumberOfTargetItems;
11271 llvm::Value *BasePointersArray =
11272 InputInfo.BasePointersArray.emitRawPointer(CGF);
11273 llvm::Value *PointersArray = InputInfo.PointersArray.emitRawPointer(CGF);
11274 llvm::Value *SizesArray = InputInfo.SizesArray.emitRawPointer(CGF);
11275 llvm::Value *MappersArray = InputInfo.MappersArray.emitRawPointer(CGF);
11277 auto &&EmitTargetCallFallbackCB =
11278 [&OMPRuntime, OutlinedFn, &D, &CapturedVars, RequiresOuterTask, &CS,
11279 OffloadingMandatory, &CGF](llvm::OpenMPIRBuilder::InsertPointTy IP)
11280 -> llvm::OpenMPIRBuilder::InsertPointTy {
11283 RequiresOuterTask, CS, OffloadingMandatory, CGF);
11296 NumThreads.push_back(
11302 llvm::Value *NumIterations =
11305 llvm::OpenMPIRBuilder::InsertPointTy AllocaIP(
11308 llvm::OpenMPIRBuilder::TargetDataRTArgs RTArgs(
11309 BasePointersArray, PointersArray, SizesArray, MapTypesArray,
11310 nullptr , MappersArray, MapNamesArray);
11312 llvm::OpenMPIRBuilder::TargetKernelArgs Args(
11313 NumTargetItems, RTArgs, NumIterations, NumTeams, NumThreads,
11314 DynCGroupMem, HasNoWait, IsBare,
11315 IsBare, DynCGroupMemFallback);
11317 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
11319 CGF.
Builder, OutlinedFnID, EmitTargetCallFallbackCB, Args, DeviceID,
11321 CGF.
Builder.restoreIP(AfterIP);
11324 if (RequiresOuterTask)
11339 [&OMPRuntime, OutlinedFn, &D, &CapturedVars, RequiresOuterTask, &CS,
11342 RequiresOuterTask, CS, OffloadingMandatory, CGF);
11345 if (RequiresOuterTask) {
11355 llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID,
const Expr *IfCond,
11356 llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier>
Device,
11363 const bool OffloadingMandatory = !
CGM.getLangOpts().OpenMPIsTargetDevice &&
11364 CGM.getLangOpts().OpenMPOffloadMandatory;
11366 assert((OffloadingMandatory || OutlinedFn) &&
"Invalid outlined function!");
11368 const bool RequiresOuterTask =
11370 D.hasClausesOfKind<OMPNowaitClause>() ||
11371 D.hasClausesOfKind<OMPInReductionClause>() ||
11372 (
CGM.getLangOpts().OpenMP >= 51 &&
11376 const CapturedStmt &CS = *D.getCapturedStmt(OMPD_target);
11384 llvm::Value *MapTypesArray =
nullptr;
11385 llvm::Value *MapNamesArray =
nullptr;
11387 auto &&TargetThenGen = [
this, OutlinedFn, &D, &CapturedVars,
11388 RequiresOuterTask, &CS, OffloadingMandatory,
Device,
11389 OutlinedFnID, &InputInfo, &MapTypesArray,
11393 RequiresOuterTask, CS, OffloadingMandatory,
11394 Device, OutlinedFnID, InputInfo, MapTypesArray,
11395 MapNamesArray, SizeEmitter, CGF,
CGM);
11398 auto &&TargetElseGen =
11399 [
this, OutlinedFn, &D, &CapturedVars, RequiresOuterTask, &CS,
11402 CS, OffloadingMandatory, CGF);
11409 if (OutlinedFnID) {
11411 emitIfClause(CGF, IfCond, TargetThenGen, TargetElseGen);
11423 StringRef ParentName) {
11430 if (
auto *E = dyn_cast<OMPExecutableDirective>(S);
11439 bool RequiresDeviceCodegen =
11444 if (RequiresDeviceCodegen) {
11452 if (!
OMPBuilder.OffloadInfoManager.hasTargetRegionEntryInfo(EntryInfo))
11455 switch (E.getDirectiveKind()) {
11460 case OMPD_target_parallel:
11464 case OMPD_target_teams:
11468 case OMPD_target_teams_distribute:
11472 case OMPD_target_teams_distribute_simd:
11476 case OMPD_target_parallel_for:
11480 case OMPD_target_parallel_for_simd:
11484 case OMPD_target_simd:
11488 case OMPD_target_teams_distribute_parallel_for:
11493 case OMPD_target_teams_distribute_parallel_for_simd:
11499 case OMPD_target_teams_loop:
11503 case OMPD_target_parallel_loop:
11507 case OMPD_parallel:
11509 case OMPD_parallel_for:
11510 case OMPD_parallel_master:
11511 case OMPD_parallel_sections:
11512 case OMPD_for_simd:
11513 case OMPD_parallel_for_simd:
11515 case OMPD_cancellation_point:
11516 case OMPD_ordered_standalone:
11517 case OMPD_ordered_blockassoc:
11518 case OMPD_threadprivate:
11519 case OMPD_allocate:
11524 case OMPD_sections:
11528 case OMPD_critical:
11529 case OMPD_taskyield:
11531 case OMPD_taskwait:
11532 case OMPD_taskgroup:
11538 case OMPD_target_data:
11539 case OMPD_target_exit_data:
11540 case OMPD_target_enter_data:
11541 case OMPD_distribute:
11542 case OMPD_distribute_simd:
11543 case OMPD_distribute_parallel_for:
11544 case OMPD_distribute_parallel_for_simd:
11545 case OMPD_teams_distribute:
11546 case OMPD_teams_distribute_simd:
11547 case OMPD_teams_distribute_parallel_for:
11548 case OMPD_teams_distribute_parallel_for_simd:
11549 case OMPD_target_update:
11550 case OMPD_declare_simd:
11551 case OMPD_declare_variant:
11552 case OMPD_begin_declare_variant:
11553 case OMPD_end_declare_variant:
11554 case OMPD_declare_target:
11555 case OMPD_end_declare_target:
11556 case OMPD_declare_reduction:
11557 case OMPD_declare_mapper:
11558 case OMPD_taskloop:
11559 case OMPD_taskloop_simd:
11560 case OMPD_master_taskloop:
11561 case OMPD_master_taskloop_simd:
11562 case OMPD_parallel_master_taskloop:
11563 case OMPD_parallel_master_taskloop_simd:
11564 case OMPD_requires:
11565 case OMPD_metadirective:
11568 llvm_unreachable(
"Unknown target directive for OpenMP device codegen.");
11573 if (
const auto *E = dyn_cast<OMPExecutableDirective>(S)) {
11574 if (!E->hasAssociatedStmt() || !E->getAssociatedStmt())
11582 if (
const auto *L = dyn_cast<LambdaExpr>(S))
11591 std::optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
11592 OMPDeclareTargetDeclAttr::getDeviceType(VD);
11596 if (!IsDevice && DevTy == OMPDeclareTargetDeclAttr::DT_NoHost)
11599 if (IsDevice && DevTy == OMPDeclareTargetDeclAttr::DT_Host)
11607 if (!
CGM.getLangOpts().OpenMPIsTargetDevice) {
11608 if (
const auto *FD = dyn_cast<FunctionDecl>(GD.
getDecl()))
11610 CGM.getLangOpts().OpenMPIsTargetDevice))
11617 if (
const auto *FD = dyn_cast<FunctionDecl>(VD)) {
11618 StringRef Name =
CGM.getMangledName(GD);
11621 CGM.getLangOpts().OpenMPIsTargetDevice))
11626 return !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD) &&
11632 CGM.getLangOpts().OpenMPIsTargetDevice))
11635 if (!
CGM.getLangOpts().OpenMPIsTargetDevice)
11644 StringRef ParentName =
11649 StringRef ParentName =
11656 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
11657 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(
11659 if (!Res || *Res == OMPDeclareTargetDeclAttr::MT_Link ||
11660 ((*Res == OMPDeclareTargetDeclAttr::MT_To ||
11661 *Res == OMPDeclareTargetDeclAttr::MT_Enter) &&
11670 llvm::Constant *
Addr) {
11671 if (
CGM.getLangOpts().OMPTargetTriples.empty() &&
11672 !
CGM.getLangOpts().OpenMPIsTargetDevice)
11675 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
11676 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
11680 if (Res && *Res != OMPDeclareTargetDeclAttr::MT_Link &&
11686 if (Res && *Res == OMPDeclareTargetDeclAttr::MT_Local)
11690 if (
CGM.getLangOpts().OpenMPIsTargetDevice) {
11693 StringRef VarName =
CGM.getMangledName(VD);
11699 auto AddrOfGlobal = [&VD,
this]() {
return CGM.GetAddrOfGlobal(VD); };
11700 auto LinkageForVariable = [&VD,
this]() {
11701 return CGM.getLLVMLinkageVarDefinition(VD);
11704 std::vector<llvm::GlobalVariable *> GeneratedRefs;
11711 CGM.getMangledName(VD), GeneratedRefs,
CGM.getLangOpts().OpenMPSimd,
11712 CGM.getLangOpts().OMPTargetTriples, AddrOfGlobal, LinkageForVariable,
11713 CGM.getTypes().ConvertTypeForMem(
11714 CGM.getContext().getPointerType(VD->
getType())),
11717 for (
auto *ref : GeneratedRefs)
11718 CGM.addCompilerUsedGlobal(ref);
11731 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
11732 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
11736 if (*Res == OMPDeclareTargetDeclAttr::MT_Local ||
11737 ((*Res == OMPDeclareTargetDeclAttr::MT_To ||
11738 *Res == OMPDeclareTargetDeclAttr::MT_Enter) &&
11740 CGM.EmitGlobal(VD);
11742 assert((*Res == OMPDeclareTargetDeclAttr::MT_Link ||
11743 ((*Res == OMPDeclareTargetDeclAttr::MT_To ||
11744 *Res == OMPDeclareTargetDeclAttr::MT_Enter ||
11745 *Res == OMPDeclareTargetDeclAttr::MT_Local) &&
11747 "Expected link clause or to clause with unified memory.");
11748 (void)
CGM.getOpenMPRuntime().getAddrOfDeclareTargetVar(VD);
11756 " Expected target-based directive.");
11761 if (Clause->getClauseKind() == OMPC_unified_shared_memory) {
11763 OMPBuilder.Config.setHasRequiresUnifiedSharedMemory(
true);
11764 }
else if (
const auto *AC =
11765 dyn_cast<OMPAtomicDefaultMemOrderClause>(Clause)) {
11766 switch (AC->getAtomicDefaultMemOrderKind()) {
11767 case OMPC_ATOMIC_DEFAULT_MEM_ORDER_acq_rel:
11770 case OMPC_ATOMIC_DEFAULT_MEM_ORDER_seq_cst:
11773 case OMPC_ATOMIC_DEFAULT_MEM_ORDER_relaxed:
11789 if (!VD || !VD->
hasAttr<OMPAllocateDeclAttr>())
11791 const auto *A = VD->
getAttr<OMPAllocateDeclAttr>();
11792 switch(A->getAllocatorType()) {
11793 case OMPAllocateDeclAttr::OMPNullMemAlloc:
11794 case OMPAllocateDeclAttr::OMPDefaultMemAlloc:
11796 case OMPAllocateDeclAttr::OMPLargeCapMemAlloc:
11797 case OMPAllocateDeclAttr::OMPCGroupMemAlloc:
11798 case OMPAllocateDeclAttr::OMPHighBWMemAlloc:
11799 case OMPAllocateDeclAttr::OMPLowLatMemAlloc:
11800 case OMPAllocateDeclAttr::OMPThreadMemAlloc:
11801 case OMPAllocateDeclAttr::OMPConstMemAlloc:
11802 case OMPAllocateDeclAttr::OMPPTeamMemAlloc:
11805 case OMPAllocateDeclAttr::OMPUserDefinedMemAlloc:
11806 llvm_unreachable(
"Expected predefined allocator for the variables with the "
11807 "static storage.");
11819 if (CGM.getLangOpts().OpenMPIsTargetDevice) {
11820 SavedShouldMarkAsGlobal = CGM.getOpenMPRuntime().ShouldMarkAsGlobal;
11821 CGM.getOpenMPRuntime().ShouldMarkAsGlobal = false;
11826 if (CGM.getLangOpts().OpenMPIsTargetDevice)
11827 CGM.getOpenMPRuntime().ShouldMarkAsGlobal = SavedShouldMarkAsGlobal;
11837 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(D)) {
11839 if (
auto *F = dyn_cast_or_null<llvm::Function>(
11840 CGM.GetGlobalValue(
CGM.getMangledName(GD))))
11841 return !F->isDeclaration();
11853 llvm::Function *OutlinedFn,
11862 llvm::Value *Args[] = {
11864 CGF.
Builder.getInt32(CapturedVars.size()),
11867 RealArgs.append(std::begin(Args), std::end(Args));
11868 RealArgs.append(CapturedVars.begin(), CapturedVars.end());
11870 llvm::FunctionCallee RTLFn =
OMPBuilder.getOrCreateRuntimeFunction(
11871 CGM.getModule(), OMPRTL___kmpc_fork_teams);
11876 const Expr *NumTeams,
11877 const Expr *ThreadLimit,
11884 llvm::Value *NumTeamsVal =
11890 llvm::Value *ThreadLimitVal =
11897 llvm::Value *PushNumTeamsArgs[] = {RTLoc,
getThreadID(CGF, Loc), NumTeamsVal,
11900 CGM.getModule(), OMPRTL___kmpc_push_num_teams),
11905 const Expr *ThreadLimit,
11908 llvm::Value *ThreadLimitVal =
11915 llvm::Value *ThreadLimitArgs[] = {RTLoc,
getThreadID(CGF, Loc),
11918 CGM.getModule(), OMPRTL___kmpc_set_thread_limit),
11933 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
11935 llvm::Value *IfCondVal =
nullptr;
11940 llvm::Value *DeviceID =
nullptr;
11945 DeviceID = CGF.
Builder.getInt64(OMP_DEVICEID_UNDEF);
11949 MappableExprsHandler::MapCombinedInfoTy CombinedInfo;
11950 auto GenMapInfoCB =
11951 [&](InsertPointTy CodeGenIP) -> llvm::OpenMPIRBuilder::MapInfosTy & {
11952 CGF.
Builder.restoreIP(CodeGenIP);
11954 MappableExprsHandler MEHandler(D, CGF);
11955 MEHandler.generateAllInfo(CombinedInfo,
OMPBuilder);
11957 auto FillInfoMap = [&](MappableExprsHandler::MappingExprInfo &MapExpr) {
11960 if (
CGM.getCodeGenOpts().getDebugInfo() !=
11961 llvm::codegenoptions::NoDebugInfo) {
11962 CombinedInfo.Names.resize(CombinedInfo.Exprs.size());
11963 llvm::transform(CombinedInfo.Exprs, CombinedInfo.Names.begin(),
11967 return CombinedInfo;
11969 using BodyGenTy = llvm::OpenMPIRBuilder::BodyGenTy;
11970 auto BodyCB = [&](InsertPointTy CodeGenIP, BodyGenTy BodyGenType) {
11971 CGF.
Builder.restoreIP(CodeGenIP);
11972 switch (BodyGenType) {
11973 case BodyGenTy::Priv:
11977 case BodyGenTy::DupNoPriv:
11979 CodeGen.setAction(NoPrivAction);
11983 case BodyGenTy::NoPriv:
11985 CodeGen.setAction(NoPrivAction);
11990 return InsertPointTy(CGF.
Builder.GetInsertPoint());
11993 auto DeviceAddrCB = [&](
unsigned int I, llvm::Value *NewDecl) {
11994 if (
const ValueDecl *DevVD = CombinedInfo.DevicePtrDecls[I]) {
11999 auto CustomMapperCB = [&](
unsigned int I) {
12000 llvm::Function *MFunc =
nullptr;
12001 if (CombinedInfo.Mappers[I]) {
12002 Info.HasMapper =
true;
12013 InsertPointTy CodeGenIP(CGF.
Builder.GetInsertPoint());
12014 llvm::OpenMPIRBuilder::LocationDescription OmpLoc(CGF.
Builder);
12015 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
12017 OmpLoc, AllocaIP, CodeGenIP, {}, DeviceID,
12018 IfCondVal, Info, GenMapInfoCB, CustomMapperCB,
12019 nullptr, BodyCB, DeviceAddrCB, RTLoc));
12020 CGF.
Builder.restoreIP(AfterIP);
12032 "Expecting either target enter, exit data, or update directives.");
12035 llvm::Value *MapTypesArray =
nullptr;
12036 llvm::Value *MapNamesArray =
nullptr;
12038 auto &&ThenGen = [
this, &D,
Device, &InputInfo, &MapTypesArray,
12041 llvm::Value *DeviceID =
nullptr;
12046 DeviceID = CGF.
Builder.getInt64(OMP_DEVICEID_UNDEF);
12050 llvm::Constant *PointerNum =
12057 {RTLoc, DeviceID, PointerNum,
12065 const bool HasNowait = D.hasClausesOfKind<OMPNowaitClause>();
12066 RuntimeFunction RTLFn;
12067 switch (D.getDirectiveKind()) {
12068 case OMPD_target_enter_data:
12069 RTLFn = HasNowait ? OMPRTL___tgt_target_data_begin_nowait_mapper
12070 : OMPRTL___tgt_target_data_begin_mapper;
12072 case OMPD_target_exit_data:
12073 RTLFn = HasNowait ? OMPRTL___tgt_target_data_end_nowait_mapper
12074 : OMPRTL___tgt_target_data_end_mapper;
12076 case OMPD_target_update:
12077 RTLFn = HasNowait ? OMPRTL___tgt_target_data_update_nowait_mapper
12078 : OMPRTL___tgt_target_data_update_mapper;
12080 case OMPD_parallel:
12082 case OMPD_parallel_for:
12083 case OMPD_parallel_master:
12084 case OMPD_parallel_sections:
12085 case OMPD_for_simd:
12086 case OMPD_parallel_for_simd:
12088 case OMPD_cancellation_point:
12089 case OMPD_ordered_standalone:
12090 case OMPD_ordered_blockassoc:
12091 case OMPD_threadprivate:
12092 case OMPD_allocate:
12097 case OMPD_sections:
12101 case OMPD_critical:
12102 case OMPD_taskyield:
12104 case OMPD_taskwait:
12105 case OMPD_taskgroup:
12111 case OMPD_target_data:
12112 case OMPD_distribute:
12113 case OMPD_distribute_simd:
12114 case OMPD_distribute_parallel_for:
12115 case OMPD_distribute_parallel_for_simd:
12116 case OMPD_teams_distribute:
12117 case OMPD_teams_distribute_simd:
12118 case OMPD_teams_distribute_parallel_for:
12119 case OMPD_teams_distribute_parallel_for_simd:
12120 case OMPD_declare_simd:
12121 case OMPD_declare_variant:
12122 case OMPD_begin_declare_variant:
12123 case OMPD_end_declare_variant:
12124 case OMPD_declare_target:
12125 case OMPD_end_declare_target:
12126 case OMPD_declare_reduction:
12127 case OMPD_declare_mapper:
12128 case OMPD_taskloop:
12129 case OMPD_taskloop_simd:
12130 case OMPD_master_taskloop:
12131 case OMPD_master_taskloop_simd:
12132 case OMPD_parallel_master_taskloop:
12133 case OMPD_parallel_master_taskloop_simd:
12135 case OMPD_target_simd:
12136 case OMPD_target_teams_distribute:
12137 case OMPD_target_teams_distribute_simd:
12138 case OMPD_target_teams_distribute_parallel_for:
12139 case OMPD_target_teams_distribute_parallel_for_simd:
12140 case OMPD_target_teams:
12141 case OMPD_target_parallel:
12142 case OMPD_target_parallel_for:
12143 case OMPD_target_parallel_for_simd:
12144 case OMPD_requires:
12145 case OMPD_metadirective:
12148 llvm_unreachable(
"Unexpected standalone target data directive.");
12152 OffloadingArgs.push_back(llvm::Constant::getNullValue(CGF.
Int32Ty));
12153 OffloadingArgs.push_back(llvm::Constant::getNullValue(CGF.
VoidPtrTy));
12154 OffloadingArgs.push_back(llvm::Constant::getNullValue(CGF.
Int32Ty));
12155 OffloadingArgs.push_back(llvm::Constant::getNullValue(CGF.
VoidPtrTy));
12158 OMPBuilder.getOrCreateRuntimeFunction(
CGM.getModule(), RTLFn),
12162 auto &&TargetThenGen = [
this, &ThenGen, &D, &InputInfo, &MapTypesArray,
12166 MappableExprsHandler::MapCombinedInfoTy CombinedInfo;
12168 MappableExprsHandler MEHandler(D, CGF);
12174 D.hasClausesOfKind<OMPNowaitClause>();
12180 CGM.getPointerAlign());
12185 MapTypesArray = Info.RTArgs.MapTypesArray;
12186 MapNamesArray = Info.RTArgs.MapNamesArray;
12187 if (RequiresOuterTask)
12232 unsigned Offset = 0;
12233 if (
const auto *MD = dyn_cast<CXXMethodDecl>(FD)) {
12234 if (ParamAttrs[Offset].Kind ==
12235 llvm::OpenMPIRBuilder::DeclareSimdKindTy::Vector)
12236 CDT =
C.getPointerType(
C.getCanonicalTagType(MD->
getParent()));
12240 for (
unsigned I = 0, E = FD->
getNumParams(); I < E; ++I) {
12241 if (ParamAttrs[I + Offset].Kind ==
12242 llvm::OpenMPIRBuilder::DeclareSimdKindTy::Vector) {
12254 return C.getTypeSize(CDT);
12265 llvm::OpenMPIRBuilder::DeclareSimdKindTy Kind) {
12271 if (Kind == llvm::OpenMPIRBuilder::DeclareSimdKindTy::Uniform)
12274 if (Kind == llvm::OpenMPIRBuilder::DeclareSimdKindTy::LinearUVal ||
12275 Kind == llvm::OpenMPIRBuilder::DeclareSimdKindTy::LinearRef)
12278 if ((Kind == llvm::OpenMPIRBuilder::DeclareSimdKindTy::Linear ||
12279 Kind == llvm::OpenMPIRBuilder::DeclareSimdKindTy::LinearVal) &&
12289 unsigned Size =
C.getTypeSize(QT);
12292 if (Size != 8 && Size != 16 && Size != 32 && Size != 64 && Size != 128)
12313 llvm::OpenMPIRBuilder::DeclareSimdKindTy Kind,
12318 return C.getTypeSize(PTy);
12321 return C.getTypeSize(QT);
12323 return C.getTypeSize(
C.getUIntPtrType());
12329static std::tuple<unsigned, unsigned, bool>
12336 bool OutputBecomesInput =
false;
12341 RetType, llvm::OpenMPIRBuilder::DeclareSimdKindTy::Vector,
C));
12343 OutputBecomesInput =
true;
12345 for (
unsigned I = 0, E = FD->
getNumParams(); I < E; ++I) {
12350 assert(!Sizes.empty() &&
"Unable to determine NDS and WDS.");
12353 assert(llvm::all_of(Sizes,
12354 [](
unsigned Size) {
12355 return Size == 8 || Size == 16 || Size == 32 ||
12356 Size == 64 || Size == 128;
12360 return std::make_tuple(*llvm::min_element(Sizes), *llvm::max_element(Sizes),
12361 OutputBecomesInput);
12364static llvm::OpenMPIRBuilder::DeclareSimdBranch
12367 case OMPDeclareSimdDeclAttr::BS_Undefined:
12368 return llvm::OpenMPIRBuilder::DeclareSimdBranch::Undefined;
12369 case OMPDeclareSimdDeclAttr::BS_Inbranch:
12370 return llvm::OpenMPIRBuilder::DeclareSimdBranch::Inbranch;
12371 case OMPDeclareSimdDeclAttr::BS_Notinbranch:
12372 return llvm::OpenMPIRBuilder::DeclareSimdBranch::Notinbranch;
12374 llvm_unreachable(
"unexpected declare simd branch state");
12379 unsigned UserVLEN,
unsigned WDS,
char ISA) {
12381 if (UserVLEN == 1) {
12388 if (ISA ==
'n' && UserVLEN && !llvm::isPowerOf2_32(UserVLEN)) {
12394 if (ISA ==
's' && UserVLEN != 0 &&
12395 ((UserVLEN * WDS > 2048) || (UserVLEN * WDS % 128 != 0))) {
12404 llvm::Function *Fn) {
12409 llvm::DenseMap<const Decl *, unsigned> ParamPositions;
12411 ParamPositions.try_emplace(FD, 0);
12412 unsigned ParamPos = ParamPositions.size();
12414 ParamPositions.try_emplace(P->getCanonicalDecl(), ParamPos);
12419 ParamPositions.size());
12421 for (
const Expr *E :
Attr->uniforms()) {
12425 Pos = ParamPositions[FD];
12428 ->getCanonicalDecl();
12429 auto It = ParamPositions.find(PVD);
12430 assert(It != ParamPositions.end() &&
"Function parameter not found");
12433 ParamAttrs[Pos].Kind =
12434 llvm::OpenMPIRBuilder::DeclareSimdKindTy::Uniform;
12437 auto *NI =
Attr->alignments_begin();
12438 for (
const Expr *E :
Attr->aligneds()) {
12443 Pos = ParamPositions[FD];
12447 ->getCanonicalDecl();
12448 auto It = ParamPositions.find(PVD);
12449 assert(It != ParamPositions.end() &&
"Function parameter not found");
12451 ParmTy = PVD->getType();
12453 ParamAttrs[Pos].Alignment =
12455 ? (*NI)->EvaluateKnownConstInt(
C)
12456 : llvm::APSInt::getUnsigned(
12457 C.toCharUnitsFromBits(
C.getOpenMPDefaultSimdAlign(ParmTy))
12462 auto *SI =
Attr->steps_begin();
12463 auto *MI =
Attr->modifiers_begin();
12464 for (
const Expr *E :
Attr->linears()) {
12467 bool IsReferenceType =
false;
12470 unsigned PtrRescalingFactor = 1;
12472 Pos = ParamPositions[FD];
12474 PtrRescalingFactor =
CGM.getContext()
12475 .getTypeSizeInChars(P->getPointeeType())
12479 ->getCanonicalDecl();
12480 auto It = ParamPositions.find(PVD);
12481 assert(It != ParamPositions.end() &&
"Function parameter not found");
12483 if (
auto *P = dyn_cast<PointerType>(PVD->getType()))
12484 PtrRescalingFactor =
CGM.getContext()
12485 .getTypeSizeInChars(P->getPointeeType())
12487 else if (PVD->getType()->isReferenceType()) {
12488 IsReferenceType =
true;
12489 PtrRescalingFactor =
12491 .getTypeSizeInChars(PVD->getType().getNonReferenceType())
12495 llvm::OpenMPIRBuilder::DeclareSimdAttrTy &ParamAttr = ParamAttrs[Pos];
12496 if (*MI == OMPC_LINEAR_ref)
12497 ParamAttr.Kind = llvm::OpenMPIRBuilder::DeclareSimdKindTy::LinearRef;
12498 else if (*MI == OMPC_LINEAR_uval)
12499 ParamAttr.Kind = llvm::OpenMPIRBuilder::DeclareSimdKindTy::LinearUVal;
12500 else if (IsReferenceType)
12501 ParamAttr.Kind = llvm::OpenMPIRBuilder::DeclareSimdKindTy::LinearVal;
12503 ParamAttr.Kind = llvm::OpenMPIRBuilder::DeclareSimdKindTy::Linear;
12505 ParamAttr.StrideOrArg = llvm::APSInt::getUnsigned(1);
12509 if (
const auto *DRE =
12511 if (
const auto *StridePVD =
12512 dyn_cast<ParmVarDecl>(DRE->getDecl())) {
12513 ParamAttr.HasVarStride =
true;
12514 auto It = ParamPositions.find(StridePVD->getCanonicalDecl());
12515 assert(It != ParamPositions.end() &&
12516 "Function parameter not found");
12517 ParamAttr.StrideOrArg = llvm::APSInt::getUnsigned(It->second);
12521 ParamAttr.StrideOrArg =
Result.Val.getInt();
12527 if (!ParamAttr.HasVarStride &&
12529 llvm::OpenMPIRBuilder::DeclareSimdKindTy::Linear ||
12531 llvm::OpenMPIRBuilder::DeclareSimdKindTy::LinearRef))
12532 ParamAttr.StrideOrArg = ParamAttr.StrideOrArg * PtrRescalingFactor;
12536 llvm::APSInt VLENVal;
12538 const Expr *VLENExpr =
Attr->getSimdlen();
12543 llvm::OpenMPIRBuilder::DeclareSimdBranch State =
12545 if (
CGM.getTriple().isX86()) {
12547 assert(NumElts &&
"Non-zero simdlen/cdtsize expected");
12548 OMPBuilder.emitX86DeclareSimdFunction(Fn, NumElts, VLENVal, ParamAttrs,
12550 }
else if (
CGM.getTriple().getArch() == llvm::Triple::aarch64) {
12551 unsigned VLEN = VLENVal.getExtValue();
12554 const unsigned NDS = std::get<0>(
Data);
12555 const unsigned WDS = std::get<1>(
Data);
12556 const bool OutputBecomesInput = std::get<2>(
Data);
12557 if (
CGM.getTarget().hasFeature(
"sve")) {
12560 Fn, VLEN, ParamAttrs, State,
's', NDS, OutputBecomesInput);
12561 }
else if (
CGM.getTarget().hasFeature(
"neon")) {
12564 Fn, VLEN, ParamAttrs, State,
'n', NDS, OutputBecomesInput);
12574class DoacrossCleanupTy final :
public EHScopeStack::Cleanup {
12576 static const int DoacrossFinArgs = 2;
12579 llvm::FunctionCallee RTLFn;
12580 llvm::Value *Args[DoacrossFinArgs];
12583 DoacrossCleanupTy(llvm::FunctionCallee RTLFn,
12586 assert(CallArgs.size() == DoacrossFinArgs);
12587 std::copy(CallArgs.begin(), CallArgs.end(), std::begin(Args));
12604 QualType Int64Ty =
C.getIntTypeForBitwidth(64,
true);
12612 RD =
C.buildImplicitRecord(
"kmp_dim");
12620 RD =
KmpDimTy->castAsRecordDecl();
12622 llvm::APInt Size(32, NumIterations.size());
12628 enum { LowerFD = 0, UpperFD, StrideFD };
12630 for (
unsigned I = 0, E = NumIterations.size(); I < E; ++I) {
12635 DimsLVal, *std::next(RD->
field_begin(), UpperFD));
12637 CGF.
EmitScalarExpr(NumIterations[I]), NumIterations[I]->getType(),
12638 Int64Ty, NumIterations[I]->getExprLoc());
12642 DimsLVal, *std::next(RD->
field_begin(), StrideFD));
12649 llvm::Value *Args[] = {
12652 llvm::ConstantInt::getSigned(
CGM.Int32Ty, NumIterations.size()),
12657 llvm::FunctionCallee RTLFn =
OMPBuilder.getOrCreateRuntimeFunction(
12658 CGM.getModule(), OMPRTL___kmpc_doacross_init);
12660 llvm::Value *FiniArgs[DoacrossCleanupTy::DoacrossFinArgs] = {
12662 llvm::FunctionCallee FiniRTLFn =
OMPBuilder.getOrCreateRuntimeFunction(
12663 CGM.getModule(), OMPRTL___kmpc_doacross_fini);
12668template <
typename T>
12670 const T *
C, llvm::Value *ULoc,
12671 llvm::Value *ThreadID) {
12674 llvm::APInt Size(32,
C->getNumLoops());
12678 for (
unsigned I = 0, E =
C->getNumLoops(); I < E; ++I) {
12679 const Expr *CounterVal =
C->getLoopData(I);
12680 assert(CounterVal);
12687 llvm::Value *Args[] = {
12690 llvm::FunctionCallee RTLFn;
12692 OMPDoacrossKind<T> ODK;
12693 if (ODK.isSource(
C)) {
12695 OMPRTL___kmpc_doacross_post);
12697 assert(ODK.isSink(
C) &&
"Expect sink modifier.");
12699 OMPRTL___kmpc_doacross_wait);
12719 llvm::FunctionCallee Callee,
12721 assert(Loc.
isValid() &&
"Outlined function call location must be valid.");
12724 if (
auto *Fn = dyn_cast<llvm::Function>(Callee.getCallee())) {
12725 if (Fn->doesNotThrow()) {
12736 emitCall(CGF, Loc, OutlinedFn, Args);
12740 if (
const auto *FD = dyn_cast<FunctionDecl>(D))
12741 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(FD))
12747 const VarDecl *TargetParam)
const {
12754 const Expr *Allocator) {
12755 llvm::Value *AllocVal;
12765 AllocVal = llvm::Constant::getNullValue(
12775 if (!AllocateAlignment)
12778 return llvm::ConstantInt::get(
CGM.
SizeTy, AllocateAlignment->getQuantity());
12791 auto I = UntiedData.find(VD);
12792 if (I != UntiedData.end()) {
12793 UntiedAddr = I->second.first;
12794 UntiedRealAddr = I->second.second;
12798 if (CVD->
hasAttr<OMPAllocateDeclAttr>()) {
12807 Size = CGF.
Builder.CreateNUWAdd(
12809 Size = CGF.
Builder.CreateUDiv(Size,
CGM.getSize(Align));
12810 Size = CGF.
Builder.CreateNUWMul(Size,
CGM.getSize(Align));
12816 const auto *AA = CVD->
getAttr<OMPAllocateDeclAttr>();
12817 const Expr *Allocator = AA->getAllocator();
12821 Args.push_back(ThreadID);
12823 Args.push_back(Alignment);
12824 Args.push_back(Size);
12825 Args.push_back(AllocVal);
12826 llvm::omp::RuntimeFunction FnID =
12827 Alignment ? OMPRTL___kmpc_aligned_alloc : OMPRTL___kmpc_alloc;
12829 OMPBuilder.getOrCreateRuntimeFunction(
CGM.getModule(), FnID), Args,
12831 llvm::FunctionCallee FiniRTLFn =
OMPBuilder.getOrCreateRuntimeFunction(
12832 CGM.getModule(), OMPRTL___kmpc_free);
12840 class OMPAllocateCleanupTy final :
public EHScopeStack::Cleanup {
12841 llvm::FunctionCallee RTLFn;
12844 const Expr *AllocExpr;
12847 OMPAllocateCleanupTy(llvm::FunctionCallee RTLFn,
12849 const Expr *AllocExpr)
12850 : RTLFn(RTLFn), LocEncoding(LocEncoding),
Addr(
Addr),
12851 AllocExpr(AllocExpr) {}
12855 llvm::Value *Args[3];
12861 Args[2] = AllocVal;
12869 CGF.
EHStack.pushCleanup<OMPAllocateCleanupTy>(
12871 VDAddr, Allocator);
12872 if (UntiedRealAddr.
isValid())
12875 Region->emitUntiedSwitch(CGF);
12892 assert(CGM.getLangOpts().OpenMP &&
"Not in OpenMP mode.");
12896 CGM.getOpenMPRuntime().NontemporalDeclsStack.emplace_back();
12898 for (
const Stmt *Ref :
C->private_refs()) {
12899 const auto *SimpleRefExpr =
cast<Expr>(Ref)->IgnoreParenImpCasts();
12901 if (
const auto *DRE = dyn_cast<DeclRefExpr>(SimpleRefExpr)) {
12902 VD = DRE->getDecl();
12905 assert((ME->isImplicitCXXThis() ||
12907 "Expected member of current class.");
12908 VD = ME->getMemberDecl();
12918 CGM.getOpenMPRuntime().NontemporalDeclsStack.pop_back();
12924 std::pair<Address, Address>> &LocalVars)
12925 : CGM(CGF.CGM), NeedToPush(!LocalVars.empty()) {
12929 CGF.
CurFn, CGM.getOpenMPRuntime().UntiedLocalVarsStack.size());
12930 CGM.getOpenMPRuntime().UntiedLocalVarsStack.push_back(LocalVars);
12936 CGM.getOpenMPRuntime().UntiedLocalVarsStack.pop_back();
12940 assert(
CGM.getLangOpts().OpenMP &&
"Not in OpenMP mode.");
12942 return llvm::any_of(
12943 CGM.getOpenMPRuntime().NontemporalDeclsStack,
12947void CGOpenMPRuntime::LastprivateConditionalRAII::tryToDisableInnerAnalysis(
12951 llvm::DenseSet<CanonicalDeclPtr<const Decl>> NeedToCheckForLPCs;
12957 const CapturedStmt *CS = S.getCapturedStmt(CaptureRegions.front());
12964 for (
const auto *
C : S.getClausesOfKind<OMPPrivateClause>()) {
12965 for (
const Expr *Ref :
C->varlist()) {
12966 if (!Ref->getType()->isScalarType())
12968 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
12971 NeedToCheckForLPCs.insert(DRE->getDecl());
12974 for (
const auto *
C : S.getClausesOfKind<OMPFirstprivateClause>()) {
12975 for (
const Expr *Ref :
C->varlist()) {
12976 if (!Ref->getType()->isScalarType())
12978 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
12981 NeedToCheckForLPCs.insert(DRE->getDecl());
12984 for (
const auto *
C : S.getClausesOfKind<OMPLastprivateClause>()) {
12985 for (
const Expr *Ref :
C->varlist()) {
12986 if (!Ref->getType()->isScalarType())
12988 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
12991 NeedToCheckForLPCs.insert(DRE->getDecl());
12994 for (
const auto *
C : S.getClausesOfKind<OMPReductionClause>()) {
12995 for (
const Expr *Ref :
C->varlist()) {
12996 if (!Ref->getType()->isScalarType())
12998 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
13001 NeedToCheckForLPCs.insert(DRE->getDecl());
13004 for (
const auto *
C : S.getClausesOfKind<OMPLinearClause>()) {
13005 for (
const Expr *Ref :
C->varlist()) {
13006 if (!Ref->getType()->isScalarType())
13008 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
13011 NeedToCheckForLPCs.insert(DRE->getDecl());
13014 for (
const Decl *VD : NeedToCheckForLPCs) {
13016 llvm::reverse(
CGM.getOpenMPRuntime().LastprivateConditionalStack)) {
13017 if (
Data.DeclToUniqueName.count(VD) > 0) {
13018 if (!
Data.Disabled)
13019 NeedToAddForLPCsAsDisabled.insert(VD);
13026CGOpenMPRuntime::LastprivateConditionalRAII::LastprivateConditionalRAII(
13029 Action((CGM.getLangOpts().OpenMP >= 50 &&
13030 llvm::any_of(S.getClausesOfKind<OMPLastprivateClause>(),
13031 [](const OMPLastprivateClause *
C) {
13032 return C->getKind() ==
13033 OMPC_LASTPRIVATE_conditional;
13035 ? ActionToDo::PushAsLastprivateConditional
13036 : ActionToDo::DoNotPush) {
13037 assert(
CGM.getLangOpts().OpenMP &&
"Not in OpenMP mode.");
13038 if (
CGM.getLangOpts().OpenMP < 50 || Action == ActionToDo::DoNotPush)
13040 assert(Action == ActionToDo::PushAsLastprivateConditional &&
13041 "Expected a push action.");
13043 CGM.getOpenMPRuntime().LastprivateConditionalStack.emplace_back();
13044 for (
const auto *
C : S.getClausesOfKind<OMPLastprivateClause>()) {
13045 if (
C->getKind() != OMPC_LASTPRIVATE_conditional)
13048 for (
const Expr *Ref :
C->varlist()) {
13049 Data.DeclToUniqueName.insert(std::make_pair(
13054 Data.IVLVal = IVLVal;
13058CGOpenMPRuntime::LastprivateConditionalRAII::LastprivateConditionalRAII(
13060 :
CGM(CGF.
CGM), Action(ActionToDo::DoNotPush) {
13064 llvm::DenseSet<CanonicalDeclPtr<const Decl>> NeedToAddForLPCsAsDisabled;
13065 tryToDisableInnerAnalysis(S, NeedToAddForLPCsAsDisabled);
13066 if (!NeedToAddForLPCsAsDisabled.empty()) {
13067 Action = ActionToDo::DisableLastprivateConditional;
13068 LastprivateConditionalData &
Data =
13070 for (
const Decl *VD : NeedToAddForLPCsAsDisabled)
13071 Data.DeclToUniqueName.try_emplace(VD);
13073 Data.Disabled =
true;
13077CGOpenMPRuntime::LastprivateConditionalRAII
13080 return LastprivateConditionalRAII(CGF, S);
13084 if (CGM.getLangOpts().OpenMP < 50)
13086 if (Action == ActionToDo::DisableLastprivateConditional) {
13087 assert(CGM.getOpenMPRuntime().LastprivateConditionalStack.back().Disabled &&
13088 "Expected list of disabled private vars.");
13089 CGM.getOpenMPRuntime().LastprivateConditionalStack.pop_back();
13091 if (Action == ActionToDo::PushAsLastprivateConditional) {
13093 !CGM.getOpenMPRuntime().LastprivateConditionalStack.back().Disabled &&
13094 "Expected list of lastprivate conditional vars.");
13095 CGM.getOpenMPRuntime().LastprivateConditionalStack.pop_back();
13107 auto VI = I->getSecond().find(VD);
13108 if (VI == I->getSecond().end()) {
13109 RecordDecl *RD =
C.buildImplicitRecord(
"lasprivate.conditional");
13114 NewType =
C.getCanonicalTagType(RD);
13117 I->getSecond().try_emplace(VD, NewType, VDField, FiredField, BaseLVal);
13119 NewType = std::get<0>(VI->getSecond());
13120 VDField = std::get<1>(VI->getSecond());
13121 FiredField = std::get<2>(VI->getSecond());
13122 BaseLVal = std::get<3>(VI->getSecond());
13134class LastprivateConditionalRefChecker final
13137 const Expr *FoundE =
nullptr;
13138 const Decl *FoundD =
nullptr;
13139 StringRef UniqueDeclName;
13141 llvm::Function *FoundFn =
nullptr;
13147 llvm::reverse(LPM)) {
13148 auto It = D.DeclToUniqueName.find(E->
getDecl());
13149 if (It == D.DeclToUniqueName.end())
13155 UniqueDeclName = It->second;
13160 return FoundE == E;
13166 llvm::reverse(LPM)) {
13168 if (It == D.DeclToUniqueName.end())
13174 UniqueDeclName = It->second;
13179 return FoundE == E;
13181 bool VisitStmt(
const Stmt *S) {
13182 for (
const Stmt *Child : S->
children()) {
13185 if (
const auto *E = dyn_cast<Expr>(Child))
13193 explicit LastprivateConditionalRefChecker(
13194 ArrayRef<CGOpenMPRuntime::LastprivateConditionalData> LPM)
13196 std::tuple<const Expr *, const Decl *, StringRef, LValue, llvm::Function *>
13197 getFoundData()
const {
13198 return std::make_tuple(FoundE, FoundD, UniqueDeclName, IVLVal, FoundFn);
13205 StringRef UniqueDeclName,
13211 llvm::Constant *LastIV =
OMPBuilder.getOrCreateInternalVariable(
13212 LLIVTy,
getName({UniqueDeclName,
"iv"}));
13220 llvm::GlobalVariable *
Last =
OMPBuilder.getOrCreateInternalVariable(
13236 auto &&
CodeGen = [&LastIVLVal, &IVLVal, IVVal, &LVal, &LastLVal,
13242 llvm::Value *CmpRes;
13244 CmpRes = CGF.
Builder.CreateICmpSLE(LastIVVal, IVVal);
13247 "Loop iteration variable must be integer.");
13248 CmpRes = CGF.
Builder.CreateICmpULE(LastIVVal, IVVal);
13252 CGF.
Builder.CreateCondBr(CmpRes, ThenBB, ExitBB);
13273 "Aggregates are not supported in lastprivate conditional.");
13282 if (
CGM.getLangOpts().OpenMPSimd) {
13296 if (!Checker.Visit(LHS))
13298 const Expr *FoundE;
13299 const Decl *FoundD;
13300 StringRef UniqueDeclName;
13302 llvm::Function *FoundFn;
13303 std::tie(FoundE, FoundD, UniqueDeclName, IVLVal, FoundFn) =
13304 Checker.getFoundData();
13305 if (FoundFn != CGF.
CurFn) {
13310 "Lastprivate conditional is not found in outer region.");
13311 QualType StructTy = std::get<0>(It->getSecond());
13312 const FieldDecl* FiredDecl = std::get<2>(It->getSecond());
13323 FiredLVal, llvm::AtomicOrdering::Unordered,
13341 auto It = llvm::find_if(
13343 if (It == Range.end() || It->Fn != CGF.
CurFn)
13347 "Lastprivates must be registered already.");
13350 const CapturedStmt *CS = D.getCapturedStmt(CaptureRegions.back());
13351 for (
const auto &Pair : It->DeclToUniqueName) {
13352 const auto *VD =
cast<VarDecl>(Pair.first->getCanonicalDecl());
13355 auto I = LPCI->getSecond().find(Pair.first);
13356 assert(I != LPCI->getSecond().end() &&
13357 "Lastprivate must be rehistered already.");
13359 LValue BaseLVal = std::get<3>(I->getSecond());
13363 llvm::Value *
Cmp = CGF.
Builder.CreateIsNotNull(Res);
13367 CGF.
Builder.CreateCondBr(
Cmp, ThenBB, DoneBB);
13392 "Unknown lastprivate conditional variable.");
13393 StringRef UniqueName = It->second;
13394 llvm::GlobalVariable *GV =
CGM.getModule().getNamedGlobal(UniqueName);
13408 llvm_unreachable(
"Not supported in SIMD-only mode");
13415 llvm_unreachable(
"Not supported in SIMD-only mode");
13422 bool Tied,
unsigned &NumberOfParts) {
13423 llvm_unreachable(
"Not supported in SIMD-only mode");
13431 llvm_unreachable(
"Not supported in SIMD-only mode");
13437 const Expr *Hint) {
13438 llvm_unreachable(
"Not supported in SIMD-only mode");
13444 llvm_unreachable(
"Not supported in SIMD-only mode");
13450 const Expr *Filter) {
13451 llvm_unreachable(
"Not supported in SIMD-only mode");
13456 llvm_unreachable(
"Not supported in SIMD-only mode");
13462 llvm_unreachable(
"Not supported in SIMD-only mode");
13470 llvm_unreachable(
"Not supported in SIMD-only mode");
13477 llvm_unreachable(
"Not supported in SIMD-only mode");
13484 bool ForceSimpleCall) {
13485 llvm_unreachable(
"Not supported in SIMD-only mode");
13492 llvm_unreachable(
"Not supported in SIMD-only mode");
13497 llvm_unreachable(
"Not supported in SIMD-only mode");
13503 llvm_unreachable(
"Not supported in SIMD-only mode");
13509 llvm_unreachable(
"Not supported in SIMD-only mode");
13516 llvm_unreachable(
"Not supported in SIMD-only mode");
13522 llvm_unreachable(
"Not supported in SIMD-only mode");
13527 unsigned IVSize,
bool IVSigned,
13530 llvm_unreachable(
"Not supported in SIMD-only mode");
13538 llvm_unreachable(
"Not supported in SIMD-only mode");
13542 ProcBindKind ProcBind,
13544 llvm_unreachable(
"Not supported in SIMD-only mode");
13551 llvm_unreachable(
"Not supported in SIMD-only mode");
13557 llvm_unreachable(
"Not supported in SIMD-only mode");
13562 llvm_unreachable(
"Not supported in SIMD-only mode");
13568 llvm::AtomicOrdering AO) {
13569 llvm_unreachable(
"Not supported in SIMD-only mode");
13574 llvm::Function *TaskFunction,
13576 const Expr *IfCond,
13578 llvm_unreachable(
"Not supported in SIMD-only mode");
13585 llvm_unreachable(
"Not supported in SIMD-only mode");
13592 assert(Options.
SimpleReduction &&
"Only simple reduction is expected.");
13594 ReductionOps, Options);
13600 llvm_unreachable(
"Not supported in SIMD-only mode");
13605 bool IsWorksharingReduction) {
13606 llvm_unreachable(
"Not supported in SIMD-only mode");
13613 llvm_unreachable(
"Not supported in SIMD-only mode");
13618 llvm::Value *ReductionsPtr,
13620 llvm_unreachable(
"Not supported in SIMD-only mode");
13626 llvm_unreachable(
"Not supported in SIMD-only mode");
13632 llvm_unreachable(
"Not supported in SIMD-only mode");
13638 llvm_unreachable(
"Not supported in SIMD-only mode");
13643 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
13645 llvm_unreachable(
"Not supported in SIMD-only mode");
13650 llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID,
const Expr *IfCond,
13651 llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier>
Device,
13655 llvm_unreachable(
"Not supported in SIMD-only mode");
13659 llvm_unreachable(
"Not supported in SIMD-only mode");
13663 llvm_unreachable(
"Not supported in SIMD-only mode");
13673 llvm::Function *OutlinedFn,
13675 llvm_unreachable(
"Not supported in SIMD-only mode");
13679 const Expr *NumTeams,
13680 const Expr *ThreadLimit,
13682 llvm_unreachable(
"Not supported in SIMD-only mode");
13689 llvm_unreachable(
"Not supported in SIMD-only mode");
13695 llvm_unreachable(
"Not supported in SIMD-only mode");
13701 llvm_unreachable(
"Not supported in SIMD-only mode");
13706 llvm_unreachable(
"Not supported in SIMD-only mode");
13711 llvm_unreachable(
"Not supported in SIMD-only mode");
13716 const VarDecl *NativeParam)
const {
13717 llvm_unreachable(
"Not supported in SIMD-only mode");
13723 const VarDecl *TargetParam)
const {
13724 llvm_unreachable(
"Not supported in SIMD-only mode");
static llvm::Value * emitCopyprivateCopyFunction(CodeGenModule &CGM, llvm::Type *ArgsElemType, ArrayRef< const Expr * > CopyprivateVars, ArrayRef< const Expr * > DestExprs, ArrayRef< const Expr * > SrcExprs, ArrayRef< const Expr * > AssignmentOps, SourceLocation Loc)
static StringRef getIdentStringFromSourceLocation(CodeGenFunction &CGF, SourceLocation Loc, SmallString< 128 > &Buffer)
static void emitOffloadingArraysAndArgs(CodeGenFunction &CGF, MappableExprsHandler::MapCombinedInfoTy &CombinedInfo, CGOpenMPRuntime::TargetDataInfo &Info, llvm::OpenMPIRBuilder &OMPBuilder, bool IsNonContiguous=false, bool ForEndCall=false)
Emit the arrays used to pass the captures and map information to the offloading runtime library.
static RecordDecl * createKmpTaskTWithPrivatesRecordDecl(CodeGenModule &CGM, QualType KmpTaskTQTy, ArrayRef< PrivateDataTy > Privates)
static void emitInitWithReductionInitializer(CodeGenFunction &CGF, const OMPDeclareReductionDecl *DRD, const Expr *InitOp, Address Private, Address Original, QualType Ty)
static Address castToBase(CodeGenFunction &CGF, QualType BaseTy, QualType ElTy, Address OriginalBaseAddress, llvm::Value *Addr)
static void emitPrivatesInit(CodeGenFunction &CGF, const OMPExecutableDirective &D, Address KmpTaskSharedsPtr, LValue TDBase, const RecordDecl *KmpTaskTWithPrivatesQTyRD, QualType SharedsTy, QualType SharedsPtrTy, const OMPTaskDataTy &Data, ArrayRef< PrivateDataTy > Privates, bool ForDup)
Emit initialization for private variables in task-based directives.
static void emitClauseForBareTargetDirective(CodeGenFunction &CGF, const OMPExecutableDirective &D, llvm::SmallVectorImpl< llvm::Value * > &Values)
static llvm::Value * emitDestructorsFunction(CodeGenModule &CGM, SourceLocation Loc, QualType KmpInt32Ty, QualType KmpTaskTWithPrivatesPtrQTy, QualType KmpTaskTWithPrivatesQTy)
static void EmitOMPAggregateReduction(CodeGenFunction &CGF, QualType Type, const VarDecl *LHSVar, const VarDecl *RHSVar, const llvm::function_ref< void(CodeGenFunction &CGF, const Expr *, const Expr *, const Expr *)> &RedOpGen, const Expr *XExpr=nullptr, const Expr *EExpr=nullptr, const Expr *UpExpr=nullptr)
Emit reduction operation for each element of array (required for array sections) LHS op = RHS.
static void emitTargetCallFallback(CGOpenMPRuntime *OMPRuntime, llvm::Function *OutlinedFn, const OMPExecutableDirective &D, llvm::SmallVectorImpl< llvm::Value * > &CapturedVars, bool RequiresOuterTask, const CapturedStmt &CS, bool OffloadingMandatory, CodeGenFunction &CGF)
static llvm::Value * emitReduceInitFunction(CodeGenModule &CGM, SourceLocation Loc, ReductionCodeGen &RCG, unsigned N)
Emits reduction initializer function:
static RTCancelKind getCancellationKind(OpenMPDirectiveKind CancelRegion)
static void emitDependData(CodeGenFunction &CGF, QualType &KmpDependInfoTy, llvm::PointerUnion< unsigned *, LValue * > Pos, const OMPTaskDataTy::DependData &Data, Address DependenciesArray)
static llvm::Value * emitTaskPrivateMappingFunction(CodeGenModule &CGM, SourceLocation Loc, const OMPTaskDataTy &Data, QualType PrivatesQTy, ArrayRef< PrivateDataTy > Privates)
Emit a privates mapping function for correct handling of private and firstprivate variables.
static llvm::Value * emitReduceCombFunction(CodeGenModule &CGM, SourceLocation Loc, ReductionCodeGen &RCG, unsigned N, const Expr *ReductionOp, const Expr *LHS, const Expr *RHS, const Expr *PrivateRef)
Emits reduction combiner function:
static RecordDecl * createPrivatesRecordDecl(CodeGenModule &CGM, ArrayRef< PrivateDataTy > Privates)
static llvm::Value * getAllocatorVal(CodeGenFunction &CGF, const Expr *Allocator)
Return allocator value from expression, or return a null allocator (default when no allocator specifi...
static llvm::Function * emitProxyTaskFunction(CodeGenModule &CGM, SourceLocation Loc, OpenMPDirectiveKind Kind, QualType KmpInt32Ty, QualType KmpTaskTWithPrivatesPtrQTy, QualType KmpTaskTWithPrivatesQTy, QualType KmpTaskTQTy, QualType SharedsPtrTy, llvm::Function *TaskFunction, llvm::Value *TaskPrivatesMap)
Emit a proxy function which accepts kmp_task_t as the second argument.
static bool isAllocatableDecl(const VarDecl *VD)
static llvm::Value * getAlignmentValue(CodeGenModule &CGM, const VarDecl *VD)
Return the alignment from an allocate directive if present.
static void emitTargetCallKernelLaunch(CGOpenMPRuntime *OMPRuntime, llvm::Function *OutlinedFn, const OMPExecutableDirective &D, llvm::SmallVectorImpl< llvm::Value * > &CapturedVars, bool RequiresOuterTask, const CapturedStmt &CS, bool OffloadingMandatory, llvm::PointerIntPair< const Expr *, 2, OpenMPDeviceClauseModifier > Device, llvm::Value *OutlinedFnID, CodeGenFunction::OMPTargetDataInfo &InputInfo, llvm::Value *&MapTypesArray, llvm::Value *&MapNamesArray, llvm::function_ref< llvm::Value *(CodeGenFunction &CGF, const OMPLoopDirective &D)> SizeEmitter, CodeGenFunction &CGF, CodeGenModule &CGM)
static const OMPExecutableDirective * getNestedDistributeDirective(ASTContext &Ctx, const OMPExecutableDirective &D)
Check for inner distribute directive.
static std::pair< llvm::Value *, llvm::Value * > getPointerAndSize(CodeGenFunction &CGF, const Expr *E)
static const VarDecl * getBaseDecl(const Expr *Ref, const DeclRefExpr *&DE)
static bool getAArch64MTV(QualType QT, llvm::OpenMPIRBuilder::DeclareSimdKindTy Kind)
Maps To Vector (MTV), as defined in 4.1.1 of the AAVFABI (2021Q1).
static bool isTrivial(ASTContext &Ctx, const Expr *E)
Checks if the expression is constant or does not have non-trivial function calls.
static OpenMPSchedType getRuntimeSchedule(OpenMPScheduleClauseKind ScheduleKind, bool Chunked, bool Ordered)
Map the OpenMP loop schedule to the runtime enumeration.
static void getNumThreads(CodeGenFunction &CGF, const CapturedStmt *CS, const Expr **E, int32_t &UpperBound, bool UpperBoundOnly, llvm::Value **CondVal)
Check for a num threads constant value (stored in DefaultVal), or expression (stored in E).
static llvm::Value * emitDeviceID(llvm::PointerIntPair< const Expr *, 2, OpenMPDeviceClauseModifier > Device, CodeGenFunction &CGF)
static const OMPDeclareReductionDecl * getReductionInit(const Expr *ReductionOp)
Check if the combiner is a call to UDR combiner and if it is so return the UDR decl used for reductio...
static bool checkInitIsRequired(CodeGenFunction &CGF, ArrayRef< PrivateDataTy > Privates)
Check if duplication function is required for taskloops.
static bool validateAArch64Simdlen(CodeGenModule &CGM, SourceLocation SLoc, unsigned UserVLEN, unsigned WDS, char ISA)
static bool checkDestructorsRequired(const RecordDecl *KmpTaskTWithPrivatesQTyRD, ArrayRef< PrivateDataTy > Privates)
Checks if destructor function is required to be generated.
static llvm::TargetRegionEntryInfo getEntryInfoFromPresumedLoc(CodeGenModule &CGM, llvm::OpenMPIRBuilder &OMPBuilder, SourceLocation BeginLoc, llvm::StringRef ParentName="")
static void genMapInfo(MappableExprsHandler &MEHandler, CodeGenFunction &CGF, MappableExprsHandler::MapCombinedInfoTy &CombinedInfo, llvm::OpenMPIRBuilder &OMPBuilder, const llvm::DenseSet< CanonicalDeclPtr< const Decl > > &SkippedVarSet=llvm::DenseSet< CanonicalDeclPtr< const Decl > >())
static unsigned getAArch64LS(QualType QT, llvm::OpenMPIRBuilder::DeclareSimdKindTy Kind, ASTContext &C)
Computes the lane size (LS) of a return type or of an input parameter, as defined by LS(P) in 3....
static llvm::OpenMPIRBuilder::DeclareSimdBranch convertDeclareSimdBranch(OMPDeclareSimdDeclAttr::BranchStateTy State)
static void emitForStaticInitCall(CodeGenFunction &CGF, llvm::Value *UpdateLocation, llvm::Value *ThreadId, llvm::FunctionCallee ForStaticInitFunction, OpenMPSchedType Schedule, OpenMPScheduleClauseModifier M1, OpenMPScheduleClauseModifier M2, const CGOpenMPRuntime::StaticRTInput &Values)
static LValue loadToBegin(CodeGenFunction &CGF, QualType BaseTy, QualType ElTy, LValue BaseLV)
static void getKmpAffinityType(ASTContext &C, QualType &KmpTaskAffinityInfoTy)
Builds kmp_depend_info, if it is not built yet, and builds flags type.
static llvm::Constant * emitMappingInformation(CodeGenFunction &CGF, llvm::OpenMPIRBuilder &OMPBuilder, MappableExprsHandler::MappingExprInfo &MapExprs)
Emit a string constant containing the names of the values mapped to the offloading runtime library.
static void getDependTypes(ASTContext &C, QualType &KmpDependInfoTy, QualType &FlagsTy)
Builds kmp_depend_info, if it is not built yet, and builds flags type.
static llvm::Value * emitTaskDupFunction(CodeGenModule &CGM, SourceLocation Loc, const OMPExecutableDirective &D, QualType KmpTaskTWithPrivatesPtrQTy, const RecordDecl *KmpTaskTWithPrivatesQTyRD, const RecordDecl *KmpTaskTQTyRD, QualType SharedsTy, QualType SharedsPtrTy, const OMPTaskDataTy &Data, ArrayRef< PrivateDataTy > Privates, bool WithLastIter)
Emit task_dup function (for initialization of private/firstprivate/lastprivate vars and last_iter fla...
static std::pair< llvm::Value *, OMPDynGroupprivateFallbackType > emitDynCGroupMem(const OMPExecutableDirective &D, CodeGenFunction &CGF)
static llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseKind convertDeviceClause(const VarDecl *VD)
static llvm::Value * emitReduceFiniFunction(CodeGenModule &CGM, SourceLocation Loc, ReductionCodeGen &RCG, unsigned N)
Emits reduction finalizer function:
static void EmitOMPAggregateInit(CodeGenFunction &CGF, Address DestAddr, QualType Type, bool EmitDeclareReductionInit, const Expr *Init, const OMPDeclareReductionDecl *DRD, Address SrcAddr=Address::invalid())
Emit initialization of arrays of complex types.
static bool getAArch64PBV(QualType QT, ASTContext &C)
Pass By Value (PBV), as defined in 3.1.2 of the AAVFABI.
static void EmitDoacrossOrdered(CodeGenFunction &CGF, CodeGenModule &CGM, const T *C, llvm::Value *ULoc, llvm::Value *ThreadID)
static RTLDependenceKindTy translateDependencyKind(OpenMPDependClauseKind K)
Translates internal dependency kind into the runtime kind.
static void emitTargetCallElse(CGOpenMPRuntime *OMPRuntime, llvm::Function *OutlinedFn, const OMPExecutableDirective &D, llvm::SmallVectorImpl< llvm::Value * > &CapturedVars, bool RequiresOuterTask, const CapturedStmt &CS, bool OffloadingMandatory, CodeGenFunction &CGF)
static llvm::Function * emitCombinerOrInitializer(CodeGenModule &CGM, QualType Ty, const Expr *CombinerInitializer, const VarDecl *In, const VarDecl *Out, bool IsCombiner)
static void emitReductionCombiner(CodeGenFunction &CGF, const Expr *ReductionOp)
Emit reduction combiner.
static std::tuple< unsigned, unsigned, bool > getNDSWDS(const FunctionDecl *FD, ArrayRef< llvm::OpenMPIRBuilder::DeclareSimdAttrTy > ParamAttrs)
static std::string generateUniqueName(CodeGenModule &CGM, llvm::StringRef Prefix, const Expr *Ref)
static llvm::Function * emitParallelOrTeamsOutlinedFunction(CodeGenModule &CGM, const OMPExecutableDirective &D, const CapturedStmt *CS, const VarDecl *ThreadIDVar, OpenMPDirectiveKind InnermostKind, const StringRef OutlinedHelperName, const RegionCodeGenTy &CodeGen)
static Address emitAddrOfVarFromArray(CodeGenFunction &CGF, Address Array, unsigned Index, const VarDecl *Var)
Given an array of pointers to variables, project the address of a given variable.
static const VarDecl * getOriginalVarDecl(const ValueDecl *Decl)
For BindingDecls, returns the DecomposedDecl as the original VarDecl.
static void mergeThreadCountUpperBound(int32_t &UpperBound, int32_t Val)
Merge the thread count upper bound Val into UpperBound.
static FieldDecl * addFieldToRecordDecl(ASTContext &C, DeclContext *DC, QualType FieldTy)
static unsigned evaluateCDTSize(const FunctionDecl *FD, ArrayRef< llvm::OpenMPIRBuilder::DeclareSimdAttrTy > ParamAttrs)
static ValueDecl * getDeclFromThisExpr(const Expr *E)
static void genMapInfoForCaptures(MappableExprsHandler &MEHandler, CodeGenFunction &CGF, const CapturedStmt &CS, llvm::SmallVectorImpl< llvm::Value * > &CapturedVars, llvm::OpenMPIRBuilder &OMPBuilder, llvm::DenseSet< CanonicalDeclPtr< const Decl > > &MappedVarSet, MappableExprsHandler::MapCombinedInfoTy &CombinedInfo)
static RecordDecl * createKmpTaskTRecordDecl(CodeGenModule &CGM, OpenMPDirectiveKind Kind, QualType KmpInt32Ty, QualType KmpRoutineEntryPointerQTy)
static int addMonoNonMonoModifier(CodeGenModule &CGM, OpenMPSchedType Schedule, OpenMPScheduleClauseModifier M1, OpenMPScheduleClauseModifier M2)
static mlir::omp::DeclareTargetCaptureClause convertCaptureClause(OMPDeclareTargetDeclAttr::MapTypeTy mapTy)
static bool isAssumedToBeNotEmitted(const ValueDecl *vd, bool isDevice)
Returns true if the declaration should be skipped based on its device_type attribute and the current ...
Result
Implement __builtin_bit_cast and related operations.
This file defines OpenMP AST classes for clauses.
Defines some OpenMP-specific enums and functions.
Defines the SourceManager interface.
This file defines OpenMP AST classes for executable directives and clauses.
__DEVICE__ int max(int __a, int __b)
This represents clause 'affinity' in the 'pragma omp task'-based directives.
ValueDecl * getAssociatedDeclaration() const
Expr * getAssociatedExpression() const
static std::pair< const Expr *, std::optional< size_t > > findAttachPtrExpr(MappableExprComponentListRef Components, OpenMPDirectiveKind CurDirKind)
Find the attach pointer expression from a list of mappable expression components.
static QualType getComponentExprElementType(const Expr *Exp)
Get the type of an element of a ComponentList Expr Exp.
ArrayRef< MappableComponent > MappableExprComponentListRef
This represents implicit clause 'depend' for the 'pragma omp task' directive.
This represents 'detach' clause in the 'pragma omp task' directive.
This represents 'device' clause in the 'pragma omp ...' directive.
This represents the 'doacross' clause for the 'pragma omp ordered' directive.
This represents 'dyn_groupprivate' clause in 'pragma omp target ...' and 'pragma omp teams ....
This is a common base class for loop directives ('omp simd', 'omp for', 'omp for simd' etc....
Expr * getLowerBoundVariable() const
Expr * getUpperBoundVariable() const
Expr * getStrideVariable() const
This represents clause 'map' in the 'pragma omp ...' directives.
This represents clause 'nontemporal' in the 'pragma omp ...' directives.
This represents 'num_teams' clause in the 'pragma omp ...' directive.
This represents 'thread_limit' clause in the 'pragma omp ...' directive.
This represents clause 'uses_allocators' in the 'pragma omp target'-based directives.
This represents 'ompx_attribute' clause in a directive that might generate an outlined function.
This represents 'ompx_bare' clause in the 'pragma omp target teams ...' directive.
This represents 'ompx_dyn_cgroup_mem' clause in the 'pragma omp target ...' directive.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
SourceManager & getSourceManager()
const ConstantArrayType * getAsConstantArrayType(QualType T) const
CharUnits getTypeAlignInChars(QualType T) const
Return the ABI-specified alignment of a (complete) type T, in characters.
const ASTRecordLayout & getASTRecordLayout(const RecordDecl *D) const
Get or compute information about the layout of the specified record (struct/union/class) D,...
QualType getPointerType(QualType T) const
Return the uniqued reference to the type for a pointer to the specified type.
QualType getConstantArrayType(QualType EltTy, const llvm::APInt &ArySize, const Expr *SizeExpr, ArraySizeModifier ASM, unsigned IndexTypeQuals) const
Return the unique reference to the type for a constant array of the specified element type.
const LangOptions & getLangOpts() const
QualType getIntTypeForBitwidth(unsigned DestWidth, unsigned Signed) const
getIntTypeForBitwidth - sets integer QualTy according to specified details: bitwidth,...
CharUnits getDeclAlign(const Decl *D, bool ForAlignof=false) const
Return a conservative estimate of the alignment of the specified decl D.
int64_t toBits(CharUnits CharSize) const
Convert a size in characters to a size in bits.
const ArrayType * getAsArrayType(QualType T) const
Type Query functions.
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
static bool hasSameType(QualType T1, QualType T2)
Determine whether the given types T1 and T2 are equivalent.
const VariableArrayType * getAsVariableArrayType(QualType T) const
QualType getSizeType() const
Return the unique type for "size_t" (C99 7.17), defined in <stddef.h>.
unsigned getTypeAlign(QualType T) const
Return the ABI-specified alignment of a (complete) type T, in bits.
CharUnits getSize() const
getSize - Get the record size in characters.
uint64_t getFieldOffset(unsigned FieldNo) const
getFieldOffset - Get the offset of the given field index, in bits.
CharUnits getNonVirtualSize() const
getNonVirtualSize - Get the non-virtual size (in chars) of an object, which is the size of the object...
static QualType getBaseOriginalType(const Expr *Base)
Return original type of the base expression for array section.
Represents an array type, per C99 6.7.5.2 - Array Declarators.
Attr - This represents one attribute.
A binding in a decomposition declaration.
Expr * getBinding() const
Get the expression to which this declaration is bound.
DecompositionDecl * getDecomposedDecl() const
Get the decomposition declaration that this binding represents a decomposition of.
Represents a base class of a C++ class.
Represents a C++ constructor within a class.
Represents a C++ destructor within a class.
const CXXRecordDecl * getParent() const
Return the parent of this method declaration, which is the class in which this method is defined.
QualType getFunctionObjectParameterType() const
Represents a C++ struct/union/class.
bool isLambda() const
Determine whether this class describes a lambda function object.
void getCaptureFields(llvm::DenseMap< const ValueDecl *, FieldDecl * > &Captures, FieldDecl *&ThisCapture) const
For a closure type, retrieve the mapping from captured variables and this to the non-static data memb...
unsigned getNumBases() const
Retrieves the number of base classes of this class.
base_class_range vbases()
capture_const_range captures() const
CXXDestructorDecl * getDestructor() const
Returns the destructor decl for this class.
CanProxy< U > castAs() const
A wrapper class around a pointer that always points to its canonical declaration.
Describes the capture of either a variable, or 'this', or variable-length array type.
bool capturesVariableByCopy() const
Determine whether this capture handles a variable by copy.
VarDecl * getCapturedVar() const
Retrieve the declaration of the variable being captured.
bool capturesVariableArrayType() const
Determine whether this capture handles a variable-length array type.
bool capturesThis() const
Determine whether this capture handles the C++ 'this' pointer.
bool capturesVariable() const
Determine whether this capture handles a variable (by reference).
This captures a statement into a function.
const Capture * const_capture_iterator
capture_iterator capture_end() const
Retrieve an iterator pointing past the end of the sequence of captures.
const RecordDecl * getCapturedRecordDecl() const
Retrieve the record declaration for captured variables.
Stmt * getCapturedStmt()
Retrieve the statement being captured.
bool capturesVariable(const VarDecl *Var) const
True if this variable has been captured.
capture_iterator capture_begin()
Retrieve an iterator pointing to the first capture.
This is an opaque type for sizes expressed in character units.
bool isZero() const
Test whether the quantity equals zero.
CharUnits alignTo(CharUnits Align) const
Returns the next integer (mod 2**64) that is greater than or equal to this quantity and is a multiple...
llvm::Align getAsAlign() const
Returns Quantity as a valid llvm::Align, Beware llvm::Align assumes power of two 8-bit bytes.
QuantityType getQuantity() const
Get the raw integer representation of this quantity.
CharUnits alignmentOfArrayElement(CharUnits elementSize) const
Given that this is the alignment of the first element of an array, return the minimum alignment of an...
static CharUnits fromQuantity(QuantityType Quantity)
Construct a CharUnits quantity from a raw integer type.
std::string SampleProfileFile
Name of the profile file to use with -fprofile-sample-use.
Like RawAddress, an abstract representation of an aligned address, but the pointer contained in this ...
llvm::Value * emitRawPointer(CodeGenFunction &CGF) const
Return the pointer contained in this class after authenticating it and adding offset to it if necessa...
CharUnits getAlignment() const
llvm::Type * getElementType() const
Return the type of the values stored in this address.
Address withPointer(llvm::Value *NewPointer, KnownNonNull_t IsKnownNonNull) const
Return address with different pointer, but same element type and alignment.
Address withElementType(llvm::Type *ElemTy) const
Return address with different element type, but same pointer and alignment.
llvm::PointerType * getType() const
Return the type of the pointer value.
static ApplyDebugLocation CreateArtificial(CodeGenFunction &CGF)
Apply TemporaryLocation if it is valid.
static ApplyDebugLocation CreateDefaultArtificial(CodeGenFunction &CGF, SourceLocation TemporaryLocation)
Apply TemporaryLocation if it is valid.
static ApplyDebugLocation CreateEmpty(CodeGenFunction &CGF)
Set the IRBuilder to not attach debug locations.
llvm::StoreInst * CreateStore(llvm::Value *Val, Address Addr, bool IsVolatile=false)
Address CreateGEP(CodeGenFunction &CGF, Address Addr, llvm::Value *Index, const llvm::Twine &Name="")
Address CreatePointerBitCastOrAddrSpaceCast(Address Addr, llvm::Type *Ty, llvm::Type *ElementTy, const llvm::Twine &Name="")
Address CreateConstArrayGEP(Address Addr, uint64_t Index, const llvm::Twine &Name="")
Given addr = [n x T]* ... produce name = getelementptr inbounds addr, i64 0, i64 index where i64 is a...
llvm::LoadInst * CreateLoad(Address Addr, const llvm::Twine &Name="")
llvm::CallInst * CreateMemCpy(Address Dest, Address Src, llvm::Value *Size, bool IsVolatile=false)
Address CreateConstGEP(Address Addr, uint64_t Index, const llvm::Twine &Name="")
Given addr = T* ... produce name = getelementptr inbounds addr, i64 index where i64 is actually the t...
Address CreateAddrSpaceCast(Address Addr, llvm::Type *Ty, llvm::Type *ElementTy, const llvm::Twine &Name="")
CGFunctionInfo - Class to encapsulate the information about a function definition.
DisableAutoDeclareTargetRAII(CodeGenModule &CGM)
~DisableAutoDeclareTargetRAII()
~LastprivateConditionalRAII()
static LastprivateConditionalRAII disable(CodeGenFunction &CGF, const OMPExecutableDirective &S)
NontemporalDeclsRAII(CodeGenModule &CGM, const OMPLoopDirective &S)
Struct that keeps all the relevant information that should be kept throughout a 'target data' region.
llvm::DenseMap< const ValueDecl *, llvm::Value * > CaptureDeviceAddrMap
Map between the a declaration of a capture and the corresponding new llvm address where the runtime r...
~UntiedTaskLocalDeclsRAII()
UntiedTaskLocalDeclsRAII(CodeGenFunction &CGF, const llvm::MapVector< CanonicalDeclPtr< const VarDecl >, std::pair< Address, Address > > &LocalVars)
virtual Address emitThreadIDAddress(CodeGenFunction &CGF, SourceLocation Loc)
Emits address of the word in a memory where current thread id is stored.
llvm::StringSet ThreadPrivateWithDefinition
Set of threadprivate variables with the generated initializer.
CGOpenMPRuntime(CodeGenModule &CGM)
void emitUpdateDependObjectsClause(CodeGenFunction &CGF, LValue DepobjLVal, OpenMPDependClauseKind NewDepKind, SourceLocation Loc)
Updates the dependency kind in the specified depobj object.
virtual void emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc, const OMPExecutableDirective &D, llvm::Function *TaskFunction, QualType SharedsTy, Address Shareds, const Expr *IfCond, const OMPTaskDataTy &Data)
Emit task region for the task directive.
void createOffloadEntriesAndInfoMetadata()
Creates all the offload entries in the current compilation unit along with the associated metadata.
const Expr * getNumTeamsExprForTargetDirective(CodeGenFunction &CGF, const OMPExecutableDirective &D, int32_t &MinTeamsVal, int32_t &MaxTeamsVal)
Emit the number of teams for a target directive.
virtual Address getAddrOfThreadPrivate(CodeGenFunction &CGF, const VarDecl *VD, Address VDAddr, SourceLocation Loc)
Returns address of the threadprivate variable for the current thread.
void emitDeferredTargetDecls() const
Emit deferred declare target variables marked for deferred emission.
virtual llvm::Value * emitForNext(CodeGenFunction &CGF, SourceLocation Loc, unsigned IVSize, bool IVSigned, Address IL, Address LB, Address UB, Address ST)
Call __kmpc_dispatch_next( ident_t *loc, kmp_int32 tid, kmp_int32 *p_lastiter, kmp_int[32|64] *p_lowe...
bool markAsGlobalTarget(GlobalDecl GD)
Marks the declaration as already emitted for the device code and returns true, if it was marked alrea...
virtual void emitParallelCall(CodeGenFunction &CGF, SourceLocation Loc, llvm::Function *OutlinedFn, ArrayRef< llvm::Value * > CapturedVars, const Expr *IfCond, llvm::Value *NumThreads, OpenMPNumThreadsClauseModifier NumThreadsModifier=OMPC_NUMTHREADS_unknown, OpenMPSeverityClauseKind Severity=OMPC_SEVERITY_fatal, const Expr *Message=nullptr)
Emits code for parallel or serial call of the OutlinedFn with variables captured in a record which ad...
llvm::SmallDenseSet< CanonicalDeclPtr< const Decl > > NontemporalDeclsSet
virtual void emitTargetDataStandAloneCall(CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, const Expr *Device)
Emit the data mapping/movement code associated with the directive D that should be of the form 'targe...
virtual void emitNumThreadsClause(CodeGenFunction &CGF, llvm::Value *NumThreads, SourceLocation Loc, OpenMPNumThreadsClauseModifier Modifier=OMPC_NUMTHREADS_unknown, OpenMPSeverityClauseKind Severity=OMPC_SEVERITY_fatal, SourceLocation SeverityLoc=SourceLocation(), const Expr *Message=nullptr, SourceLocation MessageLoc=SourceLocation())
Emits call to void __kmpc_push_num_threads(ident_t *loc, kmp_int32global_tid, kmp_int32 num_threads) ...
QualType SavedKmpTaskloopTQTy
Saved kmp_task_t for taskloop-based directive.
virtual void emitSingleRegion(CodeGenFunction &CGF, const RegionCodeGenTy &SingleOpGen, SourceLocation Loc, ArrayRef< const Expr * > CopyprivateVars, ArrayRef< const Expr * > DestExprs, ArrayRef< const Expr * > SrcExprs, ArrayRef< const Expr * > AssignmentOps)
Emits a single region.
virtual bool emitTargetGlobal(GlobalDecl GD)
Emit the global GD if it is meaningful for the target.
void setLocThreadIdInsertPt(CodeGenFunction &CGF, bool AtCurrentPoint=false)
std::string getOutlinedHelperName(StringRef Name) const
Get the function name of an outlined region.
bool HasEmittedDeclareTargetRegion
Flag for keeping track of weather a device routine has been emitted.
llvm::Constant * getOrCreateThreadPrivateCache(const VarDecl *VD)
If the specified mangled name is not in the module, create and return threadprivate cache object.
virtual Address getTaskReductionItem(CodeGenFunction &CGF, SourceLocation Loc, llvm::Value *ReductionsPtr, LValue SharedLVal)
Get the address of void * type of the privatue copy of the reduction item specified by the SharedLVal...
virtual void emitForDispatchDeinit(CodeGenFunction &CGF, SourceLocation Loc)
This is used for non static scheduled types and when the ordered clause is present on the loop constr...
void emitCall(CodeGenFunction &CGF, SourceLocation Loc, llvm::FunctionCallee Callee, ArrayRef< llvm::Value * > Args={}) const
Emits Callee function call with arguments Args with location Loc.
virtual void getDefaultScheduleAndChunk(CodeGenFunction &CGF, const OMPLoopDirective &S, OpenMPScheduleClauseKind &ScheduleKind, const Expr *&ChunkExpr) const
Choose default schedule type and chunk value for the schedule clause.
virtual std::pair< llvm::Function *, llvm::Function * > getUserDefinedReduction(const OMPDeclareReductionDecl *D)
Get combiner/initializer for the specified user-defined reduction, if any.
virtual bool isGPU() const
Returns true if the current target is a GPU.
static const Stmt * getSingleCompoundChild(ASTContext &Ctx, const Stmt *Body)
Checks if the Body is the CompoundStmt and returns its child statement iff there is only one that is ...
virtual void emitDeclareTargetFunction(const FunctionDecl *FD, llvm::GlobalValue *GV)
Emit code for handling declare target functions in the runtime.
bool HasRequiresUnifiedSharedMemory
Flag for keeping track of weather a requires unified_shared_memory directive is present.
llvm::Value * emitUpdateLocation(CodeGenFunction &CGF, SourceLocation Loc, unsigned Flags=0, bool EmitLoc=false)
Emits object of ident_t type with info for source location.
bool isLocalVarInUntiedTask(CodeGenFunction &CGF, const VarDecl *VD) const
Returns true if the variable is a local variable in untied task.
virtual void emitTeamsCall(CodeGenFunction &CGF, const OMPExecutableDirective &D, SourceLocation Loc, llvm::Function *OutlinedFn, ArrayRef< llvm::Value * > CapturedVars)
Emits code for teams call of the OutlinedFn with variables captured in a record which address is stor...
virtual void emitCancellationPointCall(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind CancelRegion)
Emit code for 'cancellation point' construct.
virtual llvm::Function * emitThreadPrivateVarDefinition(const VarDecl *VD, Address VDAddr, SourceLocation Loc, bool PerformInit, CodeGenFunction *CGF=nullptr)
Emit a code for initialization of threadprivate variable.
FunctionUDMMapTy FunctionUDMMap
virtual ConstantAddress getAddrOfDeclareTargetVar(const VarDecl *VD)
Returns the address of the variable marked as declare target with link clause OR as declare target wi...
llvm::Function * getOrCreateUserDefinedMapperFunc(const OMPDeclareMapperDecl *D)
Get the function for the specified user-defined mapper.
OpenMPLocThreadIDMapTy OpenMPLocThreadIDMap
virtual void functionFinished(CodeGenFunction &CGF)
Cleans up references to the objects in finished function.
virtual llvm::Function * emitTeamsOutlinedFunction(CodeGenFunction &CGF, const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen)
Emits outlined function for the specified OpenMP teams directive D.
QualType KmpTaskTQTy
Type typedef struct kmp_task { void * shareds; /**< pointer to block of pointers to shared vars / k...
llvm::OpenMPIRBuilder OMPBuilder
An OpenMP-IR-Builder instance.
virtual void emitDoacrossInit(CodeGenFunction &CGF, const OMPLoopDirective &D, ArrayRef< Expr * > NumIterations)
Emit initialization for doacross loop nesting support.
virtual void adjustTargetSpecificDataForLambdas(CodeGenFunction &CGF, const OMPExecutableDirective &D) const
Adjust some parameters for the target-based directives, like addresses of the variables captured by r...
FunctionUDRMapTy FunctionUDRMap
virtual void emitTargetDataCalls(CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, const Expr *Device, const RegionCodeGenTy &CodeGen, CGOpenMPRuntime::TargetDataInfo &Info)
Emit the target data mapping code associated with D.
virtual unsigned getDefaultLocationReserved2Flags() const
Returns additional flags that can be stored in reserved_2 field of the default location.
virtual Address getParameterAddress(CodeGenFunction &CGF, const VarDecl *NativeParam, const VarDecl *TargetParam) const
Gets the address of the native argument basing on the address of the target-specific parameter.
void emitUsesAllocatorsFini(CodeGenFunction &CGF, const Expr *Allocator)
Destroys user defined allocators specified in the uses_allocators clause.
QualType KmpTaskAffinityInfoTy
Type typedef struct kmp_task_affinity_info { kmp_intptr_t base_addr; size_t len; struct { bool flag1 ...
void emitPrivateReduction(CodeGenFunction &CGF, SourceLocation Loc, const Expr *Privates, const Expr *LHSExprs, const Expr *RHSExprs, const Expr *ReductionOps)
Emits code for private variable reduction.
llvm::Value * emitNumTeamsForTargetDirective(CodeGenFunction &CGF, const OMPExecutableDirective &D)
virtual void emitTargetOutlinedFunctionHelper(const OMPExecutableDirective &D, StringRef ParentName, llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID, bool IsOffloadEntry, const RegionCodeGenTy &CodeGen)
Helper to emit outlined function for 'target' directive.
void scanForTargetRegionsFunctions(const Stmt *S, StringRef ParentName)
Start scanning from statement S and emit all target regions found along the way.
SmallVector< llvm::Value *, 4 > emitDepobjElementsSizes(CodeGenFunction &CGF, QualType &KmpDependInfoTy, const OMPTaskDataTy::DependData &Data)
virtual llvm::Value * emitMessageClause(CodeGenFunction &CGF, const Expr *Message, SourceLocation Loc)
virtual void emitTaskgroupRegion(CodeGenFunction &CGF, const RegionCodeGenTy &TaskgroupOpGen, SourceLocation Loc)
Emit a taskgroup region.
llvm::DenseMap< llvm::Function *, llvm::DenseMap< CanonicalDeclPtr< const Decl >, std::tuple< QualType, const FieldDecl *, const FieldDecl *, LValue > > > LastprivateConditionalToTypes
Maps local variables marked as lastprivate conditional to their internal types.
virtual bool emitTargetGlobalVariable(GlobalDecl GD)
Emit the global variable if it is a valid device global variable.
virtual void emitNumTeamsClause(CodeGenFunction &CGF, const Expr *NumTeams, const Expr *ThreadLimit, SourceLocation Loc)
Emits call to void __kmpc_push_num_teams(ident_t *loc, kmp_int32global_tid, kmp_int32 num_teams,...
bool hasRequiresUnifiedSharedMemory() const
Return whether the unified_shared_memory has been specified.
virtual Address getAddrOfArtificialThreadPrivate(CodeGenFunction &CGF, QualType VarType, StringRef Name)
Creates artificial threadprivate variable with name Name and type VarType.
void emitUserDefinedMapper(const OMPDeclareMapperDecl *D, CodeGenFunction *CGF=nullptr)
Emit the function for the user defined mapper construct.
bool HasEmittedTargetRegion
Flag for keeping track of weather a target region has been emitted.
void emitDepobjElements(CodeGenFunction &CGF, QualType &KmpDependInfoTy, LValue PosLVal, const OMPTaskDataTy::DependData &Data, Address DependenciesArray)
std::string getReductionFuncName(StringRef Name) const
Get the function name of a reduction function.
virtual void processRequiresDirective(const OMPRequiresDecl *D)
Perform check on requires decl to ensure that target architecture supports unified addressing.
llvm::DenseSet< CanonicalDeclPtr< const Decl > > AlreadyEmittedTargetDecls
List of the emitted declarations.
virtual llvm::Value * emitTaskReductionInit(CodeGenFunction &CGF, SourceLocation Loc, ArrayRef< const Expr * > LHSExprs, ArrayRef< const Expr * > RHSExprs, const OMPTaskDataTy &Data)
Emit a code for initialization of task reduction clause.
llvm::Value * getThreadID(CodeGenFunction &CGF, SourceLocation Loc)
Gets thread id value for the current thread.
virtual void emitLastprivateConditionalFinalUpdate(CodeGenFunction &CGF, LValue PrivLVal, const VarDecl *VD, SourceLocation Loc)
Gets the address of the global copy used for lastprivate conditional update, if any.
llvm::MapVector< CanonicalDeclPtr< const VarDecl >, std::pair< Address, Address > > UntiedLocalVarsAddressesMap
virtual void emitErrorCall(CodeGenFunction &CGF, SourceLocation Loc, Expr *ME, bool IsFatal)
Emit __kmpc_error call for error directive extern void __kmpc_error(ident_t *loc, int severity,...
void clearLocThreadIdInsertPt(CodeGenFunction &CGF)
virtual void emitTaskyieldCall(CodeGenFunction &CGF, SourceLocation Loc)
Emits code for a taskyield directive.
std::string getName(ArrayRef< StringRef > Parts) const
Get the platform-specific name separator.
QualType KmpRoutineEntryPtrQTy
void computeMinAndMaxThreadsAndTeams(const OMPExecutableDirective &D, CodeGenFunction &CGF, llvm::OpenMPIRBuilder::TargetKernelDefaultAttrs &Attrs)
Helper to determine the min/max number of threads/teams for D.
virtual void emitFlush(CodeGenFunction &CGF, ArrayRef< const Expr * > Vars, SourceLocation Loc, llvm::AtomicOrdering AO)
Emit flush of the variables specified in 'omp flush' directive.
virtual void emitTaskwaitCall(CodeGenFunction &CGF, SourceLocation Loc, const OMPTaskDataTy &Data)
Emit code for 'taskwait' directive.
virtual void emitProcBindClause(CodeGenFunction &CGF, llvm::omp::ProcBindKind ProcBind, SourceLocation Loc)
Emit call to void __kmpc_push_proc_bind(ident_t *loc, kmp_int32global_tid, int proc_bind) to generate...
void emitLastprivateConditionalUpdate(CodeGenFunction &CGF, LValue IVLVal, StringRef UniqueDeclName, LValue LVal, SourceLocation Loc)
Emit update for lastprivate conditional data.
virtual void emitTaskLoopCall(CodeGenFunction &CGF, SourceLocation Loc, const OMPLoopDirective &D, llvm::Function *TaskFunction, QualType SharedsTy, Address Shareds, const Expr *IfCond, const OMPTaskDataTy &Data)
Emit task region for the taskloop directive.
virtual void emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind Kind, bool EmitChecks=true, bool ForceSimpleCall=false)
Emit an implicit/explicit barrier for OpenMP threads.
static unsigned getDefaultFlagsForBarriers(OpenMPDirectiveKind Kind)
Returns default flags for the barriers depending on the directive, for which this barier is going to ...
virtual bool emitTargetFunctions(GlobalDecl GD)
Emit the target regions enclosed in GD function definition or the function itself in case it is a val...
TaskResultTy emitTaskInit(CodeGenFunction &CGF, SourceLocation Loc, const OMPExecutableDirective &D, llvm::Function *TaskFunction, QualType SharedsTy, Address Shareds, const OMPTaskDataTy &Data)
Emit task region for the task directive.
llvm::Value * emitTargetNumIterationsCall(CodeGenFunction &CGF, const OMPExecutableDirective &D, llvm::function_ref< llvm::Value *(CodeGenFunction &CGF, const OMPLoopDirective &D)> SizeEmitter)
Return the trip count of loops associated with constructs / 'target teams distribute' and 'teams dist...
llvm::StringMap< llvm::AssertingVH< llvm::GlobalVariable >, llvm::BumpPtrAllocator > InternalVars
An ordered map of auto-generated variables to their unique names.
virtual void emitDistributeStaticInit(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDistScheduleClauseKind SchedKind, const StaticRTInput &Values)
llvm::SmallVector< UntiedLocalVarsAddressesMap, 4 > UntiedLocalVarsStack
virtual void emitForStaticFinish(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind DKind)
Call the appropriate runtime routine to notify that we finished all the work with current loop.
virtual void emitThreadLimitClause(CodeGenFunction &CGF, const Expr *ThreadLimit, SourceLocation Loc)
Emits call to void __kmpc_set_thread_limit(ident_t *loc, kmp_int32global_tid, kmp_int32 thread_limit)...
void emitIfClause(CodeGenFunction &CGF, const Expr *Cond, const RegionCodeGenTy &ThenGen, const RegionCodeGenTy &ElseGen)
Emits code for OpenMP 'if' clause using specified CodeGen function.
Address emitDepobjDependClause(CodeGenFunction &CGF, const OMPTaskDataTy::DependData &Dependencies, SourceLocation Loc)
Emits list of dependecies based on the provided data (array of dependence/expression pairs) for depob...
bool isNontemporalDecl(const ValueDecl *VD) const
Checks if the VD variable is marked as nontemporal declaration in current context.
virtual llvm::Function * emitParallelOutlinedFunction(CodeGenFunction &CGF, const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen)
Emits outlined function for the specified OpenMP parallel directive D.
const Expr * getNumThreadsExprForTargetDirective(CodeGenFunction &CGF, const OMPExecutableDirective &D, int32_t &UpperBound, bool UpperBoundOnly, llvm::Value **CondExpr=nullptr, const Expr **ThreadLimitExpr=nullptr)
Check for a number of threads upper bound constant value (stored in UpperBound), or expression (retur...
virtual void registerVTableOffloadEntry(llvm::GlobalVariable *VTable, const VarDecl *VD)
Register VTable to OpenMP offload entry.
virtual llvm::Value * emitSeverityClause(OpenMPSeverityClauseKind Severity, SourceLocation Loc)
llvm::SmallVector< LastprivateConditionalData, 4 > LastprivateConditionalStack
Stack for list of addresses of declarations in current context marked as lastprivate conditional.
virtual void emitForStaticInit(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind DKind, const OpenMPScheduleTy &ScheduleKind, const StaticRTInput &Values)
Call the appropriate runtime routine to initialize it before start of loop.
virtual void emitDeclareSimdFunction(const FunctionDecl *FD, llvm::Function *Fn)
Marks function Fn with properly mangled versions of vector functions.
llvm::AtomicOrdering getDefaultMemoryOrdering() const
Gets default memory ordering as specified in requires directive.
virtual bool isStaticNonchunked(OpenMPScheduleClauseKind ScheduleKind, bool Chunked) const
Check if the specified ScheduleKind is static non-chunked.
virtual void emitAndRegisterVTable(CodeGenModule &CGM, CXXRecordDecl *CXXRecord, const VarDecl *VD)
Emit and register VTable for the C++ class in OpenMP offload entry.
llvm::Value * getCriticalRegionLock(StringRef CriticalName)
Returns corresponding lock object for the specified critical region name.
virtual void emitCancelCall(CodeGenFunction &CGF, SourceLocation Loc, const Expr *IfCond, OpenMPDirectiveKind CancelRegion)
Emit code for 'cancel' construct.
QualType SavedKmpTaskTQTy
Saved kmp_task_t for task directive.
virtual void emitMasterRegion(CodeGenFunction &CGF, const RegionCodeGenTy &MasterOpGen, SourceLocation Loc)
Emits a master region.
virtual llvm::Function * emitTaskOutlinedFunction(const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, const VarDecl *PartIDVar, const VarDecl *TaskTVar, OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen, bool Tied, unsigned &NumberOfParts)
Emits outlined function for the OpenMP task directive D.
llvm::DenseMap< llvm::Function *, unsigned > FunctionToUntiedTaskStackMap
Maps function to the position of the untied task locals stack.
void emitHostKernelEnvironment(const OMPExecutableDirective &D, CodeGenFunction &CGF)
Emit the '<kernel>_kernel_environment' global for a target region that is compiled for a non-GPU (hos...
void emitDestroyClause(CodeGenFunction &CGF, LValue DepobjLVal, SourceLocation Loc)
Emits the code to destroy the dependency object provided in depobj directive.
virtual void emitTaskReductionFixups(CodeGenFunction &CGF, SourceLocation Loc, ReductionCodeGen &RCG, unsigned N)
Required to resolve existing problems in the runtime.
llvm::ArrayType * KmpCriticalNameTy
Type kmp_critical_name, originally defined as typedef kmp_int32 kmp_critical_name[8];.
virtual void emitDoacrossOrdered(CodeGenFunction &CGF, const OMPDependClause *C)
Emit code for doacross ordered directive with 'depend' clause.
llvm::DenseMap< const OMPDeclareMapperDecl *, llvm::Function * > UDMMap
Map from the user-defined mapper declaration to its corresponding functions.
virtual void checkAndEmitLastprivateConditional(CodeGenFunction &CGF, const Expr *LHS)
Checks if the provided LVal is lastprivate conditional and emits the code to update the value of the ...
std::pair< llvm::Value *, LValue > getDepobjElements(CodeGenFunction &CGF, LValue DepobjLVal, SourceLocation Loc)
Returns the number of the elements and the address of the depobj dependency array.
llvm::SmallDenseSet< const VarDecl * > DeferredGlobalVariables
List of variables that can become declare target implicitly and, thus, must be emitted.
void emitUsesAllocatorsInit(CodeGenFunction &CGF, const Expr *Allocator, const Expr *AllocatorTraits)
Initializes user defined allocators specified in the uses_allocators clauses.
virtual void registerVTable(const OMPExecutableDirective &D)
Emit code for registering vtable by scanning through map clause in OpenMP target region.
llvm::Type * KmpRoutineEntryPtrTy
Type typedef kmp_int32 (* kmp_routine_entry_t)(kmp_int32, void *);.
llvm::Type * getIdentTyPointerTy()
Returns pointer to ident_t type.
void emitSingleReductionCombiner(CodeGenFunction &CGF, const Expr *ReductionOp, const Expr *PrivateRef, const DeclRefExpr *LHS, const DeclRefExpr *RHS)
Emits single reduction combiner.
llvm::OpenMPIRBuilder & getOMPBuilder()
virtual void emitTargetOutlinedFunction(const OMPExecutableDirective &D, StringRef ParentName, llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID, bool IsOffloadEntry, const RegionCodeGenTy &CodeGen)
Emit outilined function for 'target' directive.
virtual void emitCriticalRegion(CodeGenFunction &CGF, StringRef CriticalName, const RegionCodeGenTy &CriticalOpGen, SourceLocation Loc, const Expr *Hint=nullptr)
Emits a critical region.
virtual void emitForOrderedIterationEnd(CodeGenFunction &CGF, SourceLocation Loc, unsigned IVSize, bool IVSigned)
Call the appropriate runtime routine to notify that we finished iteration of the ordered loop with th...
virtual void emitOutlinedFunctionCall(CodeGenFunction &CGF, SourceLocation Loc, llvm::FunctionCallee OutlinedFn, ArrayRef< llvm::Value * > Args={}) const
Emits call of the outlined function with the provided arguments, translating these arguments to corre...
llvm::Value * emitNumThreadsForTargetDirective(CodeGenFunction &CGF, const OMPExecutableDirective &D)
Emit an expression that denotes the number of threads a target region shall use.
void emitThreadPrivateVarInit(CodeGenFunction &CGF, Address VDAddr, llvm::Value *Ctor, llvm::Value *CopyCtor, llvm::Value *Dtor, SourceLocation Loc)
Emits initialization code for the threadprivate variables.
virtual void emitUserDefinedReduction(CodeGenFunction *CGF, const OMPDeclareReductionDecl *D)
Emit code for the specified user defined reduction construct.
virtual void checkAndEmitSharedLastprivateConditional(CodeGenFunction &CGF, const OMPExecutableDirective &D, const llvm::DenseSet< CanonicalDeclPtr< const VarDecl > > &IgnoredDecls)
Checks if the lastprivate conditional was updated in inner region and writes the value.
QualType KmpDimTy
struct kmp_dim { // loop bounds info casted to kmp_int64 kmp_int64 lo; // lower kmp_int64 up; // uppe...
virtual void emitInlinedDirective(CodeGenFunction &CGF, OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen, bool HasCancel=false)
Emit code for the directive that does not require outlining.
virtual void registerTargetGlobalVariable(const VarDecl *VD, llvm::Constant *Addr)
Checks if the provided global decl GD is a declare target variable and registers it when emitting cod...
virtual void emitFunctionProlog(CodeGenFunction &CGF, const Decl *D)
Emits OpenMP-specific function prolog.
void emitKmpRoutineEntryT(QualType KmpInt32Ty)
Build type kmp_routine_entry_t (if not built yet).
virtual bool isStaticChunked(OpenMPScheduleClauseKind ScheduleKind, bool Chunked) const
Check if the specified ScheduleKind is static chunked.
virtual void emitTargetCall(CodeGenFunction &CGF, const OMPExecutableDirective &D, llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID, const Expr *IfCond, llvm::PointerIntPair< const Expr *, 2, OpenMPDeviceClauseModifier > Device, llvm::function_ref< llvm::Value *(CodeGenFunction &CGF, const OMPLoopDirective &D)> SizeEmitter)
Emit the target offloading code associated with D.
virtual bool hasAllocateAttributeForGlobalVar(const VarDecl *VD, LangAS &AS)
Checks if the variable has associated OMPAllocateDeclAttr attribute with the predefined allocator and...
llvm::AtomicOrdering RequiresAtomicOrdering
Atomic ordering from the omp requires directive.
virtual void emitReduction(CodeGenFunction &CGF, SourceLocation Loc, ArrayRef< const Expr * > Privates, ArrayRef< const Expr * > LHSExprs, ArrayRef< const Expr * > RHSExprs, ArrayRef< const Expr * > ReductionOps, ReductionOptionsTy Options)
Emit a code for reduction clause.
std::pair< llvm::Value *, Address > emitDependClause(CodeGenFunction &CGF, ArrayRef< OMPTaskDataTy::DependData > Dependencies, SourceLocation Loc)
Emits list of dependecies based on the provided data (array of dependence/expression pairs).
llvm::StringMap< llvm::WeakTrackingVH > EmittedNonTargetVariables
List of the global variables with their addresses that should not be emitted for the target.
virtual bool isDynamic(OpenMPScheduleClauseKind ScheduleKind) const
Check if the specified ScheduleKind is dynamic.
Address emitLastprivateConditionalInit(CodeGenFunction &CGF, const VarDecl *VD)
Create specialized alloca to handle lastprivate conditionals.
virtual void emitOrderedRegion(CodeGenFunction &CGF, const RegionCodeGenTy &OrderedOpGen, SourceLocation Loc, bool IsThreads)
Emit an ordered region.
virtual Address getAddressOfLocalVariable(CodeGenFunction &CGF, const VarDecl *VD)
Gets the OpenMP-specific address of the local variable.
virtual void emitTaskReductionFini(CodeGenFunction &CGF, SourceLocation Loc, bool IsWorksharingReduction)
Emits the following code for reduction clause with task modifier:
virtual void emitMaskedRegion(CodeGenFunction &CGF, const RegionCodeGenTy &MaskedOpGen, SourceLocation Loc, const Expr *Filter=nullptr)
Emits a masked region.
QualType KmpDependInfoTy
Type typedef struct kmp_depend_info { kmp_intptr_t base_addr; size_t len; struct { bool in:1; bool ou...
llvm::Function * emitReductionFunction(StringRef ReducerName, SourceLocation Loc, llvm::Type *ArgsElemType, ArrayRef< const Expr * > Privates, ArrayRef< const Expr * > LHSExprs, ArrayRef< const Expr * > RHSExprs, ArrayRef< const Expr * > ReductionOps)
Emits reduction function.
virtual void emitForDispatchInit(CodeGenFunction &CGF, SourceLocation Loc, const OpenMPScheduleTy &ScheduleKind, unsigned IVSize, bool IVSigned, bool Ordered, const DispatchRTInput &DispatchValues)
Call the appropriate runtime routine to initialize it before start of loop.
Address getTaskReductionItem(CodeGenFunction &CGF, SourceLocation Loc, llvm::Value *ReductionsPtr, LValue SharedLVal) override
Get the address of void * type of the privatue copy of the reduction item specified by the SharedLVal...
void emitCriticalRegion(CodeGenFunction &CGF, StringRef CriticalName, const RegionCodeGenTy &CriticalOpGen, SourceLocation Loc, const Expr *Hint=nullptr) override
Emits a critical region.
void emitDistributeStaticInit(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDistScheduleClauseKind SchedKind, const StaticRTInput &Values) override
void emitForStaticInit(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind DKind, const OpenMPScheduleTy &ScheduleKind, const StaticRTInput &Values) override
Call the appropriate runtime routine to initialize it before start of loop.
bool emitTargetGlobalVariable(GlobalDecl GD) override
Emit the global variable if it is a valid device global variable.
llvm::Value * emitForNext(CodeGenFunction &CGF, SourceLocation Loc, unsigned IVSize, bool IVSigned, Address IL, Address LB, Address UB, Address ST) override
Call __kmpc_dispatch_next( ident_t *loc, kmp_int32 tid, kmp_int32 *p_lastiter, kmp_int[32|64] *p_lowe...
llvm::Function * emitThreadPrivateVarDefinition(const VarDecl *VD, Address VDAddr, SourceLocation Loc, bool PerformInit, CodeGenFunction *CGF=nullptr) override
Emit a code for initialization of threadprivate variable.
void emitTargetDataStandAloneCall(CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, const Expr *Device) override
Emit the data mapping/movement code associated with the directive D that should be of the form 'targe...
llvm::Function * emitTeamsOutlinedFunction(CodeGenFunction &CGF, const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) override
Emits outlined function for the specified OpenMP teams directive D.
void emitParallelCall(CodeGenFunction &CGF, SourceLocation Loc, llvm::Function *OutlinedFn, ArrayRef< llvm::Value * > CapturedVars, const Expr *IfCond, llvm::Value *NumThreads, OpenMPNumThreadsClauseModifier NumThreadsModifier=OMPC_NUMTHREADS_unknown, OpenMPSeverityClauseKind Severity=OMPC_SEVERITY_fatal, const Expr *Message=nullptr) override
Emits code for parallel or serial call of the OutlinedFn with variables captured in a record which ad...
void emitReduction(CodeGenFunction &CGF, SourceLocation Loc, ArrayRef< const Expr * > Privates, ArrayRef< const Expr * > LHSExprs, ArrayRef< const Expr * > RHSExprs, ArrayRef< const Expr * > ReductionOps, ReductionOptionsTy Options) override
Emit a code for reduction clause.
void emitFlush(CodeGenFunction &CGF, ArrayRef< const Expr * > Vars, SourceLocation Loc, llvm::AtomicOrdering AO) override
Emit flush of the variables specified in 'omp flush' directive.
void emitDoacrossOrdered(CodeGenFunction &CGF, const OMPDependClause *C) override
Emit code for doacross ordered directive with 'depend' clause.
void emitTaskyieldCall(CodeGenFunction &CGF, SourceLocation Loc) override
Emits a masked region.
Address getAddrOfArtificialThreadPrivate(CodeGenFunction &CGF, QualType VarType, StringRef Name) override
Creates artificial threadprivate variable with name Name and type VarType.
Address getAddrOfThreadPrivate(CodeGenFunction &CGF, const VarDecl *VD, Address VDAddr, SourceLocation Loc) override
Returns address of the threadprivate variable for the current thread.
void emitSingleRegion(CodeGenFunction &CGF, const RegionCodeGenTy &SingleOpGen, SourceLocation Loc, ArrayRef< const Expr * > CopyprivateVars, ArrayRef< const Expr * > DestExprs, ArrayRef< const Expr * > SrcExprs, ArrayRef< const Expr * > AssignmentOps) override
Emits a single region.
void emitTaskReductionFixups(CodeGenFunction &CGF, SourceLocation Loc, ReductionCodeGen &RCG, unsigned N) override
Required to resolve existing problems in the runtime.
llvm::Function * emitParallelOutlinedFunction(CodeGenFunction &CGF, const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) override
Emits outlined function for the specified OpenMP parallel directive D.
void emitCancellationPointCall(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind CancelRegion) override
Emit code for 'cancellation point' construct.
void emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind Kind, bool EmitChecks=true, bool ForceSimpleCall=false) override
Emit an implicit/explicit barrier for OpenMP threads.
Address getParameterAddress(CodeGenFunction &CGF, const VarDecl *NativeParam, const VarDecl *TargetParam) const override
Gets the address of the native argument basing on the address of the target-specific parameter.
void emitTeamsCall(CodeGenFunction &CGF, const OMPExecutableDirective &D, SourceLocation Loc, llvm::Function *OutlinedFn, ArrayRef< llvm::Value * > CapturedVars) override
Emits code for teams call of the OutlinedFn with variables captured in a record which address is stor...
void emitForOrderedIterationEnd(CodeGenFunction &CGF, SourceLocation Loc, unsigned IVSize, bool IVSigned) override
Call the appropriate runtime routine to notify that we finished iteration of the ordered loop with th...
bool emitTargetGlobal(GlobalDecl GD) override
Emit the global GD if it is meaningful for the target.
void emitTaskReductionFini(CodeGenFunction &CGF, SourceLocation Loc, bool IsWorksharingReduction) override
Emits the following code for reduction clause with task modifier:
void emitOrderedRegion(CodeGenFunction &CGF, const RegionCodeGenTy &OrderedOpGen, SourceLocation Loc, bool IsThreads) override
Emit an ordered region.
void emitForStaticFinish(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind DKind) override
Call the appropriate runtime routine to notify that we finished all the work with current loop.
llvm::Value * emitTaskReductionInit(CodeGenFunction &CGF, SourceLocation Loc, ArrayRef< const Expr * > LHSExprs, ArrayRef< const Expr * > RHSExprs, const OMPTaskDataTy &Data) override
Emit a code for initialization of task reduction clause.
void emitProcBindClause(CodeGenFunction &CGF, llvm::omp::ProcBindKind ProcBind, SourceLocation Loc) override
Emit call to void __kmpc_push_proc_bind(ident_t *loc, kmp_int32global_tid, int proc_bind) to generate...
void emitTargetOutlinedFunction(const OMPExecutableDirective &D, StringRef ParentName, llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID, bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) override
Emit outilined function for 'target' directive.
void emitMasterRegion(CodeGenFunction &CGF, const RegionCodeGenTy &MasterOpGen, SourceLocation Loc) override
Emits a master region.
void emitNumTeamsClause(CodeGenFunction &CGF, const Expr *NumTeams, const Expr *ThreadLimit, SourceLocation Loc) override
Emits call to void __kmpc_push_num_teams(ident_t *loc, kmp_int32global_tid, kmp_int32 num_teams,...
void emitForDispatchDeinit(CodeGenFunction &CGF, SourceLocation Loc) override
This is used for non static scheduled types and when the ordered clause is present on the loop constr...
const VarDecl * translateParameter(const FieldDecl *FD, const VarDecl *NativeParam) const override
Translates the native parameter of outlined function if this is required for target.
void emitNumThreadsClause(CodeGenFunction &CGF, llvm::Value *NumThreads, SourceLocation Loc, OpenMPNumThreadsClauseModifier Modifier=OMPC_NUMTHREADS_unknown, OpenMPSeverityClauseKind Severity=OMPC_SEVERITY_fatal, SourceLocation SeverityLoc=SourceLocation(), const Expr *Message=nullptr, SourceLocation MessageLoc=SourceLocation()) override
Emits call to void __kmpc_push_num_threads(ident_t *loc, kmp_int32global_tid, kmp_int32 num_threads) ...
void emitMaskedRegion(CodeGenFunction &CGF, const RegionCodeGenTy &MaskedOpGen, SourceLocation Loc, const Expr *Filter=nullptr) override
Emits a masked region.
void emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc, const OMPExecutableDirective &D, llvm::Function *TaskFunction, QualType SharedsTy, Address Shareds, const Expr *IfCond, const OMPTaskDataTy &Data) override
Emit task region for the task directive.
void emitTargetCall(CodeGenFunction &CGF, const OMPExecutableDirective &D, llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID, const Expr *IfCond, llvm::PointerIntPair< const Expr *, 2, OpenMPDeviceClauseModifier > Device, llvm::function_ref< llvm::Value *(CodeGenFunction &CGF, const OMPLoopDirective &D)> SizeEmitter) override
Emit the target offloading code associated with D.
bool emitTargetFunctions(GlobalDecl GD) override
Emit the target regions enclosed in GD function definition or the function itself in case it is a val...
void emitDoacrossInit(CodeGenFunction &CGF, const OMPLoopDirective &D, ArrayRef< Expr * > NumIterations) override
Emit initialization for doacross loop nesting support.
void emitCancelCall(CodeGenFunction &CGF, SourceLocation Loc, const Expr *IfCond, OpenMPDirectiveKind CancelRegion) override
Emit code for 'cancel' construct.
void emitTaskwaitCall(CodeGenFunction &CGF, SourceLocation Loc, const OMPTaskDataTy &Data) override
Emit code for 'taskwait' directive.
void emitTaskgroupRegion(CodeGenFunction &CGF, const RegionCodeGenTy &TaskgroupOpGen, SourceLocation Loc) override
Emit a taskgroup region.
void emitTargetDataCalls(CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, const Expr *Device, const RegionCodeGenTy &CodeGen, CGOpenMPRuntime::TargetDataInfo &Info) override
Emit the target data mapping code associated with D.
void emitForDispatchInit(CodeGenFunction &CGF, SourceLocation Loc, const OpenMPScheduleTy &ScheduleKind, unsigned IVSize, bool IVSigned, bool Ordered, const DispatchRTInput &DispatchValues) override
This is used for non static scheduled types and when the ordered clause is present on the loop constr...
llvm::Function * emitTaskOutlinedFunction(const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, const VarDecl *PartIDVar, const VarDecl *TaskTVar, OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen, bool Tied, unsigned &NumberOfParts) override
Emits outlined function for the OpenMP task directive D.
void emitTaskLoopCall(CodeGenFunction &CGF, SourceLocation Loc, const OMPLoopDirective &D, llvm::Function *TaskFunction, QualType SharedsTy, Address Shareds, const Expr *IfCond, const OMPTaskDataTy &Data) override
Emit task region for the taskloop directive.
unsigned getNonVirtualBaseLLVMFieldNo(const CXXRecordDecl *RD) const
llvm::StructType * getLLVMType() const
Return the "complete object" LLVM type associated with this record.
llvm::StructType * getBaseSubobjectLLVMType() const
Return the "base subobject" LLVM type associated with this record.
unsigned getLLVMFieldNo(const FieldDecl *FD) const
Return llvm::StructType element number that corresponds to the field FD.
unsigned getVirtualBaseIndex(const CXXRecordDecl *base) const
Return the LLVM field index corresponding to the given virtual base.
API for captured statement code generation.
virtual void EmitBody(CodeGenFunction &CGF, const Stmt *S)
Emit the captured statement body.
virtual const FieldDecl * lookup(const VarDecl *VD) const
Lookup the captured field decl for a variable.
RAII for correct setting/restoring of CapturedStmtInfo.
The scope used to remap some variables as private in the OpenMP loop body (or other captured region e...
bool Privatize()
Privatizes local variables previously registered as private.
bool addPrivate(const ValueDecl *LocalVD, Address Addr)
Registers LocalVD variable as a private with Addr as the address of the corresponding private variabl...
An RAII object to set (and then clear) a mapping for an OpaqueValueExpr.
Enters a new scope for capturing cleanups, all of which will be executed once the scope is exited.
CodeGenFunction - This class organizes the per-function state that is used while generating LLVM code...
LValue EmitLoadOfReferenceLValue(LValue RefLVal)
void EmitBranchOnBoolExpr(const Expr *Cond, llvm::BasicBlock *TrueBlock, llvm::BasicBlock *FalseBlock, uint64_t TrueCount, Stmt::Likelihood LH=Stmt::LH_None, const Expr *ConditionalOp=nullptr, const VarDecl *ConditionalDecl=nullptr)
EmitBranchOnBoolExpr - Emit a branch on a boolean condition (e.g.
void emitDestroy(Address addr, QualType type, Destroyer *destroyer, bool useEHCleanupForArray)
emitDestroy - Immediately perform the destruction of the given object.
JumpDest getJumpDestInCurrentScope(llvm::BasicBlock *Target)
The given basic block lies in the current EH scope, but may be a target of a potentially scope-crossi...
static void EmitOMPTargetParallelDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetParallelDirective &S)
void EmitNullInitialization(Address DestPtr, QualType Ty)
EmitNullInitialization - Generate code to set a value of the given type to null, If the type contains...
Address LoadCXXThisAddress()
CGCapturedStmtInfo * CapturedStmtInfo
ComplexPairTy EmitLoadOfComplex(LValue src, SourceLocation loc)
EmitLoadOfComplex - Load a complex number from the specified l-value.
static void EmitOMPTargetDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetDirective &S)
Emit device code for the target directive.
static void EmitOMPTargetTeamsDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsDirective &S)
Emit device code for the target teams directive.
void eraseLocalDecl(const Decl *D)
static void EmitOMPTargetTeamsDistributeDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsDistributeDirective &S)
Emit device code for the target teams distribute directive.
llvm::Function * GenerateOpenMPCapturedStmtFunctionAggregate(const CapturedStmt &S, const OMPExecutableDirective &D)
llvm::BasicBlock * createBasicBlock(const Twine &name="", llvm::Function *parent=nullptr, llvm::BasicBlock *before=nullptr)
createBasicBlock - Create an LLVM basic block.
const LangOptions & getLangOpts() const
AutoVarEmission EmitAutoVarAlloca(const VarDecl &var)
EmitAutoVarAlloca - Emit the alloca and debug information for a local variable.
void pushDestroy(QualType::DestructionKind dtorKind, Address addr, QualType type)
pushDestroy - Push the standard destructor for the given type as at least a normal cleanup.
Address EmitLoadOfPointer(Address Ptr, const PointerType *PtrTy, LValueBaseInfo *BaseInfo=nullptr, TBAAAccessInfo *TBAAInfo=nullptr)
Load a pointer with type PtrTy stored at address Ptr.
DeclMapTy::iterator localDeclMapEnd()
void EmitBranchThroughCleanup(JumpDest Dest)
EmitBranchThroughCleanup - Emit a branch from the current insert block through the normal cleanup han...
const Decl * CurCodeDecl
CurCodeDecl - This is the inner-most code context, which includes blocks.
Destroyer * getDestroyer(QualType::DestructionKind destructionKind)
llvm::AssertingVH< llvm::Instruction > AllocaInsertPt
AllocaInsertPoint - This is an instruction in the entry block before which we prefer to insert alloca...
void EmitAggregateAssign(LValue Dest, LValue Src, QualType EltTy)
Emit an aggregate assignment.
JumpDest ReturnBlock
ReturnBlock - Unified return block.
void EmitAggregateCopy(LValue Dest, LValue Src, QualType EltTy, AggValueSlot::Overlap_t MayOverlap, bool isVolatile=false)
EmitAggregateCopy - Emit an aggregate copy.
LValue EmitLValueForField(LValue Base, const FieldDecl *Field, bool IsInBounds=true)
RawAddress CreateDefaultAlignTempAlloca(llvm::Type *Ty, const Twine &Name="tmp")
CreateDefaultAlignedTempAlloca - This creates an alloca with the default ABI alignment of the given L...
void GenerateOpenMPCapturedVars(const CapturedStmt &S, SmallVectorImpl< llvm::Value * > &CapturedVars)
DeclMapTy::iterator findLocalDecl(const Decl *D)
Accessors for LocalDeclMap.
void EmitIgnoredExpr(const Expr *E)
EmitIgnoredExpr - Emit an expression in a context which ignores the result.
RValue EmitLoadOfLValue(LValue V, SourceLocation Loc)
EmitLoadOfLValue - Given an expression that represents a value lvalue, this method emits the address ...
std::pair< DeclMapTy::iterator, bool > insertLocalDecl(const Decl *D, Address Addr)
LValue EmitArraySectionExpr(const ArraySectionExpr *E, bool IsLowerBound=true)
LValue EmitOMPSharedLValue(const Expr *E)
Emits the lvalue for the expression with possibly captured variable.
void StartFunction(GlobalDecl GD, QualType RetTy, llvm::Function *Fn, const CGFunctionInfo &FnInfo, const FunctionArgList &Args, SourceLocation Loc=SourceLocation(), SourceLocation StartLoc=SourceLocation())
Emit code for the start of a function.
void EmitOMPCopy(QualType OriginalType, Address DestAddr, Address SrcAddr, const VarDecl *DestVD, const VarDecl *SrcVD, const Expr *Copy)
Emit proper copying of data from one variable to another.
llvm::Value * EvaluateExprAsBool(const Expr *E)
EvaluateExprAsBool - Perform the usual unary conversions on the specified expression and compare the ...
JumpDest getOMPCancelDestination(OpenMPDirectiveKind Kind)
llvm::Value * emitArrayLength(const ArrayType *arrayType, QualType &baseType, Address &addr)
emitArrayLength - Compute the length of an array, even if it's a VLA, and drill down to the base elem...
void EmitOMPAggregateAssign(Address DestAddr, Address SrcAddr, QualType OriginalType, const llvm::function_ref< void(Address, Address)> CopyGen)
Perform element by element copying of arrays with type OriginalType from SrcAddr to DestAddr using co...
bool HaveInsertPoint() const
HaveInsertPoint - True if an insertion point is defined.
CGDebugInfo * getDebugInfo()
llvm::Value * getTypeSize(QualType Ty)
Returns calculated size of the specified type.
LValue MakeRawAddrLValue(llvm::Value *V, QualType T, CharUnits Alignment, AlignmentSource Source=AlignmentSource::Type)
Same as MakeAddrLValue above except that the pointer is known to be unsigned.
LValue EmitLValueForFieldInitialization(LValue Base, const FieldDecl *Field)
EmitLValueForFieldInitialization - Like EmitLValueForField, except that if the Field is a reference,...
RawAddress CreateMemTempWithoutCast(QualType T, const Twine &Name="tmp")
CreateMemTemp - Create a temporary memory object of the given type, with appropriate alignmen without...
VlaSizePair getVLASize(const VariableArrayType *vla)
Returns an LLVM value that corresponds to the size, in non-variably-sized elements,...
llvm::CallInst * EmitNounwindRuntimeCall(llvm::FunctionCallee callee, const Twine &name="")
ASTContext & getContext() const
llvm::Value * EmitLoadOfScalar(Address Addr, bool Volatile, QualType Ty, SourceLocation Loc, AlignmentSource Source=AlignmentSource::Type, bool isNontemporal=false)
EmitLoadOfScalar - Load a scalar value from an address, taking care to appropriately convert from the...
void EmitStoreOfComplex(ComplexPairTy V, LValue dest, bool isInit)
EmitStoreOfComplex - Store a complex number into the specified l-value.
const Decl * CurFuncDecl
CurFuncDecl - Holds the Decl for the current outermost non-closure context.
void EmitAutoVarCleanups(const AutoVarEmission &emission)
void EmitStoreThroughLValue(RValue Src, LValue Dst, bool isInit=false)
EmitStoreThroughLValue - Store the specified rvalue into the specified lvalue, where both are guarant...
LValue EmitLoadOfPointerLValue(Address Ptr, const PointerType *PtrTy)
void EmitAnyExprToMem(const Expr *E, Address Location, Qualifiers Quals, bool IsInitializer)
EmitAnyExprToMem - Emits the code necessary to evaluate an arbitrary expression into the given memory...
bool needsEHCleanup(QualType::DestructionKind kind)
Determines whether an EH cleanup is required to destroy a type with the given destruction kind.
llvm::DenseMap< const ValueDecl *, FieldDecl * > LambdaCaptureFields
llvm::CallInst * EmitRuntimeCall(llvm::FunctionCallee callee, const Twine &name="")
llvm::Type * ConvertTypeForMem(QualType T)
static void EmitOMPTargetTeamsDistributeParallelForDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsDistributeParallelForDirective &S)
static void EmitOMPTargetParallelForSimdDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetParallelForSimdDirective &S)
Emit device code for the target parallel for simd directive.
CodeGenTypes & getTypes() const
static TypeEvaluationKind getEvaluationKind(QualType T)
getEvaluationKind - Return the TypeEvaluationKind of QualType T.
void EmitOMPTargetTaskBasedDirective(const OMPExecutableDirective &S, const RegionCodeGenTy &BodyGen, OMPTargetDataInfo &InputInfo)
Address EmitPointerWithAlignment(const Expr *Addr, LValueBaseInfo *BaseInfo=nullptr, TBAAAccessInfo *TBAAInfo=nullptr, KnownNonNull_t IsKnownNonNull=NotKnownNonNull)
EmitPointerWithAlignment - Given an expression with a pointer type, emit the value and compute our be...
static void EmitOMPTargetTeamsDistributeParallelForSimdDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsDistributeParallelForSimdDirective &S)
Emit device code for the target teams distribute parallel for simd directive.
void EmitBranch(llvm::BasicBlock *Block)
EmitBranch - Emit a branch to the specified basic block from the current insert block,...
llvm::Function * GenerateOpenMPCapturedStmtFunction(const CapturedStmt &S, const OMPExecutableDirective &D)
RawAddress CreateMemTemp(QualType T, const Twine &Name="tmp", RawAddress *Alloca=nullptr)
CreateMemTemp - Create a temporary memory object of the given type, with appropriate alignmen and cas...
void EmitVarDecl(const VarDecl &D)
EmitVarDecl - Emit a local variable declaration.
llvm::Value * EmitCheckedInBoundsGEP(llvm::Type *ElemTy, llvm::Value *Ptr, ArrayRef< llvm::Value * > IdxList, bool SignedIndices, bool IsSubtraction, SourceLocation Loc, const Twine &Name="")
Same as IRBuilder::CreateInBoundsGEP, but additionally emits a check to detect undefined behavior whe...
static void EmitOMPTargetParallelGenericLoopDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetParallelGenericLoopDirective &S)
Emit device code for the target parallel loop directive.
llvm::Value * EmitScalarExpr(const Expr *E, bool IgnoreResultAssign=false)
EmitScalarExpr - Emit the computation of the specified expression of LLVM scalar type,...
static bool IsWrappedCXXThis(const Expr *E)
Check if E is a C++ "this" pointer wrapped in value-preserving casts.
LValue MakeAddrLValue(Address Addr, QualType T, AlignmentSource Source=AlignmentSource::Type)
void FinishFunction(SourceLocation EndLoc=SourceLocation())
FinishFunction - Complete IR generation of the current function.
void EmitAtomicStore(RValue rvalue, LValue lvalue, bool isInit)
static void EmitOMPTargetSimdDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetSimdDirective &S)
Emit device code for the target simd directive.
static void EmitOMPTargetParallelForDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetParallelForDirective &S)
Emit device code for the target parallel for directive.
Address GetAddrOfLocalVar(const VarDecl *VD)
GetAddrOfLocalVar - Return the address of a local variable.
bool ConstantFoldsToSimpleInteger(const Expr *Cond, bool &Result, bool AllowLabels=false)
ConstantFoldsToSimpleInteger - If the specified expression does not fold to a constant,...
static void EmitOMPTargetTeamsGenericLoopDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsGenericLoopDirective &S)
Emit device code for the target teams loop directive.
LValue EmitMemberExpr(const MemberExpr *E)
std::pair< llvm::Value *, llvm::Value * > ComplexPairTy
Address ReturnValue
ReturnValue - The temporary alloca to hold the return value.
LValue EmitLValue(const Expr *E, KnownNonNull_t IsKnownNonNull=NotKnownNonNull)
EmitLValue - Emit code to compute a designator that specifies the location of the expression.
void incrementProfileCounter(const Stmt *S, llvm::Value *StepV=nullptr)
Increment the profiler's counter for the given statement by StepV.
static void EmitOMPTargetTeamsDistributeSimdDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsDistributeSimdDirective &S)
Emit device code for the target teams distribute simd directive.
llvm::Value * EmitScalarConversion(llvm::Value *Src, QualType SrcTy, QualType DstTy, SourceLocation Loc)
Emit a conversion from the specified type to the specified destination type, both of which are LLVM s...
void EmitVariablyModifiedType(QualType Ty)
EmitVLASize - Capture all the sizes for the VLA expressions in the given variably-modified type and s...
bool isTrivialInitializer(const Expr *Init)
Determine whether the given initializer is trivial in the sense that it requires no code to be genera...
void EmitStoreOfScalar(llvm::Value *Value, Address Addr, bool Volatile, QualType Ty, AlignmentSource Source=AlignmentSource::Type, bool isInit=false, bool isNontemporal=false)
EmitStoreOfScalar - Store a scalar value to an address, taking care to appropriately convert from the...
void EmitBlock(llvm::BasicBlock *BB, bool IsFinished=false)
EmitBlock - Emit the given block.
void EmitExprAsInit(const Expr *init, const ValueDecl *D, LValue lvalue, bool capturedByInit)
EmitExprAsInit - Emits the code necessary to initialize a location in memory with the given initializ...
LValue MakeNaturalAlignRawAddrLValue(llvm::Value *V, QualType T)
This class organizes the cross-function state that is used while generating LLVM code.
void SetInternalFunctionAttributes(GlobalDecl GD, llvm::Function *F, const CGFunctionInfo &FI)
Set the attributes on the LLVM function for the given decl and function info.
llvm::Module & getModule() const
const IntrusiveRefCntPtr< llvm::vfs::FileSystem > & getFileSystem() const
DiagnosticsEngine & getDiags() const
const LangOptions & getLangOpts() const
CharUnits getNaturalTypeAlignment(QualType T, LValueBaseInfo *BaseInfo=nullptr, TBAAAccessInfo *TBAAInfo=nullptr, bool forPointeeType=false)
CodeGenTypes & getTypes()
const llvm::DataLayout & getDataLayout() const
CGOpenMPRuntime & getOpenMPRuntime()
Return a reference to the configured OpenMP runtime.
TBAAAccessInfo getTBAAInfoForSubobject(LValue Base, QualType AccessType)
getTBAAInfoForSubobject - Get TBAA information for an access with a given base lvalue.
ASTContext & getContext() const
const CodeGenOptions & getCodeGenOpts() const
StringRef getMangledName(GlobalDecl GD)
std::optional< CharUnits > getOMPAllocateAlignment(const VarDecl *VD)
Return the alignment specified in an allocate directive, if present.
llvm::Constant * EmitNullConstant(QualType T)
Return the result of value-initializing the given type, i.e.
llvm::Type * ConvertType(QualType T)
ConvertType - Convert type T into a llvm::Type.
llvm::FunctionType * GetFunctionType(const CGFunctionInfo &Info)
GetFunctionType - Get the LLVM function type for.
const CGFunctionInfo & arrangeBuiltinFunctionDeclaration(QualType resultType, const FunctionArgList &args)
A builtin function is a freestanding function using the default C conventions.
const CGRecordLayout & getCGRecordLayout(const RecordDecl *)
getCGRecordLayout - Return record layout info for the given record decl.
llvm::GlobalVariable * GetAddrOfVTable(const CXXRecordDecl *RD)
GetAddrOfVTable - Get the address of the VTable for the given record decl.
A specialization of Address that requires the address to be an LLVM Constant.
static ConstantAddress invalid()
bool requiresLandingPad() const
void pushTerminate()
Push a terminate handler on the stack.
void popTerminate()
Pops a terminate handler off the stack.
FunctionArgList - Type for representing both the decl and type of parameters to a function.
LValue - This represents an lvalue references.
CharUnits getAlignment() const
llvm::Value * getPointer(CodeGenFunction &CGF) const
const Qualifiers & getQuals() const
Address getAddress() const
LValueBaseInfo getBaseInfo() const
TBAAAccessInfo getTBAAInfo() const
A basic class for pre|post-action for advanced codegen sequence for OpenMP region.
virtual void Enter(CodeGenFunction &CGF)
RValue - This trivial value class is used to represent the result of an expression that is evaluated.
static RValue get(llvm::Value *V)
static RValue getComplex(llvm::Value *V1, llvm::Value *V2)
llvm::Value * getScalarVal() const
getScalarVal() - Return the Value* of this scalar value.
An abstract representation of an aligned address.
llvm::Type * getElementType() const
Return the type of the values stored in this address.
llvm::Value * getPointer() const
static RawAddress invalid()
Class intended to support codegen of all kind of the reduction clauses.
LValue getSharedLValue(unsigned N) const
Returns LValue for the reduction item.
const Expr * getRefExpr(unsigned N) const
Returns the base declaration of the reduction item.
LValue getOrigLValue(unsigned N) const
Returns LValue for the original reduction item.
bool needCleanups(unsigned N)
Returns true if the private copy requires cleanups.
void emitAggregateType(CodeGenFunction &CGF, unsigned N)
Emits the code for the variable-modified type, if required.
const VarDecl * getBaseDecl(unsigned N) const
Returns the base declaration of the reduction item.
QualType getPrivateType(unsigned N) const
Return the type of the private item.
bool usesReductionInitializer(unsigned N) const
Returns true if the initialization of the reduction item uses initializer from declare reduction cons...
void emitSharedOrigLValue(CodeGenFunction &CGF, unsigned N)
Emits lvalue for the shared and original reduction item.
void emitInitialization(CodeGenFunction &CGF, unsigned N, Address PrivateAddr, Address SharedAddr, llvm::function_ref< bool(CodeGenFunction &)> DefaultInit)
Performs initialization of the private copy for the reduction item.
std::pair< llvm::Value *, llvm::Value * > getSizes(unsigned N) const
Returns the size of the reduction item (in chars and total number of elements in the item),...
ReductionCodeGen(ArrayRef< const Expr * > Shareds, ArrayRef< const Expr * > Origs, ArrayRef< const Expr * > Privates, ArrayRef< const Expr * > ReductionOps)
void emitCleanups(CodeGenFunction &CGF, unsigned N, Address PrivateAddr)
Emits cleanup code for the reduction item.
Address adjustPrivateAddress(CodeGenFunction &CGF, unsigned N, Address PrivateAddr)
Adjusts PrivatedAddr for using instead of the original variable address in normal operations.
Class provides a way to call simple version of codegen for OpenMP region, or an advanced with possibl...
void operator()(CodeGenFunction &CGF) const
void setAction(PrePostActionTy &Action) const
ConstStmtVisitor - This class implements a simple visitor for Stmt subclasses.
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
void addDecl(Decl *D)
Add the declaration D into this context.
A reference to a declared variable, function, enum, etc.
Decl - This represents one declaration (or definition), e.g.
ASTContext & getASTContext() const LLVM_READONLY
virtual Stmt * getBody() const
getBody - If this Decl represents a declaration for a body of code, such as a function or method defi...
llvm::iterator_range< specific_attr_iterator< T > > specific_attrs() const
SourceLocation getLocation() const
DeclContext * getDeclContext()
virtual Decl * getCanonicalDecl()
Retrieves the "canonical" declaration of the given declaration.
SourceLocation getBeginLoc() const LLVM_READONLY
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
This represents one expression.
bool isIntegerConstantExpr(const ASTContext &Ctx) const
Expr * IgnoreParenNoopCasts(const ASTContext &Ctx) LLVM_READONLY
Skip past any parentheses and casts which do not change the value (including ptr->int casts of the sa...
@ SE_AllowSideEffects
Allow any unmodeled side effect.
@ SE_AllowUndefinedBehavior
Allow UB that we can give a value, but not arbitrary unmodeled side effects.
Expr * IgnoreParenCasts() LLVM_READONLY
Skip past any parentheses and casts which might surround this expression until reaching a fixed point...
llvm::APSInt EvaluateKnownConstInt(const ASTContext &Ctx) const
EvaluateKnownConstInt - Call EvaluateAsRValue and return the folded integer.
Expr * IgnoreParenImpCasts() LLVM_READONLY
Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...
bool isEvaluatable(const ASTContext &Ctx, SideEffectsKind AllowSideEffects=SE_NoSideEffects) const
isEvaluatable - Call EvaluateAsRValue to see if this expression can be constant folded without side-e...
bool HasSideEffects(const ASTContext &Ctx, bool IncludePossibleEffects=true) const
HasSideEffects - This routine returns true for all those expressions which have any effect other than...
std::optional< llvm::APSInt > getIntegerConstantExpr(const ASTContext &Ctx, bool AllowRelaxedEval=false) const
isIntegerConstantExpr - Return the value if this expression is a valid integer constant expression.
bool EvaluateAsBooleanCondition(bool &Result, const ASTContext &Ctx, bool InConstantContext=false) const
EvaluateAsBooleanCondition - Return true if this is a constant which we can fold and convert to a boo...
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
static bool isSameComparisonOperand(const Expr *E1, const Expr *E2)
Checks that the two Expr's will refer to the same value as a comparison operand.
bool hasNonTrivialCall(const ASTContext &Ctx) const
Determine whether this expression involves a call to any function that is not trivial.
Represents a member of a struct/union/class.
unsigned getFieldIndex() const
Returns the index of this field within its record, as appropriate for passing to ASTRecordLayout::get...
const RecordDecl * getParent() const
Returns the parent of this field declaration, which is the struct in which this field is defined.
static FieldDecl * Create(const ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, const IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, Expr *BW, bool Mutable, InClassInitStyle InitStyle)
Represents a function declaration or definition.
const ParmVarDecl * getParamDecl(unsigned i) const
QualType getReturnType() const
ArrayRef< ParmVarDecl * > parameters() const
FunctionDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
FunctionDecl * getMostRecentDecl()
Returns the most recent (re)declaration of this declaration.
unsigned getNumParams() const
Return the number of parameters this function must have based on its FunctionType.
FunctionDecl * getPreviousDecl()
Return the previous declaration of this declaration or NULL if this is the first declaration.
GlobalDecl - represents a global declaration.
const Decl * getDecl() const
static ImplicitParamDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation IdLoc, const IdentifierInfo *Id, QualType T, ImplicitParamKind ParamKind)
Create implicit parameter.
static IntegerLiteral * Create(const ASTContext &C, const llvm::APInt &V, QualType type, SourceLocation l)
Returns a new integer literal with value 'V' and type 'type'.
An lvalue reference type, per C++11 [dcl.ref].
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
ValueDecl * getMemberDecl() const
Retrieve the member declaration to which this expression refers.
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
bool isExternallyVisible() const
const Stmt * getPreInitStmt() const
Get pre-initialization statement for the clause.
This is a basic class for representing single OpenMP clause.
ArrayRef< OMPClause * > clauses() const
This represents 'pragma omp declare mapper ...' directive.
Expr * getMapperVarRef()
Get the variable declared in the mapper.
This represents 'pragma omp declare reduction ...' directive.
Expr * getInitializer()
Get initializer expression (if specified) of the declare reduction construct.
Expr * getInitPriv()
Get Priv variable of the initializer.
Expr * getCombinerOut()
Get Out variable of the combiner.
Expr * getCombinerIn()
Get In variable of the combiner.
Expr * getCombiner()
Get combiner expression of the declare reduction construct.
Expr * getInitOrig()
Get Orig variable of the initializer.
OMPDeclareReductionInitKind getInitializerKind() const
Get initializer kind.
This represents 'if' clause in the 'pragma omp ...' directive.
Expr * getCondition() const
Returns condition.
OMPIteratorHelperData & getHelper(unsigned I)
Fetches helper data for the specified iteration space.
unsigned numOfIterators() const
Returns number of iterator definitions.
This represents 'num_threads' clause in the 'pragma omp ...' directive.
This represents 'pragma omp requires...' directive.
clauselist_range clauselists()
This represents 'threadset' clause in the 'pragma omp task ...' directive.
OpaqueValueExpr - An expression referring to an opaque object of a fixed type and value class.
Represents a parameter to a function.
PointerType - C99 6.7.5.1 - Pointer Declarators.
Represents an unpacked "presumed" location which can be presented to the user.
unsigned getColumn() const
Return the presumed column number of this location.
const char * getFilename() const
Return the presumed filename of this location.
unsigned getLine() const
Return the presumed line number of this location.
A (possibly-)qualified type.
void addRestrict()
Add the restrict qualifier to this QualType.
QualType withRestrict() const
bool isNull() const
Return true if this QualType doesn't point to a type yet.
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
Qualifiers getQualifiers() const
Retrieve the set of qualifiers applied to this type.
QualType getNonReferenceType() const
If Type is a reference type (e.g., const int&), returns the type that the reference refers to ("const...
QualType getCanonicalType() const
DestructionKind isDestructedType() const
Returns a nonzero value if objects of this type require non-trivial work to clean up after.
Represents a struct/union/class.
field_iterator field_end() const
field_range fields() const
virtual void completeDefinition()
Note that the definition of this type is now complete.
field_iterator field_begin() const
Scope - A scope is a transient data structure that is used while parsing the program.
Encodes a location in the source.
static SourceLocation getFromRawEncoding(UIntTy Encoding)
Turn a raw encoding of a SourceLocation object into a real SourceLocation.
bool isValid() const
Return true if this is a valid SourceLocation object.
UIntTy getRawEncoding() const
When a SourceLocation itself cannot be used, this returns an (opaque) 32-bit integer encoding for it.
This class handles loading and caching of source files into memory.
PresumedLoc getPresumedLoc(SourceLocation Loc, bool UseLineDirectives=true) const
Returns the "presumed" location of a SourceLocation specifies.
Stmt - This represents one statement.
StmtClass getStmtClass() const
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Stmt * IgnoreContainers(bool IgnoreCaptured=false)
Skip no-op (attributed, compound) container stmts and skip captured stmt at the top,...
SourceLocation getBeginLoc() const LLVM_READONLY
void startDefinition()
Starts the definition of this tag declaration.
The base class of the type hierarchy.
const Type * getPointeeOrArrayElementType() const
If this is a pointer type, return the pointee type.
bool isSignedIntegerType() const
Return true if this is an integer type that is signed, according to C99 6.2.5p4 [char,...
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
RecordDecl * getAsRecordDecl() const
Retrieves the RecordDecl this type refers to.
bool isPointerType() const
CanQualType getCanonicalTypeUnqualified() const
bool isIntegerType() const
isIntegerType() does not include complex integers (a GCC extension).
const T * castAs() const
Member-template castAs<specific type>.
bool isReferenceType() const
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
bool isLValueReferenceType() const
bool isAggregateType() const
Determines whether the type is a C++ aggregate type or C aggregate or union type.
RecordDecl * castAsRecordDecl() const
QualType getCanonicalTypeInternal() const
const Type * getBaseElementTypeUnsafe() const
Get the base element type of this type, potentially discarding type qualifiers.
bool isVariablyModifiedType() const
Whether this type is a variably-modified type (C99 6.7.5).
const ArrayType * getAsArrayTypeUnsafe() const
A variant of getAs<> for array types which silently discards qualifiers from the outermost type.
bool isFloatingType() const
bool isUnsignedIntegerType() const
Return true if this is an integer type that is unsigned, according to C99 6.2.5p6 [which returns true...
bool isAnyPointerType() const
const T * getAs() const
Member-template getAs<specific type>'.
bool isRecordType() const
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Represents a variable declaration or definition.
VarDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
VarDecl * getDefinition(ASTContext &)
Get the real (not just tentative) definition for this declaration.
const Expr * getInit() const
bool hasExternalStorage() const
Returns true if a variable has extern or private_extern storage.
@ DeclarationOnly
This declaration is only a declaration.
DefinitionKind hasDefinition(ASTContext &) const
Check whether this variable is defined in this translation unit.
bool isLocalVarDeclOrParm() const
Similar to isLocalVarDecl but also includes parameters.
const Expr * getAnyInitializer() const
Get the initializer for this variable, no matter which declaration it is attached to.
Represents a C array with a specified size that is not an integer-constant-expression.
Expr * getSizeExpr() const
specific_attr_iterator - Iterates over a subrange of an AttrVec, only providing attributes that are o...
const clang::Expr * ExprTy
@ LLVM_MARK_AS_BITMASK_ENUM
bool isEmptyFieldForLayout(const ASTContext &Ctx, const FieldDecl *FD)
Return true iff the field is "empty", that is, either a zero-width bit-field or an isEmptyRecordForLa...
bool isEmptyRecordForLayout(const ASTContext &Ctx, QualType T)
Return true iff a structure contains only empty base classes (per isEmptyRecordForLayout) and fields ...
@ 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 ...
ComparisonResult
Indicates the result of a tentative comparison.
@ Address
A pointer to a ValueDecl.
Top level wrappers for InstallAPI frontend operations.
bool isOpenMPWorksharingDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a worksharing directive.
CanQual< Type > CanQualType
Represents a canonical, potentially-qualified type.
bool needsTaskBasedThreadLimit(OpenMPDirectiveKind DKind)
Checks if the specified target directive, combined or not, needs task based thread_limit.
@ Match
This is not an overload because the signature exactly matches an existing declaration.
@ Ctor_Complete
Complete object ctor.
Privates[]
This class represents the 'transparent' clause in the 'pragma omp task' directive.
bool isa(CodeGen::Address addr)
if(T->getSizeExpr()) TRY_TO(TraverseStmt(const_cast< Expr * >(T -> getSizeExpr())))
bool isOpenMPTargetDataManagementDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a target data offload directive.
static bool classof(const OMPClause *T)
@ Conditional
A conditional (?:) operator.
@ ICIS_NoInit
No in-class initializer.
bool isOpenMPDistributeDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a distribute directive.
@ LCK_ByRef
Capturing by reference.
LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE()
@ Private
'private' clause, allowed on 'parallel', 'serial', 'loop', 'parallel loop', and 'serial loop' constru...
@ Reduction
'reduction' clause, allowed on Parallel, Serial, Loop, and the combined constructs.
@ Present
'present' clause, allowed on Compute and Combined constructs, plus 'data' and 'declare'.
OpenMPScheduleClauseModifier
OpenMP modifiers for 'schedule' clause.
@ OMPC_SCHEDULE_MODIFIER_last
@ OMPC_SCHEDULE_MODIFIER_unknown
nullptr
This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...
bool isOpenMPParallelDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a parallel-kind directive.
OpenMPDistScheduleClauseKind
OpenMP attributes for 'dist_schedule' clause.
bool isOpenMPTaskingDirective(OpenMPDirectiveKind Kind)
Checks if the specified directive kind is one of tasking directives - task, taskloop,...
bool isOpenMPTargetExecutionDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a target code offload directive.
@ OMPC_DYN_GROUPPRIVATE_FALLBACK_unknown
@ Result
The result type of a method or function.
bool isOpenMPTeamsDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a teams-kind directive.
const FunctionProtoType * T
OpenMPDependClauseKind
OpenMP attributes for 'depend' clause.
@ Dtor_Complete
Complete object dtor.
@ Union
The "union" keyword.
bool isOpenMPTargetMapEnteringDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a map-entering target directive.
bool isOpenMPLoopDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a directive with an associated loop construct.
OpenMPSeverityClauseKind
OpenMP attributes for 'severity' clause.
LangAS
Defines the address space values used by the address space qualifier of QualType.
llvm::omp::Directive OpenMPDirectiveKind
OpenMP directives.
bool isOpenMPSimdDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a simd directive.
@ VK_PRValue
A pr-value expression (in the C++11 taxonomy) produces a temporary value.
@ VK_LValue
An l-value expression is a reference to an object with independent storage.
for(const auto &A :T->param_types())
void getOpenMPCaptureRegions(llvm::SmallVectorImpl< OpenMPDirectiveKind > &CaptureRegions, OpenMPDirectiveKind DKind)
Return the captured regions of an OpenMP directive.
OpenMPNumThreadsClauseModifier
@ OMPC_ATOMIC_DEFAULT_MEM_ORDER_unknown
U cast(CodeGen::Address addr)
OpenMPMapModifierKind
OpenMP modifier kind for 'map' clause.
@ OMPC_MAP_MODIFIER_unknown
@ Other
Other implicit parameter.
OpenMPScheduleClauseKind
OpenMP attributes for 'schedule' clause.
bool isOpenMPTaskLoopDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a taskloop directive.
OpenMPThreadsetKind
OpenMP modifiers for 'threadset' clause.
OpenMPMapClauseKind
OpenMP mapping kind for 'map' clause.
Diagnostic wrappers for TextAPI types for error reporting.
__builtin_bitreverse32 uint32_t __builtin_riscv_aaddu_u32 __builtin_riscv_asubu_u32 __builtin_elementwise_add_sat __builtin_elementwise_sub_sat int32_t uint32_t uint32_t __builtin_riscv_mhacc_i32 __builtin_riscv_mhaccu_u32 __builtin_riscv_mhaccsu_i32 __builtin_riscv_mulq_i32 int64_t
__builtin_bitreverse32 uint32_t __builtin_riscv_aaddu_u32 __builtin_riscv_asubu_u32 __builtin_elementwise_add_sat __builtin_elementwise_sub_sat int32_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.