32#include "llvm/ADT/ArrayRef.h"
33#include "llvm/ADT/SmallSet.h"
34#include "llvm/ADT/SmallVector.h"
35#include "llvm/ADT/StringExtras.h"
36#include "llvm/Bitcode/BitcodeReader.h"
37#include "llvm/IR/Constants.h"
38#include "llvm/IR/DerivedTypes.h"
39#include "llvm/IR/GlobalValue.h"
40#include "llvm/IR/InstrTypes.h"
41#include "llvm/IR/Value.h"
42#include "llvm/Support/AtomicOrdering.h"
43#include "llvm/Support/VirtualFileSystem.h"
44#include "llvm/Support/raw_ostream.h"
52using namespace llvm::omp;
59 enum CGOpenMPRegionKind {
62 ParallelOutlinedRegion,
72 CGOpenMPRegionInfo(
const CapturedStmt &CS,
73 const CGOpenMPRegionKind RegionKind,
76 : CGCapturedStmtInfo(CS,
CR_OpenMP), RegionKind(RegionKind),
77 CodeGen(CodeGen), Kind(Kind), HasCancel(HasCancel) {}
79 CGOpenMPRegionInfo(
const CGOpenMPRegionKind RegionKind,
82 : CGCapturedStmtInfo(
CR_OpenMP), RegionKind(RegionKind), CodeGen(CodeGen),
83 Kind(Kind), HasCancel(HasCancel) {}
87 virtual const VarDecl *getThreadIDVariable()
const = 0;
90 void EmitBody(CodeGenFunction &CGF,
const Stmt *S)
override;
94 virtual LValue getThreadIDVariableLValue(CodeGenFunction &CGF);
96 virtual void emitUntiedSwitch(CodeGenFunction & ) {}
98 CGOpenMPRegionKind getRegionKind()
const {
return RegionKind; }
102 bool hasCancel()
const {
return HasCancel; }
104 static bool classof(
const CGCapturedStmtInfo *Info) {
108 ~CGOpenMPRegionInfo()
override =
default;
111 CGOpenMPRegionKind RegionKind;
112 RegionCodeGenTy CodeGen;
118class CGOpenMPOutlinedRegionInfo final :
public CGOpenMPRegionInfo {
120 CGOpenMPOutlinedRegionInfo(
const CapturedStmt &CS,
const VarDecl *ThreadIDVar,
121 const RegionCodeGenTy &CodeGen,
123 StringRef HelperName)
124 : CGOpenMPRegionInfo(CS, ParallelOutlinedRegion, CodeGen,
Kind,
126 ThreadIDVar(ThreadIDVar), HelperName(HelperName) {
127 assert(ThreadIDVar !=
nullptr &&
"No ThreadID in OpenMP region.");
132 const VarDecl *getThreadIDVariable()
const override {
return ThreadIDVar; }
135 StringRef getHelperName()
const override {
return HelperName; }
137 static bool classof(
const CGCapturedStmtInfo *Info) {
138 return CGOpenMPRegionInfo::classof(Info) &&
140 ParallelOutlinedRegion;
146 const VarDecl *ThreadIDVar;
147 StringRef HelperName;
151class CGOpenMPTaskOutlinedRegionInfo final :
public CGOpenMPRegionInfo {
153 class UntiedTaskActionTy final :
public PrePostActionTy {
155 const VarDecl *PartIDVar;
156 const RegionCodeGenTy UntiedCodeGen;
157 llvm::SwitchInst *UntiedSwitch =
nullptr;
160 UntiedTaskActionTy(
bool Tied,
const VarDecl *PartIDVar,
161 const RegionCodeGenTy &UntiedCodeGen)
162 : Untied(!Tied), PartIDVar(PartIDVar), UntiedCodeGen(UntiedCodeGen) {}
163 void Enter(CodeGenFunction &CGF)
override {
168 PartIDVar->
getType()->castAs<PointerType>());
172 UntiedSwitch = CGF.
Builder.CreateSwitch(Res, DoneBB);
176 UntiedSwitch->addCase(CGF.
Builder.getInt32(0),
178 emitUntiedSwitch(CGF);
181 void emitUntiedSwitch(CodeGenFunction &CGF)
const {
185 PartIDVar->
getType()->castAs<PointerType>());
189 CodeGenFunction::JumpDest CurPoint =
193 UntiedSwitch->addCase(CGF.
Builder.getInt32(UntiedSwitch->getNumCases()),
199 unsigned getNumberOfParts()
const {
return UntiedSwitch->getNumCases(); }
201 CGOpenMPTaskOutlinedRegionInfo(
const CapturedStmt &CS,
202 const VarDecl *ThreadIDVar,
203 const RegionCodeGenTy &CodeGen,
205 const UntiedTaskActionTy &Action)
206 : CGOpenMPRegionInfo(CS, TaskOutlinedRegion, CodeGen,
Kind, HasCancel),
207 ThreadIDVar(ThreadIDVar), Action(Action) {
208 assert(ThreadIDVar !=
nullptr &&
"No ThreadID in OpenMP region.");
213 const VarDecl *getThreadIDVariable()
const override {
return ThreadIDVar; }
216 LValue getThreadIDVariableLValue(CodeGenFunction &CGF)
override;
219 StringRef getHelperName()
const override {
return ".omp_outlined."; }
221 void emitUntiedSwitch(CodeGenFunction &CGF)
override {
222 Action.emitUntiedSwitch(CGF);
225 static bool classof(
const CGCapturedStmtInfo *Info) {
226 return CGOpenMPRegionInfo::classof(Info) &&
234 const VarDecl *ThreadIDVar;
236 const UntiedTaskActionTy &Action;
241class CGOpenMPInlinedRegionInfo :
public CGOpenMPRegionInfo {
243 CGOpenMPInlinedRegionInfo(CodeGenFunction::CGCapturedStmtInfo *OldCSI,
244 const RegionCodeGenTy &CodeGen,
246 : CGOpenMPRegionInfo(InlinedRegion, CodeGen,
Kind, HasCancel),
248 OuterRegionInfo(dyn_cast_or_null<CGOpenMPRegionInfo>(OldCSI)) {}
251 llvm::Value *getContextValue()
const override {
253 return OuterRegionInfo->getContextValue();
254 llvm_unreachable(
"No context value for inlined OpenMP region");
257 void setContextValue(llvm::Value *
V)
override {
258 if (OuterRegionInfo) {
259 OuterRegionInfo->setContextValue(
V);
262 llvm_unreachable(
"No context value for inlined OpenMP region");
266 const FieldDecl *lookup(
const VarDecl *VD)
const override {
268 return OuterRegionInfo->lookup(VD);
274 FieldDecl *getThisFieldDecl()
const override {
276 return OuterRegionInfo->getThisFieldDecl();
282 const VarDecl *getThreadIDVariable()
const override {
284 return OuterRegionInfo->getThreadIDVariable();
289 LValue getThreadIDVariableLValue(CodeGenFunction &CGF)
override {
291 return OuterRegionInfo->getThreadIDVariableLValue(CGF);
292 llvm_unreachable(
"No LValue for inlined OpenMP construct");
296 StringRef getHelperName()
const override {
297 if (
auto *OuterRegionInfo = getOldCSI())
298 return OuterRegionInfo->getHelperName();
299 llvm_unreachable(
"No helper name for inlined OpenMP construct");
302 void emitUntiedSwitch(CodeGenFunction &CGF)
override {
304 OuterRegionInfo->emitUntiedSwitch(CGF);
307 CodeGenFunction::CGCapturedStmtInfo *getOldCSI()
const {
return OldCSI; }
309 static bool classof(
const CGCapturedStmtInfo *Info) {
310 return CGOpenMPRegionInfo::classof(Info) &&
314 ~CGOpenMPInlinedRegionInfo()
override =
default;
318 CodeGenFunction::CGCapturedStmtInfo *OldCSI;
319 CGOpenMPRegionInfo *OuterRegionInfo;
327class CGOpenMPTargetRegionInfo final :
public CGOpenMPRegionInfo {
329 CGOpenMPTargetRegionInfo(
const CapturedStmt &CS,
330 const RegionCodeGenTy &CodeGen, StringRef HelperName)
331 : CGOpenMPRegionInfo(CS, TargetRegion, CodeGen, OMPD_target,
333 HelperName(HelperName) {}
337 const VarDecl *getThreadIDVariable()
const override {
return nullptr; }
340 StringRef getHelperName()
const override {
return HelperName; }
342 static bool classof(
const CGCapturedStmtInfo *Info) {
343 return CGOpenMPRegionInfo::classof(Info) &&
348 StringRef HelperName;
352 llvm_unreachable(
"No codegen for expressions");
356class CGOpenMPInnerExprInfo final :
public CGOpenMPInlinedRegionInfo {
358 CGOpenMPInnerExprInfo(CodeGenFunction &CGF,
const CapturedStmt &CS)
359 : CGOpenMPInlinedRegionInfo(CGF.CapturedStmtInfo, EmptyCodeGen,
367 if (!C.capturesVariable() && !C.capturesVariableByCopy())
370 const VarDecl *VD = C.getCapturedVar();
371 if (VD->isLocalVarDeclOrParm())
374 DeclRefExpr DRE(CGF.getContext(), const_cast<VarDecl *>(VD),
376 VD->getType().getNonReferenceType(), VK_LValue,
378 PrivScope.addPrivate(VD, CGF.EmitLValue(&DRE).getAddress());
380 (
void)PrivScope.Privatize();
384 const FieldDecl *lookup(
const VarDecl *VD)
const override {
385 if (
const FieldDecl *FD = CGOpenMPInlinedRegionInfo::lookup(VD))
391 void EmitBody(CodeGenFunction &CGF,
const Stmt *S)
override {
392 llvm_unreachable(
"No body for expressions");
397 const VarDecl *getThreadIDVariable()
const override {
398 llvm_unreachable(
"No thread id for expressions");
402 StringRef getHelperName()
const override {
403 llvm_unreachable(
"No helper name for expressions");
406 static bool classof(
const CGCapturedStmtInfo *Info) {
return false; }
410 CodeGenFunction::OMPPrivateScope PrivScope;
414class InlinedOpenMPRegionRAII {
415 CodeGenFunction &CGF;
416 llvm::DenseMap<const ValueDecl *, FieldDecl *> LambdaCaptureFields;
417 FieldDecl *LambdaThisCaptureField =
nullptr;
418 const CodeGen::CGBlockInfo *BlockInfo =
nullptr;
419 bool NoInheritance =
false;
426 InlinedOpenMPRegionRAII(CodeGenFunction &CGF,
const RegionCodeGenTy &CodeGen,
428 bool NoInheritance =
true)
429 : CGF(CGF), NoInheritance(NoInheritance) {
431 CGF.CapturedStmtInfo =
new CGOpenMPInlinedRegionInfo(
432 CGF.CapturedStmtInfo, CodeGen, Kind, HasCancel);
434 std::swap(CGF.LambdaCaptureFields, LambdaCaptureFields);
435 LambdaThisCaptureField = CGF.LambdaThisCaptureField;
436 CGF.LambdaThisCaptureField =
nullptr;
437 BlockInfo = CGF.BlockInfo;
438 CGF.BlockInfo =
nullptr;
442 ~InlinedOpenMPRegionRAII() {
446 delete CGF.CapturedStmtInfo;
447 CGF.CapturedStmtInfo = OldCSI;
449 std::swap(CGF.LambdaCaptureFields, LambdaCaptureFields);
450 CGF.LambdaThisCaptureField = LambdaThisCaptureField;
451 CGF.BlockInfo = BlockInfo;
459enum OpenMPLocationFlags :
unsigned {
461 OMP_IDENT_IMD = 0x01,
463 OMP_IDENT_KMPC = 0x02,
465 OMP_ATOMIC_REDUCE = 0x10,
467 OMP_IDENT_BARRIER_EXPL = 0x20,
469 OMP_IDENT_BARRIER_IMPL = 0x40,
471 OMP_IDENT_BARRIER_IMPL_FOR = 0x40,
473 OMP_IDENT_BARRIER_IMPL_SECTIONS = 0xC0,
475 OMP_IDENT_BARRIER_IMPL_SINGLE = 0x140,
477 OMP_IDENT_WORK_LOOP = 0x200,
479 OMP_IDENT_WORK_SECTIONS = 0x400,
481 OMP_IDENT_WORK_DISTRIBUTE = 0x800,
511enum IdentFieldIndex {
513 IdentField_Reserved_1,
517 IdentField_Reserved_2,
519 IdentField_Reserved_3,
528enum OpenMPSchedType {
531 OMP_sch_static_chunked = 33,
533 OMP_sch_dynamic_chunked = 35,
534 OMP_sch_guided_chunked = 36,
535 OMP_sch_runtime = 37,
538 OMP_sch_static_balanced_chunked = 45,
541 OMP_ord_static_chunked = 65,
543 OMP_ord_dynamic_chunked = 67,
544 OMP_ord_guided_chunked = 68,
545 OMP_ord_runtime = 69,
547 OMP_sch_default = OMP_sch_static,
549 OMP_dist_sch_static_chunked = 91,
550 OMP_dist_sch_static = 92,
556 OMP_dist_sch_static_chunked_sch_static_chunkone = 93,
559 OMP_sch_modifier_monotonic = (1 << 29),
561 OMP_sch_modifier_nonmonotonic = (1 << 30),
566class CleanupTy final :
public EHScopeStack::Cleanup {
567 PrePostActionTy *Action;
570 explicit CleanupTy(PrePostActionTy *Action) : Action(Action) {}
571 void Emit(CodeGenFunction &CGF, Flags )
override {
584 Callback(CodeGen, CGF, *PrePostAction);
595 if (
const auto *CE = dyn_cast<CallExpr>(ReductionOp))
596 if (
const auto *OVE = dyn_cast<OpaqueValueExpr>(CE->getCallee()))
597 if (
const auto *DRE =
598 dyn_cast<DeclRefExpr>(OVE->getSourceExpr()->IgnoreImpCasts()))
599 if (
const auto *DRD = dyn_cast<OMPDeclareReductionDecl>(DRE->getDecl()))
610 std::pair<llvm::Function *, llvm::Function *>
Reduction =
630 auto *GV =
new llvm::GlobalVariable(
632 llvm::GlobalValue::PrivateLinkage,
Init, Name);
673 llvm::Value *NumElements = CGF.
emitArrayLength(ArrayTy, ElementTy, DestAddr);
677 llvm::Value *SrcBegin =
nullptr;
679 SrcBegin = SrcAddr.emitRawPointer(CGF);
682 llvm::Value *DestEnd =
687 llvm::Value *IsEmpty =
688 CGF.
Builder.CreateICmpEQ(DestBegin, DestEnd,
"omp.arrayinit.isempty");
689 CGF.
Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
692 llvm::BasicBlock *EntryBB = CGF.
Builder.GetInsertBlock();
697 llvm::PHINode *SrcElementPHI =
nullptr;
700 SrcElementPHI = CGF.
Builder.CreatePHI(SrcBegin->getType(), 2,
701 "omp.arraycpy.srcElementPast");
702 SrcElementPHI->addIncoming(SrcBegin, EntryBB);
704 Address(SrcElementPHI, SrcAddr.getElementType(),
705 SrcAddr.getAlignment().alignmentOfArrayElement(ElementSize));
707 llvm::PHINode *DestElementPHI = CGF.
Builder.CreatePHI(
708 DestBegin->getType(), 2,
"omp.arraycpy.destElementPast");
709 DestElementPHI->addIncoming(DestBegin, EntryBB);
717 if (EmitDeclareReductionInit) {
719 SrcElementCurrent, ElementTy);
727 llvm::Value *SrcElementNext = CGF.
Builder.CreateConstGEP1_32(
728 SrcAddr.getElementType(), SrcElementPHI, 1,
729 "omp.arraycpy.dest.element");
730 SrcElementPHI->addIncoming(SrcElementNext, CGF.
Builder.GetInsertBlock());
734 llvm::Value *DestElementNext = CGF.
Builder.CreateConstGEP1_32(
736 "omp.arraycpy.dest.element");
739 CGF.
Builder.CreateICmpEQ(DestElementNext, DestEnd,
"omp.arraycpy.done");
740 CGF.
Builder.CreateCondBr(Done, DoneBB, BodyBB);
741 DestElementPHI->addIncoming(DestElementNext, CGF.
Builder.GetInsertBlock());
753 if (
const auto *OASE = dyn_cast<ArraySectionExpr>(E))
758void ReductionCodeGen::emitAggregateInitialization(
760 const OMPDeclareReductionDecl *DRD) {
764 const auto *PrivateVD =
766 bool EmitDeclareReductionInit =
769 EmitDeclareReductionInit,
770 EmitDeclareReductionInit ? ClausesData[N].ReductionOp
771 : PrivateVD->getInit(),
779 ClausesData.reserve(Shareds.size());
780 SharedAddresses.reserve(Shareds.size());
781 Sizes.reserve(Shareds.size());
782 BaseDecls.reserve(Shareds.size());
783 const auto *IOrig = Origs.begin();
784 const auto *IPriv =
Privates.begin();
785 const auto *IRed = ReductionOps.begin();
786 for (
const Expr *Ref : Shareds) {
787 ClausesData.emplace_back(Ref, *IOrig, *IPriv, *IRed);
788 std::advance(IOrig, 1);
789 std::advance(IPriv, 1);
790 std::advance(IRed, 1);
795 assert(SharedAddresses.size() == N && OrigAddresses.size() == N &&
796 "Number of generated lvalues must be exactly N.");
797 LValue First = emitSharedLValue(CGF, ClausesData[N].Shared);
798 LValue Second = emitSharedLValueUB(CGF, ClausesData[N].Shared);
799 SharedAddresses.emplace_back(
First, Second);
800 if (ClausesData[N].Shared == ClausesData[N].Ref) {
801 OrigAddresses.emplace_back(
First, Second);
803 LValue First = emitSharedLValue(CGF, ClausesData[N].Ref);
804 LValue Second = emitSharedLValueUB(CGF, ClausesData[N].Ref);
805 OrigAddresses.emplace_back(
First, Second);
814 CGF.
getTypeSize(OrigAddresses[N].first.getType().getNonReferenceType()),
819 llvm::Value *SizeInChars;
820 auto *ElemType = OrigAddresses[N].first.getAddress().getElementType();
821 auto *ElemSizeOf = llvm::ConstantInt::get(
823 if (AsArraySection) {
825 CGF.
Builder.CreatePtrDiff(OrigAddresses[N].second.getPointer(CGF),
826 OrigAddresses[N].first.getPointer(CGF));
827 SizeInChars = CGF.
Builder.CreateNUWAdd(SizeInChars, ElemSizeOf);
830 CGF.
getTypeSize(OrigAddresses[N].first.getType().getNonReferenceType());
832 Size = ElemSizeOf->isOne()
834 : CGF.
Builder.CreateExactUDiv(SizeInChars, ElemSizeOf);
835 Sizes.emplace_back(SizeInChars, Size);
848 assert(!Size && !Sizes[N].second &&
849 "Size should be nullptr for non-variably modified reduction "
864 assert(SharedAddresses.size() > N &&
"No variable was generated");
865 const auto *PrivateVD =
871 (void)DefaultInit(CGF);
872 emitAggregateInitialization(CGF, N, PrivateAddr, SharedAddr, DRD);
873 }
else if (DRD && (DRD->
getInitializer() || !PrivateVD->hasInit())) {
874 (void)DefaultInit(CGF);
875 QualType SharedType = SharedAddresses[N].first.getType();
877 PrivateAddr, SharedAddr, SharedType);
878 }
else if (!DefaultInit(CGF) && PrivateVD->hasInit() &&
881 PrivateVD->
getType().getQualifiers(),
899 CGF.
pushDestroy(DTorKind, PrivateAddr, PrivateType);
918 BaseLV.getType(), BaseLV.getBaseInfo(),
952 const VarDecl *OrigVD =
nullptr;
953 if (
const auto *OASE = dyn_cast<ArraySectionExpr>(Ref)) {
954 const Expr *
Base = OASE->getBase()->IgnoreParenImpCasts();
955 while (
const auto *TempOASE = dyn_cast<ArraySectionExpr>(
Base))
956 Base = TempOASE->getBase()->IgnoreParenImpCasts();
957 while (
const auto *TempASE = dyn_cast<ArraySubscriptExpr>(
Base))
958 Base = TempASE->getBase()->IgnoreParenImpCasts();
961 }
else if (
const auto *ASE = dyn_cast<ArraySubscriptExpr>(Ref)) {
962 const Expr *
Base = ASE->getBase()->IgnoreParenImpCasts();
963 while (
const auto *TempASE = dyn_cast<ArraySubscriptExpr>(
Base))
964 Base = TempASE->getBase()->IgnoreParenImpCasts();
975 BaseDecls.emplace_back(OrigVD);
978 loadToBegin(CGF, OrigVD->getType(), SharedAddresses[N].first.getType(),
980 Address SharedAddr = SharedAddresses[N].first.getAddress();
981 llvm::Value *Adjustment = CGF.
Builder.CreatePtrDiff(
984 llvm::Value *PrivatePointer =
990 SharedAddresses[N].first.getType(),
993 BaseDecls.emplace_back(
1007 getThreadIDVariable()->
getType()->castAs<PointerType>());
1025LValue CGOpenMPTaskOutlinedRegionInfo::getThreadIDVariableLValue(
1028 getThreadIDVariable()->
getType(),
1046 llvm::OpenMPIRBuilderConfig Config(
1047 CGM.getLangOpts().OpenMPIsTargetDevice,
isGPU(),
1048 CGM.getLangOpts().OpenMPOffloadMandatory,
1051 Config.setDefaultTargetAS(
1053 Config.setRuntimeCC(
CGM.getRuntimeCC());
1058 CGM.getLangOpts().OpenMPIsTargetDevice
1059 ?
CGM.getLangOpts().OMPHostIRFile
1064 if (
CGM.getLangOpts().OpenMPForceUSM) {
1066 OMPBuilder.Config.setHasRequiresUnifiedSharedMemory(
true);
1074 if (!
Data.getValue().pointsToAliveValue())
1076 auto *GV = dyn_cast<llvm::GlobalVariable>(
Data.getValue());
1079 if (!GV->isDeclaration() || GV->getNumUses() > 0)
1081 GV->eraseFromParent();
1086 return OMPBuilder.createPlatformSpecificName(Parts);
1089static llvm::Function *
1091 const Expr *CombinerInitializer,
const VarDecl *In,
1092 const VarDecl *Out,
bool IsCombiner) {
1095 QualType PtrTy =
C.getPointerType(Ty).withRestrict();
1097 C,
nullptr, Out->getLocation(),
1100 C,
nullptr, In->getLocation(),
1107 {IsCombiner ?
"omp_combiner" :
"omp_initializer",
""});
1108 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
1112 Fn->addFnAttr(
"sample-profile-suffix-elision-policy",
"selected");
1114 Fn->removeFnAttr(llvm::Attribute::NoInline);
1115 Fn->removeFnAttr(llvm::Attribute::OptimizeNone);
1116 Fn->addFnAttr(llvm::Attribute::AlwaysInline);
1122 Out->getLocation());
1132 (void)
Scope.Privatize();
1133 if (!IsCombiner && Out->hasInit() &&
1136 Out->getType().getQualifiers(),
1139 if (CombinerInitializer)
1141 Scope.ForceCleanup();
1170std::pair<llvm::Function *, llvm::Function *>
1182struct PushAndPopStackRAII {
1183 PushAndPopStackRAII(llvm::OpenMPIRBuilder *OMPBuilder,
CodeGenFunction &CGF,
1184 bool HasCancel, llvm::omp::Directive Kind)
1185 : OMPBuilder(OMPBuilder) {
1201 auto FiniCB = [&CGF](llvm::OpenMPIRBuilder::InsertPointTy IP) {
1202 assert(IP == IP.getNodeParent()->end() &&
1203 "Clang CG should cause non-terminated block!");
1204 CGBuilderTy::InsertPointGuard IPG(CGF.
Builder);
1209 return llvm::Error::success();
1214 llvm::OpenMPIRBuilder::FinalizationInfo FI({FiniCB, Kind, HasCancel});
1215 OMPBuilder->pushFinalizationCB(std::move(FI));
1217 ~PushAndPopStackRAII() {
1219 OMPBuilder->popFinalizationCB();
1221 llvm::OpenMPIRBuilder *OMPBuilder;
1230 "thread id variable must be of type kmp_int32 *");
1232 bool HasCancel =
false;
1233 if (
const auto *OPD = dyn_cast<OMPParallelDirective>(&D))
1234 HasCancel = OPD->hasCancel();
1235 else if (
const auto *OPD = dyn_cast<OMPTargetParallelDirective>(&D))
1236 HasCancel = OPD->hasCancel();
1237 else if (
const auto *OPSD = dyn_cast<OMPParallelSectionsDirective>(&D))
1238 HasCancel = OPSD->hasCancel();
1239 else if (
const auto *OPFD = dyn_cast<OMPParallelForDirective>(&D))
1240 HasCancel = OPFD->hasCancel();
1241 else if (
const auto *OPFD = dyn_cast<OMPTargetParallelForDirective>(&D))
1242 HasCancel = OPFD->hasCancel();
1243 else if (
const auto *OPFD = dyn_cast<OMPDistributeParallelForDirective>(&D))
1244 HasCancel = OPFD->hasCancel();
1245 else if (
const auto *OPFD =
1246 dyn_cast<OMPTeamsDistributeParallelForDirective>(&D))
1247 HasCancel = OPFD->hasCancel();
1248 else if (
const auto *OPFD =
1249 dyn_cast<OMPTargetTeamsDistributeParallelForDirective>(&D))
1250 HasCancel = OPFD->hasCancel();
1255 PushAndPopStackRAII PSR(&OMPBuilder, CGF, HasCancel, InnermostKind);
1256 CGOpenMPOutlinedRegionInfo CGInfo(*CS, ThreadIDVar,
CodeGen, InnermostKind,
1257 HasCancel, OutlinedHelperName);
1263 std::string Suffix =
getName({
"omp_outlined"});
1264 return (Name + Suffix).str();
1272 std::string Suffix =
getName({
"omp",
"reduction",
"reduction_func"});
1273 return (Name + Suffix).str();
1280 const CapturedStmt *CS = D.getCapturedStmt(OMPD_parallel);
1290 const CapturedStmt *CS = D.getCapturedStmt(OMPD_teams);
1297 OutlinedFn->setDoesNotRecurse();
1305 bool Tied,
unsigned &NumberOfParts) {
1308 llvm::Value *ThreadID =
getThreadID(CGF, D.getBeginLoc());
1310 llvm::Value *TaskArgs[] = {
1312 CGF.EmitLoadOfPointerLValue(CGF.GetAddrOfLocalVar(TaskTVar),
1315 CGF.EmitRuntimeCall(
OMPBuilder.getOrCreateRuntimeFunction(
1316 CGM.getModule(), OMPRTL___kmpc_omp_task),
1319 CGOpenMPTaskOutlinedRegionInfo::UntiedTaskActionTy Action(Tied, PartIDVar,
1323 "thread id variable must be of type kmp_int32 for tasks");
1328 bool HasCancel =
false;
1329 if (
const auto *TD = dyn_cast<OMPTaskDirective>(&D))
1330 HasCancel = TD->hasCancel();
1331 else if (
const auto *TD = dyn_cast<OMPTaskLoopDirective>(&D))
1332 HasCancel = TD->hasCancel();
1333 else if (
const auto *TD = dyn_cast<OMPMasterTaskLoopDirective>(&D))
1334 HasCancel = TD->hasCancel();
1335 else if (
const auto *TD = dyn_cast<OMPParallelMasterTaskLoopDirective>(&D))
1336 HasCancel = TD->hasCancel();
1339 CGOpenMPTaskOutlinedRegionInfo CGInfo(*CS, ThreadIDVar,
CodeGen,
1340 InnermostKind, HasCancel, Action);
1342 llvm::Function *Res = CGF.GenerateCapturedStmtFunction(*CS);
1344 NumberOfParts = Action.getNumberOfParts();
1349 bool AtCurrentPoint) {
1351 assert(!Elem.ServiceInsertPt &&
"Insert point is set already.");
1353 llvm::Value *Undef = llvm::UndefValue::get(CGF.
Int32Ty);
1354 if (AtCurrentPoint) {
1355 Elem.ServiceInsertPt =
new llvm::BitCastInst(Undef, CGF.
Int32Ty,
"svcpt",
1356 CGF.
Builder.GetInsertBlock());
1358 Elem.ServiceInsertPt =
new llvm::BitCastInst(Undef, CGF.
Int32Ty,
"svcpt");
1359 Elem.ServiceInsertPt->insertAfter(CGF.
AllocaInsertPt->getIterator());
1365 if (Elem.ServiceInsertPt) {
1366 llvm::Instruction *Ptr = Elem.ServiceInsertPt;
1367 Elem.ServiceInsertPt =
nullptr;
1368 Ptr->eraseFromParent();
1375 llvm::raw_svector_ostream OS(Buffer);
1384 if (
const auto *FD = dyn_cast_or_null<FunctionDecl>(CGF.
CurFuncDecl))
1385 OS << FD->getQualifiedNameAsString();
1392 unsigned Flags,
bool EmitLoc) {
1393 uint32_t SrcLocStrSize;
1394 llvm::Constant *SrcLocStr;
1395 if ((!EmitLoc &&
CGM.getCodeGenOpts().getDebugInfo() ==
1396 llvm::codegenoptions::NoDebugInfo) ||
1398 SrcLocStr =
OMPBuilder.getOrCreateDefaultSrcLocStr(SrcLocStrSize);
1400 std::string FunctionName;
1402 if (
const auto *FD = dyn_cast_or_null<FunctionDecl>(CGF.
CurFuncDecl))
1403 FunctionName = FD->getQualifiedNameAsString();
1416 SrcLocStr, SrcLocStrSize, llvm::omp::IdentFlag(Flags), Reserved2Flags);
1421 assert(CGF.
CurFn &&
"No function in current CodeGenFunction.");
1424 if (
CGM.getLangOpts().OpenMPIRBuilder) {
1427 uint32_t SrcLocStrSize;
1428 auto *SrcLocStr =
OMPBuilder.getOrCreateSrcLocStr(
1431 OMPBuilder.getOrCreateIdent(SrcLocStr, SrcLocStrSize));
1434 llvm::Value *ThreadID =
nullptr;
1439 ThreadID = I->second.ThreadID;
1440 if (ThreadID !=
nullptr)
1444 if (
auto *OMPRegionInfo =
1446 if (OMPRegionInfo->getThreadIDVariable()) {
1448 LValue LVal = OMPRegionInfo->getThreadIDVariableLValue(CGF);
1452 CGF.
Builder.GetInsertBlock() == TopBlock ||
1457 CGF.
Builder.GetInsertBlock()) {
1461 if (CGF.
Builder.GetInsertBlock() == TopBlock)
1473 if (!Elem.ServiceInsertPt)
1475 CGBuilderTy::InsertPointGuard IPG(CGF.
Builder);
1476 CGF.
Builder.SetInsertPoint(Elem.ServiceInsertPt);
1480 OMPRTL___kmpc_global_thread_num),
1483 Elem.ThreadID =
Call;
1488 assert(CGF.
CurFn &&
"No function in current CodeGenFunction.");
1494 for (
const auto *D : I->second)
1499 for (
const auto *D : I->second)
1511static llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseKind
1513 std::optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
1514 OMPDeclareTargetDeclAttr::getDeviceType(VD);
1516 return llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseNone;
1518 switch ((
int)*DevTy) {
1519 case OMPDeclareTargetDeclAttr::DT_Host:
1520 return llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseHost;
1522 case OMPDeclareTargetDeclAttr::DT_NoHost:
1523 return llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseNoHost;
1525 case OMPDeclareTargetDeclAttr::DT_Any:
1526 return llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseAny;
1529 return llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseNone;
1534static llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryKind
1536 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> MapType =
1537 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
1539 return llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryNone;
1540 switch ((
int)*MapType) {
1541 case OMPDeclareTargetDeclAttr::MapTypeTy::MT_To:
1542 return llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryTo;
1544 case OMPDeclareTargetDeclAttr::MapTypeTy::MT_Enter:
1545 return llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryEnter;
1546 case OMPDeclareTargetDeclAttr::MapTypeTy::MT_Link:
1547 return llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryLink;
1549 case OMPDeclareTargetDeclAttr::MapTypeTy::MT_Local:
1551 llvm_unreachable(
"MT_Local should not reach convertCaptureClause");
1554 return llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryNone;
1563 auto FileInfoCallBack = [&]() {
1573 return OMPBuilder.getTargetEntryUniqueInfo(FileInfoCallBack,
1578 auto AddrOfGlobal = [&VD,
this]() {
return CGM.GetAddrOfGlobal(VD); };
1580 auto LinkageForVariable = [&VD,
this]() {
1581 return CGM.getLLVMLinkageVarDefinition(VD);
1584 std::vector<llvm::GlobalVariable *> GeneratedRefs;
1586 llvm::Type *LlvmPtrTy =
CGM.getTypes().ConvertTypeForMem(
1587 CGM.getContext().getPointerType(VD->
getType()));
1588 llvm::Constant *addr =
OMPBuilder.getAddrOfDeclareTargetVar(
1594 CGM.getMangledName(VD), GeneratedRefs,
CGM.getLangOpts().OpenMPSimd,
1595 CGM.getLangOpts().OMPTargetTriples, LlvmPtrTy, AddrOfGlobal,
1596 LinkageForVariable);
1605 assert(!
CGM.getLangOpts().OpenMPUseTLS ||
1606 !
CGM.getContext().getTargetInfo().isTLSSupported());
1608 std::string Suffix =
getName({
"cache",
""});
1609 return OMPBuilder.getOrCreateInternalVariable(
1610 CGM.Int8PtrPtrTy, Twine(
CGM.getMangledName(VD)).concat(Suffix).str());
1617 if (
CGM.getLangOpts().OpenMPUseTLS &&
1618 CGM.getContext().getTargetInfo().isTLSSupported())
1622 llvm::Value *Args[] = {
1625 CGM.getSize(
CGM.GetTargetTypeStoreSize(VarTy)),
1630 CGM.getModule(), OMPRTL___kmpc_threadprivate_cached),
1642 CGM.getModule(), OMPRTL___kmpc_global_thread_num),
1646 llvm::Value *Args[] = {
1649 Ctor, CopyCtor, Dtor};
1652 CGM.getModule(), OMPRTL___kmpc_threadprivate_register),
1659 if (
CGM.getLangOpts().OpenMPUseTLS &&
1660 CGM.getContext().getTargetInfo().isTLSSupported())
1667 llvm::Value *Ctor =
nullptr, *CopyCtor =
nullptr, *Dtor =
nullptr;
1669 if (
CGM.getLangOpts().CPlusPlus && PerformInit) {
1674 CGM.getContext(),
nullptr, Loc,
1678 const auto &FI =
CGM.getTypes().arrangeBuiltinFunctionDeclaration(
1679 CGM.getContext().VoidPtrTy, Args);
1680 llvm::FunctionType *FTy =
CGM.getTypes().GetFunctionType(FI);
1681 std::string Name =
getName({
"__kmpc_global_ctor_",
""});
1682 llvm::Function *Fn =
1683 CGM.CreateGlobalInitOrCleanUpFunction(FTy, Name, FI, Loc);
1688 CGM.getContext().VoidPtrTy, Dst->getLocation());
1695 CGM.getContext().VoidPtrTy, Dst->getLocation());
1705 CGM.getContext(),
nullptr, Loc,
1709 const auto &FI =
CGM.getTypes().arrangeBuiltinFunctionDeclaration(
1710 CGM.getContext().VoidTy, Args);
1711 llvm::FunctionType *FTy =
CGM.getTypes().GetFunctionType(FI);
1712 std::string Name =
getName({
"__kmpc_global_dtor_",
""});
1713 llvm::Function *Fn =
1714 CGM.CreateGlobalInitOrCleanUpFunction(FTy, Name, FI, Loc);
1722 false,
CGM.getContext().VoidPtrTy, Dst->getLocation());
1737 CopyCtor = llvm::Constant::getNullValue(
CGM.DefaultPtrTy);
1738 if (Ctor ==
nullptr) {
1739 Ctor = llvm::Constant::getNullValue(
CGM.DefaultPtrTy);
1741 if (Dtor ==
nullptr) {
1742 Dtor = llvm::Constant::getNullValue(
CGM.DefaultPtrTy);
1745 auto *InitFunctionTy =
1746 llvm::FunctionType::get(
CGM.VoidTy,
false);
1747 std::string Name =
getName({
"__omp_threadprivate_init_",
""});
1748 llvm::Function *InitFunction =
CGM.CreateGlobalInitOrCleanUpFunction(
1749 InitFunctionTy, Name,
CGM.getTypes().arrangeNullaryFunction());
1753 CGM.getTypes().arrangeNullaryFunction(), ArgList,
1757 return InitFunction;
1765 llvm::GlobalValue *GV) {
1766 std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr =
1767 OMPDeclareTargetDeclAttr::getActiveAttr(FD);
1770 if (!ActiveAttr || !(*ActiveAttr)->getIndirect())
1777 OMPBuilder.OffloadInfoManager.getTargetRegionEntryFnName(Name, EntryInfo);
1783 llvm::GlobalValue *
Addr = GV;
1784 if (
CGM.getLangOpts().OpenMPIsTargetDevice) {
1785 llvm::PointerType *FnPtrTy = llvm::PointerType::get(
1786 CGM.getLLVMContext(),
1787 CGM.getModule().getDataLayout().getProgramAddressSpace());
1788 Addr =
new llvm::GlobalVariable(
1789 CGM.getModule(), FnPtrTy,
1790 true, llvm::GlobalValue::ExternalLinkage, GV, Name,
1791 nullptr, llvm::GlobalValue::NotThreadLocal,
1792 CGM.getModule().getDataLayout().getDefaultGlobalsAddressSpace());
1793 Addr->setVisibility(llvm::GlobalValue::ProtectedVisibility);
1800 OMPBuilder.OffloadInfoManager.registerDeviceGlobalVarEntryInfo(
1801 Name,
Addr,
CGM.GetTargetTypeStoreSize(
CGM.VoidPtrTy).getQuantity(),
1802 llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryIndirect,
1803 llvm::GlobalValue::WeakODRLinkage);
1816 llvm::OpenMPIRBuilder &
OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
1832 llvm::GlobalVariable *
Addr = VTable;
1834 OMPBuilder.OffloadInfoManager.getTargetRegionEntryFnName(AddrName, EntryInfo);
1835 AddrName.append(
"addr");
1837 if (
CGM.getLangOpts().OpenMPIsTargetDevice) {
1838 Addr =
new llvm::GlobalVariable(
1839 CGM.getModule(), VTable->getType(),
1840 true, llvm::GlobalValue::ExternalLinkage, VTable,
1842 nullptr, llvm::GlobalValue::NotThreadLocal,
1843 CGM.getModule().getDataLayout().getDefaultGlobalsAddressSpace());
1844 Addr->setVisibility(llvm::GlobalValue::ProtectedVisibility);
1846 OMPBuilder.OffloadInfoManager.registerDeviceGlobalVarEntryInfo(
1848 CGM.getDataLayout().getTypeAllocSize(VTable->getInitializer()->getType()),
1849 llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryIndirectVTable,
1850 llvm::GlobalValue::WeakODRLinkage);
1859 !
CGM.getOpenMPRuntime().VTableDeclMap.contains(
CXXRecord)) {
1860 auto Res =
CGM.getOpenMPRuntime().VTableDeclMap.try_emplace(
CXXRecord, VD);
1865 assert(VTablesAddr &&
"Expected non-null VTable address");
1867 if (VTablesAddr->hasExternalLinkage())
1868 VTablesAddr->setLinkage(llvm::GlobalValue::WeakODRLinkage);
1869 CGM.getOpenMPRuntime().registerVTableOffloadEntry(VTablesAddr, VD);
1887 auto GetVTableDecl = [](
const Expr *E) {
1898 if (
auto *DRE = dyn_cast<DeclRefExpr>(E)) {
1900 if (
auto *BD = dyn_cast<BindingDecl>(DRE->getDecl()))
1904 }
else if (
auto *MRE = dyn_cast<MemberExpr>(E)) {
1905 if (
auto *BaseDRE = dyn_cast<DeclRefExpr>(MRE->getBase())) {
1906 if (
auto *BaseVD = dyn_cast<VarDecl>(BaseDRE->getDecl()))
1910 return std::pair<CXXRecordDecl *, const VarDecl *>(
CXXRecord, VD);
1914 for (
const auto *E :
C->varlist()) {
1915 auto DeclPair = GetVTableDecl(E);
1917 if (DeclPair.second)
1926 std::string Suffix =
getName({
"artificial",
""});
1928 llvm::GlobalVariable *GAddr =
OMPBuilder.getOrCreateInternalVariable(
1929 VarLVType, Twine(Name).concat(Suffix).str());
1930 if (
CGM.getLangOpts().OpenMP &&
CGM.getLangOpts().OpenMPUseTLS &&
1931 CGM.getTarget().isTLSSupported()) {
1932 GAddr->setThreadLocal(
true);
1933 return Address(GAddr, GAddr->getValueType(),
1934 CGM.getContext().getTypeAlignInChars(VarType));
1936 std::string CacheSuffix =
getName({
"cache",
""});
1937 llvm::Value *Args[] = {
1945 Twine(Name).concat(Suffix).concat(CacheSuffix).str())};
1950 CGM.getModule(), OMPRTL___kmpc_threadprivate_cached),
1953 VarLVType,
CGM.getContext().getTypeAlignInChars(VarType));
2003 auto &M =
CGM.getModule();
2004 auto &&ThenGen = [&M, OutlinedFn, CapturedVars, RTLoc,
2007 llvm::Value *Args[] = {
2009 CGF.
Builder.getInt32(CapturedVars.size()),
2012 RealArgs.append(std::begin(Args), std::end(Args));
2013 RealArgs.append(CapturedVars.begin(), CapturedVars.end());
2015 llvm::FunctionCallee RTLFn =
2016 OMPBuilder.getOrCreateRuntimeFunction(M, OMPRTL___kmpc_fork_call);
2019 auto &&ElseGen = [&M, OutlinedFn, CapturedVars, RTLoc, Loc,
2025 llvm::Value *Args[] = {RTLoc, ThreadID};
2027 M, OMPRTL___kmpc_serialized_parallel),
2034 ".bound.zero.addr");
2039 OutlinedFnArgs.push_back(ZeroAddrBound.
getPointer());
2040 OutlinedFnArgs.append(CapturedVars.begin(), CapturedVars.end());
2048 OutlinedFn->removeFnAttr(llvm::Attribute::AlwaysInline);
2049 OutlinedFn->addFnAttr(llvm::Attribute::NoInline);
2055 M, OMPRTL___kmpc_end_serialized_parallel),
2074 if (
auto *OMPRegionInfo =
2076 if (OMPRegionInfo->getThreadIDVariable())
2077 return OMPRegionInfo->getThreadIDVariableLValue(CGF).getAddress();
2087 return ThreadIDTemp;
2091 std::string Prefix = Twine(
"gomp_critical_user_", CriticalName).str();
2092 std::string Name =
getName({Prefix,
"var"});
2093 llvm::GlobalVariable *GV =
2095 CGM.setDSOLocal(GV);
2102 llvm::FunctionCallee EnterCallee;
2104 llvm::FunctionCallee ExitCallee;
2107 llvm::BasicBlock *ContBlock =
nullptr;
2110 CommonActionTy(llvm::FunctionCallee EnterCallee,
2112 llvm::FunctionCallee ExitCallee,
2114 : EnterCallee(EnterCallee), EnterArgs(EnterArgs), ExitCallee(ExitCallee),
2119 llvm::Value *CallBool = CGF.
Builder.CreateIsNotNull(EnterRes);
2123 CGF.
Builder.CreateCondBr(CallBool, ThenBlock, ContBlock);
2127 void Done(CodeGenFunction &CGF) {
2132 void Exit(CodeGenFunction &CGF)
override {
2139 StringRef CriticalName,
2148 llvm::FunctionCallee RuntimeFcn =
OMPBuilder.getOrCreateRuntimeFunction(
2150 Hint ? OMPRTL___kmpc_critical_with_hint : OMPRTL___kmpc_critical);
2152 unsigned LockVarArgIdx = 2;
2154 RuntimeFcn.getFunctionType()
2155 ->getParamType(LockVarArgIdx)
2156 ->getPointerAddressSpace())
2158 LockVar, RuntimeFcn.getFunctionType()->getParamType(LockVarArgIdx));
2164 EnterArgs.push_back(CGF.
Builder.CreateIntCast(
2167 CommonActionTy Action(RuntimeFcn, EnterArgs,
2169 CGM.getModule(), OMPRTL___kmpc_end_critical),
2186 CommonActionTy Action(
OMPBuilder.getOrCreateRuntimeFunction(
2187 CGM.getModule(), OMPRTL___kmpc_master),
2190 CGM.getModule(), OMPRTL___kmpc_end_master),
2208 llvm::Value *FilterVal = Filter
2210 : llvm::ConstantInt::get(
CGM.Int32Ty, 0);
2215 CommonActionTy Action(
OMPBuilder.getOrCreateRuntimeFunction(
2216 CGM.getModule(), OMPRTL___kmpc_masked),
2219 CGM.getModule(), OMPRTL___kmpc_end_masked),
2235 llvm::Value *Args[] = {
2237 llvm::ConstantInt::get(
CGM.IntTy, 0,
true)};
2239 CGM.getModule(), OMPRTL___kmpc_omp_taskyield),
2243 if (
auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.
CapturedStmtInfo))
2244 Region->emitUntiedSwitch(CGF);
2257 CommonActionTy Action(
OMPBuilder.getOrCreateRuntimeFunction(
2258 CGM.getModule(), OMPRTL___kmpc_taskgroup),
2261 CGM.getModule(), OMPRTL___kmpc_end_taskgroup),
2270 unsigned Index,
const VarDecl *Var) {
2299 llvm::GlobalValue::InternalLinkage, Name,
2303 Fn->addFnAttr(
"sample-profile-suffix-elision-policy",
"selected");
2304 Fn->setDoesNotRecurse();
2321 for (
unsigned I = 0, E = AssignmentOps.size(); I < E; ++I) {
2322 const auto *DestVar =
2326 const auto *SrcVar =
2332 CGF.
EmitOMPCopy(
Type, DestAddr, SrcAddr, DestVar, SrcVar, AssignmentOps[I]);
2347 assert(CopyprivateVars.size() == SrcExprs.size() &&
2348 CopyprivateVars.size() == DstExprs.size() &&
2349 CopyprivateVars.size() == AssignmentOps.size());
2361 if (!CopyprivateVars.empty()) {
2364 C.getIntTypeForBitwidth(32, 1);
2370 CommonActionTy Action(
OMPBuilder.getOrCreateRuntimeFunction(
2371 CGM.getModule(), OMPRTL___kmpc_single),
2374 CGM.getModule(), OMPRTL___kmpc_end_single),
2387 llvm::APInt ArraySize(32, CopyprivateVars.size());
2388 QualType CopyprivateArrayTy =
C.getConstantArrayType(
2393 CopyprivateArrayTy,
".omp.copyprivate.cpr_list");
2394 for (
unsigned I = 0, E = CopyprivateVars.size(); I < E; ++I) {
2406 SrcExprs, DstExprs, AssignmentOps, Loc);
2407 llvm::Value *BufSize = CGF.
getTypeSize(CopyprivateArrayTy);
2411 llvm::Value *Args[] = {
2415 CL.emitRawPointer(CGF),
2420 CGM.getModule(), OMPRTL___kmpc_copyprivate),
2436 CommonActionTy Action(
OMPBuilder.getOrCreateRuntimeFunction(
2437 CGM.getModule(), OMPRTL___kmpc_ordered),
2440 CGM.getModule(), OMPRTL___kmpc_end_ordered),
2451 if (Kind == OMPD_for)
2452 Flags = OMP_IDENT_BARRIER_IMPL_FOR;
2453 else if (Kind == OMPD_sections)
2454 Flags = OMP_IDENT_BARRIER_IMPL_SECTIONS;
2455 else if (Kind == OMPD_single)
2456 Flags = OMP_IDENT_BARRIER_IMPL_SINGLE;
2457 else if (Kind == OMPD_barrier)
2458 Flags = OMP_IDENT_BARRIER_EXPL;
2460 Flags = OMP_IDENT_BARRIER_IMPL;
2470 S.getClausesOfKind<OMPOrderedClause>(),
2471 [](
const OMPOrderedClause *
C) { return C->getNumForLoops(); })) {
2472 ScheduleKind = OMPC_SCHEDULE_static;
2474 llvm::APInt ChunkSize(32, 1);
2484 bool ForceSimpleCall) {
2486 auto *OMPRegionInfo =
2489 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
2492 CGF.
Builder.restoreIP(AfterIP);
2505 if (OMPRegionInfo) {
2506 if (!ForceSimpleCall && OMPRegionInfo->hasCancel()) {
2509 OMPRTL___kmpc_cancel_barrier),
2518 CGF.
Builder.CreateCondBr(
Cmp, ExitBB, ContBB);
2530 CGM.getModule(), OMPRTL___kmpc_barrier),
2535 Expr *ME,
bool IsFatal) {
2537 : llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
2540 llvm::Value *Args[] = {
2542 llvm::ConstantInt::get(
CGM.Int32Ty, IsFatal ? 2 : 1),
2543 CGF.
Builder.CreatePointerCast(MVL,
CGM.Int8PtrTy)};
2545 CGM.getModule(), OMPRTL___kmpc_error),
2551 bool Chunked,
bool Ordered) {
2552 switch (ScheduleKind) {
2553 case OMPC_SCHEDULE_static:
2554 return Chunked ? (Ordered ? OMP_ord_static_chunked : OMP_sch_static_chunked)
2555 : (Ordered ? OMP_ord_static : OMP_sch_static);
2556 case OMPC_SCHEDULE_dynamic:
2557 return Ordered ? OMP_ord_dynamic_chunked : OMP_sch_dynamic_chunked;
2558 case OMPC_SCHEDULE_guided:
2559 return Ordered ? OMP_ord_guided_chunked : OMP_sch_guided_chunked;
2560 case OMPC_SCHEDULE_runtime:
2561 return Ordered ? OMP_ord_runtime : OMP_sch_runtime;
2562 case OMPC_SCHEDULE_auto:
2563 return Ordered ? OMP_ord_auto : OMP_sch_auto;
2565 assert(!Chunked &&
"chunk was specified but schedule kind not known");
2566 return Ordered ? OMP_ord_static : OMP_sch_static;
2568 llvm_unreachable(
"Unexpected runtime schedule");
2572static OpenMPSchedType
2575 return Chunked ? OMP_dist_sch_static_chunked : OMP_dist_sch_static;
2579 bool Chunked)
const {
2580 OpenMPSchedType Schedule =
2582 return Schedule == OMP_sch_static;
2588 return Schedule == OMP_dist_sch_static;
2592 bool Chunked)
const {
2593 OpenMPSchedType Schedule =
2595 return Schedule == OMP_sch_static_chunked;
2601 return Schedule == OMP_dist_sch_static_chunked;
2605 OpenMPSchedType Schedule =
2607 assert(Schedule != OMP_sch_static_chunked &&
"cannot be chunked here");
2608 return Schedule != OMP_sch_static;
2616 case OMPC_SCHEDULE_MODIFIER_monotonic:
2617 Modifier = OMP_sch_modifier_monotonic;
2619 case OMPC_SCHEDULE_MODIFIER_nonmonotonic:
2620 Modifier = OMP_sch_modifier_nonmonotonic;
2622 case OMPC_SCHEDULE_MODIFIER_simd:
2623 if (Schedule == OMP_sch_static_chunked)
2624 Schedule = OMP_sch_static_balanced_chunked;
2631 case OMPC_SCHEDULE_MODIFIER_monotonic:
2632 Modifier = OMP_sch_modifier_monotonic;
2634 case OMPC_SCHEDULE_MODIFIER_nonmonotonic:
2635 Modifier = OMP_sch_modifier_nonmonotonic;
2637 case OMPC_SCHEDULE_MODIFIER_simd:
2638 if (Schedule == OMP_sch_static_chunked)
2639 Schedule = OMP_sch_static_balanced_chunked;
2651 if (CGM.
getLangOpts().OpenMP >= 50 && Modifier == 0) {
2652 if (!(Schedule == OMP_sch_static_chunked || Schedule == OMP_sch_static ||
2653 Schedule == OMP_sch_static_balanced_chunked ||
2654 Schedule == OMP_ord_static_chunked || Schedule == OMP_ord_static ||
2655 Schedule == OMP_dist_sch_static_chunked ||
2656 Schedule == OMP_dist_sch_static ||
2657 Schedule == OMP_dist_sch_static_chunked_sch_static_chunkone))
2658 Modifier = OMP_sch_modifier_nonmonotonic;
2660 return Schedule | Modifier;
2670 ScheduleKind.
Schedule, DispatchValues.
Chunk !=
nullptr, Ordered);
2672 (Schedule != OMP_sch_static && Schedule != OMP_sch_static_chunked &&
2673 Schedule != OMP_ord_static && Schedule != OMP_ord_static_chunked &&
2674 Schedule != OMP_sch_static_balanced_chunked));
2681 llvm::Value *Chunk = DispatchValues.
Chunk ? DispatchValues.
Chunk
2682 : CGF.
Builder.getIntN(IVSize, 1);
2683 llvm::Value *Args[] = {
2687 CGM, Schedule, ScheduleKind.
M1, ScheduleKind.
M2)),
2690 CGF.
Builder.getIntN(IVSize, 1),
2707 CodeGenFunction &CGF, llvm::Value *UpdateLocation, llvm::Value *ThreadId,
2708 llvm::FunctionCallee ForStaticInitFunction, OpenMPSchedType Schedule,
2715 assert(Schedule == OMP_sch_static || Schedule == OMP_sch_static_chunked ||
2716 Schedule == OMP_sch_static_balanced_chunked ||
2717 Schedule == OMP_ord_static || Schedule == OMP_ord_static_chunked ||
2718 Schedule == OMP_dist_sch_static ||
2719 Schedule == OMP_dist_sch_static_chunked ||
2720 Schedule == OMP_dist_sch_static_chunked_sch_static_chunkone);
2727 llvm::Value *Chunk = Values.
Chunk;
2728 if (Chunk ==
nullptr) {
2729 assert((Schedule == OMP_sch_static || Schedule == OMP_ord_static ||
2730 Schedule == OMP_dist_sch_static) &&
2731 "expected static non-chunked schedule");
2735 assert((Schedule == OMP_sch_static_chunked ||
2736 Schedule == OMP_sch_static_balanced_chunked ||
2737 Schedule == OMP_ord_static_chunked ||
2738 Schedule == OMP_dist_sch_static_chunked ||
2739 Schedule == OMP_dist_sch_static_chunked_sch_static_chunkone) &&
2740 "expected static chunked schedule");
2742 llvm::Value *Args[] = {
2762 OpenMPSchedType ScheduleNum =
2764 ? OMP_dist_sch_static_chunked_sch_static_chunkone
2768 "Expected loop-based or sections-based directive.");
2771 ? OMP_IDENT_WORK_LOOP
2772 : OMP_IDENT_WORK_SECTIONS);
2774 llvm::FunctionCallee StaticInitFunction =
2779 ScheduleNum, ScheduleKind.
M1, ScheduleKind.
M2, Values);
2786 OpenMPSchedType ScheduleNum =
2788 llvm::Value *UpdatedLocation =
2791 llvm::FunctionCallee StaticInitFunction;
2792 bool isGPUDistribute =
2793 CGM.getLangOpts().OpenMPIsTargetDevice &&
CGM.getTriple().isGPU();
2794 StaticInitFunction =
OMPBuilder.createForStaticInitFunction(
2805 assert((DKind == OMPD_distribute || DKind == OMPD_for ||
2806 DKind == OMPD_sections) &&
2807 "Expected distribute, for, or sections directive kind");
2811 llvm::Value *Args[] = {
2814 (DKind == OMPD_target_teams_loop)
2815 ? OMP_IDENT_WORK_DISTRIBUTE
2817 ? OMP_IDENT_WORK_LOOP
2818 : OMP_IDENT_WORK_SECTIONS),
2822 CGM.getLangOpts().OpenMPIsTargetDevice &&
CGM.getTriple().isGPU())
2825 CGM.getModule(), OMPRTL___kmpc_distribute_static_fini),
2829 CGM.getModule(), OMPRTL___kmpc_for_static_fini),
2854 llvm::Value *Args[] = {
2862 OMPBuilder.createDispatchNextFunction(IVSize, IVSigned), Args);
2869 const Expr *Message,
2872 return llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
2881 return llvm::ConstantInt::get(
CGM.Int32Ty,
2882 Severity == OMPC_SEVERITY_warning ? 1 : 2);
2898 RuntimeFunction FnID = OMPRTL___kmpc_push_num_threads;
2899 if (Modifier == OMPC_NUMTHREADS_strict) {
2900 FnID = OMPRTL___kmpc_push_num_threads_strict;
2905 OMPBuilder.getOrCreateRuntimeFunction(
CGM.getModule(), FnID), Args);
2909 ProcBindKind ProcBind,
2913 assert(ProcBind != OMP_PROC_BIND_unknown &&
"Unsupported proc_bind value.");
2915 llvm::Value *Args[] = {
2917 llvm::ConstantInt::get(
CGM.IntTy,
unsigned(ProcBind),
true)};
2919 CGM.getModule(), OMPRTL___kmpc_push_proc_bind),
2932 CGM.getModule(), OMPRTL___kmpc_flush),
2939enum KmpTaskTFields {
2966 if (
CGM.getLangOpts().OpenMPSimd ||
OMPBuilder.OffloadInfoManager.empty())
2969 llvm::OpenMPIRBuilder::EmitMetadataErrorReportFunctionTy &&ErrorReportFn =
2970 [
this](llvm::OpenMPIRBuilder::EmitMetadataErrorKind Kind,
2971 const llvm::TargetRegionEntryInfo &EntryInfo) ->
void {
2973 if (Kind != llvm::OpenMPIRBuilder::EMIT_MD_GLOBAL_VAR_LINK_ERROR) {
2974 for (
auto I =
CGM.getContext().getSourceManager().fileinfo_begin(),
2975 E =
CGM.getContext().getSourceManager().fileinfo_end();
2977 if (I->getFirst().getUniqueID().getDevice() == EntryInfo.DeviceID &&
2978 I->getFirst().getUniqueID().getFile() == EntryInfo.FileID) {
2979 Loc =
CGM.getContext().getSourceManager().translateFileLineCol(
2980 I->getFirst(), EntryInfo.Line, 1);
2986 case llvm::OpenMPIRBuilder::EMIT_MD_TARGET_REGION_ERROR: {
2987 CGM.getDiags().Report(Loc,
2988 diag::err_target_region_offloading_entry_incorrect)
2989 << EntryInfo.ParentName;
2991 case llvm::OpenMPIRBuilder::EMIT_MD_DECLARE_TARGET_ERROR: {
2992 CGM.getDiags().Report(
2993 Loc, diag::err_target_var_offloading_entry_incorrect_with_parent)
2994 << EntryInfo.ParentName;
2996 case llvm::OpenMPIRBuilder::EMIT_MD_GLOBAL_VAR_LINK_ERROR: {
2997 CGM.getDiags().Report(diag::err_target_var_offloading_entry_incorrect);
2999 case llvm::OpenMPIRBuilder::EMIT_MD_GLOBAL_VAR_INDIRECT_ERROR: {
3000 unsigned DiagID =
CGM.getDiags().getCustomDiagID(
3002 "target variable is incorrect: the "
3003 "address is invalid.");
3004 CGM.getDiags().Report(DiagID);
3009 OMPBuilder.createOffloadEntriesAndInfoMetadata(ErrorReportFn);
3016 QualType KmpRoutineEntryTyArgs[] = {KmpInt32Ty,
C.VoidPtrTy};
3019 C.getFunctionType(KmpInt32Ty, KmpRoutineEntryTyArgs, EPI));
3025struct PrivateHelpersTy {
3026 PrivateHelpersTy(
const Expr *OriginalRef,
const VarDecl *Original,
3028 : OriginalRef(OriginalRef), Original(Original), PrivateCopy(PrivateCopy),
3029 PrivateElemInit(PrivateElemInit) {}
3030 PrivateHelpersTy(
const VarDecl *Original) : Original(Original) {}
3031 const Expr *OriginalRef =
nullptr;
3032 const VarDecl *Original =
nullptr;
3033 const VarDecl *PrivateCopy =
nullptr;
3034 const VarDecl *PrivateElemInit =
nullptr;
3035 bool isLocalPrivate()
const {
3036 return !OriginalRef && !PrivateCopy && !PrivateElemInit;
3039typedef std::pair<CharUnits , PrivateHelpersTy> PrivateDataTy;
3045 if (
const auto *BD = dyn_cast<BindingDecl>(
Decl))
3052 if (!CVD->
hasAttr<OMPAllocateDeclAttr>())
3054 const auto *AA = CVD->
getAttr<OMPAllocateDeclAttr>();
3056 return !(AA->getAllocatorType() == OMPAllocateDeclAttr::OMPDefaultMemAlloc &&
3057 !AA->getAllocator());
3067 RecordDecl *RD =
C.buildImplicitRecord(
".kmp_privates.t");
3069 for (
const auto &Pair :
Privates) {
3070 const VarDecl *VD = Pair.second.Original;
3071 const VarDecl *PrivateCopy = Pair.second.PrivateCopy;
3077 Pair.second.OriginalRef &&
3085 if (Pair.second.isLocalPrivate()) {
3108 QualType KmpRoutineEntryPointerQTy) {
3128 CanQualType KmpCmplrdataTy =
C.getCanonicalTagType(UD);
3129 RecordDecl *RD =
C.buildImplicitRecord(
"kmp_task_t");
3159 RecordDecl *RD =
C.buildImplicitRecord(
"kmp_task_t_with_privates");
3179static llvm::Function *
3182 QualType KmpTaskTWithPrivatesPtrQTy,
3184 QualType SharedsPtrTy, llvm::Function *TaskFunction,
3185 llvm::Value *TaskPrivatesMap) {
3191 C,
nullptr, Loc,
nullptr,
3194 const auto &TaskEntryFnInfo =
3196 llvm::FunctionType *TaskEntryTy =
3199 auto *TaskEntry = llvm::Function::Create(
3200 TaskEntryTy, llvm::GlobalValue::InternalLinkage, Name, &CGM.
getModule());
3203 TaskEntry->addFnAttr(
"sample-profile-suffix-elision-policy",
"selected");
3204 TaskEntry->setDoesNotRecurse();
3219 const auto *KmpTaskTWithPrivatesQTyRD =
3224 auto PartIdFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTPartId);
3226 llvm::Value *PartidParam = PartIdLVal.getPointer(CGF);
3228 auto SharedsFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTShareds);
3234 auto PrivatesFI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin(), 1);
3235 llvm::Value *PrivatesParam;
3236 if (PrivatesFI != KmpTaskTWithPrivatesQTyRD->field_end()) {
3239 PrivatesLVal.getPointer(CGF), CGF.
VoidPtrTy);
3241 PrivatesParam = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
3244 llvm::Value *CommonArgs[] = {
3245 GtidParam, PartidParam, PrivatesParam, TaskPrivatesMap,
3251 std::end(CommonArgs));
3253 auto LBFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound);
3256 auto UBFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound);
3259 auto StFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTStride);
3262 auto LIFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLastIter);
3265 auto RFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTReductions);
3268 CallArgs.push_back(LBParam);
3269 CallArgs.push_back(UBParam);
3270 CallArgs.push_back(StParam);
3271 CallArgs.push_back(LIParam);
3272 CallArgs.push_back(RParam);
3274 CallArgs.push_back(SharedsParam);
3287 QualType KmpTaskTWithPrivatesPtrQTy,
3288 QualType KmpTaskTWithPrivatesQTy) {
3294 C,
nullptr, Loc,
nullptr,
3297 const auto &DestructorFnInfo =
3299 llvm::FunctionType *DestructorFnTy =
3303 auto *DestructorFn =
3304 llvm::Function::Create(DestructorFnTy, llvm::GlobalValue::InternalLinkage,
3309 DestructorFn->addFnAttr(
"sample-profile-suffix-elision-policy",
"selected");
3310 DestructorFn->setDoesNotRecurse();
3318 const auto *KmpTaskTWithPrivatesQTyRD =
3320 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin());
3322 for (
const auto *Field : FI->getType()->castAsRecordDecl()->fields()) {
3324 Field->getType().isDestructedType()) {
3326 CGF.
pushDestroy(DtorKind, FieldLValue.getAddress(), Field->getType());
3330 return DestructorFn;
3350 C,
nullptr, Loc,
nullptr,
3351 C.getPointerType(PrivatesQTy).withConst().withRestrict(),
3353 Args.push_back(TaskPrivatesArg);
3354 llvm::SmallDenseMap<CanonicalDeclPtr<const VarDecl>,
unsigned> PrivateVarsPos;
3356 llvm::SmallDenseMap<const BindingDecl *, unsigned> BindingDeclPos;
3357 unsigned Counter = 1;
3358 for (
const Expr *E :
Data.PrivateVars) {
3360 C,
nullptr, Loc,
nullptr,
3361 C.getPointerType(
C.getPointerType(E->
getType()))
3366 if (
const auto *BD = dyn_cast<BindingDecl>(VD))
3372 for (
const Expr *E :
Data.FirstprivateVars) {
3374 C,
nullptr, Loc,
nullptr,
3375 C.getPointerType(
C.getPointerType(E->
getType()))
3380 if (
const auto *BD = dyn_cast<BindingDecl>(VD))
3386 for (
const Expr *E :
Data.LastprivateVars) {
3388 C,
nullptr, Loc,
nullptr,
3389 C.getPointerType(
C.getPointerType(E->
getType()))
3394 if (
const auto *BD = dyn_cast<BindingDecl>(VD))
3403 Ty =
C.getPointerType(Ty);
3405 Ty =
C.getPointerType(Ty);
3407 C,
nullptr, Loc,
nullptr,
3408 C.getPointerType(
C.getPointerType(Ty)).withConst().withRestrict(),
3410 PrivateVarsPos[VD] = Counter;
3413 const auto &TaskPrivatesMapFnInfo =
3415 llvm::FunctionType *TaskPrivatesMapTy =
3419 auto *TaskPrivatesMap = llvm::Function::Create(
3420 TaskPrivatesMapTy, llvm::GlobalValue::InternalLinkage, Name,
3423 TaskPrivatesMapFnInfo);
3425 TaskPrivatesMap->addFnAttr(
"sample-profile-suffix-elision-policy",
3428 TaskPrivatesMap->removeFnAttr(llvm::Attribute::NoInline);
3429 TaskPrivatesMap->removeFnAttr(llvm::Attribute::OptimizeNone);
3430 TaskPrivatesMap->addFnAttr(llvm::Attribute::AlwaysInline);
3434 TaskPrivatesMapFnInfo, Args, Loc, Loc);
3442 for (
const FieldDecl *Field : PrivatesQTyRD->fields()) {
3446 if (
Privates[Counter].second.OriginalRef) {
3450 LookupVD =
Privates[Counter].second.Original;
3458 if (
const auto *BD = dyn_cast<BindingDecl>(LookupVD)) {
3461 assert(Position &&
"binding not in privates mapping");
3465 const VarDecl *VD = Args[Position];
3469 RefLVal.getAddress(), RefLVal.getType()->castAs<
PointerType>());
3474 return TaskPrivatesMap;
3480 Address KmpTaskSharedsPtr, LValue TDBase,
3486 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->
field_begin());
3500 if ((!IsTargetTask && !
Data.FirstprivateVars.empty() && ForDup) ||
3501 (IsTargetTask && KmpTaskSharedsPtr.
isValid())) {
3508 FI = FI->getType()->castAsRecordDecl()->field_begin();
3509 for (
const PrivateDataTy &Pair :
Privates) {
3511 if (Pair.second.isLocalPrivate()) {
3515 const VarDecl *VD = Pair.second.PrivateCopy;
3520 if (
const VarDecl *Elem = Pair.second.PrivateElemInit) {
3521 const VarDecl *OriginalVD = Pair.second.Original;
3524 LValue SharedRefLValue;
3527 if (IsTargetTask && !SharedField) {
3531 ->getNumParams() == 0 &&
3534 ->getDeclContext()) &&
3535 "Expected artificial target data variable.");
3538 }
else if (ForDup) {
3542 if (Pair.second.OriginalRef) {
3543 if (
const auto *DRE =
3544 dyn_cast<DeclRefExpr>(Pair.second.OriginalRef)) {
3545 if (
const auto *BD = dyn_cast<BindingDecl>(DRE->getDecl())) {
3553 It->second = SharedRefLValue.getAddress();
3556 SharedRefLValue = CGF.
EmitLValue(BD->getBinding());
3559 RestoreIt->second = Saved;
3567 Pair.second.OriginalRef &&
3571 SharedRefLValue.getAddress().withAlignment(
3572 IsBinding ?
C.toCharUnitsFromBits(
3573 C.getTypeAlign(SharedRefLValue.getType()))
3574 :
C.getDeclAlign(OriginalVD)),
3576 SharedRefLValue.getTBAAInfo());
3578 Pair.second.Original->getCanonicalDecl()) > 0 ||
3580 SharedRefLValue = CGF.
EmitLValue(Pair.second.OriginalRef);
3583 InlinedOpenMPRegionRAII Region(
3586 SharedRefLValue = CGF.
EmitLValue(Pair.second.OriginalRef);
3597 PrivateLValue.getAddress(), SharedRefLValue.getAddress(),
Type,
3598 [&CGF, Elem,
Init, &CapturesInfo](
Address DestElement,
3601 CodeGenFunction::OMPPrivateScope InitScope(CGF);
3602 InitScope.addPrivate(Elem, SrcElement);
3603 (void)InitScope.Privatize();
3605 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(
3606 CGF, &CapturesInfo);
3607 CGF.EmitAnyExprToMem(Init, DestElement,
3608 Init->getType().getQualifiers(),
3614 InitScope.addPrivate(Elem, SharedRefLValue.getAddress());
3615 (void)InitScope.Privatize();
3623 }
else if (
const VarDecl *OriginalVD = Pair.second.Original) {
3628 if (Pair.second.OriginalRef) {
3629 if (
const auto *DRE = dyn_cast<DeclRefExpr>(Pair.second.OriginalRef)) {
3630 BD = dyn_cast<BindingDecl>(DRE->getDecl());
3640 auto EmitBindingWithTempMap = [&CGF](
const BindingDecl *BD,
3647 It->second = DDAddr;
3656 RestoreIt->second = Saved;
3664 LValue SharedRefLValue;
3668 EmitBindingWithTempMap(BD, SharedRefLValue.getAddress());
3670 SharedRefLValue.getAddress().withAlignment(
3671 C.getDeclAlign(OriginalVD)),
3673 SharedRefLValue.getTBAAInfo());
3677 InlinedOpenMPRegionRAII Region(
3684 SharedRefLValue = EmitBindingWithTempMap(BD, DDAddr);
3697 bool InitRequired =
false;
3698 for (
const PrivateDataTy &Pair :
Privates) {
3699 if (Pair.second.isLocalPrivate())
3701 const VarDecl *VD = Pair.second.PrivateCopy;
3703 InitRequired = InitRequired || (isa_and_nonnull<CXXConstructExpr>(
Init) &&
3708 return InitRequired;
3725 QualType KmpTaskTWithPrivatesPtrQTy,
3732 C,
nullptr, Loc,
nullptr, KmpTaskTWithPrivatesPtrQTy,
3735 C,
nullptr, Loc,
nullptr, KmpTaskTWithPrivatesPtrQTy,
3741 const auto &TaskDupFnInfo =
3745 auto *TaskDup = llvm::Function::Create(
3746 TaskDupTy, llvm::GlobalValue::InternalLinkage, Name, &CGM.
getModule());
3749 TaskDup->addFnAttr(
"sample-profile-suffix-elision-policy",
"selected");
3750 TaskDup->setDoesNotRecurse();
3760 auto LIFI = std::next(KmpTaskTQTyRD->
field_begin(), KmpTaskTLastIter);
3762 TDBase, *KmpTaskTWithPrivatesQTyRD->
field_begin());
3772 if (!
Data.FirstprivateVars.empty()) {
3777 TDBase, *KmpTaskTWithPrivatesQTyRD->
field_begin());
3785 emitPrivatesInit(CGF, D, KmpTaskSharedsPtr, TDBase, KmpTaskTWithPrivatesQTyRD,
3796 for (
const PrivateDataTy &P :
Privates) {
3797 if (P.second.isLocalPrivate())
3799 QualType Ty = P.second.Original->getType().getNonReferenceType();
3808class OMPIteratorGeneratorScope final
3810 CodeGenFunction &CGF;
3811 const OMPIteratorExpr *E =
nullptr;
3812 SmallVector<CodeGenFunction::JumpDest, 4> ContDests;
3813 SmallVector<CodeGenFunction::JumpDest, 4> ExitDests;
3814 OMPIteratorGeneratorScope() =
delete;
3815 OMPIteratorGeneratorScope(OMPIteratorGeneratorScope &) =
delete;
3818 OMPIteratorGeneratorScope(CodeGenFunction &CGF,
const OMPIteratorExpr *E)
3819 : CodeGenFunction::OMPPrivateScope(CGF), CGF(CGF), E(E) {
3822 SmallVector<llvm::Value *, 4> Uppers;
3824 Uppers.push_back(CGF.EmitScalarExpr(E->getHelper(I).Upper));
3825 const auto *VD = cast<VarDecl>(E->getIteratorDecl(I));
3826 addPrivate(VD, CGF.CreateMemTemp(VD->getType(), VD->getName()));
3827 const OMPIteratorHelperData &HelperData = E->getHelper(I);
3829 HelperData.CounterVD,
3830 CGF.CreateMemTemp(HelperData.CounterVD->getType(),
"counter.addr"));
3835 const OMPIteratorHelperData &HelperData = E->getHelper(I);
3837 CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(HelperData.CounterVD),
3838 HelperData.CounterVD->getType());
3840 CGF.EmitStoreOfScalar(
3841 llvm::ConstantInt::get(CLVal.getAddress().getElementType(), 0),
3843 CodeGenFunction::JumpDest &ContDest =
3844 ContDests.emplace_back(CGF.getJumpDestInCurrentScope(
"iter.cont"));
3845 CodeGenFunction::JumpDest &ExitDest =
3846 ExitDests.emplace_back(CGF.getJumpDestInCurrentScope(
"iter.exit"));
3848 llvm::Value *N = Uppers[I];
3851 CGF.EmitBlock(ContDest.getBlock());
3853 CGF.EmitLoadOfScalar(CLVal, HelperData.CounterVD->getLocation());
3855 HelperData.CounterVD->getType()->isSignedIntegerOrEnumerationType()
3856 ? CGF.Builder.CreateICmpSLT(CVal, N)
3857 : CGF.Builder.CreateICmpULT(CVal, N);
3858 llvm::BasicBlock *BodyBB = CGF.createBasicBlock(
"iter.body");
3859 CGF.Builder.CreateCondBr(Cmp, BodyBB, ExitDest.getBlock());
3861 CGF.EmitBlock(BodyBB);
3863 CGF.EmitIgnoredExpr(HelperData.Update);
3866 ~OMPIteratorGeneratorScope() {
3871 const OMPIteratorHelperData &HelperData = E->
getHelper(I - 1);
3876 CGF.
EmitBlock(ExitDests[I - 1].getBlock(), I == 1);
3882static std::pair<llvm::Value *, llvm::Value *>
3884 const auto *OASE = dyn_cast<OMPArrayShapingExpr>(E);
3887 const Expr *
Base = OASE->getBase();
3892 llvm::Value *SizeVal;
3895 SizeVal = CGF.
getTypeSize(OASE->getBase()->getType()->getPointeeType());
3896 for (
const Expr *SE : OASE->getDimensions()) {
3900 SizeVal = CGF.
Builder.CreateNUWMul(SizeVal, Sz);
3902 }
else if (
const auto *ASE =
3905 Address UpAddrAddress = UpAddrLVal.getAddress();
3906 llvm::Value *UpAddr = CGF.
Builder.CreateConstGEP1_32(
3909 SizeVal = CGF.
Builder.CreatePtrDiff(UpAddr,
Addr,
"",
true);
3913 return std::make_pair(
Addr, SizeVal);
3918 QualType FlagsTy =
C.getIntTypeForBitwidth(32,
false);
3919 if (KmpTaskAffinityInfoTy.
isNull()) {
3921 C.buildImplicitRecord(
"kmp_task_affinity_info_t");
3927 KmpTaskAffinityInfoTy =
C.getCanonicalTagType(KmpAffinityInfoRD);
3934 llvm::Function *TaskFunction,
QualType SharedsTy,
3939 const auto *I =
Data.PrivateCopies.begin();
3940 for (
const Expr *E :
Data.PrivateVars) {
3944 Privates.emplace_back(
C.getDeclAlign(VD),
3945 PrivateHelpersTy(E, VD, CopyVD,
3949 I =
Data.FirstprivateCopies.begin();
3950 const auto *IElemInitRef =
Data.FirstprivateInits.begin();
3951 for (
const Expr *E :
Data.FirstprivateVars) {
3955 const auto *InitVD =
3957 Privates.emplace_back(
C.getDeclAlign(VD),
3958 PrivateHelpersTy(E, VD, CopyVD, InitVD));
3962 I =
Data.LastprivateCopies.begin();
3963 for (
const Expr *E :
Data.LastprivateVars) {
3967 Privates.emplace_back(
C.getDeclAlign(VD),
3968 PrivateHelpersTy(E, VD, CopyVD,
3974 Privates.emplace_back(
CGM.getPointerAlign(), PrivateHelpersTy(VD));
3976 Privates.emplace_back(
C.getDeclAlign(VD), PrivateHelpersTy(VD));
3979 [](
const PrivateDataTy &L,
const PrivateDataTy &R) {
3980 return L.first > R.first;
3982 QualType KmpInt32Ty =
C.getIntTypeForBitwidth(32, 1);
3993 assert((D.getDirectiveKind() == OMPD_task ||
3996 "Expected taskloop, task or target directive");
4003 const auto *KmpTaskTQTyRD =
KmpTaskTQTy->castAsRecordDecl();
4005 const RecordDecl *KmpTaskTWithPrivatesQTyRD =
4008 C.getCanonicalTagType(KmpTaskTWithPrivatesQTyRD);
4009 QualType KmpTaskTWithPrivatesPtrQTy =
4010 C.getPointerType(KmpTaskTWithPrivatesQTy);
4011 llvm::Type *KmpTaskTWithPrivatesPtrTy = CGF.
Builder.getPtrTy(0);
4012 llvm::Value *KmpTaskTWithPrivatesTySize =
4014 QualType SharedsPtrTy =
C.getPointerType(SharedsTy);
4017 llvm::Value *TaskPrivatesMap =
nullptr;
4018 llvm::Type *TaskPrivatesMapTy =
4019 std::next(TaskFunction->arg_begin(), 3)->getType();
4021 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->
field_begin());
4025 TaskPrivatesMap, TaskPrivatesMapTy);
4027 TaskPrivatesMap = llvm::ConstantPointerNull::get(
4033 CGM, Loc, D.getDirectiveKind(), KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy,
4034 KmpTaskTWithPrivatesQTy,
KmpTaskTQTy, SharedsPtrTy, TaskFunction,
4046 DestructorsFlag = 0x8,
4047 PriorityFlag = 0x20,
4048 DetachableFlag = 0x40,
4049 FreeAgentFlag = 0x80,
4050 TransparentFlag = 0x100,
4052 unsigned Flags =
Data.Tied ? TiedFlag : 0;
4053 bool NeedsCleanup =
false;
4058 Flags = Flags | DestructorsFlag;
4062 if (Kind == OMPC_THREADSET_omp_pool)
4063 Flags = Flags | FreeAgentFlag;
4065 if (D.getSingleClause<OMPTransparentClause>())
4066 Flags |= TransparentFlag;
4068 if (
Data.Priority.getInt())
4069 Flags = Flags | PriorityFlag;
4071 Flags = Flags | DetachableFlag;
4072 llvm::Value *TaskFlags =
4073 Data.Final.getPointer()
4074 ? CGF.
Builder.CreateSelect(
Data.Final.getPointer(),
4075 CGF.
Builder.getInt32(FinalFlag),
4077 : CGF.
Builder.getInt32(
Data.Final.getInt() ? FinalFlag : 0);
4078 TaskFlags = CGF.
Builder.CreateOr(TaskFlags, CGF.
Builder.getInt32(Flags));
4079 llvm::Value *SharedsSize =
CGM.getSize(
C.getTypeSizeInChars(SharedsTy));
4081 getThreadID(CGF, Loc), TaskFlags, KmpTaskTWithPrivatesTySize,
4084 llvm::Value *NewTask;
4085 if (D.hasClausesOfKind<OMPNowaitClause>()) {
4091 llvm::Value *DeviceID;
4096 DeviceID = CGF.
Builder.getInt64(OMP_DEVICEID_UNDEF);
4097 AllocArgs.push_back(DeviceID);
4100 CGM.getModule(), OMPRTL___kmpc_omp_target_task_alloc),
4105 CGM.getModule(), OMPRTL___kmpc_omp_task_alloc),
4118 llvm::Value *Tid =
getThreadID(CGF, DC->getBeginLoc());
4119 Tid = CGF.
Builder.CreateIntCast(Tid, CGF.
IntTy,
false);
4122 CGM.getModule(), OMPRTL___kmpc_task_allow_completion_event),
4123 {Loc, Tid, NewTask});
4134 llvm::Value *NumOfElements =
nullptr;
4135 unsigned NumAffinities = 0;
4137 if (
const Expr *Modifier =
C->getModifier()) {
4139 for (
unsigned I = 0, E = IE->numOfIterators(); I < E; ++I) {
4143 NumOfElements ? CGF.
Builder.CreateNUWMul(NumOfElements, Sz) : Sz;
4146 NumAffinities +=
C->varlist_size();
4151 enum RTLAffinityInfoFieldsTy { BaseAddr, Len, Flags };
4153 QualType KmpTaskAffinityInfoArrayTy;
4154 if (NumOfElements) {
4155 NumOfElements = CGF.
Builder.CreateNUWAdd(
4156 llvm::ConstantInt::get(CGF.
SizeTy, NumAffinities), NumOfElements);
4159 C.getIntTypeForBitwidth(
C.getTypeSize(
C.getSizeType()), 0),
4163 KmpTaskAffinityInfoArrayTy =
C.getVariableArrayType(
4171 NumOfElements = CGF.
Builder.CreateIntCast(NumOfElements, CGF.
Int32Ty,
4174 KmpTaskAffinityInfoArrayTy =
C.getConstantArrayType(
4176 llvm::APInt(
C.getTypeSize(
C.getSizeType()), NumAffinities),
nullptr,
4181 NumOfElements = llvm::ConstantInt::get(
CGM.Int32Ty, NumAffinities,
4188 bool HasIterator =
false;
4190 if (
C->getModifier()) {
4194 for (
const Expr *E :
C->varlist()) {
4203 Base, *std::next(KmpAffinityInfoRD->field_begin(), BaseAddr));
4208 Base, *std::next(KmpAffinityInfoRD->field_begin(), Len));
4222 const Expr *Modifier =
C->getModifier();
4225 OMPIteratorGeneratorScope IteratorScope(
4227 for (
const Expr *E :
C->varlist()) {
4237 Base, *std::next(KmpAffinityInfoRD->field_begin(), BaseAddr));
4242 Base, *std::next(KmpAffinityInfoRD->field_begin(), Len));
4244 Idx = CGF.
Builder.CreateNUWAdd(
4245 Idx, llvm::ConstantInt::get(Idx->getType(), 1));
4260 CGM.getModule(), OMPRTL___kmpc_omp_reg_task_with_affinity),
4261 {LocRef, GTid, NewTask, NumOfElements, AffinListPtr});
4263 llvm::Value *NewTaskNewTaskTTy =
4265 NewTask, KmpTaskTWithPrivatesPtrTy);
4267 KmpTaskTWithPrivatesQTy);
4278 *std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTShareds)),
4280 CGF.
Int8Ty,
CGM.getNaturalTypeAlignment(SharedsTy));
4294 CGM, Loc, D, KmpTaskTWithPrivatesPtrQTy, KmpTaskTWithPrivatesQTyRD,
4295 KmpTaskTQTyRD, SharedsTy, SharedsPtrTy,
Data,
Privates,
4296 !
Data.LastprivateVars.empty());
4300 enum { Priority = 0, Destructors = 1 };
4302 auto FI = std::next(KmpTaskTQTyRD->field_begin(), Data1);
4303 const auto *KmpCmplrdataUD = (*FI)->getType()->castAsRecordDecl();
4304 assert(KmpCmplrdataUD->isUnion());
4307 CGM, Loc, KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy,
4308 KmpTaskTWithPrivatesQTy);
4311 Data1LV, *std::next(KmpCmplrdataUD->field_begin(), Destructors));
4317 if (
Data.Priority.getInt()) {
4319 TDBase, *std::next(KmpTaskTQTyRD->field_begin(), Data2));
4321 Data2LV, *std::next(KmpCmplrdataUD->field_begin(), Priority));
4324 Result.NewTask = NewTask;
4325 Result.TaskEntry = TaskEntry;
4326 Result.NewTaskNewTaskTTy = NewTaskNewTaskTTy;
4328 Result.KmpTaskTQTyRD = KmpTaskTQTyRD;
4334 RTLDependenceKindTy DepKind;
4336 case OMPC_DEPEND_in:
4337 DepKind = RTLDependenceKindTy::DepIn;
4340 case OMPC_DEPEND_out:
4341 case OMPC_DEPEND_inout:
4342 DepKind = RTLDependenceKindTy::DepInOut;
4344 case OMPC_DEPEND_mutexinoutset:
4345 DepKind = RTLDependenceKindTy::DepMutexInOutSet;
4347 case OMPC_DEPEND_inoutset:
4348 DepKind = RTLDependenceKindTy::DepInOutSet;
4350 case OMPC_DEPEND_outallmemory:
4351 DepKind = RTLDependenceKindTy::DepOmpAllMem;
4353 case OMPC_DEPEND_source:
4354 case OMPC_DEPEND_sink:
4355 case OMPC_DEPEND_depobj:
4356 case OMPC_DEPEND_inoutallmemory:
4358 llvm_unreachable(
"Unknown task dependence type");
4366 FlagsTy =
C.getIntTypeForBitwidth(
C.getTypeSize(
C.BoolTy),
false);
4367 if (KmpDependInfoTy.
isNull()) {
4368 RecordDecl *KmpDependInfoRD =
C.buildImplicitRecord(
"kmp_depend_info");
4374 KmpDependInfoTy =
C.getCanonicalTagType(KmpDependInfoRD);
4378std::pair<llvm::Value *, LValue>
4391 CGF,
Base.getAddress(),
4392 llvm::ConstantInt::get(CGF.
IntPtrTy, -1,
true));
4398 *std::next(KmpDependInfoRD->field_begin(),
4399 static_cast<unsigned int>(RTLDependInfoFields::BaseAddr)));
4401 return std::make_pair(NumDeps,
Base);
4405 llvm::PointerUnion<unsigned *, LValue *> Pos,
4415 OMPIteratorGeneratorScope IteratorScope(
4416 CGF, cast_or_null<OMPIteratorExpr>(
4417 Data.IteratorExpr ?
Data.IteratorExpr->IgnoreParenImpCasts()
4419 for (
const Expr *E :
Data.DepExprs) {
4429 Size = llvm::ConstantInt::get(CGF.
SizeTy, 0);
4432 if (
unsigned *P = dyn_cast<unsigned *>(Pos)) {
4436 assert(E &&
"Expected a non-null expression");
4445 *std::next(KmpDependInfoRD->field_begin(),
4446 static_cast<unsigned int>(RTLDependInfoFields::BaseAddr)));
4450 Base, *std::next(KmpDependInfoRD->field_begin(),
4451 static_cast<unsigned int>(RTLDependInfoFields::Len)));
4457 *std::next(KmpDependInfoRD->field_begin(),
4458 static_cast<unsigned int>(RTLDependInfoFields::Flags)));
4460 llvm::ConstantInt::get(LLVMFlagsTy,
static_cast<unsigned int>(DepKind)),
4462 if (
unsigned *P = dyn_cast<unsigned *>(Pos)) {
4467 Idx = CGF.
Builder.CreateNUWAdd(Idx,
4468 llvm::ConstantInt::get(Idx->getType(), 1));
4477 assert(
Data.DepKind == OMPC_DEPEND_depobj &&
4478 "Expected depobj dependency kind.");
4483 OMPIteratorGeneratorScope IteratorScope(
4484 CGF, cast_or_null<OMPIteratorExpr>(
4485 Data.IteratorExpr ?
Data.IteratorExpr->IgnoreParenImpCasts()
4487 for (
const Expr *E :
Data.DepExprs) {
4488 llvm::Value *NumDeps;
4491 std::tie(NumDeps,
Base) =
4495 C.getUIntPtrType());
4499 llvm::Value *Add = CGF.
Builder.CreateNUWAdd(PrevVal, NumDeps);
4501 SizeLVals.push_back(NumLVal);
4504 for (
unsigned I = 0, E = SizeLVals.size(); I < E; ++I) {
4507 Sizes.push_back(Size);
4517 assert(
Data.DepKind == OMPC_DEPEND_depobj &&
4518 "Expected depobj dependency kind.");
4521 OMPIteratorGeneratorScope IteratorScope(
4522 CGF, cast_or_null<OMPIteratorExpr>(
4523 Data.IteratorExpr ?
Data.IteratorExpr->IgnoreParenImpCasts()
4525 for (
const Expr *E :
Data.DepExprs) {
4526 llvm::Value *NumDeps;
4529 std::tie(NumDeps,
Base) =
4533 llvm::Value *Size = CGF.
Builder.CreateNUWMul(
4542 llvm::Value *Add = CGF.
Builder.CreateNUWAdd(Pos, NumDeps);
4558 llvm::Value *NumOfElements =
nullptr;
4559 unsigned NumDependencies = std::accumulate(
4560 Dependencies.begin(), Dependencies.end(), 0,
4562 return D.DepKind == OMPC_DEPEND_depobj
4564 : (V + (D.IteratorExpr ? 0 : D.DepExprs.size()));
4568 bool HasDepobjDeps =
false;
4569 bool HasRegularWithIterators =
false;
4570 llvm::Value *NumOfDepobjElements = llvm::ConstantInt::get(CGF.
IntPtrTy, 0);
4571 llvm::Value *NumOfRegularWithIterators =
4572 llvm::ConstantInt::get(CGF.
IntPtrTy, 0);
4576 if (D.
DepKind == OMPC_DEPEND_depobj) {
4579 for (llvm::Value *Size : Sizes) {
4580 NumOfDepobjElements =
4581 CGF.
Builder.CreateNUWAdd(NumOfDepobjElements, Size);
4583 HasDepobjDeps =
true;
4588 if (
const auto *IE = cast_or_null<OMPIteratorExpr>(D.
IteratorExpr)) {
4589 llvm::Value *ClauseIteratorSpace =
4590 llvm::ConstantInt::get(CGF.
IntPtrTy, 1);
4594 ClauseIteratorSpace = CGF.
Builder.CreateNUWMul(Sz, ClauseIteratorSpace);
4596 llvm::Value *NumClauseDeps = CGF.
Builder.CreateNUWMul(
4597 ClauseIteratorSpace,
4599 NumOfRegularWithIterators =
4600 CGF.
Builder.CreateNUWAdd(NumOfRegularWithIterators, NumClauseDeps);
4601 HasRegularWithIterators =
true;
4607 if (HasDepobjDeps || HasRegularWithIterators) {
4608 NumOfElements = llvm::ConstantInt::get(
CGM.IntPtrTy, NumDependencies,
4610 if (HasDepobjDeps) {
4612 CGF.
Builder.CreateNUWAdd(NumOfDepobjElements, NumOfElements);
4614 if (HasRegularWithIterators) {
4616 CGF.
Builder.CreateNUWAdd(NumOfRegularWithIterators, NumOfElements);
4619 Loc,
C.getIntTypeForBitwidth(64, 0),
4623 KmpDependInfoArrayTy =
4632 NumOfElements = CGF.
Builder.CreateIntCast(NumOfElements, CGF.
Int32Ty,
4635 KmpDependInfoArrayTy =
C.getConstantArrayType(
4641 NumOfElements = llvm::ConstantInt::get(
CGM.Int32Ty, NumDependencies,
4646 if (Dep.DepKind == OMPC_DEPEND_depobj || Dep.IteratorExpr)
4656 if (Dep.DepKind == OMPC_DEPEND_depobj || !Dep.IteratorExpr)
4661 if (HasDepobjDeps) {
4663 if (Dep.DepKind != OMPC_DEPEND_depobj)
4670 return std::make_pair(NumOfElements, DependenciesArray);
4681 unsigned NumDependencies = Dependencies.
DepExprs.size();
4691 llvm::Value *NumDepsVal;
4693 if (
const auto *IE =
4694 cast_or_null<OMPIteratorExpr>(Dependencies.
IteratorExpr)) {
4695 NumDepsVal = llvm::ConstantInt::get(CGF.
SizeTy, 1);
4699 NumDepsVal = CGF.
Builder.CreateNUWMul(NumDepsVal, Sz);
4701 Size = CGF.
Builder.CreateNUWAdd(llvm::ConstantInt::get(CGF.
SizeTy, 1),
4705 llvm::Value *RecSize =
CGM.getSize(SizeInBytes);
4706 Size = CGF.
Builder.CreateNUWMul(Size, RecSize);
4710 QualType KmpDependInfoArrayTy =
C.getConstantArrayType(
4713 CharUnits Sz =
C.getTypeSizeInChars(KmpDependInfoArrayTy);
4715 NumDepsVal = llvm::ConstantInt::get(CGF.
IntPtrTy, NumDependencies);
4720 llvm::Value *Allocator = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
4721 llvm::Value *Args[] = {ThreadID, Size, Allocator};
4725 CGM.getModule(), OMPRTL___kmpc_alloc),
4726 Args,
".dep.arr.addr");
4730 DependenciesArray =
Address(
Addr, KmpDependInfoLlvmTy, Align);
4736 *std::next(KmpDependInfoRD->field_begin(),
4737 static_cast<unsigned int>(RTLDependInfoFields::BaseAddr)));
4739 llvm::PointerUnion<unsigned *, LValue *> Pos;
4756 return DependenciesArray;
4771 Addr.getElementType(),
Addr.emitRawPointer(CGF),
4772 llvm::ConstantInt::get(CGF.
IntPtrTy, -1,
true));
4777 llvm::Value *Allocator = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
4778 llvm::Value *Args[] = {ThreadID, DepObjAddr, Allocator};
4782 CGM.getModule(), OMPRTL___kmpc_free),
4794 llvm::Value *NumDeps;
4805 llvm::BasicBlock *EntryBB = CGF.
Builder.GetInsertBlock();
4807 llvm::PHINode *ElementPHI =
4812 Base.getTBAAInfo());
4816 Base, *std::next(KmpDependInfoRD->field_begin(),
4817 static_cast<unsigned int>(RTLDependInfoFields::Flags)));
4819 llvm::ConstantInt::get(LLVMFlagsTy,
static_cast<unsigned int>(DepKind)),
4823 llvm::Value *ElementNext =
4826 ElementPHI->addIncoming(ElementNext, CGF.
Builder.GetInsertBlock());
4827 llvm::Value *IsEmpty =
4828 CGF.
Builder.CreateICmpEQ(ElementNext, End,
"omp.isempty");
4829 CGF.
Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
4836 llvm::Function *TaskFunction,
4845 llvm::Value *NewTask =
Result.NewTask;
4846 llvm::Function *TaskEntry =
Result.TaskEntry;
4847 llvm::Value *NewTaskNewTaskTTy =
Result.NewTaskNewTaskTTy;
4852 llvm::Value *NumOfElements;
4853 std::tie(NumOfElements, DependenciesArray) =
4864 llvm::Value *TaskArgs[] = { UpLoc, ThreadID, NewTask };
4865 llvm::Value *DepTaskArgs[7];
4866 if (!
Data.Dependences.empty()) {
4867 DepTaskArgs[0] = UpLoc;
4868 DepTaskArgs[1] = ThreadID;
4869 DepTaskArgs[2] = NewTask;
4870 DepTaskArgs[3] = NumOfElements;
4872 DepTaskArgs[5] = CGF.
Builder.getInt32(0);
4873 DepTaskArgs[6] = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
4875 auto &&ThenCodeGen = [
this, &
Data, TDBase, KmpTaskTQTyRD, &TaskArgs,
4878 auto PartIdFI = std::next(KmpTaskTQTyRD->
field_begin(), KmpTaskTPartId);
4882 if (!
Data.Dependences.empty()) {
4885 CGM.getModule(), OMPRTL___kmpc_omp_task_with_deps),
4889 CGM.getModule(), OMPRTL___kmpc_omp_task),
4895 Region->emitUntiedSwitch(CGF);
4898 llvm::Value *DepWaitTaskArgs[7];
4899 if (!
Data.Dependences.empty()) {
4900 DepWaitTaskArgs[0] = UpLoc;
4901 DepWaitTaskArgs[1] = ThreadID;
4902 DepWaitTaskArgs[2] = NumOfElements;
4904 DepWaitTaskArgs[4] = CGF.
Builder.getInt32(0);
4905 DepWaitTaskArgs[5] = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
4906 DepWaitTaskArgs[6] =
4907 llvm::ConstantInt::get(CGF.
Int32Ty,
Data.HasNowaitClause);
4909 auto &M =
CGM.getModule();
4910 auto &&ElseCodeGen = [
this, &M, &TaskArgs, ThreadID, NewTaskNewTaskTTy,
4911 TaskEntry, &
Data, &DepWaitTaskArgs,
4918 if (!
Data.Dependences.empty())
4920 M, OMPRTL___kmpc_omp_taskwait_deps_51),
4923 auto &&
CodeGen = [TaskEntry, ThreadID, NewTaskNewTaskTTy,
4926 llvm::Value *OutlinedFnArgs[] = {ThreadID, NewTaskNewTaskTTy};
4927 CGF.CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, Loc, TaskEntry,
4936 CommonActionTy Action(
OMPBuilder.getOrCreateRuntimeFunction(
4937 M, OMPRTL___kmpc_omp_task_begin_if0),
4940 M, OMPRTL___kmpc_omp_task_complete_if0),
4956 llvm::Function *TaskFunction,
4976 IfVal = llvm::ConstantInt::getSigned(CGF.
IntTy, 1);
4981 *std::next(
Result.KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound));
4988 *std::next(
Result.KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound));
4995 *std::next(
Result.KmpTaskTQTyRD->field_begin(), KmpTaskTStride));
5003 *std::next(
Result.KmpTaskTQTyRD->field_begin(), KmpTaskTReductions));
5004 if (
Data.Reductions) {
5010 enum { NoSchedule = 0, Grainsize = 1, NumTasks = 2 };
5019 llvm::ConstantInt::getSigned(
5021 llvm::ConstantInt::getSigned(
5023 ?
Data.Schedule.getInt() ? NumTasks : Grainsize
5025 Data.Schedule.getPointer()
5028 : llvm::ConstantInt::get(CGF.
Int64Ty, 0)};
5029 if (
Data.HasModifier)
5030 TaskArgs.push_back(llvm::ConstantInt::get(CGF.
Int32Ty, 1));
5032 TaskArgs.push_back(
Result.TaskDupFn
5035 : llvm::ConstantPointerNull::get(CGF.
VoidPtrTy));
5037 CGM.getModule(),
Data.HasModifier
5038 ? OMPRTL___kmpc_taskloop_5
5039 : OMPRTL___kmpc_taskloop),
5056 const Expr *,
const Expr *)> &RedOpGen,
5057 const Expr *XExpr =
nullptr,
const Expr *EExpr =
nullptr,
5058 const Expr *UpExpr =
nullptr) {
5066 llvm::Value *NumElements = CGF.
emitArrayLength(ArrayTy, ElementTy, LHSAddr);
5071 llvm::Value *LHSEnd =
5076 llvm::Value *IsEmpty =
5077 CGF.
Builder.CreateICmpEQ(LHSBegin, LHSEnd,
"omp.arraycpy.isempty");
5078 CGF.
Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
5081 llvm::BasicBlock *EntryBB = CGF.
Builder.GetInsertBlock();
5086 llvm::PHINode *RHSElementPHI = CGF.
Builder.CreatePHI(
5087 RHSBegin->getType(), 2,
"omp.arraycpy.srcElementPast");
5088 RHSElementPHI->addIncoming(RHSBegin, EntryBB);
5093 llvm::PHINode *LHSElementPHI = CGF.
Builder.CreatePHI(
5094 LHSBegin->getType(), 2,
"omp.arraycpy.destElementPast");
5095 LHSElementPHI->addIncoming(LHSBegin, EntryBB);
5102 Scope.addPrivate(LHSVar, LHSElementCurrent);
5103 Scope.addPrivate(RHSVar, RHSElementCurrent);
5105 RedOpGen(CGF, XExpr, EExpr, UpExpr);
5106 Scope.ForceCleanup();
5109 llvm::Value *LHSElementNext = CGF.
Builder.CreateConstGEP1_32(
5111 "omp.arraycpy.dest.element");
5112 llvm::Value *RHSElementNext = CGF.
Builder.CreateConstGEP1_32(
5114 "omp.arraycpy.src.element");
5117 CGF.
Builder.CreateICmpEQ(LHSElementNext, LHSEnd,
"omp.arraycpy.done");
5118 CGF.
Builder.CreateCondBr(Done, DoneBB, BodyBB);
5119 LHSElementPHI->addIncoming(LHSElementNext, CGF.
Builder.GetInsertBlock());
5120 RHSElementPHI->addIncoming(RHSElementNext, CGF.
Builder.GetInsertBlock());
5130 const Expr *ReductionOp) {
5131 if (
const auto *CE = dyn_cast<CallExpr>(ReductionOp))
5132 if (
const auto *OVE = dyn_cast<OpaqueValueExpr>(CE->getCallee()))
5133 if (
const auto *DRE =
5134 dyn_cast<DeclRefExpr>(OVE->getSourceExpr()->IgnoreImpCasts()))
5135 if (
const auto *DRD =
5136 dyn_cast<OMPDeclareReductionDecl>(DRE->getDecl())) {
5137 std::pair<llvm::Function *, llvm::Function *>
Reduction =
5148 StringRef ReducerName,
SourceLocation Loc, llvm::Type *ArgsElemType,
5162 CGM.getTypes().arrangeBuiltinFunctionDeclaration(
C.VoidTy, Args);
5164 auto *Fn = llvm::Function::Create(
CGM.getTypes().GetFunctionType(CGFI),
5165 llvm::GlobalValue::InternalLinkage, Name,
5168 if (!
CGM.getCodeGenOpts().SampleProfileFile.empty())
5169 Fn->addFnAttr(
"sample-profile-suffix-elision-policy",
"selected");
5170 Fn->setDoesNotRecurse();
5189 const auto *IPriv =
Privates.begin();
5191 for (
unsigned I = 0, E = ReductionOps.size(); I < E; ++I, ++IPriv, ++Idx) {
5192 const auto *RHSVar =
5195 const auto *LHSVar =
5198 QualType PrivTy = (*IPriv)->getType();
5214 const auto *ILHS = LHSExprs.begin();
5215 const auto *IRHS = RHSExprs.begin();
5216 for (
const Expr *E : ReductionOps) {
5217 if ((*IPriv)->getType()->isArrayType()) {
5222 CGF, (*IPriv)->getType(), LHSVar, RHSVar,
5224 emitReductionCombiner(CGF, E);
5234 Scope.ForceCleanup();
5240 const Expr *ReductionOp,
5241 const Expr *PrivateRef,
5249 CGF, PrivateRef->
getType(), LHSVar, RHSVar,
5251 emitReductionCombiner(CGF, ReductionOp);
5260 llvm::StringRef Prefix,
const Expr *Ref);
5264 const Expr *LHSExprs,
const Expr *RHSExprs,
const Expr *ReductionOps) {
5291 std::string ReductionVarNameStr;
5292 if (
const auto *DRE = dyn_cast<DeclRefExpr>(
Privates->IgnoreParenCasts()))
5293 ReductionVarNameStr =
5296 ReductionVarNameStr =
"unnamed_priv_var";
5299 std::string SharedName =
5300 CGM.getOpenMPRuntime().getName({
"internal_pivate_", ReductionVarNameStr});
5301 llvm::GlobalVariable *SharedVar =
OMPBuilder.getOrCreateInternalVariable(
5302 LLVMType,
".omp.reduction." + SharedName);
5304 SharedVar->setAlignment(
5312 llvm::Value *BarrierArgs[] = {BarrierLoc, ThreadId};
5317 llvm::Value *IsWorker = CGF.
Builder.CreateICmpEQ(
5318 ThreadId, llvm::ConstantInt::get(ThreadId->getType(), 0));
5319 CGF.
Builder.CreateCondBr(IsWorker, InitBB, InitEndBB);
5323 auto EmitSharedInit = [&]() {
5326 std::pair<llvm::Function *, llvm::Function *> FnPair =
5328 llvm::Function *InitializerFn = FnPair.second;
5329 if (InitializerFn) {
5330 if (
const auto *CE =
5331 dyn_cast<CallExpr>(UDRInitExpr->IgnoreParenImpCasts())) {
5338 LocalScope.addPrivate(OutVD, SharedResult);
5340 (void)LocalScope.Privatize();
5341 if (
const auto *OVE = dyn_cast<OpaqueValueExpr>(
5342 CE->getCallee()->IgnoreParenImpCasts())) {
5368 if (
const auto *DRE = dyn_cast<DeclRefExpr>(
Privates)) {
5369 if (
const auto *VD = dyn_cast<VarDecl>(DRE->getDecl())) {
5380 CGF.
Builder.CreateBr(InitEndBB);
5384 CGM.getModule(), OMPRTL___kmpc_barrier),
5387 const Expr *ReductionOp = ReductionOps;
5392 auto EmitCriticalReduction = [&](
auto ReductionGen) {
5393 std::string CriticalName =
getName({
"reduction_critical"});
5401 std::pair<llvm::Function *, llvm::Function *> FnPair =
5404 if (
const auto *CE = dyn_cast<CallExpr>(ReductionOp)) {
5416 (void)LocalScope.Privatize();
5421 EmitCriticalReduction(ReductionGen);
5426 if (
const auto *Cleanup = dyn_cast<ExprWithCleanups>(ReductionClauseExpr))
5429 const Expr *AssignRHS =
nullptr;
5430 if (
const auto *BinOp = dyn_cast<BinaryOperator>(ReductionClauseExpr)) {
5431 if (BinOp->getOpcode() == BO_Assign)
5432 AssignRHS = BinOp->getRHS();
5433 }
else if (
const auto *OpCall =
5434 dyn_cast<CXXOperatorCallExpr>(ReductionClauseExpr)) {
5435 if (OpCall->getOperator() == OO_Equal)
5436 AssignRHS = OpCall->getArg(1);
5440 "Private Variable Reduction : Invalid ReductionOp expression");
5445 const auto *OmpOutDRE =
5447 const auto *OmpInDRE =
5450 OmpOutDRE && OmpInDRE &&
5451 "Private Variable Reduction : LHSExpr/RHSExpr must be DeclRefExprs");
5455 LocalScope.addPrivate(OmpOutVD, SharedLV.
getAddress());
5456 LocalScope.addPrivate(OmpInVD, LHSLV.
getAddress());
5457 (void)LocalScope.Privatize();
5461 EmitCriticalReduction(ReductionGen);
5465 CGM.getModule(), OMPRTL___kmpc_barrier),
5471 llvm::Value *FinalResultVal =
nullptr;
5475 FinalResultAddr = SharedResult;
5489 CGM.getModule(), OMPRTL___kmpc_barrier),
5500 EmitCriticalReduction(OriginalListCombiner);
5552 if (SimpleReduction) {
5554 const auto *IPriv = OrgPrivates.begin();
5555 const auto *ILHS = OrgLHSExprs.begin();
5556 const auto *IRHS = OrgRHSExprs.begin();
5557 for (
const Expr *E : OrgReductionOps) {
5570 FilteredRHSExprs, FilteredReductionOps;
5571 for (
unsigned I : llvm::seq<unsigned>(
5572 std::min(OrgReductionOps.size(), OrgLHSExprs.size()))) {
5574 FilteredPrivates.emplace_back(OrgPrivates[I]);
5575 FilteredLHSExprs.emplace_back(OrgLHSExprs[I]);
5576 FilteredRHSExprs.emplace_back(OrgRHSExprs[I]);
5577 FilteredReductionOps.emplace_back(OrgReductionOps[I]);
5589 auto Size = RHSExprs.size();
5595 llvm::APInt ArraySize(32, Size);
5596 QualType ReductionArrayTy =
C.getConstantArrayType(
5600 CGF.
CreateMemTemp(ReductionArrayTy,
".omp.reduction.red_list");
5601 const auto *IPriv =
Privates.begin();
5603 for (
unsigned I = 0, E = RHSExprs.size(); I < E; ++I, ++IPriv, ++Idx) {
5609 if ((*IPriv)->getType()->isVariablyModifiedType()) {
5613 llvm::Value *Size = CGF.
Builder.CreateIntCast(
5626 Privates, LHSExprs, RHSExprs, ReductionOps);
5629 std::string Name =
getName({
"reduction"});
5636 llvm::Value *ReductionArrayTySize = CGF.
getTypeSize(ReductionArrayTy);
5639 llvm::Value *Args[] = {
5642 CGF.
Builder.getInt32(RHSExprs.size()),
5643 ReductionArrayTySize,
5651 WithNowait ? OMPRTL___kmpc_reduce_nowait : OMPRTL___kmpc_reduce),
5655 llvm::BasicBlock *DefaultBB = CGF.
createBasicBlock(
".omp.reduction.default");
5656 llvm::SwitchInst *SwInst =
5657 CGF.
Builder.CreateSwitch(Res, DefaultBB, 2);
5666 SwInst->addCase(CGF.
Builder.getInt32(1), Case1BB);
5670 llvm::Value *EndArgs[] = {
5678 const auto *IPriv =
Privates.begin();
5679 const auto *ILHS = LHSExprs.begin();
5680 const auto *IRHS = RHSExprs.begin();
5681 for (
const Expr *E : ReductionOps) {
5690 CommonActionTy Action(
5693 CGM.getModule(), WithNowait ? OMPRTL___kmpc_end_reduce_nowait
5694 : OMPRTL___kmpc_end_reduce),
5707 SwInst->addCase(CGF.
Builder.getInt32(2), Case2BB);
5710 auto &&AtomicCodeGen = [Loc,
Privates, LHSExprs, RHSExprs, ReductionOps](
5712 const auto *ILHS = LHSExprs.begin();
5713 const auto *IRHS = RHSExprs.begin();
5714 const auto *IPriv =
Privates.begin();
5715 for (
const Expr *E : ReductionOps) {
5716 const Expr *XExpr =
nullptr;
5717 const Expr *EExpr =
nullptr;
5718 const Expr *UpExpr =
nullptr;
5720 if (
const auto *BO = dyn_cast<BinaryOperator>(E)) {
5721 if (BO->getOpcode() == BO_Assign) {
5722 XExpr = BO->getLHS();
5723 UpExpr = BO->getRHS();
5727 const Expr *RHSExpr = UpExpr;
5730 if (
const auto *ACO = dyn_cast<AbstractConditionalOperator>(
5734 RHSExpr = ACO->getCond();
5736 if (
const auto *BORHS =
5738 EExpr = BORHS->getRHS();
5739 BO = BORHS->getOpcode();
5744 auto &&AtomicRedGen = [BO, VD,
5746 const Expr *EExpr,
const Expr *UpExpr) {
5747 LValue X = CGF.EmitLValue(XExpr);
5750 E = CGF.EmitAnyExpr(EExpr);
5751 CGF.EmitOMPAtomicSimpleUpdateExpr(
5753 llvm::AtomicOrdering::Monotonic, Loc,
5754 [&CGF, UpExpr, VD, Loc](
RValue XRValue) {
5756 Address LHSTemp = CGF.CreateMemTemp(VD->getType());
5757 CGF.emitOMPSimpleStore(
5758 CGF.MakeAddrLValue(LHSTemp, VD->
getType()), XRValue,
5759 VD->getType().getNonReferenceType(), Loc);
5762 return CGF.EmitAnyExpr(UpExpr);
5765 if ((*IPriv)->getType()->isArrayType()) {
5767 const auto *RHSVar =
5770 AtomicRedGen, XExpr, EExpr, UpExpr);
5773 AtomicRedGen(CGF, XExpr, EExpr, UpExpr);
5780 std::string Name = RT.
getName({
"atomic_reduction"});
5789 if ((*IPriv)->getType()->isArrayType()) {
5790 const auto *LHSVar =
5792 const auto *RHSVar =
5797 CritRedGen(CGF,
nullptr,
nullptr,
nullptr);
5808 llvm::Value *EndArgs[] = {
5813 CommonActionTy Action(
nullptr, {},
5815 CGM.getModule(), OMPRTL___kmpc_end_reduce),
5825 assert(OrgLHSExprs.size() == OrgPrivates.size() &&
5826 "PrivateVarReduction: Privates size mismatch");
5827 assert(OrgLHSExprs.size() == OrgReductionOps.size() &&
5828 "PrivateVarReduction: ReductionOps size mismatch");
5829 for (
unsigned I : llvm::seq<unsigned>(
5830 std::min(OrgReductionOps.size(), OrgLHSExprs.size()))) {
5833 OrgRHSExprs[I], OrgReductionOps[I]);
5842 llvm::raw_svector_ostream Out(Buffer);
5847 if (
const auto *BD = dyn_cast<BindingDecl>(DRE->getDecl())) {
5857 Out << Prefix << Name <<
"_"
5859 return std::string(Out.str());
5883 Args.emplace_back(Param);
5884 Args.emplace_back(ParamOrig);
5885 const auto &FnInfo =
5889 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
5893 Fn->addFnAttr(
"sample-profile-suffix-elision-policy",
"selected");
5894 Fn->setDoesNotRecurse();
5901 llvm::Value *Size =
nullptr;
5944 const Expr *ReductionOp,
5946 const Expr *PrivateRef) {
5957 Args.emplace_back(ParamInOut);
5958 Args.emplace_back(ParamIn);
5959 const auto &FnInfo =
5963 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
5967 Fn->addFnAttr(
"sample-profile-suffix-elision-policy",
"selected");
5968 Fn->setDoesNotRecurse();
5971 llvm::Value *Size =
nullptr;
5992 C.getPointerType(LHSVD->getType())->castAs<
PointerType>()));
5999 C.getPointerType(RHSVD->getType())->castAs<
PointerType>()));
6029 Args.emplace_back(Param);
6030 const auto &FnInfo =
6034 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
6038 Fn->addFnAttr(
"sample-profile-suffix-elision-policy",
"selected");
6039 Fn->setDoesNotRecurse();
6044 llvm::Value *Size =
nullptr;
6079 RecordDecl *RD =
C.buildImplicitRecord(
"kmp_taskred_input_t");
6088 C, RD,
C.getIntTypeForBitwidth(32,
false));
6091 unsigned Size =
Data.ReductionVars.size();
6092 llvm::APInt ArraySize(64, Size);
6094 C.getConstantArrayType(RDType, ArraySize,
nullptr,
6099 Data.ReductionCopies,
Data.ReductionOps);
6100 for (
unsigned Cnt = 0; Cnt < Size; ++Cnt) {
6102 llvm::Value *Idxs[] = {llvm::ConstantInt::get(
CGM.SizeTy, 0),
6103 llvm::ConstantInt::get(
CGM.SizeTy, Cnt)};
6119 llvm::Value *SizeValInChars;
6120 llvm::Value *SizeVal;
6121 std::tie(SizeValInChars, SizeVal) = RCG.
getSizes(Cnt);
6127 bool DelayedCreation = !!SizeVal;
6128 SizeValInChars = CGF.
Builder.CreateIntCast(SizeValInChars,
CGM.SizeTy,
6139 llvm::Value *FiniAddr =
6140 Fini ? Fini : llvm::ConstantPointerNull::get(
CGM.VoidPtrTy);
6145 CGM, Loc, RCG, Cnt,
Data.ReductionOps[Cnt], LHSExprs[Cnt],
6146 RHSExprs[Cnt],
Data.ReductionCopies[Cnt]);
6150 if (DelayedCreation) {
6152 llvm::ConstantInt::get(
CGM.Int32Ty, 1,
true),
6157 if (
Data.IsReductionWithTaskMod) {
6163 llvm::Value *Args[] = {
6165 llvm::ConstantInt::get(
CGM.IntTy,
Data.IsWorksharingReduction ? 1 : 0,
6167 llvm::ConstantInt::get(
CGM.IntTy, Size,
true),
6172 CGM.getModule(), OMPRTL___kmpc_taskred_modifier_init),
6176 llvm::Value *Args[] = {
6179 llvm::ConstantInt::get(
CGM.IntTy, Size,
true),
6183 CGM.getModule(), OMPRTL___kmpc_taskred_init),
6189 bool IsWorksharingReduction) {
6195 llvm::Value *Args[] = {IdentTLoc, GTid,
6196 llvm::ConstantInt::get(
CGM.IntTy,
6197 IsWorksharingReduction ? 1 : 0,
6201 CGM.getModule(), OMPRTL___kmpc_task_reduction_modifier_fini),
6213 llvm::Value *SizeVal = CGF.
Builder.CreateIntCast(Sizes.second,
CGM.SizeTy,
6216 CGF,
CGM.getContext().getSizeType(),
6224 llvm::Value *ReductionsPtr,
6237 CGM.getModule(), OMPRTL___kmpc_task_reduction_get_th_data),
6253 auto &M =
CGM.getModule();
6255 llvm::Value *NumOfElements;
6256 std::tie(NumOfElements, DependenciesArray) =
6258 if (!
Data.Dependences.empty()) {
6259 llvm::Value *DepWaitTaskArgs[7];
6260 DepWaitTaskArgs[0] = UpLoc;
6261 DepWaitTaskArgs[1] = ThreadID;
6262 DepWaitTaskArgs[2] = NumOfElements;
6264 DepWaitTaskArgs[4] = CGF.
Builder.getInt32(0);
6265 DepWaitTaskArgs[5] = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
6266 DepWaitTaskArgs[6] =
6267 llvm::ConstantInt::get(CGF.
Int32Ty,
Data.HasNowaitClause);
6276 M, OMPRTL___kmpc_omp_taskwait_deps_51),
6283 llvm::Value *Args[] = {UpLoc, ThreadID};
6286 OMPBuilder.getOrCreateRuntimeFunction(M, OMPRTL___kmpc_omp_taskwait),
6291 if (
auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.
CapturedStmtInfo))
6292 Region->emitUntiedSwitch(CGF);
6301 InlinedOpenMPRegionRAII Region(CGF,
CodeGen, InnerKind, HasCancel,
6302 InnerKind != OMPD_critical &&
6303 InnerKind != OMPD_master &&
6304 InnerKind != OMPD_masked);
6319 RTCancelKind CancelKind = CancelNoreq;
6320 if (CancelRegion == OMPD_parallel)
6321 CancelKind = CancelParallel;
6322 else if (CancelRegion == OMPD_for)
6323 CancelKind = CancelLoop;
6324 else if (CancelRegion == OMPD_sections)
6325 CancelKind = CancelSections;
6327 assert(CancelRegion == OMPD_taskgroup);
6328 CancelKind = CancelTaskgroup;
6340 if (
auto *OMPRegionInfo =
6344 if (CancelRegion == OMPD_taskgroup || OMPRegionInfo->hasCancel()) {
6345 llvm::Value *Args[] = {
6351 CGM.getModule(), OMPRTL___kmpc_cancellationpoint),
6360 CGF.
Builder.CreateCondBr(
Cmp, ExitBB, ContBB);
6362 if (CancelRegion == OMPD_parallel)
6380 auto &M =
CGM.getModule();
6381 if (
auto *OMPRegionInfo =
6383 auto &&ThenGen = [
this, &M, Loc, CancelRegion,
6386 llvm::Value *Args[] = {
6390 llvm::Value *
Result = CGF.EmitRuntimeCall(
6391 OMPBuilder.getOrCreateRuntimeFunction(M, OMPRTL___kmpc_cancel), Args);
6396 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(
".cancel.exit");
6397 llvm::BasicBlock *ContBB = CGF.createBasicBlock(
".cancel.continue");
6398 llvm::Value *
Cmp = CGF.Builder.CreateIsNotNull(
Result);
6399 CGF.Builder.CreateCondBr(
Cmp, ExitBB, ContBB);
6400 CGF.EmitBlock(ExitBB);
6401 if (CancelRegion == OMPD_parallel)
6405 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind());
6406 CGF.EmitBranchThroughCleanup(CancelDest);
6407 CGF.EmitBlock(ContBB,
true);
6424 bool IsOffloadEntry;
6427 OMPUsesAllocatorsActionTy(
6428 ArrayRef<std::pair<const Expr *, const Expr *>> Allocators,
6430 : Allocators(Allocators), D(D), IsOffloadEntry(IsOffloadEntry) {}
6434 for (
const auto &AllocatorData : Allocators) {
6436 CGF, AllocatorData.first, AllocatorData.second);
6445 void Exit(CodeGenFunction &CGF)
override {
6448 for (
const auto &AllocatorData : Allocators) {
6450 AllocatorData.first);
6458 llvm::OpenMPIRBuilder::TargetKernelDefaultAttrs Attrs;
6459 Attrs.ExecFlags = llvm::omp::OMPTgtExecModeFlags::OMP_TGT_EXEC_MODE_GENERIC;
6466 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
6468 assert(!ParentName.empty() &&
"Invalid target entry parent name!");
6472 for (
unsigned I = 0, E =
C->getNumberOfAllocators(); I < E; ++I) {
6479 OMPUsesAllocatorsActionTy UsesAllocatorAction(Allocators, D, IsOffloadEntry);
6480 CodeGen.setAction(UsesAllocatorAction);
6486 const Expr *Allocator,
6487 const Expr *AllocatorTraits) {
6489 ThreadId = CGF.
Builder.CreateIntCast(ThreadId, CGF.
IntTy,
true);
6491 llvm::Value *MemSpaceHandle = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
6492 llvm::Value *NumTraits = llvm::ConstantInt::get(
6496 .getLimitedValue());
6503 llvm::Value *Traits =
Addr.emitRawPointer(CGF);
6505 llvm::Value *AllocatorVal =
6507 CGM.getModule(), OMPRTL___kmpc_init_allocator),
6508 {ThreadId, MemSpaceHandle, NumTraits, Traits});
6520 const Expr *Allocator) {
6522 ThreadId = CGF.
Builder.CreateIntCast(ThreadId, CGF.
IntTy,
true);
6524 llvm::Value *AllocatorVal =
6531 OMPRTL___kmpc_destroy_allocator),
6532 {ThreadId, AllocatorVal});
6537 llvm::OpenMPIRBuilder::TargetKernelDefaultAttrs &Attrs) {
6538 assert(Attrs.MaxTeams.size() == 1 && Attrs.MaxThreads.size() == 1 &&
6539 "invalid default attrs structure");
6540 int32_t &MaxTeamsVal = Attrs.MaxTeams.front();
6541 int32_t &MaxThreadsVal = Attrs.MaxThreads.front();
6549 for (
auto *A :
C->getAttrs()) {
6550 int32_t AttrMinThreadsVal = 1, AttrMaxThreadsVal = -1;
6551 int32_t AttrMinBlocksVal = 1, AttrMaxBlocksVal = -1;
6552 if (
auto *
Attr = dyn_cast<CUDALaunchBoundsAttr>(A))
6553 CGM.handleCUDALaunchBoundsAttr(
nullptr,
Attr, &AttrMaxThreadsVal,
6554 &AttrMinBlocksVal, &AttrMaxBlocksVal);
6555 else if (
auto *
Attr = dyn_cast<AMDGPUFlatWorkGroupSizeAttr>(A))
6556 CGM.handleAMDGPUFlatWorkGroupSizeAttr(
6557 nullptr,
Attr,
nullptr, &AttrMinThreadsVal,
6558 &AttrMaxThreadsVal);
6562 Attrs.MinThreads.front() =
6563 std::max(Attrs.MinThreads.front(), AttrMinThreadsVal);
6564 if (AttrMaxThreadsVal > 0)
6565 MaxThreadsVal = MaxThreadsVal > 0
6566 ? std::min(MaxThreadsVal, AttrMaxThreadsVal)
6567 : AttrMaxThreadsVal;
6568 Attrs.MinTeams.front() =
6569 std::max(Attrs.MinTeams.front(), AttrMinBlocksVal);
6570 if (AttrMaxBlocksVal > 0)
6571 MaxTeamsVal = MaxTeamsVal > 0 ? std::min(MaxTeamsVal, AttrMaxBlocksVal)
6579 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
6582 llvm::TargetRegionEntryInfo EntryInfo =
6586 llvm::OpenMPIRBuilder::FunctionGenCallback &&GenerateOutlinedFunction =
6587 [&CGF, &D, &
CodeGen,
this](StringRef EntryFnName) {
6588 const CapturedStmt &CS = *D.getCapturedStmt(OMPD_target);
6590 CGOpenMPTargetRegionInfo CGInfo(CS,
CodeGen, EntryFnName);
6592 if (
CGM.getLangOpts().OpenMPIsTargetDevice && !
isGPU())
6597 cantFail(
OMPBuilder.emitTargetRegionFunction(
6598 EntryInfo, GenerateOutlinedFunction, IsOffloadEntry, OutlinedFn,
6606 OutlinedFn->setDoesNotRecurse();
6608 CGM.getTargetCodeGenInfo().setTargetAttributes(
nullptr, OutlinedFn,
CGM);
6611 for (
auto *A :
C->getAttrs()) {
6612 if (
auto *
Attr = dyn_cast<AMDGPUWavesPerEUAttr>(A))
6613 CGM.handleAMDGPUWavesPerEUAttr(OutlinedFn,
Attr);
6632 while (
const auto *
C = dyn_cast_or_null<CompoundStmt>(Child)) {
6634 for (
const Stmt *S :
C->body()) {
6635 if (
const auto *E = dyn_cast<Expr>(S)) {
6644 if (
const auto *DS = dyn_cast<DeclStmt>(S)) {
6645 if (llvm::all_of(DS->decls(), [](
const Decl *D) {
6646 if (isa<EmptyDecl>(D) || isa<DeclContext>(D) ||
6647 isa<TypeDecl>(D) || isa<PragmaCommentDecl>(D) ||
6648 isa<PragmaDetectMismatchDecl>(D) || isa<UsingDecl>(D) ||
6649 isa<UsingDirectiveDecl>(D) ||
6650 isa<OMPDeclareReductionDecl>(D) ||
6651 isa<OMPThreadPrivateDecl>(D) || isa<OMPAllocateDecl>(D))
6653 const auto *VD = dyn_cast<VarDecl>(D);
6656 return VD->hasGlobalStorage() || !VD->isUsed();
6666 Child = Child->IgnoreContainers();
6673 int32_t &MaxTeamsVal) {
6677 "Expected target-based executable directive.");
6678 switch (DirectiveKind) {
6680 const auto *CS = D.getInnermostCapturedStmt();
6683 const Stmt *ChildStmt =
6685 if (
const auto *NestedDir =
6686 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) {
6695 MinTeamsVal = MaxTeamsVal =
Constant->getExtValue();
6698 MinTeamsVal = MaxTeamsVal = 0;
6701 MinTeamsVal = MaxTeamsVal = 1;
6705 MinTeamsVal = MaxTeamsVal = -1;
6708 case OMPD_target_teams_loop:
6709 case OMPD_target_teams:
6710 case OMPD_target_teams_distribute:
6711 case OMPD_target_teams_distribute_simd:
6712 case OMPD_target_teams_distribute_parallel_for:
6713 case OMPD_target_teams_distribute_parallel_for_simd: {
6715 const Expr *NumTeams =
6719 MinTeamsVal = MaxTeamsVal =
Constant->getExtValue();
6722 MinTeamsVal = MaxTeamsVal = 0;
6725 case OMPD_target_parallel:
6726 case OMPD_target_parallel_for:
6727 case OMPD_target_parallel_for_simd:
6728 case OMPD_target_parallel_loop:
6729 case OMPD_target_simd:
6730 MinTeamsVal = MaxTeamsVal = 1;
6734 case OMPD_parallel_for:
6735 case OMPD_parallel_loop:
6736 case OMPD_parallel_master:
6737 case OMPD_parallel_sections:
6739 case OMPD_parallel_for_simd:
6741 case OMPD_cancellation_point:
6742 case OMPD_ordered_standalone:
6743 case OMPD_ordered_blockassoc:
6744 case OMPD_threadprivate:
6755 case OMPD_taskyield:
6758 case OMPD_taskgroup:
6764 case OMPD_target_data:
6765 case OMPD_target_exit_data:
6766 case OMPD_target_enter_data:
6767 case OMPD_distribute:
6768 case OMPD_distribute_simd:
6769 case OMPD_distribute_parallel_for:
6770 case OMPD_distribute_parallel_for_simd:
6771 case OMPD_teams_distribute:
6772 case OMPD_teams_distribute_simd:
6773 case OMPD_teams_distribute_parallel_for:
6774 case OMPD_teams_distribute_parallel_for_simd:
6775 case OMPD_target_update:
6776 case OMPD_declare_simd:
6777 case OMPD_declare_variant:
6778 case OMPD_begin_declare_variant:
6779 case OMPD_end_declare_variant:
6780 case OMPD_declare_target:
6781 case OMPD_end_declare_target:
6782 case OMPD_declare_reduction:
6783 case OMPD_declare_mapper:
6785 case OMPD_taskloop_simd:
6786 case OMPD_master_taskloop:
6787 case OMPD_master_taskloop_simd:
6788 case OMPD_parallel_master_taskloop:
6789 case OMPD_parallel_master_taskloop_simd:
6791 case OMPD_metadirective:
6797 llvm_unreachable(
"Unexpected directive kind.");
6803 "Clauses associated with the teams directive expected to be emitted "
6804 "only for the host!");
6806 int32_t MinNT = -1, MaxNT = -1;
6807 const Expr *NumTeams =
6809 if (NumTeams !=
nullptr) {
6812 switch (DirectiveKind) {
6814 const auto *CS = D.getInnermostCapturedStmt();
6815 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6819 return Bld.CreateIntCast(NumTeamsVal, CGF.
Int32Ty,
6822 case OMPD_target_teams:
6823 case OMPD_target_teams_distribute:
6824 case OMPD_target_teams_distribute_simd:
6825 case OMPD_target_teams_distribute_parallel_for:
6826 case OMPD_target_teams_distribute_parallel_for_simd: {
6830 return Bld.CreateIntCast(NumTeamsVal, CGF.
Int32Ty,
6838 assert(MinNT == MaxNT &&
"Num threads ranges require handling here.");
6839 return llvm::ConstantInt::getSigned(CGF.
Int32Ty, MinNT);
6853 UpperBound = UpperBound > 0 ? std::min(UpperBound, Val) : Val;
6862 bool UpperBoundOnly, llvm::Value **CondVal) {
6865 const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child);
6872 if (CondVal && Dir->hasClausesOfKind<
OMPIfClause>()) {
6873 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6876 for (
const auto *
C : Dir->getClausesOfKind<
OMPIfClause>()) {
6877 if (
C->getNameModifier() == OMPD_unknown ||
6878 C->getNameModifier() == OMPD_parallel) {
6893 if (
const auto *PreInit =
6895 for (
const auto *I : PreInit->decls()) {
6896 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
6912 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6914 const auto *NumThreadsClause =
6916 const Expr *NTExpr = NumThreadsClause->getNumThreads().front();
6917 if (NTExpr->isIntegerConstantExpr(CGF.
getContext()))
6923 if (UpperBound == -1)
6928 if (
const auto *PreInit =
6929 cast_or_null<DeclStmt>(NumThreadsClause->getPreInitStmt())) {
6930 for (
const auto *I : PreInit->decls()) {
6931 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
6950 bool UpperBoundOnly, llvm::Value **CondVal,
const Expr **ThreadLimitExpr) {
6951 assert((!CGF.
getLangOpts().OpenMPIsTargetDevice || UpperBoundOnly) &&
6952 "Clauses associated with the teams directive expected to be emitted "
6953 "only for the host!");
6956 "Expected target-based executable directive.");
6958 const Expr *NT =
nullptr;
6959 const Expr **NTPtr = UpperBoundOnly ?
nullptr : &NT;
6961 auto CheckForConstExpr = [&](
const Expr *E,
const Expr **EPtr) {
6965 UpperBound,
static_cast<int32_t
>(
Constant->getZExtValue()));
6969 if (UpperBound == -1)
6975 auto ReturnSequential = [&]() {
6980 switch (DirectiveKind) {
6983 getNumThreads(CGF, CS, NTPtr, UpperBound, UpperBoundOnly, CondVal);
6989 if (
const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) {
6991 ThreadLimitClause = TLC;
6992 if (ThreadLimitExpr) {
6993 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6997 ThreadLimitClause->getThreadLimit().front()->getSourceRange());
6998 if (
const auto *PreInit =
6999 cast_or_null<DeclStmt>(ThreadLimitClause->getPreInitStmt())) {
7000 for (
const auto *I : PreInit->decls()) {
7001 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
7013 if (ThreadLimitClause)
7014 CheckForConstExpr(ThreadLimitClause->getThreadLimit().front(),
7016 if (
const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) {
7019 CS = Dir->getInnermostCapturedStmt();
7033 Dir = dyn_cast_or_null<OMPExecutableDirective>(Child);
7036 CS = Dir->getInnermostCapturedStmt();
7037 getNumThreads(CGF, CS, NTPtr, UpperBound, UpperBoundOnly, CondVal);
7039 return ReturnSequential();
7043 case OMPD_target_teams: {
7047 CheckForConstExpr(ThreadLimitClause->getThreadLimit().front(),
7051 getNumThreads(CGF, CS, NTPtr, UpperBound, UpperBoundOnly, CondVal);
7054 if (
const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) {
7055 if (Dir->getDirectiveKind() == OMPD_distribute) {
7056 CS = Dir->getInnermostCapturedStmt();
7057 getNumThreads(CGF, CS, NTPtr, UpperBound, UpperBoundOnly, CondVal);
7062 case OMPD_target_teams_distribute:
7066 CheckForConstExpr(ThreadLimitClause->getThreadLimit().front(),
7069 getNumThreads(CGF, D.getInnermostCapturedStmt(), NTPtr, UpperBound,
7070 UpperBoundOnly, CondVal);
7072 case OMPD_target_teams_loop:
7073 case OMPD_target_parallel_loop:
7074 case OMPD_target_parallel:
7075 case OMPD_target_parallel_for:
7076 case OMPD_target_parallel_for_simd:
7077 case OMPD_target_teams_distribute_parallel_for:
7078 case OMPD_target_teams_distribute_parallel_for_simd: {
7079 if (CondVal && D.hasClausesOfKind<
OMPIfClause>()) {
7081 for (
const auto *
C : D.getClausesOfKind<
OMPIfClause>()) {
7082 if (
C->getNameModifier() == OMPD_unknown ||
7083 C->getNameModifier() == OMPD_parallel) {
7093 return ReturnSequential();
7103 CheckForConstExpr(ThreadLimitClause->getThreadLimit().front(),
7109 CheckForConstExpr(NumThreadsClause->getNumThreads().front(),
nullptr);
7110 return NumThreadsClause->getNumThreads().front();
7114 case OMPD_target_teams_distribute_simd:
7115 case OMPD_target_simd:
7116 return ReturnSequential();
7120 llvm_unreachable(
"Unsupported directive kind.");
7125 llvm::Value *NumThreadsVal =
nullptr;
7126 llvm::Value *CondVal =
nullptr;
7127 llvm::Value *ThreadLimitVal =
nullptr;
7128 const Expr *ThreadLimitExpr =
nullptr;
7129 int32_t UpperBound = -1;
7132 CGF, D, UpperBound,
false, &CondVal,
7136 if (ThreadLimitExpr) {
7139 ThreadLimitVal = CGF.
Builder.CreateIntCast(ThreadLimitVal, CGF.
Int32Ty,
7144 if (UpperBound == 1) {
7145 NumThreadsVal = CGF.
Builder.getInt32(UpperBound);
7148 NumThreadsVal = CGF.
Builder.CreateIntCast(NumThreadsVal, CGF.
Int32Ty,
7150 }
else if (ThreadLimitVal) {
7153 NumThreadsVal = ThreadLimitVal;
7154 ThreadLimitVal =
nullptr;
7157 assert(!ThreadLimitVal &&
"Default not applicable with thread limit value");
7158 NumThreadsVal = CGF.
Builder.getInt32(0);
7165 NumThreadsVal = CGF.
Builder.CreateSelect(CondVal, NumThreadsVal,
7171 if (ThreadLimitVal) {
7172 NumThreadsVal = CGF.
Builder.CreateSelect(
7173 CGF.
Builder.CreateICmpULT(ThreadLimitVal, NumThreadsVal),
7174 ThreadLimitVal, NumThreadsVal);
7177 return NumThreadsVal;
7187class MappableExprsHandler {
7193 struct AttachPtrExprComparator {
7194 const MappableExprsHandler &Handler;
7196 mutable llvm::DenseMap<std::pair<const Expr *, const Expr *>,
bool>
7197 CachedEqualityComparisons;
7199 AttachPtrExprComparator(
const MappableExprsHandler &H) : Handler(H) {}
7200 AttachPtrExprComparator() =
delete;
7203 bool operator()(
const Expr *LHS,
const Expr *RHS)
const {
7208 const auto ItLHS = Handler.AttachPtrComponentDepthMap.find(LHS);
7209 const auto ItRHS = Handler.AttachPtrComponentDepthMap.find(RHS);
7211 std::optional<size_t> DepthLHS =
7212 (ItLHS != Handler.AttachPtrComponentDepthMap.end()) ? ItLHS->second
7214 std::optional<size_t> DepthRHS =
7215 (ItRHS != Handler.AttachPtrComponentDepthMap.end()) ? ItRHS->second
7219 if (!DepthLHS.has_value() && !DepthRHS.has_value()) {
7221 if (areEqual(LHS, RHS))
7224 return wasComputedBefore(LHS, RHS);
7226 if (!DepthLHS.has_value())
7228 if (!DepthRHS.has_value())
7232 if (DepthLHS.value() != DepthRHS.value())
7233 return DepthLHS.value() < DepthRHS.value();
7236 if (areEqual(LHS, RHS))
7239 return wasComputedBefore(LHS, RHS);
7245 bool areEqual(
const Expr *LHS,
const Expr *RHS)
const {
7247 const auto CachedResultIt = CachedEqualityComparisons.find({LHS, RHS});
7248 if (CachedResultIt != CachedEqualityComparisons.end())
7249 return CachedResultIt->second;
7263 bool wasComputedBefore(
const Expr *LHS,
const Expr *RHS)
const {
7264 const size_t &OrderLHS = Handler.AttachPtrComputationOrderMap.at(LHS);
7265 const size_t &OrderRHS = Handler.AttachPtrComputationOrderMap.at(RHS);
7267 return OrderLHS < OrderRHS;
7276 bool areSemanticallyEqual(
const Expr *LHS,
const Expr *RHS)
const {
7298 if (
const auto *LD = dyn_cast<DeclRefExpr>(LHS)) {
7299 const auto *RD = dyn_cast<DeclRefExpr>(RHS);
7302 return LD->getDecl()->getCanonicalDecl() ==
7303 RD->getDecl()->getCanonicalDecl();
7307 if (
const auto *LA = dyn_cast<ArraySubscriptExpr>(LHS)) {
7308 const auto *RA = dyn_cast<ArraySubscriptExpr>(RHS);
7311 return areSemanticallyEqual(LA->getBase(), RA->getBase()) &&
7312 areSemanticallyEqual(LA->getIdx(), RA->getIdx());
7316 if (
const auto *LM = dyn_cast<MemberExpr>(LHS)) {
7317 const auto *RM = dyn_cast<MemberExpr>(RHS);
7320 if (LM->getMemberDecl()->getCanonicalDecl() !=
7321 RM->getMemberDecl()->getCanonicalDecl())
7323 return areSemanticallyEqual(LM->getBase(), RM->getBase());
7327 if (
const auto *LU = dyn_cast<UnaryOperator>(LHS)) {
7328 const auto *RU = dyn_cast<UnaryOperator>(RHS);
7331 if (LU->getOpcode() != RU->getOpcode())
7333 return areSemanticallyEqual(LU->getSubExpr(), RU->getSubExpr());
7337 if (
const auto *LB = dyn_cast<BinaryOperator>(LHS)) {
7338 const auto *RB = dyn_cast<BinaryOperator>(RHS);
7341 if (LB->getOpcode() != RB->getOpcode())
7343 return areSemanticallyEqual(LB->getLHS(), RB->getLHS()) &&
7344 areSemanticallyEqual(LB->getRHS(), RB->getRHS());
7350 if (
const auto *LAS = dyn_cast<ArraySectionExpr>(LHS)) {
7351 const auto *RAS = dyn_cast<ArraySectionExpr>(RHS);
7354 return areSemanticallyEqual(LAS->getBase(), RAS->getBase()) &&
7355 areSemanticallyEqual(LAS->getLowerBound(),
7356 RAS->getLowerBound()) &&
7357 areSemanticallyEqual(LAS->getLength(), RAS->getLength());
7361 if (
const auto *LC = dyn_cast<CastExpr>(LHS)) {
7362 const auto *RC = dyn_cast<CastExpr>(RHS);
7365 if (LC->getCastKind() != RC->getCastKind())
7367 return areSemanticallyEqual(LC->getSubExpr(), RC->getSubExpr());
7375 if (
const auto *LI = dyn_cast<IntegerLiteral>(LHS)) {
7376 const auto *RI = dyn_cast<IntegerLiteral>(RHS);
7379 return LI->getValue() == RI->getValue();
7383 if (
const auto *LC = dyn_cast<CharacterLiteral>(LHS)) {
7384 const auto *RC = dyn_cast<CharacterLiteral>(RHS);
7387 return LC->getValue() == RC->getValue();
7391 if (
const auto *LF = dyn_cast<FloatingLiteral>(LHS)) {
7392 const auto *RF = dyn_cast<FloatingLiteral>(RHS);
7396 return LF->getValue().bitwiseIsEqual(RF->getValue());
7400 if (
const auto *LS = dyn_cast<StringLiteral>(LHS)) {
7401 const auto *RS = dyn_cast<StringLiteral>(RHS);
7404 return LS->getString() == RS->getString();
7412 if (
const auto *LB = dyn_cast<CXXBoolLiteralExpr>(LHS)) {
7413 const auto *RB = dyn_cast<CXXBoolLiteralExpr>(RHS);
7416 return LB->getValue() == RB->getValue();
7425 static unsigned getFlagMemberOffset() {
7426 unsigned Offset = 0;
7427 for (uint64_t Remain =
7428 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
7429 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF);
7430 !(Remain & 1); Remain = Remain >> 1)
7437 class MappingExprInfo {
7439 const ValueDecl *MapDecl =
nullptr;
7442 const Expr *MapExpr =
nullptr;
7445 MappingExprInfo(
const ValueDecl *MapDecl,
const Expr *MapExpr =
nullptr)
7446 : MapDecl(MapDecl), MapExpr(MapExpr) {}
7448 const ValueDecl *getMapDecl()
const {
return MapDecl; }
7449 const Expr *getMapExpr()
const {
return MapExpr; }
7452 using DeviceInfoTy = llvm::OpenMPIRBuilder::DeviceInfoTy;
7453 using MapBaseValuesArrayTy = llvm::OpenMPIRBuilder::MapValuesArrayTy;
7454 using MapValuesArrayTy = llvm::OpenMPIRBuilder::MapValuesArrayTy;
7455 using MapFlagsArrayTy = llvm::OpenMPIRBuilder::MapFlagsArrayTy;
7456 using MapDimArrayTy = llvm::OpenMPIRBuilder::MapDimArrayTy;
7457 using MapNonContiguousArrayTy =
7458 llvm::OpenMPIRBuilder::MapNonContiguousArrayTy;
7459 using MapExprsArrayTy = SmallVector<MappingExprInfo, 4>;
7460 using MapValueDeclsArrayTy = SmallVector<const ValueDecl *, 4>;
7464 bool ,
const ValueDecl *,
const Expr *>;
7465 using MapDataArrayTy = SmallVector<MapData, 4>;
7470 struct MapCombinedInfoTy : llvm::OpenMPIRBuilder::MapInfosTy {
7471 MapExprsArrayTy Exprs;
7472 MapValueDeclsArrayTy Mappers;
7473 MapValueDeclsArrayTy DevicePtrDecls;
7476 void append(MapCombinedInfoTy &CurInfo) {
7477 Exprs.append(CurInfo.Exprs.begin(), CurInfo.Exprs.end());
7478 DevicePtrDecls.append(CurInfo.DevicePtrDecls.begin(),
7479 CurInfo.DevicePtrDecls.end());
7480 Mappers.append(CurInfo.Mappers.begin(), CurInfo.Mappers.end());
7481 llvm::OpenMPIRBuilder::MapInfosTy::append(CurInfo);
7489 struct StructRangeInfoTy {
7490 MapCombinedInfoTy PreliminaryMapData;
7491 std::pair<
unsigned ,
Address > LowestElem = {
7493 std::pair<
unsigned ,
Address > HighestElem = {
7497 bool IsArraySection =
false;
7498 bool HasCompleteRecord =
false;
7503 struct AttachInfoTy {
7506 const ValueDecl *AttachPtrDecl =
nullptr;
7507 const Expr *AttachMapExpr =
nullptr;
7509 bool isValid()
const {
7516 bool hasAttachEntryForCapturedVar(
const ValueDecl *VD)
const {
7517 for (
const auto &AttachEntry : AttachPtrExprMap) {
7518 if (AttachEntry.second) {
7521 if (
const auto *DRE = dyn_cast<DeclRefExpr>(AttachEntry.second))
7522 if (DRE->getDecl() == VD)
7530 const Expr *getAttachPtrExpr(
7533 const auto It = AttachPtrExprMap.find(Components);
7534 if (It != AttachPtrExprMap.end())
7545 ArrayRef<OpenMPMapModifierKind> MapModifiers;
7546 ArrayRef<OpenMPMotionModifierKind> MotionModifiers;
7547 bool ReturnDevicePointer =
false;
7548 bool IsImplicit =
false;
7549 const ValueDecl *Mapper =
nullptr;
7550 const Expr *VarRef =
nullptr;
7551 bool ForDeviceAddr =
false;
7552 bool HasUdpFbNullify =
false;
7554 MapInfo() =
default;
7558 ArrayRef<OpenMPMapModifierKind> MapModifiers,
7559 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
7560 bool ReturnDevicePointer,
bool IsImplicit,
7561 const ValueDecl *Mapper =
nullptr,
const Expr *VarRef =
nullptr,
7562 bool ForDeviceAddr =
false,
bool HasUdpFbNullify =
false)
7563 : Components(Components), MapType(MapType), MapModifiers(MapModifiers),
7564 MotionModifiers(MotionModifiers),
7565 ReturnDevicePointer(ReturnDevicePointer), IsImplicit(IsImplicit),
7566 Mapper(Mapper), VarRef(VarRef), ForDeviceAddr(ForDeviceAddr),
7567 HasUdpFbNullify(HasUdpFbNullify) {}
7572 llvm::PointerUnion<
const OMPExecutableDirective *,
7573 const OMPDeclareMapperDecl *>
7577 CodeGenFunction &CGF;
7582 llvm::DenseMap<CanonicalDeclPtr<const VarDecl>,
bool> FirstPrivateDecls;
7585 llvm::SmallSet<OpenMPDefaultmapClauseKind, 4> DefaultmapFirstprivateKinds;
7591 SmallVector<OMPClauseMappableExprCommon::MappableExprComponentListRef, 4>>
7598 SmallVector<OMPClauseMappableExprCommon::MappableExprComponentListRef, 4>>
7602 llvm::DenseMap<const ValueDecl *, const OMPMapClause *> LambdasMap;
7617 llvm::DenseMap<const Expr *, std::optional<size_t>>
7618 AttachPtrComponentDepthMap = {{
nullptr, std::nullopt}};
7622 llvm::DenseMap<const Expr *, size_t> AttachPtrComputationOrderMap = {
7627 AttachPtrExprComparator AttachPtrComparator;
7629 llvm::Value *getExprTypeSize(
const Expr *E)
const {
7633 if (
const auto *OAE = dyn_cast<OMPArrayShapingExpr>(E)) {
7635 CGF.
getTypeSize(OAE->getBase()->getType()->getPointeeType());
7636 for (
const Expr *SE : OAE->getDimensions()) {
7647 if (
const auto *RefTy =
ExprTy->getAs<ReferenceType>())
7648 ExprTy = RefTy->getPointeeType().getCanonicalType();
7653 if (
const auto *OAE = dyn_cast<ArraySectionExpr>(E)) {
7655 OAE->getBase()->IgnoreParenImpCasts())
7661 if (!OAE->getLength() && OAE->getColonLocFirst().isValid() &&
7662 !OAE->getLowerBound())
7665 llvm::Value *ElemSize;
7666 if (
const auto *PTy = BaseTy->
getAs<PointerType>()) {
7667 ElemSize = CGF.
getTypeSize(PTy->getPointeeType().getCanonicalType());
7670 assert(ATy &&
"Expecting array type if not a pointer type.");
7671 ElemSize = CGF.
getTypeSize(ATy->getElementType().getCanonicalType());
7676 if (!OAE->getLength() && OAE->getColonLocFirst().isInvalid())
7679 if (
const Expr *LenExpr = OAE->getLength()) {
7683 LenExpr->getExprLoc());
7684 return CGF.
Builder.CreateNUWMul(LengthVal, ElemSize);
7686 assert(!OAE->getLength() && OAE->getColonLocFirst().isValid() &&
7687 OAE->getLowerBound() &&
"expected array_section[lb:].");
7693 OAE->getLowerBound()->getExprLoc());
7694 LBVal = CGF.
Builder.CreateNUWMul(LBVal, ElemSize);
7695 llvm::Value *
Cmp = CGF.
Builder.CreateICmpUGT(LengthVal, LBVal);
7696 llvm::Value *TrueVal = CGF.
Builder.CreateNUWSub(LengthVal, LBVal);
7697 LengthVal = CGF.
Builder.CreateSelect(
7698 Cmp, TrueVal, llvm::ConstantInt::get(CGF.
SizeTy, 0));
7708 OpenMPOffloadMappingFlags getMapTypeBits(
7710 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
bool IsImplicit,
7711 bool AddPtrFlag,
bool AddIsTargetParamFlag,
bool IsNonContiguous)
const {
7712 OpenMPOffloadMappingFlags Bits =
7713 IsImplicit ? OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT
7714 : OpenMPOffloadMappingFlags::OMP_MAP_NONE;
7716 case OMPC_MAP_alloc:
7717 case OMPC_MAP_release:
7724 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_TO;
7727 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_FROM;
7729 case OMPC_MAP_tofrom:
7730 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_TO |
7731 OpenMPOffloadMappingFlags::OMP_MAP_FROM;
7733 case OMPC_MAP_delete:
7734 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_DELETE;
7737 llvm_unreachable(
"Unexpected map type!");
7740 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ;
7741 if (AddIsTargetParamFlag)
7742 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM;
7743 if (llvm::is_contained(MapModifiers, OMPC_MAP_MODIFIER_always))
7744 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_ALWAYS;
7745 if (llvm::is_contained(MapModifiers, OMPC_MAP_MODIFIER_close))
7746 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_CLOSE;
7747 if (llvm::is_contained(MapModifiers, OMPC_MAP_MODIFIER_present) ||
7748 llvm::is_contained(MotionModifiers, OMPC_MOTION_MODIFIER_present))
7749 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_PRESENT;
7750 if (llvm::is_contained(MapModifiers, OMPC_MAP_MODIFIER_ompx_hold))
7751 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_OMPX_HOLD;
7752 if (IsNonContiguous)
7753 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_NON_CONTIG;
7759 bool isFinalArraySectionExpression(
const Expr *E)
const {
7760 const auto *OASE = dyn_cast<ArraySectionExpr>(E);
7767 if (OASE->getColonLocFirst().isInvalid())
7770 const Expr *Length = OASE->getLength();
7777 OASE->getBase()->IgnoreParenImpCasts())
7779 if (
const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.
getTypePtr()))
7780 return ATy->getSExtSize() != 1;
7792 llvm::APSInt ConstLength =
Result.Val.getInt();
7793 return ConstLength.getSExtValue() != 1;
7800 void emitAttachEntry(CodeGenFunction &CGF, MapCombinedInfoTy &CombinedInfo,
7801 const AttachInfoTy &AttachInfo)
const {
7802 assert(AttachInfo.isValid() &&
7803 "Expected valid attach pointer/pointee information!");
7807 llvm::Value *PointerSize = CGF.
Builder.CreateIntCast(
7808 llvm::ConstantInt::get(
7814 CombinedInfo.Exprs.emplace_back(AttachInfo.AttachPtrDecl,
7815 AttachInfo.AttachMapExpr);
7816 CombinedInfo.BasePointers.push_back(
7817 AttachInfo.AttachPtrAddr.emitRawPointer(CGF));
7818 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
7819 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
7820 CombinedInfo.Pointers.push_back(
7821 AttachInfo.AttachPteeAddr.emitRawPointer(CGF));
7822 CombinedInfo.Sizes.push_back(PointerSize);
7823 CombinedInfo.Types.push_back(OpenMPOffloadMappingFlags::OMP_MAP_ATTACH);
7825 CombinedInfo.HasAttachPtr.push_back(
false);
7826 CombinedInfo.Mappers.push_back(
nullptr);
7827 CombinedInfo.NonContigInfo.Dims.push_back(1);
7834 class CopyOverlappedEntryGaps {
7835 CodeGenFunction &CGF;
7836 MapCombinedInfoTy &CombinedInfo;
7837 OpenMPOffloadMappingFlags Flags = OpenMPOffloadMappingFlags::OMP_MAP_NONE;
7838 const ValueDecl *MapDecl =
nullptr;
7839 const Expr *MapExpr =
nullptr;
7841 bool IsNonContiguous =
false;
7845 const RecordDecl *LastParent =
nullptr;
7847 unsigned LastIndex = -1u;
7851 CopyOverlappedEntryGaps(CodeGenFunction &CGF,
7852 MapCombinedInfoTy &CombinedInfo,
7853 OpenMPOffloadMappingFlags Flags,
7854 const ValueDecl *MapDecl,
const Expr *MapExpr,
7855 Address BP, Address LB,
bool IsNonContiguous,
7857 : CGF(CGF), CombinedInfo(CombinedInfo), Flags(Flags), MapDecl(MapDecl),
7858 MapExpr(MapExpr), BP(BP), IsNonContiguous(IsNonContiguous),
7859 DimSize(DimSize), LB(LB) {}
7862 const OMPClauseMappableExprCommon::MappableComponent &MC,
7863 const FieldDecl *FD,
7864 llvm::function_ref<LValue(CodeGenFunction &,
const MemberExpr *)>
7865 EmitMemberExprBase) {
7875 LValue BaseLVal = EmitMemberExprBase(CGF, ME);
7887 copyUntilField(FD, ComponentLB);
7890 if (((int64_t)FieldOffset - (int64_t)Cursor) > 0)
7891 copyUntilField(FD, ComponentLB);
7893 Cursor = FieldOffset + FieldSize;
7898 void copyUntilField(
const FieldDecl *FD, Address ComponentLB) {
7901 llvm::Value *
Size = CGF.
Builder.CreatePtrDiff(ComponentLBPtr, LBPtr);
7902 copySizedChunk(LBPtr, Size);
7905 void copyUntilEnd(Address HB) {
7907 const ASTRecordLayout &RL =
7915 copySizedChunk(LBPtr, Size);
7918 void copySizedChunk(llvm::Value *Base, llvm::Value *Size) {
7919 CombinedInfo.Exprs.emplace_back(MapDecl, MapExpr);
7921 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
7922 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
7923 CombinedInfo.Pointers.push_back(Base);
7924 CombinedInfo.Sizes.push_back(
7926 CombinedInfo.Types.push_back(Flags);
7927 CombinedInfo.HasAttachPtr.push_back(
false);
7928 CombinedInfo.Mappers.push_back(
nullptr);
7929 CombinedInfo.NonContigInfo.Dims.push_back(IsNonContiguous ? DimSize : 1);
7938 void generateInfoForComponentList(
7940 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
7942 MapCombinedInfoTy &CombinedInfo,
7943 MapCombinedInfoTy &StructBaseCombinedInfo,
7944 StructRangeInfoTy &PartialStruct, AttachInfoTy &AttachInfo,
7945 bool IsFirstComponentList,
bool IsImplicit,
7946 bool GenerateAllInfoForClauses,
const ValueDecl *Mapper =
nullptr,
7947 bool ForDeviceAddr =
false,
const ValueDecl *BaseDecl =
nullptr,
7948 const Expr *MapExpr =
nullptr,
7949 ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef>
7950 OverlappedElements = {})
const {
8168 bool IsCaptureFirstInfo = IsFirstComponentList;
8172 bool RequiresReference =
false;
8175 auto CI = Components.rbegin();
8176 auto CE = Components.rend();
8181 bool IsExpressionFirstInfo =
true;
8182 bool FirstPointerInComplexData =
false;
8185 const Expr *AssocExpr = I->getAssociatedExpression();
8186 const auto *AE = dyn_cast<ArraySubscriptExpr>(AssocExpr);
8187 const auto *OASE = dyn_cast<ArraySectionExpr>(AssocExpr);
8188 const auto *OAShE = dyn_cast<OMPArrayShapingExpr>(AssocExpr);
8191 const Expr *AttachPtrExpr = getAttachPtrExpr(Components);
8192 auto [AttachPtrAddr, AttachPteeBaseAddr] =
8193 getAttachPtrAddrAndPteeBaseAddr(AttachPtrExpr, CGF);
8195 bool HasAttachPtr = AttachPtrExpr !=
nullptr;
8196 bool FirstComponentIsForAttachPtr = AssocExpr == AttachPtrExpr;
8197 bool SeenAttachPtr = FirstComponentIsForAttachPtr;
8199 if (FirstComponentIsForAttachPtr) {
8207 }
else if ((AE &&
isa<CXXThisExpr>(AE->getBase()->IgnoreParenImpCasts())) ||
8221 if (
const auto *VD =
8222 dyn_cast_or_null<VarDecl>(I->getAssociatedDeclaration())) {
8223 if (std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
8224 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD)) {
8225 if ((*Res == OMPDeclareTargetDeclAttr::MT_Link) ||
8226 ((*Res == OMPDeclareTargetDeclAttr::MT_To ||
8227 *Res == OMPDeclareTargetDeclAttr::MT_Enter) &&
8229 RequiresReference =
true;
8239 I->getAssociatedDeclaration()->
getType().getNonReferenceType();
8244 const auto *VD = dyn_cast<VarDecl>(I->getAssociatedDeclaration());
8246 !VD || VD->hasLocalStorage() || HasAttachPtr)
8249 FirstPointerInComplexData =
true;
8268 bool ShouldBeMemberOf =
false;
8277 const MemberExpr *EncounteredME =
nullptr;
8289 bool IsNonContiguous =
8290 CombinedInfo.NonContigInfo.IsNonContiguous ||
8291 any_of(Components, [&](
const auto &Component) {
8293 dyn_cast<ArraySectionExpr>(Component.getAssociatedExpression());
8297 const Expr *StrideExpr = OASE->getStride();
8302 "Stride expression must be of integer type");
8315 bool IsPrevMemberReference =
false;
8317 bool IsPartialMapped =
8318 !PartialStruct.PreliminaryMapData.BasePointers.empty();
8325 bool IsMappingWholeStruct =
true;
8326 if (!GenerateAllInfoForClauses) {
8327 IsMappingWholeStruct =
false;
8329 for (
auto TempI = I; TempI != CE; ++TempI) {
8330 const MemberExpr *PossibleME =
8331 dyn_cast<MemberExpr>(TempI->getAssociatedExpression());
8333 IsMappingWholeStruct =
false;
8339 bool SeenFirstNonBinOpExprAfterAttachPtr =
false;
8340 for (; I != CE; ++I) {
8343 if (HasAttachPtr && !SeenAttachPtr) {
8344 SeenAttachPtr = I->getAssociatedExpression() == AttachPtrExpr;
8351 if (HasAttachPtr && !SeenFirstNonBinOpExprAfterAttachPtr) {
8352 const auto *BO = dyn_cast<BinaryOperator>(I->getAssociatedExpression());
8357 SeenFirstNonBinOpExprAfterAttachPtr =
true;
8358 BP = AttachPteeBaseAddr;
8362 if (!EncounteredME) {
8363 EncounteredME = dyn_cast<MemberExpr>(I->getAssociatedExpression());
8366 if (EncounteredME) {
8367 ShouldBeMemberOf =
true;
8370 if (FirstPointerInComplexData) {
8371 QualType Ty = std::prev(I)
8372 ->getAssociatedDeclaration()
8374 .getNonReferenceType();
8376 FirstPointerInComplexData =
false;
8381 auto Next = std::next(I);
8391 bool IsFinalArraySection =
8393 isFinalArraySectionExpression(I->getAssociatedExpression());
8397 const ValueDecl *MapDecl = (I->getAssociatedDeclaration())
8398 ? I->getAssociatedDeclaration()
8400 MapExpr = (I->getAssociatedExpression()) ? I->getAssociatedExpression()
8407 dyn_cast<ArraySectionExpr>(I->getAssociatedExpression());
8409 dyn_cast<OMPArrayShapingExpr>(I->getAssociatedExpression());
8410 const auto *UO = dyn_cast<UnaryOperator>(I->getAssociatedExpression());
8411 const auto *BO = dyn_cast<BinaryOperator>(I->getAssociatedExpression());
8417 I->getAssociatedExpression()->getType()->isAnyPointerType();
8418 bool IsMemberReference =
isa<MemberExpr>(I->getAssociatedExpression()) &&
8421 bool IsNonDerefPointer = IsPointer &&
8422 !(UO && UO->getOpcode() != UO_Deref) && !BO &&
8428 if (
Next == CE || IsMemberReference || IsNonDerefPointer ||
8429 IsFinalArraySection) {
8432 assert((
Next == CE ||
8439 "Unexpected expression");
8443 auto &&EmitMemberExprBase = [](CodeGenFunction &CGF,
8444 const MemberExpr *E) {
8445 const Expr *BaseExpr = E->getBase();
8450 LValueBaseInfo BaseInfo;
8451 TBAAAccessInfo TBAAInfo;
8465 OAShE->getBase()->getType()->getPointeeType()),
8467 OAShE->getBase()->getType()));
8468 }
else if (IsMemberReference) {
8470 LValue BaseLVal = EmitMemberExprBase(CGF, ME);
8485 FinalLowestElem = LowestElem;
8490 bool IsMemberPointerOrAddr =
8492 (((IsPointer || ForDeviceAddr) &&
8493 I->getAssociatedExpression() == EncounteredME) ||
8494 (IsPrevMemberReference && !IsPointer) ||
8495 (IsMemberReference &&
Next != CE &&
8496 !
Next->getAssociatedExpression()->getType()->isPointerType()));
8497 if (!OverlappedElements.empty() &&
Next == CE) {
8499 assert(!PartialStruct.Base.isValid() &&
"The base element is set.");
8500 assert(!IsPointer &&
8501 "Unexpected base element with the pointer type.");
8504 PartialStruct.LowestElem = {0, LowestElem};
8506 I->getAssociatedExpression()->getType());
8511 PartialStruct.HighestElem = {
8512 std::numeric_limits<
decltype(
8513 PartialStruct.HighestElem.first)>
::max(),
8515 PartialStruct.Base = BP;
8516 PartialStruct.LB = LB;
8518 PartialStruct.PreliminaryMapData.BasePointers.empty() &&
8519 "Overlapped elements must be used only once for the variable.");
8520 std::swap(PartialStruct.PreliminaryMapData, CombinedInfo);
8522 OpenMPOffloadMappingFlags Flags =
8523 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF |
8524 getMapTypeBits(MapType, MapModifiers, MotionModifiers, IsImplicit,
8526 false, IsNonContiguous);
8527 CopyOverlappedEntryGaps CopyGaps(CGF, CombinedInfo, Flags, MapDecl,
8528 MapExpr, BP, LB, IsNonContiguous,
8532 Component : OverlappedElements) {
8533 for (
const OMPClauseMappableExprCommon::MappableComponent &MC :
8536 if (
const auto *FD = dyn_cast<FieldDecl>(VD)) {
8537 CopyGaps.processField(MC, FD, EmitMemberExprBase);
8542 CopyGaps.copyUntilEnd(HB);
8545 llvm::Value *
Size = getExprTypeSize(I->getAssociatedExpression());
8552 if ((!IsMemberPointerOrAddr && !IsPartialMapped) ||
8554 if (!IsMappingWholeStruct) {
8555 CombinedInfo.Exprs.emplace_back(MapDecl, MapExpr);
8557 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
8558 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
8560 CombinedInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
8562 CombinedInfo.NonContigInfo.Dims.push_back(IsNonContiguous ? DimSize
8565 StructBaseCombinedInfo.Exprs.emplace_back(MapDecl, MapExpr);
8566 StructBaseCombinedInfo.BasePointers.push_back(
8568 StructBaseCombinedInfo.DevicePtrDecls.push_back(
nullptr);
8569 StructBaseCombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
8570 StructBaseCombinedInfo.Pointers.push_back(LB.
emitRawPointer(CGF));
8571 StructBaseCombinedInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
8573 StructBaseCombinedInfo.NonContigInfo.Dims.push_back(
8574 IsNonContiguous ? DimSize : 1);
8578 bool HasMapper = Mapper &&
Next == CE;
8579 if (!IsMappingWholeStruct)
8580 CombinedInfo.Mappers.push_back(HasMapper ? Mapper :
nullptr);
8582 StructBaseCombinedInfo.Mappers.push_back(HasMapper ? Mapper
8589 OpenMPOffloadMappingFlags Flags = getMapTypeBits(
8590 MapType, MapModifiers, MotionModifiers, IsImplicit,
8591 !IsExpressionFirstInfo || RequiresReference ||
8592 FirstPointerInComplexData || IsMemberReference,
8593 IsCaptureFirstInfo && !RequiresReference, IsNonContiguous);
8595 if (!IsExpressionFirstInfo || IsMemberReference) {
8598 if (IsPointer || (IsMemberReference &&
Next != CE))
8599 Flags &= ~(OpenMPOffloadMappingFlags::OMP_MAP_TO |
8600 OpenMPOffloadMappingFlags::OMP_MAP_FROM |
8601 OpenMPOffloadMappingFlags::OMP_MAP_ALWAYS |
8602 OpenMPOffloadMappingFlags::OMP_MAP_DELETE |
8603 OpenMPOffloadMappingFlags::OMP_MAP_CLOSE);
8605 if (ShouldBeMemberOf) {
8608 Flags |= OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF;
8611 ShouldBeMemberOf =
false;
8615 if (!IsMappingWholeStruct) {
8616 CombinedInfo.Types.push_back(Flags);
8618 CombinedInfo.HasAttachPtr.push_back(HasAttachPtr);
8620 StructBaseCombinedInfo.Types.push_back(Flags);
8621 StructBaseCombinedInfo.HasAttachPtr.push_back(HasAttachPtr);
8628 if (EncounteredME) {
8633 if (!PartialStruct.Base.isValid()) {
8634 PartialStruct.LowestElem = {FieldIndex, LowestElem};
8635 if (IsFinalArraySection && OASE) {
8639 PartialStruct.HighestElem = {FieldIndex, HB};
8641 PartialStruct.HighestElem = {FieldIndex, LowestElem};
8643 PartialStruct.Base = BP;
8644 PartialStruct.LB = BP;
8645 }
else if (FieldIndex < PartialStruct.LowestElem.first) {
8646 PartialStruct.LowestElem = {FieldIndex, LowestElem};
8647 }
else if (FieldIndex > PartialStruct.HighestElem.first) {
8648 if (IsFinalArraySection && OASE) {
8652 PartialStruct.HighestElem = {FieldIndex, HB};
8654 PartialStruct.HighestElem = {FieldIndex, LowestElem};
8660 if (IsFinalArraySection || IsNonContiguous)
8661 PartialStruct.IsArraySection =
true;
8664 if (IsFinalArraySection)
8669 BP = IsMemberReference ? LowestElem : LB;
8670 if (!IsPartialMapped)
8671 IsExpressionFirstInfo =
false;
8672 IsCaptureFirstInfo =
false;
8673 FirstPointerInComplexData =
false;
8674 IsPrevMemberReference = IsMemberReference;
8675 }
else if (FirstPointerInComplexData) {
8676 QualType Ty = Components.rbegin()
8677 ->getAssociatedDeclaration()
8679 .getNonReferenceType();
8681 FirstPointerInComplexData =
false;
8687 PartialStruct.HasCompleteRecord =
true;
8690 if (shouldEmitAttachEntry(AttachPtrExpr, BaseDecl, CGF, CurDir)) {
8691 AttachInfo.AttachPtrAddr = AttachPtrAddr;
8692 AttachInfo.AttachPteeAddr = FinalLowestElem;
8693 AttachInfo.AttachPtrDecl = BaseDecl;
8694 AttachInfo.AttachMapExpr = MapExpr;
8697 if (!IsNonContiguous)
8700 const ASTContext &Context = CGF.
getContext();
8704 MapValuesArrayTy CurOffsets = {llvm::ConstantInt::get(CGF.
CGM.
Int64Ty, 0)};
8705 MapValuesArrayTy CurCounts;
8706 MapValuesArrayTy CurStrides = {llvm::ConstantInt::get(CGF.
CGM.
Int64Ty, 1)};
8707 MapValuesArrayTy DimSizes{llvm::ConstantInt::get(CGF.
CGM.
Int64Ty, 1)};
8713 for (
const OMPClauseMappableExprCommon::MappableComponent &Component :
8715 const Expr *AssocExpr = Component.getAssociatedExpression();
8716 const auto *OASE = dyn_cast<ArraySectionExpr>(AssocExpr);
8726 assert((VAT || CAT || &Component == &*Components.begin()) &&
8727 "Should be either ConstantArray or VariableArray if not the "
8731 if (CurCounts.empty()) {
8732 const Type *ElementType =
nullptr;
8734 ElementType = CAT->getElementType().getTypePtr();
8736 ElementType = VAT->getElementType().getTypePtr();
8737 else if (&Component == &*Components.begin()) {
8744 if (
const auto *PtrType = Ty->
getAs<PointerType>())
8745 ElementType = PtrType->getPointeeType().getTypePtr();
8751 "Non-first components should not be raw pointers");
8759 if (&Component != &*Components.begin())
8760 ElementType = ElementType->getPointeeOrArrayElementType();
8763 CurCounts.push_back(
8764 llvm::ConstantInt::get(CGF.
Int64Ty, ElementTypeSize));
8769 if (DimSizes.size() < Components.size() - 1) {
8772 llvm::ConstantInt::get(CGF.
Int64Ty, CAT->getZExtSize()));
8774 DimSizes.push_back(CGF.
Builder.CreateIntCast(
8781 auto *DI = DimSizes.begin() + 1;
8783 llvm::Value *DimProd =
8784 llvm::ConstantInt::get(CGF.
CGM.
Int64Ty, ElementTypeSize);
8793 for (
const OMPClauseMappableExprCommon::MappableComponent &Component :
8795 const Expr *AssocExpr = Component.getAssociatedExpression();
8797 if (
const auto *AE = dyn_cast<ArraySubscriptExpr>(AssocExpr)) {
8798 llvm::Value *Offset = CGF.
Builder.CreateIntCast(
8801 CurOffsets.push_back(Offset);
8802 CurCounts.push_back(llvm::ConstantInt::get(CGF.
Int64Ty, 1));
8803 CurStrides.push_back(CurStrides.back());
8807 const auto *OASE = dyn_cast<ArraySectionExpr>(AssocExpr);
8813 const Expr *OffsetExpr = OASE->getLowerBound();
8814 llvm::Value *Offset =
nullptr;
8817 Offset = llvm::ConstantInt::get(CGF.
Int64Ty, 0);
8825 const Expr *CountExpr = OASE->getLength();
8826 llvm::Value *Count =
nullptr;
8832 if (!OASE->getColonLocFirst().isValid() &&
8833 !OASE->getColonLocSecond().isValid()) {
8834 Count = llvm::ConstantInt::get(CGF.
Int64Ty, 1);
8840 const Expr *StrideExpr = OASE->getStride();
8841 llvm::Value *Stride =
8847 Count = CGF.
Builder.CreateUDiv(
8848 CGF.
Builder.CreateNUWSub(*DI, Offset), Stride);
8850 Count = CGF.
Builder.CreateNUWSub(*DI, Offset);
8856 CurCounts.push_back(Count);
8866 const Expr *StrideExpr = OASE->getStride();
8867 llvm::Value *Stride =
8872 DimProd = CGF.
Builder.CreateNUWMul(DimProd, *(DI - 1));
8874 CurStrides.push_back(CGF.
Builder.CreateNUWMul(DimProd, Stride));
8876 CurStrides.push_back(DimProd);
8878 Offset = CGF.
Builder.CreateNUWMul(DimProd, Offset);
8879 CurOffsets.push_back(Offset);
8881 if (DI != DimSizes.end())
8885 CombinedInfo.NonContigInfo.Offsets.push_back(CurOffsets);
8886 CombinedInfo.NonContigInfo.Counts.push_back(CurCounts);
8887 CombinedInfo.NonContigInfo.Strides.push_back(CurStrides);
8893 OpenMPOffloadMappingFlags
8894 getMapModifiersForPrivateClauses(
const CapturedStmt::Capture &Cap)
const {
8902 return OpenMPOffloadMappingFlags::OMP_MAP_TO |
8903 OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ;
8904 return OpenMPOffloadMappingFlags::OMP_MAP_PRIVATE |
8905 OpenMPOffloadMappingFlags::OMP_MAP_TO;
8908 if (I != LambdasMap.end())
8910 return getMapTypeBits(
8911 I->getSecond()->getMapType(), I->getSecond()->getMapTypeModifiers(),
8912 {}, I->getSecond()->isImplicit(),
8916 return OpenMPOffloadMappingFlags::OMP_MAP_TO |
8917 OpenMPOffloadMappingFlags::OMP_MAP_FROM;
8920 void getPlainLayout(
const CXXRecordDecl *RD,
8921 llvm::SmallVectorImpl<const FieldDecl *> &Layout,
8922 bool AsBase)
const {
8925 llvm::StructType *St =
8928 unsigned NumElements = St->getNumElements();
8930 llvm::PointerUnion<const CXXRecordDecl *, const FieldDecl *>, 4>
8931 RecordLayout(NumElements);
8934 for (
const auto &I : RD->
bases()) {
8938 QualType BaseTy = I.getType();
8949 RecordLayout[FieldIndex] =
Base;
8952 for (
const auto &I : RD->
vbases()) {
8953 QualType BaseTy = I.getType();
8960 if (RecordLayout[FieldIndex])
8962 RecordLayout[FieldIndex] =
Base;
8965 assert(!RD->
isUnion() &&
"Unexpected union.");
8966 for (
const auto *Field : RD->
fields()) {
8969 if (!
Field->isBitField() &&
8972 RecordLayout[FieldIndex] =
Field;
8975 for (
const llvm::PointerUnion<const CXXRecordDecl *, const FieldDecl *>
8976 &
Data : RecordLayout) {
8979 if (
const auto *Base = dyn_cast<const CXXRecordDecl *>(
Data))
8980 getPlainLayout(Base, Layout,
true);
8987 static Address getAttachPtrAddr(
const Expr *PointerExpr,
8988 CodeGenFunction &CGF) {
8989 assert(PointerExpr &&
"Cannot get addr from null attach-ptr expr");
8992 if (
auto *DRE = dyn_cast<DeclRefExpr>(PointerExpr)) {
8995 }
else if (
auto *OASE = dyn_cast<ArraySectionExpr>(PointerExpr)) {
8998 }
else if (
auto *ASE = dyn_cast<ArraySubscriptExpr>(PointerExpr)) {
9000 }
else if (
auto *ME = dyn_cast<MemberExpr>(PointerExpr)) {
9002 }
else if (
auto *UO = dyn_cast<UnaryOperator>(PointerExpr)) {
9003 assert(UO->getOpcode() == UO_Deref &&
9004 "Unexpected unary-operator on attach-ptr-expr");
9007 assert(AttachPtrAddr.
isValid() &&
9008 "Failed to get address for attach pointer expression");
9009 return AttachPtrAddr;
9016 static std::pair<Address, Address>
9017 getAttachPtrAddrAndPteeBaseAddr(
const Expr *AttachPtrExpr,
9018 CodeGenFunction &CGF) {
9023 Address AttachPtrAddr = getAttachPtrAddr(AttachPtrExpr, CGF);
9024 assert(AttachPtrAddr.
isValid() &&
"Invalid attach pointer addr");
9026 QualType AttachPtrType =
9031 AttachPtrAddr, AttachPtrType->
castAs<PointerType>());
9032 assert(AttachPteeBaseAddr.
isValid() &&
"Invalid attach pointee base addr");
9034 return {AttachPtrAddr, AttachPteeBaseAddr};
9040 shouldEmitAttachEntry(
const Expr *PointerExpr,
const ValueDecl *MapBaseDecl,
9041 CodeGenFunction &CGF,
9042 llvm::PointerUnion<
const OMPExecutableDirective *,
9043 const OMPDeclareMapperDecl *>
9053 ->getDirectiveKind());
9062 void collectAttachPtrExprInfo(
9064 llvm::PointerUnion<
const OMPExecutableDirective *,
9065 const OMPDeclareMapperDecl *>
9070 ? OMPD_declare_mapper
9073 const auto &[AttachPtrExpr, Depth] =
9077 AttachPtrComputationOrderMap.try_emplace(
9078 AttachPtrExpr, AttachPtrComputationOrderMap.size());
9079 AttachPtrComponentDepthMap.try_emplace(AttachPtrExpr, Depth);
9080 AttachPtrExprMap.try_emplace(Components, AttachPtrExpr);
9088 void generateAllInfoForClauses(
9089 ArrayRef<const OMPClause *> Clauses, MapCombinedInfoTy &CombinedInfo,
9090 llvm::OpenMPIRBuilder &OMPBuilder,
9091 const llvm::DenseSet<CanonicalDeclPtr<const Decl>> &SkipVarSet =
9092 llvm::DenseSet<CanonicalDeclPtr<const Decl>>())
const {
9097 llvm::MapVector<CanonicalDeclPtr<const Decl>,
9098 SmallVector<SmallVector<MapInfo, 8>, 4>>
9104 [&Info, &SkipVarSet](
9105 const ValueDecl *D, MapKind
Kind,
9108 ArrayRef<OpenMPMapModifierKind> MapModifiers,
9109 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
9110 bool ReturnDevicePointer,
bool IsImplicit,
const ValueDecl *Mapper,
9111 const Expr *VarRef =
nullptr,
bool ForDeviceAddr =
false) {
9112 if (SkipVarSet.contains(D))
9114 auto It = Info.try_emplace(D, Total).first;
9115 It->second[
Kind].emplace_back(
9116 L, MapType, MapModifiers, MotionModifiers, ReturnDevicePointer,
9117 IsImplicit, Mapper, VarRef, ForDeviceAddr);
9120 for (
const auto *
Cl : Clauses) {
9121 const auto *
C = dyn_cast<OMPMapClause>(
Cl);
9125 if (llvm::is_contained(
C->getMapTypeModifiers(),
9126 OMPC_MAP_MODIFIER_present))
9128 else if (
C->getMapType() == OMPC_MAP_alloc)
9130 const auto *EI =
C->getVarRefs().begin();
9131 for (
const auto L :
C->component_lists()) {
9132 const Expr *E = (
C->getMapLoc().isValid()) ? *EI :
nullptr;
9133 InfoGen(std::get<0>(L), Kind, std::get<1>(L),
C->getMapType(),
9134 C->getMapTypeModifiers(), {},
9135 false,
C->isImplicit(), std::get<2>(L),
9140 for (
const auto *
Cl : Clauses) {
9141 const auto *
C = dyn_cast<OMPToClause>(
Cl);
9145 if (llvm::is_contained(
C->getMotionModifiers(),
9146 OMPC_MOTION_MODIFIER_present))
9148 if (llvm::is_contained(
C->getMotionModifiers(),
9149 OMPC_MOTION_MODIFIER_iterator)) {
9150 if (
auto *IteratorExpr = dyn_cast<OMPIteratorExpr>(
9151 C->getIteratorModifier()->IgnoreParenImpCasts())) {
9152 const auto *VD =
cast<VarDecl>(IteratorExpr->getIteratorDecl(0));
9157 const auto *EI =
C->getVarRefs().begin();
9158 for (
const auto L :
C->component_lists()) {
9159 InfoGen(std::get<0>(L), Kind, std::get<1>(L), OMPC_MAP_to, {},
9160 C->getMotionModifiers(),
false,
9161 C->isImplicit(), std::get<2>(L), *EI);
9165 for (
const auto *
Cl : Clauses) {
9166 const auto *
C = dyn_cast<OMPFromClause>(
Cl);
9170 if (llvm::is_contained(
C->getMotionModifiers(),
9171 OMPC_MOTION_MODIFIER_present))
9173 if (llvm::is_contained(
C->getMotionModifiers(),
9174 OMPC_MOTION_MODIFIER_iterator)) {
9175 if (
auto *IteratorExpr = dyn_cast<OMPIteratorExpr>(
9176 C->getIteratorModifier()->IgnoreParenImpCasts())) {
9177 const auto *VD =
cast<VarDecl>(IteratorExpr->getIteratorDecl(0));
9182 const auto *EI =
C->getVarRefs().begin();
9183 for (
const auto L :
C->component_lists()) {
9184 InfoGen(std::get<0>(L), Kind, std::get<1>(L), OMPC_MAP_from, {},
9185 C->getMotionModifiers(),
9186 false,
C->isImplicit(), std::get<2>(L),
9199 MapCombinedInfoTy UseDeviceDataCombinedInfo;
9201 auto &&UseDeviceDataCombinedInfoGen =
9202 [&UseDeviceDataCombinedInfo](
const ValueDecl *VD, llvm::Value *
Ptr,
9203 CodeGenFunction &CGF,
bool IsDevAddr,
9204 bool HasUdpFbNullify =
false) {
9205 UseDeviceDataCombinedInfo.Exprs.push_back(VD);
9206 UseDeviceDataCombinedInfo.BasePointers.emplace_back(Ptr);
9207 UseDeviceDataCombinedInfo.DevicePtrDecls.emplace_back(VD);
9208 UseDeviceDataCombinedInfo.DevicePointers.emplace_back(
9209 IsDevAddr ? DeviceInfoTy::Address : DeviceInfoTy::Pointer);
9215 UseDeviceDataCombinedInfo.Pointers.push_back(Ptr);
9216 UseDeviceDataCombinedInfo.Sizes.push_back(
9217 llvm::Constant::getNullValue(CGF.Int64Ty));
9218 OpenMPOffloadMappingFlags Flags =
9219 OpenMPOffloadMappingFlags::OMP_MAP_RETURN_PARAM;
9220 if (HasUdpFbNullify)
9221 Flags |= OpenMPOffloadMappingFlags::OMP_MAP_FB_NULLIFY;
9222 UseDeviceDataCombinedInfo.Types.push_back(Flags);
9223 UseDeviceDataCombinedInfo.HasAttachPtr.push_back(
false);
9224 UseDeviceDataCombinedInfo.Mappers.push_back(
nullptr);
9228 [&UseDeviceDataCombinedInfoGen](
9229 CodeGenFunction &CGF,
const Expr *IE,
const ValueDecl *VD,
9232 bool IsDevAddr,
bool IEIsAttachPtrForDevAddr =
false,
9233 bool HasUdpFbNullify =
false) {
9237 if (IsDevAddr && !IEIsAttachPtrForDevAddr) {
9238 if (IE->isGLValue())
9245 bool TreatDevAddrAsDevPtr = IEIsAttachPtrForDevAddr;
9252 UseDeviceDataCombinedInfoGen(VD, Ptr, CGF, IsDevAddr &&
9253 !TreatDevAddrAsDevPtr,
9257 auto &&IsMapInfoExist =
9258 [&Info,
this](CodeGenFunction &CGF,
const ValueDecl *VD,
const Expr *IE,
9259 const Expr *DesiredAttachPtrExpr,
bool IsDevAddr,
9260 bool HasUdpFbNullify =
false) ->
bool {
9268 if (It != Info.end()) {
9270 for (
auto &
Data : It->second) {
9271 MapInfo *CI =
nullptr;
9275 auto *It = llvm::find_if(
Data, [&](
const MapInfo &MI) {
9276 if (MI.Components.back().getAssociatedDeclaration() != VD)
9279 const Expr *MapAttachPtr = getAttachPtrExpr(MI.Components);
9280 bool Match = AttachPtrComparator.areEqual(MapAttachPtr,
9281 DesiredAttachPtrExpr);
9285 if (It !=
Data.end())
9290 CI->ForDeviceAddr =
true;
9291 CI->ReturnDevicePointer =
true;
9292 CI->HasUdpFbNullify = HasUdpFbNullify;
9296 auto PrevCI = std::next(CI->Components.rbegin());
9297 const auto *VarD = dyn_cast<VarDecl>(VD);
9298 const Expr *AttachPtrExpr = getAttachPtrExpr(CI->Components);
9299 if (CGF.CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory() ||
9301 !VD->getType().getNonReferenceType()->isPointerType() ||
9302 PrevCI == CI->Components.rend() ||
9304 VarD->hasLocalStorage() ||
9305 (isa_and_nonnull<DeclRefExpr>(AttachPtrExpr) &&
9307 CI->ForDeviceAddr = IsDevAddr;
9308 CI->ReturnDevicePointer =
true;
9309 CI->HasUdpFbNullify = HasUdpFbNullify;
9327 for (
const auto *
Cl : Clauses) {
9328 const auto *
C = dyn_cast<OMPUseDevicePtrClause>(
Cl);
9331 bool HasUdpFbNullify =
9332 C->getFallbackModifier() == OMPC_USE_DEVICE_PTR_FALLBACK_fb_nullify;
9333 for (
const auto L :
C->component_lists()) {
9336 assert(!Components.empty() &&
9337 "Not expecting empty list of components!");
9338 const ValueDecl *VD = Components.back().getAssociatedDeclaration();
9340 const Expr *IE = Components.back().getAssociatedExpression();
9348 const Expr *UDPOperandExpr =
9349 Components.front().getAssociatedExpression();
9350 if (IsMapInfoExist(CGF, VD, IE,
9352 false, HasUdpFbNullify))
9354 MapInfoGen(CGF, IE, VD, Components,
false,
9355 false, HasUdpFbNullify);
9359 llvm::SmallDenseSet<CanonicalDeclPtr<const Decl>, 4> Processed;
9360 for (
const auto *
Cl : Clauses) {
9361 const auto *
C = dyn_cast<OMPUseDeviceAddrClause>(
Cl);
9364 for (
const auto L :
C->component_lists()) {
9367 assert(!std::get<1>(L).empty() &&
9368 "Not expecting empty list of components!");
9369 const ValueDecl *VD = std::get<1>(L).back().getAssociatedDeclaration();
9370 if (!Processed.insert(VD).second)
9391 const Expr *UDAAttachPtrExpr = getAttachPtrExpr(Components);
9392 const Expr *IE = std::get<1>(L).back().getAssociatedExpression();
9393 assert((!UDAAttachPtrExpr || UDAAttachPtrExpr == IE) &&
9394 "use_device_addr operand has an attach-ptr, but does not match "
9395 "last component's expr.");
9396 if (IsMapInfoExist(CGF, VD, IE,
9400 MapInfoGen(CGF, IE, VD, Components,
9402 UDAAttachPtrExpr !=
nullptr);
9406 for (
const auto &
Data : Info) {
9407 MapCombinedInfoTy CurInfo;
9409 const ValueDecl *VD = cast_or_null<ValueDecl>(D);
9416 SmallVector<std::pair<const Expr *, MapInfo>, 16> AttachPtrMapInfoPairs;
9419 for (
const auto &M :
Data.second) {
9420 for (
const MapInfo &L : M) {
9421 assert(!L.Components.empty() &&
9422 "Not expecting declaration with no component lists.");
9424 const Expr *AttachPtrExpr = getAttachPtrExpr(L.Components);
9425 AttachPtrMapInfoPairs.emplace_back(AttachPtrExpr, L);
9430 llvm::stable_sort(AttachPtrMapInfoPairs,
9431 [
this](
const auto &LHS,
const auto &RHS) {
9432 return AttachPtrComparator(LHS.first, RHS.first);
9437 auto *It = AttachPtrMapInfoPairs.begin();
9438 while (It != AttachPtrMapInfoPairs.end()) {
9439 const Expr *AttachPtrExpr = It->first;
9441 SmallVector<MapInfo, 8> GroupLists;
9442 while (It != AttachPtrMapInfoPairs.end() &&
9443 (It->first == AttachPtrExpr ||
9444 AttachPtrComparator.areEqual(It->first, AttachPtrExpr))) {
9445 GroupLists.push_back(It->second);
9448 assert(!GroupLists.empty() &&
"GroupLists should not be empty");
9450 StructRangeInfoTy PartialStruct;
9451 AttachInfoTy AttachInfo;
9452 MapCombinedInfoTy GroupCurInfo;
9454 MapCombinedInfoTy GroupStructBaseCurInfo;
9455 for (
const MapInfo &L : GroupLists) {
9457 unsigned CurrentBasePointersIdx = GroupCurInfo.BasePointers.size();
9458 unsigned StructBasePointersIdx =
9459 GroupStructBaseCurInfo.BasePointers.size();
9461 GroupCurInfo.NonContigInfo.IsNonContiguous =
9462 L.Components.back().isNonContiguous();
9463 generateInfoForComponentList(
9464 L.MapType, L.MapModifiers, L.MotionModifiers, L.Components,
9465 GroupCurInfo, GroupStructBaseCurInfo, PartialStruct, AttachInfo,
9466 false, L.IsImplicit,
9467 true, L.Mapper, L.ForDeviceAddr, VD,
9472 if (L.ReturnDevicePointer) {
9476 assert((CurrentBasePointersIdx < GroupCurInfo.BasePointers.size() ||
9477 StructBasePointersIdx <
9478 GroupStructBaseCurInfo.BasePointers.size()) &&
9479 "Unexpected number of mapped base pointers.");
9482 const ValueDecl *RelevantVD =
9483 L.Components.back().getAssociatedDeclaration();
9484 assert(RelevantVD &&
9485 "No relevant declaration related with device pointer??");
9492 auto SetDevicePointerInfo = [&](MapCombinedInfoTy &Info,
9494 Info.DevicePtrDecls[Idx] = RelevantVD;
9495 Info.DevicePointers[Idx] = L.ForDeviceAddr
9496 ? DeviceInfoTy::Address
9497 : DeviceInfoTy::Pointer;
9499 OpenMPOffloadMappingFlags::OMP_MAP_RETURN_PARAM;
9500 if (L.HasUdpFbNullify)
9502 OpenMPOffloadMappingFlags::OMP_MAP_FB_NULLIFY;
9505 if (StructBasePointersIdx <
9506 GroupStructBaseCurInfo.BasePointers.size())
9507 SetDevicePointerInfo(GroupStructBaseCurInfo,
9508 StructBasePointersIdx);
9510 SetDevicePointerInfo(GroupCurInfo, CurrentBasePointersIdx);
9516 MapCombinedInfoTy GroupUnionCurInfo;
9517 GroupUnionCurInfo.append(GroupStructBaseCurInfo);
9518 GroupUnionCurInfo.append(GroupCurInfo);
9522 if (PartialStruct.Base.isValid()) {
9530 GroupUnionCurInfo.NonContigInfo.Dims.insert(
9531 GroupUnionCurInfo.NonContigInfo.Dims.begin(), 1);
9533 CurInfo, GroupUnionCurInfo.Types, PartialStruct, AttachInfo,
9534 !VD, OMPBuilder, VD,
9535 CombinedInfo.BasePointers.size(),
9541 CurInfo.append(GroupUnionCurInfo);
9542 if (AttachInfo.isValid())
9543 emitAttachEntry(CGF, CurInfo, AttachInfo);
9547 CombinedInfo.append(CurInfo);
9550 CombinedInfo.append(UseDeviceDataCombinedInfo);
9554 MappableExprsHandler(
const OMPExecutableDirective &Dir, CodeGenFunction &CGF)
9555 : CurDir(&Dir), CGF(CGF), AttachPtrComparator(*this) {
9557 for (
const auto *
C : Dir.getClausesOfKind<OMPFirstprivateClause>())
9558 for (
const auto *D :
C->varlist()) {
9559 const ValueDecl *VD = cast<DeclRefExpr>(D)->getDecl();
9560 if (const auto *BD = dyn_cast<BindingDecl>(VD))
9561 VD = cast<VarDecl>(BD->getDecomposedDecl());
9562 FirstPrivateDecls.try_emplace(cast<VarDecl>(VD), C->isImplicit());
9565 for (
const auto *
C : Dir.getClausesOfKind<OMPUsesAllocatorsClause>()) {
9566 for (unsigned I = 0, E = C->getNumberOfAllocators(); I < E; ++I) {
9567 OMPUsesAllocatorsClause::Data D = C->getAllocatorData(I);
9568 if (const auto *DRE = dyn_cast_or_null<DeclRefExpr>(D.AllocatorTraits))
9569 FirstPrivateDecls.try_emplace(cast<VarDecl>(DRE->getDecl()),
9571 else if (const auto *VD = dyn_cast<VarDecl>(
9572 cast<DeclRefExpr>(D.Allocator->IgnoreParenImpCasts())
9574 FirstPrivateDecls.try_emplace(VD, true);
9578 for (
const auto *
C : Dir.getClausesOfKind<OMPDefaultmapClause>())
9579 if (
C->getDefaultmapModifier() == OMPC_DEFAULTMAP_MODIFIER_firstprivate)
9580 DefaultmapFirstprivateKinds.insert(
C->getDefaultmapKind());
9582 for (
const auto *
C : Dir.getClausesOfKind<OMPIsDevicePtrClause>())
9583 for (
auto L :
C->component_lists())
9584 DevPointersMap[std::get<0>(L)].push_back(std::get<1>(L));
9586 for (
const auto *
C : Dir.getClausesOfKind<OMPHasDeviceAddrClause>())
9587 for (
auto L :
C->component_lists())
9588 HasDevAddrsMap[std::get<0>(L)].push_back(std::get<1>(L));
9590 for (
const auto *
C : Dir.getClausesOfKind<OMPMapClause>()) {
9591 if (C->getMapType() != OMPC_MAP_to)
9593 for (auto L : C->component_lists()) {
9594 const ValueDecl *VD = std::get<0>(L);
9595 const auto *RD = VD ? VD->getType()
9597 .getNonReferenceType()
9598 ->getAsCXXRecordDecl()
9600 if (RD && RD->isLambda())
9601 LambdasMap.try_emplace(std::get<0>(L), C);
9605 auto CollectAttachPtrExprsForClauseComponents = [
this](
const auto *
C) {
9606 for (
auto L :
C->component_lists()) {
9609 if (!Components.empty())
9610 collectAttachPtrExprInfo(Components, CurDir);
9616 for (
const auto *
C : Dir.getClausesOfKind<OMPMapClause>())
9617 CollectAttachPtrExprsForClauseComponents(
C);
9618 for (
const auto *
C : Dir.getClausesOfKind<OMPToClause>())
9619 CollectAttachPtrExprsForClauseComponents(
C);
9620 for (
const auto *
C : Dir.getClausesOfKind<OMPFromClause>())
9621 CollectAttachPtrExprsForClauseComponents(
C);
9622 for (
const auto *
C : Dir.getClausesOfKind<OMPUseDevicePtrClause>())
9623 CollectAttachPtrExprsForClauseComponents(
C);
9624 for (
const auto *
C : Dir.getClausesOfKind<OMPUseDeviceAddrClause>())
9625 CollectAttachPtrExprsForClauseComponents(
C);
9626 for (
const auto *
C : Dir.getClausesOfKind<OMPIsDevicePtrClause>())
9627 CollectAttachPtrExprsForClauseComponents(
C);
9628 for (
const auto *
C : Dir.getClausesOfKind<OMPHasDeviceAddrClause>())
9629 CollectAttachPtrExprsForClauseComponents(
C);
9633 MappableExprsHandler(
const OMPDeclareMapperDecl &Dir,
CodeGenFunction &CGF)
9634 : CurDir(&Dir), CGF(CGF), AttachPtrComparator(*this) {
9635 auto CollectAttachPtrExprsForClauseComponents = [
this](
const auto *
C) {
9636 for (
auto L :
C->component_lists()) {
9639 if (!Components.empty())
9640 collectAttachPtrExprInfo(Components, CurDir);
9648 if (const auto *C = dyn_cast<OMPMapClause>(Cl))
9649 CollectAttachPtrExprsForClauseComponents(C);
9650 else if (const auto *C = dyn_cast<OMPToClause>(Cl))
9651 CollectAttachPtrExprsForClauseComponents(C);
9652 else if (const auto *C = dyn_cast<OMPFromClause>(Cl))
9653 CollectAttachPtrExprsForClauseComponents(C);
9665 void emitCombinedEntry(MapCombinedInfoTy &CombinedInfo,
9666 MapFlagsArrayTy &CurTypes,
9667 const StructRangeInfoTy &PartialStruct,
9668 AttachInfoTy &AttachInfo,
bool IsMapThis,
9669 llvm::OpenMPIRBuilder &OMPBuilder,
const ValueDecl *VD,
9670 unsigned OffsetForMemberOfFlag,
9671 bool NotTargetParams)
const {
9672 if (CurTypes.size() == 1 &&
9673 ((CurTypes.back() & OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF) !=
9674 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF) &&
9675 !PartialStruct.IsArraySection)
9677 Address LBAddr = PartialStruct.LowestElem.second;
9678 Address HBAddr = PartialStruct.HighestElem.second;
9679 if (PartialStruct.HasCompleteRecord) {
9680 LBAddr = PartialStruct.LB;
9681 HBAddr = PartialStruct.LB;
9683 CombinedInfo.Exprs.push_back(VD);
9685 CombinedInfo.BasePointers.push_back(PartialStruct.Base.emitRawPointer(CGF));
9686 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
9687 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
9690 const CXXMethodDecl *MD =
9692 const CXXRecordDecl *RD = MD ? MD->
getParent() :
nullptr;
9693 bool HasBaseClass = RD && IsMapThis ? RD->
getNumBases() > 0 :
false;
9703 CombinedInfo.Pointers.push_back(PartialStruct.Base.emitRawPointer(CGF));
9708 CombinedInfo.Sizes.push_back(Size);
9710 CombinedInfo.Pointers.push_back(LB);
9713 llvm::Value *HAddr = CGF.
Builder.CreateConstGEP1_32(
9717 llvm::Value *Diff = CGF.
Builder.CreatePtrDiff(CHAddr, CLAddr);
9720 CombinedInfo.Sizes.push_back(Size);
9722 CombinedInfo.Mappers.push_back(
nullptr);
9724 CombinedInfo.Types.push_back(
9725 NotTargetParams ? OpenMPOffloadMappingFlags::OMP_MAP_NONE
9726 : !PartialStruct.PreliminaryMapData.BasePointers.empty()
9727 ? OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ
9728 : OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM);
9736 CombinedInfo.HasAttachPtr.push_back(AttachInfo.isValid());
9739 if (CurTypes.end() !=
9740 llvm::find_if(CurTypes, [](OpenMPOffloadMappingFlags
Type) {
9741 return static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>>(
9742 Type & OpenMPOffloadMappingFlags::OMP_MAP_PRESENT);
9744 CombinedInfo.Types.back() |= OpenMPOffloadMappingFlags::OMP_MAP_PRESENT;
9746 (*CurTypes.begin()) &= ~OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM;
9753 if (CurTypes.end() !=
9754 llvm::find_if(CurTypes, [](OpenMPOffloadMappingFlags
Type) {
9755 return static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>>(
9756 Type & OpenMPOffloadMappingFlags::OMP_MAP_OMPX_HOLD);
9758 CombinedInfo.Types.back() |= OpenMPOffloadMappingFlags::OMP_MAP_OMPX_HOLD;
9759 for (
auto &M : CurTypes)
9760 M |= OpenMPOffloadMappingFlags::OMP_MAP_OMPX_HOLD;
9767 OpenMPOffloadMappingFlags MemberOfFlag = OMPBuilder.getMemberOfFlag(
9768 OffsetForMemberOfFlag + CombinedInfo.BasePointers.size() - 1);
9769 for (
auto &M : CurTypes)
9770 OMPBuilder.setCorrectMemberOfFlag(M, MemberOfFlag);
9787 if (AttachInfo.isValid())
9788 AttachInfo.AttachPteeAddr = LBAddr;
9796 void generateAllInfo(
9797 MapCombinedInfoTy &CombinedInfo, llvm::OpenMPIRBuilder &OMPBuilder,
9798 const llvm::DenseSet<CanonicalDeclPtr<const Decl>> &SkipVarSet =
9799 llvm::DenseSet<CanonicalDeclPtr<const Decl>>())
const {
9801 "Expect a executable directive");
9803 generateAllInfoForClauses(CurExecDir->clauses(), CombinedInfo, OMPBuilder,
9810 void generateAllInfoForMapper(MapCombinedInfoTy &CombinedInfo,
9811 llvm::OpenMPIRBuilder &OMPBuilder)
const {
9813 "Expect a declare mapper directive");
9815 generateAllInfoForClauses(CurMapperDir->clauses(), CombinedInfo,
9820 void generateInfoForLambdaCaptures(
9821 const ValueDecl *VD, llvm::Value *Arg, MapCombinedInfoTy &CombinedInfo,
9822 llvm::DenseMap<llvm::Value *, llvm::Value *> &LambdaPointers)
const {
9830 llvm::DenseMap<const ValueDecl *, FieldDecl *> Captures;
9831 FieldDecl *ThisCapture =
nullptr;
9837 LambdaPointers.try_emplace(ThisLVal.getPointer(CGF),
9838 VDLVal.getPointer(CGF));
9839 CombinedInfo.Exprs.push_back(VD);
9840 CombinedInfo.BasePointers.push_back(ThisLVal.getPointer(CGF));
9841 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
9842 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
9843 CombinedInfo.Pointers.push_back(ThisLValVal.getPointer(CGF));
9844 CombinedInfo.Sizes.push_back(
9847 CombinedInfo.Types.push_back(
9848 OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ |
9849 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL |
9850 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF |
9851 OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT);
9852 CombinedInfo.HasAttachPtr.push_back(
false);
9853 CombinedInfo.Mappers.push_back(
nullptr);
9855 for (
const LambdaCapture &LC : RD->
captures()) {
9856 if (!LC.capturesVariable())
9861 auto It = Captures.find(VD);
9862 assert(It != Captures.end() &&
"Found lambda capture without field.");
9866 LambdaPointers.try_emplace(VarLVal.getPointer(CGF),
9867 VDLVal.getPointer(CGF));
9868 CombinedInfo.Exprs.push_back(VD);
9869 CombinedInfo.BasePointers.push_back(VarLVal.getPointer(CGF));
9870 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
9871 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
9872 CombinedInfo.Pointers.push_back(VarLValVal.getPointer(CGF));
9873 CombinedInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
9879 LambdaPointers.try_emplace(VarLVal.getPointer(CGF),
9880 VDLVal.getPointer(CGF));
9881 CombinedInfo.Exprs.push_back(VD);
9882 CombinedInfo.BasePointers.push_back(VarLVal.getPointer(CGF));
9883 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
9884 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
9885 CombinedInfo.Pointers.push_back(VarRVal.
getScalarVal());
9886 CombinedInfo.Sizes.push_back(llvm::ConstantInt::get(CGF.
Int64Ty, 0));
9888 CombinedInfo.Types.push_back(
9889 OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ |
9890 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL |
9891 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF |
9892 OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT);
9893 CombinedInfo.HasAttachPtr.push_back(
false);
9894 CombinedInfo.Mappers.push_back(
nullptr);
9899 void adjustMemberOfForLambdaCaptures(
9900 llvm::OpenMPIRBuilder &OMPBuilder,
9901 const llvm::DenseMap<llvm::Value *, llvm::Value *> &LambdaPointers,
9902 MapBaseValuesArrayTy &BasePointers, MapValuesArrayTy &Pointers,
9903 MapFlagsArrayTy &Types)
const {
9904 for (
unsigned I = 0, E = Types.size(); I < E; ++I) {
9906 if (Types[I] != (OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ |
9907 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL |
9908 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF |
9909 OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT))
9911 llvm::Value *BasePtr = LambdaPointers.lookup(BasePointers[I]);
9912 assert(BasePtr &&
"Unable to find base lambda address.");
9914 for (
unsigned J = I; J > 0; --J) {
9915 unsigned Idx = J - 1;
9916 if (Pointers[Idx] != BasePtr)
9921 assert(TgtIdx != -1 &&
"Unable to find parent lambda.");
9925 OpenMPOffloadMappingFlags MemberOfFlag =
9926 OMPBuilder.getMemberOfFlag(TgtIdx);
9927 OMPBuilder.setCorrectMemberOfFlag(Types[I], MemberOfFlag);
9933 void populateComponentListsForNonLambdaCaptureFromClauses(
9934 const ValueDecl *VD, MapDataArrayTy &DeclComponentLists,
9936 SmallVector<OMPClauseMappableExprCommon::MappableComponent, 8>>
9937 &StorageForImplicitlyAddedComponentLists)
const {
9938 if (VD && LambdasMap.count(VD))
9944 auto It = DevPointersMap.find(VD);
9945 if (It != DevPointersMap.end())
9946 for (
const auto &MCL : It->second)
9947 DeclComponentLists.emplace_back(MCL, OMPC_MAP_to,
Unknown,
9950 auto I = HasDevAddrsMap.find(VD);
9951 if (I != HasDevAddrsMap.end())
9952 for (
const auto &MCL : I->second)
9953 DeclComponentLists.emplace_back(MCL, OMPC_MAP_tofrom,
Unknown,
9957 "Expect a executable directive");
9959 for (
const auto *
C : CurExecDir->getClausesOfKind<OMPMapClause>()) {
9960 const auto *EI =
C->getVarRefs().begin();
9961 for (
const auto L :
C->decl_component_lists(VD)) {
9962 const ValueDecl *VDecl, *Mapper;
9964 const Expr *E = (
C->getMapLoc().isValid()) ? *EI :
nullptr;
9966 std::tie(VDecl, Components, Mapper) = L;
9967 assert(VDecl == VD &&
"We got information for the wrong declaration??");
9968 assert(!Components.empty() &&
9969 "Not expecting declaration with no component lists.");
9970 DeclComponentLists.emplace_back(Components,
C->getMapType(),
9971 C->getMapTypeModifiers(),
9972 C->isImplicit(), Mapper, E);
9981 addImplicitMapForAttachPtrBaseIfMemberOfCapturedVD(
9982 VD, DeclComponentLists, StorageForImplicitlyAddedComponentLists);
9984 llvm::stable_sort(DeclComponentLists, [](
const MapData &LHS,
9985 const MapData &RHS) {
9986 ArrayRef<OpenMPMapModifierKind> MapModifiers = std::get<2>(LHS);
9989 llvm::is_contained(MapModifiers, clang::OMPC_MAP_MODIFIER_present);
9990 bool HasAllocs = MapType == OMPC_MAP_alloc;
9991 MapModifiers = std::get<2>(RHS);
9992 MapType = std::get<1>(LHS);
9994 llvm::is_contained(MapModifiers, clang::OMPC_MAP_MODIFIER_present);
9995 bool HasAllocsR = MapType == OMPC_MAP_alloc;
9996 return (HasPresent && !HasPresentR) || (HasAllocs && !HasAllocsR);
10032 void addImplicitMapForAttachPtrBaseIfMemberOfCapturedVD(
10033 const ValueDecl *CapturedVD, MapDataArrayTy &DeclComponentLists,
10035 SmallVector<OMPClauseMappableExprCommon::MappableComponent, 8>>
10036 &ComponentVectorStorage)
const {
10037 bool IsThisCapture = CapturedVD ==
nullptr;
10039 for (
const auto &ComponentsAndAttachPtr : AttachPtrExprMap) {
10041 ComponentsWithAttachPtr = ComponentsAndAttachPtr.first;
10042 const Expr *AttachPtrExpr = ComponentsAndAttachPtr.second;
10043 if (!AttachPtrExpr)
10046 const auto *ME = dyn_cast<MemberExpr>(AttachPtrExpr);
10050 const Expr *
Base = ME->getBase()->IgnoreParenImpCasts();
10071 bool FoundExistingMap =
false;
10072 for (
const MapData &ExistingL : DeclComponentLists) {
10074 ExistingComponents = std::get<0>(ExistingL);
10076 if (ExistingComponents.empty())
10080 const auto &FirstComponent = ExistingComponents.front();
10081 const Expr *FirstExpr = FirstComponent.getAssociatedExpression();
10087 if (AttachPtrComparator.areEqual(FirstExpr, AttachPtrExpr)) {
10088 FoundExistingMap =
true;
10093 if (IsThisCapture) {
10094 if (
const auto *OASE = dyn_cast<ArraySectionExpr>(FirstExpr)) {
10096 FoundExistingMap =
true;
10105 if (
const auto *DRE = dyn_cast<DeclRefExpr>(FirstExpr)) {
10106 if (DRE->getDecl() == CapturedVD) {
10107 FoundExistingMap =
true;
10113 if (FoundExistingMap)
10119 ComponentVectorStorage.emplace_back();
10120 auto &AttachPtrComponents = ComponentVectorStorage.back();
10123 bool SeenAttachPtrComponent =
false;
10129 for (
size_t i = 0; i < ComponentsWithAttachPtr.size(); ++i) {
10130 const auto &Component = ComponentsWithAttachPtr[i];
10131 const Expr *ComponentExpr = Component.getAssociatedExpression();
10133 if (!SeenAttachPtrComponent && ComponentExpr != AttachPtrExpr)
10135 SeenAttachPtrComponent =
true;
10137 AttachPtrComponents.emplace_back(Component.getAssociatedExpression(),
10138 Component.getAssociatedDeclaration(),
10139 Component.isNonContiguous());
10141 assert(!AttachPtrComponents.empty() &&
10142 "Could not populate component-lists for mapping attach-ptr");
10144 DeclComponentLists.emplace_back(
10145 AttachPtrComponents, OMPC_MAP_tofrom,
Unknown,
10146 true,
nullptr, AttachPtrExpr);
10153 void generateInfoForCaptureFromClauseInfo(
10154 const MapDataArrayTy &DeclComponentListsFromClauses,
10155 const CapturedStmt::Capture *Cap, llvm::Value *Arg,
10156 MapCombinedInfoTy &CurCaptureVarInfo, llvm::OpenMPIRBuilder &OMPBuilder,
10157 unsigned OffsetForMemberOfFlag)
const {
10159 "Not expecting to generate map info for a variable array type!");
10168 if (LambdasMap.count(VD))
10174 if (VD && (DevPointersMap.count(VD) || HasDevAddrsMap.count(VD))) {
10175 CurCaptureVarInfo.Exprs.push_back(VD);
10176 CurCaptureVarInfo.BasePointers.emplace_back(Arg);
10177 CurCaptureVarInfo.DevicePtrDecls.emplace_back(VD);
10178 CurCaptureVarInfo.DevicePointers.emplace_back(DeviceInfoTy::Pointer);
10179 CurCaptureVarInfo.Pointers.push_back(Arg);
10180 CurCaptureVarInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
10183 CurCaptureVarInfo.Types.push_back(
10184 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL |
10185 OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM);
10186 CurCaptureVarInfo.HasAttachPtr.push_back(
false);
10187 CurCaptureVarInfo.Mappers.push_back(
nullptr);
10191 auto GenerateInfoForComponentLists =
10192 [&](ArrayRef<MapData> DeclComponentListsFromClauses,
10193 bool IsEligibleForTargetParamFlag) {
10194 MapCombinedInfoTy CurInfoForComponentLists;
10195 StructRangeInfoTy PartialStruct;
10196 AttachInfoTy AttachInfo;
10198 if (DeclComponentListsFromClauses.empty())
10201 generateInfoForCaptureFromComponentLists(
10202 VD, DeclComponentListsFromClauses, CurInfoForComponentLists,
10203 PartialStruct, AttachInfo, IsEligibleForTargetParamFlag);
10208 if (PartialStruct.Base.isValid()) {
10209 CurCaptureVarInfo.append(PartialStruct.PreliminaryMapData);
10211 CurCaptureVarInfo, CurInfoForComponentLists.Types,
10212 PartialStruct, AttachInfo, Cap->
capturesThis(), OMPBuilder,
10213 nullptr, OffsetForMemberOfFlag,
10214 !IsEligibleForTargetParamFlag);
10219 CurCaptureVarInfo.append(CurInfoForComponentLists);
10220 if (AttachInfo.isValid())
10221 emitAttachEntry(CGF, CurCaptureVarInfo, AttachInfo);
10245 SmallVector<std::pair<const Expr *, MapData>, 16> AttachPtrMapDataPairs;
10247 for (
const MapData &L : DeclComponentListsFromClauses) {
10250 const Expr *AttachPtrExpr = getAttachPtrExpr(Components);
10251 AttachPtrMapDataPairs.emplace_back(AttachPtrExpr, L);
10255 llvm::stable_sort(AttachPtrMapDataPairs,
10256 [
this](
const auto &LHS,
const auto &RHS) {
10257 return AttachPtrComparator(LHS.first, RHS.first);
10260 bool NoDefaultMappingDoneForVD = CurCaptureVarInfo.BasePointers.empty();
10261 bool IsFirstGroup =
true;
10265 auto *It = AttachPtrMapDataPairs.begin();
10266 while (It != AttachPtrMapDataPairs.end()) {
10267 const Expr *AttachPtrExpr = It->first;
10269 MapDataArrayTy GroupLists;
10270 while (It != AttachPtrMapDataPairs.end() &&
10271 (It->first == AttachPtrExpr ||
10272 AttachPtrComparator.areEqual(It->first, AttachPtrExpr))) {
10273 GroupLists.push_back(It->second);
10276 assert(!GroupLists.empty() &&
"GroupLists should not be empty");
10281 bool IsEligibleForTargetParamFlag =
10282 IsFirstGroup && NoDefaultMappingDoneForVD;
10284 GenerateInfoForComponentLists(GroupLists, IsEligibleForTargetParamFlag);
10285 IsFirstGroup =
false;
10292 void generateInfoForCaptureFromComponentLists(
10293 const ValueDecl *VD, ArrayRef<MapData> DeclComponentLists,
10294 MapCombinedInfoTy &CurComponentListInfo, StructRangeInfoTy &PartialStruct,
10295 AttachInfoTy &AttachInfo,
bool IsListEligibleForTargetParamFlag)
const {
10297 llvm::SmallDenseMap<
10304 for (
const MapData &L : DeclComponentLists) {
10307 ArrayRef<OpenMPMapModifierKind> MapModifiers;
10309 const ValueDecl *Mapper;
10310 const Expr *VarRef;
10311 std::tie(Components, MapType, MapModifiers, IsImplicit, Mapper, VarRef) =
10314 for (
const MapData &L1 : ArrayRef(DeclComponentLists).slice(Count)) {
10316 std::tie(Components1, MapType, MapModifiers, IsImplicit, Mapper,
10318 auto CI = Components.rbegin();
10319 auto CE = Components.rend();
10320 auto SI = Components1.rbegin();
10321 auto SE = Components1.rend();
10322 for (; CI != CE && SI != SE; ++CI, ++SI) {
10323 if (CI->getAssociatedExpression()->getStmtClass() !=
10324 SI->getAssociatedExpression()->getStmtClass())
10327 if (CI->getAssociatedDeclaration() != SI->getAssociatedDeclaration())
10332 if (CI == CE || SI == SE) {
10334 if (CI == CE && SI == SE)
10336 const auto It = (SI == SE) ? CI : SI;
10343 (std::prev(It)->getAssociatedDeclaration() &&
10345 ->getAssociatedDeclaration()
10347 ->isPointerType()) ||
10348 (It->getAssociatedDeclaration() &&
10349 It->getAssociatedDeclaration()->getType()->isPointerType() &&
10350 std::next(It) != CE && std::next(It) != SE))
10352 const MapData &BaseData = CI == CE ? L : L1;
10354 SI == SE ? Components : Components1;
10355 OverlappedData[&BaseData].push_back(SubData);
10360 llvm::SmallVector<const FieldDecl *, 4> Layout;
10361 if (!OverlappedData.empty()) {
10364 while (BaseType != OrigType) {
10370 getPlainLayout(CRD, Layout,
false);
10376 for (
auto &Pair : OverlappedData) {
10383 auto CI = First.rbegin();
10384 auto CE = First.rend();
10385 auto SI = Second.rbegin();
10386 auto SE = Second.rend();
10387 for (; CI != CE && SI != SE; ++CI, ++SI) {
10388 if (CI->getAssociatedExpression()->getStmtClass() !=
10389 SI->getAssociatedExpression()->getStmtClass())
10392 if (CI->getAssociatedDeclaration() !=
10393 SI->getAssociatedDeclaration())
10398 if (CI == CE && SI == SE)
10402 if (CI == CE || SI == SE)
10407 if (FD1->getParent() == FD2->getParent())
10408 return FD1->getFieldIndex() < FD2->getFieldIndex();
10410 llvm::find_if(Layout, [FD1, FD2](
const FieldDecl *FD) {
10411 return FD == FD1 || FD == FD2;
10419 bool AddTargetParamFlag = IsListEligibleForTargetParamFlag;
10420 MapCombinedInfoTy StructBaseCombinedInfo;
10421 for (
const auto &Pair : OverlappedData) {
10422 const MapData &L = *Pair.getFirst();
10425 ArrayRef<OpenMPMapModifierKind> MapModifiers;
10427 const ValueDecl *Mapper;
10428 const Expr *VarRef;
10429 std::tie(Components, MapType, MapModifiers, IsImplicit, Mapper, VarRef) =
10431 ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef>
10432 OverlappedComponents = Pair.getSecond();
10433 generateInfoForComponentList(
10434 MapType, MapModifiers, {}, Components, CurComponentListInfo,
10435 StructBaseCombinedInfo, PartialStruct, AttachInfo, AddTargetParamFlag,
10436 IsImplicit,
false, Mapper,
10437 false, VD, VarRef, OverlappedComponents);
10438 AddTargetParamFlag =
false;
10441 for (
const MapData &L : DeclComponentLists) {
10444 ArrayRef<OpenMPMapModifierKind> MapModifiers;
10446 const ValueDecl *Mapper;
10447 const Expr *VarRef;
10448 std::tie(Components, MapType, MapModifiers, IsImplicit, Mapper, VarRef) =
10450 auto It = OverlappedData.find(&L);
10451 if (It == OverlappedData.end())
10452 generateInfoForComponentList(
10453 MapType, MapModifiers, {}, Components, CurComponentListInfo,
10454 StructBaseCombinedInfo, PartialStruct, AttachInfo,
10455 AddTargetParamFlag, IsImplicit,
false,
10456 Mapper,
false, VD, VarRef,
10458 AddTargetParamFlag =
false;
10464 bool isEffectivelyFirstprivate(
const VarDecl *VD, QualType
Type)
const {
10466 auto I = FirstPrivateDecls.find(VD);
10467 if (I != FirstPrivateDecls.end() && !I->getSecond())
10471 if (DefaultmapFirstprivateKinds.count(OMPC_DEFAULTMAP_scalar)) {
10472 if (
Type->isScalarType())
10477 if (DefaultmapFirstprivateKinds.count(OMPC_DEFAULTMAP_pointer)) {
10478 if (
Type->isAnyPointerType())
10483 if (DefaultmapFirstprivateKinds.count(OMPC_DEFAULTMAP_aggregate)) {
10484 if (
Type->isAggregateType())
10489 return DefaultmapFirstprivateKinds.count(OMPC_DEFAULTMAP_all);
10494 void generateDefaultMapInfo(
const CapturedStmt::Capture &CI,
10495 const FieldDecl &RI, llvm::Value *CV,
10496 MapCombinedInfoTy &CombinedInfo)
const {
10497 bool IsImplicit =
true;
10500 CombinedInfo.Exprs.push_back(
nullptr);
10501 CombinedInfo.BasePointers.push_back(CV);
10502 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
10503 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
10504 CombinedInfo.Pointers.push_back(CV);
10506 CombinedInfo.Sizes.push_back(
10510 CombinedInfo.Types.push_back(OpenMPOffloadMappingFlags::OMP_MAP_TO |
10511 OpenMPOffloadMappingFlags::OMP_MAP_FROM);
10515 CombinedInfo.BasePointers.push_back(CV);
10516 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
10517 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
10518 CombinedInfo.Pointers.push_back(CV);
10519 bool IsFirstprivate =
10525 CombinedInfo.Types.push_back(
10526 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL);
10527 CombinedInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
10529 }
else if (IsFirstprivate) {
10532 CombinedInfo.Types.push_back(
10533 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL);
10535 CombinedInfo.Sizes.push_back(llvm::Constant::getNullValue(CGF.
Int64Ty));
10539 CombinedInfo.Types.push_back(OpenMPOffloadMappingFlags::OMP_MAP_NONE);
10540 CombinedInfo.Sizes.push_back(llvm::Constant::getNullValue(CGF.
Int64Ty));
10542 auto I = FirstPrivateDecls.find(VD);
10543 if (I != FirstPrivateDecls.end())
10544 IsImplicit = I->getSecond();
10550 bool IsFirstprivate = isEffectivelyFirstprivate(VD, ElementType);
10552 CombinedInfo.BasePointers.push_back(CV);
10553 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
10554 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
10557 if (IsFirstprivate && ElementType->isAnyPointerType()) {
10559 CombinedInfo.Pointers.push_back(CV);
10561 CombinedInfo.Sizes.push_back(llvm::Constant::getNullValue(CGF.
Int64Ty));
10562 CombinedInfo.Types.push_back(
10563 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL);
10565 CombinedInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
10570 CombinedInfo.Types.push_back(getMapModifiersForPrivateClauses(CI));
10571 CombinedInfo.Pointers.push_back(CV);
10573 auto I = FirstPrivateDecls.find(VD);
10574 if (I != FirstPrivateDecls.end())
10575 IsImplicit = I->getSecond();
10578 CombinedInfo.Types.back() |=
10579 OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM;
10583 CombinedInfo.Types.back() |= OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT;
10585 CombinedInfo.HasAttachPtr.push_back(
false);
10587 CombinedInfo.Mappers.push_back(
nullptr);
10599 dyn_cast<MemberExpr>(OASE->getBase()->IgnoreParenImpCasts()))
10600 return ME->getMemberDecl();
10606static llvm::Constant *
10608 MappableExprsHandler::MappingExprInfo &MapExprs) {
10611 if (!MapExprs.getMapDecl() && !MapExprs.getMapExpr())
10612 return OMPBuilder.getOrCreateDefaultSrcLocStr(SrcLocStrSize);
10615 if (!MapExprs.getMapDecl() && MapExprs.getMapExpr()) {
10619 Loc = MapExprs.getMapExpr()->getExprLoc();
10621 Loc = MapExprs.getMapDecl()->getLocation();
10624 std::string ExprName;
10625 if (MapExprs.getMapExpr()) {
10627 llvm::raw_string_ostream OS(ExprName);
10628 MapExprs.getMapExpr()->printPretty(OS,
nullptr, P);
10630 ExprName = MapExprs.getMapDecl()->getNameAsString();
10639 return OMPBuilder.getOrCreateSrcLocStr(
FileName, ExprName, PLoc.
getLine(),
10646 CodeGenFunction &CGF, MappableExprsHandler::MapCombinedInfoTy &CombinedInfo,
10648 bool IsNonContiguous =
false,
bool ForEndCall =
false) {
10651 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
10653 InsertPointTy CodeGenIP(CGF.
Builder.GetInsertPoint());
10655 auto DeviceAddrCB = [&](
unsigned int I, llvm::Value *NewDecl) {
10656 if (
const ValueDecl *DevVD = CombinedInfo.DevicePtrDecls[I]) {
10661 auto CustomMapperCB = [&](
unsigned int I) {
10662 llvm::Function *MFunc =
nullptr;
10663 if (CombinedInfo.Mappers[I]) {
10664 Info.HasMapper =
true;
10670 cantFail(OMPBuilder.emitOffloadingArraysAndArgs(
10671 AllocaIP, CodeGenIP, Info, Info.RTArgs, CombinedInfo, CustomMapperCB,
10672 IsNonContiguous, ForEndCall, DeviceAddrCB));
10676static const OMPExecutableDirective *
10678 const auto *CS = D.getInnermostCapturedStmt();
10681 const Stmt *ChildStmt =
10684 if (
const auto *NestedDir =
10685 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) {
10687 switch (D.getDirectiveKind()) {
10693 if (DKind == OMPD_teams) {
10694 Body = NestedDir->getInnermostCapturedStmt()->IgnoreContainers(
10699 if (
const auto *NND =
10700 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) {
10701 DKind = NND->getDirectiveKind();
10707 case OMPD_target_teams:
10711 case OMPD_target_parallel:
10712 case OMPD_target_simd:
10713 case OMPD_target_parallel_for:
10714 case OMPD_target_parallel_for_simd:
10716 case OMPD_target_teams_distribute:
10717 case OMPD_target_teams_distribute_simd:
10718 case OMPD_target_teams_distribute_parallel_for:
10719 case OMPD_target_teams_distribute_parallel_for_simd:
10720 case OMPD_parallel:
10722 case OMPD_parallel_for:
10723 case OMPD_parallel_master:
10724 case OMPD_parallel_sections:
10725 case OMPD_for_simd:
10726 case OMPD_parallel_for_simd:
10728 case OMPD_cancellation_point:
10729 case OMPD_ordered_standalone:
10730 case OMPD_ordered_blockassoc:
10731 case OMPD_threadprivate:
10732 case OMPD_allocate:
10737 case OMPD_sections:
10741 case OMPD_critical:
10742 case OMPD_taskyield:
10744 case OMPD_taskwait:
10745 case OMPD_taskgroup:
10751 case OMPD_target_data:
10752 case OMPD_target_exit_data:
10753 case OMPD_target_enter_data:
10754 case OMPD_distribute:
10755 case OMPD_distribute_simd:
10756 case OMPD_distribute_parallel_for:
10757 case OMPD_distribute_parallel_for_simd:
10758 case OMPD_teams_distribute:
10759 case OMPD_teams_distribute_simd:
10760 case OMPD_teams_distribute_parallel_for:
10761 case OMPD_teams_distribute_parallel_for_simd:
10762 case OMPD_target_update:
10763 case OMPD_declare_simd:
10764 case OMPD_declare_variant:
10765 case OMPD_begin_declare_variant:
10766 case OMPD_end_declare_variant:
10767 case OMPD_declare_target:
10768 case OMPD_end_declare_target:
10769 case OMPD_declare_reduction:
10770 case OMPD_declare_mapper:
10771 case OMPD_taskloop:
10772 case OMPD_taskloop_simd:
10773 case OMPD_master_taskloop:
10774 case OMPD_master_taskloop_simd:
10775 case OMPD_parallel_master_taskloop:
10776 case OMPD_parallel_master_taskloop_simd:
10777 case OMPD_requires:
10778 case OMPD_metadirective:
10781 llvm_unreachable(
"Unexpected directive.");
10841 if (
UDMMap.count(D) > 0)
10845 auto *MapperVarDecl =
10847 CharUnits ElementSize =
C.getTypeSizeInChars(Ty);
10848 llvm::Type *ElemTy =
CGM.getTypes().ConvertTypeForMem(Ty);
10851 MappableExprsHandler::MapCombinedInfoTy CombinedInfo;
10852 auto PrivatizeAndGenMapInfoCB =
10853 [&](llvm::OpenMPIRBuilder::InsertPointTy CodeGenIP, llvm::Value *PtrPHI,
10854 llvm::Value *BeginArg) -> llvm::OpenMPIRBuilder::MapInfosTy & {
10855 MapperCGF.
Builder.restoreIP(CodeGenIP);
10865 Scope.addPrivate(MapperVarDecl, PtrCurrent);
10866 (void)
Scope.Privatize();
10869 MappableExprsHandler MEHandler(*D, MapperCGF);
10870 MEHandler.generateAllInfoForMapper(CombinedInfo,
OMPBuilder);
10872 auto FillInfoMap = [&](MappableExprsHandler::MappingExprInfo &MapExpr) {
10875 if (
CGM.getCodeGenOpts().getDebugInfo() !=
10876 llvm::codegenoptions::NoDebugInfo) {
10877 CombinedInfo.Names.resize(CombinedInfo.Exprs.size());
10878 llvm::transform(CombinedInfo.Exprs, CombinedInfo.Names.begin(),
10882 return CombinedInfo;
10885 auto CustomMapperCB = [&](
unsigned I) {
10886 llvm::Function *MapperFunc =
nullptr;
10887 if (CombinedInfo.Mappers[I]) {
10891 assert(MapperFunc &&
"Expect a valid mapper function is available.");
10897 llvm::raw_svector_ostream Out(TyStr);
10898 CGM.getCXXABI().getMangleContext().mangleCanonicalTypeName(Ty, Out);
10899 std::string Name =
getName({
"omp_mapper", TyStr, D->
getName()});
10905 bool PropagatePresentToPointee =
CGM.getLangOpts().OpenMP >= 60;
10906 llvm::Function *NewFn = cantFail(
OMPBuilder.emitUserDefinedMapper(
10907 PrivatizeAndGenMapInfoCB, ElemTy, Name, CustomMapperCB,
10908 false, PropagatePresentToPointee));
10909 UDMMap.try_emplace(D, NewFn);
10916 auto I =
UDMMap.find(D);
10920 return UDMMap.lookup(D);
10933 Kind != OMPD_target_teams_loop)
10936 return llvm::ConstantInt::get(CGF.
Int64Ty, 0);
10939 if (llvm::Value *NumIterations = SizeEmitter(CGF, *LD))
10940 return NumIterations;
10941 return llvm::ConstantInt::get(CGF.
Int64Ty, 0);
10950 if (OffloadingMandatory) {
10951 CGF.
Builder.CreateUnreachable();
10953 if (RequiresOuterTask) {
10954 CapturedVars.clear();
10958 CapturedVars.end());
10959 Args.push_back(llvm::Constant::getNullValue(CGF.
Builder.getPtrTy()));
10966 llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier>
Device,
10969 llvm::Value *DeviceID;
10970 if (
Device.getPointer()) {
10972 Device.getInt() == OMPC_DEVICE_device_num) &&
10973 "Expected device_num modifier.");
10978 DeviceID = CGF.
Builder.getInt64(OMP_DEVICEID_UNDEF);
10983static std::pair<llvm::Value *, OMPDynGroupprivateFallbackType>
10985 llvm::Value *DynGP = CGF.
Builder.getInt32(0);
10986 auto DynGPFallback = OMPDynGroupprivateFallbackType::Abort;
10990 llvm::Value *DynGPVal =
10994 auto FallbackModifier = DynGPClause->getDynGroupprivateFallbackModifier();
10995 switch (FallbackModifier) {
10996 case OMPC_DYN_GROUPPRIVATE_FALLBACK_abort:
10997 DynGPFallback = OMPDynGroupprivateFallbackType::Abort;
10999 case OMPC_DYN_GROUPPRIVATE_FALLBACK_null:
11000 DynGPFallback = OMPDynGroupprivateFallbackType::Null;
11002 case OMPC_DYN_GROUPPRIVATE_FALLBACK_default_mem:
11005 DynGPFallback = OMPDynGroupprivateFallbackType::DefaultMem;
11008 llvm_unreachable(
"Unknown fallback modifier for OpenMP dyn_groupprivate");
11010 }
else if (
auto *OMPXDynCGClause =
11013 llvm::Value *DynCGMemVal = CGF.
EmitScalarExpr(OMPXDynCGClause->getSize(),
11018 return {DynGP, DynGPFallback};
11024 llvm::OpenMPIRBuilder &OMPBuilder,
11026 MappableExprsHandler::MapCombinedInfoTy &CombinedInfo) {
11028 llvm::DenseMap<llvm::Value *, llvm::Value *> LambdaPointers;
11030 auto *CV = CapturedVars.begin();
11033 CI != CE; ++CI, ++RI, ++CV) {
11034 MappableExprsHandler::MapCombinedInfoTy CurInfo;
11039 CurInfo.Exprs.push_back(
nullptr);
11040 CurInfo.BasePointers.push_back(*CV);
11041 CurInfo.DevicePtrDecls.push_back(
nullptr);
11042 CurInfo.DevicePointers.push_back(
11043 MappableExprsHandler::DeviceInfoTy::None);
11044 CurInfo.Pointers.push_back(*CV);
11045 CurInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
11048 CurInfo.Types.push_back(OpenMPOffloadMappingFlags::OMP_MAP_LITERAL |
11049 OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM |
11050 OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT);
11051 CurInfo.HasAttachPtr.push_back(
false);
11052 CurInfo.Mappers.push_back(
nullptr);
11057 bool HasEntryWithCVAsAttachPtr =
false;
11059 HasEntryWithCVAsAttachPtr =
11060 MEHandler.hasAttachEntryForCapturedVar(CapturedVD);
11063 MappableExprsHandler::MapDataArrayTy DeclComponentLists;
11066 StorageForImplicitlyAddedComponentLists;
11067 MEHandler.populateComponentListsForNonLambdaCaptureFromClauses(
11068 CapturedVD, DeclComponentLists,
11069 StorageForImplicitlyAddedComponentLists);
11080 bool HasEntryWithoutAttachPtr =
11081 llvm::any_of(DeclComponentLists, [&](
const auto &MapData) {
11083 Components = std::get<0>(MapData);
11084 return !MEHandler.getAttachPtrExpr(Components);
11089 if (DeclComponentLists.empty() ||
11090 (!HasEntryWithCVAsAttachPtr && !HasEntryWithoutAttachPtr))
11091 MEHandler.generateDefaultMapInfo(*CI, **RI, *CV, CurInfo);
11095 MEHandler.generateInfoForCaptureFromClauseInfo(
11096 DeclComponentLists, CI, *CV, CurInfo, OMPBuilder,
11097 CombinedInfo.BasePointers.size());
11102 MappedVarSet.insert(
nullptr);
11107 MEHandler.generateInfoForLambdaCaptures(CI->
getCapturedVar(), *CV,
11108 CurInfo, LambdaPointers);
11111 assert(!CurInfo.BasePointers.empty() &&
11112 "Non-existing map pointer for capture!");
11113 assert(CurInfo.BasePointers.size() == CurInfo.Pointers.size() &&
11114 CurInfo.BasePointers.size() == CurInfo.Sizes.size() &&
11115 CurInfo.BasePointers.size() == CurInfo.Types.size() &&
11116 CurInfo.BasePointers.size() == CurInfo.Mappers.size() &&
11117 "Inconsistent map information sizes!");
11120 CombinedInfo.append(CurInfo);
11123 MEHandler.adjustMemberOfForLambdaCaptures(
11124 OMPBuilder, LambdaPointers, CombinedInfo.BasePointers,
11125 CombinedInfo.Pointers, CombinedInfo.Types);
11129 MappableExprsHandler::MapCombinedInfoTy &CombinedInfo,
11130 llvm::OpenMPIRBuilder &OMPBuilder,
11137 MEHandler.generateAllInfo(CombinedInfo, OMPBuilder, SkippedVarSet);
11139 auto FillInfoMap = [&](MappableExprsHandler::MappingExprInfo &MapExpr) {
11143 llvm::codegenoptions::NoDebugInfo) {
11144 CombinedInfo.Names.resize(CombinedInfo.Exprs.size());
11145 llvm::transform(CombinedInfo.Exprs, CombinedInfo.Names.begin(),
11153 llvm::OpenMPIRBuilder &OMPBuilder,
11154 MappableExprsHandler::MapCombinedInfoTy &CombinedInfo) {
11156 MappableExprsHandler MEHandler(D, CGF);
11157 llvm::DenseSet<CanonicalDeclPtr<const Decl>> MappedVarSet;
11160 MappedVarSet, CombinedInfo);
11161 genMapInfo(MEHandler, CGF, CombinedInfo, OMPBuilder, MappedVarSet);
11164template <
typename ClauseTy>
11169 const auto *
C = D.getSingleClause<ClauseTy>();
11170 assert(!
C->varlist_empty() &&
11171 "ompx_bare requires explicit num_teams and thread_limit");
11173 for (
auto *E :
C->varlist()) {
11185 llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier>
Device,
11187 llvm::Value *&MapTypesArray, llvm::Value *&MapNamesArray,
11192 llvm::OpenMPIRBuilder &OMPBuilder = OMPRuntime->
getOMPBuilder();
11195 MappableExprsHandler::MapCombinedInfoTy CombinedInfo;
11197 genMapInfo(D, CGF, CS, CapturedVars, OMPBuilder, CombinedInfo);
11200 using OpenMPOffloadMappingFlags = llvm::omp::OpenMPOffloadMappingFlags;
11201 auto *NullPtr = llvm::Constant::getNullValue(CGF.
Builder.getPtrTy());
11202 CombinedInfo.BasePointers.push_back(NullPtr);
11203 CombinedInfo.Pointers.push_back(NullPtr);
11204 CombinedInfo.DevicePointers.push_back(
11205 llvm::OpenMPIRBuilder::DeviceInfoTy::None);
11206 CombinedInfo.Sizes.push_back(CGF.
Builder.getInt64(0));
11207 CombinedInfo.Types.push_back(OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM |
11208 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL);
11209 CombinedInfo.HasAttachPtr.push_back(
false);
11210 if (!CombinedInfo.Names.empty())
11211 CombinedInfo.Names.push_back(NullPtr);
11212 CombinedInfo.Exprs.push_back(
nullptr);
11213 CombinedInfo.Mappers.push_back(
nullptr);
11214 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
11228 MapTypesArray = Info.RTArgs.MapTypesArray;
11229 MapNamesArray = Info.RTArgs.MapNamesArray;
11231 auto &&ThenGen = [&OMPRuntime, OutlinedFn, &D, &CapturedVars,
11232 RequiresOuterTask, &CS, OffloadingMandatory,
Device,
11233 OutlinedFnID, &InputInfo, &MapTypesArray, &MapNamesArray,
11235 bool IsReverseOffloading =
Device.getInt() == OMPC_DEVICE_ancestor;
11237 if (IsReverseOffloading) {
11243 RequiresOuterTask, CS, OffloadingMandatory, CGF);
11247 bool HasNoWait = D.hasClausesOfKind<OMPNowaitClause>();
11248 unsigned NumTargetItems = InputInfo.NumberOfTargetItems;
11250 llvm::Value *BasePointersArray =
11251 InputInfo.BasePointersArray.emitRawPointer(CGF);
11252 llvm::Value *PointersArray = InputInfo.PointersArray.emitRawPointer(CGF);
11253 llvm::Value *SizesArray = InputInfo.SizesArray.emitRawPointer(CGF);
11254 llvm::Value *MappersArray = InputInfo.MappersArray.emitRawPointer(CGF);
11256 auto &&EmitTargetCallFallbackCB =
11257 [&OMPRuntime, OutlinedFn, &D, &CapturedVars, RequiresOuterTask, &CS,
11258 OffloadingMandatory, &CGF](llvm::OpenMPIRBuilder::InsertPointTy IP)
11259 -> llvm::OpenMPIRBuilder::InsertPointTy {
11262 RequiresOuterTask, CS, OffloadingMandatory, CGF);
11275 NumThreads.push_back(
11281 llvm::Value *NumIterations =
11284 llvm::OpenMPIRBuilder::InsertPointTy AllocaIP(
11287 llvm::OpenMPIRBuilder::TargetDataRTArgs RTArgs(
11288 BasePointersArray, PointersArray, SizesArray, MapTypesArray,
11289 nullptr , MappersArray, MapNamesArray);
11291 llvm::OpenMPIRBuilder::TargetKernelArgs Args(
11292 NumTargetItems, RTArgs, NumIterations, NumTeams, NumThreads,
11293 DynCGroupMem, HasNoWait, IsBare,
11294 IsBare, DynCGroupMemFallback);
11296 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
11298 CGF.
Builder, OutlinedFnID, EmitTargetCallFallbackCB, Args, DeviceID,
11300 CGF.
Builder.restoreIP(AfterIP);
11303 if (RequiresOuterTask)
11318 [&OMPRuntime, OutlinedFn, &D, &CapturedVars, RequiresOuterTask, &CS,
11321 RequiresOuterTask, CS, OffloadingMandatory, CGF);
11324 if (RequiresOuterTask) {
11334 llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID,
const Expr *IfCond,
11335 llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier>
Device,
11342 const bool OffloadingMandatory = !
CGM.getLangOpts().OpenMPIsTargetDevice &&
11343 CGM.getLangOpts().OpenMPOffloadMandatory;
11345 assert((OffloadingMandatory || OutlinedFn) &&
"Invalid outlined function!");
11347 const bool RequiresOuterTask =
11349 D.hasClausesOfKind<OMPNowaitClause>() ||
11350 D.hasClausesOfKind<OMPInReductionClause>() ||
11351 (
CGM.getLangOpts().OpenMP >= 51 &&
11355 const CapturedStmt &CS = *D.getCapturedStmt(OMPD_target);
11363 llvm::Value *MapTypesArray =
nullptr;
11364 llvm::Value *MapNamesArray =
nullptr;
11366 auto &&TargetThenGen = [
this, OutlinedFn, &D, &CapturedVars,
11367 RequiresOuterTask, &CS, OffloadingMandatory,
Device,
11368 OutlinedFnID, &InputInfo, &MapTypesArray,
11372 RequiresOuterTask, CS, OffloadingMandatory,
11373 Device, OutlinedFnID, InputInfo, MapTypesArray,
11374 MapNamesArray, SizeEmitter, CGF,
CGM);
11377 auto &&TargetElseGen =
11378 [
this, OutlinedFn, &D, &CapturedVars, RequiresOuterTask, &CS,
11381 CS, OffloadingMandatory, CGF);
11388 if (OutlinedFnID) {
11390 emitIfClause(CGF, IfCond, TargetThenGen, TargetElseGen);
11402 StringRef ParentName) {
11409 if (
auto *E = dyn_cast<OMPExecutableDirective>(S);
11418 bool RequiresDeviceCodegen =
11423 if (RequiresDeviceCodegen) {
11431 if (!
OMPBuilder.OffloadInfoManager.hasTargetRegionEntryInfo(EntryInfo))
11434 switch (E.getDirectiveKind()) {
11439 case OMPD_target_parallel:
11443 case OMPD_target_teams:
11447 case OMPD_target_teams_distribute:
11451 case OMPD_target_teams_distribute_simd:
11455 case OMPD_target_parallel_for:
11459 case OMPD_target_parallel_for_simd:
11463 case OMPD_target_simd:
11467 case OMPD_target_teams_distribute_parallel_for:
11472 case OMPD_target_teams_distribute_parallel_for_simd:
11478 case OMPD_target_teams_loop:
11482 case OMPD_target_parallel_loop:
11486 case OMPD_parallel:
11488 case OMPD_parallel_for:
11489 case OMPD_parallel_master:
11490 case OMPD_parallel_sections:
11491 case OMPD_for_simd:
11492 case OMPD_parallel_for_simd:
11494 case OMPD_cancellation_point:
11495 case OMPD_ordered_standalone:
11496 case OMPD_ordered_blockassoc:
11497 case OMPD_threadprivate:
11498 case OMPD_allocate:
11503 case OMPD_sections:
11507 case OMPD_critical:
11508 case OMPD_taskyield:
11510 case OMPD_taskwait:
11511 case OMPD_taskgroup:
11517 case OMPD_target_data:
11518 case OMPD_target_exit_data:
11519 case OMPD_target_enter_data:
11520 case OMPD_distribute:
11521 case OMPD_distribute_simd:
11522 case OMPD_distribute_parallel_for:
11523 case OMPD_distribute_parallel_for_simd:
11524 case OMPD_teams_distribute:
11525 case OMPD_teams_distribute_simd:
11526 case OMPD_teams_distribute_parallel_for:
11527 case OMPD_teams_distribute_parallel_for_simd:
11528 case OMPD_target_update:
11529 case OMPD_declare_simd:
11530 case OMPD_declare_variant:
11531 case OMPD_begin_declare_variant:
11532 case OMPD_end_declare_variant:
11533 case OMPD_declare_target:
11534 case OMPD_end_declare_target:
11535 case OMPD_declare_reduction:
11536 case OMPD_declare_mapper:
11537 case OMPD_taskloop:
11538 case OMPD_taskloop_simd:
11539 case OMPD_master_taskloop:
11540 case OMPD_master_taskloop_simd:
11541 case OMPD_parallel_master_taskloop:
11542 case OMPD_parallel_master_taskloop_simd:
11543 case OMPD_requires:
11544 case OMPD_metadirective:
11547 llvm_unreachable(
"Unknown target directive for OpenMP device codegen.");
11552 if (
const auto *E = dyn_cast<OMPExecutableDirective>(S)) {
11553 if (!E->hasAssociatedStmt() || !E->getAssociatedStmt())
11561 if (
const auto *L = dyn_cast<LambdaExpr>(S))
11570 std::optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
11571 OMPDeclareTargetDeclAttr::getDeviceType(VD);
11575 if (!IsDevice && DevTy == OMPDeclareTargetDeclAttr::DT_NoHost)
11578 if (IsDevice && DevTy == OMPDeclareTargetDeclAttr::DT_Host)
11586 if (!
CGM.getLangOpts().OpenMPIsTargetDevice) {
11587 if (
const auto *FD = dyn_cast<FunctionDecl>(GD.
getDecl()))
11589 CGM.getLangOpts().OpenMPIsTargetDevice))
11596 if (
const auto *FD = dyn_cast<FunctionDecl>(VD)) {
11597 StringRef Name =
CGM.getMangledName(GD);
11600 CGM.getLangOpts().OpenMPIsTargetDevice))
11605 return !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD) &&
11611 CGM.getLangOpts().OpenMPIsTargetDevice))
11614 if (!
CGM.getLangOpts().OpenMPIsTargetDevice)
11623 StringRef ParentName =
11628 StringRef ParentName =
11635 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
11636 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(
11638 if (!Res || *Res == OMPDeclareTargetDeclAttr::MT_Link ||
11639 ((*Res == OMPDeclareTargetDeclAttr::MT_To ||
11640 *Res == OMPDeclareTargetDeclAttr::MT_Enter) &&
11649 llvm::Constant *
Addr) {
11650 if (
CGM.getLangOpts().OMPTargetTriples.empty() &&
11651 !
CGM.getLangOpts().OpenMPIsTargetDevice)
11654 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
11655 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
11659 if (Res && *Res != OMPDeclareTargetDeclAttr::MT_Link &&
11665 if (Res && *Res == OMPDeclareTargetDeclAttr::MT_Local)
11669 if (
CGM.getLangOpts().OpenMPIsTargetDevice) {
11672 StringRef VarName =
CGM.getMangledName(VD);
11678 auto AddrOfGlobal = [&VD,
this]() {
return CGM.GetAddrOfGlobal(VD); };
11679 auto LinkageForVariable = [&VD,
this]() {
11680 return CGM.getLLVMLinkageVarDefinition(VD);
11683 std::vector<llvm::GlobalVariable *> GeneratedRefs;
11690 CGM.getMangledName(VD), GeneratedRefs,
CGM.getLangOpts().OpenMPSimd,
11691 CGM.getLangOpts().OMPTargetTriples, AddrOfGlobal, LinkageForVariable,
11692 CGM.getTypes().ConvertTypeForMem(
11693 CGM.getContext().getPointerType(VD->
getType())),
11696 for (
auto *ref : GeneratedRefs)
11697 CGM.addCompilerUsedGlobal(ref);
11710 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
11711 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
11715 if (*Res == OMPDeclareTargetDeclAttr::MT_Local ||
11716 ((*Res == OMPDeclareTargetDeclAttr::MT_To ||
11717 *Res == OMPDeclareTargetDeclAttr::MT_Enter) &&
11719 CGM.EmitGlobal(VD);
11721 assert((*Res == OMPDeclareTargetDeclAttr::MT_Link ||
11722 ((*Res == OMPDeclareTargetDeclAttr::MT_To ||
11723 *Res == OMPDeclareTargetDeclAttr::MT_Enter ||
11724 *Res == OMPDeclareTargetDeclAttr::MT_Local) &&
11726 "Expected link clause or to clause with unified memory.");
11727 (void)
CGM.getOpenMPRuntime().getAddrOfDeclareTargetVar(VD);
11735 " Expected target-based directive.");
11740 if (Clause->getClauseKind() == OMPC_unified_shared_memory) {
11742 OMPBuilder.Config.setHasRequiresUnifiedSharedMemory(
true);
11743 }
else if (
const auto *AC =
11744 dyn_cast<OMPAtomicDefaultMemOrderClause>(Clause)) {
11745 switch (AC->getAtomicDefaultMemOrderKind()) {
11746 case OMPC_ATOMIC_DEFAULT_MEM_ORDER_acq_rel:
11749 case OMPC_ATOMIC_DEFAULT_MEM_ORDER_seq_cst:
11752 case OMPC_ATOMIC_DEFAULT_MEM_ORDER_relaxed:
11768 if (!VD || !VD->
hasAttr<OMPAllocateDeclAttr>())
11770 const auto *A = VD->
getAttr<OMPAllocateDeclAttr>();
11771 switch(A->getAllocatorType()) {
11772 case OMPAllocateDeclAttr::OMPNullMemAlloc:
11773 case OMPAllocateDeclAttr::OMPDefaultMemAlloc:
11775 case OMPAllocateDeclAttr::OMPLargeCapMemAlloc:
11776 case OMPAllocateDeclAttr::OMPCGroupMemAlloc:
11777 case OMPAllocateDeclAttr::OMPHighBWMemAlloc:
11778 case OMPAllocateDeclAttr::OMPLowLatMemAlloc:
11779 case OMPAllocateDeclAttr::OMPThreadMemAlloc:
11780 case OMPAllocateDeclAttr::OMPConstMemAlloc:
11781 case OMPAllocateDeclAttr::OMPPTeamMemAlloc:
11784 case OMPAllocateDeclAttr::OMPUserDefinedMemAlloc:
11785 llvm_unreachable(
"Expected predefined allocator for the variables with the "
11786 "static storage.");
11798 if (CGM.getLangOpts().OpenMPIsTargetDevice) {
11799 SavedShouldMarkAsGlobal = CGM.getOpenMPRuntime().ShouldMarkAsGlobal;
11800 CGM.getOpenMPRuntime().ShouldMarkAsGlobal = false;
11805 if (CGM.getLangOpts().OpenMPIsTargetDevice)
11806 CGM.getOpenMPRuntime().ShouldMarkAsGlobal = SavedShouldMarkAsGlobal;
11816 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(D)) {
11818 if (
auto *F = dyn_cast_or_null<llvm::Function>(
11819 CGM.GetGlobalValue(
CGM.getMangledName(GD))))
11820 return !F->isDeclaration();
11832 llvm::Function *OutlinedFn,
11841 llvm::Value *Args[] = {
11843 CGF.
Builder.getInt32(CapturedVars.size()),
11846 RealArgs.append(std::begin(Args), std::end(Args));
11847 RealArgs.append(CapturedVars.begin(), CapturedVars.end());
11849 llvm::FunctionCallee RTLFn =
OMPBuilder.getOrCreateRuntimeFunction(
11850 CGM.getModule(), OMPRTL___kmpc_fork_teams);
11855 const Expr *NumTeams,
11856 const Expr *ThreadLimit,
11863 llvm::Value *NumTeamsVal =
11869 llvm::Value *ThreadLimitVal =
11876 llvm::Value *PushNumTeamsArgs[] = {RTLoc,
getThreadID(CGF, Loc), NumTeamsVal,
11879 CGM.getModule(), OMPRTL___kmpc_push_num_teams),
11884 const Expr *ThreadLimit,
11887 llvm::Value *ThreadLimitVal =
11894 llvm::Value *ThreadLimitArgs[] = {RTLoc,
getThreadID(CGF, Loc),
11897 CGM.getModule(), OMPRTL___kmpc_set_thread_limit),
11912 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
11914 llvm::Value *IfCondVal =
nullptr;
11919 llvm::Value *DeviceID =
nullptr;
11924 DeviceID = CGF.
Builder.getInt64(OMP_DEVICEID_UNDEF);
11928 MappableExprsHandler::MapCombinedInfoTy CombinedInfo;
11929 auto GenMapInfoCB =
11930 [&](InsertPointTy CodeGenIP) -> llvm::OpenMPIRBuilder::MapInfosTy & {
11931 CGF.
Builder.restoreIP(CodeGenIP);
11933 MappableExprsHandler MEHandler(D, CGF);
11934 MEHandler.generateAllInfo(CombinedInfo,
OMPBuilder);
11936 auto FillInfoMap = [&](MappableExprsHandler::MappingExprInfo &MapExpr) {
11939 if (
CGM.getCodeGenOpts().getDebugInfo() !=
11940 llvm::codegenoptions::NoDebugInfo) {
11941 CombinedInfo.Names.resize(CombinedInfo.Exprs.size());
11942 llvm::transform(CombinedInfo.Exprs, CombinedInfo.Names.begin(),
11946 return CombinedInfo;
11948 using BodyGenTy = llvm::OpenMPIRBuilder::BodyGenTy;
11949 auto BodyCB = [&](InsertPointTy CodeGenIP, BodyGenTy BodyGenType) {
11950 CGF.
Builder.restoreIP(CodeGenIP);
11951 switch (BodyGenType) {
11952 case BodyGenTy::Priv:
11956 case BodyGenTy::DupNoPriv:
11958 CodeGen.setAction(NoPrivAction);
11962 case BodyGenTy::NoPriv:
11964 CodeGen.setAction(NoPrivAction);
11969 return InsertPointTy(CGF.
Builder.GetInsertPoint());
11972 auto DeviceAddrCB = [&](
unsigned int I, llvm::Value *NewDecl) {
11973 if (
const ValueDecl *DevVD = CombinedInfo.DevicePtrDecls[I]) {
11978 auto CustomMapperCB = [&](
unsigned int I) {
11979 llvm::Function *MFunc =
nullptr;
11980 if (CombinedInfo.Mappers[I]) {
11981 Info.HasMapper =
true;
11992 InsertPointTy CodeGenIP(CGF.
Builder.GetInsertPoint());
11993 llvm::OpenMPIRBuilder::LocationDescription OmpLoc(CGF.
Builder);
11994 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
11996 OmpLoc, AllocaIP, CodeGenIP, {}, DeviceID,
11997 IfCondVal, Info, GenMapInfoCB, CustomMapperCB,
11998 nullptr, BodyCB, DeviceAddrCB, RTLoc));
11999 CGF.
Builder.restoreIP(AfterIP);
12011 "Expecting either target enter, exit data, or update directives.");
12014 llvm::Value *MapTypesArray =
nullptr;
12015 llvm::Value *MapNamesArray =
nullptr;
12017 auto &&ThenGen = [
this, &D,
Device, &InputInfo, &MapTypesArray,
12020 llvm::Value *DeviceID =
nullptr;
12025 DeviceID = CGF.
Builder.getInt64(OMP_DEVICEID_UNDEF);
12029 llvm::Constant *PointerNum =
12036 {RTLoc, DeviceID, PointerNum,
12044 const bool HasNowait = D.hasClausesOfKind<OMPNowaitClause>();
12045 RuntimeFunction RTLFn;
12046 switch (D.getDirectiveKind()) {
12047 case OMPD_target_enter_data:
12048 RTLFn = HasNowait ? OMPRTL___tgt_target_data_begin_nowait_mapper
12049 : OMPRTL___tgt_target_data_begin_mapper;
12051 case OMPD_target_exit_data:
12052 RTLFn = HasNowait ? OMPRTL___tgt_target_data_end_nowait_mapper
12053 : OMPRTL___tgt_target_data_end_mapper;
12055 case OMPD_target_update:
12056 RTLFn = HasNowait ? OMPRTL___tgt_target_data_update_nowait_mapper
12057 : OMPRTL___tgt_target_data_update_mapper;
12059 case OMPD_parallel:
12061 case OMPD_parallel_for:
12062 case OMPD_parallel_master:
12063 case OMPD_parallel_sections:
12064 case OMPD_for_simd:
12065 case OMPD_parallel_for_simd:
12067 case OMPD_cancellation_point:
12068 case OMPD_ordered_standalone:
12069 case OMPD_ordered_blockassoc:
12070 case OMPD_threadprivate:
12071 case OMPD_allocate:
12076 case OMPD_sections:
12080 case OMPD_critical:
12081 case OMPD_taskyield:
12083 case OMPD_taskwait:
12084 case OMPD_taskgroup:
12090 case OMPD_target_data:
12091 case OMPD_distribute:
12092 case OMPD_distribute_simd:
12093 case OMPD_distribute_parallel_for:
12094 case OMPD_distribute_parallel_for_simd:
12095 case OMPD_teams_distribute:
12096 case OMPD_teams_distribute_simd:
12097 case OMPD_teams_distribute_parallel_for:
12098 case OMPD_teams_distribute_parallel_for_simd:
12099 case OMPD_declare_simd:
12100 case OMPD_declare_variant:
12101 case OMPD_begin_declare_variant:
12102 case OMPD_end_declare_variant:
12103 case OMPD_declare_target:
12104 case OMPD_end_declare_target:
12105 case OMPD_declare_reduction:
12106 case OMPD_declare_mapper:
12107 case OMPD_taskloop:
12108 case OMPD_taskloop_simd:
12109 case OMPD_master_taskloop:
12110 case OMPD_master_taskloop_simd:
12111 case OMPD_parallel_master_taskloop:
12112 case OMPD_parallel_master_taskloop_simd:
12114 case OMPD_target_simd:
12115 case OMPD_target_teams_distribute:
12116 case OMPD_target_teams_distribute_simd:
12117 case OMPD_target_teams_distribute_parallel_for:
12118 case OMPD_target_teams_distribute_parallel_for_simd:
12119 case OMPD_target_teams:
12120 case OMPD_target_parallel:
12121 case OMPD_target_parallel_for:
12122 case OMPD_target_parallel_for_simd:
12123 case OMPD_requires:
12124 case OMPD_metadirective:
12127 llvm_unreachable(
"Unexpected standalone target data directive.");
12131 OffloadingArgs.push_back(llvm::Constant::getNullValue(CGF.
Int32Ty));
12132 OffloadingArgs.push_back(llvm::Constant::getNullValue(CGF.
VoidPtrTy));
12133 OffloadingArgs.push_back(llvm::Constant::getNullValue(CGF.
Int32Ty));
12134 OffloadingArgs.push_back(llvm::Constant::getNullValue(CGF.
VoidPtrTy));
12137 OMPBuilder.getOrCreateRuntimeFunction(
CGM.getModule(), RTLFn),
12141 auto &&TargetThenGen = [
this, &ThenGen, &D, &InputInfo, &MapTypesArray,
12145 MappableExprsHandler::MapCombinedInfoTy CombinedInfo;
12147 MappableExprsHandler MEHandler(D, CGF);
12153 D.hasClausesOfKind<OMPNowaitClause>();
12159 CGM.getPointerAlign());
12164 MapTypesArray = Info.RTArgs.MapTypesArray;
12165 MapNamesArray = Info.RTArgs.MapNamesArray;
12166 if (RequiresOuterTask)
12211 unsigned Offset = 0;
12212 if (
const auto *MD = dyn_cast<CXXMethodDecl>(FD)) {
12213 if (ParamAttrs[Offset].Kind ==
12214 llvm::OpenMPIRBuilder::DeclareSimdKindTy::Vector)
12215 CDT =
C.getPointerType(
C.getCanonicalTagType(MD->
getParent()));
12219 for (
unsigned I = 0, E = FD->
getNumParams(); I < E; ++I) {
12220 if (ParamAttrs[I + Offset].Kind ==
12221 llvm::OpenMPIRBuilder::DeclareSimdKindTy::Vector) {
12233 return C.getTypeSize(CDT);
12244 llvm::OpenMPIRBuilder::DeclareSimdKindTy Kind) {
12250 if (Kind == llvm::OpenMPIRBuilder::DeclareSimdKindTy::Uniform)
12253 if (Kind == llvm::OpenMPIRBuilder::DeclareSimdKindTy::LinearUVal ||
12254 Kind == llvm::OpenMPIRBuilder::DeclareSimdKindTy::LinearRef)
12257 if ((Kind == llvm::OpenMPIRBuilder::DeclareSimdKindTy::Linear ||
12258 Kind == llvm::OpenMPIRBuilder::DeclareSimdKindTy::LinearVal) &&
12268 unsigned Size =
C.getTypeSize(QT);
12271 if (Size != 8 && Size != 16 && Size != 32 && Size != 64 && Size != 128)
12292 llvm::OpenMPIRBuilder::DeclareSimdKindTy Kind,
12297 return C.getTypeSize(PTy);
12300 return C.getTypeSize(QT);
12302 return C.getTypeSize(
C.getUIntPtrType());
12308static std::tuple<unsigned, unsigned, bool>
12315 bool OutputBecomesInput =
false;
12320 RetType, llvm::OpenMPIRBuilder::DeclareSimdKindTy::Vector,
C));
12322 OutputBecomesInput =
true;
12324 for (
unsigned I = 0, E = FD->
getNumParams(); I < E; ++I) {
12329 assert(!Sizes.empty() &&
"Unable to determine NDS and WDS.");
12332 assert(llvm::all_of(Sizes,
12333 [](
unsigned Size) {
12334 return Size == 8 || Size == 16 || Size == 32 ||
12335 Size == 64 || Size == 128;
12339 return std::make_tuple(*llvm::min_element(Sizes), *llvm::max_element(Sizes),
12340 OutputBecomesInput);
12343static llvm::OpenMPIRBuilder::DeclareSimdBranch
12346 case OMPDeclareSimdDeclAttr::BS_Undefined:
12347 return llvm::OpenMPIRBuilder::DeclareSimdBranch::Undefined;
12348 case OMPDeclareSimdDeclAttr::BS_Inbranch:
12349 return llvm::OpenMPIRBuilder::DeclareSimdBranch::Inbranch;
12350 case OMPDeclareSimdDeclAttr::BS_Notinbranch:
12351 return llvm::OpenMPIRBuilder::DeclareSimdBranch::Notinbranch;
12353 llvm_unreachable(
"unexpected declare simd branch state");
12358 unsigned UserVLEN,
unsigned WDS,
char ISA) {
12360 if (UserVLEN == 1) {
12367 if (ISA ==
'n' && UserVLEN && !llvm::isPowerOf2_32(UserVLEN)) {
12373 if (ISA ==
's' && UserVLEN != 0 &&
12374 ((UserVLEN * WDS > 2048) || (UserVLEN * WDS % 128 != 0))) {
12383 llvm::Function *Fn) {
12388 llvm::DenseMap<const Decl *, unsigned> ParamPositions;
12390 ParamPositions.try_emplace(FD, 0);
12391 unsigned ParamPos = ParamPositions.size();
12393 ParamPositions.try_emplace(P->getCanonicalDecl(), ParamPos);
12398 ParamPositions.size());
12400 for (
const Expr *E :
Attr->uniforms()) {
12404 Pos = ParamPositions[FD];
12407 ->getCanonicalDecl();
12408 auto It = ParamPositions.find(PVD);
12409 assert(It != ParamPositions.end() &&
"Function parameter not found");
12412 ParamAttrs[Pos].Kind =
12413 llvm::OpenMPIRBuilder::DeclareSimdKindTy::Uniform;
12416 auto *NI =
Attr->alignments_begin();
12417 for (
const Expr *E :
Attr->aligneds()) {
12422 Pos = ParamPositions[FD];
12426 ->getCanonicalDecl();
12427 auto It = ParamPositions.find(PVD);
12428 assert(It != ParamPositions.end() &&
"Function parameter not found");
12430 ParmTy = PVD->getType();
12432 ParamAttrs[Pos].Alignment =
12434 ? (*NI)->EvaluateKnownConstInt(
C)
12435 : llvm::APSInt::getUnsigned(
12436 C.toCharUnitsFromBits(
C.getOpenMPDefaultSimdAlign(ParmTy))
12441 auto *SI =
Attr->steps_begin();
12442 auto *MI =
Attr->modifiers_begin();
12443 for (
const Expr *E :
Attr->linears()) {
12446 bool IsReferenceType =
false;
12449 unsigned PtrRescalingFactor = 1;
12451 Pos = ParamPositions[FD];
12453 PtrRescalingFactor =
CGM.getContext()
12454 .getTypeSizeInChars(P->getPointeeType())
12458 ->getCanonicalDecl();
12459 auto It = ParamPositions.find(PVD);
12460 assert(It != ParamPositions.end() &&
"Function parameter not found");
12462 if (
auto *P = dyn_cast<PointerType>(PVD->getType()))
12463 PtrRescalingFactor =
CGM.getContext()
12464 .getTypeSizeInChars(P->getPointeeType())
12466 else if (PVD->getType()->isReferenceType()) {
12467 IsReferenceType =
true;
12468 PtrRescalingFactor =
12470 .getTypeSizeInChars(PVD->getType().getNonReferenceType())
12474 llvm::OpenMPIRBuilder::DeclareSimdAttrTy &ParamAttr = ParamAttrs[Pos];
12475 if (*MI == OMPC_LINEAR_ref)
12476 ParamAttr.Kind = llvm::OpenMPIRBuilder::DeclareSimdKindTy::LinearRef;
12477 else if (*MI == OMPC_LINEAR_uval)
12478 ParamAttr.Kind = llvm::OpenMPIRBuilder::DeclareSimdKindTy::LinearUVal;
12479 else if (IsReferenceType)
12480 ParamAttr.Kind = llvm::OpenMPIRBuilder::DeclareSimdKindTy::LinearVal;
12482 ParamAttr.Kind = llvm::OpenMPIRBuilder::DeclareSimdKindTy::Linear;
12484 ParamAttr.StrideOrArg = llvm::APSInt::getUnsigned(1);
12488 if (
const auto *DRE =
12490 if (
const auto *StridePVD =
12491 dyn_cast<ParmVarDecl>(DRE->getDecl())) {
12492 ParamAttr.HasVarStride =
true;
12493 auto It = ParamPositions.find(StridePVD->getCanonicalDecl());
12494 assert(It != ParamPositions.end() &&
12495 "Function parameter not found");
12496 ParamAttr.StrideOrArg = llvm::APSInt::getUnsigned(It->second);
12500 ParamAttr.StrideOrArg =
Result.Val.getInt();
12506 if (!ParamAttr.HasVarStride &&
12508 llvm::OpenMPIRBuilder::DeclareSimdKindTy::Linear ||
12510 llvm::OpenMPIRBuilder::DeclareSimdKindTy::LinearRef))
12511 ParamAttr.StrideOrArg = ParamAttr.StrideOrArg * PtrRescalingFactor;
12515 llvm::APSInt VLENVal;
12517 const Expr *VLENExpr =
Attr->getSimdlen();
12522 llvm::OpenMPIRBuilder::DeclareSimdBranch State =
12524 if (
CGM.getTriple().isX86()) {
12526 assert(NumElts &&
"Non-zero simdlen/cdtsize expected");
12527 OMPBuilder.emitX86DeclareSimdFunction(Fn, NumElts, VLENVal, ParamAttrs,
12529 }
else if (
CGM.getTriple().getArch() == llvm::Triple::aarch64) {
12530 unsigned VLEN = VLENVal.getExtValue();
12533 const unsigned NDS = std::get<0>(
Data);
12534 const unsigned WDS = std::get<1>(
Data);
12535 const bool OutputBecomesInput = std::get<2>(
Data);
12536 if (
CGM.getTarget().hasFeature(
"sve")) {
12539 Fn, VLEN, ParamAttrs, State,
's', NDS, OutputBecomesInput);
12540 }
else if (
CGM.getTarget().hasFeature(
"neon")) {
12543 Fn, VLEN, ParamAttrs, State,
'n', NDS, OutputBecomesInput);
12553class DoacrossCleanupTy final :
public EHScopeStack::Cleanup {
12555 static const int DoacrossFinArgs = 2;
12558 llvm::FunctionCallee RTLFn;
12559 llvm::Value *Args[DoacrossFinArgs];
12562 DoacrossCleanupTy(llvm::FunctionCallee RTLFn,
12565 assert(CallArgs.size() == DoacrossFinArgs);
12566 std::copy(CallArgs.begin(), CallArgs.end(), std::begin(Args));
12583 QualType Int64Ty =
C.getIntTypeForBitwidth(64,
true);
12591 RD =
C.buildImplicitRecord(
"kmp_dim");
12599 RD =
KmpDimTy->castAsRecordDecl();
12601 llvm::APInt Size(32, NumIterations.size());
12607 enum { LowerFD = 0, UpperFD, StrideFD };
12609 for (
unsigned I = 0, E = NumIterations.size(); I < E; ++I) {
12614 DimsLVal, *std::next(RD->
field_begin(), UpperFD));
12616 CGF.
EmitScalarExpr(NumIterations[I]), NumIterations[I]->getType(),
12617 Int64Ty, NumIterations[I]->getExprLoc());
12621 DimsLVal, *std::next(RD->
field_begin(), StrideFD));
12628 llvm::Value *Args[] = {
12631 llvm::ConstantInt::getSigned(
CGM.Int32Ty, NumIterations.size()),
12636 llvm::FunctionCallee RTLFn =
OMPBuilder.getOrCreateRuntimeFunction(
12637 CGM.getModule(), OMPRTL___kmpc_doacross_init);
12639 llvm::Value *FiniArgs[DoacrossCleanupTy::DoacrossFinArgs] = {
12641 llvm::FunctionCallee FiniRTLFn =
OMPBuilder.getOrCreateRuntimeFunction(
12642 CGM.getModule(), OMPRTL___kmpc_doacross_fini);
12647template <
typename T>
12649 const T *
C, llvm::Value *ULoc,
12650 llvm::Value *ThreadID) {
12653 llvm::APInt Size(32,
C->getNumLoops());
12657 for (
unsigned I = 0, E =
C->getNumLoops(); I < E; ++I) {
12658 const Expr *CounterVal =
C->getLoopData(I);
12659 assert(CounterVal);
12666 llvm::Value *Args[] = {
12669 llvm::FunctionCallee RTLFn;
12671 OMPDoacrossKind<T> ODK;
12672 if (ODK.isSource(
C)) {
12674 OMPRTL___kmpc_doacross_post);
12676 assert(ODK.isSink(
C) &&
"Expect sink modifier.");
12678 OMPRTL___kmpc_doacross_wait);
12698 llvm::FunctionCallee Callee,
12700 assert(Loc.
isValid() &&
"Outlined function call location must be valid.");
12703 if (
auto *Fn = dyn_cast<llvm::Function>(Callee.getCallee())) {
12704 if (Fn->doesNotThrow()) {
12715 emitCall(CGF, Loc, OutlinedFn, Args);
12719 if (
const auto *FD = dyn_cast<FunctionDecl>(D))
12720 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(FD))
12726 const VarDecl *TargetParam)
const {
12733 const Expr *Allocator) {
12734 llvm::Value *AllocVal;
12744 AllocVal = llvm::Constant::getNullValue(
12754 if (!AllocateAlignment)
12757 return llvm::ConstantInt::get(
CGM.
SizeTy, AllocateAlignment->getQuantity());
12770 auto I = UntiedData.find(VD);
12771 if (I != UntiedData.end()) {
12772 UntiedAddr = I->second.first;
12773 UntiedRealAddr = I->second.second;
12777 if (CVD->
hasAttr<OMPAllocateDeclAttr>()) {
12786 Size = CGF.
Builder.CreateNUWAdd(
12788 Size = CGF.
Builder.CreateUDiv(Size,
CGM.getSize(Align));
12789 Size = CGF.
Builder.CreateNUWMul(Size,
CGM.getSize(Align));
12795 const auto *AA = CVD->
getAttr<OMPAllocateDeclAttr>();
12796 const Expr *Allocator = AA->getAllocator();
12800 Args.push_back(ThreadID);
12802 Args.push_back(Alignment);
12803 Args.push_back(Size);
12804 Args.push_back(AllocVal);
12805 llvm::omp::RuntimeFunction FnID =
12806 Alignment ? OMPRTL___kmpc_aligned_alloc : OMPRTL___kmpc_alloc;
12808 OMPBuilder.getOrCreateRuntimeFunction(
CGM.getModule(), FnID), Args,
12810 llvm::FunctionCallee FiniRTLFn =
OMPBuilder.getOrCreateRuntimeFunction(
12811 CGM.getModule(), OMPRTL___kmpc_free);
12819 class OMPAllocateCleanupTy final :
public EHScopeStack::Cleanup {
12820 llvm::FunctionCallee RTLFn;
12823 const Expr *AllocExpr;
12826 OMPAllocateCleanupTy(llvm::FunctionCallee RTLFn,
12828 const Expr *AllocExpr)
12829 : RTLFn(RTLFn), LocEncoding(LocEncoding),
Addr(
Addr),
12830 AllocExpr(AllocExpr) {}
12834 llvm::Value *Args[3];
12840 Args[2] = AllocVal;
12848 CGF.
EHStack.pushCleanup<OMPAllocateCleanupTy>(
12850 VDAddr, Allocator);
12851 if (UntiedRealAddr.
isValid())
12854 Region->emitUntiedSwitch(CGF);
12871 assert(CGM.getLangOpts().OpenMP &&
"Not in OpenMP mode.");
12875 CGM.getOpenMPRuntime().NontemporalDeclsStack.emplace_back();
12877 for (
const Stmt *Ref :
C->private_refs()) {
12878 const auto *SimpleRefExpr =
cast<Expr>(Ref)->IgnoreParenImpCasts();
12880 if (
const auto *DRE = dyn_cast<DeclRefExpr>(SimpleRefExpr)) {
12881 VD = DRE->getDecl();
12884 assert((ME->isImplicitCXXThis() ||
12886 "Expected member of current class.");
12887 VD = ME->getMemberDecl();
12897 CGM.getOpenMPRuntime().NontemporalDeclsStack.pop_back();
12903 std::pair<Address, Address>> &LocalVars)
12904 : CGM(CGF.CGM), NeedToPush(!LocalVars.empty()) {
12908 CGF.
CurFn, CGM.getOpenMPRuntime().UntiedLocalVarsStack.size());
12909 CGM.getOpenMPRuntime().UntiedLocalVarsStack.push_back(LocalVars);
12915 CGM.getOpenMPRuntime().UntiedLocalVarsStack.pop_back();
12919 assert(
CGM.getLangOpts().OpenMP &&
"Not in OpenMP mode.");
12921 return llvm::any_of(
12922 CGM.getOpenMPRuntime().NontemporalDeclsStack,
12926void CGOpenMPRuntime::LastprivateConditionalRAII::tryToDisableInnerAnalysis(
12930 llvm::DenseSet<CanonicalDeclPtr<const Decl>> NeedToCheckForLPCs;
12936 const CapturedStmt *CS = S.getCapturedStmt(CaptureRegions.front());
12943 for (
const auto *
C : S.getClausesOfKind<OMPPrivateClause>()) {
12944 for (
const Expr *Ref :
C->varlist()) {
12945 if (!Ref->getType()->isScalarType())
12947 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
12950 NeedToCheckForLPCs.insert(DRE->getDecl());
12953 for (
const auto *
C : S.getClausesOfKind<OMPFirstprivateClause>()) {
12954 for (
const Expr *Ref :
C->varlist()) {
12955 if (!Ref->getType()->isScalarType())
12957 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
12960 NeedToCheckForLPCs.insert(DRE->getDecl());
12963 for (
const auto *
C : S.getClausesOfKind<OMPLastprivateClause>()) {
12964 for (
const Expr *Ref :
C->varlist()) {
12965 if (!Ref->getType()->isScalarType())
12967 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
12970 NeedToCheckForLPCs.insert(DRE->getDecl());
12973 for (
const auto *
C : S.getClausesOfKind<OMPReductionClause>()) {
12974 for (
const Expr *Ref :
C->varlist()) {
12975 if (!Ref->getType()->isScalarType())
12977 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
12980 NeedToCheckForLPCs.insert(DRE->getDecl());
12983 for (
const auto *
C : S.getClausesOfKind<OMPLinearClause>()) {
12984 for (
const Expr *Ref :
C->varlist()) {
12985 if (!Ref->getType()->isScalarType())
12987 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
12990 NeedToCheckForLPCs.insert(DRE->getDecl());
12993 for (
const Decl *VD : NeedToCheckForLPCs) {
12995 llvm::reverse(
CGM.getOpenMPRuntime().LastprivateConditionalStack)) {
12996 if (
Data.DeclToUniqueName.count(VD) > 0) {
12997 if (!
Data.Disabled)
12998 NeedToAddForLPCsAsDisabled.insert(VD);
13005CGOpenMPRuntime::LastprivateConditionalRAII::LastprivateConditionalRAII(
13008 Action((CGM.getLangOpts().OpenMP >= 50 &&
13009 llvm::any_of(S.getClausesOfKind<OMPLastprivateClause>(),
13010 [](const OMPLastprivateClause *
C) {
13011 return C->getKind() ==
13012 OMPC_LASTPRIVATE_conditional;
13014 ? ActionToDo::PushAsLastprivateConditional
13015 : ActionToDo::DoNotPush) {
13016 assert(
CGM.getLangOpts().OpenMP &&
"Not in OpenMP mode.");
13017 if (
CGM.getLangOpts().OpenMP < 50 || Action == ActionToDo::DoNotPush)
13019 assert(Action == ActionToDo::PushAsLastprivateConditional &&
13020 "Expected a push action.");
13022 CGM.getOpenMPRuntime().LastprivateConditionalStack.emplace_back();
13023 for (
const auto *
C : S.getClausesOfKind<OMPLastprivateClause>()) {
13024 if (
C->getKind() != OMPC_LASTPRIVATE_conditional)
13027 for (
const Expr *Ref :
C->varlist()) {
13028 Data.DeclToUniqueName.insert(std::make_pair(
13033 Data.IVLVal = IVLVal;
13037CGOpenMPRuntime::LastprivateConditionalRAII::LastprivateConditionalRAII(
13039 :
CGM(CGF.
CGM), Action(ActionToDo::DoNotPush) {
13043 llvm::DenseSet<CanonicalDeclPtr<const Decl>> NeedToAddForLPCsAsDisabled;
13044 tryToDisableInnerAnalysis(S, NeedToAddForLPCsAsDisabled);
13045 if (!NeedToAddForLPCsAsDisabled.empty()) {
13046 Action = ActionToDo::DisableLastprivateConditional;
13047 LastprivateConditionalData &
Data =
13049 for (
const Decl *VD : NeedToAddForLPCsAsDisabled)
13050 Data.DeclToUniqueName.try_emplace(VD);
13052 Data.Disabled =
true;
13056CGOpenMPRuntime::LastprivateConditionalRAII
13059 return LastprivateConditionalRAII(CGF, S);
13063 if (CGM.getLangOpts().OpenMP < 50)
13065 if (Action == ActionToDo::DisableLastprivateConditional) {
13066 assert(CGM.getOpenMPRuntime().LastprivateConditionalStack.back().Disabled &&
13067 "Expected list of disabled private vars.");
13068 CGM.getOpenMPRuntime().LastprivateConditionalStack.pop_back();
13070 if (Action == ActionToDo::PushAsLastprivateConditional) {
13072 !CGM.getOpenMPRuntime().LastprivateConditionalStack.back().Disabled &&
13073 "Expected list of lastprivate conditional vars.");
13074 CGM.getOpenMPRuntime().LastprivateConditionalStack.pop_back();
13086 auto VI = I->getSecond().find(VD);
13087 if (VI == I->getSecond().end()) {
13088 RecordDecl *RD =
C.buildImplicitRecord(
"lasprivate.conditional");
13093 NewType =
C.getCanonicalTagType(RD);
13096 I->getSecond().try_emplace(VD, NewType, VDField, FiredField, BaseLVal);
13098 NewType = std::get<0>(VI->getSecond());
13099 VDField = std::get<1>(VI->getSecond());
13100 FiredField = std::get<2>(VI->getSecond());
13101 BaseLVal = std::get<3>(VI->getSecond());
13113class LastprivateConditionalRefChecker final
13116 const Expr *FoundE =
nullptr;
13117 const Decl *FoundD =
nullptr;
13118 StringRef UniqueDeclName;
13120 llvm::Function *FoundFn =
nullptr;
13126 llvm::reverse(LPM)) {
13127 auto It = D.DeclToUniqueName.find(E->
getDecl());
13128 if (It == D.DeclToUniqueName.end())
13134 UniqueDeclName = It->second;
13139 return FoundE == E;
13145 llvm::reverse(LPM)) {
13147 if (It == D.DeclToUniqueName.end())
13153 UniqueDeclName = It->second;
13158 return FoundE == E;
13160 bool VisitStmt(
const Stmt *S) {
13161 for (
const Stmt *Child : S->
children()) {
13164 if (
const auto *E = dyn_cast<Expr>(Child))
13172 explicit LastprivateConditionalRefChecker(
13173 ArrayRef<CGOpenMPRuntime::LastprivateConditionalData> LPM)
13175 std::tuple<const Expr *, const Decl *, StringRef, LValue, llvm::Function *>
13176 getFoundData()
const {
13177 return std::make_tuple(FoundE, FoundD, UniqueDeclName, IVLVal, FoundFn);
13184 StringRef UniqueDeclName,
13190 llvm::Constant *LastIV =
OMPBuilder.getOrCreateInternalVariable(
13191 LLIVTy,
getName({UniqueDeclName,
"iv"}));
13199 llvm::GlobalVariable *
Last =
OMPBuilder.getOrCreateInternalVariable(
13215 auto &&
CodeGen = [&LastIVLVal, &IVLVal, IVVal, &LVal, &LastLVal,
13221 llvm::Value *CmpRes;
13223 CmpRes = CGF.
Builder.CreateICmpSLE(LastIVVal, IVVal);
13226 "Loop iteration variable must be integer.");
13227 CmpRes = CGF.
Builder.CreateICmpULE(LastIVVal, IVVal);
13231 CGF.
Builder.CreateCondBr(CmpRes, ThenBB, ExitBB);
13252 "Aggregates are not supported in lastprivate conditional.");
13261 if (
CGM.getLangOpts().OpenMPSimd) {
13275 if (!Checker.Visit(LHS))
13277 const Expr *FoundE;
13278 const Decl *FoundD;
13279 StringRef UniqueDeclName;
13281 llvm::Function *FoundFn;
13282 std::tie(FoundE, FoundD, UniqueDeclName, IVLVal, FoundFn) =
13283 Checker.getFoundData();
13284 if (FoundFn != CGF.
CurFn) {
13289 "Lastprivate conditional is not found in outer region.");
13290 QualType StructTy = std::get<0>(It->getSecond());
13291 const FieldDecl* FiredDecl = std::get<2>(It->getSecond());
13302 FiredLVal, llvm::AtomicOrdering::Unordered,
13320 auto It = llvm::find_if(
13322 if (It == Range.end() || It->Fn != CGF.
CurFn)
13326 "Lastprivates must be registered already.");
13329 const CapturedStmt *CS = D.getCapturedStmt(CaptureRegions.back());
13330 for (
const auto &Pair : It->DeclToUniqueName) {
13331 const auto *VD =
cast<VarDecl>(Pair.first->getCanonicalDecl());
13334 auto I = LPCI->getSecond().find(Pair.first);
13335 assert(I != LPCI->getSecond().end() &&
13336 "Lastprivate must be rehistered already.");
13338 LValue BaseLVal = std::get<3>(I->getSecond());
13342 llvm::Value *
Cmp = CGF.
Builder.CreateIsNotNull(Res);
13346 CGF.
Builder.CreateCondBr(
Cmp, ThenBB, DoneBB);
13371 "Unknown lastprivate conditional variable.");
13372 StringRef UniqueName = It->second;
13373 llvm::GlobalVariable *GV =
CGM.getModule().getNamedGlobal(UniqueName);
13387 llvm_unreachable(
"Not supported in SIMD-only mode");
13394 llvm_unreachable(
"Not supported in SIMD-only mode");
13401 bool Tied,
unsigned &NumberOfParts) {
13402 llvm_unreachable(
"Not supported in SIMD-only mode");
13410 llvm_unreachable(
"Not supported in SIMD-only mode");
13416 const Expr *Hint) {
13417 llvm_unreachable(
"Not supported in SIMD-only mode");
13423 llvm_unreachable(
"Not supported in SIMD-only mode");
13429 const Expr *Filter) {
13430 llvm_unreachable(
"Not supported in SIMD-only mode");
13435 llvm_unreachable(
"Not supported in SIMD-only mode");
13441 llvm_unreachable(
"Not supported in SIMD-only mode");
13449 llvm_unreachable(
"Not supported in SIMD-only mode");
13456 llvm_unreachable(
"Not supported in SIMD-only mode");
13463 bool ForceSimpleCall) {
13464 llvm_unreachable(
"Not supported in SIMD-only mode");
13471 llvm_unreachable(
"Not supported in SIMD-only mode");
13476 llvm_unreachable(
"Not supported in SIMD-only mode");
13482 llvm_unreachable(
"Not supported in SIMD-only mode");
13488 llvm_unreachable(
"Not supported in SIMD-only mode");
13495 llvm_unreachable(
"Not supported in SIMD-only mode");
13501 llvm_unreachable(
"Not supported in SIMD-only mode");
13506 unsigned IVSize,
bool IVSigned,
13509 llvm_unreachable(
"Not supported in SIMD-only mode");
13517 llvm_unreachable(
"Not supported in SIMD-only mode");
13521 ProcBindKind ProcBind,
13523 llvm_unreachable(
"Not supported in SIMD-only mode");
13530 llvm_unreachable(
"Not supported in SIMD-only mode");
13536 llvm_unreachable(
"Not supported in SIMD-only mode");
13541 llvm_unreachable(
"Not supported in SIMD-only mode");
13547 llvm::AtomicOrdering AO) {
13548 llvm_unreachable(
"Not supported in SIMD-only mode");
13553 llvm::Function *TaskFunction,
13555 const Expr *IfCond,
13557 llvm_unreachable(
"Not supported in SIMD-only mode");
13564 llvm_unreachable(
"Not supported in SIMD-only mode");
13571 assert(Options.
SimpleReduction &&
"Only simple reduction is expected.");
13573 ReductionOps, Options);
13579 llvm_unreachable(
"Not supported in SIMD-only mode");
13584 bool IsWorksharingReduction) {
13585 llvm_unreachable(
"Not supported in SIMD-only mode");
13592 llvm_unreachable(
"Not supported in SIMD-only mode");
13597 llvm::Value *ReductionsPtr,
13599 llvm_unreachable(
"Not supported in SIMD-only mode");
13605 llvm_unreachable(
"Not supported in SIMD-only mode");
13611 llvm_unreachable(
"Not supported in SIMD-only mode");
13617 llvm_unreachable(
"Not supported in SIMD-only mode");
13622 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
13624 llvm_unreachable(
"Not supported in SIMD-only mode");
13629 llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID,
const Expr *IfCond,
13630 llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier>
Device,
13634 llvm_unreachable(
"Not supported in SIMD-only mode");
13638 llvm_unreachable(
"Not supported in SIMD-only mode");
13642 llvm_unreachable(
"Not supported in SIMD-only mode");
13652 llvm::Function *OutlinedFn,
13654 llvm_unreachable(
"Not supported in SIMD-only mode");
13658 const Expr *NumTeams,
13659 const Expr *ThreadLimit,
13661 llvm_unreachable(
"Not supported in SIMD-only mode");
13668 llvm_unreachable(
"Not supported in SIMD-only mode");
13674 llvm_unreachable(
"Not supported in SIMD-only mode");
13680 llvm_unreachable(
"Not supported in SIMD-only mode");
13685 llvm_unreachable(
"Not supported in SIMD-only mode");
13690 llvm_unreachable(
"Not supported in SIMD-only mode");
13695 const VarDecl *NativeParam)
const {
13696 llvm_unreachable(
"Not supported in SIMD-only mode");
13702 const VarDecl *TargetParam)
const {
13703 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.
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.