30#include "llvm/ADT/ArrayRef.h"
31#include "llvm/ADT/SmallVector.h"
32#include "llvm/ADT/StringExtras.h"
33#include "llvm/Bitcode/BitcodeReader.h"
34#include "llvm/IR/Constants.h"
35#include "llvm/IR/DerivedTypes.h"
36#include "llvm/IR/GlobalValue.h"
37#include "llvm/IR/InstrTypes.h"
38#include "llvm/IR/Value.h"
39#include "llvm/Support/AtomicOrdering.h"
40#include "llvm/Support/raw_ostream.h"
47using namespace CodeGen;
48using namespace llvm::omp;
55 enum CGOpenMPRegionKind {
58 ParallelOutlinedRegion,
69 const CGOpenMPRegionKind RegionKind,
72 : CGCapturedStmtInfo(CS,
CR_OpenMP), RegionKind(RegionKind),
73 CodeGen(CodeGen),
Kind(
Kind), HasCancel(HasCancel) {}
75 CGOpenMPRegionInfo(
const CGOpenMPRegionKind RegionKind,
78 : CGCapturedStmtInfo(
CR_OpenMP), RegionKind(RegionKind), CodeGen(CodeGen),
83 virtual const VarDecl *getThreadIDVariable()
const = 0;
94 CGOpenMPRegionKind getRegionKind()
const {
return RegionKind; }
98 bool hasCancel()
const {
return HasCancel; }
100 static bool classof(
const CGCapturedStmtInfo *Info) {
104 ~CGOpenMPRegionInfo()
override =
default;
107 CGOpenMPRegionKind RegionKind;
114class CGOpenMPOutlinedRegionInfo final :
public CGOpenMPRegionInfo {
119 StringRef HelperName)
120 : CGOpenMPRegionInfo(CS, ParallelOutlinedRegion, CodeGen,
Kind,
122 ThreadIDVar(ThreadIDVar), HelperName(HelperName) {
123 assert(ThreadIDVar !=
nullptr &&
"No ThreadID in OpenMP region.");
128 const VarDecl *getThreadIDVariable()
const override {
return ThreadIDVar; }
131 StringRef getHelperName()
const override {
return HelperName; }
133 static bool classof(
const CGCapturedStmtInfo *Info) {
134 return CGOpenMPRegionInfo::classof(Info) &&
135 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() ==
136 ParallelOutlinedRegion;
143 StringRef HelperName;
147class CGOpenMPTaskOutlinedRegionInfo final :
public CGOpenMPRegionInfo {
153 llvm::SwitchInst *UntiedSwitch =
nullptr;
156 UntiedTaskActionTy(
bool Tied,
const VarDecl *PartIDVar,
158 : Untied(!Tied), PartIDVar(PartIDVar), UntiedCodeGen(UntiedCodeGen) {}
168 UntiedSwitch = CGF.
Builder.CreateSwitch(Res, DoneBB);
172 UntiedSwitch->addCase(CGF.
Builder.getInt32(0),
174 emitUntiedSwitch(CGF);
189 UntiedSwitch->addCase(CGF.
Builder.getInt32(UntiedSwitch->getNumCases()),
195 unsigned getNumberOfParts()
const {
return UntiedSwitch->getNumCases(); }
201 const UntiedTaskActionTy &Action)
202 : CGOpenMPRegionInfo(CS, TaskOutlinedRegion, CodeGen,
Kind, HasCancel),
203 ThreadIDVar(ThreadIDVar), Action(Action) {
204 assert(ThreadIDVar !=
nullptr &&
"No ThreadID in OpenMP region.");
209 const VarDecl *getThreadIDVariable()
const override {
return ThreadIDVar; }
215 StringRef getHelperName()
const override {
return ".omp_outlined."; }
218 Action.emitUntiedSwitch(CGF);
221 static bool classof(
const CGCapturedStmtInfo *Info) {
222 return CGOpenMPRegionInfo::classof(Info) &&
223 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() ==
232 const UntiedTaskActionTy &Action;
237class CGOpenMPInlinedRegionInfo :
public CGOpenMPRegionInfo {
242 : CGOpenMPRegionInfo(InlinedRegion, CodeGen,
Kind, HasCancel),
244 OuterRegionInfo(dyn_cast_or_null<CGOpenMPRegionInfo>(OldCSI)) {}
247 llvm::Value *getContextValue()
const override {
250 llvm_unreachable(
"No context value for inlined OpenMP region");
253 void setContextValue(llvm::Value *
V)
override {
254 if (OuterRegionInfo) {
255 OuterRegionInfo->setContextValue(
V);
258 llvm_unreachable(
"No context value for inlined OpenMP region");
264 return OuterRegionInfo->lookup(VD);
270 FieldDecl *getThisFieldDecl()
const override {
272 return OuterRegionInfo->getThisFieldDecl();
278 const VarDecl *getThreadIDVariable()
const override {
280 return OuterRegionInfo->getThreadIDVariable();
287 return OuterRegionInfo->getThreadIDVariableLValue(CGF);
288 llvm_unreachable(
"No LValue for inlined OpenMP construct");
292 StringRef getHelperName()
const override {
293 if (
auto *OuterRegionInfo = getOldCSI())
294 return OuterRegionInfo->getHelperName();
295 llvm_unreachable(
"No helper name for inlined OpenMP construct");
300 OuterRegionInfo->emitUntiedSwitch(CGF);
305 static bool classof(
const CGCapturedStmtInfo *Info) {
306 return CGOpenMPRegionInfo::classof(Info) &&
307 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == InlinedRegion;
310 ~CGOpenMPInlinedRegionInfo()
override =
default;
315 CGOpenMPRegionInfo *OuterRegionInfo;
323class CGOpenMPTargetRegionInfo final :
public CGOpenMPRegionInfo {
327 : CGOpenMPRegionInfo(CS, TargetRegion, CodeGen, OMPD_target,
329 HelperName(HelperName) {}
333 const VarDecl *getThreadIDVariable()
const override {
return nullptr; }
336 StringRef getHelperName()
const override {
return HelperName; }
338 static bool classof(
const CGCapturedStmtInfo *Info) {
339 return CGOpenMPRegionInfo::classof(Info) &&
340 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == TargetRegion;
344 StringRef HelperName;
348 llvm_unreachable(
"No codegen for expressions");
352class CGOpenMPInnerExprInfo final :
public CGOpenMPInlinedRegionInfo {
355 : CGOpenMPInlinedRegionInfo(CGF.CapturedStmtInfo, EmptyCodeGen,
363 if (!
C.capturesVariable() && !
C.capturesVariableByCopy())
366 const VarDecl *VD =
C.getCapturedVar();
376 (void)PrivScope.Privatize();
381 if (
const FieldDecl *FD = CGOpenMPInlinedRegionInfo::lookup(VD))
388 llvm_unreachable(
"No body for expressions");
393 const VarDecl *getThreadIDVariable()
const override {
394 llvm_unreachable(
"No thread id for expressions");
398 StringRef getHelperName()
const override {
399 llvm_unreachable(
"No helper name for expressions");
402 static bool classof(
const CGCapturedStmtInfo *Info) {
return false; }
410class InlinedOpenMPRegionRAII {
412 llvm::DenseMap<const ValueDecl *, FieldDecl *> LambdaCaptureFields;
413 FieldDecl *LambdaThisCaptureField =
nullptr;
415 bool NoInheritance =
false;
424 bool NoInheritance =
true)
425 : CGF(CGF), NoInheritance(NoInheritance) {
438 ~InlinedOpenMPRegionRAII() {
455enum OpenMPLocationFlags :
unsigned {
457 OMP_IDENT_IMD = 0x01,
459 OMP_IDENT_KMPC = 0x02,
461 OMP_ATOMIC_REDUCE = 0x10,
463 OMP_IDENT_BARRIER_EXPL = 0x20,
465 OMP_IDENT_BARRIER_IMPL = 0x40,
467 OMP_IDENT_BARRIER_IMPL_FOR = 0x40,
469 OMP_IDENT_BARRIER_IMPL_SECTIONS = 0xC0,
471 OMP_IDENT_BARRIER_IMPL_SINGLE = 0x140,
473 OMP_IDENT_WORK_LOOP = 0x200,
475 OMP_IDENT_WORK_SECTIONS = 0x400,
477 OMP_IDENT_WORK_DISTRIBUTE = 0x800,
507enum IdentFieldIndex {
509 IdentField_Reserved_1,
513 IdentField_Reserved_2,
515 IdentField_Reserved_3,
524enum OpenMPSchedType {
527 OMP_sch_static_chunked = 33,
529 OMP_sch_dynamic_chunked = 35,
530 OMP_sch_guided_chunked = 36,
531 OMP_sch_runtime = 37,
534 OMP_sch_static_balanced_chunked = 45,
537 OMP_ord_static_chunked = 65,
539 OMP_ord_dynamic_chunked = 67,
540 OMP_ord_guided_chunked = 68,
541 OMP_ord_runtime = 69,
543 OMP_sch_default = OMP_sch_static,
545 OMP_dist_sch_static_chunked = 91,
546 OMP_dist_sch_static = 92,
549 OMP_sch_modifier_monotonic = (1 << 29),
551 OMP_sch_modifier_nonmonotonic = (1 << 30),
574 Callback(CodeGen, CGF, *PrePostAction);
577 Callback(CodeGen, CGF, Action);
585 if (
const auto *CE = dyn_cast<CallExpr>(ReductionOp))
586 if (
const auto *OVE = dyn_cast<OpaqueValueExpr>(CE->getCallee()))
587 if (
const auto *DRE =
588 dyn_cast<DeclRefExpr>(OVE->getSourceExpr()->IgnoreImpCasts()))
589 if (
const auto *DRD = dyn_cast<OMPDeclareReductionDecl>(DRE->getDecl()))
600 std::pair<llvm::Function *, llvm::Function *>
Reduction =
602 const auto *CE = cast<CallExpr>(InitOp);
603 const auto *OVE = cast<OpaqueValueExpr>(CE->getCallee());
607 cast<DeclRefExpr>(cast<UnaryOperator>(LHS)->getSubExpr());
609 cast<DeclRefExpr>(cast<UnaryOperator>(RHS)->getSubExpr());
612 PrivateScope.
addPrivate(cast<VarDecl>(RHSDRE->getDecl()), Original);
620 auto *GV =
new llvm::GlobalVariable(
622 llvm::GlobalValue::PrivateLinkage,
Init, Name);
663 llvm::Value *NumElements = CGF.
emitArrayLength(ArrayTy, ElementTy, DestAddr);
667 llvm::Value *SrcBegin =
nullptr;
669 SrcBegin = SrcAddr.emitRawPointer(CGF);
672 llvm::Value *DestEnd =
677 llvm::Value *IsEmpty =
678 CGF.
Builder.CreateICmpEQ(DestBegin, DestEnd,
"omp.arrayinit.isempty");
679 CGF.
Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
682 llvm::BasicBlock *EntryBB = CGF.
Builder.GetInsertBlock();
687 llvm::PHINode *SrcElementPHI =
nullptr;
690 SrcElementPHI = CGF.
Builder.CreatePHI(SrcBegin->getType(), 2,
691 "omp.arraycpy.srcElementPast");
692 SrcElementPHI->addIncoming(SrcBegin, EntryBB);
694 Address(SrcElementPHI, SrcAddr.getElementType(),
695 SrcAddr.getAlignment().alignmentOfArrayElement(ElementSize));
697 llvm::PHINode *DestElementPHI = CGF.
Builder.CreatePHI(
698 DestBegin->getType(), 2,
"omp.arraycpy.destElementPast");
699 DestElementPHI->addIncoming(DestBegin, EntryBB);
707 if (EmitDeclareReductionInit) {
709 SrcElementCurrent, ElementTy);
717 llvm::Value *SrcElementNext = CGF.
Builder.CreateConstGEP1_32(
718 SrcAddr.getElementType(), SrcElementPHI, 1,
719 "omp.arraycpy.dest.element");
720 SrcElementPHI->addIncoming(SrcElementNext, CGF.
Builder.GetInsertBlock());
724 llvm::Value *DestElementNext = CGF.
Builder.CreateConstGEP1_32(
726 "omp.arraycpy.dest.element");
729 CGF.
Builder.CreateICmpEQ(DestElementNext, DestEnd,
"omp.arraycpy.done");
730 CGF.
Builder.CreateCondBr(Done, DoneBB, BodyBB);
731 DestElementPHI->addIncoming(DestElementNext, CGF.
Builder.GetInsertBlock());
743 if (
const auto *OASE = dyn_cast<ArraySectionExpr>(
E))
748void ReductionCodeGen::emitAggregateInitialization(
754 const auto *PrivateVD =
755 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].
Private)->getDecl());
756 bool EmitDeclareReductionInit =
759 EmitDeclareReductionInit,
760 EmitDeclareReductionInit ? ClausesData[N].ReductionOp
761 : PrivateVD->getInit(),
769 ClausesData.reserve(Shareds.size());
770 SharedAddresses.reserve(Shareds.size());
771 Sizes.reserve(Shareds.size());
772 BaseDecls.reserve(Shareds.size());
773 const auto *IOrig = Origs.begin();
774 const auto *IPriv = Privates.begin();
775 const auto *IRed = ReductionOps.begin();
776 for (
const Expr *Ref : Shareds) {
777 ClausesData.emplace_back(Ref, *IOrig, *IPriv, *IRed);
778 std::advance(IOrig, 1);
779 std::advance(IPriv, 1);
780 std::advance(IRed, 1);
785 assert(SharedAddresses.size() == N && OrigAddresses.size() == N &&
786 "Number of generated lvalues must be exactly N.");
787 LValue First = emitSharedLValue(CGF, ClausesData[N].Shared);
788 LValue Second = emitSharedLValueUB(CGF, ClausesData[N].Shared);
789 SharedAddresses.emplace_back(
First, Second);
790 if (ClausesData[N].Shared == ClausesData[N].Ref) {
791 OrigAddresses.emplace_back(
First, Second);
793 LValue First = emitSharedLValue(CGF, ClausesData[N].Ref);
794 LValue Second = emitSharedLValueUB(CGF, ClausesData[N].Ref);
795 OrigAddresses.emplace_back(
First, Second);
801 bool AsArraySection = isa<ArraySectionExpr>(ClausesData[N].Ref);
804 CGF.
getTypeSize(OrigAddresses[N].first.getType().getNonReferenceType()),
809 llvm::Value *SizeInChars;
810 auto *ElemType = OrigAddresses[N].first.getAddress().getElementType();
811 auto *ElemSizeOf = llvm::ConstantExpr::getSizeOf(ElemType);
812 if (AsArraySection) {
813 Size = CGF.
Builder.CreatePtrDiff(ElemType,
814 OrigAddresses[N].second.getPointer(CGF),
815 OrigAddresses[N].first.getPointer(CGF));
816 Size = CGF.
Builder.CreateNUWAdd(
817 Size, llvm::ConstantInt::get(Size->getType(), 1));
818 SizeInChars = CGF.
Builder.CreateNUWMul(Size, ElemSizeOf);
821 CGF.
getTypeSize(OrigAddresses[N].first.getType().getNonReferenceType());
822 Size = CGF.
Builder.CreateExactUDiv(SizeInChars, ElemSizeOf);
824 Sizes.emplace_back(SizeInChars, Size);
827 cast<OpaqueValueExpr>(
837 assert(!Size && !Sizes[N].second &&
838 "Size should be nullptr for non-variably modified reduction "
844 cast<OpaqueValueExpr>(
853 assert(SharedAddresses.size() > N &&
"No variable was generated");
854 const auto *PrivateVD =
855 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].
Private)->getDecl());
860 (void)DefaultInit(CGF);
861 emitAggregateInitialization(CGF, N, PrivateAddr, SharedAddr, DRD);
862 }
else if (DRD && (DRD->
getInitializer() || !PrivateVD->hasInit())) {
863 (void)DefaultInit(CGF);
864 QualType SharedType = SharedAddresses[N].first.getType();
866 PrivateAddr, SharedAddr, SharedType);
867 }
else if (!DefaultInit(CGF) && PrivateVD->hasInit() &&
870 PrivateVD->
getType().getQualifiers(),
888 CGF.
pushDestroy(DTorKind, PrivateAddr, PrivateType);
941 const VarDecl *OrigVD =
nullptr;
942 if (
const auto *OASE = dyn_cast<ArraySectionExpr>(Ref)) {
943 const Expr *
Base = OASE->getBase()->IgnoreParenImpCasts();
944 while (
const auto *TempOASE = dyn_cast<ArraySectionExpr>(
Base))
945 Base = TempOASE->getBase()->IgnoreParenImpCasts();
946 while (
const auto *TempASE = dyn_cast<ArraySubscriptExpr>(
Base))
947 Base = TempASE->getBase()->IgnoreParenImpCasts();
948 DE = cast<DeclRefExpr>(
Base);
949 OrigVD = cast<VarDecl>(DE->
getDecl());
950 }
else if (
const auto *ASE = dyn_cast<ArraySubscriptExpr>(Ref)) {
951 const Expr *
Base = ASE->getBase()->IgnoreParenImpCasts();
952 while (
const auto *TempASE = dyn_cast<ArraySubscriptExpr>(
Base))
953 Base = TempASE->getBase()->IgnoreParenImpCasts();
954 DE = cast<DeclRefExpr>(
Base);
955 OrigVD = cast<VarDecl>(DE->
getDecl());
964 BaseDecls.emplace_back(OrigVD);
967 loadToBegin(CGF, OrigVD->getType(), SharedAddresses[N].first.getType(),
969 Address SharedAddr = SharedAddresses[N].first.getAddress();
970 llvm::Value *Adjustment = CGF.
Builder.CreatePtrDiff(
973 llvm::Value *PrivatePointer =
979 SharedAddresses[N].first.getType(),
982 BaseDecls.emplace_back(
983 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Ref)->getDecl()));
996 getThreadIDVariable()->getType()->castAs<PointerType>());
1014LValue CGOpenMPTaskOutlinedRegionInfo::getThreadIDVariableLValue(
1017 getThreadIDVariable()->getType(),
1033 : CGM(CGM), OMPBuilder(CGM.getModule()) {
1035 llvm::OpenMPIRBuilderConfig Config(
1050 OMPBuilder.Config.setHasRequiresUnifiedSharedMemory(
true);
1058 if (!
Data.getValue().pointsToAliveValue())
1060 auto *GV = dyn_cast<llvm::GlobalVariable>(
Data.getValue());
1063 if (!GV->isDeclaration() || GV->getNumUses() > 0)
1065 GV->eraseFromParent();
1070 return OMPBuilder.createPlatformSpecificName(Parts);
1073static llvm::Function *
1075 const Expr *CombinerInitializer,
const VarDecl *In,
1076 const VarDecl *Out,
bool IsCombiner) {
1079 QualType PtrTy =
C.getPointerType(Ty).withRestrict();
1085 Args.push_back(&OmpOutParm);
1086 Args.push_back(&OmpInParm);
1091 {IsCombiner ?
"omp_combiner" :
"omp_initializer",
""});
1092 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
1096 Fn->removeFnAttr(llvm::Attribute::NoInline);
1097 Fn->removeFnAttr(llvm::Attribute::OptimizeNone);
1098 Fn->addFnAttr(llvm::Attribute::AlwaysInline);
1104 Out->getLocation());
1114 (void)
Scope.Privatize();
1115 if (!IsCombiner && Out->hasInit() &&
1118 Out->getType().getQualifiers(),
1121 if (CombinerInitializer)
1123 Scope.ForceCleanup();
1133 CGM,
D->getType(),
D->getCombiner(),
1134 cast<VarDecl>(cast<DeclRefExpr>(
D->getCombinerIn())->getDecl()),
1135 cast<VarDecl>(cast<DeclRefExpr>(
D->getCombinerOut())->getDecl()),
1138 if (
const Expr *
Init =
D->getInitializer()) {
1143 cast<VarDecl>(cast<DeclRefExpr>(
D->getInitOrig())->getDecl()),
1144 cast<VarDecl>(cast<DeclRefExpr>(
D->getInitPriv())->getDecl()),
1152std::pair<llvm::Function *, llvm::Function *>
1164struct PushAndPopStackRAII {
1165 PushAndPopStackRAII(llvm::OpenMPIRBuilder *OMPBuilder,
CodeGenFunction &CGF,
1166 bool HasCancel, llvm::omp::Directive
Kind)
1167 : OMPBuilder(OMPBuilder) {
1183 auto FiniCB = [&CGF](llvm::OpenMPIRBuilder::InsertPointTy IP) {
1184 assert(IP.getBlock()->end() == IP.getPoint() &&
1185 "Clang CG should cause non-terminated block!");
1186 CGBuilderTy::InsertPointGuard IPG(CGF.
Builder);
1191 return llvm::Error::success();
1196 llvm::OpenMPIRBuilder::FinalizationInfo FI({FiniCB,
Kind, HasCancel});
1197 OMPBuilder->pushFinalizationCB(std::move(FI));
1199 ~PushAndPopStackRAII() {
1201 OMPBuilder->popFinalizationCB();
1203 llvm::OpenMPIRBuilder *OMPBuilder;
1212 "thread id variable must be of type kmp_int32 *");
1214 bool HasCancel =
false;
1215 if (
const auto *OPD = dyn_cast<OMPParallelDirective>(&
D))
1216 HasCancel = OPD->hasCancel();
1217 else if (
const auto *OPD = dyn_cast<OMPTargetParallelDirective>(&
D))
1218 HasCancel = OPD->hasCancel();
1219 else if (
const auto *OPSD = dyn_cast<OMPParallelSectionsDirective>(&
D))
1220 HasCancel = OPSD->hasCancel();
1221 else if (
const auto *OPFD = dyn_cast<OMPParallelForDirective>(&
D))
1222 HasCancel = OPFD->hasCancel();
1223 else if (
const auto *OPFD = dyn_cast<OMPTargetParallelForDirective>(&
D))
1224 HasCancel = OPFD->hasCancel();
1225 else if (
const auto *OPFD = dyn_cast<OMPDistributeParallelForDirective>(&
D))
1226 HasCancel = OPFD->hasCancel();
1227 else if (
const auto *OPFD =
1228 dyn_cast<OMPTeamsDistributeParallelForDirective>(&
D))
1229 HasCancel = OPFD->hasCancel();
1230 else if (
const auto *OPFD =
1231 dyn_cast<OMPTargetTeamsDistributeParallelForDirective>(&
D))
1232 HasCancel = OPFD->hasCancel();
1237 PushAndPopStackRAII PSR(&OMPBuilder, CGF, HasCancel, InnermostKind);
1238 CGOpenMPOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen, InnermostKind,
1239 HasCancel, OutlinedHelperName);
1245 std::string Suffix =
getName({
"omp_outlined"});
1246 return (Name + Suffix).str();
1254 std::string Suffix =
getName({
"omp",
"reduction",
"reduction_func"});
1255 return (Name + Suffix).str();
1282 bool Tied,
unsigned &NumberOfParts) {
1287 llvm::Value *TaskArgs[] = {
1289 CGF.EmitLoadOfPointerLValue(CGF.GetAddrOfLocalVar(TaskTVar),
1292 CGF.EmitRuntimeCall(
OMPBuilder.getOrCreateRuntimeFunction(
1296 CGOpenMPTaskOutlinedRegionInfo::UntiedTaskActionTy Action(Tied, PartIDVar,
1300 "thread id variable must be of type kmp_int32 for tasks");
1305 bool HasCancel =
false;
1306 if (
const auto *TD = dyn_cast<OMPTaskDirective>(&
D))
1307 HasCancel = TD->hasCancel();
1308 else if (
const auto *TD = dyn_cast<OMPTaskLoopDirective>(&
D))
1309 HasCancel = TD->hasCancel();
1310 else if (
const auto *TD = dyn_cast<OMPMasterTaskLoopDirective>(&
D))
1311 HasCancel = TD->hasCancel();
1312 else if (
const auto *TD = dyn_cast<OMPParallelMasterTaskLoopDirective>(&
D))
1313 HasCancel = TD->hasCancel();
1316 CGOpenMPTaskOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen,
1317 InnermostKind, HasCancel, Action);
1319 llvm::Function *Res = CGF.GenerateCapturedStmtFunction(*CS);
1321 NumberOfParts = Action.getNumberOfParts();
1326 bool AtCurrentPoint) {
1328 assert(!Elem.ServiceInsertPt &&
"Insert point is set already.");
1330 llvm::Value *Undef = llvm::UndefValue::get(CGF.
Int32Ty);
1331 if (AtCurrentPoint) {
1332 Elem.ServiceInsertPt =
new llvm::BitCastInst(Undef, CGF.
Int32Ty,
"svcpt",
1333 CGF.
Builder.GetInsertBlock());
1335 Elem.ServiceInsertPt =
new llvm::BitCastInst(Undef, CGF.
Int32Ty,
"svcpt");
1336 Elem.ServiceInsertPt->insertAfter(CGF.
AllocaInsertPt->getIterator());
1342 if (Elem.ServiceInsertPt) {
1343 llvm::Instruction *Ptr = Elem.ServiceInsertPt;
1344 Elem.ServiceInsertPt =
nullptr;
1345 Ptr->eraseFromParent();
1352 llvm::raw_svector_ostream OS(Buffer);
1361 if (
const auto *FD = dyn_cast_or_null<FunctionDecl>(CGF.
CurFuncDecl))
1362 OS << FD->getQualifiedNameAsString();
1369 unsigned Flags,
bool EmitLoc) {
1370 uint32_t SrcLocStrSize;
1371 llvm::Constant *SrcLocStr;
1373 llvm::codegenoptions::NoDebugInfo) ||
1375 SrcLocStr =
OMPBuilder.getOrCreateDefaultSrcLocStr(SrcLocStrSize);
1377 std::string FunctionName;
1379 if (
const auto *FD = dyn_cast_or_null<FunctionDecl>(CGF.
CurFuncDecl))
1380 FunctionName = FD->getQualifiedNameAsString();
1393 SrcLocStr, SrcLocStrSize, llvm::omp::IdentFlag(Flags), Reserved2Flags);
1398 assert(CGF.
CurFn &&
"No function in current CodeGenFunction.");
1404 uint32_t SrcLocStrSize;
1405 auto *SrcLocStr =
OMPBuilder.getOrCreateSrcLocStr(
1408 OMPBuilder.getOrCreateIdent(SrcLocStr, SrcLocStrSize));
1411 llvm::Value *ThreadID =
nullptr;
1416 ThreadID = I->second.ThreadID;
1417 if (ThreadID !=
nullptr)
1421 if (
auto *OMPRegionInfo =
1423 if (OMPRegionInfo->getThreadIDVariable()) {
1425 LValue LVal = OMPRegionInfo->getThreadIDVariableLValue(CGF);
1429 CGF.
Builder.GetInsertBlock() == TopBlock ||
1430 !isa<llvm::Instruction>(LVal.
getPointer(CGF)) ||
1431 cast<llvm::Instruction>(LVal.
getPointer(CGF))->getParent() ==
1433 cast<llvm::Instruction>(LVal.
getPointer(CGF))->getParent() ==
1434 CGF.
Builder.GetInsertBlock()) {
1438 if (CGF.
Builder.GetInsertBlock() == TopBlock)
1450 if (!Elem.ServiceInsertPt)
1452 CGBuilderTy::InsertPointGuard IPG(CGF.
Builder);
1453 CGF.
Builder.SetInsertPoint(Elem.ServiceInsertPt);
1457 OMPRTL___kmpc_global_thread_num),
1460 Elem.ThreadID =
Call;
1465 assert(CGF.
CurFn &&
"No function in current CodeGenFunction.");
1471 for (
const auto *
D : I->second)
1476 for (
const auto *
D : I->second)
1488static llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseKind
1490 std::optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
1491 OMPDeclareTargetDeclAttr::getDeviceType(VD);
1493 return llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseNone;
1495 switch ((
int)*DevTy) {
1496 case OMPDeclareTargetDeclAttr::DT_Host:
1497 return llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseHost;
1499 case OMPDeclareTargetDeclAttr::DT_NoHost:
1500 return llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseNoHost;
1502 case OMPDeclareTargetDeclAttr::DT_Any:
1503 return llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseAny;
1506 return llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseNone;
1511static llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryKind
1513 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> MapType =
1514 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
1516 return llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryNone;
1517 switch ((
int)*MapType) {
1518 case OMPDeclareTargetDeclAttr::MapTypeTy::MT_To:
1519 return llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryTo;
1521 case OMPDeclareTargetDeclAttr::MapTypeTy::MT_Enter:
1522 return llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryEnter;
1524 case OMPDeclareTargetDeclAttr::MapTypeTy::MT_Link:
1525 return llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryLink;
1528 return llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryNone;
1537 auto FileInfoCallBack = [&]() {
1541 llvm::sys::fs::UniqueID ID;
1542 if (llvm::sys::fs::getUniqueID(PLoc.
getFilename(), ID)) {
1543 PLoc =
SM.getPresumedLoc(BeginLoc,
false);
1549 return OMPBuilder.getTargetEntryUniqueInfo(FileInfoCallBack, ParentName);
1555 auto LinkageForVariable = [&VD,
this]() {
1559 std::vector<llvm::GlobalVariable *> GeneratedRefs;
1563 llvm::Constant *addr =
OMPBuilder.getAddrOfDeclareTargetVar(
1571 LinkageForVariable);
1583 std::string Suffix =
getName({
"cache",
""});
1584 return OMPBuilder.getOrCreateInternalVariable(
1597 llvm::Value *Args[] = {
1621 llvm::Value *Args[] = {
1624 Ctor, CopyCtor, Dtor};
1627 CGM.
getModule(), OMPRTL___kmpc_threadprivate_register),
1642 llvm::Value *Ctor =
nullptr, *CopyCtor =
nullptr, *Dtor =
nullptr;
1652 Args.push_back(&Dst);
1657 std::string Name =
getName({
"__kmpc_global_ctor_",
""});
1658 llvm::Function *Fn =
1684 Args.push_back(&Dst);
1689 std::string Name =
getName({
"__kmpc_global_dtor_",
""});
1690 llvm::Function *Fn =
1715 if (Ctor ==
nullptr) {
1718 if (Dtor ==
nullptr) {
1722 auto *InitFunctionTy =
1723 llvm::FunctionType::get(
CGM.
VoidTy,
false);
1724 std::string Name =
getName({
"__omp_threadprivate_init_",
""});
1734 return InitFunction;
1742 llvm::GlobalValue *GV) {
1743 std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr =
1744 OMPDeclareTargetDeclAttr::getActiveAttr(FD);
1747 if (!ActiveAttr || !(*ActiveAttr)->getIndirect())
1754 OMPBuilder.OffloadInfoManager.getTargetRegionEntryFnName(Name, EntryInfo);
1760 llvm::GlobalValue *
Addr = GV;
1762 Addr =
new llvm::GlobalVariable(
1764 true, llvm::GlobalValue::ExternalLinkage, GV, Name,
1765 nullptr, llvm::GlobalValue::NotThreadLocal,
1766 CGM.
getModule().getDataLayout().getDefaultGlobalsAddressSpace());
1767 Addr->setVisibility(llvm::GlobalValue::ProtectedVisibility);
1770 OMPBuilder.OffloadInfoManager.registerDeviceGlobalVarEntryInfo(
1772 llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryIndirect,
1773 llvm::GlobalValue::WeakODRLinkage);
1779 std::string Suffix =
getName({
"artificial",
""});
1781 llvm::GlobalVariable *GAddr =
OMPBuilder.getOrCreateInternalVariable(
1782 VarLVType, Twine(Name).concat(Suffix).str());
1785 GAddr->setThreadLocal(
true);
1786 return Address(GAddr, GAddr->getValueType(),
1789 std::string CacheSuffix =
getName({
"cache",
""});
1790 llvm::Value *Args[] = {
1798 Twine(Name).concat(Suffix).concat(CacheSuffix).str())};
1857 auto &&ThenGen = [&M, OutlinedFn, CapturedVars, RTLoc,
1860 llvm::Value *Args[] = {
1862 CGF.
Builder.getInt32(CapturedVars.size()),
1865 RealArgs.append(std::begin(Args), std::end(Args));
1866 RealArgs.append(CapturedVars.begin(), CapturedVars.end());
1868 llvm::FunctionCallee RTLFn =
1869 OMPBuilder.getOrCreateRuntimeFunction(M, OMPRTL___kmpc_fork_call);
1872 auto &&ElseGen = [&M, OutlinedFn, CapturedVars, RTLoc,
Loc,
1878 llvm::Value *Args[] = {RTLoc, ThreadID};
1880 M, OMPRTL___kmpc_serialized_parallel),
1887 ".bound.zero.addr");
1892 OutlinedFnArgs.push_back(ZeroAddrBound.
getPointer());
1893 OutlinedFnArgs.append(CapturedVars.begin(), CapturedVars.end());
1901 OutlinedFn->removeFnAttr(llvm::Attribute::AlwaysInline);
1902 OutlinedFn->addFnAttr(llvm::Attribute::NoInline);
1908 M, OMPRTL___kmpc_end_serialized_parallel),
1927 if (
auto *OMPRegionInfo =
1929 if (OMPRegionInfo->getThreadIDVariable())
1930 return OMPRegionInfo->getThreadIDVariableLValue(CGF).getAddress();
1939 return ThreadIDTemp;
1943 std::string Prefix = Twine(
"gomp_critical_user_", CriticalName).str();
1944 std::string Name =
getName({Prefix,
"var"});
1951 llvm::FunctionCallee EnterCallee;
1953 llvm::FunctionCallee ExitCallee;
1956 llvm::BasicBlock *ContBlock =
nullptr;
1959 CommonActionTy(llvm::FunctionCallee EnterCallee,
1961 llvm::FunctionCallee ExitCallee,
1963 : EnterCallee(EnterCallee), EnterArgs(EnterArgs), ExitCallee(ExitCallee),
1968 llvm::Value *CallBool = CGF.
Builder.CreateIsNotNull(EnterRes);
1972 CGF.
Builder.CreateCondBr(CallBool, ThenBlock, ContBlock);
1988 StringRef CriticalName,
2002 EnterArgs.push_back(CGF.
Builder.CreateIntCast(
2005 CommonActionTy Action(
2008 Hint ? OMPRTL___kmpc_critical_with_hint : OMPRTL___kmpc_critical),
2011 OMPRTL___kmpc_end_critical),
2028 CommonActionTy Action(
OMPBuilder.getOrCreateRuntimeFunction(
2050 llvm::Value *FilterVal = Filter
2057 CommonActionTy Action(
OMPBuilder.getOrCreateRuntimeFunction(
2077 llvm::Value *Args[] = {
2079 llvm::ConstantInt::get(
CGM.
IntTy, 0,
true)};
2085 if (
auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.
CapturedStmtInfo))
2086 Region->emitUntiedSwitch(CGF);
2099 CommonActionTy Action(
OMPBuilder.getOrCreateRuntimeFunction(
2112 unsigned Index,
const VarDecl *Var) {
2133 Args.push_back(&LHSArg);
2134 Args.push_back(&RHSArg);
2140 llvm::GlobalValue::InternalLinkage, Name,
2143 Fn->setDoesNotRecurse();
2160 for (
unsigned I = 0,
E = AssignmentOps.size(); I <
E; ++I) {
2161 const auto *DestVar =
2162 cast<VarDecl>(cast<DeclRefExpr>(DestExprs[I])->getDecl());
2165 const auto *SrcVar =
2166 cast<VarDecl>(cast<DeclRefExpr>(SrcExprs[I])->getDecl());
2169 const auto *VD = cast<DeclRefExpr>(CopyprivateVars[I])->getDecl();
2171 CGF.
EmitOMPCopy(
Type, DestAddr, SrcAddr, DestVar, SrcVar, AssignmentOps[I]);
2186 assert(CopyprivateVars.size() == SrcExprs.size() &&
2187 CopyprivateVars.size() == DstExprs.size() &&
2188 CopyprivateVars.size() == AssignmentOps.size());
2200 if (!CopyprivateVars.empty()) {
2203 C.getIntTypeForBitwidth(32, 1);
2204 DidIt = CGF.
CreateMemTemp(KmpInt32Ty,
".omp.copyprivate.did_it");
2209 CommonActionTy Action(
OMPBuilder.getOrCreateRuntimeFunction(
2226 llvm::APInt ArraySize(32, CopyprivateVars.size());
2227 QualType CopyprivateArrayTy =
C.getConstantArrayType(
2232 CGF.
CreateMemTemp(CopyprivateArrayTy,
".omp.copyprivate.cpr_list");
2233 for (
unsigned I = 0,
E = CopyprivateVars.size(); I <
E; ++I) {
2245 SrcExprs, DstExprs, AssignmentOps,
Loc);
2246 llvm::Value *BufSize = CGF.
getTypeSize(CopyprivateArrayTy);
2250 llvm::Value *Args[] = {
2254 CL.emitRawPointer(CGF),
2275 CommonActionTy Action(
OMPBuilder.getOrCreateRuntimeFunction(
2290 if (Kind == OMPD_for)
2291 Flags = OMP_IDENT_BARRIER_IMPL_FOR;
2292 else if (Kind == OMPD_sections)
2293 Flags = OMP_IDENT_BARRIER_IMPL_SECTIONS;
2294 else if (Kind == OMPD_single)
2295 Flags = OMP_IDENT_BARRIER_IMPL_SINGLE;
2296 else if (Kind == OMPD_barrier)
2297 Flags = OMP_IDENT_BARRIER_EXPL;
2299 Flags = OMP_IDENT_BARRIER_IMPL;
2311 ScheduleKind = OMPC_SCHEDULE_static;
2313 llvm::APInt ChunkSize(32, 1);
2323 bool ForceSimpleCall) {
2325 auto *OMPRegionInfo =
2328 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
2331 CGF.
Builder.restoreIP(AfterIP);
2344 if (OMPRegionInfo) {
2345 if (!ForceSimpleCall && OMPRegionInfo->hasCancel()) {
2348 OMPRTL___kmpc_cancel_barrier),
2357 CGF.
Builder.CreateCondBr(Cmp, ExitBB, ContBB);
2374 Expr *ME,
bool IsFatal) {
2376 : llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
2379 llvm::Value *Args[] = {
2381 llvm::ConstantInt::get(
CGM.
Int32Ty, IsFatal ? 2 : 1),
2390 bool Chunked,
bool Ordered) {
2391 switch (ScheduleKind) {
2392 case OMPC_SCHEDULE_static:
2393 return Chunked ? (Ordered ? OMP_ord_static_chunked : OMP_sch_static_chunked)
2394 : (Ordered ? OMP_ord_static : OMP_sch_static);
2395 case OMPC_SCHEDULE_dynamic:
2396 return Ordered ? OMP_ord_dynamic_chunked : OMP_sch_dynamic_chunked;
2397 case OMPC_SCHEDULE_guided:
2398 return Ordered ? OMP_ord_guided_chunked : OMP_sch_guided_chunked;
2399 case OMPC_SCHEDULE_runtime:
2400 return Ordered ? OMP_ord_runtime : OMP_sch_runtime;
2401 case OMPC_SCHEDULE_auto:
2402 return Ordered ? OMP_ord_auto : OMP_sch_auto;
2404 assert(!Chunked &&
"chunk was specified but schedule kind not known");
2405 return Ordered ? OMP_ord_static : OMP_sch_static;
2407 llvm_unreachable(
"Unexpected runtime schedule");
2411static OpenMPSchedType
2414 return Chunked ? OMP_dist_sch_static_chunked : OMP_dist_sch_static;
2418 bool Chunked)
const {
2419 OpenMPSchedType Schedule =
2421 return Schedule == OMP_sch_static;
2427 return Schedule == OMP_dist_sch_static;
2431 bool Chunked)
const {
2432 OpenMPSchedType Schedule =
2434 return Schedule == OMP_sch_static_chunked;
2440 return Schedule == OMP_dist_sch_static_chunked;
2444 OpenMPSchedType Schedule =
2446 assert(Schedule != OMP_sch_static_chunked &&
"cannot be chunked here");
2447 return Schedule != OMP_sch_static;
2455 case OMPC_SCHEDULE_MODIFIER_monotonic:
2456 Modifier = OMP_sch_modifier_monotonic;
2458 case OMPC_SCHEDULE_MODIFIER_nonmonotonic:
2459 Modifier = OMP_sch_modifier_nonmonotonic;
2461 case OMPC_SCHEDULE_MODIFIER_simd:
2462 if (Schedule == OMP_sch_static_chunked)
2463 Schedule = OMP_sch_static_balanced_chunked;
2470 case OMPC_SCHEDULE_MODIFIER_monotonic:
2471 Modifier = OMP_sch_modifier_monotonic;
2473 case OMPC_SCHEDULE_MODIFIER_nonmonotonic:
2474 Modifier = OMP_sch_modifier_nonmonotonic;
2476 case OMPC_SCHEDULE_MODIFIER_simd:
2477 if (Schedule == OMP_sch_static_chunked)
2478 Schedule = OMP_sch_static_balanced_chunked;
2490 if (CGM.
getLangOpts().OpenMP >= 50 && Modifier == 0) {
2491 if (!(Schedule == OMP_sch_static_chunked || Schedule == OMP_sch_static ||
2492 Schedule == OMP_sch_static_balanced_chunked ||
2493 Schedule == OMP_ord_static_chunked || Schedule == OMP_ord_static ||
2494 Schedule == OMP_dist_sch_static_chunked ||
2495 Schedule == OMP_dist_sch_static))
2496 Modifier = OMP_sch_modifier_nonmonotonic;
2498 return Schedule | Modifier;
2508 ScheduleKind.
Schedule, DispatchValues.
Chunk !=
nullptr, Ordered);
2510 (Schedule != OMP_sch_static && Schedule != OMP_sch_static_chunked &&
2511 Schedule != OMP_ord_static && Schedule != OMP_ord_static_chunked &&
2512 Schedule != OMP_sch_static_balanced_chunked));
2519 llvm::Value *Chunk = DispatchValues.
Chunk ? DispatchValues.
Chunk
2520 : CGF.
Builder.getIntN(IVSize, 1);
2521 llvm::Value *Args[] = {
2525 CGM, Schedule, ScheduleKind.
M1, ScheduleKind.
M2)),
2528 CGF.
Builder.getIntN(IVSize, 1),
2545 CodeGenFunction &CGF, llvm::Value *UpdateLocation, llvm::Value *ThreadId,
2546 llvm::FunctionCallee ForStaticInitFunction, OpenMPSchedType Schedule,
2553 assert(Schedule == OMP_sch_static || Schedule == OMP_sch_static_chunked ||
2554 Schedule == OMP_sch_static_balanced_chunked ||
2555 Schedule == OMP_ord_static || Schedule == OMP_ord_static_chunked ||
2556 Schedule == OMP_dist_sch_static ||
2557 Schedule == OMP_dist_sch_static_chunked);
2564 llvm::Value *Chunk = Values.
Chunk;
2565 if (Chunk ==
nullptr) {
2566 assert((Schedule == OMP_sch_static || Schedule == OMP_ord_static ||
2567 Schedule == OMP_dist_sch_static) &&
2568 "expected static non-chunked schedule");
2572 assert((Schedule == OMP_sch_static_chunked ||
2573 Schedule == OMP_sch_static_balanced_chunked ||
2574 Schedule == OMP_ord_static_chunked ||
2575 Schedule == OMP_dist_sch_static_chunked) &&
2576 "expected static chunked schedule");
2578 llvm::Value *Args[] = {
2601 "Expected loop-based or sections-based directive.");
2604 ? OMP_IDENT_WORK_LOOP
2605 : OMP_IDENT_WORK_SECTIONS);
2607 llvm::FunctionCallee StaticInitFunction =
2612 ScheduleNum, ScheduleKind.
M1, ScheduleKind.
M2, Values);
2619 OpenMPSchedType ScheduleNum =
2621 llvm::Value *UpdatedLocation =
2624 llvm::FunctionCallee StaticInitFunction;
2625 bool isGPUDistribute =
2627 StaticInitFunction =
OMPBuilder.createForStaticInitFunction(
2638 assert((DKind == OMPD_distribute || DKind == OMPD_for ||
2639 DKind == OMPD_sections) &&
2640 "Expected distribute, for, or sections directive kind");
2644 llvm::Value *Args[] = {
2647 (DKind == OMPD_target_teams_loop)
2648 ? OMP_IDENT_WORK_DISTRIBUTE
2650 ? OMP_IDENT_WORK_LOOP
2651 : OMP_IDENT_WORK_SECTIONS),
2658 CGM.
getModule(), OMPRTL___kmpc_distribute_static_fini),
2687 llvm::Value *Args[] = {
2695 OMPBuilder.createDispatchNextFunction(IVSize, IVSigned), Args);
2702 const Expr *Message) {
2704 return llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
2720 Severity == OMPC_SEVERITY_warning ? 1 : 2);
2732 const Expr *Message) {
2741 RuntimeFunction FnID = OMPRTL___kmpc_push_num_threads;
2742 if (Modifier == OMPC_NUMTHREADS_strict) {
2743 FnID = OMPRTL___kmpc_push_num_threads_strict;
2752 ProcBindKind ProcBind,
2756 assert(ProcBind != OMP_PROC_BIND_unknown &&
"Unsupported proc_bind value.");
2758 llvm::Value *Args[] = {
2760 llvm::ConstantInt::get(
CGM.
IntTy,
unsigned(ProcBind),
true)};
2782enum KmpTaskTFields {
2812 llvm::OpenMPIRBuilder::EmitMetadataErrorReportFunctionTy &&ErrorReportFn =
2813 [
this](llvm::OpenMPIRBuilder::EmitMetadataErrorKind Kind,
2814 const llvm::TargetRegionEntryInfo &EntryInfo) ->
void {
2816 if (Kind != llvm::OpenMPIRBuilder::EMIT_MD_GLOBAL_VAR_LINK_ERROR) {
2820 if (I->getFirst().getUniqueID().getDevice() == EntryInfo.DeviceID &&
2821 I->getFirst().getUniqueID().getFile() == EntryInfo.FileID) {
2823 I->getFirst(), EntryInfo.Line, 1);
2829 case llvm::OpenMPIRBuilder::EMIT_MD_TARGET_REGION_ERROR: {
2832 "%0 is incorrect: either the "
2833 "address or the ID is invalid.");
2836 case llvm::OpenMPIRBuilder::EMIT_MD_DECLARE_TARGET_ERROR: {
2839 "variable %0 is incorrect: the "
2840 "address is invalid.");
2843 case llvm::OpenMPIRBuilder::EMIT_MD_GLOBAL_VAR_LINK_ERROR: {
2846 "Offloading entry for declare target variable is incorrect: the "
2847 "address is invalid.");
2853 OMPBuilder.createOffloadEntriesAndInfoMetadata(ErrorReportFn);
2860 QualType KmpRoutineEntryTyArgs[] = {KmpInt32Ty,
C.VoidPtrTy};
2863 C.getFunctionType(KmpInt32Ty, KmpRoutineEntryTyArgs, EPI));
2869struct PrivateHelpersTy {
2870 PrivateHelpersTy(
const Expr *OriginalRef,
const VarDecl *Original,
2872 : OriginalRef(OriginalRef), Original(Original), PrivateCopy(PrivateCopy),
2873 PrivateElemInit(PrivateElemInit) {}
2874 PrivateHelpersTy(
const VarDecl *Original) : Original(Original) {}
2875 const Expr *OriginalRef =
nullptr;
2876 const VarDecl *Original =
nullptr;
2877 const VarDecl *PrivateCopy =
nullptr;
2878 const VarDecl *PrivateElemInit =
nullptr;
2879 bool isLocalPrivate()
const {
2880 return !OriginalRef && !PrivateCopy && !PrivateElemInit;
2883typedef std::pair<
CharUnits , PrivateHelpersTy> PrivateDataTy;
2888 if (!CVD->
hasAttr<OMPAllocateDeclAttr>())
2890 const auto *AA = CVD->
getAttr<OMPAllocateDeclAttr>();
2892 return !(AA->getAllocatorType() == OMPAllocateDeclAttr::OMPDefaultMemAlloc &&
2893 !AA->getAllocator());
2898 if (!Privates.empty()) {
2903 RecordDecl *RD =
C.buildImplicitRecord(
".kmp_privates.t");
2905 for (
const auto &Pair : Privates) {
2906 const VarDecl *VD = Pair.second.Original;
2910 if (Pair.second.isLocalPrivate()) {
2933 QualType KmpRoutineEntryPointerQTy) {
2953 CanQualType KmpCmplrdataTy =
C.getCanonicalTagType(UD);
2954 RecordDecl *RD =
C.buildImplicitRecord(
"kmp_task_t");
2984 RecordDecl *RD =
C.buildImplicitRecord(
"kmp_task_t_with_privates");
3004static llvm::Function *
3007 QualType KmpTaskTWithPrivatesPtrQTy,
3009 QualType SharedsPtrTy, llvm::Function *TaskFunction,
3010 llvm::Value *TaskPrivatesMap) {
3018 Args.push_back(&GtidArg);
3019 Args.push_back(&TaskTypeArg);
3020 const auto &TaskEntryFnInfo =
3022 llvm::FunctionType *TaskEntryTy =
3025 auto *TaskEntry = llvm::Function::Create(
3026 TaskEntryTy, llvm::GlobalValue::InternalLinkage, Name, &CGM.
getModule());
3028 TaskEntry->setDoesNotRecurse();
3043 const auto *KmpTaskTWithPrivatesQTyRD =
3048 auto PartIdFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTPartId);
3050 llvm::Value *PartidParam = PartIdLVal.
getPointer(CGF);
3052 auto SharedsFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTShareds);
3058 auto PrivatesFI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin(), 1);
3059 llvm::Value *PrivatesParam;
3060 if (PrivatesFI != KmpTaskTWithPrivatesQTyRD->field_end()) {
3065 PrivatesParam = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
3068 llvm::Value *CommonArgs[] = {
3069 GtidParam, PartidParam, PrivatesParam, TaskPrivatesMap,
3075 std::end(CommonArgs));
3077 auto LBFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound);
3080 auto UBFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound);
3083 auto StFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTStride);
3086 auto LIFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLastIter);
3089 auto RFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTReductions);
3092 CallArgs.push_back(LBParam);
3093 CallArgs.push_back(UBParam);
3094 CallArgs.push_back(StParam);
3095 CallArgs.push_back(LIParam);
3096 CallArgs.push_back(RParam);
3098 CallArgs.push_back(SharedsParam);
3111 QualType KmpTaskTWithPrivatesPtrQTy,
3112 QualType KmpTaskTWithPrivatesQTy) {
3120 Args.push_back(&GtidArg);
3121 Args.push_back(&TaskTypeArg);
3122 const auto &DestructorFnInfo =
3124 llvm::FunctionType *DestructorFnTy =
3128 auto *DestructorFn =
3129 llvm::Function::Create(DestructorFnTy, llvm::GlobalValue::InternalLinkage,
3133 DestructorFn->setDoesNotRecurse();
3141 const auto *KmpTaskTWithPrivatesQTyRD =
3143 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin());
3145 for (
const auto *Field : FI->getType()->castAsRecordDecl()->fields()) {
3147 Field->getType().isDestructedType()) {
3153 return DestructorFn;
3173 C,
nullptr,
Loc,
nullptr,
3174 C.getPointerType(PrivatesQTy).withConst().withRestrict(),
3176 Args.push_back(&TaskPrivatesArg);
3177 llvm::DenseMap<CanonicalDeclPtr<const VarDecl>,
unsigned> PrivateVarsPos;
3178 unsigned Counter = 1;
3179 for (
const Expr *
E :
Data.PrivateVars) {
3181 C,
nullptr,
Loc,
nullptr,
3182 C.getPointerType(
C.getPointerType(
E->
getType()))
3186 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(
E)->getDecl());
3187 PrivateVarsPos[VD] = Counter;
3190 for (
const Expr *
E :
Data.FirstprivateVars) {
3192 C,
nullptr,
Loc,
nullptr,
3193 C.getPointerType(
C.getPointerType(
E->
getType()))
3197 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(
E)->getDecl());
3198 PrivateVarsPos[VD] = Counter;
3201 for (
const Expr *
E :
Data.LastprivateVars) {
3203 C,
nullptr,
Loc,
nullptr,
3204 C.getPointerType(
C.getPointerType(
E->
getType()))
3208 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(
E)->getDecl());
3209 PrivateVarsPos[VD] = Counter;
3215 Ty =
C.getPointerType(Ty);
3217 Ty =
C.getPointerType(Ty);
3219 C,
nullptr,
Loc,
nullptr,
3220 C.getPointerType(
C.getPointerType(Ty)).withConst().withRestrict(),
3222 PrivateVarsPos[VD] = Counter;
3225 const auto &TaskPrivatesMapFnInfo =
3227 llvm::FunctionType *TaskPrivatesMapTy =
3231 auto *TaskPrivatesMap = llvm::Function::Create(
3232 TaskPrivatesMapTy, llvm::GlobalValue::InternalLinkage, Name,
3235 TaskPrivatesMapFnInfo);
3237 TaskPrivatesMap->removeFnAttr(llvm::Attribute::NoInline);
3238 TaskPrivatesMap->removeFnAttr(llvm::Attribute::OptimizeNone);
3239 TaskPrivatesMap->addFnAttr(llvm::Attribute::AlwaysInline);
3243 TaskPrivatesMapFnInfo, Args,
Loc,
Loc);
3251 for (
const FieldDecl *Field : PrivatesQTyRD->fields()) {
3253 const VarDecl *VD = Args[PrivateVarsPos[Privates[Counter].second.Original]];
3262 return TaskPrivatesMap;
3274 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->
field_begin());
3288 if ((!IsTargetTask && !
Data.FirstprivateVars.empty() && ForDup) ||
3289 (IsTargetTask && KmpTaskSharedsPtr.
isValid())) {
3297 for (
const PrivateDataTy &Pair : Privates) {
3299 if (Pair.second.isLocalPrivate()) {
3303 const VarDecl *VD = Pair.second.PrivateCopy;
3305 if (
Init && (!ForDup || (isa<CXXConstructExpr>(
Init) &&
3308 if (
const VarDecl *Elem = Pair.second.PrivateElemInit) {
3309 const VarDecl *OriginalVD = Pair.second.Original;
3315 if (IsTargetTask && !SharedField) {
3316 assert(isa<ImplicitParamDecl>(OriginalVD) &&
3319 ->getNumParams() == 0 &&
3320 isa<TranslationUnitDecl>(
3322 ->getDeclContext()) &&
3323 "Expected artificial target data variable.");
3326 }
else if (ForDup) {
3330 C.getDeclAlign(OriginalVD)),
3334 Pair.second.Original->getCanonicalDecl()) > 0 ||
3336 SharedRefLValue = CGF.
EmitLValue(Pair.second.OriginalRef);
3339 InlinedOpenMPRegionRAII Region(
3342 SharedRefLValue = CGF.
EmitLValue(Pair.second.OriginalRef);
3354 [&CGF, Elem,
Init, &CapturesInfo](
Address DestElement,
3357 CodeGenFunction::OMPPrivateScope InitScope(CGF);
3358 InitScope.addPrivate(Elem, SrcElement);
3359 (void)InitScope.Privatize();
3361 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(
3362 CGF, &CapturesInfo);
3363 CGF.EmitAnyExprToMem(Init, DestElement,
3364 Init->getType().getQualifiers(),
3370 InitScope.addPrivate(Elem, SharedRefLValue.
getAddress());
3371 (void)InitScope.Privatize();
3387 bool InitRequired =
false;
3388 for (
const PrivateDataTy &Pair : Privates) {
3389 if (Pair.second.isLocalPrivate())
3391 const VarDecl *VD = Pair.second.PrivateCopy;
3393 InitRequired = InitRequired || (isa_and_nonnull<CXXConstructExpr>(
Init) &&
3398 return InitRequired;
3415 QualType KmpTaskTWithPrivatesPtrQTy,
3423 KmpTaskTWithPrivatesPtrQTy,
3426 KmpTaskTWithPrivatesPtrQTy,
3430 Args.push_back(&DstArg);
3431 Args.push_back(&SrcArg);
3432 Args.push_back(&LastprivArg);
3433 const auto &TaskDupFnInfo =
3437 auto *TaskDup = llvm::Function::Create(
3438 TaskDupTy, llvm::GlobalValue::InternalLinkage, Name, &CGM.
getModule());
3440 TaskDup->setDoesNotRecurse();
3450 auto LIFI = std::next(KmpTaskTQTyRD->
field_begin(), KmpTaskTLastIter);
3452 TDBase, *KmpTaskTWithPrivatesQTyRD->
field_begin());
3460 assert(!Privates.empty());
3462 if (!
Data.FirstprivateVars.empty()) {
3467 TDBase, *KmpTaskTWithPrivatesQTyRD->
field_begin());
3476 SharedsTy, SharedsPtrTy,
Data, Privates,
true);
3486 for (
const PrivateDataTy &
P : Privates) {
3487 if (
P.second.isLocalPrivate())
3489 QualType Ty =
P.second.Original->getType().getNonReferenceType();
3498class OMPIteratorGeneratorScope final
3504 OMPIteratorGeneratorScope() =
delete;
3505 OMPIteratorGeneratorScope(OMPIteratorGeneratorScope &) =
delete;
3513 for (
unsigned I = 0, End =
E->numOfIterators(); I < End; ++I) {
3515 const auto *VD = cast<VarDecl>(
E->getIteratorDecl(I));
3524 for (
unsigned I = 0, End =
E->numOfIterators(); I < End; ++I) {
3538 llvm::Value *N = Uppers[I];
3546 ? CGF.
Builder.CreateICmpSLT(CVal, N)
3547 : CGF.
Builder.CreateICmpULT(CVal, N);
3556 ~OMPIteratorGeneratorScope() {
3559 for (
unsigned I =
E->numOfIterators(); I > 0; --I) {
3566 CGF.
EmitBlock(ExitDests[I - 1].getBlock(), I == 1);
3572static std::pair<llvm::Value *, llvm::Value *>
3574 const auto *OASE = dyn_cast<OMPArrayShapingExpr>(
E);
3577 const Expr *
Base = OASE->getBase();
3582 llvm::Value *SizeVal;
3585 SizeVal = CGF.
getTypeSize(OASE->getBase()->getType()->getPointeeType());
3586 for (
const Expr *SE : OASE->getDimensions()) {
3590 SizeVal = CGF.
Builder.CreateNUWMul(SizeVal, Sz);
3592 }
else if (
const auto *ASE =
3596 llvm::Value *UpAddr = CGF.
Builder.CreateConstGEP1_32(
3600 llvm::Value *UpIntPtr = CGF.
Builder.CreatePtrToInt(UpAddr, CGF.
SizeTy);
3601 SizeVal = CGF.
Builder.CreateNUWSub(UpIntPtr, LowIntPtr);
3605 return std::make_pair(
Addr, SizeVal);
3610 QualType FlagsTy =
C.getIntTypeForBitwidth(32,
false);
3611 if (KmpTaskAffinityInfoTy.
isNull()) {
3613 C.buildImplicitRecord(
"kmp_task_affinity_info_t");
3619 KmpTaskAffinityInfoTy =
C.getCanonicalTagType(KmpAffinityInfoRD);
3626 llvm::Function *TaskFunction,
QualType SharedsTy,
3631 const auto *I =
Data.PrivateCopies.begin();
3632 for (
const Expr *
E :
Data.PrivateVars) {
3633 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(
E)->getDecl());
3634 Privates.emplace_back(
3636 PrivateHelpersTy(
E, VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()),
3640 I =
Data.FirstprivateCopies.begin();
3641 const auto *IElemInitRef =
Data.FirstprivateInits.begin();
3642 for (
const Expr *
E :
Data.FirstprivateVars) {
3643 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(
E)->getDecl());
3644 Privates.emplace_back(
3647 E, VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()),
3648 cast<VarDecl>(cast<DeclRefExpr>(*IElemInitRef)->getDecl())));
3652 I =
Data.LastprivateCopies.begin();
3653 for (
const Expr *
E :
Data.LastprivateVars) {
3654 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(
E)->getDecl());
3655 Privates.emplace_back(
3657 PrivateHelpersTy(
E, VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()),
3665 Privates.emplace_back(
C.getDeclAlign(VD), PrivateHelpersTy(VD));
3667 llvm::stable_sort(Privates,
3668 [](
const PrivateDataTy &L,
const PrivateDataTy &R) {
3669 return L.first > R.first;
3671 QualType KmpInt32Ty =
C.getIntTypeForBitwidth(32, 1);
3682 assert((
D.getDirectiveKind() == OMPD_task ||
3685 "Expected taskloop, task or target directive");
3694 const RecordDecl *KmpTaskTWithPrivatesQTyRD =
3697 C.getCanonicalTagType(KmpTaskTWithPrivatesQTyRD);
3698 QualType KmpTaskTWithPrivatesPtrQTy =
3699 C.getPointerType(KmpTaskTWithPrivatesQTy);
3700 llvm::Type *KmpTaskTWithPrivatesPtrTy = CGF.
Builder.getPtrTy(0);
3701 llvm::Value *KmpTaskTWithPrivatesTySize =
3703 QualType SharedsPtrTy =
C.getPointerType(SharedsTy);
3706 llvm::Value *TaskPrivatesMap =
nullptr;
3707 llvm::Type *TaskPrivatesMapTy =
3708 std::next(TaskFunction->arg_begin(), 3)->getType();
3709 if (!Privates.empty()) {
3710 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->
field_begin());
3714 TaskPrivatesMap, TaskPrivatesMapTy);
3716 TaskPrivatesMap = llvm::ConstantPointerNull::get(
3717 cast<llvm::PointerType>(TaskPrivatesMapTy));
3722 CGM,
Loc,
D.getDirectiveKind(), KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy,
3723 KmpTaskTWithPrivatesQTy,
KmpTaskTQTy, SharedsPtrTy, TaskFunction,
3735 DestructorsFlag = 0x8,
3736 PriorityFlag = 0x20,
3737 DetachableFlag = 0x40,
3739 unsigned Flags =
Data.Tied ? TiedFlag : 0;
3740 bool NeedsCleanup =
false;
3741 if (!Privates.empty()) {
3745 Flags = Flags | DestructorsFlag;
3747 if (
Data.Priority.getInt())
3748 Flags = Flags | PriorityFlag;
3750 Flags = Flags | DetachableFlag;
3751 llvm::Value *TaskFlags =
3752 Data.Final.getPointer()
3753 ? CGF.
Builder.CreateSelect(
Data.Final.getPointer(),
3754 CGF.
Builder.getInt32(FinalFlag),
3756 : CGF.
Builder.getInt32(
Data.Final.getInt() ? FinalFlag : 0);
3757 TaskFlags = CGF.
Builder.CreateOr(TaskFlags, CGF.
Builder.getInt32(Flags));
3758 llvm::Value *SharedsSize =
CGM.
getSize(
C.getTypeSizeInChars(SharedsTy));
3763 llvm::Value *NewTask;
3770 llvm::Value *DeviceID;
3775 DeviceID = CGF.
Builder.getInt64(OMP_DEVICEID_UNDEF);
3776 AllocArgs.push_back(DeviceID);
3797 llvm::Value *Tid =
getThreadID(CGF, DC->getBeginLoc());
3798 Tid = CGF.
Builder.CreateIntCast(Tid, CGF.
IntTy,
false);
3801 CGM.
getModule(), OMPRTL___kmpc_task_allow_completion_event),
3802 {Loc, Tid, NewTask});
3813 llvm::Value *NumOfElements =
nullptr;
3814 unsigned NumAffinities = 0;
3816 if (
const Expr *Modifier =
C->getModifier()) {
3817 const auto *IE = cast<OMPIteratorExpr>(Modifier->IgnoreParenImpCasts());
3818 for (
unsigned I = 0,
E = IE->numOfIterators(); I <
E; ++I) {
3822 NumOfElements ? CGF.
Builder.CreateNUWMul(NumOfElements, Sz) : Sz;
3825 NumAffinities +=
C->varlist_size();
3830 enum RTLAffinityInfoFieldsTy { BaseAddr, Len, Flags };
3832 QualType KmpTaskAffinityInfoArrayTy;
3833 if (NumOfElements) {
3834 NumOfElements = CGF.
Builder.CreateNUWAdd(
3835 llvm::ConstantInt::get(CGF.
SizeTy, NumAffinities), NumOfElements);
3838 C.getIntTypeForBitwidth(
C.getTypeSize(
C.getSizeType()), 0),
3842 KmpTaskAffinityInfoArrayTy =
C.getVariableArrayType(
3850 NumOfElements = CGF.
Builder.CreateIntCast(NumOfElements, CGF.
Int32Ty,
3853 KmpTaskAffinityInfoArrayTy =
C.getConstantArrayType(
3855 llvm::APInt(
C.getTypeSize(
C.getSizeType()), NumAffinities),
nullptr,
3858 CGF.
CreateMemTemp(KmpTaskAffinityInfoArrayTy,
".affs.arr.addr");
3860 NumOfElements = llvm::ConstantInt::get(
CGM.
Int32Ty, NumAffinities,
3867 bool HasIterator =
false;
3869 if (
C->getModifier()) {
3873 for (
const Expr *
E :
C->varlist()) {
3882 Base, *std::next(KmpAffinityInfoRD->field_begin(), BaseAddr));
3887 Base, *std::next(KmpAffinityInfoRD->field_begin(), Len));
3901 const Expr *Modifier =
C->getModifier();
3904 OMPIteratorGeneratorScope IteratorScope(
3906 for (
const Expr *
E :
C->varlist()) {
3916 Base, *std::next(KmpAffinityInfoRD->field_begin(), BaseAddr));
3921 Base, *std::next(KmpAffinityInfoRD->field_begin(), Len));
3923 Idx = CGF.
Builder.CreateNUWAdd(
3924 Idx, llvm::ConstantInt::get(Idx->getType(), 1));
3939 CGM.
getModule(), OMPRTL___kmpc_omp_reg_task_with_affinity),
3940 {LocRef, GTid, NewTask, NumOfElements, AffinListPtr});
3942 llvm::Value *NewTaskNewTaskTTy =
3944 NewTask, KmpTaskTWithPrivatesPtrTy);
3946 KmpTaskTWithPrivatesQTy);
3957 *std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTShareds)),
3966 if (!Privates.empty()) {
3968 SharedsTy, SharedsPtrTy,
Data, Privates,
3973 CGM,
Loc,
D, KmpTaskTWithPrivatesPtrQTy, KmpTaskTWithPrivatesQTyRD,
3974 KmpTaskTQTyRD, SharedsTy, SharedsPtrTy,
Data, Privates,
3975 !
Data.LastprivateVars.empty());
3979 enum {
Priority = 0, Destructors = 1 };
3981 auto FI = std::next(KmpTaskTQTyRD->field_begin(), Data1);
3982 const auto *KmpCmplrdataUD = (*FI)->getType()->castAsRecordDecl();
3983 assert(KmpCmplrdataUD->isUnion());
3986 CGM,
Loc, KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy,
3987 KmpTaskTWithPrivatesQTy);
3990 Data1LV, *std::next(KmpCmplrdataUD->field_begin(), Destructors));
3996 if (
Data.Priority.getInt()) {
3998 TDBase, *std::next(KmpTaskTQTyRD->field_begin(), Data2));
4000 Data2LV, *std::next(KmpCmplrdataUD->field_begin(),
Priority));
4003 Result.NewTask = NewTask;
4004 Result.TaskEntry = TaskEntry;
4005 Result.NewTaskNewTaskTTy = NewTaskNewTaskTTy;
4007 Result.KmpTaskTQTyRD = KmpTaskTQTyRD;
4013 RTLDependenceKindTy DepKind;
4015 case OMPC_DEPEND_in:
4016 DepKind = RTLDependenceKindTy::DepIn;
4019 case OMPC_DEPEND_out:
4020 case OMPC_DEPEND_inout:
4021 DepKind = RTLDependenceKindTy::DepInOut;
4023 case OMPC_DEPEND_mutexinoutset:
4024 DepKind = RTLDependenceKindTy::DepMutexInOutSet;
4026 case OMPC_DEPEND_inoutset:
4027 DepKind = RTLDependenceKindTy::DepInOutSet;
4029 case OMPC_DEPEND_outallmemory:
4030 DepKind = RTLDependenceKindTy::DepOmpAllMem;
4032 case OMPC_DEPEND_source:
4033 case OMPC_DEPEND_sink:
4034 case OMPC_DEPEND_depobj:
4035 case OMPC_DEPEND_inoutallmemory:
4037 llvm_unreachable(
"Unknown task dependence type");
4045 FlagsTy =
C.getIntTypeForBitwidth(
C.getTypeSize(
C.BoolTy),
false);
4046 if (KmpDependInfoTy.
isNull()) {
4047 RecordDecl *KmpDependInfoRD =
C.buildImplicitRecord(
"kmp_depend_info");
4053 KmpDependInfoTy =
C.getCanonicalTagType(KmpDependInfoRD);
4057std::pair<llvm::Value *, LValue>
4070 CGF,
Base.getAddress(),
4071 llvm::ConstantInt::get(CGF.
IntPtrTy, -1,
true));
4077 *std::next(KmpDependInfoRD->field_begin(),
4078 static_cast<unsigned int>(RTLDependInfoFields::BaseAddr)));
4080 return std::make_pair(NumDeps,
Base);
4084 llvm::PointerUnion<unsigned *, LValue *> Pos,
4094 OMPIteratorGeneratorScope IteratorScope(
4095 CGF, cast_or_null<OMPIteratorExpr>(
4096 Data.IteratorExpr ?
Data.IteratorExpr->IgnoreParenImpCasts()
4108 Size = llvm::ConstantInt::get(CGF.
SizeTy, 0);
4111 if (
unsigned *
P = dyn_cast<unsigned *>(Pos)) {
4115 assert(
E &&
"Expected a non-null expression");
4116 LValue &PosLVal = *cast<LValue *>(Pos);
4124 *std::next(KmpDependInfoRD->field_begin(),
4125 static_cast<unsigned int>(RTLDependInfoFields::BaseAddr)));
4129 Base, *std::next(KmpDependInfoRD->field_begin(),
4130 static_cast<unsigned int>(RTLDependInfoFields::Len)));
4136 *std::next(KmpDependInfoRD->field_begin(),
4137 static_cast<unsigned int>(RTLDependInfoFields::Flags)));
4139 llvm::ConstantInt::get(LLVMFlagsTy,
static_cast<unsigned int>(DepKind)),
4141 if (
unsigned *
P = dyn_cast<unsigned *>(Pos)) {
4144 LValue &PosLVal = *cast<LValue *>(Pos);
4146 Idx = CGF.
Builder.CreateNUWAdd(Idx,
4147 llvm::ConstantInt::get(Idx->getType(), 1));
4156 assert(
Data.DepKind == OMPC_DEPEND_depobj &&
4157 "Expected depobj dependency kind.");
4162 OMPIteratorGeneratorScope IteratorScope(
4163 CGF, cast_or_null<OMPIteratorExpr>(
4164 Data.IteratorExpr ?
Data.IteratorExpr->IgnoreParenImpCasts()
4167 llvm::Value *NumDeps;
4170 std::tie(NumDeps,
Base) =
4174 C.getUIntPtrType());
4178 llvm::Value *Add = CGF.
Builder.CreateNUWAdd(PrevVal, NumDeps);
4180 SizeLVals.push_back(NumLVal);
4183 for (
unsigned I = 0,
E = SizeLVals.size(); I <
E; ++I) {
4186 Sizes.push_back(Size);
4196 assert(
Data.DepKind == OMPC_DEPEND_depobj &&
4197 "Expected depobj dependency kind.");
4200 OMPIteratorGeneratorScope IteratorScope(
4201 CGF, cast_or_null<OMPIteratorExpr>(
4202 Data.IteratorExpr ?
Data.IteratorExpr->IgnoreParenImpCasts()
4205 llvm::Value *NumDeps;
4208 std::tie(NumDeps,
Base) =
4212 llvm::Value *Size = CGF.
Builder.CreateNUWMul(
4221 llvm::Value *Add = CGF.
Builder.CreateNUWAdd(Pos, NumDeps);
4231 return D.DepExprs.empty();
4237 llvm::Value *NumOfElements =
nullptr;
4238 unsigned NumDependencies = std::accumulate(
4239 Dependencies.begin(), Dependencies.end(), 0,
4241 return D.DepKind == OMPC_DEPEND_depobj
4243 : (V + (D.IteratorExpr ? 0 : D.DepExprs.size()));
4247 bool HasDepobjDeps =
false;
4248 bool HasRegularWithIterators =
false;
4249 llvm::Value *NumOfDepobjElements = llvm::ConstantInt::get(CGF.
IntPtrTy, 0);
4250 llvm::Value *NumOfRegularWithIterators =
4251 llvm::ConstantInt::get(CGF.
IntPtrTy, 0);
4255 if (
D.DepKind == OMPC_DEPEND_depobj) {
4258 for (llvm::Value *Size : Sizes) {
4259 NumOfDepobjElements =
4260 CGF.
Builder.CreateNUWAdd(NumOfDepobjElements, Size);
4262 HasDepobjDeps =
true;
4267 if (
const auto *IE = cast_or_null<OMPIteratorExpr>(
D.IteratorExpr)) {
4268 llvm::Value *ClauseIteratorSpace =
4269 llvm::ConstantInt::get(CGF.
IntPtrTy, 1);
4270 for (
unsigned I = 0,
E = IE->numOfIterators(); I <
E; ++I) {
4273 ClauseIteratorSpace = CGF.
Builder.CreateNUWMul(Sz, ClauseIteratorSpace);
4275 llvm::Value *NumClauseDeps = CGF.
Builder.CreateNUWMul(
4276 ClauseIteratorSpace,
4277 llvm::ConstantInt::get(CGF.
IntPtrTy,
D.DepExprs.size()));
4278 NumOfRegularWithIterators =
4279 CGF.
Builder.CreateNUWAdd(NumOfRegularWithIterators, NumClauseDeps);
4280 HasRegularWithIterators =
true;
4286 if (HasDepobjDeps || HasRegularWithIterators) {
4287 NumOfElements = llvm::ConstantInt::get(
CGM.
IntPtrTy, NumDependencies,
4289 if (HasDepobjDeps) {
4291 CGF.
Builder.CreateNUWAdd(NumOfDepobjElements, NumOfElements);
4293 if (HasRegularWithIterators) {
4295 CGF.
Builder.CreateNUWAdd(NumOfRegularWithIterators, NumOfElements);
4298 Loc,
C.getIntTypeForBitwidth(64, 0),
4302 KmpDependInfoArrayTy =
4311 NumOfElements = CGF.
Builder.CreateIntCast(NumOfElements, CGF.
Int32Ty,
4314 KmpDependInfoArrayTy =
C.getConstantArrayType(
4320 NumOfElements = llvm::ConstantInt::get(
CGM.
Int32Ty, NumDependencies,
4325 if (Dep.DepKind == OMPC_DEPEND_depobj || Dep.IteratorExpr)
4331 CGF.
CreateMemTemp(
C.getSizeType(),
"dep.counter.addr"),
C.getSizeType());
4334 if (Dep.DepKind == OMPC_DEPEND_depobj || !Dep.IteratorExpr)
4339 if (HasDepobjDeps) {
4341 if (Dep.DepKind != OMPC_DEPEND_depobj)
4348 return std::make_pair(NumOfElements, DependenciesArray);
4359 unsigned NumDependencies = Dependencies.
DepExprs.size();
4369 llvm::Value *NumDepsVal;
4371 if (
const auto *IE =
4372 cast_or_null<OMPIteratorExpr>(Dependencies.
IteratorExpr)) {
4373 NumDepsVal = llvm::ConstantInt::get(CGF.
SizeTy, 1);
4374 for (
unsigned I = 0,
E = IE->numOfIterators(); I <
E; ++I) {
4377 NumDepsVal = CGF.
Builder.CreateNUWMul(NumDepsVal, Sz);
4379 Size = CGF.
Builder.CreateNUWAdd(llvm::ConstantInt::get(CGF.
SizeTy, 1),
4383 llvm::Value *RecSize =
CGM.
getSize(SizeInBytes);
4384 Size = CGF.
Builder.CreateNUWMul(Size, RecSize);
4388 QualType KmpDependInfoArrayTy =
C.getConstantArrayType(
4391 CharUnits Sz =
C.getTypeSizeInChars(KmpDependInfoArrayTy);
4393 NumDepsVal = llvm::ConstantInt::get(CGF.
IntPtrTy, NumDependencies);
4398 llvm::Value *Allocator = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
4399 llvm::Value *Args[] = {ThreadID, Size, Allocator};
4404 Args,
".dep.arr.addr");
4408 DependenciesArray =
Address(
Addr, KmpDependInfoLlvmTy, Align);
4414 *std::next(KmpDependInfoRD->field_begin(),
4415 static_cast<unsigned int>(RTLDependInfoFields::BaseAddr)));
4417 llvm::PointerUnion<unsigned *, LValue *> Pos;
4434 return DependenciesArray;
4449 Addr.getElementType(),
Addr.emitRawPointer(CGF),
4450 llvm::ConstantInt::get(CGF.
IntPtrTy, -1,
true));
4455 llvm::Value *Allocator = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
4456 llvm::Value *Args[] = {ThreadID, DepObjAddr, Allocator};
4472 llvm::Value *NumDeps;
4479 Begin.emitRawPointer(CGF), NumDeps);
4483 llvm::BasicBlock *EntryBB = CGF.
Builder.GetInsertBlock();
4485 llvm::PHINode *ElementPHI =
4486 CGF.
Builder.CreatePHI(
Begin.getType(), 2,
"omp.elementPast");
4487 ElementPHI->addIncoming(
Begin.emitRawPointer(CGF), EntryBB);
4490 Base.getTBAAInfo());
4494 Base, *std::next(KmpDependInfoRD->field_begin(),
4495 static_cast<unsigned int>(RTLDependInfoFields::Flags)));
4497 llvm::ConstantInt::get(LLVMFlagsTy,
static_cast<unsigned int>(DepKind)),
4501 llvm::Value *ElementNext =
4504 ElementPHI->addIncoming(ElementNext, CGF.
Builder.GetInsertBlock());
4505 llvm::Value *IsEmpty =
4506 CGF.
Builder.CreateICmpEQ(ElementNext, End,
"omp.isempty");
4507 CGF.
Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
4514 llvm::Function *TaskFunction,
4523 llvm::Value *NewTask =
Result.NewTask;
4524 llvm::Function *TaskEntry =
Result.TaskEntry;
4525 llvm::Value *NewTaskNewTaskTTy =
Result.NewTaskNewTaskTTy;
4530 llvm::Value *NumOfElements;
4531 std::tie(NumOfElements, DependenciesArray) =
4542 llvm::Value *TaskArgs[] = { UpLoc, ThreadID, NewTask };
4543 llvm::Value *DepTaskArgs[7];
4544 if (!
Data.Dependences.empty()) {
4545 DepTaskArgs[0] = UpLoc;
4546 DepTaskArgs[1] = ThreadID;
4547 DepTaskArgs[2] = NewTask;
4548 DepTaskArgs[3] = NumOfElements;
4550 DepTaskArgs[5] = CGF.
Builder.getInt32(0);
4551 DepTaskArgs[6] = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
4553 auto &&ThenCodeGen = [
this, &
Data, TDBase, KmpTaskTQTyRD, &TaskArgs,
4556 auto PartIdFI = std::next(KmpTaskTQTyRD->
field_begin(), KmpTaskTPartId);
4560 if (!
Data.Dependences.empty()) {
4573 Region->emitUntiedSwitch(CGF);
4576 llvm::Value *DepWaitTaskArgs[7];
4577 if (!
Data.Dependences.empty()) {
4578 DepWaitTaskArgs[0] = UpLoc;
4579 DepWaitTaskArgs[1] = ThreadID;
4580 DepWaitTaskArgs[2] = NumOfElements;
4582 DepWaitTaskArgs[4] = CGF.
Builder.getInt32(0);
4583 DepWaitTaskArgs[5] = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
4584 DepWaitTaskArgs[6] =
4585 llvm::ConstantInt::get(CGF.
Int32Ty,
Data.HasNowaitClause);
4588 auto &&ElseCodeGen = [
this, &M, &TaskArgs, ThreadID, NewTaskNewTaskTTy,
4589 TaskEntry, &
Data, &DepWaitTaskArgs,
4596 if (!
Data.Dependences.empty())
4598 M, OMPRTL___kmpc_omp_taskwait_deps_51),
4601 auto &&CodeGen = [TaskEntry, ThreadID, NewTaskNewTaskTTy,
4604 llvm::Value *OutlinedFnArgs[] = {ThreadID, NewTaskNewTaskTTy};
4605 CGF.CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF,
Loc, TaskEntry,
4614 CommonActionTy Action(
OMPBuilder.getOrCreateRuntimeFunction(
4615 M, OMPRTL___kmpc_omp_task_begin_if0),
4618 M, OMPRTL___kmpc_omp_task_complete_if0),
4634 llvm::Function *TaskFunction,
4654 IfVal = llvm::ConstantInt::getSigned(CGF.
IntTy, 1);
4659 *std::next(
Result.KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound));
4661 cast<VarDecl>(cast<DeclRefExpr>(
D.getLowerBoundVariable())->getDecl());
4666 *std::next(
Result.KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound));
4668 cast<VarDecl>(cast<DeclRefExpr>(
D.getUpperBoundVariable())->getDecl());
4673 *std::next(
Result.KmpTaskTQTyRD->field_begin(), KmpTaskTStride));
4675 cast<VarDecl>(cast<DeclRefExpr>(
D.getStrideVariable())->getDecl());
4681 *std::next(
Result.KmpTaskTQTyRD->field_begin(), KmpTaskTReductions));
4682 if (
Data.Reductions) {
4688 enum { NoSchedule = 0, Grainsize = 1, NumTasks = 2 };
4697 llvm::ConstantInt::getSigned(
4699 llvm::ConstantInt::getSigned(
4701 ?
Data.Schedule.getInt() ? NumTasks : Grainsize
4703 Data.Schedule.getPointer()
4706 : llvm::ConstantInt::get(CGF.
Int64Ty, 0)};
4707 if (
Data.HasModifier)
4708 TaskArgs.push_back(llvm::ConstantInt::get(CGF.
Int32Ty, 1));
4710 TaskArgs.push_back(
Result.TaskDupFn
4713 : llvm::ConstantPointerNull::get(CGF.
VoidPtrTy));
4716 ? OMPRTL___kmpc_taskloop_5
4717 : OMPRTL___kmpc_taskloop),
4734 const Expr *,
const Expr *)> &RedOpGen,
4735 const Expr *XExpr =
nullptr,
const Expr *EExpr =
nullptr,
4736 const Expr *UpExpr =
nullptr) {
4744 llvm::Value *NumElements = CGF.
emitArrayLength(ArrayTy, ElementTy, LHSAddr);
4749 llvm::Value *LHSEnd =
4754 llvm::Value *IsEmpty =
4755 CGF.
Builder.CreateICmpEQ(LHSBegin, LHSEnd,
"omp.arraycpy.isempty");
4756 CGF.
Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
4759 llvm::BasicBlock *EntryBB = CGF.
Builder.GetInsertBlock();
4764 llvm::PHINode *RHSElementPHI = CGF.
Builder.CreatePHI(
4765 RHSBegin->getType(), 2,
"omp.arraycpy.srcElementPast");
4766 RHSElementPHI->addIncoming(RHSBegin, EntryBB);
4771 llvm::PHINode *LHSElementPHI = CGF.
Builder.CreatePHI(
4772 LHSBegin->getType(), 2,
"omp.arraycpy.destElementPast");
4773 LHSElementPHI->addIncoming(LHSBegin, EntryBB);
4780 Scope.addPrivate(LHSVar, LHSElementCurrent);
4781 Scope.addPrivate(RHSVar, RHSElementCurrent);
4783 RedOpGen(CGF, XExpr, EExpr, UpExpr);
4784 Scope.ForceCleanup();
4787 llvm::Value *LHSElementNext = CGF.
Builder.CreateConstGEP1_32(
4789 "omp.arraycpy.dest.element");
4790 llvm::Value *RHSElementNext = CGF.
Builder.CreateConstGEP1_32(
4792 "omp.arraycpy.src.element");
4795 CGF.
Builder.CreateICmpEQ(LHSElementNext, LHSEnd,
"omp.arraycpy.done");
4796 CGF.
Builder.CreateCondBr(Done, DoneBB, BodyBB);
4797 LHSElementPHI->addIncoming(LHSElementNext, CGF.
Builder.GetInsertBlock());
4798 RHSElementPHI->addIncoming(RHSElementNext, CGF.
Builder.GetInsertBlock());
4808 const Expr *ReductionOp) {
4809 if (
const auto *CE = dyn_cast<CallExpr>(ReductionOp))
4810 if (
const auto *OVE = dyn_cast<OpaqueValueExpr>(CE->getCallee()))
4811 if (
const auto *DRE =
4812 dyn_cast<DeclRefExpr>(OVE->getSourceExpr()->IgnoreImpCasts()))
4813 if (
const auto *DRD =
4814 dyn_cast<OMPDeclareReductionDecl>(DRE->getDecl())) {
4815 std::pair<llvm::Function *, llvm::Function *>
Reduction =
4837 Args.push_back(&LHSArg);
4838 Args.push_back(&RHSArg);
4843 llvm::GlobalValue::InternalLinkage, Name,
4846 Fn->setDoesNotRecurse();
4865 const auto *IPriv = Privates.begin();
4867 for (
unsigned I = 0,
E = ReductionOps.size(); I <
E; ++I, ++IPriv, ++Idx) {
4868 const auto *RHSVar =
4869 cast<VarDecl>(cast<DeclRefExpr>(RHSExprs[I])->getDecl());
4871 const auto *LHSVar =
4872 cast<VarDecl>(cast<DeclRefExpr>(LHSExprs[I])->getDecl());
4874 QualType PrivTy = (*IPriv)->getType();
4882 const auto *OVE = cast<OpaqueValueExpr>(VLA->
getSizeExpr());
4889 IPriv = Privates.begin();
4890 const auto *ILHS = LHSExprs.begin();
4891 const auto *IRHS = RHSExprs.begin();
4892 for (
const Expr *
E : ReductionOps) {
4893 if ((*IPriv)->getType()->isArrayType()) {
4895 const auto *LHSVar = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
4896 const auto *RHSVar = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
4898 CGF, (*IPriv)->getType(), LHSVar, RHSVar,
4900 emitReductionCombiner(CGF, E);
4910 Scope.ForceCleanup();
4916 const Expr *ReductionOp,
4917 const Expr *PrivateRef,
4922 const auto *LHSVar = cast<VarDecl>(LHS->
getDecl());
4923 const auto *RHSVar = cast<VarDecl>(RHS->
getDecl());
4925 CGF, PrivateRef->
getType(), LHSVar, RHSVar,
4927 emitReductionCombiner(CGF, ReductionOp);
4936 llvm::StringRef Prefix,
const Expr *Ref);
4940 const Expr *LHSExprs,
const Expr *RHSExprs,
const Expr *ReductionOps) {
4967 std::string ReductionVarNameStr;
4969 ReductionVarNameStr =
4972 ReductionVarNameStr =
"unnamed_priv_var";
4975 std::string SharedName =
4977 llvm::GlobalVariable *SharedVar =
OMPBuilder.getOrCreateInternalVariable(
4978 LLVMType,
".omp.reduction." + SharedName);
4980 SharedVar->setAlignment(
4988 llvm::Value *BarrierArgs[] = {BarrierLoc, ThreadId};
4993 llvm::Value *IsWorker = CGF.
Builder.CreateICmpEQ(
4994 ThreadId, llvm::ConstantInt::get(ThreadId->getType(), 0));
4995 CGF.
Builder.CreateCondBr(IsWorker, InitBB, InitEndBB);
4999 auto EmitSharedInit = [&]() {
5002 std::pair<llvm::Function *, llvm::Function *> FnPair =
5004 llvm::Function *InitializerFn = FnPair.second;
5005 if (InitializerFn) {
5006 if (
const auto *CE =
5007 dyn_cast<CallExpr>(UDRInitExpr->IgnoreParenImpCasts())) {
5008 const auto *OutDRE = cast<DeclRefExpr>(
5009 cast<UnaryOperator>(CE->getArg(0)->IgnoreParenImpCasts())
5011 const VarDecl *OutVD = cast<VarDecl>(OutDRE->getDecl());
5017 if (
const auto *OVE = dyn_cast<OpaqueValueExpr>(
5018 CE->getCallee()->IgnoreParenImpCasts())) {
5044 if (
const auto *DRE = dyn_cast<DeclRefExpr>(Privates)) {
5045 if (
const auto *VD = dyn_cast<VarDecl>(DRE->getDecl())) {
5056 CGF.
Builder.CreateBr(InitEndBB);
5063 const Expr *ReductionOp = ReductionOps;
5068 auto EmitCriticalReduction = [&](
auto ReductionGen) {
5069 std::string CriticalName =
getName({
"reduction_critical"});
5077 std::pair<llvm::Function *, llvm::Function *> FnPair =
5080 if (
const auto *CE = dyn_cast<CallExpr>(ReductionOp)) {
5081 const auto *OutDRE = cast<DeclRefExpr>(
5082 cast<UnaryOperator>(CE->getArg(0)->IgnoreParenImpCasts())
5084 const auto *InDRE = cast<DeclRefExpr>(
5085 cast<UnaryOperator>(CE->getArg(1)->IgnoreParenImpCasts())
5088 LocalScope.
addPrivate(cast<VarDecl>(OutDRE->getDecl()),
5090 LocalScope.
addPrivate(cast<VarDecl>(InDRE->getDecl()),
5097 EmitCriticalReduction(ReductionGen);
5102 if (
const auto *Cleanup = dyn_cast<ExprWithCleanups>(ReductionClauseExpr))
5105 const Expr *AssignRHS =
nullptr;
5106 if (
const auto *BinOp = dyn_cast<BinaryOperator>(ReductionClauseExpr)) {
5107 if (BinOp->getOpcode() == BO_Assign)
5108 AssignRHS = BinOp->getRHS();
5109 }
else if (
const auto *OpCall =
5110 dyn_cast<CXXOperatorCallExpr>(ReductionClauseExpr)) {
5111 if (OpCall->getOperator() == OO_Equal)
5112 AssignRHS = OpCall->getArg(1);
5116 "Private Variable Reduction : Invalid ReductionOp expression");
5121 const auto *OmpOutDRE =
5123 const auto *OmpInDRE =
5126 OmpOutDRE && OmpInDRE &&
5127 "Private Variable Reduction : LHSExpr/RHSExpr must be DeclRefExprs");
5128 const VarDecl *OmpOutVD = cast<VarDecl>(OmpOutDRE->getDecl());
5129 const VarDecl *OmpInVD = cast<VarDecl>(OmpInDRE->getDecl());
5137 EmitCriticalReduction(ReductionGen);
5147 llvm::Value *FinalResultVal =
nullptr;
5151 FinalResultAddr = SharedResult;
5173 cast<DeclRefExpr>(LHSExprs),
5174 cast<DeclRefExpr>(RHSExprs));
5176 EmitCriticalReduction(OriginalListCombiner);
5188 bool WithNowait = Options.WithNowait;
5189 bool SimpleReduction = Options.SimpleReduction;
5228 if (SimpleReduction) {
5230 const auto *IPriv = OrgPrivates.begin();
5231 const auto *ILHS = OrgLHSExprs.begin();
5232 const auto *IRHS = OrgRHSExprs.begin();
5233 for (
const Expr *
E : OrgReductionOps) {
5235 cast<DeclRefExpr>(*IRHS));
5246 FilteredRHSExprs, FilteredReductionOps;
5247 for (
unsigned I : llvm::seq<unsigned>(
5248 std::min(OrgReductionOps.size(), OrgLHSExprs.size()))) {
5249 if (!Options.IsPrivateVarReduction[I]) {
5250 FilteredPrivates.emplace_back(OrgPrivates[I]);
5251 FilteredLHSExprs.emplace_back(OrgLHSExprs[I]);
5252 FilteredRHSExprs.emplace_back(OrgRHSExprs[I]);
5253 FilteredReductionOps.emplace_back(OrgReductionOps[I]);
5265 auto Size = RHSExprs.size();
5266 for (
const Expr *
E : Privates) {
5271 llvm::APInt ArraySize(32, Size);
5272 QualType ReductionArrayTy =
C.getConstantArrayType(
5276 CGF.
CreateMemTemp(ReductionArrayTy,
".omp.reduction.red_list");
5277 const auto *IPriv = Privates.begin();
5279 for (
unsigned I = 0,
E = RHSExprs.size(); I <
E; ++I, ++IPriv, ++Idx) {
5285 if ((*IPriv)->getType()->isVariablyModifiedType()) {
5289 llvm::Value *Size = CGF.
Builder.CreateIntCast(
5302 Privates, LHSExprs, RHSExprs, ReductionOps);
5305 std::string Name =
getName({
"reduction"});
5312 llvm::Value *ReductionArrayTySize = CGF.
getTypeSize(ReductionArrayTy);
5315 llvm::Value *Args[] = {
5318 CGF.
Builder.getInt32(RHSExprs.size()),
5319 ReductionArrayTySize,
5327 WithNowait ? OMPRTL___kmpc_reduce_nowait : OMPRTL___kmpc_reduce),
5331 llvm::BasicBlock *DefaultBB = CGF.
createBasicBlock(
".omp.reduction.default");
5332 llvm::SwitchInst *SwInst =
5333 CGF.
Builder.CreateSwitch(Res, DefaultBB, 2);
5342 SwInst->addCase(CGF.
Builder.getInt32(1), Case1BB);
5346 llvm::Value *EndArgs[] = {
5351 auto &&CodeGen = [Privates, LHSExprs, RHSExprs, ReductionOps](
5354 const auto *IPriv = Privates.begin();
5355 const auto *ILHS = LHSExprs.begin();
5356 const auto *IRHS = RHSExprs.begin();
5357 for (
const Expr *
E : ReductionOps) {
5359 cast<DeclRefExpr>(*IRHS));
5366 CommonActionTy Action(
5369 CGM.
getModule(), WithNowait ? OMPRTL___kmpc_end_reduce_nowait
5370 : OMPRTL___kmpc_end_reduce),
5383 SwInst->addCase(CGF.
Builder.getInt32(2), Case2BB);
5386 auto &&AtomicCodeGen = [
Loc, Privates, LHSExprs, RHSExprs, ReductionOps](
5388 const auto *ILHS = LHSExprs.begin();
5389 const auto *IRHS = RHSExprs.begin();
5390 const auto *IPriv = Privates.begin();
5391 for (
const Expr *
E : ReductionOps) {
5392 const Expr *XExpr =
nullptr;
5393 const Expr *EExpr =
nullptr;
5394 const Expr *UpExpr =
nullptr;
5396 if (
const auto *BO = dyn_cast<BinaryOperator>(
E)) {
5397 if (BO->getOpcode() == BO_Assign) {
5398 XExpr = BO->getLHS();
5399 UpExpr = BO->getRHS();
5403 const Expr *RHSExpr = UpExpr;
5406 if (
const auto *ACO = dyn_cast<AbstractConditionalOperator>(
5410 RHSExpr = ACO->getCond();
5412 if (
const auto *BORHS =
5414 EExpr = BORHS->getRHS();
5415 BO = BORHS->getOpcode();
5419 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
5420 auto &&AtomicRedGen = [BO, VD,
5422 const Expr *EExpr,
const Expr *UpExpr) {
5423 LValue X = CGF.EmitLValue(XExpr);
5426 E = CGF.EmitAnyExpr(EExpr);
5427 CGF.EmitOMPAtomicSimpleUpdateExpr(
5429 llvm::AtomicOrdering::Monotonic,
Loc,
5430 [&CGF, UpExpr, VD,
Loc](
RValue XRValue) {
5432 Address LHSTemp = CGF.CreateMemTemp(VD->getType());
5433 CGF.emitOMPSimpleStore(
5434 CGF.MakeAddrLValue(LHSTemp, VD->
getType()), XRValue,
5435 VD->getType().getNonReferenceType(),
Loc);
5438 return CGF.EmitAnyExpr(UpExpr);
5441 if ((*IPriv)->getType()->isArrayType()) {
5443 const auto *RHSVar =
5444 cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
5446 AtomicRedGen, XExpr, EExpr, UpExpr);
5449 AtomicRedGen(CGF, XExpr, EExpr, UpExpr);
5456 std::string Name = RT.
getName({
"atomic_reduction"});
5465 if ((*IPriv)->getType()->isArrayType()) {
5466 const auto *LHSVar =
5467 cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
5468 const auto *RHSVar =
5469 cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
5473 CritRedGen(CGF,
nullptr,
nullptr,
nullptr);
5484 llvm::Value *EndArgs[] = {
5489 CommonActionTy Action(
nullptr, {},
5501 assert(OrgLHSExprs.size() == OrgPrivates.size() &&
5502 "PrivateVarReduction: Privates size mismatch");
5503 assert(OrgLHSExprs.size() == OrgReductionOps.size() &&
5504 "PrivateVarReduction: ReductionOps size mismatch");
5505 for (
unsigned I : llvm::seq<unsigned>(
5506 std::min(OrgReductionOps.size(), OrgLHSExprs.size()))) {
5507 if (Options.IsPrivateVarReduction[I])
5509 OrgRHSExprs[I], OrgReductionOps[I]);
5518 llvm::raw_svector_ostream Out(Buffer);
5522 D = cast<VarDecl>(cast<DeclRefExpr>(Ref)->getDecl());
5526 Out << Prefix << Name <<
"_"
5528 return std::string(Out.str());
5550 Args.emplace_back(&Param);
5551 Args.emplace_back(&ParamOrig);
5552 const auto &FnInfo =
5556 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
5559 Fn->setDoesNotRecurse();
5566 llvm::Value *Size =
nullptr;
5609 const Expr *ReductionOp,
5611 const Expr *PrivateRef) {
5613 const auto *LHSVD = cast<VarDecl>(cast<DeclRefExpr>(LHS)->getDecl());
5614 const auto *RHSVD = cast<VarDecl>(cast<DeclRefExpr>(RHS)->getDecl());
5620 Args.emplace_back(&ParamInOut);
5621 Args.emplace_back(&ParamIn);
5622 const auto &FnInfo =
5626 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
5629 Fn->setDoesNotRecurse();
5632 llvm::Value *Size =
nullptr;
5653 C.getPointerType(LHSVD->getType())->castAs<
PointerType>()));
5660 C.getPointerType(RHSVD->getType())->castAs<
PointerType>()));
5666 CGF, ReductionOp, PrivateRef, cast<DeclRefExpr>(LHS),
5667 cast<DeclRefExpr>(RHS));
5689 Args.emplace_back(&Param);
5690 const auto &FnInfo =
5694 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
5697 Fn->setDoesNotRecurse();
5702 llvm::Value *Size =
nullptr;
5737 RecordDecl *RD =
C.buildImplicitRecord(
"kmp_taskred_input_t");
5746 C, RD,
C.getIntTypeForBitwidth(32,
false));
5749 unsigned Size =
Data.ReductionVars.size();
5750 llvm::APInt ArraySize(64, Size);
5752 C.getConstantArrayType(RDType, ArraySize,
nullptr,
5757 Data.ReductionCopies,
Data.ReductionOps);
5758 for (
unsigned Cnt = 0; Cnt < Size; ++Cnt) {
5760 llvm::Value *Idxs[] = {llvm::ConstantInt::get(
CGM.
SizeTy, 0),
5761 llvm::ConstantInt::get(
CGM.
SizeTy, Cnt)};
5777 llvm::Value *SizeValInChars;
5778 llvm::Value *SizeVal;
5779 std::tie(SizeValInChars, SizeVal) = RCG.
getSizes(Cnt);
5785 bool DelayedCreation = !!SizeVal;
5797 llvm::Value *FiniAddr =
5798 Fini ? Fini : llvm::ConstantPointerNull::get(
CGM.
VoidPtrTy);
5803 CGM,
Loc, RCG, Cnt,
Data.ReductionOps[Cnt], LHSExprs[Cnt],
5804 RHSExprs[Cnt],
Data.ReductionCopies[Cnt]);
5808 if (DelayedCreation) {
5810 llvm::ConstantInt::get(
CGM.
Int32Ty, 1,
true),
5815 if (
Data.IsReductionWithTaskMod) {
5821 llvm::Value *Args[] = {
5823 llvm::ConstantInt::get(
CGM.
IntTy,
Data.IsWorksharingReduction ? 1 : 0,
5825 llvm::ConstantInt::get(
CGM.
IntTy, Size,
true),
5834 llvm::Value *Args[] = {
5837 llvm::ConstantInt::get(
CGM.
IntTy, Size,
true),
5847 bool IsWorksharingReduction) {
5853 llvm::Value *Args[] = {IdentTLoc, GTid,
5855 IsWorksharingReduction ? 1 : 0,
5859 CGM.
getModule(), OMPRTL___kmpc_task_reduction_modifier_fini),
5882 llvm::Value *ReductionsPtr,
5895 CGM.
getModule(), OMPRTL___kmpc_task_reduction_get_th_data),
5913 llvm::Value *NumOfElements;
5914 std::tie(NumOfElements, DependenciesArray) =
5916 if (!
Data.Dependences.empty()) {
5917 llvm::Value *DepWaitTaskArgs[7];
5918 DepWaitTaskArgs[0] = UpLoc;
5919 DepWaitTaskArgs[1] = ThreadID;
5920 DepWaitTaskArgs[2] = NumOfElements;
5922 DepWaitTaskArgs[4] = CGF.
Builder.getInt32(0);
5923 DepWaitTaskArgs[5] = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
5924 DepWaitTaskArgs[6] =
5925 llvm::ConstantInt::get(CGF.
Int32Ty,
Data.HasNowaitClause);
5934 M, OMPRTL___kmpc_omp_taskwait_deps_51),
5941 llvm::Value *Args[] = {UpLoc, ThreadID};
5944 OMPBuilder.getOrCreateRuntimeFunction(M, OMPRTL___kmpc_omp_taskwait),
5949 if (
auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.
CapturedStmtInfo))
5950 Region->emitUntiedSwitch(CGF);
5959 InlinedOpenMPRegionRAII Region(CGF, CodeGen, InnerKind, HasCancel,
5960 InnerKind != OMPD_critical &&
5961 InnerKind != OMPD_master &&
5962 InnerKind != OMPD_masked);
5977 RTCancelKind CancelKind = CancelNoreq;
5978 if (CancelRegion == OMPD_parallel)
5979 CancelKind = CancelParallel;
5980 else if (CancelRegion == OMPD_for)
5981 CancelKind = CancelLoop;
5982 else if (CancelRegion == OMPD_sections)
5983 CancelKind = CancelSections;
5985 assert(CancelRegion == OMPD_taskgroup);
5986 CancelKind = CancelTaskgroup;
5998 if (
auto *OMPRegionInfo =
6002 if (CancelRegion == OMPD_taskgroup || OMPRegionInfo->hasCancel()) {
6003 llvm::Value *Args[] = {
6018 CGF.
Builder.CreateCondBr(Cmp, ExitBB, ContBB);
6020 if (CancelRegion == OMPD_parallel)
6039 if (
auto *OMPRegionInfo =
6041 auto &&ThenGen = [
this, &M,
Loc, CancelRegion,
6044 llvm::Value *Args[] = {
6048 llvm::Value *
Result = CGF.EmitRuntimeCall(
6049 OMPBuilder.getOrCreateRuntimeFunction(M, OMPRTL___kmpc_cancel), Args);
6054 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(
".cancel.exit");
6055 llvm::BasicBlock *ContBB = CGF.createBasicBlock(
".cancel.continue");
6056 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(
Result);
6057 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB);
6058 CGF.EmitBlock(ExitBB);
6059 if (CancelRegion == OMPD_parallel)
6063 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind());
6064 CGF.EmitBranchThroughCleanup(CancelDest);
6065 CGF.EmitBlock(ContBB,
true);
6083 OMPUsesAllocatorsActionTy(
6084 ArrayRef<std::pair<const Expr *, const Expr *>> Allocators)
6085 : Allocators(Allocators) {}
6089 for (
const auto &AllocatorData : Allocators) {
6091 CGF, AllocatorData.first, AllocatorData.second);
6097 for (
const auto &AllocatorData : Allocators) {
6099 AllocatorData.first);
6107 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
6109 assert(!ParentName.empty() &&
"Invalid target entry parent name!");
6113 for (
unsigned I = 0,
E =
C->getNumberOfAllocators(); I <
E; ++I) {
6115 if (!
D.AllocatorTraits)
6117 Allocators.emplace_back(
D.Allocator,
D.AllocatorTraits);
6120 OMPUsesAllocatorsActionTy UsesAllocatorAction(Allocators);
6123 IsOffloadEntry, CodeGen);
6127 const Expr *Allocator,
6128 const Expr *AllocatorTraits) {
6129 llvm::Value *ThreadId =
getThreadID(CGF, Allocator->getExprLoc());
6130 ThreadId = CGF.
Builder.CreateIntCast(ThreadId, CGF.
IntTy,
true);
6132 llvm::Value *MemSpaceHandle = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
6133 llvm::Value *NumTraits = llvm::ConstantInt::get(
6134 CGF.
IntTy, cast<ConstantArrayType>(
6137 .getLimitedValue());
6144 llvm::Value *Traits =
Addr.emitRawPointer(CGF);
6146 llvm::Value *AllocatorVal =
6149 {ThreadId, MemSpaceHandle, NumTraits, Traits});
6152 cast<DeclRefExpr>(Allocator->IgnoreParenImpCasts())->getDecl()));
6156 Allocator->getType(), Allocator->getExprLoc());
6161 const Expr *Allocator) {
6162 llvm::Value *ThreadId =
getThreadID(CGF, Allocator->getExprLoc());
6163 ThreadId = CGF.
Builder.CreateIntCast(ThreadId, CGF.
IntTy,
true);
6165 llvm::Value *AllocatorVal =
6169 Allocator->getExprLoc());
6172 OMPRTL___kmpc_destroy_allocator),
6173 {ThreadId, AllocatorVal});
6178 llvm::OpenMPIRBuilder::TargetKernelDefaultAttrs &Attrs) {
6179 assert(Attrs.MaxTeams.size() == 1 && Attrs.MaxThreads.size() == 1 &&
6180 "invalid default attrs structure");
6181 int32_t &MaxTeamsVal = Attrs.MaxTeams.front();
6182 int32_t &MaxThreadsVal = Attrs.MaxThreads.front();
6189 for (
auto *A :
C->getAttrs()) {
6190 int32_t AttrMinThreadsVal = 1, AttrMaxThreadsVal = -1;
6191 int32_t AttrMinBlocksVal = 1, AttrMaxBlocksVal = -1;
6192 if (
auto *
Attr = dyn_cast<CUDALaunchBoundsAttr>(A))
6194 &AttrMinBlocksVal, &AttrMaxBlocksVal);
6195 else if (
auto *
Attr = dyn_cast<AMDGPUFlatWorkGroupSizeAttr>(A))
6197 nullptr,
Attr,
nullptr, &AttrMinThreadsVal,
6198 &AttrMaxThreadsVal);
6202 Attrs.MinThreads = std::max(Attrs.MinThreads, AttrMinThreadsVal);
6203 if (AttrMaxThreadsVal > 0)
6204 MaxThreadsVal = MaxThreadsVal > 0
6205 ? std::min(MaxThreadsVal, AttrMaxThreadsVal)
6206 : AttrMaxThreadsVal;
6207 Attrs.MinTeams = std::max(Attrs.MinTeams, AttrMinBlocksVal);
6208 if (AttrMaxBlocksVal > 0)
6209 MaxTeamsVal = MaxTeamsVal > 0 ? std::min(MaxTeamsVal, AttrMaxBlocksVal)
6217 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
6220 llvm::TargetRegionEntryInfo EntryInfo =
6224 llvm::OpenMPIRBuilder::FunctionGenCallback &&GenerateOutlinedFunction =
6225 [&CGF, &
D, &CodeGen](StringRef EntryFnName) {
6228 CGOpenMPTargetRegionInfo CGInfo(CS, CodeGen, EntryFnName);
6233 cantFail(
OMPBuilder.emitTargetRegionFunction(
6234 EntryInfo, GenerateOutlinedFunction, IsOffloadEntry, OutlinedFn,
6243 for (
auto *A :
C->getAttrs()) {
6244 if (
auto *
Attr = dyn_cast<AMDGPUWavesPerEUAttr>(A))
6263 while (
const auto *
C = dyn_cast_or_null<CompoundStmt>(Child)) {
6265 for (
const Stmt *S :
C->body()) {
6266 if (
const auto *
E = dyn_cast<Expr>(S)) {
6271 if (isa<AsmStmt>(S) || isa<NullStmt>(S) || isa<OMPFlushDirective>(S) ||
6272 isa<OMPBarrierDirective>(S) || isa<OMPTaskyieldDirective>(S))
6275 if (
const auto *DS = dyn_cast<DeclStmt>(S)) {
6276 if (llvm::all_of(DS->decls(), [](
const Decl *
D) {
6277 if (isa<EmptyDecl>(D) || isa<DeclContext>(D) ||
6278 isa<TypeDecl>(D) || isa<PragmaCommentDecl>(D) ||
6279 isa<PragmaDetectMismatchDecl>(D) || isa<UsingDecl>(D) ||
6280 isa<UsingDirectiveDecl>(D) ||
6281 isa<OMPDeclareReductionDecl>(D) ||
6282 isa<OMPThreadPrivateDecl>(D) || isa<OMPAllocateDecl>(D))
6284 const auto *VD = dyn_cast<VarDecl>(D);
6287 return VD->hasGlobalStorage() || !VD->isUsed();
6297 Child = Child->IgnoreContainers();
6304 int32_t &MaxTeamsVal) {
6308 "Expected target-based executable directive.");
6309 switch (DirectiveKind) {
6311 const auto *CS =
D.getInnermostCapturedStmt();
6314 const Stmt *ChildStmt =
6316 if (
const auto *NestedDir =
6317 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) {
6326 MinTeamsVal = MaxTeamsVal = Constant->getExtValue();
6329 MinTeamsVal = MaxTeamsVal = 0;
6332 MinTeamsVal = MaxTeamsVal = 1;
6336 MinTeamsVal = MaxTeamsVal = -1;
6339 case OMPD_target_teams_loop:
6340 case OMPD_target_teams:
6341 case OMPD_target_teams_distribute:
6342 case OMPD_target_teams_distribute_simd:
6343 case OMPD_target_teams_distribute_parallel_for:
6344 case OMPD_target_teams_distribute_parallel_for_simd: {
6346 const Expr *NumTeams =
6350 MinTeamsVal = MaxTeamsVal = Constant->getExtValue();
6353 MinTeamsVal = MaxTeamsVal = 0;
6356 case OMPD_target_parallel:
6357 case OMPD_target_parallel_for:
6358 case OMPD_target_parallel_for_simd:
6359 case OMPD_target_parallel_loop:
6360 case OMPD_target_simd:
6361 MinTeamsVal = MaxTeamsVal = 1;
6365 case OMPD_parallel_for:
6366 case OMPD_parallel_loop:
6367 case OMPD_parallel_master:
6368 case OMPD_parallel_sections:
6370 case OMPD_parallel_for_simd:
6372 case OMPD_cancellation_point:
6374 case OMPD_threadprivate:
6385 case OMPD_taskyield:
6388 case OMPD_taskgroup:
6394 case OMPD_target_data:
6395 case OMPD_target_exit_data:
6396 case OMPD_target_enter_data:
6397 case OMPD_distribute:
6398 case OMPD_distribute_simd:
6399 case OMPD_distribute_parallel_for:
6400 case OMPD_distribute_parallel_for_simd:
6401 case OMPD_teams_distribute:
6402 case OMPD_teams_distribute_simd:
6403 case OMPD_teams_distribute_parallel_for:
6404 case OMPD_teams_distribute_parallel_for_simd:
6405 case OMPD_target_update:
6406 case OMPD_declare_simd:
6407 case OMPD_declare_variant:
6408 case OMPD_begin_declare_variant:
6409 case OMPD_end_declare_variant:
6410 case OMPD_declare_target:
6411 case OMPD_end_declare_target:
6412 case OMPD_declare_reduction:
6413 case OMPD_declare_mapper:
6415 case OMPD_taskloop_simd:
6416 case OMPD_master_taskloop:
6417 case OMPD_master_taskloop_simd:
6418 case OMPD_parallel_master_taskloop:
6419 case OMPD_parallel_master_taskloop_simd:
6421 case OMPD_metadirective:
6427 llvm_unreachable(
"Unexpected directive kind.");
6433 "Clauses associated with the teams directive expected to be emitted "
6434 "only for the host!");
6436 int32_t MinNT = -1, MaxNT = -1;
6437 const Expr *NumTeams =
6439 if (NumTeams !=
nullptr) {
6442 switch (DirectiveKind) {
6444 const auto *CS =
D.getInnermostCapturedStmt();
6445 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6449 return Bld.CreateIntCast(NumTeamsVal, CGF.
Int32Ty,
6452 case OMPD_target_teams:
6453 case OMPD_target_teams_distribute:
6454 case OMPD_target_teams_distribute_simd:
6455 case OMPD_target_teams_distribute_parallel_for:
6456 case OMPD_target_teams_distribute_parallel_for_simd: {
6460 return Bld.CreateIntCast(NumTeamsVal, CGF.
Int32Ty,
6468 assert(MinNT == MaxNT &&
"Num threads ranges require handling here.");
6469 return llvm::ConstantInt::get(CGF.
Int32Ty, MinNT);
6477 const Expr **
E, int32_t &UpperBound,
6478 bool UpperBoundOnly, llvm::Value **CondVal) {
6481 const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child);
6488 if (CondVal && Dir->hasClausesOfKind<
OMPIfClause>()) {
6489 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6492 for (
const auto *
C : Dir->getClausesOfKind<
OMPIfClause>()) {
6493 if (
C->getNameModifier() == OMPD_unknown ||
6494 C->getNameModifier() == OMPD_parallel) {
6509 if (
const auto *PreInit =
6511 for (
const auto *I : PreInit->decls()) {
6512 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
6528 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6530 const auto *NumThreadsClause =
6532 const Expr *NTExpr = NumThreadsClause->getNumThreads();
6533 if (NTExpr->isIntegerConstantExpr(CGF.
getContext()))
6534 if (
auto Constant = NTExpr->getIntegerConstantExpr(CGF.
getContext()))
6537 ? Constant->getZExtValue()
6538 : std::min(UpperBound,
6539 static_cast<int32_t
>(Constant->getZExtValue()));
6542 if (UpperBound == -1)
6547 if (
const auto *PreInit =
6548 cast_or_null<DeclStmt>(NumThreadsClause->getPreInitStmt())) {
6549 for (
const auto *I : PreInit->decls()) {
6550 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
6569 bool UpperBoundOnly, llvm::Value **CondVal,
const Expr **ThreadLimitExpr) {
6570 assert((!CGF.
getLangOpts().OpenMPIsTargetDevice || UpperBoundOnly) &&
6571 "Clauses associated with the teams directive expected to be emitted "
6572 "only for the host!");
6575 "Expected target-based executable directive.");
6577 const Expr *NT =
nullptr;
6578 const Expr **NTPtr = UpperBoundOnly ? nullptr : &NT;
6580 auto CheckForConstExpr = [&](
const Expr *
E,
const Expr **EPtr) {
6583 UpperBound = UpperBound ? Constant->getZExtValue()
6584 : std::min(UpperBound,
6585 int32_t(Constant->getZExtValue()));
6589 if (UpperBound == -1)
6595 auto ReturnSequential = [&]() {
6600 switch (DirectiveKind) {
6603 getNumThreads(CGF, CS, NTPtr, UpperBound, UpperBoundOnly, CondVal);
6609 if (
const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) {
6611 ThreadLimitClause = TLC;
6612 if (ThreadLimitExpr) {
6613 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6617 ThreadLimitClause->getThreadLimit().front()->getSourceRange());
6618 if (
const auto *PreInit =
6619 cast_or_null<DeclStmt>(ThreadLimitClause->getPreInitStmt())) {
6620 for (
const auto *I : PreInit->decls()) {
6621 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
6633 if (ThreadLimitClause)
6634 CheckForConstExpr(ThreadLimitClause->getThreadLimit().front(),
6636 if (
const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) {
6639 CS = Dir->getInnermostCapturedStmt();
6642 Dir = dyn_cast_or_null<OMPExecutableDirective>(Child);
6645 CS = Dir->getInnermostCapturedStmt();
6646 getNumThreads(CGF, CS, NTPtr, UpperBound, UpperBoundOnly, CondVal);
6648 return ReturnSequential();
6652 case OMPD_target_teams: {
6656 CheckForConstExpr(ThreadLimitClause->getThreadLimit().front(),
6660 getNumThreads(CGF, CS, NTPtr, UpperBound, UpperBoundOnly, CondVal);
6663 if (
const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) {
6664 if (Dir->getDirectiveKind() == OMPD_distribute) {
6665 CS = Dir->getInnermostCapturedStmt();
6666 getNumThreads(CGF, CS, NTPtr, UpperBound, UpperBoundOnly, CondVal);
6671 case OMPD_target_teams_distribute:
6675 CheckForConstExpr(ThreadLimitClause->getThreadLimit().front(),
6678 getNumThreads(CGF,
D.getInnermostCapturedStmt(), NTPtr, UpperBound,
6679 UpperBoundOnly, CondVal);
6681 case OMPD_target_teams_loop:
6682 case OMPD_target_parallel_loop:
6683 case OMPD_target_parallel:
6684 case OMPD_target_parallel_for:
6685 case OMPD_target_parallel_for_simd:
6686 case OMPD_target_teams_distribute_parallel_for:
6687 case OMPD_target_teams_distribute_parallel_for_simd: {
6691 if (
C->getNameModifier() == OMPD_unknown ||
6692 C->getNameModifier() == OMPD_parallel) {
6702 return ReturnSequential();
6712 CheckForConstExpr(ThreadLimitClause->getThreadLimit().front(),
6718 CheckForConstExpr(NumThreadsClause->getNumThreads(),
nullptr);
6719 return NumThreadsClause->getNumThreads();
6723 case OMPD_target_teams_distribute_simd:
6724 case OMPD_target_simd:
6725 return ReturnSequential();
6729 llvm_unreachable(
"Unsupported directive kind.");
6734 llvm::Value *NumThreadsVal =
nullptr;
6735 llvm::Value *CondVal =
nullptr;
6736 llvm::Value *ThreadLimitVal =
nullptr;
6737 const Expr *ThreadLimitExpr =
nullptr;
6738 int32_t UpperBound = -1;
6741 CGF,
D, UpperBound,
false, &CondVal,
6745 if (ThreadLimitExpr) {
6748 ThreadLimitVal = CGF.
Builder.CreateIntCast(ThreadLimitVal, CGF.
Int32Ty,
6753 if (UpperBound == 1) {
6754 NumThreadsVal = CGF.
Builder.getInt32(UpperBound);
6757 NumThreadsVal = CGF.
Builder.CreateIntCast(NumThreadsVal, CGF.
Int32Ty,
6759 }
else if (ThreadLimitVal) {
6762 NumThreadsVal = ThreadLimitVal;
6763 ThreadLimitVal =
nullptr;
6766 assert(!ThreadLimitVal &&
"Default not applicable with thread limit value");
6767 NumThreadsVal = CGF.
Builder.getInt32(0);
6774 NumThreadsVal = CGF.
Builder.CreateSelect(CondVal, NumThreadsVal,
6780 if (ThreadLimitVal) {
6781 NumThreadsVal = CGF.
Builder.CreateSelect(
6782 CGF.
Builder.CreateICmpULT(ThreadLimitVal, NumThreadsVal),
6783 ThreadLimitVal, NumThreadsVal);
6786 return NumThreadsVal;
6796class MappableExprsHandler {
6799 static unsigned getFlagMemberOffset() {
6800 unsigned Offset = 0;
6801 for (uint64_t Remain =
6802 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
6803 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF);
6804 !(Remain & 1); Remain = Remain >> 1)
6811 class MappingExprInfo {
6816 const Expr *MapExpr =
nullptr;
6819 MappingExprInfo(
const ValueDecl *MapDecl,
const Expr *MapExpr =
nullptr)
6820 : MapDecl(MapDecl), MapExpr(MapExpr) {}
6822 const ValueDecl *getMapDecl()
const {
return MapDecl; }
6823 const Expr *getMapExpr()
const {
return MapExpr; }
6826 using DeviceInfoTy = llvm::OpenMPIRBuilder::DeviceInfoTy;
6827 using MapBaseValuesArrayTy = llvm::OpenMPIRBuilder::MapValuesArrayTy;
6828 using MapValuesArrayTy = llvm::OpenMPIRBuilder::MapValuesArrayTy;
6829 using MapFlagsArrayTy = llvm::OpenMPIRBuilder::MapFlagsArrayTy;
6830 using MapDimArrayTy = llvm::OpenMPIRBuilder::MapDimArrayTy;
6831 using MapNonContiguousArrayTy =
6832 llvm::OpenMPIRBuilder::MapNonContiguousArrayTy;
6844 struct MapCombinedInfoTy : llvm::OpenMPIRBuilder::MapInfosTy {
6845 MapExprsArrayTy Exprs;
6846 MapValueDeclsArrayTy Mappers;
6847 MapValueDeclsArrayTy DevicePtrDecls;
6850 void append(MapCombinedInfoTy &CurInfo) {
6851 Exprs.append(CurInfo.Exprs.begin(), CurInfo.Exprs.end());
6852 DevicePtrDecls.append(CurInfo.DevicePtrDecls.begin(),
6853 CurInfo.DevicePtrDecls.end());
6854 Mappers.append(CurInfo.Mappers.begin(), CurInfo.Mappers.end());
6855 llvm::OpenMPIRBuilder::MapInfosTy::append(CurInfo);
6863 struct StructRangeInfoTy {
6864 MapCombinedInfoTy PreliminaryMapData;
6865 std::pair<
unsigned ,
Address > LowestElem = {
6867 std::pair<
unsigned ,
Address > HighestElem = {
6871 bool IsArraySection =
false;
6872 bool HasCompleteRecord =
false;
6882 bool ReturnDevicePointer =
false;
6883 bool IsImplicit =
false;
6885 const Expr *VarRef =
nullptr;
6886 bool ForDeviceAddr =
false;
6888 MapInfo() =
default;
6894 bool ReturnDevicePointer,
bool IsImplicit,
6895 const ValueDecl *Mapper =
nullptr,
const Expr *VarRef =
nullptr,
6896 bool ForDeviceAddr =
false)
6897 : Components(Components), MapType(MapType), MapModifiers(MapModifiers),
6898 MotionModifiers(MotionModifiers),
6899 ReturnDevicePointer(ReturnDevicePointer), IsImplicit(IsImplicit),
6900 Mapper(Mapper), VarRef(VarRef), ForDeviceAddr(ForDeviceAddr) {}
6906 struct DeferredDevicePtrEntryTy {
6907 const Expr *IE =
nullptr;
6909 bool ForDeviceAddr =
false;
6911 DeferredDevicePtrEntryTy(
const Expr *IE,
const ValueDecl *VD,
6913 : IE(IE), VD(VD), ForDeviceAddr(ForDeviceAddr) {}
6928 llvm::DenseMap<CanonicalDeclPtr<const VarDecl>,
bool> FirstPrivateDecls;
6945 llvm::DenseMap<const ValueDecl *, const OMPMapClause *> LambdasMap;
6947 llvm::Value *getExprTypeSize(
const Expr *
E)
const {
6951 if (
const auto *OAE = dyn_cast<OMPArrayShapingExpr>(
E)) {
6953 CGF.
getTypeSize(OAE->getBase()->getType()->getPointeeType());
6954 for (
const Expr *SE : OAE->getDimensions()) {
6971 if (
const auto *OAE = dyn_cast<ArraySectionExpr>(
E)) {
6973 OAE->getBase()->IgnoreParenImpCasts())
6979 if (!OAE->getLength() && OAE->getColonLocFirst().isValid() &&
6980 !OAE->getLowerBound())
6983 llvm::Value *ElemSize;
6985 ElemSize = CGF.
getTypeSize(PTy->getPointeeType().getCanonicalType());
6987 const auto *ATy = cast<ArrayType>(BaseTy.
getTypePtr());
6988 assert(ATy &&
"Expecting array type if not a pointer type.");
6989 ElemSize = CGF.
getTypeSize(ATy->getElementType().getCanonicalType());
6994 if (!OAE->getLength() && OAE->getColonLocFirst().isInvalid())
6997 if (
const Expr *LenExpr = OAE->getLength()) {
7001 LenExpr->getExprLoc());
7002 return CGF.
Builder.CreateNUWMul(LengthVal, ElemSize);
7004 assert(!OAE->getLength() && OAE->getColonLocFirst().isValid() &&
7005 OAE->getLowerBound() &&
"expected array_section[lb:].");
7011 OAE->getLowerBound()->getExprLoc());
7012 LBVal = CGF.
Builder.CreateNUWMul(LBVal, ElemSize);
7013 llvm::Value *Cmp = CGF.
Builder.CreateICmpUGT(LengthVal, LBVal);
7014 llvm::Value *TrueVal = CGF.
Builder.CreateNUWSub(LengthVal, LBVal);
7015 LengthVal = CGF.
Builder.CreateSelect(
7016 Cmp, TrueVal, llvm::ConstantInt::get(CGF.
SizeTy, 0));
7026 OpenMPOffloadMappingFlags getMapTypeBits(
7029 bool AddPtrFlag,
bool AddIsTargetParamFlag,
bool IsNonContiguous)
const {
7030 OpenMPOffloadMappingFlags Bits =
7031 IsImplicit ? OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT
7032 : OpenMPOffloadMappingFlags::OMP_MAP_NONE;
7034 case OMPC_MAP_alloc:
7035 case OMPC_MAP_release:
7042 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_TO;
7045 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_FROM;
7047 case OMPC_MAP_tofrom:
7048 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_TO |
7049 OpenMPOffloadMappingFlags::OMP_MAP_FROM;
7051 case OMPC_MAP_delete:
7052 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_DELETE;
7055 llvm_unreachable(
"Unexpected map type!");
7058 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ;
7059 if (AddIsTargetParamFlag)
7060 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM;
7061 if (llvm::is_contained(MapModifiers, OMPC_MAP_MODIFIER_always))
7062 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_ALWAYS;
7063 if (llvm::is_contained(MapModifiers, OMPC_MAP_MODIFIER_close))
7064 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_CLOSE;
7065 if (llvm::is_contained(MapModifiers, OMPC_MAP_MODIFIER_present) ||
7066 llvm::is_contained(MotionModifiers, OMPC_MOTION_MODIFIER_present))
7067 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_PRESENT;
7068 if (llvm::is_contained(MapModifiers, OMPC_MAP_MODIFIER_ompx_hold))
7069 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_OMPX_HOLD;
7070 if (IsNonContiguous)
7071 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_NON_CONTIG;
7077 bool isFinalArraySectionExpression(
const Expr *
E)
const {
7078 const auto *OASE = dyn_cast<ArraySectionExpr>(
E);
7085 if (OASE->getColonLocFirst().isInvalid())
7088 const Expr *Length = OASE->getLength();
7095 OASE->getBase()->IgnoreParenImpCasts())
7097 if (
const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.
getTypePtr()))
7098 return ATy->getSExtSize() != 1;
7107 if (!Length->EvaluateAsInt(Result, CGF.
getContext()))
7110 llvm::APSInt ConstLength = Result.Val.getInt();
7111 return ConstLength.getSExtValue() != 1;
7118 class CopyOverlappedEntryGaps {
7120 MapCombinedInfoTy &CombinedInfo;
7121 OpenMPOffloadMappingFlags Flags = OpenMPOffloadMappingFlags::OMP_MAP_NONE;
7123 const Expr *MapExpr =
nullptr;
7125 bool IsNonContiguous =
false;
7131 unsigned LastIndex = -1u;
7136 MapCombinedInfoTy &CombinedInfo,
7137 OpenMPOffloadMappingFlags Flags,
7141 : CGF(CGF), CombinedInfo(CombinedInfo), Flags(Flags), MapDecl(MapDecl),
7142 MapExpr(MapExpr), BP(BP), IsNonContiguous(IsNonContiguous),
7143 DimSize(DimSize), LB(LB) {}
7149 EmitMemberExprBase) {
7159 LValue BaseLVal = EmitMemberExprBase(CGF, ME);
7171 copyUntilField(FD, ComponentLB);
7174 if (((int64_t)FieldOffset - (int64_t)Cursor) > 0)
7175 copyUntilField(FD, ComponentLB);
7177 Cursor = FieldOffset + FieldSize;
7186 CGF.
Builder.CreatePtrDiff(CGF.
Int8Ty, ComponentLBPtr, LBPtr);
7187 copySizedChunk(LBPtr, Size);
7190 void copyUntilEnd(
Address HB) {
7201 copySizedChunk(LBPtr, Size);
7204 void copySizedChunk(llvm::Value *
Base, llvm::Value *Size) {
7205 CombinedInfo.Exprs.emplace_back(MapDecl, MapExpr);
7207 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
7208 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
7209 CombinedInfo.Pointers.push_back(
Base);
7210 CombinedInfo.Sizes.push_back(
7212 CombinedInfo.Types.push_back(Flags);
7213 CombinedInfo.Mappers.push_back(
nullptr);
7214 CombinedInfo.NonContigInfo.Dims.push_back(IsNonContiguous ? DimSize : 1);
7223 void generateInfoForComponentList(
7227 MapCombinedInfoTy &CombinedInfo,
7228 MapCombinedInfoTy &StructBaseCombinedInfo,
7229 StructRangeInfoTy &PartialStruct,
bool IsFirstComponentList,
7230 bool IsImplicit,
bool GenerateAllInfoForClauses,
7231 const ValueDecl *Mapper =
nullptr,
bool ForDeviceAddr =
false,
7232 const ValueDecl *BaseDecl =
nullptr,
const Expr *MapExpr =
nullptr,
7234 OverlappedElements = {},
7235 bool AreBothBasePtrAndPteeMapped =
false)
const {
7417 bool IsCaptureFirstInfo = IsFirstComponentList;
7421 bool RequiresReference =
false;
7424 auto CI = Components.rbegin();
7425 auto CE = Components.rend();
7430 bool IsExpressionFirstInfo =
true;
7431 bool FirstPointerInComplexData =
false;
7433 const Expr *AssocExpr = I->getAssociatedExpression();
7434 const auto *AE = dyn_cast<ArraySubscriptExpr>(AssocExpr);
7435 const auto *OASE = dyn_cast<ArraySectionExpr>(AssocExpr);
7436 const auto *OAShE = dyn_cast<OMPArrayShapingExpr>(AssocExpr);
7438 if (AreBothBasePtrAndPteeMapped && std::next(I) == CE)
7440 if (isa<MemberExpr>(AssocExpr)) {
7444 }
else if ((AE && isa<CXXThisExpr>(AE->getBase()->IgnoreParenImpCasts())) ||
7446 isa<CXXThisExpr>(OASE->getBase()->IgnoreParenImpCasts()))) {
7449 isa<CXXThisExpr>(OAShE->getBase()->IgnoreParenCasts())) {
7458 if (
const auto *VD =
7459 dyn_cast_or_null<VarDecl>(I->getAssociatedDeclaration())) {
7460 if (std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
7461 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD)) {
7462 if ((*Res == OMPDeclareTargetDeclAttr::MT_Link) ||
7463 ((*Res == OMPDeclareTargetDeclAttr::MT_To ||
7464 *Res == OMPDeclareTargetDeclAttr::MT_Enter) &&
7466 RequiresReference =
true;
7476 I->getAssociatedDeclaration()->getType().getNonReferenceType();
7481 const auto *VD = dyn_cast<VarDecl>(I->getAssociatedDeclaration());
7482 if (!AreBothBasePtrAndPteeMapped &&
7487 FirstPointerInComplexData =
true;
7506 bool ShouldBeMemberOf =
false;
7527 bool IsNonContiguous =
7528 CombinedInfo.NonContigInfo.IsNonContiguous ||
7529 any_of(Components, [&](
const auto &Component) {
7531 dyn_cast<ArraySectionExpr>(Component.getAssociatedExpression());
7535 const Expr *StrideExpr = OASE->getStride();
7539 const auto Constant =
7544 return !Constant->isOne();
7547 bool IsPrevMemberReference =
false;
7549 bool IsPartialMapped =
7550 !PartialStruct.PreliminaryMapData.BasePointers.empty();
7557 bool IsMappingWholeStruct =
true;
7558 if (!GenerateAllInfoForClauses) {
7559 IsMappingWholeStruct =
false;
7561 for (
auto TempI = I; TempI != CE; ++TempI) {
7563 dyn_cast<MemberExpr>(TempI->getAssociatedExpression());
7565 IsMappingWholeStruct =
false;
7571 for (; I != CE; ++I) {
7573 if (!EncounteredME) {
7574 EncounteredME = dyn_cast<MemberExpr>(I->getAssociatedExpression());
7577 if (EncounteredME) {
7578 ShouldBeMemberOf =
true;
7581 if (FirstPointerInComplexData) {
7583 ->getAssociatedDeclaration()
7585 .getNonReferenceType();
7587 FirstPointerInComplexData =
false;
7592 auto Next = std::next(I);
7602 bool IsFinalArraySection =
7604 isFinalArraySectionExpression(I->getAssociatedExpression());
7608 const ValueDecl *MapDecl = (I->getAssociatedDeclaration())
7609 ? I->getAssociatedDeclaration()
7611 MapExpr = (I->getAssociatedExpression()) ? I->getAssociatedExpression()
7618 dyn_cast<ArraySectionExpr>(I->getAssociatedExpression());
7620 dyn_cast<OMPArrayShapingExpr>(I->getAssociatedExpression());
7621 const auto *UO = dyn_cast<UnaryOperator>(I->getAssociatedExpression());
7622 const auto *BO = dyn_cast<BinaryOperator>(I->getAssociatedExpression());
7628 I->getAssociatedExpression()->getType()->isAnyPointerType();
7629 bool IsMemberReference = isa<MemberExpr>(I->getAssociatedExpression()) &&
7632 bool IsNonDerefPointer = IsPointer &&
7633 !(UO && UO->getOpcode() != UO_Deref) && !BO &&
7639 if (Next == CE || IsMemberReference || IsNonDerefPointer ||
7640 IsFinalArraySection) {
7643 assert((Next == CE ||
7644 isa<MemberExpr>(Next->getAssociatedExpression()) ||
7645 isa<ArraySubscriptExpr>(Next->getAssociatedExpression()) ||
7646 isa<ArraySectionExpr>(Next->getAssociatedExpression()) ||
7647 isa<OMPArrayShapingExpr>(Next->getAssociatedExpression()) ||
7648 isa<UnaryOperator>(Next->getAssociatedExpression()) ||
7649 isa<BinaryOperator>(Next->getAssociatedExpression())) &&
7650 "Unexpected expression");
7656 const Expr *BaseExpr =
E->getBase();
7676 OAShE->getBase()->getType()->getPointeeType()),
7678 OAShE->getBase()->getType()));
7679 }
else if (IsMemberReference) {
7680 const auto *ME = cast<MemberExpr>(I->getAssociatedExpression());
7681 LValue BaseLVal = EmitMemberExprBase(CGF, ME);
7683 BaseLVal, cast<FieldDecl>(MapDecl))
7696 bool IsMemberPointerOrAddr =
7698 (((IsPointer || ForDeviceAddr) &&
7699 I->getAssociatedExpression() == EncounteredME) ||
7700 (IsPrevMemberReference && !IsPointer) ||
7701 (IsMemberReference && Next != CE &&
7702 !Next->getAssociatedExpression()->getType()->isPointerType()));
7703 if (!OverlappedElements.empty() && Next == CE) {
7705 assert(!PartialStruct.Base.isValid() &&
"The base element is set.");
7706 assert(!IsPointer &&
7707 "Unexpected base element with the pointer type.");
7710 PartialStruct.LowestElem = {0, LowestElem};
7712 I->getAssociatedExpression()->getType());
7717 PartialStruct.HighestElem = {
7718 std::numeric_limits<
decltype(
7719 PartialStruct.HighestElem.first)>
::max(),
7721 PartialStruct.Base = BP;
7722 PartialStruct.LB = LB;
7724 PartialStruct.PreliminaryMapData.BasePointers.empty() &&
7725 "Overlapped elements must be used only once for the variable.");
7726 std::swap(PartialStruct.PreliminaryMapData, CombinedInfo);
7728 OpenMPOffloadMappingFlags Flags =
7729 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF |
7730 getMapTypeBits(MapType, MapModifiers, MotionModifiers, IsImplicit,
7732 false, IsNonContiguous);
7733 CopyOverlappedEntryGaps CopyGaps(CGF, CombinedInfo, Flags, MapDecl,
7734 MapExpr, BP, LB, IsNonContiguous,
7738 Component : OverlappedElements) {
7742 if (
const auto *FD = dyn_cast<FieldDecl>(VD)) {
7743 CopyGaps.processField(MC, FD, EmitMemberExprBase);
7748 CopyGaps.copyUntilEnd(HB);
7751 llvm::Value *
Size = getExprTypeSize(I->getAssociatedExpression());
7758 if ((!IsMemberPointerOrAddr && !IsPartialMapped) ||
7760 if (!IsMappingWholeStruct) {
7761 CombinedInfo.Exprs.emplace_back(MapDecl, MapExpr);
7763 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
7764 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
7766 CombinedInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
7768 CombinedInfo.NonContigInfo.Dims.push_back(IsNonContiguous ? DimSize
7771 StructBaseCombinedInfo.Exprs.emplace_back(MapDecl, MapExpr);
7772 StructBaseCombinedInfo.BasePointers.push_back(
7774 StructBaseCombinedInfo.DevicePtrDecls.push_back(
nullptr);
7775 StructBaseCombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
7776 StructBaseCombinedInfo.Pointers.push_back(LB.
emitRawPointer(CGF));
7777 StructBaseCombinedInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
7779 StructBaseCombinedInfo.NonContigInfo.Dims.push_back(
7780 IsNonContiguous ? DimSize : 1);
7784 bool HasMapper = Mapper && Next == CE;
7785 if (!IsMappingWholeStruct)
7786 CombinedInfo.Mappers.push_back(HasMapper ? Mapper :
nullptr);
7788 StructBaseCombinedInfo.Mappers.push_back(HasMapper ? Mapper
7795 OpenMPOffloadMappingFlags Flags =
7796 getMapTypeBits(MapType, MapModifiers, MotionModifiers, IsImplicit,
7797 !IsExpressionFirstInfo || RequiresReference ||
7798 FirstPointerInComplexData || IsMemberReference,
7799 AreBothBasePtrAndPteeMapped ||
7800 (IsCaptureFirstInfo && !RequiresReference),
7803 if (!IsExpressionFirstInfo || IsMemberReference) {
7806 if (IsPointer || (IsMemberReference && Next != CE))
7807 Flags &= ~(OpenMPOffloadMappingFlags::OMP_MAP_TO |
7808 OpenMPOffloadMappingFlags::OMP_MAP_FROM |
7809 OpenMPOffloadMappingFlags::OMP_MAP_ALWAYS |
7810 OpenMPOffloadMappingFlags::OMP_MAP_DELETE |
7811 OpenMPOffloadMappingFlags::OMP_MAP_CLOSE);
7813 if (ShouldBeMemberOf) {
7816 Flags |= OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF;
7819 ShouldBeMemberOf =
false;
7823 if (!IsMappingWholeStruct)
7824 CombinedInfo.Types.push_back(Flags);
7826 StructBaseCombinedInfo.Types.push_back(Flags);
7832 if (EncounteredME) {
7833 const auto *FD = cast<FieldDecl>(EncounteredME->
getMemberDecl());
7837 if (!PartialStruct.Base.isValid()) {
7838 PartialStruct.LowestElem = {FieldIndex, LowestElem};
7839 if (IsFinalArraySection && OASE) {
7843 PartialStruct.HighestElem = {FieldIndex, HB};
7845 PartialStruct.HighestElem = {FieldIndex, LowestElem};
7847 PartialStruct.Base = BP;
7848 PartialStruct.LB = BP;
7849 }
else if (FieldIndex < PartialStruct.LowestElem.first) {
7850 PartialStruct.LowestElem = {FieldIndex, LowestElem};
7851 }
else if (FieldIndex > PartialStruct.HighestElem.first) {
7852 if (IsFinalArraySection && OASE) {
7856 PartialStruct.HighestElem = {FieldIndex, HB};
7858 PartialStruct.HighestElem = {FieldIndex, LowestElem};
7864 if (IsFinalArraySection || IsNonContiguous)
7865 PartialStruct.IsArraySection =
true;
7868 if (IsFinalArraySection)
7873 BP = IsMemberReference ? LowestElem : LB;
7874 if (!IsPartialMapped)
7875 IsExpressionFirstInfo =
false;
7876 IsCaptureFirstInfo =
false;
7877 FirstPointerInComplexData =
false;
7878 IsPrevMemberReference = IsMemberReference;
7879 }
else if (FirstPointerInComplexData) {
7881 ->getAssociatedDeclaration()
7883 .getNonReferenceType();
7885 FirstPointerInComplexData =
false;
7891 PartialStruct.HasCompleteRecord =
true;
7893 if (!IsNonContiguous)
7900 MapValuesArrayTy CurOffsets = {llvm::ConstantInt::get(CGF.
CGM.
Int64Ty, 0)};
7901 MapValuesArrayTy CurCounts = {llvm::ConstantInt::get(CGF.
CGM.
Int64Ty, 1)};
7902 MapValuesArrayTy CurStrides;
7903 MapValuesArrayTy DimSizes{llvm::ConstantInt::get(CGF.
CGM.
Int64Ty, 1)};
7911 const Expr *AssocExpr = Component.getAssociatedExpression();
7912 const auto *OASE = dyn_cast<ArraySectionExpr>(AssocExpr);
7922 assert((VAT || CAT || &Component == &*Components.begin()) &&
7923 "Should be either ConstantArray or VariableArray if not the "
7927 if (CurStrides.empty()) {
7928 const Type *ElementType =
nullptr;
7930 ElementType = CAT->getElementType().getTypePtr();
7932 ElementType = VAT->getElementType().getTypePtr();
7934 assert(&Component == &*Components.begin() &&
7935 "Only expect pointer (non CAT or VAT) when this is the "
7943 if (&Component != &*Components.begin())
7947 CurStrides.push_back(
7948 llvm::ConstantInt::get(CGF.
Int64Ty, ElementTypeSize));
7953 if (DimSizes.size() < Components.size() - 1) {
7956 llvm::ConstantInt::get(CGF.
Int64Ty, CAT->getZExtSize()));
7958 DimSizes.push_back(CGF.
Builder.CreateIntCast(
7965 auto *DI = DimSizes.begin() + 1;
7967 llvm::Value *DimProd =
7968 llvm::ConstantInt::get(CGF.
CGM.
Int64Ty, ElementTypeSize);
7979 const Expr *AssocExpr = Component.getAssociatedExpression();
7981 if (
const auto *AE = dyn_cast<ArraySubscriptExpr>(AssocExpr)) {
7982 llvm::Value *Offset = CGF.
Builder.CreateIntCast(
7985 CurOffsets.push_back(Offset);
7986 CurCounts.push_back(llvm::ConstantInt::get(CGF.
Int64Ty, 1));
7987 CurStrides.push_back(CurStrides.back());
7991 const auto *OASE = dyn_cast<ArraySectionExpr>(AssocExpr);
7997 const Expr *OffsetExpr = OASE->getLowerBound();
7998 llvm::Value *Offset =
nullptr;
8001 Offset = llvm::ConstantInt::get(CGF.
Int64Ty, 0);
8007 CurOffsets.push_back(Offset);
8010 const Expr *CountExpr = OASE->getLength();
8011 llvm::Value *Count =
nullptr;
8017 if (!OASE->getColonLocFirst().isValid() &&
8018 !OASE->getColonLocSecond().isValid()) {
8019 Count = llvm::ConstantInt::get(CGF.
Int64Ty, 1);
8025 const Expr *StrideExpr = OASE->getStride();
8026 llvm::Value *Stride =
8032 Count = CGF.
Builder.CreateUDiv(
8033 CGF.
Builder.CreateNUWSub(*DI, Offset), Stride);
8035 Count = CGF.
Builder.CreateNUWSub(*DI, Offset);
8041 CurCounts.push_back(Count);
8050 const Expr *StrideExpr = OASE->getStride();
8051 llvm::Value *Stride =
8056 DimProd = CGF.
Builder.CreateNUWMul(DimProd, *(DI - 1));
8058 CurStrides.push_back(CGF.
Builder.CreateNUWMul(DimProd, Stride));
8060 CurStrides.push_back(DimProd);
8061 if (DI != DimSizes.end())
8065 CombinedInfo.NonContigInfo.Offsets.push_back(CurOffsets);
8066 CombinedInfo.NonContigInfo.Counts.push_back(CurCounts);
8067 CombinedInfo.NonContigInfo.Strides.push_back(CurStrides);
8073 OpenMPOffloadMappingFlags
8082 return OpenMPOffloadMappingFlags::OMP_MAP_TO |
8083 OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ;
8084 return OpenMPOffloadMappingFlags::OMP_MAP_PRIVATE |
8085 OpenMPOffloadMappingFlags::OMP_MAP_TO;
8088 if (I != LambdasMap.end())
8090 return getMapTypeBits(
8091 I->getSecond()->getMapType(), I->getSecond()->getMapTypeModifiers(),
8092 {}, I->getSecond()->isImplicit(),
8096 return OpenMPOffloadMappingFlags::OMP_MAP_TO |
8097 OpenMPOffloadMappingFlags::OMP_MAP_FROM;
8102 bool AsBase)
const {
8105 llvm::StructType *St =
8108 unsigned NumElements = St->getNumElements();
8110 llvm::PointerUnion<const CXXRecordDecl *, const FieldDecl *>, 4>
8111 RecordLayout(NumElements);
8114 for (
const auto &I : RD->
bases()) {
8129 RecordLayout[FieldIndex] =
Base;
8132 for (
const auto &I : RD->
vbases()) {
8140 if (RecordLayout[FieldIndex])
8142 RecordLayout[FieldIndex] =
Base;
8145 assert(!RD->
isUnion() &&
"Unexpected union.");
8146 for (
const auto *Field : RD->
fields()) {
8149 if (!
Field->isBitField() &&
8152 RecordLayout[FieldIndex] =
Field;
8155 for (
const llvm::PointerUnion<const CXXRecordDecl *, const FieldDecl *>
8156 &
Data : RecordLayout) {
8159 if (
const auto *
Base = dyn_cast<const CXXRecordDecl *>(
Data))
8160 getPlainLayout(
Base, Layout,
true);
8162 Layout.push_back(cast<const FieldDecl *>(
Data));
8171 void generateAllInfoForClauses(
8173 llvm::OpenMPIRBuilder &OMPBuilder,
8180 llvm::MapVector<CanonicalDeclPtr<const Decl>,
8187 [&Info, &SkipVarSet](
8193 bool ReturnDevicePointer,
bool IsImplicit,
const ValueDecl *Mapper,
8194 const Expr *VarRef =
nullptr,
bool ForDeviceAddr =
false) {
8195 if (SkipVarSet.contains(
D))
8197 auto It = Info.try_emplace(
D, Total).first;
8198 It->second[
Kind].emplace_back(
8199 L, MapType, MapModifiers, MotionModifiers, ReturnDevicePointer,
8200 IsImplicit, Mapper, VarRef, ForDeviceAddr);
8203 for (
const auto *
Cl : Clauses) {
8204 const auto *
C = dyn_cast<OMPMapClause>(
Cl);
8208 if (llvm::is_contained(
C->getMapTypeModifiers(),
8209 OMPC_MAP_MODIFIER_present))
8211 else if (
C->getMapType() == OMPC_MAP_alloc)
8213 const auto *EI =
C->getVarRefs().begin();
8214 for (
const auto L :
C->component_lists()) {
8215 const Expr *
E = (
C->getMapLoc().isValid()) ? *EI :
nullptr;
8216 InfoGen(std::get<0>(L),
Kind, std::get<1>(L),
C->getMapType(),
8217 C->getMapTypeModifiers(), {},
8218 false,
C->isImplicit(), std::get<2>(L),
8223 for (
const auto *
Cl : Clauses) {
8224 const auto *
C = dyn_cast<OMPToClause>(
Cl);
8228 if (llvm::is_contained(
C->getMotionModifiers(),
8229 OMPC_MOTION_MODIFIER_present))
8231 const auto *EI =
C->getVarRefs().begin();
8232 for (
const auto L :
C->component_lists()) {
8233 InfoGen(std::get<0>(L),
Kind, std::get<1>(L), OMPC_MAP_to, {},
8234 C->getMotionModifiers(),
false,
8235 C->isImplicit(), std::get<2>(L), *EI);
8239 for (
const auto *
Cl : Clauses) {
8240 const auto *
C = dyn_cast<OMPFromClause>(
Cl);
8244 if (llvm::is_contained(
C->getMotionModifiers(),
8245 OMPC_MOTION_MODIFIER_present))
8247 const auto *EI =
C->getVarRefs().begin();
8248 for (
const auto L :
C->component_lists()) {
8249 InfoGen(std::get<0>(L),
Kind, std::get<1>(L), OMPC_MAP_from, {},
8250 C->getMotionModifiers(),
8251 false,
C->isImplicit(), std::get<2>(L),
8264 llvm::MapVector<CanonicalDeclPtr<const Decl>,
8267 MapCombinedInfoTy UseDeviceDataCombinedInfo;
8269 auto &&UseDeviceDataCombinedInfoGen =
8270 [&UseDeviceDataCombinedInfo](
const ValueDecl *VD, llvm::Value *Ptr,
8272 UseDeviceDataCombinedInfo.Exprs.push_back(VD);
8273 UseDeviceDataCombinedInfo.BasePointers.emplace_back(Ptr);
8274 UseDeviceDataCombinedInfo.DevicePtrDecls.emplace_back(VD);
8275 UseDeviceDataCombinedInfo.DevicePointers.emplace_back(
8276 IsDevAddr ? DeviceInfoTy::Address : DeviceInfoTy::Pointer);
8277 UseDeviceDataCombinedInfo.Pointers.push_back(Ptr);
8278 UseDeviceDataCombinedInfo.Sizes.push_back(
8279 llvm::Constant::getNullValue(CGF.Int64Ty));
8280 UseDeviceDataCombinedInfo.Types.push_back(
8281 OpenMPOffloadMappingFlags::OMP_MAP_RETURN_PARAM);
8282 UseDeviceDataCombinedInfo.Mappers.push_back(
nullptr);
8286 [&DeferredInfo, &UseDeviceDataCombinedInfoGen,
8290 bool IsImplicit,
bool IsDevAddr) {
8294 if (isa<MemberExpr>(IE)) {
8303 false, IsImplicit,
nullptr,
nullptr,
8305 DeferredInfo[
nullptr].emplace_back(IE, VD, IsDevAddr);
8309 if (IE->isGLValue())
8310 Ptr = CGF.EmitLValue(IE).getPointer(CGF);
8312 Ptr = CGF.EmitScalarExpr(IE);
8314 Ptr = CGF.EmitLoadOfScalar(CGF.EmitLValue(IE), IE->getExprLoc());
8316 UseDeviceDataCombinedInfoGen(VD, Ptr, CGF, IsDevAddr);
8321 const Expr *IE,
bool IsDevAddr) ->
bool {
8328 auto It = Info.find(isa<MemberExpr>(IE) ? nullptr : VD);
8329 if (It != Info.end()) {
8331 for (
auto &
Data : It->second) {
8332 auto *CI = llvm::find_if(
Data, [VD](
const MapInfo &MI) {
8333 return MI.Components.back().getAssociatedDeclaration() == VD;
8341 if (CI !=
Data.end()) {
8343 CI->ForDeviceAddr = IsDevAddr;
8344 CI->ReturnDevicePointer =
true;
8348 auto PrevCI = std::next(CI->Components.rbegin());
8349 const auto *VarD = dyn_cast<VarDecl>(VD);
8351 isa<MemberExpr>(IE) ||
8352 !VD->getType().getNonReferenceType()->isPointerType() ||
8353 PrevCI == CI->Components.rend() ||
8354 isa<MemberExpr>(PrevCI->getAssociatedExpression()) || !VarD ||
8355 VarD->hasLocalStorage()) {
8356 CI->ForDeviceAddr = IsDevAddr;
8357 CI->ReturnDevicePointer =
true;
8375 for (
const auto *
Cl : Clauses) {
8376 const auto *
C = dyn_cast<OMPUseDevicePtrClause>(
Cl);
8379 for (
const auto L :
C->component_lists()) {
8382 assert(!Components.empty() &&
8383 "Not expecting empty list of components!");
8384 const ValueDecl *VD = Components.back().getAssociatedDeclaration();
8386 const Expr *IE = Components.back().getAssociatedExpression();
8387 if (IsMapInfoExist(CGF, VD, IE,
false))
8389 MapInfoGen(CGF, IE, VD, Components,
C->isImplicit(),
8394 llvm::SmallDenseSet<CanonicalDeclPtr<const Decl>, 4> Processed;
8395 for (
const auto *
Cl : Clauses) {
8396 const auto *
C = dyn_cast<OMPUseDeviceAddrClause>(
Cl);
8399 for (
const auto L :
C->component_lists()) {
8402 assert(!std::get<1>(L).empty() &&
8403 "Not expecting empty list of components!");
8404 const ValueDecl *VD = std::get<1>(L).back().getAssociatedDeclaration();
8405 if (!Processed.insert(VD).second)
8408 const Expr *IE = std::get<1>(L).back().getAssociatedExpression();
8409 if (IsMapInfoExist(CGF, VD, IE,
true))
8411 MapInfoGen(CGF, IE, VD, Components,
C->isImplicit(),
8416 for (
const auto &
Data : Info) {
8417 StructRangeInfoTy PartialStruct;
8419 MapCombinedInfoTy CurInfo;
8421 MapCombinedInfoTy StructBaseCurInfo;
8423 const ValueDecl *VD = cast_or_null<ValueDecl>(
D);
8424 bool HasMapBasePtr =
false;
8425 bool HasMapArraySec =
false;
8427 for (
const auto &M :
Data.second) {
8428 HasMapBasePtr = any_of(M, [](
const MapInfo &L) {
8429 return isa_and_present<DeclRefExpr>(L.VarRef);
8431 HasMapArraySec = any_of(M, [](
const MapInfo &L) {
8432 return isa_and_present<ArraySectionExpr, ArraySubscriptExpr>(
8435 if (HasMapBasePtr && HasMapArraySec)
8439 for (
const auto &M :
Data.second) {
8440 for (
const MapInfo &L : M) {
8441 assert(!L.Components.empty() &&
8442 "Not expecting declaration with no component lists.");
8445 unsigned CurrentBasePointersIdx = CurInfo.BasePointers.size();
8446 unsigned StructBasePointersIdx =
8447 StructBaseCurInfo.BasePointers.size();
8448 CurInfo.NonContigInfo.IsNonContiguous =
8449 L.Components.back().isNonContiguous();
8450 generateInfoForComponentList(
8451 L.MapType, L.MapModifiers, L.MotionModifiers, L.Components,
8452 CurInfo, StructBaseCurInfo, PartialStruct,
8453 false, L.IsImplicit,
8454 true, L.Mapper, L.ForDeviceAddr, VD,
8456 HasMapBasePtr && HasMapArraySec);
8460 if (L.ReturnDevicePointer) {
8464 assert((CurrentBasePointersIdx < CurInfo.BasePointers.size() ||
8465 StructBasePointersIdx <
8466 StructBaseCurInfo.BasePointers.size()) &&
8467 "Unexpected number of mapped base pointers.");
8471 L.Components.back().getAssociatedDeclaration();
8472 assert(RelevantVD &&
8473 "No relevant declaration related with device pointer??");
8480 if (StructBasePointersIdx < StructBaseCurInfo.BasePointers.size()) {
8481 StructBaseCurInfo.DevicePtrDecls[StructBasePointersIdx] =
8483 StructBaseCurInfo.DevicePointers[StructBasePointersIdx] =
8484 L.ForDeviceAddr ? DeviceInfoTy::Address
8485 : DeviceInfoTy::Pointer;
8486 StructBaseCurInfo.Types[StructBasePointersIdx] |=
8487 OpenMPOffloadMappingFlags::OMP_MAP_RETURN_PARAM;
8489 CurInfo.DevicePtrDecls[CurrentBasePointersIdx] = RelevantVD;
8490 CurInfo.DevicePointers[CurrentBasePointersIdx] =
8491 L.ForDeviceAddr ? DeviceInfoTy::Address
8492 : DeviceInfoTy::Pointer;
8493 CurInfo.Types[CurrentBasePointersIdx] |=
8494 OpenMPOffloadMappingFlags::OMP_MAP_RETURN_PARAM;
8502 auto CI = DeferredInfo.find(
Data.first);
8503 if (CI != DeferredInfo.end()) {
8504 for (
const DeferredDevicePtrEntryTy &L : CI->second) {
8505 llvm::Value *BasePtr;
8507 if (L.ForDeviceAddr) {
8508 if (L.IE->isGLValue())
8516 CurInfo.Types.push_back(
8517 OpenMPOffloadMappingFlags::OMP_MAP_RETURN_PARAM |
8518 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF);
8522 L.IE->getExprLoc());
8526 CurInfo.Types.push_back(
8527 OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ |
8528 OpenMPOffloadMappingFlags::OMP_MAP_RETURN_PARAM |
8529 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF);
8531 CurInfo.Exprs.push_back(L.VD);
8532 CurInfo.BasePointers.emplace_back(BasePtr);
8533 CurInfo.DevicePtrDecls.emplace_back(L.VD);
8534 CurInfo.DevicePointers.emplace_back(
8535 L.ForDeviceAddr ? DeviceInfoTy::Address : DeviceInfoTy::Pointer);
8536 CurInfo.Pointers.push_back(Ptr);
8537 CurInfo.Sizes.push_back(
8538 llvm::Constant::getNullValue(this->CGF.
Int64Ty));
8539 CurInfo.Mappers.push_back(
nullptr);
8545 MapCombinedInfoTy UnionCurInfo;
8546 UnionCurInfo.append(StructBaseCurInfo);
8547 UnionCurInfo.append(CurInfo);
8551 if (PartialStruct.Base.isValid()) {
8552 UnionCurInfo.NonContigInfo.Dims.push_back(0);
8554 emitCombinedEntry(CombinedInfo, UnionCurInfo.Types, PartialStruct,
8555 !VD, OMPBuilder, VD);
8559 CombinedInfo.append(UnionCurInfo);
8562 CombinedInfo.append(UseDeviceDataCombinedInfo);
8567 : CurDir(&Dir), CGF(CGF) {
8570 for (
const auto *
D :
C->varlist())
8571 FirstPrivateDecls.try_emplace(
8572 cast<VarDecl>(cast<DeclRefExpr>(
D)->getDecl()),
C->isImplicit());
8575 for (
unsigned I = 0,
E =
C->getNumberOfAllocators(); I <
E; ++I) {
8577 if (
const auto *DRE = dyn_cast_or_null<DeclRefExpr>(
D.AllocatorTraits))
8578 FirstPrivateDecls.try_emplace(cast<VarDecl>(DRE->getDecl()),
8580 else if (
const auto *VD = dyn_cast<VarDecl>(
8581 cast<DeclRefExpr>(
D.Allocator->IgnoreParenImpCasts())
8583 FirstPrivateDecls.try_emplace(VD,
true);
8588 for (
auto L :
C->component_lists())
8589 DevPointersMap[std::get<0>(L)].push_back(std::get<1>(L));
8592 for (
auto L :
C->component_lists())
8593 HasDevAddrsMap[std::get<0>(L)].push_back(std::get<1>(L));
8596 if (
C->getMapType() != OMPC_MAP_to)
8598 for (
auto L :
C->component_lists()) {
8600 const auto *RD = VD ? VD->
getType()
8606 LambdasMap.try_emplace(std::get<0>(L),
C);
8613 : CurDir(&Dir), CGF(CGF) {}
8618 void emitCombinedEntry(MapCombinedInfoTy &CombinedInfo,
8619 MapFlagsArrayTy &CurTypes,
8620 const StructRangeInfoTy &PartialStruct,
bool IsMapThis,
8621 llvm::OpenMPIRBuilder &OMPBuilder,
8623 unsigned OffsetForMemberOfFlag = 0,
8624 bool NotTargetParams =
true)
const {
8625 if (CurTypes.size() == 1 &&
8626 ((CurTypes.back() & OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF) !=
8627 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF) &&
8628 !PartialStruct.IsArraySection)
8630 Address LBAddr = PartialStruct.LowestElem.second;
8631 Address HBAddr = PartialStruct.HighestElem.second;
8632 if (PartialStruct.HasCompleteRecord) {
8633 LBAddr = PartialStruct.LB;
8634 HBAddr = PartialStruct.LB;
8636 CombinedInfo.Exprs.push_back(VD);
8638 CombinedInfo.BasePointers.push_back(PartialStruct.Base.emitRawPointer(CGF));
8639 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
8640 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
8646 bool HasBaseClass = RD && IsMapThis ? RD->
getNumBases() > 0 :
false;
8656 CombinedInfo.Pointers.push_back(PartialStruct.Base.emitRawPointer(CGF));
8661 CombinedInfo.Sizes.push_back(Size);
8663 CombinedInfo.Pointers.push_back(LB);
8666 llvm::Value *HAddr = CGF.
Builder.CreateConstGEP1_32(
8670 llvm::Value *Diff = CGF.
Builder.CreatePtrDiff(CGF.
Int8Ty, CHAddr, CLAddr);
8673 CombinedInfo.Sizes.push_back(Size);
8675 CombinedInfo.Mappers.push_back(
nullptr);
8677 CombinedInfo.Types.push_back(
8678 NotTargetParams ? OpenMPOffloadMappingFlags::OMP_MAP_NONE
8679 : !PartialStruct.PreliminaryMapData.BasePointers.empty()
8680 ? OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ
8681 : OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM);
8684 if (CurTypes.end() !=
8685 llvm::find_if(CurTypes, [](OpenMPOffloadMappingFlags
Type) {
8686 return static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>>(
8687 Type & OpenMPOffloadMappingFlags::OMP_MAP_PRESENT);
8689 CombinedInfo.Types.back() |= OpenMPOffloadMappingFlags::OMP_MAP_PRESENT;
8691 (*CurTypes.begin()) &= ~OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM;
8698 if (CurTypes.end() !=
8699 llvm::find_if(CurTypes, [](OpenMPOffloadMappingFlags
Type) {
8700 return static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
8701 Type & OpenMPOffloadMappingFlags::OMP_MAP_OMPX_HOLD);
8703 CombinedInfo.Types.back() |= OpenMPOffloadMappingFlags::OMP_MAP_OMPX_HOLD;
8704 for (
auto &M : CurTypes)
8705 M |= OpenMPOffloadMappingFlags::OMP_MAP_OMPX_HOLD;
8711 OpenMPOffloadMappingFlags MemberOfFlag = OMPBuilder.getMemberOfFlag(
8712 OffsetForMemberOfFlag + CombinedInfo.BasePointers.size() - 1);
8713 for (
auto &M : CurTypes)
8714 OMPBuilder.setCorrectMemberOfFlag(M, MemberOfFlag);
8722 void generateAllInfo(
8723 MapCombinedInfoTy &CombinedInfo, llvm::OpenMPIRBuilder &OMPBuilder,
8726 assert(isa<const OMPExecutableDirective *>(CurDir) &&
8727 "Expect a executable directive");
8728 const auto *CurExecDir = cast<const OMPExecutableDirective *>(CurDir);
8729 generateAllInfoForClauses(CurExecDir->clauses(), CombinedInfo, OMPBuilder,
8736 void generateAllInfoForMapper(MapCombinedInfoTy &CombinedInfo,
8737 llvm::OpenMPIRBuilder &OMPBuilder)
const {
8738 assert(isa<const OMPDeclareMapperDecl *>(CurDir) &&
8739 "Expect a declare mapper directive");
8740 const auto *CurMapperDir = cast<const OMPDeclareMapperDecl *>(CurDir);
8741 generateAllInfoForClauses(CurMapperDir->clauses(), CombinedInfo,
8746 void generateInfoForLambdaCaptures(
8747 const ValueDecl *VD, llvm::Value *Arg, MapCombinedInfoTy &CombinedInfo,
8748 llvm::DenseMap<llvm::Value *, llvm::Value *> &LambdaPointers)
const {
8756 llvm::DenseMap<const ValueDecl *, FieldDecl *> Captures;
8763 LambdaPointers.try_emplace(ThisLVal.
getPointer(CGF),
8765 CombinedInfo.Exprs.push_back(VD);
8766 CombinedInfo.BasePointers.push_back(ThisLVal.
getPointer(CGF));
8767 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
8768 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
8769 CombinedInfo.Pointers.push_back(ThisLValVal.
getPointer(CGF));
8770 CombinedInfo.Sizes.push_back(
8773 CombinedInfo.Types.push_back(
8774 OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ |
8775 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL |
8776 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF |
8777 OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT);
8778 CombinedInfo.Mappers.push_back(
nullptr);
8781 if (!LC.capturesVariable())
8783 const VarDecl *VD = cast<VarDecl>(LC.getCapturedVar());
8786 auto It = Captures.find(VD);
8787 assert(It != Captures.end() &&
"Found lambda capture without field.");
8791 LambdaPointers.try_emplace(VarLVal.
getPointer(CGF),
8793 CombinedInfo.Exprs.push_back(VD);
8794 CombinedInfo.BasePointers.push_back(VarLVal.
getPointer(CGF));
8795 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
8796 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
8797 CombinedInfo.Pointers.push_back(VarLValVal.
getPointer(CGF));
8798 CombinedInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
8804 LambdaPointers.try_emplace(VarLVal.
getPointer(CGF),
8806 CombinedInfo.Exprs.push_back(VD);
8807 CombinedInfo.BasePointers.push_back(VarLVal.
getPointer(CGF));
8808 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
8809 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
8810 CombinedInfo.Pointers.push_back(VarRVal.
getScalarVal());
8811 CombinedInfo.Sizes.push_back(llvm::ConstantInt::get(CGF.
Int64Ty, 0));
8813 CombinedInfo.Types.push_back(
8814 OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ |
8815 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL |
8816 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF |
8817 OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT);
8818 CombinedInfo.Mappers.push_back(
nullptr);
8823 void adjustMemberOfForLambdaCaptures(
8824 llvm::OpenMPIRBuilder &OMPBuilder,
8825 const llvm::DenseMap<llvm::Value *, llvm::Value *> &LambdaPointers,
8826 MapBaseValuesArrayTy &BasePointers, MapValuesArrayTy &Pointers,
8827 MapFlagsArrayTy &Types)
const {
8828 for (
unsigned I = 0,
E = Types.size(); I <
E; ++I) {
8830 if (Types[I] != (OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ |
8831 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL |
8832 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF |
8833 OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT))
8835 llvm::Value *BasePtr = LambdaPointers.lookup(BasePointers[I]);
8836 assert(BasePtr &&
"Unable to find base lambda address.");
8838 for (
unsigned J = I; J > 0; --J) {
8839 unsigned Idx = J - 1;
8840 if (Pointers[Idx] != BasePtr)
8845 assert(TgtIdx != -1 &&
"Unable to find parent lambda.");
8849 OpenMPOffloadMappingFlags MemberOfFlag =
8850 OMPBuilder.getMemberOfFlag(TgtIdx);
8851 OMPBuilder.setCorrectMemberOfFlag(Types[I], MemberOfFlag);
8858 void generateInfoForCaptureFromClauseInfo(
8860 MapCombinedInfoTy &CurCaptureVarInfo, llvm::OpenMPIRBuilder &OMPBuilder,
8861 unsigned OffsetForMemberOfFlag)
const {
8863 "Not expecting to generate map info for a variable array type!");
8872 if (LambdasMap.count(VD))
8878 if (VD && (DevPointersMap.count(VD) || HasDevAddrsMap.count(VD))) {
8879 CurCaptureVarInfo.Exprs.push_back(VD);
8880 CurCaptureVarInfo.BasePointers.emplace_back(Arg);
8881 CurCaptureVarInfo.DevicePtrDecls.emplace_back(VD);
8882 CurCaptureVarInfo.DevicePointers.emplace_back(DeviceInfoTy::Pointer);
8883 CurCaptureVarInfo.Pointers.push_back(Arg);
8884 CurCaptureVarInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
8887 CurCaptureVarInfo.Types.push_back(
8888 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL |
8889 OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM);
8890 CurCaptureVarInfo.Mappers.push_back(
nullptr);
8894 MapDataArrayTy DeclComponentLists;
8898 auto It = DevPointersMap.find(VD);
8899 if (It != DevPointersMap.end())
8900 for (
const auto &MCL : It->second)
8901 DeclComponentLists.emplace_back(MCL, OMPC_MAP_to,
Unknown,
8904 auto I = HasDevAddrsMap.find(VD);
8905 if (I != HasDevAddrsMap.end())
8906 for (
const auto &MCL : I->second)
8907 DeclComponentLists.emplace_back(MCL, OMPC_MAP_tofrom,
Unknown,
8910 assert(isa<const OMPExecutableDirective *>(CurDir) &&
8911 "Expect a executable directive");
8912 const auto *CurExecDir = cast<const OMPExecutableDirective *>(CurDir);
8913 bool HasMapBasePtr =
false;
8914 bool HasMapArraySec =
false;
8915 for (
const auto *
C : CurExecDir->getClausesOfKind<
OMPMapClause>()) {
8916 const auto *EI =
C->getVarRefs().begin();
8917 for (
const auto L :
C->decl_component_lists(VD)) {
8920 const Expr *
E = (
C->getMapLoc().isValid()) ? *EI :
nullptr;
8922 std::tie(VDecl, Components, Mapper) = L;
8923 assert(VDecl == VD &&
"We got information for the wrong declaration??");
8924 assert(!Components.empty() &&
8925 "Not expecting declaration with no component lists.");
8927 HasMapBasePtr =
true;
8929 (isa<ArraySectionExpr>(
E) || isa<ArraySubscriptExpr>(
E)))
8930 HasMapArraySec =
true;
8931 DeclComponentLists.emplace_back(Components,
C->getMapType(),
8932 C->getMapTypeModifiers(),
8933 C->isImplicit(), Mapper,
E);
8937 llvm::stable_sort(DeclComponentLists, [](
const MapData &LHS,
8938 const MapData &RHS) {
8942 llvm::is_contained(MapModifiers, clang::OMPC_MAP_MODIFIER_present);
8943 bool HasAllocs = MapType == OMPC_MAP_alloc;
8944 MapModifiers = std::get<2>(RHS);
8945 MapType = std::get<1>(LHS);
8947 llvm::is_contained(MapModifiers, clang::OMPC_MAP_MODIFIER_present);
8948 bool HasAllocsR = MapType == OMPC_MAP_alloc;
8949 return (HasPresent && !HasPresentR) || (HasAllocs && !HasAllocsR);
8952 auto GenerateInfoForComponentLists =
8954 bool IsEligibleForTargetParamFlag) {
8955 MapCombinedInfoTy CurInfoForComponentLists;
8956 StructRangeInfoTy PartialStruct;
8958 if (DeclComponentLists.empty())
8961 generateInfoForCaptureFromComponentLists(
8962 VD, DeclComponentLists, CurInfoForComponentLists, PartialStruct,
8963 IsEligibleForTargetParamFlag,
8964 HasMapBasePtr && HasMapArraySec);
8969 if (PartialStruct.Base.isValid()) {
8970 CurCaptureVarInfo.append(PartialStruct.PreliminaryMapData);
8972 CurCaptureVarInfo, CurInfoForComponentLists.Types,
8973 PartialStruct, Cap->
capturesThis(), OMPBuilder,
nullptr,
8974 OffsetForMemberOfFlag,
8975 !IsEligibleForTargetParamFlag);
8979 if (CurInfoForComponentLists.BasePointers.empty())
8982 CurCaptureVarInfo.append(CurInfoForComponentLists);
8985 GenerateInfoForComponentLists(DeclComponentLists,
8992 void generateInfoForCaptureFromComponentLists(
8994 MapCombinedInfoTy &CurComponentListInfo, StructRangeInfoTy &PartialStruct,
8995 bool IsListEligibleForTargetParamFlag,
8996 bool AreBothBasePtrAndPteeMapped =
false)
const {
8998 llvm::SmallDenseMap<
9005 for (
const MapData &L : DeclComponentLists) {
9012 std::tie(Components, MapType, MapModifiers, IsImplicit, Mapper, VarRef) =
9015 for (
const MapData &L1 :
ArrayRef(DeclComponentLists).slice(Count)) {
9017 std::tie(Components1, MapType, MapModifiers, IsImplicit, Mapper,
9019 auto CI = Components.rbegin();
9020 auto CE = Components.rend();
9021 auto SI = Components1.rbegin();
9022 auto SE = Components1.rend();
9023 for (; CI != CE && SI != SE; ++CI, ++SI) {
9024 if (CI->getAssociatedExpression()->getStmtClass() !=
9025 SI->getAssociatedExpression()->getStmtClass())
9028 if (CI->getAssociatedDeclaration() != SI->getAssociatedDeclaration())
9033 if (CI == CE || SI == SE) {
9035 if (CI == CE && SI == SE)
9037 const auto It = (SI == SE) ? CI : SI;
9043 if (!isa<MemberExpr>(It->getAssociatedExpression()) ||
9044 (std::prev(It)->getAssociatedDeclaration() &&
9046 ->getAssociatedDeclaration()
9048 ->isPointerType()) ||
9049 (It->getAssociatedDeclaration() &&
9050 It->getAssociatedDeclaration()->getType()->isPointerType() &&
9051 std::next(It) != CE && std::next(It) != SE))
9053 const MapData &BaseData = CI == CE ? L : L1;
9055 SI == SE ? Components : Components1;
9056 OverlappedData[&BaseData].push_back(SubData);
9062 if (!OverlappedData.empty()) {
9065 while (BaseType != OrigType) {
9071 getPlainLayout(CRD, Layout,
false);
9077 for (
auto &Pair : OverlappedData) {
9084 auto CI = First.rbegin();
9085 auto CE = First.rend();
9086 auto SI = Second.rbegin();
9087 auto SE = Second.rend();
9088 for (; CI != CE && SI != SE; ++CI, ++SI) {
9089 if (CI->getAssociatedExpression()->getStmtClass() !=
9090 SI->getAssociatedExpression()->getStmtClass())
9093 if (CI->getAssociatedDeclaration() !=
9094 SI->getAssociatedDeclaration())
9099 if (CI == CE && SI == SE)
9103 if (CI == CE || SI == SE)
9106 const auto *FD1 = cast<FieldDecl>(CI->getAssociatedDeclaration());
9107 const auto *FD2 = cast<FieldDecl>(SI->getAssociatedDeclaration());
9108 if (FD1->getParent() == FD2->getParent())
9109 return FD1->getFieldIndex() < FD2->getFieldIndex();
9111 llvm::find_if(Layout, [FD1, FD2](
const FieldDecl *FD) {
9112 return FD == FD1 || FD == FD2;
9120 bool AddTargetParamFlag = IsListEligibleForTargetParamFlag;
9121 MapCombinedInfoTy StructBaseCombinedInfo;
9122 for (
const auto &Pair : OverlappedData) {
9123 const MapData &L = *Pair.getFirst();
9130 std::tie(Components, MapType, MapModifiers, IsImplicit, Mapper, VarRef) =
9133 OverlappedComponents = Pair.getSecond();
9134 generateInfoForComponentList(
9135 MapType, MapModifiers, {}, Components, CurComponentListInfo,
9136 StructBaseCombinedInfo, PartialStruct, AddTargetParamFlag, IsImplicit,
9138 false, VD, VarRef, OverlappedComponents);
9139 AddTargetParamFlag =
false;
9142 for (
const MapData &L : DeclComponentLists) {
9149 std::tie(Components, MapType, MapModifiers, IsImplicit, Mapper, VarRef) =
9151 auto It = OverlappedData.find(&L);
9152 if (It == OverlappedData.end())
9153 generateInfoForComponentList(
9154 MapType, MapModifiers, {}, Components, CurComponentListInfo,
9155 StructBaseCombinedInfo, PartialStruct, AddTargetParamFlag,
9156 IsImplicit,
false, Mapper,
9158 {}, AreBothBasePtrAndPteeMapped);
9159 AddTargetParamFlag =
false;
9167 MapCombinedInfoTy &CombinedInfo)
const {
9168 bool IsImplicit =
true;
9171 CombinedInfo.Exprs.push_back(
nullptr);
9172 CombinedInfo.BasePointers.push_back(CV);
9173 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
9174 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
9175 CombinedInfo.Pointers.push_back(CV);
9177 CombinedInfo.Sizes.push_back(
9181 CombinedInfo.Types.push_back(OpenMPOffloadMappingFlags::OMP_MAP_TO |
9182 OpenMPOffloadMappingFlags::OMP_MAP_FROM);
9186 CombinedInfo.BasePointers.push_back(CV);
9187 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
9188 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
9189 CombinedInfo.Pointers.push_back(CV);
9193 CombinedInfo.Types.push_back(
9194 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL);
9195 CombinedInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
9200 CombinedInfo.Types.push_back(OpenMPOffloadMappingFlags::OMP_MAP_NONE);
9201 CombinedInfo.Sizes.push_back(llvm::Constant::getNullValue(CGF.
Int64Ty));
9203 auto I = FirstPrivateDecls.find(VD);
9204 if (I != FirstPrivateDecls.end())
9205 IsImplicit = I->getSecond();
9210 CombinedInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
9215 CombinedInfo.Types.push_back(getMapModifiersForPrivateClauses(CI));
9217 auto I = FirstPrivateDecls.find(VD);
9219 CombinedInfo.BasePointers.push_back(CV);
9220 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
9221 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
9228 CombinedInfo.Pointers.push_back(CV);
9230 if (I != FirstPrivateDecls.end())
9231 IsImplicit = I->getSecond();
9234 CombinedInfo.Types.back() |=
9235 OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM;
9239 CombinedInfo.Types.back() |= OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT;
9242 CombinedInfo.Mappers.push_back(
nullptr);
9254 dyn_cast<MemberExpr>(OASE->getBase()->IgnoreParenImpCasts()))
9255 return ME->getMemberDecl();
9261static llvm::Constant *
9263 MappableExprsHandler::MappingExprInfo &MapExprs) {
9265 uint32_t SrcLocStrSize;
9266 if (!MapExprs.getMapDecl() && !MapExprs.getMapExpr())
9267 return OMPBuilder.getOrCreateDefaultSrcLocStr(SrcLocStrSize);
9270 if (!MapExprs.getMapDecl() && MapExprs.getMapExpr()) {
9274 Loc = MapExprs.getMapExpr()->getExprLoc();
9276 Loc = MapExprs.getMapDecl()->getLocation();
9279 std::string ExprName;
9280 if (MapExprs.getMapExpr()) {
9282 llvm::raw_string_ostream OS(ExprName);
9283 MapExprs.getMapExpr()->printPretty(OS,
nullptr,
P);
9285 ExprName = MapExprs.getMapDecl()->getNameAsString();
9294 return OMPBuilder.getOrCreateSrcLocStr(
FileName, ExprName, PLoc.
getLine(),
9301 CodeGenFunction &CGF, MappableExprsHandler::MapCombinedInfoTy &CombinedInfo,
9303 bool IsNonContiguous =
false,
bool ForEndCall =
false) {
9306 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
9309 InsertPointTy CodeGenIP(CGF.
Builder.GetInsertBlock(),
9310 CGF.
Builder.GetInsertPoint());
9312 auto DeviceAddrCB = [&](
unsigned int I, llvm::Value *NewDecl) {
9313 if (
const ValueDecl *DevVD = CombinedInfo.DevicePtrDecls[I]) {
9318 auto CustomMapperCB = [&](
unsigned int I) {
9319 llvm::Function *MFunc =
nullptr;
9320 if (CombinedInfo.Mappers[I]) {
9321 Info.HasMapper =
true;
9323 cast<OMPDeclareMapperDecl>(CombinedInfo.Mappers[I]));
9327 cantFail(OMPBuilder.emitOffloadingArraysAndArgs(
9328 AllocaIP, CodeGenIP, Info, Info.RTArgs, CombinedInfo, CustomMapperCB,
9329 IsNonContiguous, ForEndCall, DeviceAddrCB));
9335 const auto *CS =
D.getInnermostCapturedStmt();
9338 const Stmt *ChildStmt =
9341 if (
const auto *NestedDir =
9342 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) {
9344 switch (
D.getDirectiveKind()) {
9350 if (DKind == OMPD_teams) {
9351 Body = NestedDir->getInnermostCapturedStmt()->IgnoreContainers(
9356 if (
const auto *NND =
9357 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) {
9358 DKind = NND->getDirectiveKind();
9364 case OMPD_target_teams:
9368 case OMPD_target_parallel:
9369 case OMPD_target_simd:
9370 case OMPD_target_parallel_for:
9371 case OMPD_target_parallel_for_simd:
9373 case OMPD_target_teams_distribute:
9374 case OMPD_target_teams_distribute_simd:
9375 case OMPD_target_teams_distribute_parallel_for:
9376 case OMPD_target_teams_distribute_parallel_for_simd:
9379 case OMPD_parallel_for:
9380 case OMPD_parallel_master:
9381 case OMPD_parallel_sections:
9383 case OMPD_parallel_for_simd:
9385 case OMPD_cancellation_point:
9387 case OMPD_threadprivate:
9398 case OMPD_taskyield:
9401 case OMPD_taskgroup:
9407 case OMPD_target_data:
9408 case OMPD_target_exit_data:
9409 case OMPD_target_enter_data:
9410 case OMPD_distribute:
9411 case OMPD_distribute_simd:
9412 case OMPD_distribute_parallel_for:
9413 case OMPD_distribute_parallel_for_simd:
9414 case OMPD_teams_distribute:
9415 case OMPD_teams_distribute_simd:
9416 case OMPD_teams_distribute_parallel_for:
9417 case OMPD_teams_distribute_parallel_for_simd:
9418 case OMPD_target_update:
9419 case OMPD_declare_simd:
9420 case OMPD_declare_variant:
9421 case OMPD_begin_declare_variant:
9422 case OMPD_end_declare_variant:
9423 case OMPD_declare_target:
9424 case OMPD_end_declare_target:
9425 case OMPD_declare_reduction:
9426 case OMPD_declare_mapper:
9428 case OMPD_taskloop_simd:
9429 case OMPD_master_taskloop:
9430 case OMPD_master_taskloop_simd:
9431 case OMPD_parallel_master_taskloop:
9432 case OMPD_parallel_master_taskloop_simd:
9434 case OMPD_metadirective:
9437 llvm_unreachable(
"Unexpected directive.");
9482 auto *MapperVarDecl =
9483 cast<VarDecl>(cast<DeclRefExpr>(
D->getMapperVarRef())->getDecl());
9484 CharUnits ElementSize =
C.getTypeSizeInChars(Ty);
9488 MappableExprsHandler::MapCombinedInfoTy CombinedInfo;
9489 auto PrivatizeAndGenMapInfoCB =
9490 [&](llvm::OpenMPIRBuilder::InsertPointTy CodeGenIP, llvm::Value *PtrPHI,
9491 llvm::Value *BeginArg) -> llvm::OpenMPIRBuilder::MapInfosTy & {
9492 MapperCGF.
Builder.restoreIP(CodeGenIP);
9502 Scope.addPrivate(MapperVarDecl, PtrCurrent);
9503 (void)
Scope.Privatize();
9506 MappableExprsHandler MEHandler(*
D, MapperCGF);
9507 MEHandler.generateAllInfoForMapper(CombinedInfo,
OMPBuilder);
9509 auto FillInfoMap = [&](MappableExprsHandler::MappingExprInfo &MapExpr) {
9513 llvm::codegenoptions::NoDebugInfo) {
9514 CombinedInfo.Names.resize(CombinedInfo.Exprs.size());
9515 llvm::transform(CombinedInfo.Exprs, CombinedInfo.Names.begin(),
9519 return CombinedInfo;
9522 auto CustomMapperCB = [&](
unsigned I) {
9523 llvm::Function *MapperFunc =
nullptr;
9524 if (CombinedInfo.Mappers[I]) {
9527 cast<OMPDeclareMapperDecl>(CombinedInfo.Mappers[I]));
9528 assert(MapperFunc &&
"Expect a valid mapper function is available.");
9534 llvm::raw_svector_ostream Out(TyStr);
9536 std::string Name =
getName({
"omp_mapper", TyStr,
D->getName()});
9538 llvm::Function *NewFn = cantFail(
OMPBuilder.emitUserDefinedMapper(
9539 PrivatizeAndGenMapInfoCB, ElemTy, Name, CustomMapperCB));
9564 Kind != OMPD_target_teams_loop)
9567 return llvm::ConstantInt::get(CGF.
Int64Ty, 0);
9569 const auto *LD = cast<OMPLoopDirective>(TD);
9570 if (llvm::Value *NumIterations = SizeEmitter(CGF, *LD))
9571 return NumIterations;
9572 return llvm::ConstantInt::get(CGF.
Int64Ty, 0);
9581 if (OffloadingMandatory) {
9582 CGF.
Builder.CreateUnreachable();
9584 if (RequiresOuterTask) {
9585 CapturedVars.clear();
9594 llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier>
Device,
9597 llvm::Value *DeviceID;
9598 if (
Device.getPointer()) {
9600 Device.getInt() == OMPC_DEVICE_device_num) &&
9601 "Expected device_num modifier.");
9606 DeviceID = CGF.
Builder.getInt64(OMP_DEVICEID_UNDEF);
9613 llvm::Value *DynCGroupMem = CGF.
Builder.getInt32(0);
9618 DynMemClause->getSize(),
true);
9619 DynCGroupMem = CGF.
Builder.CreateIntCast(DynCGroupMemVal, CGF.
Int32Ty,
9622 return DynCGroupMem;
9627 llvm::OpenMPIRBuilder &OMPBuilder,
9629 MappableExprsHandler::MapCombinedInfoTy &CombinedInfo) {
9631 llvm::DenseMap<llvm::Value *, llvm::Value *> LambdaPointers;
9633 auto *CV = CapturedVars.begin();
9636 CI != CE; ++CI, ++RI, ++CV) {
9637 MappableExprsHandler::MapCombinedInfoTy CurInfo;
9642 CurInfo.Exprs.push_back(
nullptr);
9643 CurInfo.BasePointers.push_back(*CV);
9644 CurInfo.DevicePtrDecls.push_back(
nullptr);
9645 CurInfo.DevicePointers.push_back(
9646 MappableExprsHandler::DeviceInfoTy::None);
9647 CurInfo.Pointers.push_back(*CV);
9648 CurInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
9651 CurInfo.Types.push_back(OpenMPOffloadMappingFlags::OMP_MAP_LITERAL |
9652 OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM |
9653 OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT);
9654 CurInfo.Mappers.push_back(
nullptr);
9658 MEHandler.generateInfoForCaptureFromClauseInfo(
9659 CI, *CV, CurInfo, OMPBuilder,
9660 CombinedInfo.BasePointers.size());
9665 MappedVarSet.insert(
nullptr);
9667 if (CurInfo.BasePointers.empty())
9668 MEHandler.generateDefaultMapInfo(*CI, **RI, *CV, CurInfo);
9673 MEHandler.generateInfoForLambdaCaptures(CI->
getCapturedVar(), *CV,
9674 CurInfo, LambdaPointers);
9677 assert(!CurInfo.BasePointers.empty() &&
9678 "Non-existing map pointer for capture!");
9679 assert(CurInfo.BasePointers.size() == CurInfo.Pointers.size() &&
9680 CurInfo.BasePointers.size() == CurInfo.Sizes.size() &&
9681 CurInfo.BasePointers.size() == CurInfo.Types.size() &&
9682 CurInfo.BasePointers.size() == CurInfo.Mappers.size() &&
9683 "Inconsistent map information sizes!");
9686 CombinedInfo.append(CurInfo);
9689 MEHandler.adjustMemberOfForLambdaCaptures(
9690 OMPBuilder, LambdaPointers, CombinedInfo.BasePointers,
9691 CombinedInfo.Pointers, CombinedInfo.Types);
9695 MappableExprsHandler::MapCombinedInfoTy &CombinedInfo,
9696 llvm::OpenMPIRBuilder &OMPBuilder,
9703 MEHandler.generateAllInfo(CombinedInfo, OMPBuilder, SkippedVarSet);
9705 auto FillInfoMap = [&](MappableExprsHandler::MappingExprInfo &MapExpr) {
9709 llvm::codegenoptions::NoDebugInfo) {
9710 CombinedInfo.Names.resize(CombinedInfo.Exprs.size());
9711 llvm::transform(CombinedInfo.Exprs, CombinedInfo.Names.begin(),
9719 llvm::OpenMPIRBuilder &OMPBuilder,
9720 MappableExprsHandler::MapCombinedInfoTy &CombinedInfo) {
9722 MappableExprsHandler MEHandler(
D, CGF);
9723 llvm::DenseSet<CanonicalDeclPtr<const Decl>> MappedVarSet;
9726 MappedVarSet, CombinedInfo);
9727 genMapInfo(MEHandler, CGF, CombinedInfo, OMPBuilder, MappedVarSet);
9730template <
typename ClauseTy>
9735 const auto *
C =
D.getSingleClause<ClauseTy>();
9736 assert(!
C->varlist_empty() &&
9737 "ompx_bare requires explicit num_teams and thread_limit");
9739 for (
auto *
E :
C->varlist()) {
9751 llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier>
Device,
9753 llvm::Value *&MapTypesArray, llvm::Value *&MapNamesArray,
9758 llvm::OpenMPIRBuilder &OMPBuilder = OMPRuntime->
getOMPBuilder();
9761 MappableExprsHandler::MapCombinedInfoTy CombinedInfo;
9763 genMapInfo(
D, CGF, CS, CapturedVars, OMPBuilder, CombinedInfo);
9777 MapTypesArray = Info.RTArgs.MapTypesArray;
9778 MapNamesArray = Info.RTArgs.MapNamesArray;
9780 auto &&ThenGen = [&OMPRuntime, OutlinedFn, &
D, &CapturedVars,
9781 RequiresOuterTask, &CS, OffloadingMandatory,
Device,
9782 OutlinedFnID, &InputInfo, &MapTypesArray, &MapNamesArray,
9784 bool IsReverseOffloading =
Device.getInt() == OMPC_DEVICE_ancestor;
9786 if (IsReverseOffloading) {
9792 RequiresOuterTask, CS, OffloadingMandatory, CGF);
9797 unsigned NumTargetItems = InputInfo.NumberOfTargetItems;
9799 llvm::Value *BasePointersArray =
9800 InputInfo.BasePointersArray.emitRawPointer(CGF);
9801 llvm::Value *PointersArray = InputInfo.PointersArray.emitRawPointer(CGF);
9802 llvm::Value *SizesArray = InputInfo.SizesArray.emitRawPointer(CGF);
9803 llvm::Value *MappersArray = InputInfo.MappersArray.emitRawPointer(CGF);
9805 auto &&EmitTargetCallFallbackCB =
9806 [&OMPRuntime, OutlinedFn, &
D, &CapturedVars, RequiresOuterTask, &CS,
9807 OffloadingMandatory, &CGF](llvm::OpenMPIRBuilder::InsertPointTy IP)
9808 -> llvm::OpenMPIRBuilder::InsertPointTy {
9811 RequiresOuterTask, CS, OffloadingMandatory, CGF);
9819 emitClauseForBareTargetDirective<OMPNumTeamsClause>(CGF,
D, NumTeams);
9820 emitClauseForBareTargetDirective<OMPThreadLimitClause>(CGF,
D,
9824 NumThreads.push_back(
9830 llvm::Value *NumIterations =
9833 llvm::OpenMPIRBuilder::InsertPointTy AllocaIP(
9836 llvm::OpenMPIRBuilder::TargetDataRTArgs RTArgs(
9837 BasePointersArray, PointersArray, SizesArray, MapTypesArray,
9838 nullptr , MappersArray, MapNamesArray);
9840 llvm::OpenMPIRBuilder::TargetKernelArgs Args(
9841 NumTargetItems, RTArgs, NumIterations, NumTeams, NumThreads,
9842 DynCGGroupMem, HasNoWait);
9844 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
9846 CGF.
Builder, OutlinedFnID, EmitTargetCallFallbackCB, Args, DeviceID,
9848 CGF.
Builder.restoreIP(AfterIP);
9851 if (RequiresOuterTask)
9866 [&OMPRuntime, OutlinedFn, &
D, &CapturedVars, RequiresOuterTask, &CS,
9869 RequiresOuterTask, CS, OffloadingMandatory, CGF);
9872 if (RequiresOuterTask) {
9882 llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID,
const Expr *IfCond,
9883 llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier>
Device,
9890 const bool OffloadingMandatory = !
CGM.
getLangOpts().OpenMPIsTargetDevice &&
9893 assert((OffloadingMandatory || OutlinedFn) &&
"Invalid outlined function!");
9895 const bool RequiresOuterTask =
9911 llvm::Value *MapTypesArray =
nullptr;
9912 llvm::Value *MapNamesArray =
nullptr;
9914 auto &&TargetThenGen = [
this, OutlinedFn, &
D, &CapturedVars,
9915 RequiresOuterTask, &CS, OffloadingMandatory,
Device,
9916 OutlinedFnID, &InputInfo, &MapTypesArray,
9920 RequiresOuterTask, CS, OffloadingMandatory,
9921 Device, OutlinedFnID, InputInfo, MapTypesArray,
9922 MapNamesArray, SizeEmitter, CGF,
CGM);
9925 auto &&TargetElseGen =
9926 [
this, OutlinedFn, &
D, &CapturedVars, RequiresOuterTask, &CS,
9929 CS, OffloadingMandatory, CGF);
9938 emitIfClause(CGF, IfCond, TargetThenGen, TargetElseGen);
9950 StringRef ParentName) {
9955 bool RequiresDeviceCodegen =
9956 isa<OMPExecutableDirective>(S) &&
9958 cast<OMPExecutableDirective>(S)->getDirectiveKind());
9960 if (RequiresDeviceCodegen) {
9961 const auto &
E = *cast<OMPExecutableDirective>(S);
9968 if (!
OMPBuilder.OffloadInfoManager.hasTargetRegionEntryInfo(EntryInfo))
9971 switch (
E.getDirectiveKind()) {
9974 cast<OMPTargetDirective>(
E));
9976 case OMPD_target_parallel:
9978 CGM, ParentName, cast<OMPTargetParallelDirective>(
E));
9980 case OMPD_target_teams:
9982 CGM, ParentName, cast<OMPTargetTeamsDirective>(
E));
9984 case OMPD_target_teams_distribute:
9986 CGM, ParentName, cast<OMPTargetTeamsDistributeDirective>(
E));
9988 case OMPD_target_teams_distribute_simd:
9990 CGM, ParentName, cast<OMPTargetTeamsDistributeSimdDirective>(
E));
9992 case OMPD_target_parallel_for:
9994 CGM, ParentName, cast<OMPTargetParallelForDirective>(
E));
9996 case OMPD_target_parallel_for_simd:
9998 CGM, ParentName, cast<OMPTargetParallelForSimdDirective>(
E));
10000 case OMPD_target_simd:
10002 CGM, ParentName, cast<OMPTargetSimdDirective>(
E));
10004 case OMPD_target_teams_distribute_parallel_for:
10007 cast<OMPTargetTeamsDistributeParallelForDirective>(
E));
10009 case OMPD_target_teams_distribute_parallel_for_simd:
10013 cast<OMPTargetTeamsDistributeParallelForSimdDirective>(
E));
10015 case OMPD_target_teams_loop:
10017 CGM, ParentName, cast<OMPTargetTeamsGenericLoopDirective>(
E));
10019 case OMPD_target_parallel_loop:
10021 CGM, ParentName, cast<OMPTargetParallelGenericLoopDirective>(
E));
10023 case OMPD_parallel:
10025 case OMPD_parallel_for:
10026 case OMPD_parallel_master:
10027 case OMPD_parallel_sections:
10028 case OMPD_for_simd:
10029 case OMPD_parallel_for_simd:
10031 case OMPD_cancellation_point:
10033 case OMPD_threadprivate:
10034 case OMPD_allocate:
10039 case OMPD_sections:
10043 case OMPD_critical:
10044 case OMPD_taskyield:
10046 case OMPD_taskwait:
10047 case OMPD_taskgroup:
10053 case OMPD_target_data:
10054 case OMPD_target_exit_data:
10055 case OMPD_target_enter_data:
10056 case OMPD_distribute:
10057 case OMPD_distribute_simd:
10058 case OMPD_distribute_parallel_for:
10059 case OMPD_distribute_parallel_for_simd:
10060 case OMPD_teams_distribute:
10061 case OMPD_teams_distribute_simd:
10062 case OMPD_teams_distribute_parallel_for:
10063 case OMPD_teams_distribute_parallel_for_simd:
10064 case OMPD_target_update:
10065 case OMPD_declare_simd:
10066 case OMPD_declare_variant:
10067 case OMPD_begin_declare_variant:
10068 case OMPD_end_declare_variant:
10069 case OMPD_declare_target:
10070 case OMPD_end_declare_target:
10071 case OMPD_declare_reduction:
10072 case OMPD_declare_mapper:
10073 case OMPD_taskloop:
10074 case OMPD_taskloop_simd:
10075 case OMPD_master_taskloop:
10076 case OMPD_master_taskloop_simd:
10077 case OMPD_parallel_master_taskloop:
10078 case OMPD_parallel_master_taskloop_simd:
10079 case OMPD_requires:
10080 case OMPD_metadirective:
10083 llvm_unreachable(
"Unknown target directive for OpenMP device codegen.");
10088 if (
const auto *
E = dyn_cast<OMPExecutableDirective>(S)) {
10089 if (!
E->hasAssociatedStmt() || !
E->getAssociatedStmt())
10097 if (
const auto *L = dyn_cast<LambdaExpr>(S))
10101 for (
const Stmt *II : S->children())
10106 std::optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
10107 OMPDeclareTargetDeclAttr::getDeviceType(VD);
10111 if (!IsDevice && DevTy == OMPDeclareTargetDeclAttr::DT_NoHost)
10114 if (IsDevice && DevTy == OMPDeclareTargetDeclAttr::DT_Host)
10123 if (
const auto *FD = dyn_cast<FunctionDecl>(GD.
getDecl()))
10132 if (
const auto *FD = dyn_cast<FunctionDecl>(VD)) {
10141 return !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD) &&
10159 StringRef ParentName =
10164 StringRef ParentName =
10171 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
10172 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(
10173 cast<VarDecl>(GD.
getDecl()));
10174 if (!Res || *Res == OMPDeclareTargetDeclAttr::MT_Link ||
10175 ((*Res == OMPDeclareTargetDeclAttr::MT_To ||
10176 *Res == OMPDeclareTargetDeclAttr::MT_Enter) &&
10185 llvm::Constant *
Addr) {
10190 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
10191 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
10195 if (Res && *Res != OMPDeclareTargetDeclAttr::MT_Link &&
10210 auto LinkageForVariable = [&VD,
this]() {
10214 std::vector<llvm::GlobalVariable *> GeneratedRefs;
10227 for (
auto *ref : GeneratedRefs)
10232 if (isa<FunctionDecl>(GD.
getDecl()) ||
10233 isa<OMPDeclareReductionDecl>(GD.
getDecl()))
10241 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
10242 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
10245 if ((*Res == OMPDeclareTargetDeclAttr::MT_To ||
10246 *Res == OMPDeclareTargetDeclAttr::MT_Enter) &&
10250 assert((*Res == OMPDeclareTargetDeclAttr::MT_Link ||
10251 ((*Res == OMPDeclareTargetDeclAttr::MT_To ||
10252 *Res == OMPDeclareTargetDeclAttr::MT_Enter) &&
10254 "Expected link clause or to clause with unified memory.");
10263 " Expected target-based directive.");
10267 for (
const OMPClause *Clause :
D->clauselists()) {
10268 if (Clause->getClauseKind() == OMPC_unified_shared_memory) {
10270 OMPBuilder.Config.setHasRequiresUnifiedSharedMemory(
true);
10271 }
else if (
const auto *AC =
10272 dyn_cast<OMPAtomicDefaultMemOrderClause>(Clause)) {
10273 switch (AC->getAtomicDefaultMemOrderKind()) {
10274 case OMPC_ATOMIC_DEFAULT_MEM_ORDER_acq_rel:
10277 case OMPC_ATOMIC_DEFAULT_MEM_ORDER_seq_cst:
10280 case OMPC_ATOMIC_DEFAULT_MEM_ORDER_relaxed:
10296 if (!VD || !VD->
hasAttr<OMPAllocateDeclAttr>())
10298 const auto *A = VD->
getAttr<OMPAllocateDeclAttr>();
10299 switch(A->getAllocatorType()) {
10300 case OMPAllocateDeclAttr::OMPNullMemAlloc:
10301 case OMPAllocateDeclAttr::OMPDefaultMemAlloc:
10303 case OMPAllocateDeclAttr::OMPLargeCapMemAlloc:
10304 case OMPAllocateDeclAttr::OMPCGroupMemAlloc:
10305 case OMPAllocateDeclAttr::OMPHighBWMemAlloc:
10306 case OMPAllocateDeclAttr::OMPLowLatMemAlloc:
10307 case OMPAllocateDeclAttr::OMPThreadMemAlloc:
10308 case OMPAllocateDeclAttr::OMPConstMemAlloc:
10309 case OMPAllocateDeclAttr::OMPPTeamMemAlloc:
10312 case OMPAllocateDeclAttr::OMPUserDefinedMemAlloc:
10313 llvm_unreachable(
"Expected predefined allocator for the variables with the "
10314 "static storage.");
10341 const auto *
D = cast<FunctionDecl>(GD.
getDecl());
10344 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(
D)) {
10346 if (
auto *F = dyn_cast_or_null<llvm::Function>(
10348 return !F->isDeclaration();
10360 llvm::Function *OutlinedFn,
10369 llvm::Value *Args[] = {
10371 CGF.
Builder.getInt32(CapturedVars.size()),
10374 RealArgs.append(std::begin(Args), std::end(Args));
10375 RealArgs.append(CapturedVars.begin(), CapturedVars.end());
10377 llvm::FunctionCallee RTLFn =
OMPBuilder.getOrCreateRuntimeFunction(
10383 const Expr *NumTeams,
10384 const Expr *ThreadLimit,
10391 llvm::Value *NumTeamsVal =
10397 llvm::Value *ThreadLimitVal =
10404 llvm::Value *PushNumTeamsArgs[] = {RTLoc,
getThreadID(CGF,
Loc), NumTeamsVal,
10412 const Expr *ThreadLimit,
10415 llvm::Value *ThreadLimitVal =
10440 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
10442 llvm::Value *IfCondVal =
nullptr;
10447 llvm::Value *DeviceID =
nullptr;
10452 DeviceID = CGF.
Builder.getInt64(OMP_DEVICEID_UNDEF);
10456 MappableExprsHandler::MapCombinedInfoTy CombinedInfo;
10457 auto GenMapInfoCB =
10458 [&](InsertPointTy CodeGenIP) -> llvm::OpenMPIRBuilder::MapInfosTy & {
10459 CGF.
Builder.restoreIP(CodeGenIP);
10461 MappableExprsHandler MEHandler(
D, CGF);
10462 MEHandler.generateAllInfo(CombinedInfo,
OMPBuilder);
10464 auto FillInfoMap = [&](MappableExprsHandler::MappingExprInfo &MapExpr) {
10468 llvm::codegenoptions::NoDebugInfo) {
10469 CombinedInfo.Names.resize(CombinedInfo.Exprs.size());
10470 llvm::transform(CombinedInfo.Exprs, CombinedInfo.Names.begin(),
10474 return CombinedInfo;
10476 using BodyGenTy = llvm::OpenMPIRBuilder::BodyGenTy;
10477 auto BodyCB = [&](InsertPointTy CodeGenIP, BodyGenTy BodyGenType) {
10478 CGF.
Builder.restoreIP(CodeGenIP);
10479 switch (BodyGenType) {
10480 case BodyGenTy::Priv:
10484 case BodyGenTy::DupNoPriv:
10490 case BodyGenTy::NoPriv:
10497 return InsertPointTy(CGF.
Builder.GetInsertBlock(),
10498 CGF.
Builder.GetInsertPoint());
10501 auto DeviceAddrCB = [&](
unsigned int I, llvm::Value *NewDecl) {
10502 if (
const ValueDecl *DevVD = CombinedInfo.DevicePtrDecls[I]) {
10507 auto CustomMapperCB = [&](
unsigned int I) {
10508 llvm::Function *MFunc =
nullptr;
10509 if (CombinedInfo.Mappers[I]) {
10510 Info.HasMapper =
true;
10512 cast<OMPDeclareMapperDecl>(CombinedInfo.Mappers[I]));
10522 InsertPointTy CodeGenIP(CGF.
Builder.GetInsertBlock(),
10523 CGF.
Builder.GetInsertPoint());
10524 llvm::OpenMPIRBuilder::LocationDescription OmpLoc(CodeGenIP);
10525 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
10527 OmpLoc, AllocaIP, CodeGenIP, DeviceID, IfCondVal, Info, GenMapInfoCB,
10529 nullptr, BodyCB, DeviceAddrCB, RTLoc));
10530 CGF.
Builder.restoreIP(AfterIP);
10539 assert((isa<OMPTargetEnterDataDirective>(
D) ||
10540 isa<OMPTargetExitDataDirective>(
D) ||
10541 isa<OMPTargetUpdateDirective>(
D)) &&
10542 "Expecting either target enter, exit data, or update directives.");
10545 llvm::Value *MapTypesArray =
nullptr;
10546 llvm::Value *MapNamesArray =
nullptr;
10548 auto &&ThenGen = [
this, &
D,
Device, &InputInfo, &MapTypesArray,
10551 llvm::Value *DeviceID =
nullptr;
10556 DeviceID = CGF.
Builder.getInt64(OMP_DEVICEID_UNDEF);
10560 llvm::Constant *PointerNum =
10567 {RTLoc, DeviceID, PointerNum,
10576 RuntimeFunction RTLFn;
10577 switch (
D.getDirectiveKind()) {
10578 case OMPD_target_enter_data:
10579 RTLFn = HasNowait ? OMPRTL___tgt_target_data_begin_nowait_mapper
10580 : OMPRTL___tgt_target_data_begin_mapper;
10582 case OMPD_target_exit_data:
10583 RTLFn = HasNowait ? OMPRTL___tgt_target_data_end_nowait_mapper
10584 : OMPRTL___tgt_target_data_end_mapper;
10586 case OMPD_target_update:
10587 RTLFn = HasNowait ? OMPRTL___tgt_target_data_update_nowait_mapper
10588 : OMPRTL___tgt_target_data_update_mapper;
10590 case OMPD_parallel:
10592 case OMPD_parallel_for:
10593 case OMPD_parallel_master:
10594 case OMPD_parallel_sections:
10595 case OMPD_for_simd:
10596 case OMPD_parallel_for_simd:
10598 case OMPD_cancellation_point:
10600 case OMPD_threadprivate:
10601 case OMPD_allocate:
10606 case OMPD_sections:
10610 case OMPD_critical:
10611 case OMPD_taskyield:
10613 case OMPD_taskwait:
10614 case OMPD_taskgroup:
10620 case OMPD_target_data:
10621 case OMPD_distribute:
10622 case OMPD_distribute_simd:
10623 case OMPD_distribute_parallel_for:
10624 case OMPD_distribute_parallel_for_simd:
10625 case OMPD_teams_distribute:
10626 case OMPD_teams_distribute_simd:
10627 case OMPD_teams_distribute_parallel_for:
10628 case OMPD_teams_distribute_parallel_for_simd:
10629 case OMPD_declare_simd:
10630 case OMPD_declare_variant:
10631 case OMPD_begin_declare_variant:
10632 case OMPD_end_declare_variant:
10633 case OMPD_declare_target:
10634 case OMPD_end_declare_target:
10635 case OMPD_declare_reduction:
10636 case OMPD_declare_mapper:
10637 case OMPD_taskloop:
10638 case OMPD_taskloop_simd:
10639 case OMPD_master_taskloop:
10640 case OMPD_master_taskloop_simd:
10641 case OMPD_parallel_master_taskloop:
10642 case OMPD_parallel_master_taskloop_simd:
10644 case OMPD_target_simd:
10645 case OMPD_target_teams_distribute:
10646 case OMPD_target_teams_distribute_simd:
10647 case OMPD_target_teams_distribute_parallel_for:
10648 case OMPD_target_teams_distribute_parallel_for_simd:
10649 case OMPD_target_teams:
10650 case OMPD_target_parallel:
10651 case OMPD_target_parallel_for:
10652 case OMPD_target_parallel_for_simd:
10653 case OMPD_requires:
10654 case OMPD_metadirective:
10657 llvm_unreachable(
"Unexpected standalone target data directive.");
10661 OffloadingArgs.push_back(llvm::Constant::getNullValue(CGF.
Int32Ty));
10662 OffloadingArgs.push_back(llvm::Constant::getNullValue(CGF.
VoidPtrTy));
10663 OffloadingArgs.push_back(llvm::Constant::getNullValue(CGF.
Int32Ty));
10664 OffloadingArgs.push_back(llvm::Constant::getNullValue(CGF.
VoidPtrTy));
10671 auto &&TargetThenGen = [
this, &ThenGen, &
D, &InputInfo, &MapTypesArray,
10675 MappableExprsHandler::MapCombinedInfoTy CombinedInfo;
10677 MappableExprsHandler MEHandler(
D, CGF);
10694 MapTypesArray = Info.RTArgs.MapTypesArray;
10695 MapNamesArray = Info.RTArgs.MapNamesArray;
10696 if (RequiresOuterTask)
10722struct ParamAttrTy {
10724 llvm::APSInt StrideOrArg;
10725 llvm::APSInt Alignment;
10726 bool HasVarStride =
false;
10759 unsigned Offset = 0;
10760 if (
const auto *MD = dyn_cast<CXXMethodDecl>(FD)) {
10761 if (ParamAttrs[Offset].Kind ==
Vector)
10762 CDT =
C.getPointerType(
C.getCanonicalTagType(MD->
getParent()));
10767 if (ParamAttrs[I + Offset].Kind ==
Vector) {
10779 return C.getTypeSize(CDT);
10787 llvm::raw_svector_ostream Out(Buffer);
10788 for (
const auto &ParamAttr : ParamAttrs) {
10789 switch (ParamAttr.Kind) {
10809 if (ParamAttr.HasVarStride)
10810 Out <<
"s" << ParamAttr.StrideOrArg;
10811 else if (ParamAttr.Kind == Linear || ParamAttr.Kind == LinearRef ||
10812 ParamAttr.Kind == LinearUVal || ParamAttr.Kind == LinearVal) {
10815 if (ParamAttr.StrideOrArg < 0)
10816 Out <<
'n' << -ParamAttr.StrideOrArg;
10817 else if (ParamAttr.StrideOrArg != 1)
10818 Out << ParamAttr.StrideOrArg;
10821 if (!!ParamAttr.Alignment)
10822 Out <<
'a' << ParamAttr.Alignment;
10825 return std::string(Out.str());
10830 const llvm::APSInt &VLENVal,
10832 OMPDeclareSimdDeclAttr::BranchStateTy State) {
10835 unsigned VecRegSize;
10837 ISADataTy ISAData[] = {
10853 case OMPDeclareSimdDeclAttr::BS_Undefined:
10854 Masked.push_back(
'N');
10855 Masked.push_back(
'M');
10857 case OMPDeclareSimdDeclAttr::BS_Notinbranch:
10858 Masked.push_back(
'N');
10860 case OMPDeclareSimdDeclAttr::BS_Inbranch:
10861 Masked.push_back(
'M');
10864 for (
char Mask : Masked) {
10865 for (
const ISADataTy &
Data : ISAData) {
10867 llvm::raw_svector_ostream Out(Buffer);
10868 Out <<
"_ZGV" <<
Data.ISA << Mask;
10871 assert(NumElts &&
"Non-zero simdlen/cdtsize expected");
10872 Out << llvm::APSInt::getUnsigned(
Data.VecRegSize / NumElts);
10877 Out <<
'_' << Fn->getName();
10878 Fn->addFnAttr(Out.str());
10896 if (Kind == ParamKindTy::Uniform)
10899 if (Kind == ParamKindTy::LinearUVal || Kind == ParamKindTy::LinearRef)
10902 if ((Kind == ParamKindTy::Linear || Kind == ParamKindTy::LinearVal) &&
10912 unsigned Size =
C.getTypeSize(QT);
10915 if (Size != 8 && Size != 16 && Size != 32 && Size != 64 && Size != 128)
10939 return C.getTypeSize(PTy);
10942 return C.getTypeSize(QT);
10944 return C.getTypeSize(
C.getUIntPtrType());
10950static std::tuple<unsigned, unsigned, bool>
10956 bool OutputBecomesInput =
false;
10960 Sizes.push_back(
getAArch64LS(RetType, ParamKindTy::Vector,
C));
10962 OutputBecomesInput =
true;
10969 assert(!Sizes.empty() &&
"Unable to determine NDS and WDS.");
10972 assert(llvm::all_of(Sizes,
10973 [](
unsigned Size) {
10974 return Size == 8 || Size == 16 || Size == 32 ||
10975 Size == 64 || Size == 128;
10979 return std::make_tuple(*llvm::min_element(Sizes), *llvm::max_element(Sizes),
10980 OutputBecomesInput);
10986template <
typename T>
10988 char ISA, StringRef ParSeq,
10989 StringRef MangledName,
bool OutputBecomesInput,
10990 llvm::Function *Fn) {
10992 llvm::raw_svector_ostream Out(Buffer);
10993 Out << Prefix << ISA << LMask << VLEN;
10994 if (OutputBecomesInput)
10996 Out << ParSeq <<
"_" << MangledName;
10997 Fn->addFnAttr(Out.str());
11003 StringRef Prefix,
char ISA,
11004 StringRef ParSeq, StringRef MangledName,
11005 bool OutputBecomesInput,
11006 llvm::Function *Fn) {
11010 OutputBecomesInput, Fn);
11012 OutputBecomesInput, Fn);
11016 OutputBecomesInput, Fn);
11018 OutputBecomesInput, Fn);
11022 OutputBecomesInput, Fn);
11024 OutputBecomesInput, Fn);
11029 OutputBecomesInput, Fn);
11032 llvm_unreachable(
"Scalar type is too wide.");
11040 OMPDeclareSimdDeclAttr::BranchStateTy State, StringRef MangledName,
11041 char ISA,
unsigned VecRegSize, llvm::Function *Fn,
SourceLocation SLoc) {
11045 const unsigned NDS = std::get<0>(
Data);
11046 const unsigned WDS = std::get<1>(
Data);
11047 const bool OutputBecomesInput = std::get<2>(
Data);
11051 if (UserVLEN == 1) {
11054 "The clause simdlen(1) has no effect when targeting aarch64.");
11061 if (ISA ==
'n' && UserVLEN && !llvm::isPowerOf2_32(UserVLEN)) {
11064 "power of 2 when targeting Advanced SIMD.");
11071 if (ISA ==
's' && UserVLEN != 0) {
11072 if ((UserVLEN * WDS > 2048) || (UserVLEN * WDS % 128 != 0)) {
11075 "lanes in the architectural constraints "
11076 "for SVE (min is 128-bit, max is "
11077 "2048-bit, by steps of 128-bit)");
11085 StringRef Prefix =
"_ZGV";
11091 OutputBecomesInput, Fn);
11093 assert(ISA ==
'n' &&
"Expected ISA either 's' or 'n'.");
11097 case OMPDeclareSimdDeclAttr::BS_Undefined:
11099 OutputBecomesInput, Fn);
11101 OutputBecomesInput, Fn);
11103 case OMPDeclareSimdDeclAttr::BS_Notinbranch:
11105 OutputBecomesInput, Fn);
11107 case OMPDeclareSimdDeclAttr::BS_Inbranch:
11109 OutputBecomesInput, Fn);
11119 OutputBecomesInput, Fn);
11121 assert(ISA ==
'n' &&
"Expected ISA either 's' or 'n'.");
11126 case OMPDeclareSimdDeclAttr::BS_Undefined:
11128 OutputBecomesInput, Fn);
11130 OutputBecomesInput, Fn);
11132 case OMPDeclareSimdDeclAttr::BS_Notinbranch:
11134 OutputBecomesInput, Fn);
11136 case OMPDeclareSimdDeclAttr::BS_Inbranch:
11138 OutputBecomesInput, Fn);
11146 llvm::Function *Fn) {
11151 llvm::DenseMap<const Decl *, unsigned> ParamPositions;
11152 if (isa<CXXMethodDecl>(FD))
11153 ParamPositions.try_emplace(FD, 0);
11154 unsigned ParamPos = ParamPositions.size();
11156 ParamPositions.try_emplace(
P->getCanonicalDecl(), ParamPos);
11162 for (
const Expr *
E :
Attr->uniforms()) {
11165 if (isa<CXXThisExpr>(
E)) {
11166 Pos = ParamPositions[FD];
11168 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(
E)->getDecl())
11169 ->getCanonicalDecl();
11170 auto It = ParamPositions.find(PVD);
11171 assert(It != ParamPositions.end() &&
"Function parameter not found");
11174 ParamAttrs[Pos].Kind = Uniform;
11177 auto *NI =
Attr->alignments_begin();
11178 for (
const Expr *
E :
Attr->aligneds()) {
11182 if (isa<CXXThisExpr>(
E)) {
11183 Pos = ParamPositions[FD];
11186 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(
E)->getDecl())
11187 ->getCanonicalDecl();
11188 auto It = ParamPositions.find(PVD);
11189 assert(It != ParamPositions.end() &&
"Function parameter not found");
11191 ParmTy = PVD->getType();
11193 ParamAttrs[Pos].Alignment =
11195 ? (*NI)->EvaluateKnownConstInt(
C)
11196 : llvm::APSInt::getUnsigned(
11197 C.toCharUnitsFromBits(
C.getOpenMPDefaultSimdAlign(ParmTy))
11202 auto *SI =
Attr->steps_begin();
11203 auto *MI =
Attr->modifiers_begin();
11204 for (
const Expr *
E :
Attr->linears()) {
11207 bool IsReferenceType =
false;
11210 unsigned PtrRescalingFactor = 1;
11211 if (isa<CXXThisExpr>(
E)) {
11212 Pos = ParamPositions[FD];
11213 auto *
P = cast<PointerType>(
E->
getType());
11218 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(
E)->getDecl())
11219 ->getCanonicalDecl();
11220 auto It = ParamPositions.find(PVD);
11221 assert(It != ParamPositions.end() &&
"Function parameter not found");
11223 if (
auto *
P = dyn_cast<PointerType>(PVD->getType()))
11227 else if (PVD->getType()->isReferenceType()) {
11228 IsReferenceType =
true;
11229 PtrRescalingFactor =
11235 ParamAttrTy &ParamAttr = ParamAttrs[Pos];
11236 if (*MI == OMPC_LINEAR_ref)
11237 ParamAttr.Kind = LinearRef;
11238 else if (*MI == OMPC_LINEAR_uval)
11239 ParamAttr.Kind = LinearUVal;
11240 else if (IsReferenceType)
11241 ParamAttr.Kind = LinearVal;
11243 ParamAttr.Kind = Linear;
11245 ParamAttr.StrideOrArg = llvm::APSInt::getUnsigned(1);
11249 if (
const auto *DRE =
11250 cast<DeclRefExpr>((*SI)->IgnoreParenImpCasts())) {
11251 if (
const auto *StridePVD =
11252 dyn_cast<ParmVarDecl>(DRE->getDecl())) {
11253 ParamAttr.HasVarStride =
true;
11254 auto It = ParamPositions.find(StridePVD->getCanonicalDecl());
11255 assert(It != ParamPositions.end() &&
11256 "Function parameter not found");
11257 ParamAttr.StrideOrArg = llvm::APSInt::getUnsigned(It->second);
11261 ParamAttr.StrideOrArg =
Result.Val.getInt();
11267 if (!ParamAttr.HasVarStride &&
11268 (ParamAttr.Kind == Linear || ParamAttr.Kind == LinearRef))
11269 ParamAttr.StrideOrArg = ParamAttr.StrideOrArg * PtrRescalingFactor;
11273 llvm::APSInt VLENVal;
11275 const Expr *VLENExpr =
Attr->getSimdlen();
11280 OMPDeclareSimdDeclAttr::BranchStateTy State =
Attr->getBranchState();
11283 }
else if (
CGM.
getTriple().getArch() == llvm::Triple::aarch64) {
11284 unsigned VLEN = VLENVal.getExtValue();
11285 StringRef MangledName = Fn->getName();
11288 MangledName,
's', 128, Fn, ExprLoc);
11291 MangledName,
'n', 128, Fn, ExprLoc);
11302 static const int DoacrossFinArgs = 2;
11305 llvm::FunctionCallee RTLFn;
11306 llvm::Value *Args[DoacrossFinArgs];
11309 DoacrossCleanupTy(llvm::FunctionCallee RTLFn,
11312 assert(CallArgs.size() == DoacrossFinArgs);
11313 std::copy(CallArgs.begin(), CallArgs.end(), std::begin(Args));
11330 QualType Int64Ty =
C.getIntTypeForBitwidth(64,
true);
11338 RD =
C.buildImplicitRecord(
"kmp_dim");
11348 llvm::APInt Size(32, NumIterations.size());
11354 enum { LowerFD = 0, UpperFD, StrideFD };
11356 for (
unsigned I = 0,
E = NumIterations.size(); I <
E; ++I) {
11361 DimsLVal, *std::next(RD->
field_begin(), UpperFD));
11363 CGF.
EmitScalarExpr(NumIterations[I]), NumIterations[I]->getType(),
11364 Int64Ty, NumIterations[I]->getExprLoc());
11368 DimsLVal, *std::next(RD->
field_begin(), StrideFD));
11375 llvm::Value *Args[] = {
11378 llvm::ConstantInt::getSigned(
CGM.
Int32Ty, NumIterations.size()),
11383 llvm::FunctionCallee RTLFn =
OMPBuilder.getOrCreateRuntimeFunction(
11386 llvm::Value *FiniArgs[DoacrossCleanupTy::DoacrossFinArgs] = {
11388 llvm::FunctionCallee FiniRTLFn =
OMPBuilder.getOrCreateRuntimeFunction(
11394template <
typename T>
11396 const T *
C, llvm::Value *ULoc,
11397 llvm::Value *ThreadID) {
11400 llvm::APInt Size(32,
C->getNumLoops());
11404 for (
unsigned I = 0,
E =
C->getNumLoops(); I <
E; ++I) {
11405 const Expr *CounterVal =
C->getLoopData(I);
11406 assert(CounterVal);
11413 llvm::Value *Args[] = {
11416 llvm::FunctionCallee RTLFn;
11418 OMPDoacrossKind<T> ODK;
11419 if (ODK.isSource(
C)) {
11421 OMPRTL___kmpc_doacross_post);
11423 assert(ODK.isSink(
C) &&
"Expect sink modifier.");
11425 OMPRTL___kmpc_doacross_wait);
11432 return EmitDoacrossOrdered<OMPDependClause>(
11439 return EmitDoacrossOrdered<OMPDoacrossClause>(
11445 llvm::FunctionCallee Callee,
11447 assert(
Loc.
isValid() &&
"Outlined function call location must be valid.");
11450 if (
auto *Fn = dyn_cast<llvm::Function>(Callee.getCallee())) {
11451 if (Fn->doesNotThrow()) {
11466 if (
const auto *FD = dyn_cast<FunctionDecl>(
D))
11467 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(FD))
11473 const VarDecl *TargetParam)
const {
11480 const Expr *Allocator) {
11481 llvm::Value *AllocVal;
11488 Allocator->getExprLoc());
11491 AllocVal = llvm::Constant::getNullValue(
11501 if (!AllocateAlignment)
11504 return llvm::ConstantInt::get(
CGM.
SizeTy, AllocateAlignment->getQuantity());
11517 auto I = UntiedData.find(VD);
11518 if (I != UntiedData.end()) {
11519 UntiedAddr = I->second.first;
11520 UntiedRealAddr = I->second.second;
11524 if (CVD->
hasAttr<OMPAllocateDeclAttr>()) {
11533 Size = CGF.
Builder.CreateNUWAdd(
11542 const auto *AA = CVD->
getAttr<OMPAllocateDeclAttr>();
11543 const Expr *Allocator = AA->getAllocator();
11547 Args.push_back(ThreadID);
11549 Args.push_back(Alignment);
11550 Args.push_back(Size);
11551 Args.push_back(AllocVal);
11552 llvm::omp::RuntimeFunction FnID =
11553 Alignment ? OMPRTL___kmpc_aligned_alloc : OMPRTL___kmpc_alloc;
11557 llvm::FunctionCallee FiniRTLFn =
OMPBuilder.getOrCreateRuntimeFunction(
11567 llvm::FunctionCallee RTLFn;
11570 const Expr *AllocExpr;
11573 OMPAllocateCleanupTy(llvm::FunctionCallee RTLFn,
11575 const Expr *AllocExpr)
11576 : RTLFn(RTLFn), LocEncoding(LocEncoding),
Addr(
Addr),
11577 AllocExpr(AllocExpr) {}
11581 llvm::Value *Args[3];
11587 Args[2] = AllocVal;
11595 CGF.
EHStack.pushCleanup<OMPAllocateCleanupTy>(
11597 VDAddr, Allocator);
11598 if (UntiedRealAddr.
isValid())
11601 Region->emitUntiedSwitch(CGF);
11618 assert(CGM.
getLangOpts().OpenMP &&
"Not in OpenMP mode.");
11624 for (
const Stmt *Ref :
C->private_refs()) {
11625 const auto *SimpleRefExpr = cast<Expr>(Ref)->IgnoreParenImpCasts();
11627 if (
const auto *DRE = dyn_cast<DeclRefExpr>(SimpleRefExpr)) {
11628 VD = DRE->getDecl();
11630 const auto *ME = cast<MemberExpr>(SimpleRefExpr);
11631 assert((ME->isImplicitCXXThis() ||
11632 isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts())) &&
11633 "Expected member of current class.");
11634 VD = ME->getMemberDecl();
11650 std::pair<Address, Address>> &LocalVars)
11651 :
CGM(CGF.
CGM), NeedToPush(!LocalVars.empty()) {
11668 return llvm::any_of(
11673void CGOpenMPRuntime::LastprivateConditionalRAII::tryToDisableInnerAnalysis(
11677 llvm::DenseSet<CanonicalDeclPtr<const Decl>> NeedToCheckForLPCs;
11683 const CapturedStmt *CS = S.getCapturedStmt(CaptureRegions.front());
11691 for (
const Expr *Ref :
C->varlist()) {
11692 if (!Ref->getType()->isScalarType())
11694 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
11697 NeedToCheckForLPCs.insert(DRE->getDecl());
11701 for (
const Expr *Ref :
C->varlist()) {
11702 if (!Ref->getType()->isScalarType())
11704 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
11707 NeedToCheckForLPCs.insert(DRE->getDecl());
11711 for (
const Expr *Ref :
C->varlist()) {
11712 if (!Ref->getType()->isScalarType())
11714 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
11717 NeedToCheckForLPCs.insert(DRE->getDecl());
11721 for (
const Expr *Ref :
C->varlist()) {
11722 if (!Ref->getType()->isScalarType())
11724 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
11727 NeedToCheckForLPCs.insert(DRE->getDecl());
11731 for (
const Expr *Ref :
C->varlist()) {
11732 if (!Ref->getType()->isScalarType())
11734 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
11737 NeedToCheckForLPCs.insert(DRE->getDecl());
11740 for (
const Decl *VD : NeedToCheckForLPCs) {
11741 for (
const LastprivateConditionalData &
Data :
11743 if (
Data.DeclToUniqueName.count(VD) > 0) {
11744 if (!
Data.Disabled)
11745 NeedToAddForLPCsAsDisabled.insert(VD);
11752CGOpenMPRuntime::LastprivateConditionalRAII::LastprivateConditionalRAII(
11755 Action((
CGM.getLangOpts().OpenMP >= 50 &&
11758 return C->getKind() ==
11759 OMPC_LASTPRIVATE_conditional;
11761 ? ActionToDo::PushAsLastprivateConditional
11762 : ActionToDo::DoNotPush) {
11764 if (
CGM.
getLangOpts().OpenMP < 50 || Action == ActionToDo::DoNotPush)
11766 assert(Action == ActionToDo::PushAsLastprivateConditional &&
11767 "Expected a push action.");
11771 if (
C->getKind() != OMPC_LASTPRIVATE_conditional)
11774 for (
const Expr *Ref :
C->varlist()) {
11775 Data.DeclToUniqueName.insert(std::make_pair(
11776 cast<DeclRefExpr>(Ref->IgnoreParenImpCasts())->getDecl(),
11780 Data.IVLVal = IVLVal;
11784CGOpenMPRuntime::LastprivateConditionalRAII::LastprivateConditionalRAII(
11786 :
CGM(CGF.
CGM), Action(ActionToDo::DoNotPush) {
11787 assert(CGM.
getLangOpts().OpenMP &&
"Not in OpenMP mode.");
11790 llvm::DenseSet<CanonicalDeclPtr<const Decl>> NeedToAddForLPCsAsDisabled;
11791 tryToDisableInnerAnalysis(S, NeedToAddForLPCsAsDisabled);
11792 if (!NeedToAddForLPCsAsDisabled.empty()) {
11793 Action = ActionToDo::DisableLastprivateConditional;
11794 LastprivateConditionalData &
Data =
11796 for (
const Decl *VD : NeedToAddForLPCsAsDisabled)
11797 Data.DeclToUniqueName.try_emplace(VD);
11799 Data.Disabled =
true;
11812 if (Action == ActionToDo::DisableLastprivateConditional) {
11814 "Expected list of disabled private vars.");
11817 if (Action == ActionToDo::PushAsLastprivateConditional) {
11820 "Expected list of lastprivate conditional vars.");
11833 auto VI = I->getSecond().find(VD);
11834 if (VI == I->getSecond().end()) {
11835 RecordDecl *RD =
C.buildImplicitRecord(
"lasprivate.conditional");
11840 NewType =
C.getCanonicalTagType(RD);
11843 I->getSecond().try_emplace(VD, NewType, VDField, FiredField, BaseLVal);
11845 NewType = std::get<0>(VI->getSecond());
11846 VDField = std::get<1>(VI->getSecond());
11847 FiredField = std::get<2>(VI->getSecond());
11848 BaseLVal = std::get<3>(VI->getSecond());
11860class LastprivateConditionalRefChecker final
11863 const Expr *FoundE =
nullptr;
11864 const Decl *FoundD =
nullptr;
11865 StringRef UniqueDeclName;
11867 llvm::Function *FoundFn =
nullptr;
11873 llvm::reverse(LPM)) {
11874 auto It =
D.DeclToUniqueName.find(
E->getDecl());
11875 if (It ==
D.DeclToUniqueName.end())
11880 FoundD =
E->getDecl()->getCanonicalDecl();
11881 UniqueDeclName = It->second;
11886 return FoundE ==
E;
11892 llvm::reverse(LPM)) {
11893 auto It =
D.DeclToUniqueName.find(
E->getMemberDecl());
11894 if (It ==
D.DeclToUniqueName.end())
11899 FoundD =
E->getMemberDecl()->getCanonicalDecl();
11900 UniqueDeclName = It->second;
11905 return FoundE ==
E;
11907 bool VisitStmt(
const Stmt *S) {
11908 for (
const Stmt *Child : S->children()) {
11911 if (
const auto *
E = dyn_cast<Expr>(Child))
11919 explicit LastprivateConditionalRefChecker(
11922 std::tuple<const Expr *, const Decl *, StringRef, LValue, llvm::Function *>
11923 getFoundData()
const {
11924 return std::make_tuple(FoundE, FoundD, UniqueDeclName, IVLVal, FoundFn);
11931 StringRef UniqueDeclName,
11937 llvm::Constant *LastIV =
OMPBuilder.getOrCreateInternalVariable(
11938 LLIVTy,
getName({UniqueDeclName,
"iv"}));
11939 cast<llvm::GlobalVariable>(LastIV)->setAlignment(
11946 llvm::GlobalVariable *
Last =
OMPBuilder.getOrCreateInternalVariable(
11948 cast<llvm::GlobalVariable>(
Last)->setAlignment(
11962 auto &&CodeGen = [&LastIVLVal, &IVLVal, IVVal, &LVal, &LastLVal,
11968 llvm::Value *CmpRes;
11970 CmpRes = CGF.
Builder.CreateICmpSLE(LastIVVal, IVVal);
11973 "Loop iteration variable must be integer.");
11974 CmpRes = CGF.
Builder.CreateICmpULE(LastIVVal, IVVal);
11978 CGF.
Builder.CreateCondBr(CmpRes, ThenBB, ExitBB);
11999 "Aggregates are not supported in lastprivate conditional.");
12022 if (!Checker.Visit(LHS))
12024 const Expr *FoundE;
12025 const Decl *FoundD;
12026 StringRef UniqueDeclName;
12028 llvm::Function *FoundFn;
12029 std::tie(FoundE, FoundD, UniqueDeclName, IVLVal, FoundFn) =
12030 Checker.getFoundData();
12031 if (FoundFn != CGF.
CurFn) {
12036 "Lastprivate conditional is not found in outer region.");
12037 QualType StructTy = std::get<0>(It->getSecond());
12038 const FieldDecl* FiredDecl = std::get<2>(It->getSecond());
12049 FiredLVal, llvm::AtomicOrdering::Unordered,
12067 auto It = llvm::find_if(
12069 if (It ==
Range.end() || It->Fn != CGF.
CurFn)
12073 "Lastprivates must be registered already.");
12076 const CapturedStmt *CS =
D.getCapturedStmt(CaptureRegions.back());
12077 for (
const auto &Pair : It->DeclToUniqueName) {
12078 const auto *VD = cast<VarDecl>(Pair.first->getCanonicalDecl());
12081 auto I = LPCI->getSecond().find(Pair.first);
12082 assert(I != LPCI->getSecond().end() &&
12083 "Lastprivate must be rehistered already.");
12085 LValue BaseLVal = std::get<3>(I->getSecond());
12089 llvm::Value *Cmp = CGF.
Builder.CreateIsNotNull(Res);
12093 CGF.
Builder.CreateCondBr(Cmp, ThenBB, DoneBB);
12118 "Unknown lastprivate conditional variable.");
12119 StringRef UniqueName = It->second;
12120 llvm::GlobalVariable *GV =
CGM.
getModule().getNamedGlobal(UniqueName);
12134 llvm_unreachable(
"Not supported in SIMD-only mode");
12141 llvm_unreachable(
"Not supported in SIMD-only mode");
12148 bool Tied,
unsigned &NumberOfParts) {
12149 llvm_unreachable(
"Not supported in SIMD-only mode");
12157 llvm_unreachable(
"Not supported in SIMD-only mode");
12163 const Expr *Hint) {
12164 llvm_unreachable(
"Not supported in SIMD-only mode");
12170 llvm_unreachable(
"Not supported in SIMD-only mode");
12176 const Expr *Filter) {
12177 llvm_unreachable(
"Not supported in SIMD-only mode");
12182 llvm_unreachable(
"Not supported in SIMD-only mode");
12188 llvm_unreachable(
"Not supported in SIMD-only mode");
12196 llvm_unreachable(
"Not supported in SIMD-only mode");
12203 llvm_unreachable(
"Not supported in SIMD-only mode");
12210 bool ForceSimpleCall) {
12211 llvm_unreachable(
"Not supported in SIMD-only mode");
12218 llvm_unreachable(
"Not supported in SIMD-only mode");
12223 llvm_unreachable(
"Not supported in SIMD-only mode");
12229 llvm_unreachable(
"Not supported in SIMD-only mode");
12235 llvm_unreachable(
"Not supported in SIMD-only mode");
12242 llvm_unreachable(
"Not supported in SIMD-only mode");
12248 llvm_unreachable(
"Not supported in SIMD-only mode");
12253 unsigned IVSize,
bool IVSigned,
12256 llvm_unreachable(
"Not supported in SIMD-only mode");
12262 const Expr *Message) {
12263 llvm_unreachable(
"Not supported in SIMD-only mode");
12267 ProcBindKind ProcBind,
12269 llvm_unreachable(
"Not supported in SIMD-only mode");
12276 llvm_unreachable(
"Not supported in SIMD-only mode");
12282 llvm_unreachable(
"Not supported in SIMD-only mode");
12287 llvm_unreachable(
"Not supported in SIMD-only mode");
12293 llvm::AtomicOrdering AO) {
12294 llvm_unreachable(
"Not supported in SIMD-only mode");
12299 llvm::Function *TaskFunction,
12301 const Expr *IfCond,
12303 llvm_unreachable(
"Not supported in SIMD-only mode");
12310 llvm_unreachable(
"Not supported in SIMD-only mode");
12317 assert(Options.SimpleReduction &&
"Only simple reduction is expected.");
12319 ReductionOps, Options);
12325 llvm_unreachable(
"Not supported in SIMD-only mode");
12330 bool IsWorksharingReduction) {
12331 llvm_unreachable(
"Not supported in SIMD-only mode");
12338 llvm_unreachable(
"Not supported in SIMD-only mode");
12343 llvm::Value *ReductionsPtr,
12345 llvm_unreachable(
"Not supported in SIMD-only mode");
12351 llvm_unreachable(
"Not supported in SIMD-only mode");
12357 llvm_unreachable(
"Not supported in SIMD-only mode");
12363 llvm_unreachable(
"Not supported in SIMD-only mode");
12368 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
12370 llvm_unreachable(
"Not supported in SIMD-only mode");
12375 llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID,
const Expr *IfCond,
12376 llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier>
Device,
12380 llvm_unreachable(
"Not supported in SIMD-only mode");
12384 llvm_unreachable(
"Not supported in SIMD-only mode");
12388 llvm_unreachable(
"Not supported in SIMD-only mode");
12398 llvm::Function *OutlinedFn,
12400 llvm_unreachable(
"Not supported in SIMD-only mode");
12404 const Expr *NumTeams,
12405 const Expr *ThreadLimit,
12407 llvm_unreachable(
"Not supported in SIMD-only mode");
12414 llvm_unreachable(
"Not supported in SIMD-only mode");
12420 llvm_unreachable(
"Not supported in SIMD-only mode");
12426 llvm_unreachable(
"Not supported in SIMD-only mode");
12431 llvm_unreachable(
"Not supported in SIMD-only mode");
12436 llvm_unreachable(
"Not supported in SIMD-only mode");
12441 const VarDecl *NativeParam)
const {
12442 llvm_unreachable(
"Not supported in SIMD-only mode");
12448 const VarDecl *TargetParam)
const {
12449 llvm_unreachable(
"Not supported in SIMD-only mode");
static llvm::Value * emitCopyprivateCopyFunction(CodeGenModule &CGM, llvm::Type *ArgsElemType, ArrayRef< const Expr * > CopyprivateVars, ArrayRef< const Expr * > DestExprs, ArrayRef< const Expr * > SrcExprs, ArrayRef< const Expr * > AssignmentOps, SourceLocation Loc)
static StringRef getIdentStringFromSourceLocation(CodeGenFunction &CGF, SourceLocation Loc, SmallString< 128 > &Buffer)
static void emitOffloadingArraysAndArgs(CodeGenFunction &CGF, MappableExprsHandler::MapCombinedInfoTy &CombinedInfo, CGOpenMPRuntime::TargetDataInfo &Info, llvm::OpenMPIRBuilder &OMPBuilder, bool IsNonContiguous=false, bool ForEndCall=false)
Emit the arrays used to pass the captures and map information to the offloading runtime library.
static RecordDecl * createKmpTaskTWithPrivatesRecordDecl(CodeGenModule &CGM, QualType KmpTaskTQTy, ArrayRef< PrivateDataTy > Privates)
static void emitInitWithReductionInitializer(CodeGenFunction &CGF, const OMPDeclareReductionDecl *DRD, const Expr *InitOp, Address Private, Address Original, QualType Ty)
static Address castToBase(CodeGenFunction &CGF, QualType BaseTy, QualType ElTy, Address OriginalBaseAddress, llvm::Value *Addr)
static void emitPrivatesInit(CodeGenFunction &CGF, const OMPExecutableDirective &D, Address KmpTaskSharedsPtr, LValue TDBase, const RecordDecl *KmpTaskTWithPrivatesQTyRD, QualType SharedsTy, QualType SharedsPtrTy, const OMPTaskDataTy &Data, ArrayRef< PrivateDataTy > Privates, bool ForDup)
Emit initialization for private variables in task-based directives.
static void emitClauseForBareTargetDirective(CodeGenFunction &CGF, const OMPExecutableDirective &D, llvm::SmallVectorImpl< llvm::Value * > &Values)
static llvm::Value * emitDestructorsFunction(CodeGenModule &CGM, SourceLocation Loc, QualType KmpInt32Ty, QualType KmpTaskTWithPrivatesPtrQTy, QualType KmpTaskTWithPrivatesQTy)
static unsigned evaluateCDTSize(const FunctionDecl *FD, ArrayRef< ParamAttrTy > ParamAttrs)
static void EmitOMPAggregateReduction(CodeGenFunction &CGF, QualType Type, const VarDecl *LHSVar, const VarDecl *RHSVar, const llvm::function_ref< void(CodeGenFunction &CGF, const Expr *, const Expr *, const Expr *)> &RedOpGen, const Expr *XExpr=nullptr, const Expr *EExpr=nullptr, const Expr *UpExpr=nullptr)
Emit reduction operation for each element of array (required for array sections) LHS op = RHS.
static void emitTargetCallFallback(CGOpenMPRuntime *OMPRuntime, llvm::Function *OutlinedFn, const OMPExecutableDirective &D, llvm::SmallVectorImpl< llvm::Value * > &CapturedVars, bool RequiresOuterTask, const CapturedStmt &CS, bool OffloadingMandatory, CodeGenFunction &CGF)
static llvm::Value * emitReduceInitFunction(CodeGenModule &CGM, SourceLocation Loc, ReductionCodeGen &RCG, unsigned N)
Emits reduction initializer function:
static RTCancelKind getCancellationKind(OpenMPDirectiveKind CancelRegion)
static void emitDependData(CodeGenFunction &CGF, QualType &KmpDependInfoTy, llvm::PointerUnion< unsigned *, LValue * > Pos, const OMPTaskDataTy::DependData &Data, Address DependenciesArray)
static llvm::Value * emitTaskPrivateMappingFunction(CodeGenModule &CGM, SourceLocation Loc, const OMPTaskDataTy &Data, QualType PrivatesQTy, ArrayRef< PrivateDataTy > Privates)
Emit a privates mapping function for correct handling of private and firstprivate variables.
static llvm::Value * emitReduceCombFunction(CodeGenModule &CGM, SourceLocation Loc, ReductionCodeGen &RCG, unsigned N, const Expr *ReductionOp, const Expr *LHS, const Expr *RHS, const Expr *PrivateRef)
Emits reduction combiner function:
static RecordDecl * createPrivatesRecordDecl(CodeGenModule &CGM, ArrayRef< PrivateDataTy > Privates)
static llvm::Value * getAllocatorVal(CodeGenFunction &CGF, const Expr *Allocator)
Return allocator value from expression, or return a null allocator (default when no allocator specifi...
static llvm::Function * emitProxyTaskFunction(CodeGenModule &CGM, SourceLocation Loc, OpenMPDirectiveKind Kind, QualType KmpInt32Ty, QualType KmpTaskTWithPrivatesPtrQTy, QualType KmpTaskTWithPrivatesQTy, QualType KmpTaskTQTy, QualType SharedsPtrTy, llvm::Function *TaskFunction, llvm::Value *TaskPrivatesMap)
Emit a proxy function which accepts kmp_task_t as the second argument.
static void addAArch64VectorName(T VLEN, StringRef LMask, StringRef Prefix, char ISA, StringRef ParSeq, StringRef MangledName, bool OutputBecomesInput, llvm::Function *Fn)
static bool isAllocatableDecl(const VarDecl *VD)
static llvm::Value * getAlignmentValue(CodeGenModule &CGM, const VarDecl *VD)
Return the alignment from an allocate directive if present.
static void emitTargetCallKernelLaunch(CGOpenMPRuntime *OMPRuntime, llvm::Function *OutlinedFn, const OMPExecutableDirective &D, llvm::SmallVectorImpl< llvm::Value * > &CapturedVars, bool RequiresOuterTask, const CapturedStmt &CS, bool OffloadingMandatory, llvm::PointerIntPair< const Expr *, 2, OpenMPDeviceClauseModifier > Device, llvm::Value *OutlinedFnID, CodeGenFunction::OMPTargetDataInfo &InputInfo, llvm::Value *&MapTypesArray, llvm::Value *&MapNamesArray, llvm::function_ref< llvm::Value *(CodeGenFunction &CGF, const OMPLoopDirective &D)> SizeEmitter, CodeGenFunction &CGF, CodeGenModule &CGM)
static llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryKind convertCaptureClause(const VarDecl *VD)
static std::tuple< unsigned, unsigned, bool > getNDSWDS(const FunctionDecl *FD, ArrayRef< ParamAttrTy > ParamAttrs)
static const OMPExecutableDirective * getNestedDistributeDirective(ASTContext &Ctx, const OMPExecutableDirective &D)
Check for inner distribute directive.
static std::pair< llvm::Value *, llvm::Value * > getPointerAndSize(CodeGenFunction &CGF, const Expr *E)
static const VarDecl * getBaseDecl(const Expr *Ref, const DeclRefExpr *&DE)
static bool isTrivial(ASTContext &Ctx, const Expr *E)
Checks if the expression is constant or does not have non-trivial function calls.
static OpenMPSchedType getRuntimeSchedule(OpenMPScheduleClauseKind ScheduleKind, bool Chunked, bool Ordered)
Map the OpenMP loop schedule to the runtime enumeration.
static void getNumThreads(CodeGenFunction &CGF, const CapturedStmt *CS, const Expr **E, int32_t &UpperBound, bool UpperBoundOnly, llvm::Value **CondVal)
Check for a num threads constant value (stored in DefaultVal), or expression (stored in E).
static llvm::Value * emitDeviceID(llvm::PointerIntPair< const Expr *, 2, OpenMPDeviceClauseModifier > Device, CodeGenFunction &CGF)
static const OMPDeclareReductionDecl * getReductionInit(const Expr *ReductionOp)
Check if the combiner is a call to UDR combiner and if it is so return the UDR decl used for reductio...
static bool checkInitIsRequired(CodeGenFunction &CGF, ArrayRef< PrivateDataTy > Privates)
Check if duplication function is required for taskloops.
static bool checkDestructorsRequired(const RecordDecl *KmpTaskTWithPrivatesQTyRD, ArrayRef< PrivateDataTy > Privates)
Checks if destructor function is required to be generated.
static llvm::TargetRegionEntryInfo getEntryInfoFromPresumedLoc(CodeGenModule &CGM, llvm::OpenMPIRBuilder &OMPBuilder, SourceLocation BeginLoc, llvm::StringRef ParentName="")
static void genMapInfo(MappableExprsHandler &MEHandler, CodeGenFunction &CGF, MappableExprsHandler::MapCombinedInfoTy &CombinedInfo, llvm::OpenMPIRBuilder &OMPBuilder, const llvm::DenseSet< CanonicalDeclPtr< const Decl > > &SkippedVarSet=llvm::DenseSet< CanonicalDeclPtr< const Decl > >())
static void emitForStaticInitCall(CodeGenFunction &CGF, llvm::Value *UpdateLocation, llvm::Value *ThreadId, llvm::FunctionCallee ForStaticInitFunction, OpenMPSchedType Schedule, OpenMPScheduleClauseModifier M1, OpenMPScheduleClauseModifier M2, const CGOpenMPRuntime::StaticRTInput &Values)
static LValue loadToBegin(CodeGenFunction &CGF, QualType BaseTy, QualType ElTy, LValue BaseLV)
static void getKmpAffinityType(ASTContext &C, QualType &KmpTaskAffinityInfoTy)
Builds kmp_depend_info, if it is not built yet, and builds flags type.
static llvm::Constant * emitMappingInformation(CodeGenFunction &CGF, llvm::OpenMPIRBuilder &OMPBuilder, MappableExprsHandler::MappingExprInfo &MapExprs)
Emit a string constant containing the names of the values mapped to the offloading runtime library.
static void getDependTypes(ASTContext &C, QualType &KmpDependInfoTy, QualType &FlagsTy)
Builds kmp_depend_info, if it is not built yet, and builds flags type.
static llvm::Value * emitTaskDupFunction(CodeGenModule &CGM, SourceLocation Loc, const OMPExecutableDirective &D, QualType KmpTaskTWithPrivatesPtrQTy, const RecordDecl *KmpTaskTWithPrivatesQTyRD, const RecordDecl *KmpTaskTQTyRD, QualType SharedsTy, QualType SharedsPtrTy, const OMPTaskDataTy &Data, ArrayRef< PrivateDataTy > Privates, bool WithLastIter)
Emit task_dup function (for initialization of private/firstprivate/lastprivate vars and last_iter fla...
static llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseKind convertDeviceClause(const VarDecl *VD)
static llvm::Value * emitReduceFiniFunction(CodeGenModule &CGM, SourceLocation Loc, ReductionCodeGen &RCG, unsigned N)
Emits reduction finalizer function:
static void EmitOMPAggregateInit(CodeGenFunction &CGF, Address DestAddr, QualType Type, bool EmitDeclareReductionInit, const Expr *Init, const OMPDeclareReductionDecl *DRD, Address SrcAddr=Address::invalid())
Emit initialization of arrays of complex types.
static bool getAArch64PBV(QualType QT, ASTContext &C)
Pass By Value (PBV), as defined in 3.1.2 of the AAVFABI.
static unsigned getAArch64LS(QualType QT, ParamKindTy Kind, ASTContext &C)
Computes the lane size (LS) of a return type or of an input parameter, as defined by LS(P) in 3....
static void EmitDoacrossOrdered(CodeGenFunction &CGF, CodeGenModule &CGM, const T *C, llvm::Value *ULoc, llvm::Value *ThreadID)
static RTLDependenceKindTy translateDependencyKind(OpenMPDependClauseKind K)
Translates internal dependency kind into the runtime kind.
static void emitTargetCallElse(CGOpenMPRuntime *OMPRuntime, llvm::Function *OutlinedFn, const OMPExecutableDirective &D, llvm::SmallVectorImpl< llvm::Value * > &CapturedVars, bool RequiresOuterTask, const CapturedStmt &CS, bool OffloadingMandatory, CodeGenFunction &CGF)
static llvm::Function * emitCombinerOrInitializer(CodeGenModule &CGM, QualType Ty, const Expr *CombinerInitializer, const VarDecl *In, const VarDecl *Out, bool IsCombiner)
static void emitX86DeclareSimdFunction(const FunctionDecl *FD, llvm::Function *Fn, const llvm::APSInt &VLENVal, ArrayRef< ParamAttrTy > ParamAttrs, OMPDeclareSimdDeclAttr::BranchStateTy State)
static void emitReductionCombiner(CodeGenFunction &CGF, const Expr *ReductionOp)
Emit reduction combiner.
static std::string mangleVectorParameters(ArrayRef< ParamAttrTy > ParamAttrs)
Mangle the parameter part of the vector function name according to their OpenMP classification.
static std::string generateUniqueName(CodeGenModule &CGM, llvm::StringRef Prefix, const Expr *Ref)
static llvm::Function * emitParallelOrTeamsOutlinedFunction(CodeGenModule &CGM, const OMPExecutableDirective &D, const CapturedStmt *CS, const VarDecl *ThreadIDVar, OpenMPDirectiveKind InnermostKind, const StringRef OutlinedHelperName, const RegionCodeGenTy &CodeGen)
static void emitAArch64DeclareSimdFunction(CodeGenModule &CGM, const FunctionDecl *FD, unsigned UserVLEN, ArrayRef< ParamAttrTy > ParamAttrs, OMPDeclareSimdDeclAttr::BranchStateTy State, StringRef MangledName, char ISA, unsigned VecRegSize, llvm::Function *Fn, SourceLocation SLoc)
Emit vector function attributes for AArch64, as defined in the AAVFABI.
static Address emitAddrOfVarFromArray(CodeGenFunction &CGF, Address Array, unsigned Index, const VarDecl *Var)
Given an array of pointers to variables, project the address of a given variable.
static llvm::Value * emitDynCGGroupMem(const OMPExecutableDirective &D, CodeGenFunction &CGF)
static bool isAssumedToBeNotEmitted(const ValueDecl *VD, bool IsDevice)
static void addAArch64AdvSIMDNDSNames(unsigned NDS, StringRef Mask, StringRef Prefix, char ISA, StringRef ParSeq, StringRef MangledName, bool OutputBecomesInput, llvm::Function *Fn)
static FieldDecl * addFieldToRecordDecl(ASTContext &C, DeclContext *DC, QualType FieldTy)
static ValueDecl * getDeclFromThisExpr(const Expr *E)
static void genMapInfoForCaptures(MappableExprsHandler &MEHandler, CodeGenFunction &CGF, const CapturedStmt &CS, llvm::SmallVectorImpl< llvm::Value * > &CapturedVars, llvm::OpenMPIRBuilder &OMPBuilder, llvm::DenseSet< CanonicalDeclPtr< const Decl > > &MappedVarSet, MappableExprsHandler::MapCombinedInfoTy &CombinedInfo)
static RecordDecl * createKmpTaskTRecordDecl(CodeGenModule &CGM, OpenMPDirectiveKind Kind, QualType KmpInt32Ty, QualType KmpRoutineEntryPointerQTy)
static int addMonoNonMonoModifier(CodeGenModule &CGM, OpenMPSchedType Schedule, OpenMPScheduleClauseModifier M1, OpenMPScheduleClauseModifier M2)
static bool getAArch64MTV(QualType QT, ParamKindTy Kind)
Maps To Vector (MTV), as defined in 4.1.1 of the AAVFABI (2021Q1).
enum clang::sema::@1840::IndirectLocalPathEntry::EntryKind Kind
@ LLVM_MARK_AS_BITMASK_ENUM
This file defines OpenMP AST classes for clauses.
Defines some OpenMP-specific enums and functions.
Defines the SourceManager interface.
This file defines OpenMP AST classes for executable directives and clauses.
__DEVICE__ int max(int __a, int __b)
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,...
bool hasSameType(QualType T1, QualType T2) const
Determine whether the given types T1 and T2 are equivalent.
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.
const VariableArrayType * getAsVariableArrayType(QualType T) const
QualType getSizeType() const
Return the unique type for "size_t" (C99 7.17), defined in <stddef.h>.
const TargetInfo & getTargetInfo() const
unsigned getTypeAlign(QualType T) const
Return the ABI-specified alignment of a (complete) type T, in bits.
ASTRecordLayout - This class contains layout information for one RecordDecl, which is a struct/union/...
CharUnits getSize() const
getSize - Get the record size in characters.
uint64_t getFieldOffset(unsigned FieldNo) const
getFieldOffset - Get the offset of the given field index, in bits.
CharUnits getNonVirtualSize() const
getNonVirtualSize - Get the non-virtual size (in chars) of an object, which is the size of the object...
static QualType getBaseOriginalType(const Expr *Base)
Return original type of the base expression for array section.
Represents an array type, per C99 6.7.5.2 - Array Declarators.
Attr - This represents one attribute.
Represents a C++ constructor within a class.
Represents a C++ destructor within a class.
Represents a static or instance method of a struct/union/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.
capture_iterator capture_end() const
Retrieve an iterator pointing past the end of the sequence of captures.
const RecordDecl * getCapturedRecordDecl() const
Retrieve the record declaration for captured variables.
Stmt * getCapturedStmt()
Retrieve the statement being captured.
bool capturesVariable(const VarDecl *Var) const
True if this variable has been captured.
capture_iterator capture_begin()
Retrieve an iterator pointing to the first capture.
CharUnits - This is an opaque type for sizes expressed in character units.
bool isZero() const
isZero - Test whether the quantity equals zero.
llvm::Align getAsAlign() const
getAsAlign - Returns Quantity as a valid llvm::Align, Beware llvm::Align assumes power of two 8-bit b...
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
CharUnits alignmentOfArrayElement(CharUnits elementSize) const
Given that this is the alignment of the first element of an array, return the minimum alignment of an...
static CharUnits fromQuantity(QuantityType Quantity)
fromQuantity - Construct a CharUnits quantity from a raw integer type.
CharUnits alignTo(const CharUnits &Align) const
alignTo - Returns the next integer (mod 2**64) that is greater than or equal to this quantity and is ...
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.
Address withAlignment(CharUnits NewAlignment) const
Return address with different alignment, but same pointer and element type.
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.
CGBlockInfo - Information to generate a block literal.
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...
MangleContext & getMangleContext()
Gets the mangle context.
CGFunctionInfo - Class to encapsulate the information about a function definition.
DisableAutoDeclareTargetRAII(CodeGenModule &CGM)
~DisableAutoDeclareTargetRAII()
Manages list of lastprivate conditional decls for the specified directive.
~LastprivateConditionalRAII()
static LastprivateConditionalRAII disable(CodeGenFunction &CGF, const OMPExecutableDirective &S)
NontemporalDeclsRAII(CodeGenModule &CGM, const OMPLoopDirective &S)
Struct that keeps all the relevant information that should be kept throughout a 'target data' region.
llvm::DenseMap< const ValueDecl *, llvm::Value * > CaptureDeviceAddrMap
Map between the a declaration of a capture and the corresponding new llvm address where the runtime r...
~UntiedTaskLocalDeclsRAII()
UntiedTaskLocalDeclsRAII(CodeGenFunction &CGF, const llvm::MapVector< CanonicalDeclPtr< const VarDecl >, std::pair< Address, Address > > &LocalVars)
virtual Address emitThreadIDAddress(CodeGenFunction &CGF, SourceLocation Loc)
Emits address of the word in a memory where current thread id is stored.
llvm::StringSet ThreadPrivateWithDefinition
Set of threadprivate variables with the generated initializer.
CGOpenMPRuntime(CodeGenModule &CGM)
virtual void emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc, const OMPExecutableDirective &D, llvm::Function *TaskFunction, QualType SharedsTy, Address Shareds, const Expr *IfCond, const OMPTaskDataTy &Data)
Emit task region for the task directive.
void createOffloadEntriesAndInfoMetadata()
Creates all the offload entries in the current compilation unit along with the associated metadata.
const Expr * getNumTeamsExprForTargetDirective(CodeGenFunction &CGF, const OMPExecutableDirective &D, int32_t &MinTeamsVal, int32_t &MaxTeamsVal)
Emit the number of teams for a target directive.
virtual Address getAddrOfThreadPrivate(CodeGenFunction &CGF, const VarDecl *VD, Address VDAddr, SourceLocation Loc)
Returns address of the threadprivate variable for the current thread.
void emitDeferredTargetDecls() const
Emit deferred declare target variables marked for deferred emission.
virtual llvm::Value * emitForNext(CodeGenFunction &CGF, SourceLocation Loc, unsigned IVSize, bool IVSigned, Address IL, Address LB, Address UB, Address ST)
Call __kmpc_dispatch_next( ident_t *loc, kmp_int32 tid, kmp_int32 *p_lastiter, kmp_int[32|64] *p_lowe...
bool markAsGlobalTarget(GlobalDecl GD)
Marks the declaration as already emitted for the device code and returns true, if it was marked alrea...
virtual void emitParallelCall(CodeGenFunction &CGF, SourceLocation Loc, llvm::Function *OutlinedFn, ArrayRef< llvm::Value * > CapturedVars, const Expr *IfCond, llvm::Value *NumThreads, OpenMPNumThreadsClauseModifier NumThreadsModifier=OMPC_NUMTHREADS_unknown, OpenMPSeverityClauseKind Severity=OMPC_SEVERITY_fatal, const Expr *Message=nullptr)
Emits code for parallel or serial call of the OutlinedFn with variables captured in a record which ad...
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...
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::MapVector< CanonicalDeclPtr< const VarDecl >, std::pair< Address, Address > > UntiedLocalVarsAddressesMap
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 ...
llvm::SmallVector< NontemporalDeclsSet, 4 > NontemporalDeclsStack
Stack for list of declarations in current context marked as nontemporal.
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 void emitTaskgroupRegion(CodeGenFunction &CGF, const RegionCodeGenTy &TaskgroupOpGen, SourceLocation Loc)
Emit a taskgroup region.
virtual llvm::Value * emitMessageClause(CodeGenFunction &CGF, const Expr *Message)
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_int32 global_tid, kmp_int32 num_teams,...
bool hasRequiresUnifiedSharedMemory() const
Return whether the unified_shared_memory has been specified.
virtual Address getAddrOfArtificialThreadPrivate(CodeGenFunction &CGF, QualType VarType, StringRef Name)
Creates artificial threadprivate variable with name Name and type VarType.
void emitUserDefinedMapper(const OMPDeclareMapperDecl *D, CodeGenFunction *CGF=nullptr)
Emit the function for the user defined mapper construct.
bool HasEmittedTargetRegion
Flag for keeping track of weather a target region has been emitted.
void emitDepobjElements(CodeGenFunction &CGF, QualType &KmpDependInfoTy, LValue PosLVal, const OMPTaskDataTy::DependData &Data, Address DependenciesArray)
std::string getReductionFuncName(StringRef Name) const
Get the function name of a reduction function.
virtual void processRequiresDirective(const OMPRequiresDecl *D)
Perform check on requires decl to ensure that target architecture supports unified addressing.
llvm::DenseSet< CanonicalDeclPtr< const Decl > > AlreadyEmittedTargetDecls
List of the emitted declarations.
virtual llvm::Value * emitTaskReductionInit(CodeGenFunction &CGF, SourceLocation Loc, ArrayRef< const Expr * > LHSExprs, ArrayRef< const Expr * > RHSExprs, const OMPTaskDataTy &Data)
Emit a code for initialization of task reduction clause.
llvm::Value * getThreadID(CodeGenFunction &CGF, SourceLocation Loc)
Gets thread id value for the current thread.
void emitUpdateClause(CodeGenFunction &CGF, LValue DepobjLVal, OpenMPDependClauseKind NewDepKind, SourceLocation Loc)
Updates the dependency kind in the specified depobj object.
virtual void emitLastprivateConditionalFinalUpdate(CodeGenFunction &CGF, LValue PrivLVal, const VarDecl *VD, SourceLocation Loc)
Gets the address of the global copy used for lastprivate conditional update, if any.
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_int32 global_tid, int proc_bind) to generat...
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_int32 global_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...
virtual llvm::Value * emitSeverityClause(OpenMPSeverityClauseKind Severity)
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.
virtual void emitNumThreadsClause(CodeGenFunction &CGF, llvm::Value *NumThreads, SourceLocation Loc, OpenMPNumThreadsClauseModifier Modifier=OMPC_NUMTHREADS_unknown, OpenMPSeverityClauseKind Severity=OMPC_SEVERITY_fatal, const Expr *Message=nullptr)
Emits call to void __kmpc_push_num_threads(ident_t *loc, kmp_int32 global_tid, kmp_int32 num_threads)...
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...
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.
llvm::SmallDenseSet< CanonicalDeclPtr< const Decl > > NontemporalDeclsSet
virtual bool isStaticNonchunked(OpenMPScheduleClauseKind ScheduleKind, bool Chunked) const
Check if the specified ScheduleKind is static non-chunked.
llvm::Value * getCriticalRegionLock(StringRef CriticalName)
Returns corresponding lock object for the specified critical region name.
virtual void emitCancelCall(CodeGenFunction &CGF, SourceLocation Loc, const Expr *IfCond, OpenMPDirectiveKind CancelRegion)
Emit code for 'cancel' construct.
QualType SavedKmpTaskTQTy
Saved kmp_task_t for task directive.
virtual void emitMasterRegion(CodeGenFunction &CGF, const RegionCodeGenTy &MasterOpGen, SourceLocation Loc)
Emits a master region.
virtual llvm::Function * emitTaskOutlinedFunction(const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, const VarDecl *PartIDVar, const VarDecl *TaskTVar, OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen, bool Tied, unsigned &NumberOfParts)
Emits outlined function for the OpenMP task directive D.
llvm::DenseMap< llvm::Function *, unsigned > FunctionToUntiedTaskStackMap
Maps function to the position of the untied task locals stack.
void emitDestroyClause(CodeGenFunction &CGF, LValue DepobjLVal, SourceLocation Loc)
Emits the code to destroy the dependency object provided in depobj directive.
virtual void emitTaskReductionFixups(CodeGenFunction &CGF, SourceLocation Loc, ReductionCodeGen &RCG, unsigned N)
Required to resolve existing problems in the runtime.
llvm::ArrayType * KmpCriticalNameTy
Type kmp_critical_name, originally defined as typedef kmp_int32 kmp_critical_name[8];.
virtual void emitDoacrossOrdered(CodeGenFunction &CGF, const OMPDependClause *C)
Emit code for doacross ordered directive with 'depend' clause.
llvm::DenseMap< const OMPDeclareMapperDecl *, llvm::Function * > UDMMap
Map from the user-defined mapper declaration to its corresponding functions.
virtual void checkAndEmitLastprivateConditional(CodeGenFunction &CGF, const Expr *LHS)
Checks if the provided LVal is lastprivate conditional and emits the code to update the value of the ...
std::pair< llvm::Value *, LValue > getDepobjElements(CodeGenFunction &CGF, LValue DepobjLVal, SourceLocation Loc)
Returns the number of the elements and the address of the depobj dependency array.
llvm::SmallDenseSet< const VarDecl * > DeferredGlobalVariables
List of variables that can become declare target implicitly and, thus, must be emitted.
void emitUsesAllocatorsInit(CodeGenFunction &CGF, const Expr *Allocator, const Expr *AllocatorTraits)
Initializes user defined allocators specified in the uses_allocators clauses.
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...
void emitNumThreadsClause(CodeGenFunction &CGF, llvm::Value *NumThreads, SourceLocation Loc, OpenMPNumThreadsClauseModifier Modifier=OMPC_NUMTHREADS_unknown, OpenMPSeverityClauseKind Severity=OMPC_SEVERITY_fatal, const Expr *Message=nullptr) override
Emits call to void __kmpc_push_num_threads(ident_t *loc, kmp_int32 global_tid, kmp_int32 num_threads)...
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_int32 global_tid, int proc_bind) to generat...
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_int32 global_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 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.
CGRecordLayout - This class handles struct and union layout info while lowering AST types to LLVM typ...
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 llvm::Value * getContextValue() const
static bool classof(const CGCapturedStmtInfo *)
virtual void EmitBody(CodeGenFunction &CGF, const Stmt *S)
Emit the captured statement body.
virtual const FieldDecl * lookup(const VarDecl *VD) const
Lookup the captured field decl for a variable.
RAII for correct setting/restoring of CapturedStmtInfo.
The scope used to remap some variables as private in the OpenMP loop body (or other captured region e...
bool Privatize()
Privatizes local variables previously registered as private.
bool addPrivate(const VarDecl *LocalVD, Address Addr)
Registers LocalVD variable as a private with Addr as the address of the corresponding private variabl...
An RAII object to set (and then clear) a mapping for an OpaqueValueExpr.
Enters a new scope for capturing cleanups, all of which will be executed once the scope is exited.
CodeGenFunction - This class organizes the per-function state that is used while generating LLVM code...
llvm::Function * GenerateOpenMPCapturedStmtFunction(const CapturedStmt &S, SourceLocation Loc)
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()
FieldDecl * LambdaThisCaptureField
CGCapturedStmtInfo * CapturedStmtInfo
ComplexPairTy EmitLoadOfComplex(LValue src, SourceLocation loc)
EmitLoadOfComplex - Load a complex number from the specified l-value.
static void EmitOMPTargetDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetDirective &S)
Emit device code for the target directive.
static void EmitOMPTargetTeamsDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsDirective &S)
Emit device code for the target teams directive.
static void EmitOMPTargetTeamsDistributeDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsDistributeDirective &S)
Emit device code for the target teams distribute directive.
llvm::BasicBlock * createBasicBlock(const Twine &name="", llvm::Function *parent=nullptr, llvm::BasicBlock *before=nullptr)
createBasicBlock - Create an LLVM basic block.
const LangOptions & getLangOpts() const
AutoVarEmission EmitAutoVarAlloca(const VarDecl &var)
EmitAutoVarAlloca - Emit the alloca and debug information for a local variable.
void pushDestroy(QualType::DestructionKind dtorKind, Address addr, QualType type)
pushDestroy - Push the standard destructor for the given type as at least a normal cleanup.
const CodeGen::CGBlockInfo * BlockInfo
Address EmitLoadOfPointer(Address Ptr, const PointerType *PtrTy, LValueBaseInfo *BaseInfo=nullptr, TBAAAccessInfo *TBAAInfo=nullptr)
Load a pointer with type PtrTy stored at address Ptr.
void EmitBranchThroughCleanup(JumpDest Dest)
EmitBranchThroughCleanup - Emit a branch from the current insert block through the normal cleanup han...
const Decl * CurCodeDecl
CurCodeDecl - This is the inner-most code context, which includes blocks.
Destroyer * getDestroyer(QualType::DestructionKind destructionKind)
llvm::AssertingVH< llvm::Instruction > AllocaInsertPt
AllocaInsertPoint - This is an instruction in the entry block before which we prefer to insert alloca...
void EmitAggregateAssign(LValue Dest, LValue Src, QualType EltTy)
Emit an aggregate assignment.
JumpDest ReturnBlock
ReturnBlock - Unified return block.
void EmitAggregateCopy(LValue Dest, LValue Src, QualType EltTy, AggValueSlot::Overlap_t MayOverlap, bool isVolatile=false)
EmitAggregateCopy - Emit an aggregate copy.
LValue EmitLValueForField(LValue Base, const FieldDecl *Field, bool IsInBounds=true)
RawAddress CreateDefaultAlignTempAlloca(llvm::Type *Ty, const Twine &Name="tmp")
CreateDefaultAlignedTempAlloca - This creates an alloca with the default ABI alignment of the given L...
void GenerateOpenMPCapturedVars(const CapturedStmt &S, SmallVectorImpl< llvm::Value * > &CapturedVars)
void EmitIgnoredExpr(const Expr *E)
EmitIgnoredExpr - Emit an expression in a context which ignores the result.
RValue EmitLoadOfLValue(LValue V, SourceLocation Loc)
EmitLoadOfLValue - Given an expression that represents a value lvalue, this method emits the address ...
LValue EmitArraySectionExpr(const ArraySectionExpr *E, bool IsLowerBound=true)
LValue EmitOMPSharedLValue(const Expr *E)
Emits the lvalue for the expression with possibly captured variable.
void StartFunction(GlobalDecl GD, QualType RetTy, llvm::Function *Fn, const CGFunctionInfo &FnInfo, const FunctionArgList &Args, SourceLocation Loc=SourceLocation(), SourceLocation StartLoc=SourceLocation())
Emit code for the start of a function.
void EmitOMPCopy(QualType OriginalType, Address DestAddr, Address SrcAddr, const VarDecl *DestVD, const VarDecl *SrcVD, const Expr *Copy)
Emit proper copying of data from one variable to another.
llvm::Value * EvaluateExprAsBool(const Expr *E)
EvaluateExprAsBool - Perform the usual unary conversions on the specified expression and compare the ...
JumpDest getOMPCancelDestination(OpenMPDirectiveKind Kind)
llvm::Value * emitArrayLength(const ArrayType *arrayType, QualType &baseType, Address &addr)
emitArrayLength - Compute the length of an array, even if it's a VLA, and drill down to the base elem...
void EmitOMPAggregateAssign(Address DestAddr, Address SrcAddr, QualType OriginalType, const llvm::function_ref< void(Address, Address)> CopyGen)
Perform element by element copying of arrays with type OriginalType from SrcAddr to DestAddr using co...
bool HaveInsertPoint() const
HaveInsertPoint - True if an insertion point is defined.
CGDebugInfo * getDebugInfo()
llvm::Value * getTypeSize(QualType Ty)
Returns calculated size of the specified type.
LValue MakeRawAddrLValue(llvm::Value *V, QualType T, CharUnits Alignment, AlignmentSource Source=AlignmentSource::Type)
Same as MakeAddrLValue above except that the pointer is known to be unsigned.
LValue EmitLValueForFieldInitialization(LValue Base, const FieldDecl *Field)
EmitLValueForFieldInitialization - Like EmitLValueForField, except that if the Field is a reference,...
void incrementProfileCounter(const Stmt *S, llvm::Value *StepV=nullptr)
Increment the profiler's counter for the given statement by StepV.
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,...
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...
Address EmitLoadOfReference(LValue RefLVal, LValueBaseInfo *PointeeBaseInfo=nullptr, TBAAAccessInfo *PointeeTBAAInfo=nullptr)
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.
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.
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 handleCUDALaunchBoundsAttr(llvm::Function *F, const CUDALaunchBoundsAttr *A, int32_t *MaxThreadsVal=nullptr, int32_t *MinBlocksVal=nullptr, int32_t *MaxClusterRankVal=nullptr)
Emit the IR encoding to attach the CUDA launch bounds attribute to F.
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
void addCompilerUsedGlobal(llvm::GlobalValue *GV)
Add a global to a list to be added to the llvm.compiler.used metadata.
CharUnits GetTargetTypeStoreSize(llvm::Type *Ty) const
Return the store size, in character units, of the given LLVM type.
void handleAMDGPUWavesPerEUAttr(llvm::Function *F, const AMDGPUWavesPerEUAttr *A)
Emit the IR encoding to attach the AMD GPU waves-per-eu attribute to F.
DiagnosticsEngine & getDiags() const
const LangOptions & getLangOpts() const
CharUnits getNaturalTypeAlignment(QualType T, LValueBaseInfo *BaseInfo=nullptr, TBAAAccessInfo *TBAAInfo=nullptr, bool forPointeeType=false)
CodeGenTypes & getTypes()
const TargetInfo & getTarget() const
void EmitGlobal(GlobalDecl D)
Emit code for a single global function or var decl.
void handleAMDGPUFlatWorkGroupSizeAttr(llvm::Function *F, const AMDGPUFlatWorkGroupSizeAttr *A, const ReqdWorkGroupSizeAttr *ReqdWGS=nullptr, int32_t *MinThreadsVal=nullptr, int32_t *MaxThreadsVal=nullptr)
Emit the IR encoding to attach the AMD GPU flat-work-group-size attribute to F.
llvm::GlobalValue::LinkageTypes getLLVMLinkageVarDefinition(const VarDecl *VD)
Returns LLVM linkage for a declarator.
CGCXXABI & getCXXABI() const
CGOpenMPRuntime & getOpenMPRuntime()
Return a reference to the configured OpenMP runtime.
const llvm::Triple & getTriple() const
TBAAAccessInfo getTBAAInfoForSubobject(LValue Base, QualType AccessType)
getTBAAInfoForSubobject - Get TBAA information for an access with a given base lvalue.
llvm::Constant * GetAddrOfGlobal(GlobalDecl GD, ForDefinition_t IsForDefinition=NotForDefinition)
ASTContext & getContext() const
const TargetCodeGenInfo & getTargetCodeGenInfo()
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::GlobalValue * GetGlobalValue(StringRef Ref)
llvm::Constant * EmitNullConstant(QualType T)
Return the result of value-initializing the given type, i.e.
llvm::Function * CreateGlobalInitOrCleanUpFunction(llvm::FunctionType *ty, const Twine &name, const CGFunctionInfo &FI, SourceLocation Loc=SourceLocation(), bool TLS=false, llvm::GlobalVariable::LinkageTypes Linkage=llvm::GlobalVariable::InternalLinkage)
llvm::ConstantInt * getSize(CharUnits numChars)
Emit the given number of characters as a value of type size_t.
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::Type * ConvertTypeForMem(QualType T)
ConvertTypeForMem - Convert type T into a llvm::Type.
const CGFunctionInfo & arrangeNullaryFunction()
A nullary function is a freestanding function of type 'void ()'.
A specialization of Address that requires the address to be an LLVM Constant.
static ConstantAddress invalid()
Information for lazily generating a cleanup.
bool requiresLandingPad() const
void popTerminate()
Pops a terminate handler off the stack.
void pushTerminate()
Push a terminate handler on 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
virtual void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &M) const
setTargetAttributes - Provides a convenient hook to handle extra target-specific attributes for the g...
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.
SourceLocation getEndLoc() const LLVM_READONLY
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...
virtual bool hasBody() const
Returns true if this Decl represents a declaration for a body of code, such as a function or method d...
llvm::iterator_range< specific_attr_iterator< T > > specific_attrs() const
SourceLocation getLocation() const
DeclContext * getDeclContext()
SourceLocation getBeginLoc() const LLVM_READONLY
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.
unsigned getCustomDiagID(Level L, const char(&FormatString)[N])
Return an ID for a diagnostic with the specified format string and level.
The return type of classify().
This represents one expression.
bool isIntegerConstantExpr(const ASTContext &Ctx) const
@ 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, SmallVectorImpl< PartialDiagnosticAt > *Diag=nullptr) const
EvaluateKnownConstInt - Call EvaluateAsRValue and return the folded integer.
Expr * IgnoreParenImpCasts() LLVM_READONLY
Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...
bool isEvaluatable(const ASTContext &Ctx, SideEffectsKind AllowSideEffects=SE_NoSideEffects) const
isEvaluatable - Call EvaluateAsRValue to see if this expression can be constant folded without side-e...
std::optional< llvm::APSInt > getIntegerConstantExpr(const ASTContext &Ctx) const
isIntegerConstantExpr - Return the value if this expression is a valid integer constant expression.
bool HasSideEffects(const ASTContext &Ctx, bool IncludePossibleEffects=true) const
HasSideEffects - This routine returns true for all those expressions which have any effect other than...
bool EvaluateAsBooleanCondition(bool &Result, const ASTContext &Ctx, bool InConstantContext=false) const
EvaluateAsBooleanCondition - Return true if this is a constant which we can fold and convert to a boo...
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
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.
unsigned getNumParams() const
Return the number of parameters this function must have based on its FunctionType.
GlobalDecl - represents a global declaration.
const Decl * getDecl() const
static ImplicitParamDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation IdLoc, IdentifierInfo *Id, QualType T, ImplicitParamKind ParamKind)
Create implicit parameter.
static IntegerLiteral * Create(const ASTContext &C, const llvm::APInt &V, QualType type, SourceLocation l)
Returns a new integer literal with value 'V' and type 'type'.
Describes the capture of a variable or of this, or of a C++1y init-capture.
std::string OMPHostIRFile
Name of the IR file that contains the result of the OpenMP target host code generation.
std::vector< llvm::Triple > OMPTargetTriples
Triples of the OpenMP targets that the host code codegen should take into account in order to generat...
virtual void mangleCanonicalTypeName(QualType T, raw_ostream &, bool NormalizeIntegers=false)=0
Generates a unique string for an externally visible type for use with TBAA or type uniquing.
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
This represents clause 'affinity' in the '#pragma omp task'-based directives.
Class that represents a component of a mappable expression.
Expr * getAssociatedExpression() const
ValueDecl * getAssociatedDeclaration() const
ArrayRef< MappableComponent > MappableExprComponentListRef
const Stmt * getPreInitStmt() const
Get pre-initialization statement for the clause.
This is a basic class for representing single OpenMP clause.
This represents '#pragma omp declare mapper ...' directive.
This represents '#pragma omp declare reduction ...' directive.
Expr * getInitializer()
Get initializer expression (if specified) of the declare reduction construct.
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 is a basic class for representing single OpenMP executable directive.
static llvm::iterator_range< specific_clause_iterator< SpecificClause > > getClausesOfKind(ArrayRef< OMPClause * > Clauses)
This represents clause 'firstprivate' in the '#pragma omp ...' directives.
This represents clause 'has_device_ptr' in the '#pragma omp ...' directives.
This represents 'if' clause in the '#pragma omp ...' directive.
Expr * getCondition() const
Returns condition.
This represents clause 'in_reduction' in the '#pragma omp task' directives.
This represents clause 'is_device_ptr' in the '#pragma omp ...' directives.
OpenMP 5.0 [2.1.6 Iterators] Iterators are identifiers that expand to multiple values in the clause o...
This represents clause 'lastprivate' in the '#pragma omp ...' directives.
This represents clause 'linear' in the '#pragma omp ...' directives.
This is a common base class for loop directives ('omp simd', 'omp for', 'omp for simd' etc....
This represents clause 'map' in the '#pragma omp ...' directives.
This represents the 'message' clause in the '#pragma omp error' and the '#pragma omp parallel' direct...
Expr * getMessageString() const
Returns message string of the clause.
This represents clause 'nontemporal' in the '#pragma omp ...' directives.
This represents 'nowait' clause in the '#pragma omp ...' directive.
This represents 'num_teams' clause in the '#pragma omp ...' directive.
This represents 'num_threads' clause in the '#pragma omp ...' directive.
This represents 'ordered' clause in the '#pragma omp ...' directive.
This represents clause 'private' in the '#pragma omp ...' directives.
This represents clause 'reduction' in the '#pragma omp ...' directives.
This represents '#pragma omp requires...' directive.
This represents the 'severity' clause in the '#pragma omp error' and the '#pragma omp parallel' direc...
OpenMPSeverityClauseKind getSeverityKind() const
Returns kind of the clause.
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.
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
decl_type * getPreviousDecl()
Return the previous declaration of this declaration or NULL if this is the first declaration.
decl_type * getMostRecentDecl()
Returns the most recent (re)declaration of this declaration.
Base for LValueReferenceType and RValueReferenceType.
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.
fileinfo_iterator fileinfo_end() const
SourceLocation translateFileLineCol(const FileEntry *SourceFile, unsigned Line, unsigned Col) const
Get the source location for the given file:line:col triplet.
fileinfo_iterator fileinfo_begin() const
Stmt - This represents one statement.
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.
bool isTLSSupported() const
Whether the target supports thread-local storage.
virtual bool hasFeature(StringRef Feature) const
Determine whether the given target has the given feature.
The base class of the type hierarchy.
bool isSignedIntegerOrEnumerationType() const
Determines whether this is an integer type that is signed or an enumeration types whose underlying ty...
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.
bool hasLocalStorage() const
Returns true if a variable with function scope is a non-static local variable.
@ DeclarationOnly
This declaration is only a declaration.
DefinitionKind hasDefinition(ASTContext &) const
Check whether this variable is defined in this translation unit.
bool isLocalVarDeclOrParm() const
Similar to isLocalVarDecl but also includes parameters.
const Expr * getAnyInitializer() const
Get the initializer for this variable, no matter which declaration it is attached to.
Represents a C array with a specified size that is not an integer-constant-expression.
Expr * getSizeExpr() const
specific_attr_iterator - Iterates over a subrange of an AttrVec, only providing attributes that are o...
bool isEmptyRecordForLayout(const ASTContext &Context, QualType T)
isEmptyRecordForLayout - Return true iff a structure contains only empty base classes (per isEmptyRec...
@ Decl
The l-value was an access to a declared entity or something equivalently strong, like the address of ...
bool isEmptyFieldForLayout(const ASTContext &Context, const FieldDecl *FD)
isEmptyFieldForLayout - Return true iff the field is "empty", that is, either a zero-width bit-field ...
The JSON file list parser is used to communicate input to InstallAPI.
bool isOpenMPWorksharingDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a worksharing directive.
bool needsTaskBasedThreadLimit(OpenMPDirectiveKind DKind)
Checks if the specified target directive, combined or not, needs task based thread_limit.
@ Ctor_Complete
Complete object ctor.
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.
llvm::omp::Directive OpenMPDirectiveKind
OpenMP directives.
@ Conditional
A conditional (?:) operator.
@ ICIS_NoInit
No in-class initializer.
bool isOpenMPDistributeDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a distribute directive.
@ LCK_ByRef
Capturing by reference.
LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE()
@ Private
'private' clause, allowed on 'parallel', 'serial', 'loop', 'parallel loop', and 'serial loop' constru...
@ Vector
'vector' clause, allowed on 'loop', Combined, and 'routine' directives.
@ Reduction
'reduction' clause, allowed on Parallel, Serial, Loop, and the combined constructs.
@ Present
'present' clause, allowed on Compute and Combined constructs, plus 'data' and 'declare'.
OpenMPScheduleClauseModifier
OpenMP modifiers for 'schedule' clause.
@ OMPC_SCHEDULE_MODIFIER_last
@ OMPC_SCHEDULE_MODIFIER_unknown
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.
@ Result
The result type of a method or function.
bool isOpenMPTeamsDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a teams-kind directive.
OpenMPDependClauseKind
OpenMP attributes for 'depend' clause.
@ Dtor_Complete
Complete object dtor.
@ Union
The "union" keyword.
bool 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.
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.
const FunctionProtoType * T
void getOpenMPCaptureRegions(llvm::SmallVectorImpl< OpenMPDirectiveKind > &CaptureRegions, OpenMPDirectiveKind DKind)
Return the captured regions of an OpenMP directive.
OpenMPNumThreadsClauseModifier
@ OMPC_ATOMIC_DEFAULT_MEM_ORDER_unknown
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.
OpenMPMapClauseKind
OpenMP mapping kind for 'map' clause.
Diagnostic wrappers for TextAPI types for error reporting.
Maps the expression for the lastprivate variable to the global copy used to store new value because o...
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::PointerType * Int8PtrPtrTy
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
llvm::PointerType * Int8PtrTy
llvm::PointerType * UnqualPtrTy
CharUnits getPointerAlign() const
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.
Helper expressions and declaration for OMPIteratorExpr class for each iteration space.
Expr * CounterUpdate
Updater for the internal counter: ++CounterVD;.
Expr * Update
Update expression for the originally specified iteration variable, calculated as VD = Begin + Counter...
VarDecl * CounterVD
Internal normalized counter.
Data for list of allocators.
Scheduling data for loop-based OpenMP directives.
OpenMPScheduleClauseModifier M2
OpenMPScheduleClauseModifier M1
OpenMPScheduleClauseKind Schedule
Describes how types, statements, expressions, and declarations should be printed.