29#include "llvm/ADT/ArrayRef.h"
30#include "llvm/ADT/SmallVector.h"
31#include "llvm/ADT/StringExtras.h"
32#include "llvm/Bitcode/BitcodeReader.h"
33#include "llvm/IR/Constants.h"
34#include "llvm/IR/DerivedTypes.h"
35#include "llvm/IR/GlobalValue.h"
36#include "llvm/IR/InstrTypes.h"
37#include "llvm/IR/Value.h"
38#include "llvm/Support/AtomicOrdering.h"
39#include "llvm/Support/raw_ostream.h"
46using namespace CodeGen;
47using namespace llvm::omp;
51class CGOpenMPRegionInfo :
public CodeGenFunction::CGCapturedStmtInfo {
54 enum CGOpenMPRegionKind {
57 ParallelOutlinedRegion,
68 const CGOpenMPRegionKind RegionKind,
71 : CGCapturedStmtInfo(CS,
CR_OpenMP), RegionKind(RegionKind),
72 CodeGen(CodeGen),
Kind(
Kind), HasCancel(HasCancel) {}
74 CGOpenMPRegionInfo(
const CGOpenMPRegionKind RegionKind,
77 : CGCapturedStmtInfo(
CR_OpenMP), RegionKind(RegionKind), CodeGen(CodeGen),
82 virtual const VarDecl *getThreadIDVariable()
const = 0;
93 CGOpenMPRegionKind getRegionKind()
const {
return RegionKind; }
97 bool hasCancel()
const {
return HasCancel; }
99 static bool classof(
const CGCapturedStmtInfo *Info) {
103 ~CGOpenMPRegionInfo()
override =
default;
106 CGOpenMPRegionKind RegionKind;
113class CGOpenMPOutlinedRegionInfo final :
public CGOpenMPRegionInfo {
118 StringRef HelperName)
119 : CGOpenMPRegionInfo(CS, ParallelOutlinedRegion, CodeGen,
Kind,
121 ThreadIDVar(ThreadIDVar), HelperName(HelperName) {
122 assert(ThreadIDVar !=
nullptr &&
"No ThreadID in OpenMP region.");
127 const VarDecl *getThreadIDVariable()
const override {
return ThreadIDVar; }
130 StringRef getHelperName()
const override {
return HelperName; }
132 static bool classof(
const CGCapturedStmtInfo *Info) {
133 return CGOpenMPRegionInfo::classof(Info) &&
134 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() ==
135 ParallelOutlinedRegion;
142 StringRef HelperName;
146class CGOpenMPTaskOutlinedRegionInfo final :
public CGOpenMPRegionInfo {
152 llvm::SwitchInst *UntiedSwitch =
nullptr;
155 UntiedTaskActionTy(
bool Tied,
const VarDecl *PartIDVar,
157 : Untied(!Tied), PartIDVar(PartIDVar), UntiedCodeGen(UntiedCodeGen) {}
167 UntiedSwitch = CGF.
Builder.CreateSwitch(Res, DoneBB);
171 UntiedSwitch->addCase(CGF.
Builder.getInt32(0),
173 emitUntiedSwitch(CGF);
184 CodeGenFunction::JumpDest CurPoint =
188 UntiedSwitch->addCase(CGF.
Builder.getInt32(UntiedSwitch->getNumCases()),
194 unsigned getNumberOfParts()
const {
return UntiedSwitch->getNumCases(); }
200 const UntiedTaskActionTy &Action)
201 : CGOpenMPRegionInfo(CS, TaskOutlinedRegion, CodeGen,
Kind, HasCancel),
202 ThreadIDVar(ThreadIDVar), Action(Action) {
203 assert(ThreadIDVar !=
nullptr &&
"No ThreadID in OpenMP region.");
208 const VarDecl *getThreadIDVariable()
const override {
return ThreadIDVar; }
214 StringRef getHelperName()
const override {
return ".omp_outlined."; }
217 Action.emitUntiedSwitch(CGF);
220 static bool classof(
const CGCapturedStmtInfo *Info) {
221 return CGOpenMPRegionInfo::classof(Info) &&
222 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() ==
231 const UntiedTaskActionTy &Action;
236class CGOpenMPInlinedRegionInfo :
public CGOpenMPRegionInfo {
238 CGOpenMPInlinedRegionInfo(CodeGenFunction::CGCapturedStmtInfo *OldCSI,
241 : CGOpenMPRegionInfo(InlinedRegion, CodeGen,
Kind, HasCancel),
243 OuterRegionInfo(dyn_cast_or_null<CGOpenMPRegionInfo>(OldCSI)) {}
246 llvm::Value *getContextValue()
const override {
248 return OuterRegionInfo->getContextValue();
249 llvm_unreachable(
"No context value for inlined OpenMP region");
252 void setContextValue(llvm::Value *
V)
override {
253 if (OuterRegionInfo) {
254 OuterRegionInfo->setContextValue(
V);
257 llvm_unreachable(
"No context value for inlined OpenMP region");
263 return OuterRegionInfo->lookup(VD);
269 FieldDecl *getThisFieldDecl()
const override {
271 return OuterRegionInfo->getThisFieldDecl();
277 const VarDecl *getThreadIDVariable()
const override {
279 return OuterRegionInfo->getThreadIDVariable();
286 return OuterRegionInfo->getThreadIDVariableLValue(CGF);
287 llvm_unreachable(
"No LValue for inlined OpenMP construct");
291 StringRef getHelperName()
const override {
292 if (
auto *OuterRegionInfo = getOldCSI())
293 return OuterRegionInfo->getHelperName();
294 llvm_unreachable(
"No helper name for inlined OpenMP construct");
299 OuterRegionInfo->emitUntiedSwitch(CGF);
302 CodeGenFunction::CGCapturedStmtInfo *getOldCSI()
const {
return OldCSI; }
304 static bool classof(
const CGCapturedStmtInfo *Info) {
305 return CGOpenMPRegionInfo::classof(Info) &&
306 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == InlinedRegion;
309 ~CGOpenMPInlinedRegionInfo()
override =
default;
313 CodeGenFunction::CGCapturedStmtInfo *OldCSI;
314 CGOpenMPRegionInfo *OuterRegionInfo;
322class CGOpenMPTargetRegionInfo final :
public CGOpenMPRegionInfo {
326 : CGOpenMPRegionInfo(CS, TargetRegion, CodeGen, OMPD_target,
328 HelperName(HelperName) {}
332 const VarDecl *getThreadIDVariable()
const override {
return nullptr; }
335 StringRef getHelperName()
const override {
return HelperName; }
337 static bool classof(
const CGCapturedStmtInfo *Info) {
338 return CGOpenMPRegionInfo::classof(Info) &&
339 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == TargetRegion;
343 StringRef HelperName;
347 llvm_unreachable(
"No codegen for expressions");
351class CGOpenMPInnerExprInfo final :
public CGOpenMPInlinedRegionInfo {
354 : CGOpenMPInlinedRegionInfo(CGF.CapturedStmtInfo, EmptyCodeGen,
362 if (!
C.capturesVariable() && !
C.capturesVariableByCopy())
365 const VarDecl *VD =
C.getCapturedVar();
375 (void)PrivScope.Privatize();
380 if (
const FieldDecl *FD = CGOpenMPInlinedRegionInfo::lookup(VD))
387 llvm_unreachable(
"No body for expressions");
392 const VarDecl *getThreadIDVariable()
const override {
393 llvm_unreachable(
"No thread id for expressions");
397 StringRef getHelperName()
const override {
398 llvm_unreachable(
"No helper name for expressions");
401 static bool classof(
const CGCapturedStmtInfo *Info) {
return false; }
405 CodeGenFunction::OMPPrivateScope PrivScope;
409class InlinedOpenMPRegionRAII {
411 llvm::DenseMap<const ValueDecl *, FieldDecl *> LambdaCaptureFields;
412 FieldDecl *LambdaThisCaptureField =
nullptr;
414 bool NoInheritance =
false;
423 bool NoInheritance =
true)
424 : CGF(CGF), NoInheritance(NoInheritance) {
437 ~InlinedOpenMPRegionRAII() {
454enum OpenMPLocationFlags :
unsigned {
456 OMP_IDENT_IMD = 0x01,
458 OMP_IDENT_KMPC = 0x02,
460 OMP_ATOMIC_REDUCE = 0x10,
462 OMP_IDENT_BARRIER_EXPL = 0x20,
464 OMP_IDENT_BARRIER_IMPL = 0x40,
466 OMP_IDENT_BARRIER_IMPL_FOR = 0x40,
468 OMP_IDENT_BARRIER_IMPL_SECTIONS = 0xC0,
470 OMP_IDENT_BARRIER_IMPL_SINGLE = 0x140,
472 OMP_IDENT_WORK_LOOP = 0x200,
474 OMP_IDENT_WORK_SECTIONS = 0x400,
476 OMP_IDENT_WORK_DISTRIBUTE = 0x800,
506enum IdentFieldIndex {
508 IdentField_Reserved_1,
512 IdentField_Reserved_2,
514 IdentField_Reserved_3,
523enum OpenMPSchedType {
526 OMP_sch_static_chunked = 33,
528 OMP_sch_dynamic_chunked = 35,
529 OMP_sch_guided_chunked = 36,
530 OMP_sch_runtime = 37,
533 OMP_sch_static_balanced_chunked = 45,
536 OMP_ord_static_chunked = 65,
538 OMP_ord_dynamic_chunked = 67,
539 OMP_ord_guided_chunked = 68,
540 OMP_ord_runtime = 69,
542 OMP_sch_default = OMP_sch_static,
544 OMP_dist_sch_static_chunked = 91,
545 OMP_dist_sch_static = 92,
548 OMP_sch_modifier_monotonic = (1 << 29),
550 OMP_sch_modifier_nonmonotonic = (1 << 30),
573 Callback(CodeGen, CGF, *PrePostAction);
576 Callback(CodeGen, CGF, Action);
584 if (
const auto *CE = dyn_cast<CallExpr>(ReductionOp))
585 if (
const auto *OVE = dyn_cast<OpaqueValueExpr>(CE->getCallee()))
586 if (
const auto *DRE =
587 dyn_cast<DeclRefExpr>(OVE->getSourceExpr()->IgnoreImpCasts()))
588 if (
const auto *DRD = dyn_cast<OMPDeclareReductionDecl>(DRE->getDecl()))
599 std::pair<llvm::Function *, llvm::Function *>
Reduction =
601 const auto *CE = cast<CallExpr>(InitOp);
602 const auto *OVE = cast<OpaqueValueExpr>(CE->getCallee());
606 cast<DeclRefExpr>(cast<UnaryOperator>(LHS)->getSubExpr());
608 cast<DeclRefExpr>(cast<UnaryOperator>(RHS)->getSubExpr());
609 CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
610 PrivateScope.addPrivate(cast<VarDecl>(LHSDRE->getDecl()),
Private);
611 PrivateScope.addPrivate(cast<VarDecl>(RHSDRE->getDecl()), Original);
612 (void)PrivateScope.Privatize();
614 CodeGenFunction::OpaqueValueMapping Map(CGF, OVE,
Func);
619 auto *GV =
new llvm::GlobalVariable(
621 llvm::GlobalValue::PrivateLinkage,
Init, Name);
634 CodeGenFunction::OpaqueValueMapping OpaqueMap(CGF, &OVE, LV);
641 CodeGenFunction::OpaqueValueMapping OpaqueMap(CGF, &OVE, InitRVal);
662 llvm::Value *NumElements = CGF.
emitArrayLength(ArrayTy, ElementTy, DestAddr);
666 llvm::Value *SrcBegin =
nullptr;
668 SrcBegin = SrcAddr.emitRawPointer(CGF);
671 llvm::Value *DestEnd =
676 llvm::Value *IsEmpty =
677 CGF.
Builder.CreateICmpEQ(DestBegin, DestEnd,
"omp.arrayinit.isempty");
678 CGF.
Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
681 llvm::BasicBlock *EntryBB = CGF.
Builder.GetInsertBlock();
686 llvm::PHINode *SrcElementPHI =
nullptr;
689 SrcElementPHI = CGF.
Builder.CreatePHI(SrcBegin->getType(), 2,
690 "omp.arraycpy.srcElementPast");
691 SrcElementPHI->addIncoming(SrcBegin, EntryBB);
693 Address(SrcElementPHI, SrcAddr.getElementType(),
694 SrcAddr.getAlignment().alignmentOfArrayElement(ElementSize));
696 llvm::PHINode *DestElementPHI = CGF.
Builder.CreatePHI(
697 DestBegin->getType(), 2,
"omp.arraycpy.destElementPast");
698 DestElementPHI->addIncoming(DestBegin, EntryBB);
705 CodeGenFunction::RunCleanupsScope InitScope(CGF);
706 if (EmitDeclareReductionInit) {
708 SrcElementCurrent, ElementTy);
716 llvm::Value *SrcElementNext = CGF.
Builder.CreateConstGEP1_32(
717 SrcAddr.getElementType(), SrcElementPHI, 1,
718 "omp.arraycpy.dest.element");
719 SrcElementPHI->addIncoming(SrcElementNext, CGF.
Builder.GetInsertBlock());
723 llvm::Value *DestElementNext = CGF.
Builder.CreateConstGEP1_32(
725 "omp.arraycpy.dest.element");
728 CGF.
Builder.CreateICmpEQ(DestElementNext, DestEnd,
"omp.arraycpy.done");
729 CGF.
Builder.CreateCondBr(Done, DoneBB, BodyBB);
730 DestElementPHI->addIncoming(DestElementNext, CGF.
Builder.GetInsertBlock());
742 if (
const auto *OASE = dyn_cast<ArraySectionExpr>(
E))
747void ReductionCodeGen::emitAggregateInitialization(
753 const auto *PrivateVD =
754 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].
Private)->getDecl());
755 bool EmitDeclareReductionInit =
758 EmitDeclareReductionInit,
759 EmitDeclareReductionInit ? ClausesData[N].ReductionOp
760 : PrivateVD->getInit(),
768 ClausesData.reserve(Shareds.size());
769 SharedAddresses.reserve(Shareds.size());
770 Sizes.reserve(Shareds.size());
771 BaseDecls.reserve(Shareds.size());
772 const auto *IOrig = Origs.begin();
773 const auto *IPriv = Privates.begin();
774 const auto *IRed = ReductionOps.begin();
775 for (
const Expr *Ref : Shareds) {
776 ClausesData.emplace_back(Ref, *IOrig, *IPriv, *IRed);
777 std::advance(IOrig, 1);
778 std::advance(IPriv, 1);
779 std::advance(IRed, 1);
784 assert(SharedAddresses.size() == N && OrigAddresses.size() == N &&
785 "Number of generated lvalues must be exactly N.");
786 LValue First = emitSharedLValue(CGF, ClausesData[N].Shared);
787 LValue Second = emitSharedLValueUB(CGF, ClausesData[N].Shared);
788 SharedAddresses.emplace_back(
First, Second);
789 if (ClausesData[N].Shared == ClausesData[N].Ref) {
790 OrigAddresses.emplace_back(
First, Second);
792 LValue First = emitSharedLValue(CGF, ClausesData[N].Ref);
793 LValue Second = emitSharedLValueUB(CGF, ClausesData[N].Ref);
794 OrigAddresses.emplace_back(
First, Second);
800 bool AsArraySection = isa<ArraySectionExpr>(ClausesData[N].Ref);
803 CGF.
getTypeSize(OrigAddresses[N].first.getType().getNonReferenceType()),
808 llvm::Value *SizeInChars;
809 auto *ElemType = OrigAddresses[N].first.getAddress().getElementType();
810 auto *ElemSizeOf = llvm::ConstantExpr::getSizeOf(ElemType);
811 if (AsArraySection) {
812 Size = CGF.
Builder.CreatePtrDiff(ElemType,
813 OrigAddresses[N].second.getPointer(CGF),
814 OrigAddresses[N].first.getPointer(CGF));
815 Size = CGF.
Builder.CreateNUWAdd(
816 Size, llvm::ConstantInt::get(Size->getType(), 1));
817 SizeInChars = CGF.
Builder.CreateNUWMul(Size, ElemSizeOf);
820 CGF.
getTypeSize(OrigAddresses[N].first.getType().getNonReferenceType());
821 Size = CGF.
Builder.CreateExactUDiv(SizeInChars, ElemSizeOf);
823 Sizes.emplace_back(SizeInChars, Size);
826 cast<OpaqueValueExpr>(
836 assert(!Size && !Sizes[N].second &&
837 "Size should be nullptr for non-variably modified reduction "
843 cast<OpaqueValueExpr>(
852 assert(SharedAddresses.size() > N &&
"No variable was generated");
853 const auto *PrivateVD =
854 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].
Private)->getDecl());
859 (void)DefaultInit(CGF);
860 emitAggregateInitialization(CGF, N, PrivateAddr, SharedAddr, DRD);
861 }
else if (DRD && (DRD->
getInitializer() || !PrivateVD->hasInit())) {
862 (void)DefaultInit(CGF);
863 QualType SharedType = SharedAddresses[N].first.getType();
865 PrivateAddr, SharedAddr, SharedType);
866 }
else if (!DefaultInit(CGF) && PrivateVD->hasInit() &&
869 PrivateVD->
getType().getQualifiers(),
887 CGF.
pushDestroy(DTorKind, PrivateAddr, PrivateType);
911 Address OriginalBaseAddress, llvm::Value *Addr) {
935 Addr, OriginalBaseAddress.
getType());
940 const VarDecl *OrigVD =
nullptr;
941 if (
const auto *OASE = dyn_cast<ArraySectionExpr>(Ref)) {
942 const Expr *
Base = OASE->getBase()->IgnoreParenImpCasts();
943 while (
const auto *TempOASE = dyn_cast<ArraySectionExpr>(
Base))
944 Base = TempOASE->getBase()->IgnoreParenImpCasts();
945 while (
const auto *TempASE = dyn_cast<ArraySubscriptExpr>(
Base))
946 Base = TempASE->getBase()->IgnoreParenImpCasts();
947 DE = cast<DeclRefExpr>(
Base);
948 OrigVD = cast<VarDecl>(DE->
getDecl());
949 }
else if (
const auto *ASE = dyn_cast<ArraySubscriptExpr>(Ref)) {
950 const Expr *
Base = ASE->getBase()->IgnoreParenImpCasts();
951 while (
const auto *TempASE = dyn_cast<ArraySubscriptExpr>(
Base))
952 Base = TempASE->getBase()->IgnoreParenImpCasts();
953 DE = cast<DeclRefExpr>(
Base);
954 OrigVD = cast<VarDecl>(DE->
getDecl());
963 BaseDecls.emplace_back(OrigVD);
966 loadToBegin(CGF, OrigVD->getType(), SharedAddresses[N].first.getType(),
968 Address SharedAddr = SharedAddresses[N].first.getAddress();
969 llvm::Value *Adjustment = CGF.
Builder.CreatePtrDiff(
972 llvm::Value *PrivatePointer =
978 SharedAddresses[N].first.getType(),
981 BaseDecls.emplace_back(
982 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Ref)->getDecl()));
995 getThreadIDVariable()->getType()->castAs<PointerType>());
1013LValue CGOpenMPTaskOutlinedRegionInfo::getThreadIDVariableLValue(
1016 getThreadIDVariable()->getType(),
1032 : CGM(CGM), OMPBuilder(CGM.getModule()) {
1034 llvm::OpenMPIRBuilderConfig Config(
1049 OMPBuilder.Config.setHasRequiresUnifiedSharedMemory(
true);
1057 if (!
Data.getValue().pointsToAliveValue())
1059 auto *GV = dyn_cast<llvm::GlobalVariable>(
Data.getValue());
1062 if (!GV->isDeclaration() || GV->getNumUses() > 0)
1064 GV->eraseFromParent();
1069 return OMPBuilder.createPlatformSpecificName(Parts);
1072static llvm::Function *
1074 const Expr *CombinerInitializer,
const VarDecl *In,
1075 const VarDecl *Out,
bool IsCombiner) {
1078 QualType PtrTy =
C.getPointerType(Ty).withRestrict();
1084 Args.push_back(&OmpOutParm);
1085 Args.push_back(&OmpInParm);
1090 {IsCombiner ?
"omp_combiner" :
"omp_initializer",
""});
1091 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
1095 Fn->removeFnAttr(llvm::Attribute::NoInline);
1096 Fn->removeFnAttr(llvm::Attribute::OptimizeNone);
1097 Fn->addFnAttr(llvm::Attribute::AlwaysInline);
1103 Out->getLocation());
1104 CodeGenFunction::OMPPrivateScope
Scope(CGF);
1113 (void)
Scope.Privatize();
1114 if (!IsCombiner && Out->hasInit() &&
1117 Out->getType().getQualifiers(),
1120 if (CombinerInitializer)
1122 Scope.ForceCleanup();
1132 CGM,
D->getType(),
D->getCombiner(),
1133 cast<VarDecl>(cast<DeclRefExpr>(
D->getCombinerIn())->getDecl()),
1134 cast<VarDecl>(cast<DeclRefExpr>(
D->getCombinerOut())->getDecl()),
1137 if (
const Expr *
Init =
D->getInitializer()) {
1142 cast<VarDecl>(cast<DeclRefExpr>(
D->getInitOrig())->getDecl()),
1143 cast<VarDecl>(cast<DeclRefExpr>(
D->getInitPriv())->getDecl()),
1151std::pair<llvm::Function *, llvm::Function *>
1163struct PushAndPopStackRAII {
1164 PushAndPopStackRAII(llvm::OpenMPIRBuilder *OMPBuilder,
CodeGenFunction &CGF,
1165 bool HasCancel, llvm::omp::Directive
Kind)
1166 : OMPBuilder(OMPBuilder) {
1182 auto FiniCB = [&CGF](llvm::OpenMPIRBuilder::InsertPointTy IP) {
1183 assert(IP.getBlock()->end() == IP.getPoint() &&
1184 "Clang CG should cause non-terminated block!");
1185 CGBuilderTy::InsertPointGuard IPG(CGF.
Builder);
1190 return llvm::Error::success();
1195 llvm::OpenMPIRBuilder::FinalizationInfo FI({FiniCB,
Kind, HasCancel});
1196 OMPBuilder->pushFinalizationCB(std::move(FI));
1198 ~PushAndPopStackRAII() {
1200 OMPBuilder->popFinalizationCB();
1202 llvm::OpenMPIRBuilder *OMPBuilder;
1211 "thread id variable must be of type kmp_int32 *");
1213 bool HasCancel =
false;
1214 if (
const auto *OPD = dyn_cast<OMPParallelDirective>(&
D))
1215 HasCancel = OPD->hasCancel();
1216 else if (
const auto *OPD = dyn_cast<OMPTargetParallelDirective>(&
D))
1217 HasCancel = OPD->hasCancel();
1218 else if (
const auto *OPSD = dyn_cast<OMPParallelSectionsDirective>(&
D))
1219 HasCancel = OPSD->hasCancel();
1220 else if (
const auto *OPFD = dyn_cast<OMPParallelForDirective>(&
D))
1221 HasCancel = OPFD->hasCancel();
1222 else if (
const auto *OPFD = dyn_cast<OMPTargetParallelForDirective>(&
D))
1223 HasCancel = OPFD->hasCancel();
1224 else if (
const auto *OPFD = dyn_cast<OMPDistributeParallelForDirective>(&
D))
1225 HasCancel = OPFD->hasCancel();
1226 else if (
const auto *OPFD =
1227 dyn_cast<OMPTeamsDistributeParallelForDirective>(&
D))
1228 HasCancel = OPFD->hasCancel();
1229 else if (
const auto *OPFD =
1230 dyn_cast<OMPTargetTeamsDistributeParallelForDirective>(&
D))
1231 HasCancel = OPFD->hasCancel();
1236 PushAndPopStackRAII PSR(&OMPBuilder, CGF, HasCancel, InnermostKind);
1237 CGOpenMPOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen, InnermostKind,
1238 HasCancel, OutlinedHelperName);
1239 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
1244 std::string Suffix =
getName({
"omp_outlined"});
1245 return (Name + Suffix).str();
1253 std::string Suffix =
getName({
"omp",
"reduction",
"reduction_func"});
1254 return (Name + Suffix).str();
1281 bool Tied,
unsigned &NumberOfParts) {
1286 llvm::Value *TaskArgs[] = {
1288 CGF.EmitLoadOfPointerLValue(CGF.GetAddrOfLocalVar(TaskTVar),
1291 CGF.EmitRuntimeCall(
OMPBuilder.getOrCreateRuntimeFunction(
1295 CGOpenMPTaskOutlinedRegionInfo::UntiedTaskActionTy Action(Tied, PartIDVar,
1299 "thread id variable must be of type kmp_int32 for tasks");
1304 bool HasCancel =
false;
1305 if (
const auto *TD = dyn_cast<OMPTaskDirective>(&
D))
1306 HasCancel = TD->hasCancel();
1307 else if (
const auto *TD = dyn_cast<OMPTaskLoopDirective>(&
D))
1308 HasCancel = TD->hasCancel();
1309 else if (
const auto *TD = dyn_cast<OMPMasterTaskLoopDirective>(&
D))
1310 HasCancel = TD->hasCancel();
1311 else if (
const auto *TD = dyn_cast<OMPParallelMasterTaskLoopDirective>(&
D))
1312 HasCancel = TD->hasCancel();
1315 CGOpenMPTaskOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen,
1316 InnermostKind, HasCancel, Action);
1318 llvm::Function *Res = CGF.GenerateCapturedStmtFunction(*CS);
1320 NumberOfParts = Action.getNumberOfParts();
1325 bool AtCurrentPoint) {
1327 assert(!Elem.ServiceInsertPt &&
"Insert point is set already.");
1329 llvm::Value *Undef = llvm::UndefValue::get(CGF.
Int32Ty);
1330 if (AtCurrentPoint) {
1331 Elem.ServiceInsertPt =
new llvm::BitCastInst(Undef, CGF.
Int32Ty,
"svcpt",
1332 CGF.
Builder.GetInsertBlock());
1334 Elem.ServiceInsertPt =
new llvm::BitCastInst(Undef, CGF.
Int32Ty,
"svcpt");
1341 if (Elem.ServiceInsertPt) {
1342 llvm::Instruction *Ptr = Elem.ServiceInsertPt;
1343 Elem.ServiceInsertPt =
nullptr;
1344 Ptr->eraseFromParent();
1351 llvm::raw_svector_ostream OS(Buffer);
1355 if (
const auto *FD = dyn_cast_or_null<FunctionDecl>(CGF.
CurFuncDecl))
1356 OS << FD->getQualifiedNameAsString();
1363 unsigned Flags,
bool EmitLoc) {
1364 uint32_t SrcLocStrSize;
1365 llvm::Constant *SrcLocStr;
1367 llvm::codegenoptions::NoDebugInfo) ||
1369 SrcLocStr =
OMPBuilder.getOrCreateDefaultSrcLocStr(SrcLocStrSize);
1371 std::string FunctionName;
1372 if (
const auto *FD = dyn_cast_or_null<FunctionDecl>(CGF.
CurFuncDecl))
1373 FunctionName = FD->getQualifiedNameAsString();
1383 SrcLocStr, SrcLocStrSize, llvm::omp::IdentFlag(Flags), Reserved2Flags);
1388 assert(CGF.
CurFn &&
"No function in current CodeGenFunction.");
1394 uint32_t SrcLocStrSize;
1395 auto *SrcLocStr =
OMPBuilder.getOrCreateSrcLocStr(
1398 OMPBuilder.getOrCreateIdent(SrcLocStr, SrcLocStrSize));
1401 llvm::Value *ThreadID =
nullptr;
1406 ThreadID = I->second.ThreadID;
1407 if (ThreadID !=
nullptr)
1411 if (
auto *OMPRegionInfo =
1413 if (OMPRegionInfo->getThreadIDVariable()) {
1415 LValue LVal = OMPRegionInfo->getThreadIDVariableLValue(CGF);
1419 CGF.
Builder.GetInsertBlock() == TopBlock ||
1420 !isa<llvm::Instruction>(LVal.
getPointer(CGF)) ||
1421 cast<llvm::Instruction>(LVal.
getPointer(CGF))->getParent() ==
1423 cast<llvm::Instruction>(LVal.
getPointer(CGF))->getParent() ==
1424 CGF.
Builder.GetInsertBlock()) {
1428 if (CGF.
Builder.GetInsertBlock() == TopBlock)
1440 if (!Elem.ServiceInsertPt)
1442 CGBuilderTy::InsertPointGuard IPG(CGF.
Builder);
1443 CGF.
Builder.SetInsertPoint(Elem.ServiceInsertPt);
1447 OMPRTL___kmpc_global_thread_num),
1450 Elem.ThreadID =
Call;
1455 assert(CGF.
CurFn &&
"No function in current CodeGenFunction.");
1467 for(
const auto *
D : I->second)
1482 llvm::Type *MicroParams[] = {llvm::PointerType::getUnqual(
CGM.
Int32Ty),
1489static llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseKind
1491 std::optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
1492 OMPDeclareTargetDeclAttr::getDeviceType(VD);
1494 return llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseNone;
1496 switch ((
int)*DevTy) {
1497 case OMPDeclareTargetDeclAttr::DT_Host:
1498 return llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseHost;
1500 case OMPDeclareTargetDeclAttr::DT_NoHost:
1501 return llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseNoHost;
1503 case OMPDeclareTargetDeclAttr::DT_Any:
1504 return llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseAny;
1507 return llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseNone;
1512static llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryKind
1514 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> MapType =
1515 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
1517 return llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryNone;
1518 switch ((
int)*MapType) {
1519 case OMPDeclareTargetDeclAttr::MapTypeTy::MT_To:
1520 return llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryTo;
1522 case OMPDeclareTargetDeclAttr::MapTypeTy::MT_Enter:
1523 return llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryEnter;
1525 case OMPDeclareTargetDeclAttr::MapTypeTy::MT_Link:
1526 return llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryLink;
1529 return llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryNone;
1538 auto FileInfoCallBack = [&]() {
1542 llvm::sys::fs::UniqueID ID;
1543 if (llvm::sys::fs::getUniqueID(PLoc.
getFilename(), ID)) {
1544 PLoc =
SM.getPresumedLoc(BeginLoc,
false);
1550 return OMPBuilder.getTargetEntryUniqueInfo(FileInfoCallBack, ParentName);
1556 auto LinkageForVariable = [&VD,
this]() {
1560 std::vector<llvm::GlobalVariable *> GeneratedRefs;
1564 llvm::Constant *addr =
OMPBuilder.getAddrOfDeclareTargetVar(
1572 LinkageForVariable);
1584 std::string Suffix =
getName({
"cache",
""});
1585 return OMPBuilder.getOrCreateInternalVariable(
1598 llvm::Value *Args[] = {
1622 llvm::Value *Args[] = {
1625 Ctor, CopyCtor, Dtor};
1628 CGM.
getModule(), OMPRTL___kmpc_threadprivate_register),
1643 llvm::Value *Ctor =
nullptr, *CopyCtor =
nullptr, *Dtor =
nullptr;
1653 Args.push_back(&Dst);
1658 std::string Name =
getName({
"__kmpc_global_ctor_",
""});
1659 llvm::Function *Fn =
1685 Args.push_back(&Dst);
1690 std::string Name =
getName({
"__kmpc_global_dtor_",
""});
1691 llvm::Function *Fn =
1716 if (Ctor ==
nullptr) {
1719 if (Dtor ==
nullptr) {
1723 auto *InitFunctionTy =
1724 llvm::FunctionType::get(
CGM.
VoidTy,
false);
1725 std::string Name =
getName({
"__omp_threadprivate_init_",
""});
1735 return InitFunction;
1743 llvm::GlobalValue *GV) {
1744 std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr =
1745 OMPDeclareTargetDeclAttr::getActiveAttr(FD);
1748 if (!ActiveAttr || !(*ActiveAttr)->getIndirect())
1755 OMPBuilder.OffloadInfoManager.getTargetRegionEntryFnName(Name, EntryInfo);
1761 llvm::GlobalValue *Addr = GV;
1763 Addr =
new llvm::GlobalVariable(
1765 true, llvm::GlobalValue::ExternalLinkage, GV, Name,
1766 nullptr, llvm::GlobalValue::NotThreadLocal,
1767 CGM.
getModule().getDataLayout().getDefaultGlobalsAddressSpace());
1768 Addr->setVisibility(llvm::GlobalValue::ProtectedVisibility);
1771 OMPBuilder.OffloadInfoManager.registerDeviceGlobalVarEntryInfo(
1773 llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryIndirect,
1774 llvm::GlobalValue::WeakODRLinkage);
1780 std::string Suffix =
getName({
"artificial",
""});
1782 llvm::GlobalVariable *GAddr =
OMPBuilder.getOrCreateInternalVariable(
1783 VarLVType, Twine(Name).concat(Suffix).str());
1786 GAddr->setThreadLocal(
true);
1787 return Address(GAddr, GAddr->getValueType(),
1790 std::string CacheSuffix =
getName({
"cache",
""});
1791 llvm::Value *Args[] = {
1799 Twine(Name).concat(Suffix).concat(CacheSuffix).str())};
1850 llvm::Function *OutlinedFn,
1853 llvm::Value *NumThreads) {
1858 auto &&ThenGen = [&M, OutlinedFn, CapturedVars, RTLoc,
1862 llvm::Value *Args[] = {
1864 CGF.
Builder.getInt32(CapturedVars.size()),
1867 RealArgs.append(std::begin(Args), std::end(Args));
1868 RealArgs.append(CapturedVars.begin(), CapturedVars.end());
1870 llvm::FunctionCallee RTLFn =
1871 OMPBuilder.getOrCreateRuntimeFunction(M, OMPRTL___kmpc_fork_call);
1874 auto &&ElseGen = [&M, OutlinedFn, CapturedVars, RTLoc,
Loc,
1880 llvm::Value *Args[] = {RTLoc, ThreadID};
1882 M, OMPRTL___kmpc_serialized_parallel),
1889 ".bound.zero.addr");
1894 OutlinedFnArgs.push_back(ZeroAddrBound.
getPointer());
1895 OutlinedFnArgs.append(CapturedVars.begin(), CapturedVars.end());
1903 OutlinedFn->removeFnAttr(llvm::Attribute::AlwaysInline);
1904 OutlinedFn->addFnAttr(llvm::Attribute::NoInline);
1910 M, OMPRTL___kmpc_end_serialized_parallel),
1929 if (
auto *OMPRegionInfo =
1931 if (OMPRegionInfo->getThreadIDVariable())
1932 return OMPRegionInfo->getThreadIDVariableLValue(CGF).getAddress();
1941 return ThreadIDTemp;
1945 std::string Prefix = Twine(
"gomp_critical_user_", CriticalName).str();
1946 std::string Name =
getName({Prefix,
"var"});
1953 llvm::FunctionCallee EnterCallee;
1955 llvm::FunctionCallee ExitCallee;
1958 llvm::BasicBlock *ContBlock =
nullptr;
1961 CommonActionTy(llvm::FunctionCallee EnterCallee,
1963 llvm::FunctionCallee ExitCallee,
1965 : EnterCallee(EnterCallee), EnterArgs(EnterArgs), ExitCallee(ExitCallee),
1966 ExitArgs(ExitArgs), Conditional(Conditional) {}
1970 llvm::Value *CallBool = CGF.
Builder.CreateIsNotNull(EnterRes);
1974 CGF.
Builder.CreateCondBr(CallBool, ThenBlock, ContBlock);
1990 StringRef CriticalName,
2004 EnterArgs.push_back(CGF.
Builder.CreateIntCast(
2007 CommonActionTy Action(
2010 Hint ? OMPRTL___kmpc_critical_with_hint : OMPRTL___kmpc_critical),
2013 OMPRTL___kmpc_end_critical),
2030 CommonActionTy Action(
OMPBuilder.getOrCreateRuntimeFunction(
2052 llvm::Value *FilterVal = Filter
2059 CommonActionTy Action(
OMPBuilder.getOrCreateRuntimeFunction(
2079 llvm::Value *Args[] = {
2081 llvm::ConstantInt::get(
CGM.
IntTy, 0,
true)};
2087 if (
auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.
CapturedStmtInfo))
2088 Region->emitUntiedSwitch(CGF);
2101 CommonActionTy Action(
OMPBuilder.getOrCreateRuntimeFunction(
2114 unsigned Index,
const VarDecl *Var) {
2135 Args.push_back(&LHSArg);
2136 Args.push_back(&RHSArg);
2142 llvm::GlobalValue::InternalLinkage, Name,
2145 Fn->setDoesNotRecurse();
2162 for (
unsigned I = 0,
E = AssignmentOps.size(); I <
E; ++I) {
2163 const auto *DestVar =
2164 cast<VarDecl>(cast<DeclRefExpr>(DestExprs[I])->getDecl());
2167 const auto *SrcVar =
2168 cast<VarDecl>(cast<DeclRefExpr>(SrcExprs[I])->getDecl());
2171 const auto *VD = cast<DeclRefExpr>(CopyprivateVars[I])->getDecl();
2173 CGF.
EmitOMPCopy(
Type, DestAddr, SrcAddr, DestVar, SrcVar, AssignmentOps[I]);
2188 assert(CopyprivateVars.size() == SrcExprs.size() &&
2189 CopyprivateVars.size() == DstExprs.size() &&
2190 CopyprivateVars.size() == AssignmentOps.size());
2202 if (!CopyprivateVars.empty()) {
2205 C.getIntTypeForBitwidth(32, 1);
2206 DidIt = CGF.
CreateMemTemp(KmpInt32Ty,
".omp.copyprivate.did_it");
2211 CommonActionTy Action(
OMPBuilder.getOrCreateRuntimeFunction(
2228 llvm::APInt ArraySize(32, CopyprivateVars.size());
2229 QualType CopyprivateArrayTy =
C.getConstantArrayType(
2234 CGF.
CreateMemTemp(CopyprivateArrayTy,
".omp.copyprivate.cpr_list");
2235 for (
unsigned I = 0,
E = CopyprivateVars.size(); I <
E; ++I) {
2247 SrcExprs, DstExprs, AssignmentOps,
Loc);
2248 llvm::Value *BufSize = CGF.
getTypeSize(CopyprivateArrayTy);
2252 llvm::Value *Args[] = {
2277 CommonActionTy Action(
OMPBuilder.getOrCreateRuntimeFunction(
2292 if (Kind == OMPD_for)
2293 Flags = OMP_IDENT_BARRIER_IMPL_FOR;
2294 else if (Kind == OMPD_sections)
2295 Flags = OMP_IDENT_BARRIER_IMPL_SECTIONS;
2296 else if (Kind == OMPD_single)
2297 Flags = OMP_IDENT_BARRIER_IMPL_SINGLE;
2298 else if (Kind == OMPD_barrier)
2299 Flags = OMP_IDENT_BARRIER_EXPL;
2301 Flags = OMP_IDENT_BARRIER_IMPL;
2313 ScheduleKind = OMPC_SCHEDULE_static;
2315 llvm::APInt ChunkSize(32, 1);
2325 bool ForceSimpleCall) {
2327 auto *OMPRegionInfo =
2330 llvm::OpenMPIRBuilder::InsertPointOrErrorTy AfterIP =
2333 assert(AfterIP &&
"unexpected error creating barrier");
2334 CGF.
Builder.restoreIP(*AfterIP);
2347 if (OMPRegionInfo) {
2348 if (!ForceSimpleCall && OMPRegionInfo->hasCancel()) {
2351 OMPRTL___kmpc_cancel_barrier),
2360 CGF.
Builder.CreateCondBr(Cmp, ExitBB, ContBB);
2377 Expr *ME,
bool IsFatal) {
2380 : llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
2383 llvm::Value *Args[] = {
2385 llvm::ConstantInt::get(
CGM.
Int32Ty, IsFatal ? 2 : 1),
2394 bool Chunked,
bool Ordered) {
2395 switch (ScheduleKind) {
2396 case OMPC_SCHEDULE_static:
2397 return Chunked ? (Ordered ? OMP_ord_static_chunked : OMP_sch_static_chunked)
2398 : (Ordered ? OMP_ord_static : OMP_sch_static);
2399 case OMPC_SCHEDULE_dynamic:
2400 return Ordered ? OMP_ord_dynamic_chunked : OMP_sch_dynamic_chunked;
2401 case OMPC_SCHEDULE_guided:
2402 return Ordered ? OMP_ord_guided_chunked : OMP_sch_guided_chunked;
2403 case OMPC_SCHEDULE_runtime:
2404 return Ordered ? OMP_ord_runtime : OMP_sch_runtime;
2405 case OMPC_SCHEDULE_auto:
2406 return Ordered ? OMP_ord_auto : OMP_sch_auto;
2408 assert(!Chunked &&
"chunk was specified but schedule kind not known");
2409 return Ordered ? OMP_ord_static : OMP_sch_static;
2411 llvm_unreachable(
"Unexpected runtime schedule");
2415static OpenMPSchedType
2418 return Chunked ? OMP_dist_sch_static_chunked : OMP_dist_sch_static;
2422 bool Chunked)
const {
2423 OpenMPSchedType Schedule =
2425 return Schedule == OMP_sch_static;
2431 return Schedule == OMP_dist_sch_static;
2435 bool Chunked)
const {
2436 OpenMPSchedType Schedule =
2438 return Schedule == OMP_sch_static_chunked;
2444 return Schedule == OMP_dist_sch_static_chunked;
2448 OpenMPSchedType Schedule =
2450 assert(Schedule != OMP_sch_static_chunked &&
"cannot be chunked here");
2451 return Schedule != OMP_sch_static;
2459 case OMPC_SCHEDULE_MODIFIER_monotonic:
2460 Modifier = OMP_sch_modifier_monotonic;
2462 case OMPC_SCHEDULE_MODIFIER_nonmonotonic:
2463 Modifier = OMP_sch_modifier_nonmonotonic;
2465 case OMPC_SCHEDULE_MODIFIER_simd:
2466 if (Schedule == OMP_sch_static_chunked)
2467 Schedule = OMP_sch_static_balanced_chunked;
2474 case OMPC_SCHEDULE_MODIFIER_monotonic:
2475 Modifier = OMP_sch_modifier_monotonic;
2477 case OMPC_SCHEDULE_MODIFIER_nonmonotonic:
2478 Modifier = OMP_sch_modifier_nonmonotonic;
2480 case OMPC_SCHEDULE_MODIFIER_simd:
2481 if (Schedule == OMP_sch_static_chunked)
2482 Schedule = OMP_sch_static_balanced_chunked;
2494 if (CGM.
getLangOpts().OpenMP >= 50 && Modifier == 0) {
2495 if (!(Schedule == OMP_sch_static_chunked || Schedule == OMP_sch_static ||
2496 Schedule == OMP_sch_static_balanced_chunked ||
2497 Schedule == OMP_ord_static_chunked || Schedule == OMP_ord_static ||
2498 Schedule == OMP_dist_sch_static_chunked ||
2499 Schedule == OMP_dist_sch_static))
2500 Modifier = OMP_sch_modifier_nonmonotonic;
2502 return Schedule | Modifier;
2512 ScheduleKind.
Schedule, DispatchValues.
Chunk !=
nullptr, Ordered);
2514 (Schedule != OMP_sch_static && Schedule != OMP_sch_static_chunked &&
2515 Schedule != OMP_ord_static && Schedule != OMP_ord_static_chunked &&
2516 Schedule != OMP_sch_static_balanced_chunked));
2523 llvm::Value *Chunk = DispatchValues.
Chunk ? DispatchValues.
Chunk
2524 : CGF.
Builder.getIntN(IVSize, 1);
2525 llvm::Value *Args[] = {
2529 CGM, Schedule, ScheduleKind.
M1, ScheduleKind.
M2)),
2532 CGF.
Builder.getIntN(IVSize, 1),
2549 CodeGenFunction &CGF, llvm::Value *UpdateLocation, llvm::Value *ThreadId,
2550 llvm::FunctionCallee ForStaticInitFunction, OpenMPSchedType Schedule,
2557 assert(Schedule == OMP_sch_static || Schedule == OMP_sch_static_chunked ||
2558 Schedule == OMP_sch_static_balanced_chunked ||
2559 Schedule == OMP_ord_static || Schedule == OMP_ord_static_chunked ||
2560 Schedule == OMP_dist_sch_static ||
2561 Schedule == OMP_dist_sch_static_chunked);
2568 llvm::Value *Chunk = Values.
Chunk;
2569 if (Chunk ==
nullptr) {
2570 assert((Schedule == OMP_sch_static || Schedule == OMP_ord_static ||
2571 Schedule == OMP_dist_sch_static) &&
2572 "expected static non-chunked schedule");
2576 assert((Schedule == OMP_sch_static_chunked ||
2577 Schedule == OMP_sch_static_balanced_chunked ||
2578 Schedule == OMP_ord_static_chunked ||
2579 Schedule == OMP_dist_sch_static_chunked) &&
2580 "expected static chunked schedule");
2582 llvm::Value *Args[] = {
2605 "Expected loop-based or sections-based directive.");
2608 ? OMP_IDENT_WORK_LOOP
2609 : OMP_IDENT_WORK_SECTIONS);
2611 llvm::FunctionCallee StaticInitFunction =
2616 ScheduleNum, ScheduleKind.
M1, ScheduleKind.
M2, Values);
2623 OpenMPSchedType ScheduleNum =
2625 llvm::Value *UpdatedLocation =
2628 llvm::FunctionCallee StaticInitFunction;
2629 bool isGPUDistribute =
2632 StaticInitFunction =
OMPBuilder.createForStaticInitFunction(
2643 assert((DKind == OMPD_distribute || DKind == OMPD_for ||
2644 DKind == OMPD_sections) &&
2645 "Expected distribute, for, or sections directive kind");
2649 llvm::Value *Args[] = {
2652 (DKind == OMPD_target_teams_loop)
2653 ? OMP_IDENT_WORK_DISTRIBUTE
2655 ? OMP_IDENT_WORK_LOOP
2656 : OMP_IDENT_WORK_SECTIONS),
2664 CGM.
getModule(), OMPRTL___kmpc_distribute_static_fini),
2693 llvm::Value *Args[] = {
2701 OMPBuilder.createDispatchNextFunction(IVSize, IVSigned), Args);
2708 llvm::Value *NumThreads,
2713 llvm::Value *Args[] = {
2722 ProcBindKind ProcBind,
2726 assert(ProcBind != OMP_PROC_BIND_unknown &&
"Unsupported proc_bind value.");
2728 llvm::Value *Args[] = {
2730 llvm::ConstantInt::get(
CGM.
IntTy,
unsigned(ProcBind),
true)};
2752enum KmpTaskTFields {
2782 llvm::OpenMPIRBuilder::EmitMetadataErrorReportFunctionTy &&ErrorReportFn =
2783 [
this](llvm::OpenMPIRBuilder::EmitMetadataErrorKind Kind,
2784 const llvm::TargetRegionEntryInfo &EntryInfo) ->
void {
2786 if (Kind != llvm::OpenMPIRBuilder::EMIT_MD_GLOBAL_VAR_LINK_ERROR) {
2790 if (I->getFirst().getUniqueID().getDevice() == EntryInfo.DeviceID &&
2791 I->getFirst().getUniqueID().getFile() == EntryInfo.FileID) {
2793 I->getFirst(), EntryInfo.Line, 1);
2799 case llvm::OpenMPIRBuilder::EMIT_MD_TARGET_REGION_ERROR: {
2802 "%0 is incorrect: either the "
2803 "address or the ID is invalid.");
2806 case llvm::OpenMPIRBuilder::EMIT_MD_DECLARE_TARGET_ERROR: {
2809 "variable %0 is incorrect: the "
2810 "address is invalid.");
2813 case llvm::OpenMPIRBuilder::EMIT_MD_GLOBAL_VAR_LINK_ERROR: {
2816 "Offloading entry for declare target variable is incorrect: the "
2817 "address is invalid.");
2823 OMPBuilder.createOffloadEntriesAndInfoMetadata(ErrorReportFn);
2830 QualType KmpRoutineEntryTyArgs[] = {KmpInt32Ty,
C.VoidPtrTy};
2833 C.getFunctionType(KmpInt32Ty, KmpRoutineEntryTyArgs, EPI));
2839struct PrivateHelpersTy {
2840 PrivateHelpersTy(
const Expr *OriginalRef,
const VarDecl *Original,
2842 : OriginalRef(OriginalRef), Original(Original), PrivateCopy(PrivateCopy),
2843 PrivateElemInit(PrivateElemInit) {}
2844 PrivateHelpersTy(
const VarDecl *Original) : Original(Original) {}
2845 const Expr *OriginalRef =
nullptr;
2846 const VarDecl *Original =
nullptr;
2847 const VarDecl *PrivateCopy =
nullptr;
2848 const VarDecl *PrivateElemInit =
nullptr;
2849 bool isLocalPrivate()
const {
2850 return !OriginalRef && !PrivateCopy && !PrivateElemInit;
2853typedef std::pair<
CharUnits , PrivateHelpersTy> PrivateDataTy;
2858 if (!CVD->
hasAttr<OMPAllocateDeclAttr>())
2860 const auto *AA = CVD->
getAttr<OMPAllocateDeclAttr>();
2862 return !(AA->getAllocatorType() == OMPAllocateDeclAttr::OMPDefaultMemAlloc &&
2863 !AA->getAllocator());
2868 if (!Privates.empty()) {
2873 RecordDecl *RD =
C.buildImplicitRecord(
".kmp_privates.t");
2875 for (
const auto &Pair : Privates) {
2876 const VarDecl *VD = Pair.second.Original;
2880 if (Pair.second.isLocalPrivate()) {
2903 QualType KmpRoutineEntryPointerQTy) {
2923 QualType KmpCmplrdataTy =
C.getRecordType(UD);
2924 RecordDecl *RD =
C.buildImplicitRecord(
"kmp_task_t");
2954 RecordDecl *RD =
C.buildImplicitRecord(
"kmp_task_t_with_privates");
2974static llvm::Function *
2977 QualType KmpTaskTWithPrivatesPtrQTy,
2979 QualType SharedsPtrTy, llvm::Function *TaskFunction,
2980 llvm::Value *TaskPrivatesMap) {
2988 Args.push_back(&GtidArg);
2989 Args.push_back(&TaskTypeArg);
2990 const auto &TaskEntryFnInfo =
2992 llvm::FunctionType *TaskEntryTy =
2995 auto *TaskEntry = llvm::Function::Create(
2996 TaskEntryTy, llvm::GlobalValue::InternalLinkage, Name, &CGM.
getModule());
2998 TaskEntry->setDoesNotRecurse();
3013 const auto *KmpTaskTWithPrivatesQTyRD =
3014 cast<RecordDecl>(KmpTaskTWithPrivatesQTy->
getAsTagDecl());
3017 const auto *KmpTaskTQTyRD = cast<RecordDecl>(KmpTaskTQTy->
getAsTagDecl());
3018 auto PartIdFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTPartId);
3020 llvm::Value *PartidParam = PartIdLVal.
getPointer(CGF);
3022 auto SharedsFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTShareds);
3028 auto PrivatesFI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin(), 1);
3029 llvm::Value *PrivatesParam;
3030 if (PrivatesFI != KmpTaskTWithPrivatesQTyRD->field_end()) {
3035 PrivatesParam = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
3038 llvm::Value *CommonArgs[] = {
3039 GtidParam, PartidParam, PrivatesParam, TaskPrivatesMap,
3045 std::end(CommonArgs));
3047 auto LBFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound);
3050 auto UBFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound);
3053 auto StFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTStride);
3056 auto LIFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLastIter);
3059 auto RFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTReductions);
3062 CallArgs.push_back(LBParam);
3063 CallArgs.push_back(UBParam);
3064 CallArgs.push_back(StParam);
3065 CallArgs.push_back(LIParam);
3066 CallArgs.push_back(RParam);
3068 CallArgs.push_back(SharedsParam);
3081 QualType KmpTaskTWithPrivatesPtrQTy,
3082 QualType KmpTaskTWithPrivatesQTy) {
3090 Args.push_back(&GtidArg);
3091 Args.push_back(&TaskTypeArg);
3092 const auto &DestructorFnInfo =
3094 llvm::FunctionType *DestructorFnTy =
3098 auto *DestructorFn =
3099 llvm::Function::Create(DestructorFnTy, llvm::GlobalValue::InternalLinkage,
3103 DestructorFn->setDoesNotRecurse();
3111 const auto *KmpTaskTWithPrivatesQTyRD =
3112 cast<RecordDecl>(KmpTaskTWithPrivatesQTy->
getAsTagDecl());
3113 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin());
3115 for (
const auto *Field :
3116 cast<RecordDecl>(FI->getType()->getAsTagDecl())->fields()) {
3118 Field->getType().isDestructedType()) {
3124 return DestructorFn;
3144 C,
nullptr,
Loc,
nullptr,
3145 C.getPointerType(PrivatesQTy).withConst().withRestrict(),
3147 Args.push_back(&TaskPrivatesArg);
3148 llvm::DenseMap<CanonicalDeclPtr<const VarDecl>,
unsigned> PrivateVarsPos;
3149 unsigned Counter = 1;
3150 for (
const Expr *
E :
Data.PrivateVars) {
3152 C,
nullptr,
Loc,
nullptr,
3153 C.getPointerType(
C.getPointerType(
E->
getType()))
3157 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(
E)->getDecl());
3158 PrivateVarsPos[VD] = Counter;
3161 for (
const Expr *
E :
Data.FirstprivateVars) {
3163 C,
nullptr,
Loc,
nullptr,
3164 C.getPointerType(
C.getPointerType(
E->
getType()))
3168 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(
E)->getDecl());
3169 PrivateVarsPos[VD] = Counter;
3172 for (
const Expr *
E :
Data.LastprivateVars) {
3174 C,
nullptr,
Loc,
nullptr,
3175 C.getPointerType(
C.getPointerType(
E->
getType()))
3179 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(
E)->getDecl());
3180 PrivateVarsPos[VD] = Counter;
3186 Ty =
C.getPointerType(Ty);
3188 Ty =
C.getPointerType(Ty);
3190 C,
nullptr,
Loc,
nullptr,
3191 C.getPointerType(
C.getPointerType(Ty)).withConst().withRestrict(),
3193 PrivateVarsPos[VD] = Counter;
3196 const auto &TaskPrivatesMapFnInfo =
3198 llvm::FunctionType *TaskPrivatesMapTy =
3202 auto *TaskPrivatesMap = llvm::Function::Create(
3203 TaskPrivatesMapTy, llvm::GlobalValue::InternalLinkage, Name,
3206 TaskPrivatesMapFnInfo);
3208 TaskPrivatesMap->removeFnAttr(llvm::Attribute::NoInline);
3209 TaskPrivatesMap->removeFnAttr(llvm::Attribute::OptimizeNone);
3210 TaskPrivatesMap->addFnAttr(llvm::Attribute::AlwaysInline);
3214 TaskPrivatesMapFnInfo, Args,
Loc,
Loc);
3220 const auto *PrivatesQTyRD = cast<RecordDecl>(PrivatesQTy->
getAsTagDecl());
3222 for (
const FieldDecl *Field : PrivatesQTyRD->fields()) {
3224 const VarDecl *VD = Args[PrivateVarsPos[Privates[Counter].second.Original]];
3233 return TaskPrivatesMap;
3245 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->
field_begin());
3251 CodeGenFunction::CGCapturedStmtInfo CapturesInfo(CS);
3259 if ((!IsTargetTask && !
Data.FirstprivateVars.empty() && ForDup) ||
3260 (IsTargetTask && KmpTaskSharedsPtr.
isValid())) {
3267 FI = cast<RecordDecl>(FI->getType()->getAsTagDecl())->field_begin();
3268 for (
const PrivateDataTy &Pair : Privates) {
3270 if (Pair.second.isLocalPrivate()) {
3274 const VarDecl *VD = Pair.second.PrivateCopy;
3276 if (
Init && (!ForDup || (isa<CXXConstructExpr>(
Init) &&
3279 if (
const VarDecl *Elem = Pair.second.PrivateElemInit) {
3280 const VarDecl *OriginalVD = Pair.second.Original;
3285 const FieldDecl *SharedField = CapturesInfo.lookup(OriginalVD);
3286 if (IsTargetTask && !SharedField) {
3287 assert(isa<ImplicitParamDecl>(OriginalVD) &&
3290 ->getNumParams() == 0 &&
3291 isa<TranslationUnitDecl>(
3293 ->getDeclContext()) &&
3294 "Expected artificial target data variable.");
3297 }
else if (ForDup) {
3301 C.getDeclAlign(OriginalVD)),
3305 Pair.second.Original->getCanonicalDecl()) > 0 ||
3307 SharedRefLValue = CGF.
EmitLValue(Pair.second.OriginalRef);
3310 InlinedOpenMPRegionRAII Region(
3313 SharedRefLValue = CGF.
EmitLValue(Pair.second.OriginalRef);
3325 [&CGF, Elem,
Init, &CapturesInfo](
Address DestElement,
3328 CodeGenFunction::OMPPrivateScope InitScope(CGF);
3329 InitScope.addPrivate(Elem, SrcElement);
3330 (void)InitScope.Privatize();
3332 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(
3333 CGF, &CapturesInfo);
3334 CGF.EmitAnyExprToMem(Init, DestElement,
3335 Init->getType().getQualifiers(),
3340 CodeGenFunction::OMPPrivateScope InitScope(CGF);
3341 InitScope.addPrivate(Elem, SharedRefLValue.
getAddress());
3342 (void)InitScope.Privatize();
3343 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CapturesInfo);
3358 bool InitRequired =
false;
3359 for (
const PrivateDataTy &Pair : Privates) {
3360 if (Pair.second.isLocalPrivate())
3362 const VarDecl *VD = Pair.second.PrivateCopy;
3364 InitRequired = InitRequired || (isa_and_nonnull<CXXConstructExpr>(
Init) &&
3369 return InitRequired;
3386 QualType KmpTaskTWithPrivatesPtrQTy,
3394 KmpTaskTWithPrivatesPtrQTy,
3397 KmpTaskTWithPrivatesPtrQTy,
3401 Args.push_back(&DstArg);
3402 Args.push_back(&SrcArg);
3403 Args.push_back(&LastprivArg);
3404 const auto &TaskDupFnInfo =
3408 auto *TaskDup = llvm::Function::Create(
3409 TaskDupTy, llvm::GlobalValue::InternalLinkage, Name, &CGM.
getModule());
3411 TaskDup->setDoesNotRecurse();
3421 auto LIFI = std::next(KmpTaskTQTyRD->
field_begin(), KmpTaskTLastIter);
3423 TDBase, *KmpTaskTWithPrivatesQTyRD->
field_begin());
3431 assert(!Privates.empty());
3433 if (!
Data.FirstprivateVars.empty()) {
3438 TDBase, *KmpTaskTWithPrivatesQTyRD->
field_begin());
3447 SharedsTy, SharedsPtrTy,
Data, Privates,
true);
3457 for (
const PrivateDataTy &
P : Privates) {
3458 if (
P.second.isLocalPrivate())
3460 QualType Ty =
P.second.Original->getType().getNonReferenceType();
3469class OMPIteratorGeneratorScope final
3470 :
public CodeGenFunction::OMPPrivateScope {
3475 OMPIteratorGeneratorScope() =
delete;
3476 OMPIteratorGeneratorScope(OMPIteratorGeneratorScope &) =
delete;
3484 for (
unsigned I = 0, End =
E->numOfIterators(); I < End; ++I) {
3486 const auto *VD = cast<VarDecl>(
E->getIteratorDecl(I));
3495 for (
unsigned I = 0, End =
E->numOfIterators(); I < End; ++I) {
3504 CodeGenFunction::JumpDest &ContDest =
3506 CodeGenFunction::JumpDest &ExitDest =
3509 llvm::Value *N = Uppers[I];
3517 ? CGF.
Builder.CreateICmpSLT(CVal, N)
3518 : CGF.
Builder.CreateICmpULT(CVal, N);
3520 CGF.
Builder.CreateCondBr(Cmp, BodyBB, ExitDest.getBlock());
3527 ~OMPIteratorGeneratorScope() {
3530 for (
unsigned I =
E->numOfIterators(); I > 0; --I) {
3537 CGF.
EmitBlock(ExitDests[I - 1].getBlock(), I == 1);
3543static std::pair<llvm::Value *, llvm::Value *>
3545 const auto *OASE = dyn_cast<OMPArrayShapingExpr>(
E);
3548 const Expr *
Base = OASE->getBase();
3553 llvm::Value *SizeVal;
3556 SizeVal = CGF.
getTypeSize(OASE->getBase()->getType()->getPointeeType());
3557 for (
const Expr *SE : OASE->getDimensions()) {
3561 SizeVal = CGF.
Builder.CreateNUWMul(SizeVal, Sz);
3563 }
else if (
const auto *ASE =
3567 llvm::Value *UpAddr = CGF.
Builder.CreateConstGEP1_32(
3570 llvm::Value *LowIntPtr = CGF.
Builder.CreatePtrToInt(Addr, CGF.
SizeTy);
3571 llvm::Value *UpIntPtr = CGF.
Builder.CreatePtrToInt(UpAddr, CGF.
SizeTy);
3572 SizeVal = CGF.
Builder.CreateNUWSub(UpIntPtr, LowIntPtr);
3576 return std::make_pair(Addr, SizeVal);
3581 QualType FlagsTy =
C.getIntTypeForBitwidth(32,
false);
3582 if (KmpTaskAffinityInfoTy.
isNull()) {
3584 C.buildImplicitRecord(
"kmp_task_affinity_info_t");
3590 KmpTaskAffinityInfoTy =
C.getRecordType(KmpAffinityInfoRD);
3597 llvm::Function *TaskFunction,
QualType SharedsTy,
3602 const auto *I =
Data.PrivateCopies.begin();
3603 for (
const Expr *
E :
Data.PrivateVars) {
3604 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(
E)->getDecl());
3605 Privates.emplace_back(
3607 PrivateHelpersTy(
E, VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()),
3611 I =
Data.FirstprivateCopies.begin();
3612 const auto *IElemInitRef =
Data.FirstprivateInits.begin();
3613 for (
const Expr *
E :
Data.FirstprivateVars) {
3614 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(
E)->getDecl());
3615 Privates.emplace_back(
3618 E, VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()),
3619 cast<VarDecl>(cast<DeclRefExpr>(*IElemInitRef)->getDecl())));
3623 I =
Data.LastprivateCopies.begin();
3624 for (
const Expr *
E :
Data.LastprivateVars) {
3625 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(
E)->getDecl());
3626 Privates.emplace_back(
3628 PrivateHelpersTy(
E, VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()),
3636 Privates.emplace_back(
C.getDeclAlign(VD), PrivateHelpersTy(VD));
3638 llvm::stable_sort(Privates,
3639 [](
const PrivateDataTy &L,
const PrivateDataTy &R) {
3640 return L.first > R.first;
3642 QualType KmpInt32Ty =
C.getIntTypeForBitwidth(32, 1);
3653 assert((
D.getDirectiveKind() == OMPD_task ||
3656 "Expected taskloop, task or target directive");
3665 const RecordDecl *KmpTaskTWithPrivatesQTyRD =
3667 QualType KmpTaskTWithPrivatesQTy =
C.getRecordType(KmpTaskTWithPrivatesQTyRD);
3668 QualType KmpTaskTWithPrivatesPtrQTy =
3669 C.getPointerType(KmpTaskTWithPrivatesQTy);
3670 llvm::Type *KmpTaskTWithPrivatesPtrTy = CGF.
Builder.getPtrTy(0);
3671 llvm::Value *KmpTaskTWithPrivatesTySize =
3673 QualType SharedsPtrTy =
C.getPointerType(SharedsTy);
3676 llvm::Value *TaskPrivatesMap =
nullptr;
3677 llvm::Type *TaskPrivatesMapTy =
3678 std::next(TaskFunction->arg_begin(), 3)->getType();
3679 if (!Privates.empty()) {
3680 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->
field_begin());
3684 TaskPrivatesMap, TaskPrivatesMapTy);
3686 TaskPrivatesMap = llvm::ConstantPointerNull::get(
3687 cast<llvm::PointerType>(TaskPrivatesMapTy));
3692 CGM,
Loc,
D.getDirectiveKind(), KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy,
3693 KmpTaskTWithPrivatesQTy,
KmpTaskTQTy, SharedsPtrTy, TaskFunction,
3705 DestructorsFlag = 0x8,
3706 PriorityFlag = 0x20,
3707 DetachableFlag = 0x40,
3709 unsigned Flags =
Data.Tied ? TiedFlag : 0;
3710 bool NeedsCleanup =
false;
3711 if (!Privates.empty()) {
3715 Flags = Flags | DestructorsFlag;
3717 if (
Data.Priority.getInt())
3718 Flags = Flags | PriorityFlag;
3720 Flags = Flags | DetachableFlag;
3721 llvm::Value *TaskFlags =
3722 Data.Final.getPointer()
3723 ? CGF.
Builder.CreateSelect(
Data.Final.getPointer(),
3724 CGF.
Builder.getInt32(FinalFlag),
3726 : CGF.
Builder.getInt32(
Data.Final.getInt() ? FinalFlag : 0);
3727 TaskFlags = CGF.
Builder.CreateOr(TaskFlags, CGF.
Builder.getInt32(Flags));
3728 llvm::Value *SharedsSize =
CGM.
getSize(
C.getTypeSizeInChars(SharedsTy));
3733 llvm::Value *NewTask;
3740 llvm::Value *DeviceID;
3745 DeviceID = CGF.
Builder.getInt64(OMP_DEVICEID_UNDEF);
3746 AllocArgs.push_back(DeviceID);
3767 llvm::Value *Tid =
getThreadID(CGF, DC->getBeginLoc());
3768 Tid = CGF.
Builder.CreateIntCast(Tid, CGF.
IntTy,
false);
3771 CGM.
getModule(), OMPRTL___kmpc_task_allow_completion_event),
3772 {Loc, Tid, NewTask});
3783 llvm::Value *NumOfElements =
nullptr;
3784 unsigned NumAffinities = 0;
3786 if (
const Expr *Modifier =
C->getModifier()) {
3787 const auto *IE = cast<OMPIteratorExpr>(Modifier->IgnoreParenImpCasts());
3788 for (
unsigned I = 0,
E = IE->numOfIterators(); I <
E; ++I) {
3792 NumOfElements ? CGF.
Builder.CreateNUWMul(NumOfElements, Sz) : Sz;
3795 NumAffinities +=
C->varlist_size();
3800 enum RTLAffinityInfoFieldsTy { BaseAddr, Len, Flags };
3802 QualType KmpTaskAffinityInfoArrayTy;
3803 if (NumOfElements) {
3804 NumOfElements = CGF.
Builder.CreateNUWAdd(
3805 llvm::ConstantInt::get(CGF.
SizeTy, NumAffinities), NumOfElements);
3808 C.getIntTypeForBitwidth(
C.getTypeSize(
C.getSizeType()), 0),
3812 KmpTaskAffinityInfoArrayTy =
C.getVariableArrayType(
3820 NumOfElements = CGF.
Builder.CreateIntCast(NumOfElements, CGF.
Int32Ty,
3823 KmpTaskAffinityInfoArrayTy =
C.getConstantArrayType(
3825 llvm::APInt(
C.getTypeSize(
C.getSizeType()), NumAffinities),
nullptr,
3828 CGF.
CreateMemTemp(KmpTaskAffinityInfoArrayTy,
".affs.arr.addr");
3830 NumOfElements = llvm::ConstantInt::get(
CGM.
Int32Ty, NumAffinities,
3837 bool HasIterator =
false;
3839 if (
C->getModifier()) {
3843 for (
const Expr *
E :
C->varlist()) {
3852 Base, *std::next(KmpAffinityInfoRD->field_begin(), BaseAddr));
3857 Base, *std::next(KmpAffinityInfoRD->field_begin(), Len));
3871 const Expr *Modifier =
C->getModifier();
3874 OMPIteratorGeneratorScope IteratorScope(
3876 for (
const Expr *
E :
C->varlist()) {
3886 Base, *std::next(KmpAffinityInfoRD->field_begin(), BaseAddr));
3891 Base, *std::next(KmpAffinityInfoRD->field_begin(), Len));
3893 Idx = CGF.
Builder.CreateNUWAdd(
3894 Idx, llvm::ConstantInt::get(Idx->getType(), 1));
3909 CGM.
getModule(), OMPRTL___kmpc_omp_reg_task_with_affinity),
3910 {LocRef, GTid, NewTask, NumOfElements, AffinListPtr});
3912 llvm::Value *NewTaskNewTaskTTy =
3914 NewTask, KmpTaskTWithPrivatesPtrTy);
3916 KmpTaskTWithPrivatesQTy);
3927 *std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTShareds)),
3936 if (!Privates.empty()) {
3938 SharedsTy, SharedsPtrTy,
Data, Privates,
3943 CGM,
Loc,
D, KmpTaskTWithPrivatesPtrQTy, KmpTaskTWithPrivatesQTyRD,
3944 KmpTaskTQTyRD, SharedsTy, SharedsPtrTy,
Data, Privates,
3945 !
Data.LastprivateVars.empty());
3949 enum {
Priority = 0, Destructors = 1 };
3951 auto FI = std::next(KmpTaskTQTyRD->field_begin(), Data1);
3953 (*FI)->getType()->getAsUnionType()->getDecl();
3956 CGM,
Loc, KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy,
3957 KmpTaskTWithPrivatesQTy);
3960 Data1LV, *std::next(KmpCmplrdataUD->
field_begin(), Destructors));
3966 if (
Data.Priority.getInt()) {
3968 TDBase, *std::next(KmpTaskTQTyRD->field_begin(), Data2));
3973 Result.NewTask = NewTask;
3974 Result.TaskEntry = TaskEntry;
3975 Result.NewTaskNewTaskTTy = NewTaskNewTaskTTy;
3977 Result.KmpTaskTQTyRD = KmpTaskTQTyRD;
3983 RTLDependenceKindTy DepKind;
3985 case OMPC_DEPEND_in:
3986 DepKind = RTLDependenceKindTy::DepIn;
3989 case OMPC_DEPEND_out:
3990 case OMPC_DEPEND_inout:
3991 DepKind = RTLDependenceKindTy::DepInOut;
3993 case OMPC_DEPEND_mutexinoutset:
3994 DepKind = RTLDependenceKindTy::DepMutexInOutSet;
3996 case OMPC_DEPEND_inoutset:
3997 DepKind = RTLDependenceKindTy::DepInOutSet;
3999 case OMPC_DEPEND_outallmemory:
4000 DepKind = RTLDependenceKindTy::DepOmpAllMem;
4002 case OMPC_DEPEND_source:
4003 case OMPC_DEPEND_sink:
4004 case OMPC_DEPEND_depobj:
4005 case OMPC_DEPEND_inoutallmemory:
4007 llvm_unreachable(
"Unknown task dependence type");
4015 FlagsTy =
C.getIntTypeForBitwidth(
C.getTypeSize(
C.BoolTy),
false);
4016 if (KmpDependInfoTy.
isNull()) {
4017 RecordDecl *KmpDependInfoRD =
C.buildImplicitRecord(
"kmp_depend_info");
4023 KmpDependInfoTy =
C.getRecordType(KmpDependInfoRD);
4027std::pair<llvm::Value *, LValue>
4041 CGF,
Base.getAddress(),
4042 llvm::ConstantInt::get(CGF.
IntPtrTy, -1,
true));
4049 static_cast<unsigned int>(RTLDependInfoFields::BaseAddr)));
4051 return std::make_pair(NumDeps,
Base);
4055 llvm::PointerUnion<unsigned *, LValue *> Pos,
4066 OMPIteratorGeneratorScope IteratorScope(
4067 CGF, cast_or_null<OMPIteratorExpr>(
4068 Data.IteratorExpr ?
Data.IteratorExpr->IgnoreParenImpCasts()
4079 Addr = llvm::ConstantInt::get(CGF.
IntPtrTy, 0);
4080 Size = llvm::ConstantInt::get(CGF.
SizeTy, 0);
4083 if (
unsigned *
P = Pos.dyn_cast<
unsigned *>()) {
4087 assert(
E &&
"Expected a non-null expression");
4088 LValue &PosLVal = *cast<LValue *>(Pos);
4097 static_cast<unsigned int>(RTLDependInfoFields::BaseAddr)));
4102 static_cast<unsigned int>(RTLDependInfoFields::Len)));
4109 static_cast<unsigned int>(RTLDependInfoFields::Flags)));
4111 llvm::ConstantInt::get(LLVMFlagsTy,
static_cast<unsigned int>(DepKind)),
4113 if (
unsigned *
P = Pos.dyn_cast<
unsigned *>()) {
4116 LValue &PosLVal = *cast<LValue *>(Pos);
4118 Idx = CGF.
Builder.CreateNUWAdd(Idx,
4119 llvm::ConstantInt::get(Idx->getType(), 1));
4128 assert(
Data.DepKind == OMPC_DEPEND_depobj &&
4129 "Expected depobj dependency kind.");
4134 OMPIteratorGeneratorScope IteratorScope(
4135 CGF, cast_or_null<OMPIteratorExpr>(
4136 Data.IteratorExpr ?
Data.IteratorExpr->IgnoreParenImpCasts()
4139 llvm::Value *NumDeps;
4142 std::tie(NumDeps,
Base) =
4146 C.getUIntPtrType());
4150 llvm::Value *Add = CGF.
Builder.CreateNUWAdd(PrevVal, NumDeps);
4152 SizeLVals.push_back(NumLVal);
4155 for (
unsigned I = 0,
E = SizeLVals.size(); I <
E; ++I) {
4158 Sizes.push_back(Size);
4168 assert(
Data.DepKind == OMPC_DEPEND_depobj &&
4169 "Expected depobj dependency kind.");
4172 OMPIteratorGeneratorScope IteratorScope(
4173 CGF, cast_or_null<OMPIteratorExpr>(
4174 Data.IteratorExpr ?
Data.IteratorExpr->IgnoreParenImpCasts()
4176 for (
unsigned I = 0, End =
Data.DepExprs.size(); I < End; ++I) {
4178 llvm::Value *NumDeps;
4181 std::tie(NumDeps,
Base) =
4185 llvm::Value *Size = CGF.
Builder.CreateNUWMul(
4194 llvm::Value *Add = CGF.
Builder.CreateNUWAdd(Pos, NumDeps);
4204 return D.DepExprs.empty();
4210 llvm::Value *NumOfElements =
nullptr;
4211 unsigned NumDependencies = std::accumulate(
4212 Dependencies.begin(), Dependencies.end(), 0,
4214 return D.DepKind == OMPC_DEPEND_depobj
4216 : (V + (D.IteratorExpr ? 0 : D.DepExprs.size()));
4220 bool HasDepobjDeps =
false;
4221 bool HasRegularWithIterators =
false;
4222 llvm::Value *NumOfDepobjElements = llvm::ConstantInt::get(CGF.
IntPtrTy, 0);
4223 llvm::Value *NumOfRegularWithIterators =
4224 llvm::ConstantInt::get(CGF.
IntPtrTy, 0);
4228 if (
D.DepKind == OMPC_DEPEND_depobj) {
4231 for (llvm::Value *Size : Sizes) {
4232 NumOfDepobjElements =
4233 CGF.
Builder.CreateNUWAdd(NumOfDepobjElements, Size);
4235 HasDepobjDeps =
true;
4240 if (
const auto *IE = cast_or_null<OMPIteratorExpr>(
D.IteratorExpr)) {
4241 llvm::Value *ClauseIteratorSpace =
4242 llvm::ConstantInt::get(CGF.
IntPtrTy, 1);
4243 for (
unsigned I = 0,
E = IE->numOfIterators(); I <
E; ++I) {
4246 ClauseIteratorSpace = CGF.
Builder.CreateNUWMul(Sz, ClauseIteratorSpace);
4248 llvm::Value *NumClauseDeps = CGF.
Builder.CreateNUWMul(
4249 ClauseIteratorSpace,
4250 llvm::ConstantInt::get(CGF.
IntPtrTy,
D.DepExprs.size()));
4251 NumOfRegularWithIterators =
4252 CGF.
Builder.CreateNUWAdd(NumOfRegularWithIterators, NumClauseDeps);
4253 HasRegularWithIterators =
true;
4259 if (HasDepobjDeps || HasRegularWithIterators) {
4260 NumOfElements = llvm::ConstantInt::get(
CGM.
IntPtrTy, NumDependencies,
4262 if (HasDepobjDeps) {
4264 CGF.
Builder.CreateNUWAdd(NumOfDepobjElements, NumOfElements);
4266 if (HasRegularWithIterators) {
4268 CGF.
Builder.CreateNUWAdd(NumOfRegularWithIterators, NumOfElements);
4271 Loc,
C.getIntTypeForBitwidth(64, 0),
4275 KmpDependInfoArrayTy =
4284 NumOfElements = CGF.
Builder.CreateIntCast(NumOfElements, CGF.
Int32Ty,
4287 KmpDependInfoArrayTy =
C.getConstantArrayType(
4293 NumOfElements = llvm::ConstantInt::get(
CGM.
Int32Ty, NumDependencies,
4297 for (
unsigned I = 0, End = Dependencies.size(); I < End; ++I) {
4298 if (Dependencies[I].DepKind == OMPC_DEPEND_depobj ||
4299 Dependencies[I].IteratorExpr)
4306 CGF.
CreateMemTemp(
C.getSizeType(),
"dep.counter.addr"),
C.getSizeType());
4308 for (
unsigned I = 0, End = Dependencies.size(); I < End; ++I) {
4309 if (Dependencies[I].DepKind == OMPC_DEPEND_depobj ||
4310 !Dependencies[I].IteratorExpr)
4316 if (HasDepobjDeps) {
4317 for (
unsigned I = 0, End = Dependencies.size(); I < End; ++I) {
4318 if (Dependencies[I].DepKind != OMPC_DEPEND_depobj)
4326 return std::make_pair(NumOfElements, DependenciesArray);
4337 unsigned NumDependencies = Dependencies.
DepExprs.size();
4348 llvm::Value *NumDepsVal;
4350 if (
const auto *IE =
4351 cast_or_null<OMPIteratorExpr>(Dependencies.
IteratorExpr)) {
4352 NumDepsVal = llvm::ConstantInt::get(CGF.
SizeTy, 1);
4353 for (
unsigned I = 0,
E = IE->numOfIterators(); I <
E; ++I) {
4356 NumDepsVal = CGF.
Builder.CreateNUWMul(NumDepsVal, Sz);
4358 Size = CGF.
Builder.CreateNUWAdd(llvm::ConstantInt::get(CGF.
SizeTy, 1),
4362 llvm::Value *RecSize =
CGM.
getSize(SizeInBytes);
4363 Size = CGF.
Builder.CreateNUWMul(Size, RecSize);
4367 QualType KmpDependInfoArrayTy =
C.getConstantArrayType(
4370 CharUnits Sz =
C.getTypeSizeInChars(KmpDependInfoArrayTy);
4372 NumDepsVal = llvm::ConstantInt::get(CGF.
IntPtrTy, NumDependencies);
4377 llvm::Value *Allocator = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
4378 llvm::Value *Args[] = {ThreadID, Size, Allocator};
4383 Args,
".dep.arr.addr");
4386 Addr, CGF.
Builder.getPtrTy(0));
4387 DependenciesArray =
Address(Addr, KmpDependInfoLlvmTy, Align);
4394 static_cast<unsigned int>(RTLDependInfoFields::BaseAddr)));
4396 llvm::PointerUnion<unsigned *, LValue *> Pos;
4413 return DependenciesArray;
4429 llvm::ConstantInt::get(CGF.
IntPtrTy, -1,
true));
4434 llvm::Value *Allocator = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
4435 llvm::Value *Args[] = {ThreadID, DepObjAddr, Allocator};
4452 llvm::Value *NumDeps;
4459 Begin.emitRawPointer(CGF), NumDeps);
4463 llvm::BasicBlock *EntryBB = CGF.
Builder.GetInsertBlock();
4465 llvm::PHINode *ElementPHI =
4466 CGF.
Builder.CreatePHI(
Begin.getType(), 2,
"omp.elementPast");
4467 ElementPHI->addIncoming(
Begin.emitRawPointer(CGF), EntryBB);
4470 Base.getTBAAInfo());
4475 static_cast<unsigned int>(RTLDependInfoFields::Flags)));
4477 llvm::ConstantInt::get(LLVMFlagsTy,
static_cast<unsigned int>(DepKind)),
4481 llvm::Value *ElementNext =
4484 ElementPHI->addIncoming(ElementNext, CGF.
Builder.GetInsertBlock());
4485 llvm::Value *IsEmpty =
4486 CGF.
Builder.CreateICmpEQ(ElementNext, End,
"omp.isempty");
4487 CGF.
Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
4494 llvm::Function *TaskFunction,
4503 llvm::Value *NewTask =
Result.NewTask;
4504 llvm::Function *TaskEntry =
Result.TaskEntry;
4505 llvm::Value *NewTaskNewTaskTTy =
Result.NewTaskNewTaskTTy;
4510 llvm::Value *NumOfElements;
4511 std::tie(NumOfElements, DependenciesArray) =
4522 llvm::Value *TaskArgs[] = { UpLoc, ThreadID, NewTask };
4523 llvm::Value *DepTaskArgs[7];
4524 if (!
Data.Dependences.empty()) {
4525 DepTaskArgs[0] = UpLoc;
4526 DepTaskArgs[1] = ThreadID;
4527 DepTaskArgs[2] = NewTask;
4528 DepTaskArgs[3] = NumOfElements;
4530 DepTaskArgs[5] = CGF.
Builder.getInt32(0);
4531 DepTaskArgs[6] = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
4533 auto &&ThenCodeGen = [
this, &
Data, TDBase, KmpTaskTQTyRD, &TaskArgs,
4536 auto PartIdFI = std::next(KmpTaskTQTyRD->
field_begin(), KmpTaskTPartId);
4540 if (!
Data.Dependences.empty()) {
4553 Region->emitUntiedSwitch(CGF);
4556 llvm::Value *DepWaitTaskArgs[7];
4557 if (!
Data.Dependences.empty()) {
4558 DepWaitTaskArgs[0] = UpLoc;
4559 DepWaitTaskArgs[1] = ThreadID;
4560 DepWaitTaskArgs[2] = NumOfElements;
4562 DepWaitTaskArgs[4] = CGF.
Builder.getInt32(0);
4563 DepWaitTaskArgs[5] = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
4564 DepWaitTaskArgs[6] =
4565 llvm::ConstantInt::get(CGF.
Int32Ty,
Data.HasNowaitClause);
4568 auto &&ElseCodeGen = [
this, &M, &TaskArgs, ThreadID, NewTaskNewTaskTTy,
4569 TaskEntry, &
Data, &DepWaitTaskArgs,
4576 if (!
Data.Dependences.empty())
4578 M, OMPRTL___kmpc_omp_taskwait_deps_51),
4581 auto &&CodeGen = [TaskEntry, ThreadID, NewTaskNewTaskTTy,
4584 llvm::Value *OutlinedFnArgs[] = {ThreadID, NewTaskNewTaskTTy};
4585 CGF.CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF,
Loc, TaskEntry,
4594 CommonActionTy Action(
OMPBuilder.getOrCreateRuntimeFunction(
4595 M, OMPRTL___kmpc_omp_task_begin_if0),
4598 M, OMPRTL___kmpc_omp_task_complete_if0),
4614 llvm::Function *TaskFunction,
4634 IfVal = llvm::ConstantInt::getSigned(CGF.
IntTy, 1);
4639 *std::next(
Result.KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound));
4641 cast<VarDecl>(cast<DeclRefExpr>(
D.getLowerBoundVariable())->getDecl());
4646 *std::next(
Result.KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound));
4648 cast<VarDecl>(cast<DeclRefExpr>(
D.getUpperBoundVariable())->getDecl());
4653 *std::next(
Result.KmpTaskTQTyRD->field_begin(), KmpTaskTStride));
4655 cast<VarDecl>(cast<DeclRefExpr>(
D.getStrideVariable())->getDecl());
4661 *std::next(
Result.KmpTaskTQTyRD->field_begin(), KmpTaskTReductions));
4662 if (
Data.Reductions) {
4668 enum { NoSchedule = 0, Grainsize = 1, NumTasks = 2 };
4677 llvm::ConstantInt::getSigned(
4679 llvm::ConstantInt::getSigned(
4681 ?
Data.Schedule.getInt() ? NumTasks : Grainsize
4683 Data.Schedule.getPointer()
4686 : llvm::ConstantInt::get(CGF.
Int64Ty, 0)};
4687 if (
Data.HasModifier)
4688 TaskArgs.push_back(llvm::ConstantInt::get(CGF.
Int32Ty, 1));
4690 TaskArgs.push_back(
Result.TaskDupFn
4693 : llvm::ConstantPointerNull::get(CGF.
VoidPtrTy));
4696 ? OMPRTL___kmpc_taskloop_5
4697 : OMPRTL___kmpc_taskloop),
4714 const Expr *,
const Expr *)> &RedOpGen,
4715 const Expr *XExpr =
nullptr,
const Expr *EExpr =
nullptr,
4716 const Expr *UpExpr =
nullptr) {
4724 llvm::Value *NumElements = CGF.
emitArrayLength(ArrayTy, ElementTy, LHSAddr);
4729 llvm::Value *LHSEnd =
4734 llvm::Value *IsEmpty =
4735 CGF.
Builder.CreateICmpEQ(LHSBegin, LHSEnd,
"omp.arraycpy.isempty");
4736 CGF.
Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
4739 llvm::BasicBlock *EntryBB = CGF.
Builder.GetInsertBlock();
4744 llvm::PHINode *RHSElementPHI = CGF.
Builder.CreatePHI(
4745 RHSBegin->getType(), 2,
"omp.arraycpy.srcElementPast");
4746 RHSElementPHI->addIncoming(RHSBegin, EntryBB);
4751 llvm::PHINode *LHSElementPHI = CGF.
Builder.CreatePHI(
4752 LHSBegin->getType(), 2,
"omp.arraycpy.destElementPast");
4753 LHSElementPHI->addIncoming(LHSBegin, EntryBB);
4759 CodeGenFunction::OMPPrivateScope
Scope(CGF);
4760 Scope.addPrivate(LHSVar, LHSElementCurrent);
4761 Scope.addPrivate(RHSVar, RHSElementCurrent);
4763 RedOpGen(CGF, XExpr, EExpr, UpExpr);
4764 Scope.ForceCleanup();
4767 llvm::Value *LHSElementNext = CGF.
Builder.CreateConstGEP1_32(
4769 "omp.arraycpy.dest.element");
4770 llvm::Value *RHSElementNext = CGF.
Builder.CreateConstGEP1_32(
4772 "omp.arraycpy.src.element");
4775 CGF.
Builder.CreateICmpEQ(LHSElementNext, LHSEnd,
"omp.arraycpy.done");
4776 CGF.
Builder.CreateCondBr(Done, DoneBB, BodyBB);
4777 LHSElementPHI->addIncoming(LHSElementNext, CGF.
Builder.GetInsertBlock());
4778 RHSElementPHI->addIncoming(RHSElementNext, CGF.
Builder.GetInsertBlock());
4788 const Expr *ReductionOp) {
4789 if (
const auto *CE = dyn_cast<CallExpr>(ReductionOp))
4790 if (
const auto *OVE = dyn_cast<OpaqueValueExpr>(CE->getCallee()))
4791 if (
const auto *DRE =
4792 dyn_cast<DeclRefExpr>(OVE->getSourceExpr()->IgnoreImpCasts()))
4793 if (
const auto *DRD =
4794 dyn_cast<OMPDeclareReductionDecl>(DRE->getDecl())) {
4795 std::pair<llvm::Function *, llvm::Function *>
Reduction =
4798 CodeGenFunction::OpaqueValueMapping Map(CGF, OVE,
Func);
4817 Args.push_back(&LHSArg);
4818 Args.push_back(&RHSArg);
4823 llvm::GlobalValue::InternalLinkage, Name,
4826 Fn->setDoesNotRecurse();
4845 const auto *IPriv = Privates.begin();
4847 for (
unsigned I = 0,
E = ReductionOps.size(); I <
E; ++I, ++IPriv, ++Idx) {
4848 const auto *RHSVar =
4849 cast<VarDecl>(cast<DeclRefExpr>(RHSExprs[I])->getDecl());
4851 const auto *LHSVar =
4852 cast<VarDecl>(cast<DeclRefExpr>(LHSExprs[I])->getDecl());
4854 QualType PrivTy = (*IPriv)->getType();
4862 const auto *OVE = cast<OpaqueValueExpr>(VLA->
getSizeExpr());
4869 IPriv = Privates.begin();
4870 const auto *ILHS = LHSExprs.begin();
4871 const auto *IRHS = RHSExprs.begin();
4872 for (
const Expr *
E : ReductionOps) {
4873 if ((*IPriv)->getType()->isArrayType()) {
4875 const auto *LHSVar = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
4876 const auto *RHSVar = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
4878 CGF, (*IPriv)->getType(), LHSVar, RHSVar,
4880 emitReductionCombiner(CGF, E);
4890 Scope.ForceCleanup();
4896 const Expr *ReductionOp,
4897 const Expr *PrivateRef,
4902 const auto *LHSVar = cast<VarDecl>(LHS->
getDecl());
4903 const auto *RHSVar = cast<VarDecl>(RHS->
getDecl());
4905 CGF, PrivateRef->
getType(), LHSVar, RHSVar,
4907 emitReductionCombiner(CGF, ReductionOp);
4924 bool WithNowait = Options.WithNowait;
4925 bool SimpleReduction = Options.SimpleReduction;
4964 if (SimpleReduction) {
4966 const auto *IPriv = Privates.begin();
4967 const auto *ILHS = LHSExprs.begin();
4968 const auto *IRHS = RHSExprs.begin();
4969 for (
const Expr *
E : ReductionOps) {
4971 cast<DeclRefExpr>(*IRHS));
4981 auto Size = RHSExprs.size();
4982 for (
const Expr *
E : Privates) {
4987 llvm::APInt ArraySize(32, Size);
4988 QualType ReductionArrayTy =
C.getConstantArrayType(
4992 CGF.
CreateMemTemp(ReductionArrayTy,
".omp.reduction.red_list");
4993 const auto *IPriv = Privates.begin();
4995 for (
unsigned I = 0,
E = RHSExprs.size(); I <
E; ++I, ++IPriv, ++Idx) {
5001 if ((*IPriv)->getType()->isVariablyModifiedType()) {
5005 llvm::Value *Size = CGF.
Builder.CreateIntCast(
5018 Privates, LHSExprs, RHSExprs, ReductionOps);
5021 std::string Name =
getName({
"reduction"});
5028 llvm::Value *ReductionArrayTySize = CGF.
getTypeSize(ReductionArrayTy);
5031 llvm::Value *Args[] = {
5034 CGF.
Builder.getInt32(RHSExprs.size()),
5035 ReductionArrayTySize,
5043 WithNowait ? OMPRTL___kmpc_reduce_nowait : OMPRTL___kmpc_reduce),
5047 llvm::BasicBlock *DefaultBB = CGF.
createBasicBlock(
".omp.reduction.default");
5048 llvm::SwitchInst *SwInst =
5049 CGF.
Builder.CreateSwitch(Res, DefaultBB, 2);
5058 SwInst->addCase(CGF.
Builder.getInt32(1), Case1BB);
5062 llvm::Value *EndArgs[] = {
5067 auto &&CodeGen = [Privates, LHSExprs, RHSExprs, ReductionOps](
5070 const auto *IPriv = Privates.begin();
5071 const auto *ILHS = LHSExprs.begin();
5072 const auto *IRHS = RHSExprs.begin();
5073 for (
const Expr *
E : ReductionOps) {
5075 cast<DeclRefExpr>(*IRHS));
5082 CommonActionTy Action(
5085 CGM.
getModule(), WithNowait ? OMPRTL___kmpc_end_reduce_nowait
5086 : OMPRTL___kmpc_end_reduce),
5099 SwInst->addCase(CGF.
Builder.getInt32(2), Case2BB);
5102 auto &&AtomicCodeGen = [
Loc, Privates, LHSExprs, RHSExprs, ReductionOps](
5104 const auto *ILHS = LHSExprs.begin();
5105 const auto *IRHS = RHSExprs.begin();
5106 const auto *IPriv = Privates.begin();
5107 for (
const Expr *
E : ReductionOps) {
5108 const Expr *XExpr =
nullptr;
5109 const Expr *EExpr =
nullptr;
5110 const Expr *UpExpr =
nullptr;
5112 if (
const auto *BO = dyn_cast<BinaryOperator>(
E)) {
5113 if (BO->getOpcode() == BO_Assign) {
5114 XExpr = BO->getLHS();
5115 UpExpr = BO->getRHS();
5119 const Expr *RHSExpr = UpExpr;
5122 if (
const auto *ACO = dyn_cast<AbstractConditionalOperator>(
5126 RHSExpr = ACO->getCond();
5128 if (
const auto *BORHS =
5130 EExpr = BORHS->getRHS();
5131 BO = BORHS->getOpcode();
5135 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
5136 auto &&AtomicRedGen = [BO, VD,
5138 const Expr *EExpr,
const Expr *UpExpr) {
5139 LValue X = CGF.EmitLValue(XExpr);
5142 E = CGF.EmitAnyExpr(EExpr);
5143 CGF.EmitOMPAtomicSimpleUpdateExpr(
5145 llvm::AtomicOrdering::Monotonic,
Loc,
5146 [&CGF, UpExpr, VD,
Loc](
RValue XRValue) {
5148 Address LHSTemp = CGF.CreateMemTemp(VD->getType());
5149 CGF.emitOMPSimpleStore(
5150 CGF.MakeAddrLValue(LHSTemp, VD->
getType()), XRValue,
5151 VD->getType().getNonReferenceType(),
Loc);
5154 return CGF.EmitAnyExpr(UpExpr);
5157 if ((*IPriv)->getType()->isArrayType()) {
5159 const auto *RHSVar =
5160 cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
5162 AtomicRedGen, XExpr, EExpr, UpExpr);
5165 AtomicRedGen(CGF, XExpr, EExpr, UpExpr);
5172 std::string Name = RT.
getName({
"atomic_reduction"});
5181 if ((*IPriv)->getType()->isArrayType()) {
5182 const auto *LHSVar =
5183 cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
5184 const auto *RHSVar =
5185 cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
5189 CritRedGen(CGF,
nullptr,
nullptr,
nullptr);
5200 llvm::Value *EndArgs[] = {
5205 CommonActionTy Action(
nullptr, {},
5224 llvm::raw_svector_ostream Out(Buffer);
5228 D = cast<VarDecl>(cast<DeclRefExpr>(Ref)->getDecl());
5232 Out << Prefix << Name <<
"_"
5234 return std::string(Out.str());
5256 Args.emplace_back(&Param);
5257 Args.emplace_back(&ParamOrig);
5258 const auto &FnInfo =
5262 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
5265 Fn->setDoesNotRecurse();
5272 llvm::Value *Size =
nullptr;
5315 const Expr *ReductionOp,
5317 const Expr *PrivateRef) {
5319 const auto *LHSVD = cast<VarDecl>(cast<DeclRefExpr>(LHS)->getDecl());
5320 const auto *RHSVD = cast<VarDecl>(cast<DeclRefExpr>(RHS)->getDecl());
5326 Args.emplace_back(&ParamInOut);
5327 Args.emplace_back(&ParamIn);
5328 const auto &FnInfo =
5332 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
5335 Fn->setDoesNotRecurse();
5338 llvm::Value *Size =
nullptr;
5352 CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
5353 PrivateScope.addPrivate(
5359 C.getPointerType(LHSVD->getType())->castAs<
PointerType>()));
5360 PrivateScope.addPrivate(
5366 C.getPointerType(RHSVD->getType())->castAs<
PointerType>()));
5367 PrivateScope.Privatize();
5372 CGF, ReductionOp, PrivateRef, cast<DeclRefExpr>(LHS),
5373 cast<DeclRefExpr>(RHS));
5395 Args.emplace_back(&Param);
5396 const auto &FnInfo =
5400 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
5403 Fn->setDoesNotRecurse();
5408 llvm::Value *Size =
nullptr;
5443 RecordDecl *RD =
C.buildImplicitRecord(
"kmp_taskred_input_t");
5452 C, RD,
C.getIntTypeForBitwidth(32,
false));
5455 unsigned Size =
Data.ReductionVars.size();
5456 llvm::APInt ArraySize(64, Size);
5458 C.getConstantArrayType(RDType, ArraySize,
nullptr,
5463 Data.ReductionCopies,
Data.ReductionOps);
5464 for (
unsigned Cnt = 0; Cnt < Size; ++Cnt) {
5466 llvm::Value *Idxs[] = {llvm::ConstantInt::get(
CGM.
SizeTy, 0),
5467 llvm::ConstantInt::get(
CGM.
SizeTy, Cnt)};
5483 llvm::Value *SizeValInChars;
5484 llvm::Value *SizeVal;
5485 std::tie(SizeValInChars, SizeVal) = RCG.
getSizes(Cnt);
5491 bool DelayedCreation = !!SizeVal;
5503 llvm::Value *FiniAddr =
5504 Fini ? Fini : llvm::ConstantPointerNull::get(
CGM.
VoidPtrTy);
5509 CGM,
Loc, RCG, Cnt,
Data.ReductionOps[Cnt], LHSExprs[Cnt],
5510 RHSExprs[Cnt],
Data.ReductionCopies[Cnt]);
5514 if (DelayedCreation) {
5516 llvm::ConstantInt::get(
CGM.
Int32Ty, 1,
true),
5521 if (
Data.IsReductionWithTaskMod) {
5527 llvm::Value *Args[] = {
5529 llvm::ConstantInt::get(
CGM.
IntTy,
Data.IsWorksharingReduction ? 1 : 0,
5531 llvm::ConstantInt::get(
CGM.
IntTy, Size,
true),
5540 llvm::Value *Args[] = {
5543 llvm::ConstantInt::get(
CGM.
IntTy, Size,
true),
5553 bool IsWorksharingReduction) {
5559 llvm::Value *Args[] = {IdentTLoc, GTid,
5561 IsWorksharingReduction ? 1 : 0,
5565 CGM.
getModule(), OMPRTL___kmpc_task_reduction_modifier_fini),
5588 llvm::Value *ReductionsPtr,
5601 CGM.
getModule(), OMPRTL___kmpc_task_reduction_get_th_data),
5619 llvm::Value *NumOfElements;
5620 std::tie(NumOfElements, DependenciesArray) =
5622 if (!
Data.Dependences.empty()) {
5623 llvm::Value *DepWaitTaskArgs[7];
5624 DepWaitTaskArgs[0] = UpLoc;
5625 DepWaitTaskArgs[1] = ThreadID;
5626 DepWaitTaskArgs[2] = NumOfElements;
5628 DepWaitTaskArgs[4] = CGF.
Builder.getInt32(0);
5629 DepWaitTaskArgs[5] = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
5630 DepWaitTaskArgs[6] =
5631 llvm::ConstantInt::get(CGF.
Int32Ty,
Data.HasNowaitClause);
5640 M, OMPRTL___kmpc_omp_taskwait_deps_51),
5647 llvm::Value *Args[] = {UpLoc, ThreadID};
5650 OMPBuilder.getOrCreateRuntimeFunction(M, OMPRTL___kmpc_omp_taskwait),
5655 if (
auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.
CapturedStmtInfo))
5656 Region->emitUntiedSwitch(CGF);
5665 InlinedOpenMPRegionRAII Region(CGF, CodeGen, InnerKind, HasCancel,
5666 InnerKind != OMPD_critical &&
5667 InnerKind != OMPD_master &&
5668 InnerKind != OMPD_masked);
5683 RTCancelKind CancelKind = CancelNoreq;
5684 if (CancelRegion == OMPD_parallel)
5685 CancelKind = CancelParallel;
5686 else if (CancelRegion == OMPD_for)
5687 CancelKind = CancelLoop;
5688 else if (CancelRegion == OMPD_sections)
5689 CancelKind = CancelSections;
5691 assert(CancelRegion == OMPD_taskgroup);
5692 CancelKind = CancelTaskgroup;
5704 if (
auto *OMPRegionInfo =
5708 if (CancelRegion == OMPD_taskgroup || OMPRegionInfo->hasCancel()) {
5709 llvm::Value *Args[] = {
5724 CGF.
Builder.CreateCondBr(Cmp, ExitBB, ContBB);
5726 if (CancelRegion == OMPD_parallel)
5745 if (
auto *OMPRegionInfo =
5747 auto &&ThenGen = [
this, &M,
Loc, CancelRegion,
5750 llvm::Value *Args[] = {
5754 llvm::Value *
Result = CGF.EmitRuntimeCall(
5755 OMPBuilder.getOrCreateRuntimeFunction(M, OMPRTL___kmpc_cancel), Args);
5760 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(
".cancel.exit");
5761 llvm::BasicBlock *ContBB = CGF.createBasicBlock(
".cancel.continue");
5762 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(
Result);
5763 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB);
5764 CGF.EmitBlock(ExitBB);
5765 if (CancelRegion == OMPD_parallel)
5769 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind());
5770 CGF.EmitBranchThroughCleanup(CancelDest);
5771 CGF.EmitBlock(ContBB,
true);
5789 OMPUsesAllocatorsActionTy(
5790 ArrayRef<std::pair<const Expr *, const Expr *>> Allocators)
5791 : Allocators(Allocators) {}
5795 for (
const auto &AllocatorData : Allocators) {
5797 CGF, AllocatorData.first, AllocatorData.second);
5803 for (
const auto &AllocatorData : Allocators) {
5805 AllocatorData.first);
5813 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
5815 assert(!ParentName.empty() &&
"Invalid target entry parent name!");
5819 for (
unsigned I = 0,
E =
C->getNumberOfAllocators(); I <
E; ++I) {
5821 if (!
D.AllocatorTraits)
5823 Allocators.emplace_back(
D.Allocator,
D.AllocatorTraits);
5826 OMPUsesAllocatorsActionTy UsesAllocatorAction(Allocators);
5829 IsOffloadEntry, CodeGen);
5833 const Expr *Allocator,
5834 const Expr *AllocatorTraits) {
5835 llvm::Value *ThreadId =
getThreadID(CGF, Allocator->getExprLoc());
5836 ThreadId = CGF.
Builder.CreateIntCast(ThreadId, CGF.
IntTy,
true);
5838 llvm::Value *MemSpaceHandle = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
5839 llvm::Value *NumTraits = llvm::ConstantInt::get(
5840 CGF.
IntTy, cast<ConstantArrayType>(
5843 .getLimitedValue());
5852 llvm::Value *AllocatorVal =
5855 {ThreadId, MemSpaceHandle, NumTraits, Traits});
5858 cast<DeclRefExpr>(Allocator->IgnoreParenImpCasts())->getDecl()));
5862 Allocator->getType(), Allocator->getExprLoc());
5867 const Expr *Allocator) {
5868 llvm::Value *ThreadId =
getThreadID(CGF, Allocator->getExprLoc());
5869 ThreadId = CGF.
Builder.CreateIntCast(ThreadId, CGF.
IntTy,
true);
5871 llvm::Value *AllocatorVal =
5875 Allocator->getExprLoc());
5878 OMPRTL___kmpc_destroy_allocator),
5879 {ThreadId, AllocatorVal});
5884 int32_t &MinThreadsVal, int32_t &MaxThreadsVal, int32_t &MinTeamsVal,
5885 int32_t &MaxTeamsVal) {
5892 for (
auto *A :
C->getAttrs()) {
5893 int32_t AttrMinThreadsVal = 1, AttrMaxThreadsVal = -1;
5894 int32_t AttrMinBlocksVal = 1, AttrMaxBlocksVal = -1;
5895 if (
auto *
Attr = dyn_cast<CUDALaunchBoundsAttr>(A))
5897 &AttrMinBlocksVal, &AttrMaxBlocksVal);
5898 else if (
auto *
Attr = dyn_cast<AMDGPUFlatWorkGroupSizeAttr>(A))
5900 nullptr,
Attr,
nullptr, &AttrMinThreadsVal,
5901 &AttrMaxThreadsVal);
5905 MinThreadsVal = std::max(MinThreadsVal, AttrMinThreadsVal);
5906 if (AttrMaxThreadsVal > 0)
5907 MaxThreadsVal = MaxThreadsVal > 0
5908 ? std::min(MaxThreadsVal, AttrMaxThreadsVal)
5909 : AttrMaxThreadsVal;
5910 MinTeamsVal = std::max(MinTeamsVal, AttrMinBlocksVal);
5911 if (AttrMaxBlocksVal > 0)
5912 MaxTeamsVal = MaxTeamsVal > 0 ? std::min(MaxTeamsVal, AttrMaxBlocksVal)
5920 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
5923 llvm::TargetRegionEntryInfo EntryInfo =
5927 llvm::OpenMPIRBuilder::FunctionGenCallback &&GenerateOutlinedFunction =
5928 [&CGF, &
D, &CodeGen](StringRef EntryFnName) {
5931 CGOpenMPTargetRegionInfo CGInfo(CS, CodeGen, EntryFnName);
5936 llvm::Error Err =
OMPBuilder.emitTargetRegionFunction(
5937 EntryInfo, GenerateOutlinedFunction, IsOffloadEntry, OutlinedFn,
5939 assert(!Err &&
"unexpected error creating target region");
5947 for (
auto *A :
C->getAttrs()) {
5948 if (
auto *
Attr = dyn_cast<AMDGPUWavesPerEUAttr>(A))
5967 while (
const auto *
C = dyn_cast_or_null<CompoundStmt>(Child)) {
5969 for (
const Stmt *S :
C->body()) {
5970 if (
const auto *
E = dyn_cast<Expr>(S)) {
5975 if (isa<AsmStmt>(S) || isa<NullStmt>(S) || isa<OMPFlushDirective>(S) ||
5976 isa<OMPBarrierDirective>(S) || isa<OMPTaskyieldDirective>(S))
5979 if (
const auto *DS = dyn_cast<DeclStmt>(S)) {
5980 if (llvm::all_of(DS->decls(), [](
const Decl *
D) {
5981 if (isa<EmptyDecl>(D) || isa<DeclContext>(D) ||
5982 isa<TypeDecl>(D) || isa<PragmaCommentDecl>(D) ||
5983 isa<PragmaDetectMismatchDecl>(D) || isa<UsingDecl>(D) ||
5984 isa<UsingDirectiveDecl>(D) ||
5985 isa<OMPDeclareReductionDecl>(D) ||
5986 isa<OMPThreadPrivateDecl>(D) || isa<OMPAllocateDecl>(D))
5988 const auto *VD = dyn_cast<VarDecl>(D);
5991 return VD->hasGlobalStorage() || !VD->isUsed();
6001 Child = Child->IgnoreContainers();
6008 int32_t &MaxTeamsVal) {
6012 "Expected target-based executable directive.");
6013 switch (DirectiveKind) {
6015 const auto *CS =
D.getInnermostCapturedStmt();
6018 const Stmt *ChildStmt =
6020 if (
const auto *NestedDir =
6021 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) {
6030 MinTeamsVal = MaxTeamsVal = Constant->getExtValue();
6033 MinTeamsVal = MaxTeamsVal = 0;
6036 MinTeamsVal = MaxTeamsVal = 1;
6040 MinTeamsVal = MaxTeamsVal = -1;
6043 case OMPD_target_teams_loop:
6044 case OMPD_target_teams:
6045 case OMPD_target_teams_distribute:
6046 case OMPD_target_teams_distribute_simd:
6047 case OMPD_target_teams_distribute_parallel_for:
6048 case OMPD_target_teams_distribute_parallel_for_simd: {
6050 const Expr *NumTeams =
6054 MinTeamsVal = MaxTeamsVal = Constant->getExtValue();
6057 MinTeamsVal = MaxTeamsVal = 0;
6060 case OMPD_target_parallel:
6061 case OMPD_target_parallel_for:
6062 case OMPD_target_parallel_for_simd:
6063 case OMPD_target_parallel_loop:
6064 case OMPD_target_simd:
6065 MinTeamsVal = MaxTeamsVal = 1;
6069 case OMPD_parallel_for:
6070 case OMPD_parallel_loop:
6071 case OMPD_parallel_master:
6072 case OMPD_parallel_sections:
6074 case OMPD_parallel_for_simd:
6076 case OMPD_cancellation_point:
6078 case OMPD_threadprivate:
6089 case OMPD_taskyield:
6092 case OMPD_taskgroup:
6098 case OMPD_target_data:
6099 case OMPD_target_exit_data:
6100 case OMPD_target_enter_data:
6101 case OMPD_distribute:
6102 case OMPD_distribute_simd:
6103 case OMPD_distribute_parallel_for:
6104 case OMPD_distribute_parallel_for_simd:
6105 case OMPD_teams_distribute:
6106 case OMPD_teams_distribute_simd:
6107 case OMPD_teams_distribute_parallel_for:
6108 case OMPD_teams_distribute_parallel_for_simd:
6109 case OMPD_target_update:
6110 case OMPD_declare_simd:
6111 case OMPD_declare_variant:
6112 case OMPD_begin_declare_variant:
6113 case OMPD_end_declare_variant:
6114 case OMPD_declare_target:
6115 case OMPD_end_declare_target:
6116 case OMPD_declare_reduction:
6117 case OMPD_declare_mapper:
6119 case OMPD_taskloop_simd:
6120 case OMPD_master_taskloop:
6121 case OMPD_master_taskloop_simd:
6122 case OMPD_parallel_master_taskloop:
6123 case OMPD_parallel_master_taskloop_simd:
6125 case OMPD_metadirective:
6131 llvm_unreachable(
"Unexpected directive kind.");
6137 "Clauses associated with the teams directive expected to be emitted "
6138 "only for the host!");
6140 int32_t MinNT = -1, MaxNT = -1;
6141 const Expr *NumTeams =
6143 if (NumTeams !=
nullptr) {
6146 switch (DirectiveKind) {
6148 const auto *CS =
D.getInnermostCapturedStmt();
6149 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6153 return Bld.CreateIntCast(NumTeamsVal, CGF.
Int32Ty,
6156 case OMPD_target_teams:
6157 case OMPD_target_teams_distribute:
6158 case OMPD_target_teams_distribute_simd:
6159 case OMPD_target_teams_distribute_parallel_for:
6160 case OMPD_target_teams_distribute_parallel_for_simd: {
6164 return Bld.CreateIntCast(NumTeamsVal, CGF.
Int32Ty,
6172 assert(MinNT == MaxNT &&
"Num threads ranges require handling here.");
6173 return llvm::ConstantInt::get(CGF.
Int32Ty, MinNT);
6181 const Expr **
E, int32_t &UpperBound,
6182 bool UpperBoundOnly, llvm::Value **CondVal) {
6185 const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child);
6192 if (CondVal && Dir->hasClausesOfKind<
OMPIfClause>()) {
6193 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6194 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
6196 for (
const auto *
C : Dir->getClausesOfKind<
OMPIfClause>()) {
6197 if (
C->getNameModifier() == OMPD_unknown ||
6198 C->getNameModifier() == OMPD_parallel) {
6213 if (
const auto *PreInit =
6215 for (
const auto *I : PreInit->decls()) {
6216 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
6219 CodeGenFunction::AutoVarEmission Emission =
6232 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6233 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
6234 const auto *NumThreadsClause =
6236 const Expr *NTExpr = NumThreadsClause->getNumThreads();
6237 if (NTExpr->isIntegerConstantExpr(CGF.
getContext()))
6238 if (
auto Constant = NTExpr->getIntegerConstantExpr(CGF.
getContext()))
6241 ? Constant->getZExtValue()
6242 : std::min(UpperBound,
6243 static_cast<int32_t
>(Constant->getZExtValue()));
6246 if (UpperBound == -1)
6250 CodeGenFunction::LexicalScope
Scope(CGF, NTExpr->getSourceRange());
6251 if (
const auto *PreInit =
6252 cast_or_null<DeclStmt>(NumThreadsClause->getPreInitStmt())) {
6253 for (
const auto *I : PreInit->decls()) {
6254 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
6257 CodeGenFunction::AutoVarEmission Emission =
6273 bool UpperBoundOnly, llvm::Value **CondVal,
const Expr **ThreadLimitExpr) {
6274 assert((!CGF.
getLangOpts().OpenMPIsTargetDevice || UpperBoundOnly) &&
6275 "Clauses associated with the teams directive expected to be emitted "
6276 "only for the host!");
6279 "Expected target-based executable directive.");
6281 const Expr *NT =
nullptr;
6282 const Expr **NTPtr = UpperBoundOnly ? nullptr : &NT;
6284 auto CheckForConstExpr = [&](
const Expr *
E,
const Expr **EPtr) {
6287 UpperBound = UpperBound ? Constant->getZExtValue()
6288 : std::min(UpperBound,
6289 int32_t(Constant->getZExtValue()));
6293 if (UpperBound == -1)
6299 auto ReturnSequential = [&]() {
6304 switch (DirectiveKind) {
6307 getNumThreads(CGF, CS, NTPtr, UpperBound, UpperBoundOnly, CondVal);
6313 if (
const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) {
6315 ThreadLimitClause = TLC;
6316 if (ThreadLimitExpr) {
6317 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6321 ThreadLimitClause->getThreadLimit().front()->getSourceRange());
6322 if (
const auto *PreInit =
6323 cast_or_null<DeclStmt>(ThreadLimitClause->getPreInitStmt())) {
6324 for (
const auto *I : PreInit->decls()) {
6325 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
6337 if (ThreadLimitClause)
6338 CheckForConstExpr(ThreadLimitClause->getThreadLimit().front(),
6340 if (
const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) {
6343 CS = Dir->getInnermostCapturedStmt();
6346 Dir = dyn_cast_or_null<OMPExecutableDirective>(Child);
6349 CS = Dir->getInnermostCapturedStmt();
6350 getNumThreads(CGF, CS, NTPtr, UpperBound, UpperBoundOnly, CondVal);
6352 return ReturnSequential();
6356 case OMPD_target_teams: {
6360 CheckForConstExpr(ThreadLimitClause->getThreadLimit().front(),
6364 getNumThreads(CGF, CS, NTPtr, UpperBound, UpperBoundOnly, CondVal);
6367 if (
const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) {
6368 if (Dir->getDirectiveKind() == OMPD_distribute) {
6369 CS = Dir->getInnermostCapturedStmt();
6370 getNumThreads(CGF, CS, NTPtr, UpperBound, UpperBoundOnly, CondVal);
6375 case OMPD_target_teams_distribute:
6379 CheckForConstExpr(ThreadLimitClause->getThreadLimit().front(),
6382 getNumThreads(CGF,
D.getInnermostCapturedStmt(), NTPtr, UpperBound,
6383 UpperBoundOnly, CondVal);
6385 case OMPD_target_teams_loop:
6386 case OMPD_target_parallel_loop:
6387 case OMPD_target_parallel:
6388 case OMPD_target_parallel_for:
6389 case OMPD_target_parallel_for_simd:
6390 case OMPD_target_teams_distribute_parallel_for:
6391 case OMPD_target_teams_distribute_parallel_for_simd: {
6395 if (
C->getNameModifier() == OMPD_unknown ||
6396 C->getNameModifier() == OMPD_parallel) {
6406 return ReturnSequential();
6416 CheckForConstExpr(ThreadLimitClause->getThreadLimit().front(),
6422 CheckForConstExpr(NumThreadsClause->getNumThreads(),
nullptr);
6423 return NumThreadsClause->getNumThreads();
6427 case OMPD_target_teams_distribute_simd:
6428 case OMPD_target_simd:
6429 return ReturnSequential();
6433 llvm_unreachable(
"Unsupported directive kind.");
6438 llvm::Value *NumThreadsVal =
nullptr;
6439 llvm::Value *CondVal =
nullptr;
6440 llvm::Value *ThreadLimitVal =
nullptr;
6441 const Expr *ThreadLimitExpr =
nullptr;
6442 int32_t UpperBound = -1;
6445 CGF,
D, UpperBound,
false, &CondVal,
6449 if (ThreadLimitExpr) {
6452 ThreadLimitVal = CGF.
Builder.CreateIntCast(ThreadLimitVal, CGF.
Int32Ty,
6457 if (UpperBound == 1) {
6458 NumThreadsVal = CGF.
Builder.getInt32(UpperBound);
6461 NumThreadsVal = CGF.
Builder.CreateIntCast(NumThreadsVal, CGF.
Int32Ty,
6463 }
else if (ThreadLimitVal) {
6466 NumThreadsVal = ThreadLimitVal;
6467 ThreadLimitVal =
nullptr;
6470 assert(!ThreadLimitVal &&
"Default not applicable with thread limit value");
6471 NumThreadsVal = CGF.
Builder.getInt32(0);
6478 NumThreadsVal = CGF.
Builder.CreateSelect(CondVal, NumThreadsVal,
6484 if (ThreadLimitVal) {
6485 NumThreadsVal = CGF.
Builder.CreateSelect(
6486 CGF.
Builder.CreateICmpULT(ThreadLimitVal, NumThreadsVal),
6487 ThreadLimitVal, NumThreadsVal);
6490 return NumThreadsVal;
6500class MappableExprsHandler {
6503 static unsigned getFlagMemberOffset() {
6504 unsigned Offset = 0;
6505 for (uint64_t Remain =
6506 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
6507 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF);
6508 !(Remain & 1); Remain = Remain >> 1)
6515 class MappingExprInfo {
6520 const Expr *MapExpr =
nullptr;
6523 MappingExprInfo(
const ValueDecl *MapDecl,
const Expr *MapExpr =
nullptr)
6524 : MapDecl(MapDecl), MapExpr(MapExpr) {}
6526 const ValueDecl *getMapDecl()
const {
return MapDecl; }
6527 const Expr *getMapExpr()
const {
return MapExpr; }
6530 using DeviceInfoTy = llvm::OpenMPIRBuilder::DeviceInfoTy;
6531 using MapBaseValuesArrayTy = llvm::OpenMPIRBuilder::MapValuesArrayTy;
6532 using MapValuesArrayTy = llvm::OpenMPIRBuilder::MapValuesArrayTy;
6533 using MapFlagsArrayTy = llvm::OpenMPIRBuilder::MapFlagsArrayTy;
6534 using MapDimArrayTy = llvm::OpenMPIRBuilder::MapDimArrayTy;
6535 using MapNonContiguousArrayTy =
6536 llvm::OpenMPIRBuilder::MapNonContiguousArrayTy;
6543 struct MapCombinedInfoTy : llvm::OpenMPIRBuilder::MapInfosTy {
6544 MapExprsArrayTy Exprs;
6545 MapValueDeclsArrayTy Mappers;
6546 MapValueDeclsArrayTy DevicePtrDecls;
6549 void append(MapCombinedInfoTy &CurInfo) {
6550 Exprs.append(CurInfo.Exprs.begin(), CurInfo.Exprs.end());
6551 DevicePtrDecls.append(CurInfo.DevicePtrDecls.begin(),
6552 CurInfo.DevicePtrDecls.end());
6553 Mappers.append(CurInfo.Mappers.begin(), CurInfo.Mappers.end());
6554 llvm::OpenMPIRBuilder::MapInfosTy::append(CurInfo);
6562 struct StructRangeInfoTy {
6563 MapCombinedInfoTy PreliminaryMapData;
6564 std::pair<
unsigned ,
Address > LowestElem = {
6566 std::pair<
unsigned ,
Address > HighestElem = {
6570 bool IsArraySection =
false;
6571 bool HasCompleteRecord =
false;
6581 bool ReturnDevicePointer =
false;
6582 bool IsImplicit =
false;
6584 const Expr *VarRef =
nullptr;
6585 bool ForDeviceAddr =
false;
6587 MapInfo() =
default;
6593 bool ReturnDevicePointer,
bool IsImplicit,
6594 const ValueDecl *Mapper =
nullptr,
const Expr *VarRef =
nullptr,
6595 bool ForDeviceAddr =
false)
6596 : Components(Components), MapType(MapType), MapModifiers(MapModifiers),
6597 MotionModifiers(MotionModifiers),
6598 ReturnDevicePointer(ReturnDevicePointer), IsImplicit(IsImplicit),
6599 Mapper(Mapper), VarRef(VarRef), ForDeviceAddr(ForDeviceAddr) {}
6605 struct DeferredDevicePtrEntryTy {
6606 const Expr *IE =
nullptr;
6608 bool ForDeviceAddr =
false;
6610 DeferredDevicePtrEntryTy(
const Expr *IE,
const ValueDecl *VD,
6612 : IE(IE), VD(VD), ForDeviceAddr(ForDeviceAddr) {}
6627 llvm::DenseMap<CanonicalDeclPtr<const VarDecl>,
bool> FirstPrivateDecls;
6644 llvm::DenseMap<const ValueDecl *, const OMPMapClause *> LambdasMap;
6646 llvm::Value *getExprTypeSize(
const Expr *
E)
const {
6650 if (
const auto *OAE = dyn_cast<OMPArrayShapingExpr>(
E)) {
6652 CGF.
getTypeSize(OAE->getBase()->getType()->getPointeeType());
6653 for (
const Expr *SE : OAE->getDimensions()) {
6670 if (
const auto *OAE = dyn_cast<ArraySectionExpr>(
E)) {
6672 OAE->getBase()->IgnoreParenImpCasts())
6678 if (!OAE->getLength() && OAE->getColonLocFirst().isValid() &&
6679 !OAE->getLowerBound())
6682 llvm::Value *ElemSize;
6684 ElemSize = CGF.
getTypeSize(PTy->getPointeeType().getCanonicalType());
6686 const auto *ATy = cast<ArrayType>(BaseTy.
getTypePtr());
6687 assert(ATy &&
"Expecting array type if not a pointer type.");
6688 ElemSize = CGF.
getTypeSize(ATy->getElementType().getCanonicalType());
6693 if (!OAE->getLength() && OAE->getColonLocFirst().isInvalid())
6696 if (
const Expr *LenExpr = OAE->getLength()) {
6700 LenExpr->getExprLoc());
6701 return CGF.
Builder.CreateNUWMul(LengthVal, ElemSize);
6703 assert(!OAE->getLength() && OAE->getColonLocFirst().isValid() &&
6704 OAE->getLowerBound() &&
"expected array_section[lb:].");
6710 OAE->getLowerBound()->getExprLoc());
6711 LBVal = CGF.
Builder.CreateNUWMul(LBVal, ElemSize);
6712 llvm::Value *Cmp = CGF.
Builder.CreateICmpUGT(LengthVal, LBVal);
6713 llvm::Value *TrueVal = CGF.
Builder.CreateNUWSub(LengthVal, LBVal);
6714 LengthVal = CGF.
Builder.CreateSelect(
6715 Cmp, TrueVal, llvm::ConstantInt::get(CGF.
SizeTy, 0));
6725 OpenMPOffloadMappingFlags getMapTypeBits(
6728 bool AddPtrFlag,
bool AddIsTargetParamFlag,
bool IsNonContiguous)
const {
6729 OpenMPOffloadMappingFlags Bits =
6730 IsImplicit ? OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT
6731 : OpenMPOffloadMappingFlags::OMP_MAP_NONE;
6733 case OMPC_MAP_alloc:
6734 case OMPC_MAP_release:
6741 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_TO;
6744 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_FROM;
6746 case OMPC_MAP_tofrom:
6747 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_TO |
6748 OpenMPOffloadMappingFlags::OMP_MAP_FROM;
6750 case OMPC_MAP_delete:
6751 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_DELETE;
6754 llvm_unreachable(
"Unexpected map type!");
6757 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ;
6758 if (AddIsTargetParamFlag)
6759 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM;
6760 if (llvm::is_contained(MapModifiers, OMPC_MAP_MODIFIER_always))
6761 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_ALWAYS;
6762 if (llvm::is_contained(MapModifiers, OMPC_MAP_MODIFIER_close))
6763 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_CLOSE;
6764 if (llvm::is_contained(MapModifiers, OMPC_MAP_MODIFIER_present) ||
6765 llvm::is_contained(MotionModifiers, OMPC_MOTION_MODIFIER_present))
6766 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_PRESENT;
6767 if (llvm::is_contained(MapModifiers, OMPC_MAP_MODIFIER_ompx_hold))
6768 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_OMPX_HOLD;
6769 if (IsNonContiguous)
6770 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_NON_CONTIG;
6776 bool isFinalArraySectionExpression(
const Expr *
E)
const {
6777 const auto *OASE = dyn_cast<ArraySectionExpr>(
E);
6784 if (OASE->getColonLocFirst().isInvalid())
6787 const Expr *Length = OASE->getLength();
6794 OASE->getBase()->IgnoreParenImpCasts())
6796 if (
const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.
getTypePtr()))
6797 return ATy->getSExtSize() != 1;
6806 if (!Length->EvaluateAsInt(Result, CGF.
getContext()))
6809 llvm::APSInt ConstLength = Result.Val.getInt();
6810 return ConstLength.getSExtValue() != 1;
6818 void generateInfoForComponentList(
6822 MapCombinedInfoTy &CombinedInfo,
6823 MapCombinedInfoTy &StructBaseCombinedInfo,
6824 StructRangeInfoTy &PartialStruct,
bool IsFirstComponentList,
6825 bool IsImplicit,
bool GenerateAllInfoForClauses,
6826 const ValueDecl *Mapper =
nullptr,
bool ForDeviceAddr =
false,
6827 const ValueDecl *BaseDecl =
nullptr,
const Expr *MapExpr =
nullptr,
6829 OverlappedElements = {},
6830 bool AreBothBasePtrAndPteeMapped =
false)
const {
7012 bool IsCaptureFirstInfo = IsFirstComponentList;
7016 bool RequiresReference =
false;
7019 auto CI = Components.rbegin();
7020 auto CE = Components.rend();
7025 bool IsExpressionFirstInfo =
true;
7026 bool FirstPointerInComplexData =
false;
7028 const Expr *AssocExpr = I->getAssociatedExpression();
7029 const auto *AE = dyn_cast<ArraySubscriptExpr>(AssocExpr);
7030 const auto *OASE = dyn_cast<ArraySectionExpr>(AssocExpr);
7031 const auto *OAShE = dyn_cast<OMPArrayShapingExpr>(AssocExpr);
7033 if (AreBothBasePtrAndPteeMapped && std::next(I) == CE)
7035 if (isa<MemberExpr>(AssocExpr)) {
7039 }
else if ((AE && isa<CXXThisExpr>(AE->getBase()->IgnoreParenImpCasts())) ||
7041 isa<CXXThisExpr>(OASE->getBase()->IgnoreParenImpCasts()))) {
7044 isa<CXXThisExpr>(OAShE->getBase()->IgnoreParenCasts())) {
7053 if (
const auto *VD =
7054 dyn_cast_or_null<VarDecl>(I->getAssociatedDeclaration())) {
7055 if (std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
7056 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD)) {
7057 if ((*Res == OMPDeclareTargetDeclAttr::MT_Link) ||
7058 ((*Res == OMPDeclareTargetDeclAttr::MT_To ||
7059 *Res == OMPDeclareTargetDeclAttr::MT_Enter) &&
7061 RequiresReference =
true;
7071 I->getAssociatedDeclaration()->getType().getNonReferenceType();
7076 const auto *VD = dyn_cast<VarDecl>(I->getAssociatedDeclaration());
7077 if (!AreBothBasePtrAndPteeMapped &&
7082 FirstPointerInComplexData =
true;
7101 bool ShouldBeMemberOf =
false;
7116 bool IsNonContiguous = CombinedInfo.NonContigInfo.IsNonContiguous;
7117 bool IsPrevMemberReference =
false;
7119 bool IsPartialMapped =
7120 !PartialStruct.PreliminaryMapData.BasePointers.empty();
7127 bool IsMappingWholeStruct =
true;
7128 if (!GenerateAllInfoForClauses) {
7129 IsMappingWholeStruct =
false;
7131 for (
auto TempI = I; TempI != CE; ++TempI) {
7133 dyn_cast<MemberExpr>(TempI->getAssociatedExpression());
7135 IsMappingWholeStruct =
false;
7141 for (; I != CE; ++I) {
7143 if (!EncounteredME) {
7144 EncounteredME = dyn_cast<MemberExpr>(I->getAssociatedExpression());
7147 if (EncounteredME) {
7148 ShouldBeMemberOf =
true;
7151 if (FirstPointerInComplexData) {
7153 ->getAssociatedDeclaration()
7155 .getNonReferenceType();
7157 FirstPointerInComplexData =
false;
7162 auto Next = std::next(I);
7172 bool IsFinalArraySection =
7174 isFinalArraySectionExpression(I->getAssociatedExpression());
7178 const ValueDecl *MapDecl = (I->getAssociatedDeclaration())
7179 ? I->getAssociatedDeclaration()
7181 MapExpr = (I->getAssociatedExpression()) ? I->getAssociatedExpression()
7188 dyn_cast<ArraySectionExpr>(I->getAssociatedExpression());
7190 dyn_cast<OMPArrayShapingExpr>(I->getAssociatedExpression());
7191 const auto *UO = dyn_cast<UnaryOperator>(I->getAssociatedExpression());
7192 const auto *BO = dyn_cast<BinaryOperator>(I->getAssociatedExpression());
7198 I->getAssociatedExpression()->getType()->isAnyPointerType();
7199 bool IsMemberReference = isa<MemberExpr>(I->getAssociatedExpression()) &&
7202 bool IsNonDerefPointer = IsPointer &&
7203 !(UO && UO->getOpcode() != UO_Deref) && !BO &&
7209 if (Next == CE || IsMemberReference || IsNonDerefPointer ||
7210 IsFinalArraySection) {
7213 assert((Next == CE ||
7214 isa<MemberExpr>(Next->getAssociatedExpression()) ||
7215 isa<ArraySubscriptExpr>(Next->getAssociatedExpression()) ||
7216 isa<ArraySectionExpr>(Next->getAssociatedExpression()) ||
7217 isa<OMPArrayShapingExpr>(Next->getAssociatedExpression()) ||
7218 isa<UnaryOperator>(Next->getAssociatedExpression()) ||
7219 isa<BinaryOperator>(Next->getAssociatedExpression())) &&
7220 "Unexpected expression");
7226 const Expr *BaseExpr =
E->getBase();
7246 OAShE->getBase()->getType()->getPointeeType()),
7248 OAShE->getBase()->getType()));
7249 }
else if (IsMemberReference) {
7250 const auto *ME = cast<MemberExpr>(I->getAssociatedExpression());
7251 LValue BaseLVal = EmitMemberExprBase(CGF, ME);
7253 BaseLVal, cast<FieldDecl>(MapDecl))
7266 bool IsMemberPointerOrAddr =
7268 (((IsPointer || ForDeviceAddr) &&
7269 I->getAssociatedExpression() == EncounteredME) ||
7270 (IsPrevMemberReference && !IsPointer) ||
7271 (IsMemberReference && Next != CE &&
7272 !Next->getAssociatedExpression()->getType()->isPointerType()));
7273 if (!OverlappedElements.empty() && Next == CE) {
7275 assert(!PartialStruct.Base.isValid() &&
"The base element is set.");
7276 assert(!IsPointer &&
7277 "Unexpected base element with the pointer type.");
7280 PartialStruct.LowestElem = {0, LowestElem};
7282 I->getAssociatedExpression()->getType());
7287 PartialStruct.HighestElem = {
7288 std::numeric_limits<
decltype(
7289 PartialStruct.HighestElem.first)>
::max(),
7291 PartialStruct.Base = BP;
7292 PartialStruct.LB = LB;
7294 PartialStruct.PreliminaryMapData.BasePointers.empty() &&
7295 "Overlapped elements must be used only once for the variable.");
7296 std::swap(PartialStruct.PreliminaryMapData, CombinedInfo);
7298 OpenMPOffloadMappingFlags Flags =
7299 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF |
7300 getMapTypeBits(MapType, MapModifiers, MotionModifiers, IsImplicit,
7302 false, IsNonContiguous);
7303 llvm::Value *
Size =
nullptr;
7306 Component : OverlappedElements) {
7310 if (
const ValueDecl *VD = MC.getAssociatedDeclaration()) {
7311 const auto *FD = dyn_cast<FieldDecl>(VD);
7312 if (FD && FD->getType()->isLValueReferenceType()) {
7314 cast<MemberExpr>(MC.getAssociatedExpression());
7315 LValue BaseLVal = EmitMemberExprBase(CGF, ME);
7331 assert(Size &&
"Failed to determine structure size");
7332 CombinedInfo.Exprs.emplace_back(MapDecl, MapExpr);
7334 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
7335 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
7337 CombinedInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
7339 CombinedInfo.Types.push_back(Flags);
7340 CombinedInfo.Mappers.push_back(
nullptr);
7341 CombinedInfo.NonContigInfo.Dims.push_back(IsNonContiguous ? DimSize
7345 CombinedInfo.Exprs.emplace_back(MapDecl, MapExpr);
7347 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
7348 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
7354 CombinedInfo.Sizes.push_back(
7356 CombinedInfo.Types.push_back(Flags);
7357 CombinedInfo.Mappers.push_back(
nullptr);
7358 CombinedInfo.NonContigInfo.Dims.push_back(IsNonContiguous ? DimSize
7362 llvm::Value *
Size = getExprTypeSize(I->getAssociatedExpression());
7369 if ((!IsMemberPointerOrAddr && !IsPartialMapped) ||
7371 if (!IsMappingWholeStruct) {
7372 CombinedInfo.Exprs.emplace_back(MapDecl, MapExpr);
7374 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
7375 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
7377 CombinedInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
7379 CombinedInfo.NonContigInfo.Dims.push_back(IsNonContiguous ? DimSize
7382 StructBaseCombinedInfo.Exprs.emplace_back(MapDecl, MapExpr);
7383 StructBaseCombinedInfo.BasePointers.push_back(
7385 StructBaseCombinedInfo.DevicePtrDecls.push_back(
nullptr);
7386 StructBaseCombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
7387 StructBaseCombinedInfo.Pointers.push_back(LB.
emitRawPointer(CGF));
7388 StructBaseCombinedInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
7390 StructBaseCombinedInfo.NonContigInfo.Dims.push_back(
7391 IsNonContiguous ? DimSize : 1);
7395 bool HasMapper = Mapper && Next == CE;
7396 if (!IsMappingWholeStruct)
7397 CombinedInfo.Mappers.push_back(HasMapper ? Mapper :
nullptr);
7399 StructBaseCombinedInfo.Mappers.push_back(HasMapper ? Mapper
7406 OpenMPOffloadMappingFlags Flags =
7407 getMapTypeBits(MapType, MapModifiers, MotionModifiers, IsImplicit,
7408 !IsExpressionFirstInfo || RequiresReference ||
7409 FirstPointerInComplexData || IsMemberReference,
7410 AreBothBasePtrAndPteeMapped ||
7411 (IsCaptureFirstInfo && !RequiresReference),
7414 if (!IsExpressionFirstInfo || IsMemberReference) {
7417 if (IsPointer || (IsMemberReference && Next != CE))
7418 Flags &= ~(OpenMPOffloadMappingFlags::OMP_MAP_TO |
7419 OpenMPOffloadMappingFlags::OMP_MAP_FROM |
7420 OpenMPOffloadMappingFlags::OMP_MAP_ALWAYS |
7421 OpenMPOffloadMappingFlags::OMP_MAP_DELETE |
7422 OpenMPOffloadMappingFlags::OMP_MAP_CLOSE);
7424 if (ShouldBeMemberOf) {
7427 Flags |= OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF;
7430 ShouldBeMemberOf =
false;
7434 if (!IsMappingWholeStruct)
7435 CombinedInfo.Types.push_back(Flags);
7437 StructBaseCombinedInfo.Types.push_back(Flags);
7443 if (EncounteredME) {
7444 const auto *FD = cast<FieldDecl>(EncounteredME->
getMemberDecl());
7445 unsigned FieldIndex = FD->getFieldIndex();
7448 if (!PartialStruct.Base.isValid()) {
7449 PartialStruct.LowestElem = {FieldIndex, LowestElem};
7450 if (IsFinalArraySection) {
7454 PartialStruct.HighestElem = {FieldIndex, HB};
7456 PartialStruct.HighestElem = {FieldIndex, LowestElem};
7458 PartialStruct.Base = BP;
7459 PartialStruct.LB = BP;
7460 }
else if (FieldIndex < PartialStruct.LowestElem.first) {
7461 PartialStruct.LowestElem = {FieldIndex, LowestElem};
7462 }
else if (FieldIndex > PartialStruct.HighestElem.first) {
7463 if (IsFinalArraySection) {
7467 PartialStruct.HighestElem = {FieldIndex, HB};
7469 PartialStruct.HighestElem = {FieldIndex, LowestElem};
7475 if (IsFinalArraySection || IsNonContiguous)
7476 PartialStruct.IsArraySection =
true;
7479 if (IsFinalArraySection)
7484 BP = IsMemberReference ? LowestElem : LB;
7485 if (!IsPartialMapped)
7486 IsExpressionFirstInfo =
false;
7487 IsCaptureFirstInfo =
false;
7488 FirstPointerInComplexData =
false;
7489 IsPrevMemberReference = IsMemberReference;
7490 }
else if (FirstPointerInComplexData) {
7492 ->getAssociatedDeclaration()
7494 .getNonReferenceType();
7496 FirstPointerInComplexData =
false;
7502 PartialStruct.HasCompleteRecord =
true;
7504 if (!IsNonContiguous)
7511 MapValuesArrayTy CurOffsets = {llvm::ConstantInt::get(CGF.
CGM.
Int64Ty, 0)};
7512 MapValuesArrayTy CurCounts = {llvm::ConstantInt::get(CGF.
CGM.
Int64Ty, 1)};
7513 MapValuesArrayTy CurStrides;
7514 MapValuesArrayTy DimSizes{llvm::ConstantInt::get(CGF.
CGM.
Int64Ty, 1)};
7522 const Expr *AssocExpr = Component.getAssociatedExpression();
7523 const auto *OASE = dyn_cast<ArraySectionExpr>(AssocExpr);
7533 assert((VAT || CAT || &Component == &*Components.begin()) &&
7534 "Should be either ConstantArray or VariableArray if not the "
7538 if (CurStrides.empty()) {
7539 const Type *ElementType =
nullptr;
7541 ElementType = CAT->getElementType().getTypePtr();
7543 ElementType = VAT->getElementType().getTypePtr();
7545 assert(&Component == &*Components.begin() &&
7546 "Only expect pointer (non CAT or VAT) when this is the "
7554 if (&Component != &*Components.begin())
7558 CurStrides.push_back(
7559 llvm::ConstantInt::get(CGF.
Int64Ty, ElementTypeSize));
7564 if (DimSizes.size() < Components.size() - 1) {
7567 llvm::ConstantInt::get(CGF.
Int64Ty, CAT->getZExtSize()));
7569 DimSizes.push_back(CGF.
Builder.CreateIntCast(
7576 auto *DI = DimSizes.begin() + 1;
7578 llvm::Value *DimProd =
7579 llvm::ConstantInt::get(CGF.
CGM.
Int64Ty, ElementTypeSize);
7590 const Expr *AssocExpr = Component.getAssociatedExpression();
7592 if (
const auto *AE = dyn_cast<ArraySubscriptExpr>(AssocExpr)) {
7593 llvm::Value *Offset = CGF.
Builder.CreateIntCast(
7596 CurOffsets.push_back(Offset);
7597 CurCounts.push_back(llvm::ConstantInt::get(CGF.
Int64Ty, 1));
7598 CurStrides.push_back(CurStrides.back());
7602 const auto *OASE = dyn_cast<ArraySectionExpr>(AssocExpr);
7608 const Expr *OffsetExpr = OASE->getLowerBound();
7609 llvm::Value *Offset =
nullptr;
7612 Offset = llvm::ConstantInt::get(CGF.
Int64Ty, 0);
7618 CurOffsets.push_back(Offset);
7621 const Expr *CountExpr = OASE->getLength();
7622 llvm::Value *Count =
nullptr;
7628 if (!OASE->getColonLocFirst().isValid() &&
7629 !OASE->getColonLocSecond().isValid()) {
7630 Count = llvm::ConstantInt::get(CGF.
Int64Ty, 1);
7636 const Expr *StrideExpr = OASE->getStride();
7637 llvm::Value *Stride =
7643 Count = CGF.
Builder.CreateUDiv(
7644 CGF.
Builder.CreateNUWSub(*DI, Offset), Stride);
7646 Count = CGF.
Builder.CreateNUWSub(*DI, Offset);
7652 CurCounts.push_back(Count);
7661 const Expr *StrideExpr = OASE->getStride();
7662 llvm::Value *Stride =
7667 DimProd = CGF.
Builder.CreateNUWMul(DimProd, *(DI - 1));
7669 CurStrides.push_back(CGF.
Builder.CreateNUWMul(DimProd, Stride));
7671 CurStrides.push_back(DimProd);
7672 if (DI != DimSizes.end())
7676 CombinedInfo.NonContigInfo.Offsets.push_back(CurOffsets);
7677 CombinedInfo.NonContigInfo.Counts.push_back(CurCounts);
7678 CombinedInfo.NonContigInfo.Strides.push_back(CurStrides);
7684 OpenMPOffloadMappingFlags
7693 return OpenMPOffloadMappingFlags::OMP_MAP_TO |
7694 OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ;
7695 return OpenMPOffloadMappingFlags::OMP_MAP_PRIVATE |
7696 OpenMPOffloadMappingFlags::OMP_MAP_TO;
7699 if (I != LambdasMap.end())
7701 return getMapTypeBits(
7702 I->getSecond()->getMapType(), I->getSecond()->getMapTypeModifiers(),
7703 {}, I->getSecond()->isImplicit(),
7707 return OpenMPOffloadMappingFlags::OMP_MAP_TO |
7708 OpenMPOffloadMappingFlags::OMP_MAP_FROM;
7713 bool AsBase)
const {
7716 llvm::StructType *St =
7719 unsigned NumElements = St->getNumElements();
7721 llvm::PointerUnion<const CXXRecordDecl *, const FieldDecl *>, 4>
7722 RecordLayout(NumElements);
7725 for (
const auto &I : RD->
bases()) {
7740 RecordLayout[FieldIndex] =
Base;
7743 for (
const auto &I : RD->
vbases()) {
7751 if (RecordLayout[FieldIndex])
7753 RecordLayout[FieldIndex] =
Base;
7756 assert(!RD->
isUnion() &&
"Unexpected union.");
7757 for (
const auto *Field : RD->
fields()) {
7760 if (!
Field->isBitField() &&
7763 RecordLayout[FieldIndex] =
Field;
7766 for (
const llvm::PointerUnion<const CXXRecordDecl *, const FieldDecl *>
7767 &
Data : RecordLayout) {
7771 getPlainLayout(
Base, Layout,
true);
7773 Layout.push_back(cast<const FieldDecl *>(
Data));
7782 void generateAllInfoForClauses(
7784 llvm::OpenMPIRBuilder &OMPBuilder,
7791 llvm::MapVector<CanonicalDeclPtr<const Decl>,
7798 [&Info, &SkipVarSet](
7804 bool ReturnDevicePointer,
bool IsImplicit,
const ValueDecl *Mapper,
7805 const Expr *VarRef =
nullptr,
bool ForDeviceAddr =
false) {
7806 if (SkipVarSet.contains(
D))
7808 auto It = Info.try_emplace(
D, Total).first;
7809 It->second[
Kind].emplace_back(
7810 L, MapType, MapModifiers, MotionModifiers, ReturnDevicePointer,
7811 IsImplicit, Mapper, VarRef, ForDeviceAddr);
7814 for (
const auto *
Cl : Clauses) {
7815 const auto *
C = dyn_cast<OMPMapClause>(
Cl);
7819 if (llvm::is_contained(
C->getMapTypeModifiers(),
7820 OMPC_MAP_MODIFIER_present))
7822 else if (
C->getMapType() == OMPC_MAP_alloc)
7824 const auto *EI =
C->getVarRefs().begin();
7825 for (
const auto L :
C->component_lists()) {
7826 const Expr *
E = (
C->getMapLoc().isValid()) ? *EI :
nullptr;
7827 InfoGen(std::get<0>(L),
Kind, std::get<1>(L),
C->getMapType(),
7828 C->getMapTypeModifiers(), {},
7829 false,
C->isImplicit(), std::get<2>(L),
7834 for (
const auto *
Cl : Clauses) {
7835 const auto *
C = dyn_cast<OMPToClause>(
Cl);
7839 if (llvm::is_contained(
C->getMotionModifiers(),
7840 OMPC_MOTION_MODIFIER_present))
7842 const auto *EI =
C->getVarRefs().begin();
7843 for (
const auto L :
C->component_lists()) {
7844 InfoGen(std::get<0>(L),
Kind, std::get<1>(L), OMPC_MAP_to, {},
7845 C->getMotionModifiers(),
false,
7846 C->isImplicit(), std::get<2>(L), *EI);
7850 for (
const auto *
Cl : Clauses) {
7851 const auto *
C = dyn_cast<OMPFromClause>(
Cl);
7855 if (llvm::is_contained(
C->getMotionModifiers(),
7856 OMPC_MOTION_MODIFIER_present))
7858 const auto *EI =
C->getVarRefs().begin();
7859 for (
const auto L :
C->component_lists()) {
7860 InfoGen(std::get<0>(L),
Kind, std::get<1>(L), OMPC_MAP_from, {},
7861 C->getMotionModifiers(),
7862 false,
C->isImplicit(), std::get<2>(L),
7875 llvm::MapVector<CanonicalDeclPtr<const Decl>,
7878 MapCombinedInfoTy UseDeviceDataCombinedInfo;
7880 auto &&UseDeviceDataCombinedInfoGen =
7881 [&UseDeviceDataCombinedInfo](
const ValueDecl *VD, llvm::Value *Ptr,
7883 UseDeviceDataCombinedInfo.Exprs.push_back(VD);
7884 UseDeviceDataCombinedInfo.BasePointers.emplace_back(Ptr);
7885 UseDeviceDataCombinedInfo.DevicePtrDecls.emplace_back(VD);
7886 UseDeviceDataCombinedInfo.DevicePointers.emplace_back(
7887 IsDevAddr ? DeviceInfoTy::Address : DeviceInfoTy::Pointer);
7888 UseDeviceDataCombinedInfo.Pointers.push_back(Ptr);
7889 UseDeviceDataCombinedInfo.Sizes.push_back(
7890 llvm::Constant::getNullValue(CGF.Int64Ty));
7891 UseDeviceDataCombinedInfo.Types.push_back(
7892 OpenMPOffloadMappingFlags::OMP_MAP_RETURN_PARAM);
7893 UseDeviceDataCombinedInfo.Mappers.push_back(
nullptr);
7897 [&DeferredInfo, &UseDeviceDataCombinedInfoGen,
7901 bool IsImplicit,
bool IsDevAddr) {
7905 if (isa<MemberExpr>(IE)) {
7914 false, IsImplicit,
nullptr,
nullptr,
7916 DeferredInfo[
nullptr].emplace_back(IE, VD, IsDevAddr);
7920 if (IE->isGLValue())
7921 Ptr = CGF.EmitLValue(IE).getPointer(CGF);
7923 Ptr = CGF.EmitScalarExpr(IE);
7925 Ptr = CGF.EmitLoadOfScalar(CGF.EmitLValue(IE), IE->getExprLoc());
7927 UseDeviceDataCombinedInfoGen(VD, Ptr, CGF, IsDevAddr);
7932 const Expr *IE,
bool IsDevAddr) ->
bool {
7939 auto It = Info.find(isa<MemberExpr>(IE) ? nullptr : VD);
7940 if (It != Info.end()) {
7942 for (
auto &
Data : It->second) {
7943 auto *CI = llvm::find_if(
Data, [VD](
const MapInfo &MI) {
7944 return MI.Components.back().getAssociatedDeclaration() == VD;
7952 if (CI !=
Data.end()) {
7954 CI->ForDeviceAddr = IsDevAddr;
7955 CI->ReturnDevicePointer =
true;
7959 auto PrevCI = std::next(CI->Components.rbegin());
7960 const auto *VarD = dyn_cast<VarDecl>(VD);
7962 isa<MemberExpr>(IE) ||
7963 !VD->getType().getNonReferenceType()->isPointerType() ||
7964 PrevCI == CI->Components.rend() ||
7965 isa<MemberExpr>(PrevCI->getAssociatedExpression()) || !VarD ||
7966 VarD->hasLocalStorage()) {
7967 CI->ForDeviceAddr = IsDevAddr;
7968 CI->ReturnDevicePointer =
true;
7986 for (
const auto *
Cl : Clauses) {
7987 const auto *
C = dyn_cast<OMPUseDevicePtrClause>(
Cl);
7990 for (
const auto L :
C->component_lists()) {
7993 assert(!Components.empty() &&
7994 "Not expecting empty list of components!");
7995 const ValueDecl *VD = Components.back().getAssociatedDeclaration();
7997 const Expr *IE = Components.back().getAssociatedExpression();
7998 if (IsMapInfoExist(CGF, VD, IE,
false))
8000 MapInfoGen(CGF, IE, VD, Components,
C->isImplicit(),
8005 llvm::SmallDenseSet<CanonicalDeclPtr<const Decl>, 4> Processed;
8006 for (
const auto *
Cl : Clauses) {
8007 const auto *
C = dyn_cast<OMPUseDeviceAddrClause>(
Cl);
8010 for (
const auto L :
C->component_lists()) {
8013 assert(!std::get<1>(L).empty() &&
8014 "Not expecting empty list of components!");
8015 const ValueDecl *VD = std::get<1>(L).back().getAssociatedDeclaration();
8016 if (!Processed.insert(VD).second)
8019 const Expr *IE = std::get<1>(L).back().getAssociatedExpression();
8020 if (IsMapInfoExist(CGF, VD, IE,
true))
8022 MapInfoGen(CGF, IE, VD, Components,
C->isImplicit(),
8027 for (
const auto &
Data : Info) {
8028 StructRangeInfoTy PartialStruct;
8030 MapCombinedInfoTy CurInfo;
8032 MapCombinedInfoTy StructBaseCurInfo;
8034 const ValueDecl *VD = cast_or_null<ValueDecl>(
D);
8035 bool HasMapBasePtr =
false;
8036 bool HasMapArraySec =
false;
8038 for (
const auto &M :
Data.second) {
8039 HasMapBasePtr = any_of(M, [](
const MapInfo &L) {
8040 return isa_and_present<DeclRefExpr>(L.VarRef);
8042 HasMapArraySec = any_of(M, [](
const MapInfo &L) {
8043 return isa_and_present<ArraySectionExpr, ArraySubscriptExpr>(
8046 if (HasMapBasePtr && HasMapArraySec)
8050 for (
const auto &M :
Data.second) {
8051 for (
const MapInfo &L : M) {
8052 assert(!L.Components.empty() &&
8053 "Not expecting declaration with no component lists.");
8056 unsigned CurrentBasePointersIdx = CurInfo.BasePointers.size();
8057 unsigned StructBasePointersIdx =
8058 StructBaseCurInfo.BasePointers.size();
8059 CurInfo.NonContigInfo.IsNonContiguous =
8060 L.Components.back().isNonContiguous();
8061 generateInfoForComponentList(
8062 L.MapType, L.MapModifiers, L.MotionModifiers, L.Components,
8063 CurInfo, StructBaseCurInfo, PartialStruct,
8064 false, L.IsImplicit,
8065 true, L.Mapper, L.ForDeviceAddr, VD,
8067 HasMapBasePtr && HasMapArraySec);
8071 if (L.ReturnDevicePointer) {
8075 assert((CurrentBasePointersIdx < CurInfo.BasePointers.size() ||
8076 StructBasePointersIdx <
8077 StructBaseCurInfo.BasePointers.size()) &&
8078 "Unexpected number of mapped base pointers.");
8082 L.Components.back().getAssociatedDeclaration();
8083 assert(RelevantVD &&
8084 "No relevant declaration related with device pointer??");
8091 if (StructBasePointersIdx < StructBaseCurInfo.BasePointers.size()) {
8092 StructBaseCurInfo.DevicePtrDecls[StructBasePointersIdx] =
8094 StructBaseCurInfo.DevicePointers[StructBasePointersIdx] =
8095 L.ForDeviceAddr ? DeviceInfoTy::Address
8096 : DeviceInfoTy::Pointer;
8097 StructBaseCurInfo.Types[StructBasePointersIdx] |=
8098 OpenMPOffloadMappingFlags::OMP_MAP_RETURN_PARAM;
8100 CurInfo.DevicePtrDecls[CurrentBasePointersIdx] = RelevantVD;
8101 CurInfo.DevicePointers[CurrentBasePointersIdx] =
8102 L.ForDeviceAddr ? DeviceInfoTy::Address
8103 : DeviceInfoTy::Pointer;
8104 CurInfo.Types[CurrentBasePointersIdx] |=
8105 OpenMPOffloadMappingFlags::OMP_MAP_RETURN_PARAM;
8113 auto CI = DeferredInfo.find(
Data.first);
8114 if (CI != DeferredInfo.end()) {
8115 for (
const DeferredDevicePtrEntryTy &L : CI->second) {
8116 llvm::Value *BasePtr;
8118 if (L.ForDeviceAddr) {
8119 if (L.IE->isGLValue())
8127 CurInfo.Types.push_back(
8128 OpenMPOffloadMappingFlags::OMP_MAP_RETURN_PARAM |
8129 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF);
8133 L.IE->getExprLoc());
8137 CurInfo.Types.push_back(
8138 OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ |
8139 OpenMPOffloadMappingFlags::OMP_MAP_RETURN_PARAM |
8140 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF);
8142 CurInfo.Exprs.push_back(L.VD);
8143 CurInfo.BasePointers.emplace_back(BasePtr);
8144 CurInfo.DevicePtrDecls.emplace_back(L.VD);
8145 CurInfo.DevicePointers.emplace_back(
8146 L.ForDeviceAddr ? DeviceInfoTy::Address : DeviceInfoTy::Pointer);
8147 CurInfo.Pointers.push_back(Ptr);
8148 CurInfo.Sizes.push_back(
8149 llvm::Constant::getNullValue(this->CGF.
Int64Ty));
8150 CurInfo.Mappers.push_back(
nullptr);
8156 MapCombinedInfoTy UnionCurInfo;
8157 UnionCurInfo.append(StructBaseCurInfo);
8158 UnionCurInfo.append(CurInfo);
8162 if (PartialStruct.Base.isValid()) {
8163 UnionCurInfo.NonContigInfo.Dims.push_back(0);
8165 emitCombinedEntry(CombinedInfo, UnionCurInfo.Types, PartialStruct,
8166 !VD, OMPBuilder, VD);
8170 CombinedInfo.append(UnionCurInfo);
8173 CombinedInfo.append(UseDeviceDataCombinedInfo);
8178 : CurDir(&Dir), CGF(CGF) {
8181 for (
const auto *
D :
C->varlist())
8182 FirstPrivateDecls.try_emplace(
8183 cast<VarDecl>(cast<DeclRefExpr>(
D)->getDecl()),
C->isImplicit());
8186 for (
unsigned I = 0,
E =
C->getNumberOfAllocators(); I <
E; ++I) {
8188 if (
const auto *DRE = dyn_cast_or_null<DeclRefExpr>(
D.AllocatorTraits))
8189 FirstPrivateDecls.try_emplace(cast<VarDecl>(DRE->getDecl()),
8191 else if (
const auto *VD = dyn_cast<VarDecl>(
8192 cast<DeclRefExpr>(
D.Allocator->IgnoreParenImpCasts())
8194 FirstPrivateDecls.try_emplace(VD,
true);
8199 for (
auto L :
C->component_lists())
8200 DevPointersMap[std::get<0>(L)].push_back(std::get<1>(L));
8203 for (
auto L :
C->component_lists())
8204 HasDevAddrsMap[std::get<0>(L)].push_back(std::get<1>(L));
8207 if (
C->getMapType() != OMPC_MAP_to)
8209 for (
auto L :
C->component_lists()) {
8211 const auto *RD = VD ? VD->
getType()
8217 LambdasMap.try_emplace(std::get<0>(L),
C);
8224 : CurDir(&Dir), CGF(CGF) {}
8229 void emitCombinedEntry(MapCombinedInfoTy &CombinedInfo,
8230 MapFlagsArrayTy &CurTypes,
8231 const StructRangeInfoTy &PartialStruct,
bool IsMapThis,
8232 llvm::OpenMPIRBuilder &OMPBuilder,
8234 bool NotTargetParams =
true)
const {
8235 if (CurTypes.size() == 1 &&
8236 ((CurTypes.back() & OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF) !=
8237 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF) &&
8238 !PartialStruct.IsArraySection)
8240 Address LBAddr = PartialStruct.LowestElem.second;
8241 Address HBAddr = PartialStruct.HighestElem.second;
8242 if (PartialStruct.HasCompleteRecord) {
8243 LBAddr = PartialStruct.LB;
8244 HBAddr = PartialStruct.LB;
8246 CombinedInfo.Exprs.push_back(VD);
8248 CombinedInfo.BasePointers.push_back(PartialStruct.Base.emitRawPointer(CGF));
8249 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
8250 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
8256 bool HasBaseClass = RD && IsMapThis ? RD->
getNumBases() > 0 :
false;
8266 CombinedInfo.Pointers.push_back(PartialStruct.Base.emitRawPointer(CGF));
8271 CombinedInfo.Sizes.push_back(Size);
8273 CombinedInfo.Pointers.push_back(LB);
8276 llvm::Value *HAddr = CGF.
Builder.CreateConstGEP1_32(
8280 llvm::Value *Diff = CGF.
Builder.CreatePtrDiff(CGF.
Int8Ty, CHAddr, CLAddr);
8283 CombinedInfo.Sizes.push_back(Size);
8285 CombinedInfo.Mappers.push_back(
nullptr);
8287 CombinedInfo.Types.push_back(
8288 NotTargetParams ? OpenMPOffloadMappingFlags::OMP_MAP_NONE
8289 : !PartialStruct.PreliminaryMapData.BasePointers.empty()
8290 ? OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ
8291 : OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM);
8294 if (CurTypes.end() !=
8295 llvm::find_if(CurTypes, [](OpenMPOffloadMappingFlags
Type) {
8296 return static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>>(
8297 Type & OpenMPOffloadMappingFlags::OMP_MAP_PRESENT);
8299 CombinedInfo.Types.back() |= OpenMPOffloadMappingFlags::OMP_MAP_PRESENT;
8301 (*CurTypes.begin()) &= ~OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM;
8308 if (CurTypes.end() !=
8309 llvm::find_if(CurTypes, [](OpenMPOffloadMappingFlags
Type) {
8310 return static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
8311 Type & OpenMPOffloadMappingFlags::OMP_MAP_OMPX_HOLD);
8313 CombinedInfo.Types.back() |= OpenMPOffloadMappingFlags::OMP_MAP_OMPX_HOLD;
8314 for (
auto &M : CurTypes)
8315 M |= OpenMPOffloadMappingFlags::OMP_MAP_OMPX_HOLD;
8321 OpenMPOffloadMappingFlags MemberOfFlag =
8322 OMPBuilder.getMemberOfFlag(CombinedInfo.BasePointers.size() - 1);
8323 for (
auto &M : CurTypes)
8324 OMPBuilder.setCorrectMemberOfFlag(M, MemberOfFlag);
8332 void generateAllInfo(
8333 MapCombinedInfoTy &CombinedInfo, llvm::OpenMPIRBuilder &OMPBuilder,
8336 assert(isa<const OMPExecutableDirective *>(CurDir) &&
8337 "Expect a executable directive");
8338 const auto *CurExecDir = cast<const OMPExecutableDirective *>(CurDir);
8339 generateAllInfoForClauses(CurExecDir->clauses(), CombinedInfo, OMPBuilder,
8346 void generateAllInfoForMapper(MapCombinedInfoTy &CombinedInfo,
8347 llvm::OpenMPIRBuilder &OMPBuilder)
const {
8348 assert(isa<const OMPDeclareMapperDecl *>(CurDir) &&
8349 "Expect a declare mapper directive");
8350 const auto *CurMapperDir = cast<const OMPDeclareMapperDecl *>(CurDir);
8351 generateAllInfoForClauses(CurMapperDir->clauses(), CombinedInfo,
8356 void generateInfoForLambdaCaptures(
8357 const ValueDecl *VD, llvm::Value *Arg, MapCombinedInfoTy &CombinedInfo,
8358 llvm::DenseMap<llvm::Value *, llvm::Value *> &LambdaPointers)
const {
8366 llvm::DenseMap<const ValueDecl *, FieldDecl *> Captures;
8373 LambdaPointers.try_emplace(ThisLVal.
getPointer(CGF),
8375 CombinedInfo.Exprs.push_back(VD);
8376 CombinedInfo.BasePointers.push_back(ThisLVal.
getPointer(CGF));
8377 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
8378 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
8379 CombinedInfo.Pointers.push_back(ThisLValVal.
getPointer(CGF));
8380 CombinedInfo.Sizes.push_back(
8383 CombinedInfo.Types.push_back(
8384 OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ |
8385 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL |
8386 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF |
8387 OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT);
8388 CombinedInfo.Mappers.push_back(
nullptr);
8391 if (!LC.capturesVariable())
8393 const VarDecl *VD = cast<VarDecl>(LC.getCapturedVar());
8396 auto It = Captures.find(VD);
8397 assert(It != Captures.end() &&
"Found lambda capture without field.");
8401 LambdaPointers.try_emplace(VarLVal.
getPointer(CGF),
8403 CombinedInfo.Exprs.push_back(VD);
8404 CombinedInfo.BasePointers.push_back(VarLVal.
getPointer(CGF));
8405 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
8406 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
8407 CombinedInfo.Pointers.push_back(VarLValVal.
getPointer(CGF));
8408 CombinedInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
8414 LambdaPointers.try_emplace(VarLVal.
getPointer(CGF),
8416 CombinedInfo.Exprs.push_back(VD);
8417 CombinedInfo.BasePointers.push_back(VarLVal.
getPointer(CGF));
8418 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
8419 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
8420 CombinedInfo.Pointers.push_back(VarRVal.
getScalarVal());
8421 CombinedInfo.Sizes.push_back(llvm::ConstantInt::get(CGF.
Int64Ty, 0));
8423 CombinedInfo.Types.push_back(
8424 OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ |
8425 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL |
8426 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF |
8427 OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT);
8428 CombinedInfo.Mappers.push_back(
nullptr);
8433 void adjustMemberOfForLambdaCaptures(
8434 llvm::OpenMPIRBuilder &OMPBuilder,
8435 const llvm::DenseMap<llvm::Value *, llvm::Value *> &LambdaPointers,
8436 MapBaseValuesArrayTy &BasePointers, MapValuesArrayTy &Pointers,
8437 MapFlagsArrayTy &Types)
const {
8438 for (
unsigned I = 0,
E = Types.size(); I <
E; ++I) {
8440 if (Types[I] != (OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ |
8441 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL |
8442 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF |
8443 OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT))
8445 llvm::Value *BasePtr = LambdaPointers.lookup(BasePointers[I]);
8446 assert(BasePtr &&
"Unable to find base lambda address.");
8448 for (
unsigned J = I; J > 0; --J) {
8449 unsigned Idx = J - 1;
8450 if (Pointers[Idx] != BasePtr)
8455 assert(TgtIdx != -1 &&
"Unable to find parent lambda.");
8459 OpenMPOffloadMappingFlags MemberOfFlag =
8460 OMPBuilder.getMemberOfFlag(TgtIdx);
8461 OMPBuilder.setCorrectMemberOfFlag(Types[I], MemberOfFlag);
8468 llvm::Value *Arg, MapCombinedInfoTy &CombinedInfo,
8469 StructRangeInfoTy &PartialStruct)
const {
8471 "Not expecting to generate map info for a variable array type!");
8480 if (LambdasMap.count(VD))
8486 if (VD && (DevPointersMap.count(VD) || HasDevAddrsMap.count(VD))) {
8487 CombinedInfo.Exprs.push_back(VD);
8488 CombinedInfo.BasePointers.emplace_back(Arg);
8489 CombinedInfo.DevicePtrDecls.emplace_back(VD);
8490 CombinedInfo.DevicePointers.emplace_back(DeviceInfoTy::Pointer);
8491 CombinedInfo.Pointers.push_back(Arg);
8492 CombinedInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
8495 CombinedInfo.Types.push_back(
8496 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL |
8497 OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM);
8498 CombinedInfo.Mappers.push_back(
nullptr);
8510 auto It = DevPointersMap.find(VD);
8511 if (It != DevPointersMap.end())
8512 for (
const auto &MCL : It->second)
8513 DeclComponentLists.emplace_back(MCL, OMPC_MAP_to,
Unknown,
8516 auto I = HasDevAddrsMap.find(VD);
8517 if (I != HasDevAddrsMap.end())
8518 for (
const auto &MCL : I->second)
8519 DeclComponentLists.emplace_back(MCL, OMPC_MAP_tofrom,
Unknown,
8522 assert(isa<const OMPExecutableDirective *>(CurDir) &&
8523 "Expect a executable directive");
8524 const auto *CurExecDir = cast<const OMPExecutableDirective *>(CurDir);
8525 bool HasMapBasePtr =
false;
8526 bool HasMapArraySec =
false;
8527 for (
const auto *
C : CurExecDir->getClausesOfKind<
OMPMapClause>()) {
8528 const auto *EI =
C->getVarRefs().begin();
8529 for (
const auto L :
C->decl_component_lists(VD)) {
8532 const Expr *
E = (
C->getMapLoc().isValid()) ? *EI :
nullptr;
8534 std::tie(VDecl, Components, Mapper) = L;
8535 assert(VDecl == VD &&
"We got information for the wrong declaration??");
8536 assert(!Components.empty() &&
8537 "Not expecting declaration with no component lists.");
8539 HasMapBasePtr =
true;
8541 (isa<ArraySectionExpr>(
E) || isa<ArraySubscriptExpr>(
E)))
8542 HasMapArraySec =
true;
8543 DeclComponentLists.emplace_back(Components,
C->getMapType(),
8544 C->getMapTypeModifiers(),
8545 C->isImplicit(), Mapper,
E);
8549 llvm::stable_sort(DeclComponentLists, [](
const MapData &LHS,
8550 const MapData &RHS) {
8554 llvm::is_contained(MapModifiers, clang::OMPC_MAP_MODIFIER_present);
8555 bool HasAllocs = MapType == OMPC_MAP_alloc;
8556 MapModifiers = std::get<2>(RHS);
8557 MapType = std::get<1>(LHS);
8559 llvm::is_contained(MapModifiers, clang::OMPC_MAP_MODIFIER_present);
8560 bool HasAllocsR = MapType == OMPC_MAP_alloc;
8561 return (HasPresent && !HasPresentR) || (HasAllocs && !HasAllocsR);
8565 llvm::SmallDenseMap<
8572 for (
const MapData &L : DeclComponentLists) {
8579 std::tie(Components, MapType, MapModifiers, IsImplicit, Mapper, VarRef) =
8582 for (
const MapData &L1 :
ArrayRef(DeclComponentLists).slice(Count)) {
8584 std::tie(Components1, MapType, MapModifiers, IsImplicit, Mapper,
8586 auto CI = Components.rbegin();
8587 auto CE = Components.rend();
8588 auto SI = Components1.rbegin();
8589 auto SE = Components1.rend();
8590 for (; CI != CE && SI != SE; ++CI, ++SI) {
8591 if (CI->getAssociatedExpression()->getStmtClass() !=
8592 SI->getAssociatedExpression()->getStmtClass())
8595 if (CI->getAssociatedDeclaration() != SI->getAssociatedDeclaration())
8600 if (CI == CE || SI == SE) {
8602 if (CI == CE && SI == SE)
8604 const auto It = (SI == SE) ? CI : SI;
8610 if (!isa<MemberExpr>(It->getAssociatedExpression()) ||
8611 (std::prev(It)->getAssociatedDeclaration() &&
8613 ->getAssociatedDeclaration()
8615 ->isPointerType()) ||
8616 (It->getAssociatedDeclaration() &&
8617 It->getAssociatedDeclaration()->getType()->isPointerType() &&
8618 std::next(It) != CE && std::next(It) != SE))
8620 const MapData &BaseData = CI == CE ? L : L1;
8622 SI == SE ? Components : Components1;
8623 OverlappedData[&BaseData].push_back(SubData);
8629 if (!OverlappedData.empty()) {
8632 while (BaseType != OrigType) {
8638 getPlainLayout(CRD, Layout,
false);
8644 for (
auto &Pair : OverlappedData) {
8651 auto CI = First.rbegin();
8652 auto CE = First.rend();
8653 auto SI = Second.rbegin();
8654 auto SE = Second.rend();
8655 for (; CI != CE && SI != SE; ++CI, ++SI) {
8656 if (CI->getAssociatedExpression()->getStmtClass() !=
8657 SI->getAssociatedExpression()->getStmtClass())
8660 if (CI->getAssociatedDeclaration() !=
8661 SI->getAssociatedDeclaration())
8666 if (CI == CE && SI == SE)
8670 if (CI == CE || SI == SE)
8673 const auto *FD1 = cast<FieldDecl>(CI->getAssociatedDeclaration());
8674 const auto *FD2 = cast<FieldDecl>(SI->getAssociatedDeclaration());
8675 if (FD1->getParent() == FD2->getParent())
8676 return FD1->getFieldIndex() < FD2->getFieldIndex();
8678 llvm::find_if(Layout, [FD1, FD2](
const FieldDecl *FD) {
8679 return FD == FD1 || FD == FD2;
8687 bool IsFirstComponentList =
true;
8688 MapCombinedInfoTy StructBaseCombinedInfo;
8689 for (
const auto &Pair : OverlappedData) {
8690 const MapData &L = *Pair.getFirst();
8697 std::tie(Components, MapType, MapModifiers, IsImplicit, Mapper, VarRef) =
8700 OverlappedComponents = Pair.getSecond();
8701 generateInfoForComponentList(
8702 MapType, MapModifiers, {}, Components, CombinedInfo,
8703 StructBaseCombinedInfo, PartialStruct, IsFirstComponentList,
8704 IsImplicit,
false, Mapper,
8705 false, VD, VarRef, OverlappedComponents);
8706 IsFirstComponentList =
false;
8709 for (
const MapData &L : DeclComponentLists) {
8716 std::tie(Components, MapType, MapModifiers, IsImplicit, Mapper, VarRef) =
8718 auto It = OverlappedData.find(&L);
8719 if (It == OverlappedData.end())
8720 generateInfoForComponentList(
8721 MapType, MapModifiers, {}, Components, CombinedInfo,
8722 StructBaseCombinedInfo, PartialStruct, IsFirstComponentList,
8723 IsImplicit,
false, Mapper,
8725 {}, HasMapBasePtr && HasMapArraySec);
8726 IsFirstComponentList =
false;
8734 MapCombinedInfoTy &CombinedInfo)
const {
8735 bool IsImplicit =
true;
8738 CombinedInfo.Exprs.push_back(
nullptr);
8739 CombinedInfo.BasePointers.push_back(CV);
8740 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
8741 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
8742 CombinedInfo.Pointers.push_back(CV);
8744 CombinedInfo.Sizes.push_back(
8748 CombinedInfo.Types.push_back(OpenMPOffloadMappingFlags::OMP_MAP_TO |
8749 OpenMPOffloadMappingFlags::OMP_MAP_FROM);
8753 CombinedInfo.BasePointers.push_back(CV);
8754 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
8755 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
8756 CombinedInfo.Pointers.push_back(CV);
8760 CombinedInfo.Types.push_back(
8761 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL);
8762 CombinedInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
8767 CombinedInfo.Types.push_back(OpenMPOffloadMappingFlags::OMP_MAP_NONE);
8768 CombinedInfo.Sizes.push_back(llvm::Constant::getNullValue(CGF.
Int64Ty));
8770 auto I = FirstPrivateDecls.find(VD);
8771 if (I != FirstPrivateDecls.end())
8772 IsImplicit = I->getSecond();
8777 CombinedInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
8782 CombinedInfo.Types.push_back(getMapModifiersForPrivateClauses(CI));
8784 auto I = FirstPrivateDecls.find(VD);
8786 CombinedInfo.BasePointers.push_back(CV);
8787 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
8788 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
8795 CombinedInfo.Pointers.push_back(CV);
8797 if (I != FirstPrivateDecls.end())
8798 IsImplicit = I->getSecond();
8801 CombinedInfo.Types.back() |=
8802 OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM;
8806 CombinedInfo.Types.back() |= OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT;
8809 CombinedInfo.Mappers.push_back(
nullptr);
8821 dyn_cast<MemberExpr>(OASE->getBase()->IgnoreParenImpCasts()))
8822 return ME->getMemberDecl();
8828static llvm::Constant *
8830 MappableExprsHandler::MappingExprInfo &MapExprs) {
8832 uint32_t SrcLocStrSize;
8833 if (!MapExprs.getMapDecl() && !MapExprs.getMapExpr())
8834 return OMPBuilder.getOrCreateDefaultSrcLocStr(SrcLocStrSize);
8837 if (!MapExprs.getMapDecl() && MapExprs.getMapExpr()) {
8841 Loc = MapExprs.getMapExpr()->getExprLoc();
8843 Loc = MapExprs.getMapDecl()->getLocation();
8846 std::string ExprName;
8847 if (MapExprs.getMapExpr()) {
8849 llvm::raw_string_ostream OS(ExprName);
8850 MapExprs.getMapExpr()->printPretty(OS,
nullptr,
P);
8852 ExprName = MapExprs.getMapDecl()->getNameAsString();
8856 return OMPBuilder.getOrCreateSrcLocStr(PLoc.
getFilename(), ExprName,
8864 CodeGenFunction &CGF, MappableExprsHandler::MapCombinedInfoTy &CombinedInfo,
8866 bool IsNonContiguous =
false,
bool ForEndCall =
false) {
8869 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
8872 InsertPointTy CodeGenIP(CGF.
Builder.GetInsertBlock(),
8873 CGF.
Builder.GetInsertPoint());
8875 auto DeviceAddrCB = [&](
unsigned int I, llvm::Value *NewDecl) {
8876 if (
const ValueDecl *DevVD = CombinedInfo.DevicePtrDecls[I]) {
8881 auto CustomMapperCB = [&](
unsigned int I) {
8882 llvm::Value *MFunc =
nullptr;
8883 if (CombinedInfo.Mappers[I]) {
8884 Info.HasMapper =
true;
8886 cast<OMPDeclareMapperDecl>(CombinedInfo.Mappers[I]));
8890 OMPBuilder.emitOffloadingArraysAndArgs(
8891 AllocaIP, CodeGenIP, Info, Info.RTArgs, CombinedInfo, IsNonContiguous,
8892 ForEndCall, DeviceAddrCB, CustomMapperCB);
8898 const auto *CS =
D.getInnermostCapturedStmt();
8901 const Stmt *ChildStmt =
8904 if (
const auto *NestedDir =
8905 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) {
8907 switch (
D.getDirectiveKind()) {
8913 if (DKind == OMPD_teams) {
8914 Body = NestedDir->getInnermostCapturedStmt()->IgnoreContainers(
8919 if (
const auto *NND =
8920 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) {
8921 DKind = NND->getDirectiveKind();
8927 case OMPD_target_teams:
8931 case OMPD_target_parallel:
8932 case OMPD_target_simd:
8933 case OMPD_target_parallel_for:
8934 case OMPD_target_parallel_for_simd:
8936 case OMPD_target_teams_distribute:
8937 case OMPD_target_teams_distribute_simd:
8938 case OMPD_target_teams_distribute_parallel_for:
8939 case OMPD_target_teams_distribute_parallel_for_simd:
8942 case OMPD_parallel_for:
8943 case OMPD_parallel_master:
8944 case OMPD_parallel_sections:
8946 case OMPD_parallel_for_simd:
8948 case OMPD_cancellation_point:
8950 case OMPD_threadprivate:
8961 case OMPD_taskyield:
8964 case OMPD_taskgroup:
8970 case OMPD_target_data:
8971 case OMPD_target_exit_data:
8972 case OMPD_target_enter_data:
8973 case OMPD_distribute:
8974 case OMPD_distribute_simd:
8975 case OMPD_distribute_parallel_for:
8976 case OMPD_distribute_parallel_for_simd:
8977 case OMPD_teams_distribute:
8978 case OMPD_teams_distribute_simd:
8979 case OMPD_teams_distribute_parallel_for:
8980 case OMPD_teams_distribute_parallel_for_simd:
8981 case OMPD_target_update:
8982 case OMPD_declare_simd:
8983 case OMPD_declare_variant:
8984 case OMPD_begin_declare_variant:
8985 case OMPD_end_declare_variant:
8986 case OMPD_declare_target:
8987 case OMPD_end_declare_target:
8988 case OMPD_declare_reduction:
8989 case OMPD_declare_mapper:
8991 case OMPD_taskloop_simd:
8992 case OMPD_master_taskloop:
8993 case OMPD_master_taskloop_simd:
8994 case OMPD_parallel_master_taskloop:
8995 case OMPD_parallel_master_taskloop_simd:
8997 case OMPD_metadirective:
9000 llvm_unreachable(
"Unexpected directive.");
9045 auto *MapperVarDecl =
9046 cast<VarDecl>(cast<DeclRefExpr>(
D->getMapperVarRef())->getDecl());
9047 CharUnits ElementSize =
C.getTypeSizeInChars(Ty);
9051 MappableExprsHandler::MapCombinedInfoTy CombinedInfo;
9052 auto PrivatizeAndGenMapInfoCB =
9053 [&](llvm::OpenMPIRBuilder::InsertPointTy CodeGenIP, llvm::Value *PtrPHI,
9054 llvm::Value *BeginArg) -> llvm::OpenMPIRBuilder::MapInfosTy & {
9055 MapperCGF.
Builder.restoreIP(CodeGenIP);
9065 Scope.addPrivate(MapperVarDecl, PtrCurrent);
9066 (void)
Scope.Privatize();
9069 MappableExprsHandler MEHandler(*
D, MapperCGF);
9070 MEHandler.generateAllInfoForMapper(CombinedInfo,
OMPBuilder);
9072 auto FillInfoMap = [&](MappableExprsHandler::MappingExprInfo &MapExpr) {
9076 llvm::codegenoptions::NoDebugInfo) {
9077 CombinedInfo.Names.resize(CombinedInfo.Exprs.size());
9078 llvm::transform(CombinedInfo.Exprs, CombinedInfo.Names.begin(),
9082 return CombinedInfo;
9085 auto CustomMapperCB = [&](
unsigned I, llvm::Function **MapperFunc) {
9086 if (CombinedInfo.Mappers[I]) {
9089 cast<OMPDeclareMapperDecl>(CombinedInfo.Mappers[I]));
9090 assert(*MapperFunc &&
"Expect a valid mapper function is available.");
9097 llvm::raw_svector_ostream Out(TyStr);
9099 std::string Name =
getName({
"omp_mapper", TyStr,
D->getName()});
9101 auto *NewFn =
OMPBuilder.emitUserDefinedMapper(PrivatizeAndGenMapInfoCB,
9102 ElemTy, Name, CustomMapperCB);
9127 Kind != OMPD_target_teams_loop)
9130 return llvm::ConstantInt::get(CGF.
Int64Ty, 0);
9132 const auto *LD = cast<OMPLoopDirective>(TD);
9133 if (llvm::Value *NumIterations = SizeEmitter(CGF, *LD))
9134 return NumIterations;
9135 return llvm::ConstantInt::get(CGF.
Int64Ty, 0);
9144 if (OffloadingMandatory) {
9145 CGF.
Builder.CreateUnreachable();
9147 if (RequiresOuterTask) {
9148 CapturedVars.clear();
9157 llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier>
Device,
9160 llvm::Value *DeviceID;
9161 if (
Device.getPointer()) {
9163 Device.getInt() == OMPC_DEVICE_device_num) &&
9164 "Expected device_num modifier.");
9169 DeviceID = CGF.
Builder.getInt64(OMP_DEVICEID_UNDEF);
9176 llvm::Value *DynCGroupMem = CGF.
Builder.getInt32(0);
9179 CodeGenFunction::RunCleanupsScope DynCGroupMemScope(CGF);
9181 DynMemClause->getSize(),
true);
9182 DynCGroupMem = CGF.
Builder.CreateIntCast(DynCGroupMemVal, CGF.
Int32Ty,
9185 return DynCGroupMem;
9190 llvm::OpenMPIRBuilder &OMPBuilder,
9192 MappableExprsHandler::MapCombinedInfoTy &CombinedInfo) {
9194 llvm::DenseMap<llvm::Value *, llvm::Value *> LambdaPointers;
9196 auto *CV = CapturedVars.begin();
9199 CI != CE; ++CI, ++RI, ++CV) {
9200 MappableExprsHandler::MapCombinedInfoTy CurInfo;
9201 MappableExprsHandler::StructRangeInfoTy PartialStruct;
9206 CurInfo.Exprs.push_back(
nullptr);
9207 CurInfo.BasePointers.push_back(*CV);
9208 CurInfo.DevicePtrDecls.push_back(
nullptr);
9209 CurInfo.DevicePointers.push_back(
9210 MappableExprsHandler::DeviceInfoTy::None);
9211 CurInfo.Pointers.push_back(*CV);
9212 CurInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
9215 CurInfo.Types.push_back(OpenMPOffloadMappingFlags::OMP_MAP_LITERAL |
9216 OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM |
9217 OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT);
9218 CurInfo.Mappers.push_back(
nullptr);
9222 MEHandler.generateInfoForCapture(CI, *CV, CurInfo, PartialStruct);
9226 MappedVarSet.insert(
nullptr);
9227 if (CurInfo.BasePointers.empty() && !PartialStruct.Base.isValid())
9228 MEHandler.generateDefaultMapInfo(*CI, **RI, *CV, CurInfo);
9232 MEHandler.generateInfoForLambdaCaptures(CI->
getCapturedVar(), *CV,
9233 CurInfo, LambdaPointers);
9236 assert((!CurInfo.BasePointers.empty() || PartialStruct.Base.isValid()) &&
9237 "Non-existing map pointer for capture!");
9238 assert(CurInfo.BasePointers.size() == CurInfo.Pointers.size() &&
9239 CurInfo.BasePointers.size() == CurInfo.Sizes.size() &&
9240 CurInfo.BasePointers.size() == CurInfo.Types.size() &&
9241 CurInfo.BasePointers.size() == CurInfo.Mappers.size() &&
9242 "Inconsistent map information sizes!");
9246 if (PartialStruct.Base.isValid()) {
9247 CombinedInfo.append(PartialStruct.PreliminaryMapData);
9248 MEHandler.emitCombinedEntry(CombinedInfo, CurInfo.Types, PartialStruct,
9254 CombinedInfo.append(CurInfo);
9257 MEHandler.adjustMemberOfForLambdaCaptures(
9258 OMPBuilder, LambdaPointers, CombinedInfo.BasePointers,
9259 CombinedInfo.Pointers, CombinedInfo.Types);
9263 MappableExprsHandler::MapCombinedInfoTy &CombinedInfo,
9264 llvm::OpenMPIRBuilder &OMPBuilder,
9271 MEHandler.generateAllInfo(CombinedInfo, OMPBuilder, SkippedVarSet);
9273 auto FillInfoMap = [&](MappableExprsHandler::MappingExprInfo &MapExpr) {
9277 llvm::codegenoptions::NoDebugInfo) {
9278 CombinedInfo.Names.resize(CombinedInfo.Exprs.size());
9279 llvm::transform(CombinedInfo.Exprs, CombinedInfo.Names.begin(),
9287 llvm::OpenMPIRBuilder &OMPBuilder,
9288 MappableExprsHandler::MapCombinedInfoTy &CombinedInfo) {
9290 MappableExprsHandler MEHandler(
D, CGF);
9291 llvm::DenseSet<CanonicalDeclPtr<const Decl>> MappedVarSet;
9294 MappedVarSet, CombinedInfo);
9295 genMapInfo(MEHandler, CGF, CombinedInfo, OMPBuilder, MappedVarSet);
9298template <
typename ClauseTy>
9303 const auto *
C =
D.getSingleClause<ClauseTy>();
9304 assert(!
C->varlist_empty() &&
9305 "ompx_bare requires explicit num_teams and thread_limit");
9306 CodeGenFunction::RunCleanupsScope
Scope(CGF);
9307 for (
auto *
E :
C->varlist()) {
9319 llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier>
Device,
9320 llvm::Value *OutlinedFnID, CodeGenFunction::OMPTargetDataInfo &InputInfo,
9321 llvm::Value *&MapTypesArray, llvm::Value *&MapNamesArray,
9326 llvm::OpenMPIRBuilder &OMPBuilder = OMPRuntime->
getOMPBuilder();
9329 MappableExprsHandler::MapCombinedInfoTy CombinedInfo;
9331 genMapInfo(
D, CGF, CS, CapturedVars, OMPBuilder, CombinedInfo);
9336 InputInfo.NumberOfTargetItems = Info.NumberOfPtrs;
9337 InputInfo.BasePointersArray =
Address(Info.RTArgs.BasePointersArray,
9339 InputInfo.PointersArray =
9341 InputInfo.SizesArray =
9343 InputInfo.MappersArray =
9345 MapTypesArray = Info.RTArgs.MapTypesArray;
9346 MapNamesArray = Info.RTArgs.MapNamesArray;
9348 auto &&ThenGen = [&OMPRuntime, OutlinedFn, &
D, &CapturedVars,
9349 RequiresOuterTask, &CS, OffloadingMandatory,
Device,
9350 OutlinedFnID, &InputInfo, &MapTypesArray, &MapNamesArray,
9352 bool IsReverseOffloading =
Device.getInt() == OMPC_DEVICE_ancestor;
9354 if (IsReverseOffloading) {
9360 RequiresOuterTask, CS, OffloadingMandatory, CGF);
9365 unsigned NumTargetItems = InputInfo.NumberOfTargetItems;
9367 llvm::Value *BasePointersArray =
9368 InputInfo.BasePointersArray.emitRawPointer(CGF);
9369 llvm::Value *PointersArray = InputInfo.PointersArray.emitRawPointer(CGF);
9370 llvm::Value *SizesArray = InputInfo.SizesArray.emitRawPointer(CGF);
9371 llvm::Value *MappersArray = InputInfo.MappersArray.emitRawPointer(CGF);
9373 auto &&EmitTargetCallFallbackCB =
9374 [&OMPRuntime, OutlinedFn, &
D, &CapturedVars, RequiresOuterTask, &CS,
9375 OffloadingMandatory, &CGF](llvm::OpenMPIRBuilder::InsertPointTy IP)
9376 -> llvm::OpenMPIRBuilder::InsertPointTy {
9379 RequiresOuterTask, CS, OffloadingMandatory, CGF);
9387 emitClauseForBareTargetDirective<OMPNumTeamsClause>(CGF,
D, NumTeams);
9388 emitClauseForBareTargetDirective<OMPThreadLimitClause>(CGF,
D,
9392 NumThreads.push_back(
9398 llvm::Value *NumIterations =
9401 llvm::OpenMPIRBuilder::InsertPointTy AllocaIP(
9404 llvm::OpenMPIRBuilder::TargetDataRTArgs RTArgs(
9405 BasePointersArray, PointersArray, SizesArray, MapTypesArray,
9406 nullptr , MappersArray, MapNamesArray);
9408 llvm::OpenMPIRBuilder::TargetKernelArgs Args(
9409 NumTargetItems, RTArgs, NumIterations, NumTeams, NumThreads,
9410 DynCGGroupMem, HasNoWait);
9412 llvm::OpenMPIRBuilder::InsertPointOrErrorTy AfterIP =
9414 CGF.
Builder, OutlinedFnID, EmitTargetCallFallbackCB, Args, DeviceID,
9416 assert(AfterIP &&
"unexpected error creating kernel launch");
9417 CGF.
Builder.restoreIP(*AfterIP);
9420 if (RequiresOuterTask)
9435 [&OMPRuntime, OutlinedFn, &
D, &CapturedVars, RequiresOuterTask, &CS,
9438 RequiresOuterTask, CS, OffloadingMandatory, CGF);
9441 if (RequiresOuterTask) {
9442 CodeGenFunction::OMPTargetDataInfo InputInfo;
9451 llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID,
const Expr *IfCond,
9452 llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier>
Device,
9459 const bool OffloadingMandatory = !
CGM.
getLangOpts().OpenMPIsTargetDevice &&
9462 assert((OffloadingMandatory || OutlinedFn) &&
"Invalid outlined function!");
9464 const bool RequiresOuterTask =
9480 llvm::Value *MapTypesArray =
nullptr;
9481 llvm::Value *MapNamesArray =
nullptr;
9483 auto &&TargetThenGen = [
this, OutlinedFn, &
D, &CapturedVars,
9484 RequiresOuterTask, &CS, OffloadingMandatory,
Device,
9485 OutlinedFnID, &InputInfo, &MapTypesArray,
9489 RequiresOuterTask, CS, OffloadingMandatory,
9490 Device, OutlinedFnID, InputInfo, MapTypesArray,
9491 MapNamesArray, SizeEmitter, CGF,
CGM);
9494 auto &&TargetElseGen =
9495 [
this, OutlinedFn, &
D, &CapturedVars, RequiresOuterTask, &CS,
9498 CS, OffloadingMandatory, CGF);
9507 emitIfClause(CGF, IfCond, TargetThenGen, TargetElseGen);
9519 StringRef ParentName) {
9524 bool RequiresDeviceCodegen =
9525 isa<OMPExecutableDirective>(S) &&
9527 cast<OMPExecutableDirective>(S)->getDirectiveKind());
9529 if (RequiresDeviceCodegen) {
9530 const auto &
E = *cast<OMPExecutableDirective>(S);
9537 if (!
OMPBuilder.OffloadInfoManager.hasTargetRegionEntryInfo(EntryInfo))
9540 switch (
E.getDirectiveKind()) {
9543 cast<OMPTargetDirective>(
E));
9545 case OMPD_target_parallel:
9547 CGM, ParentName, cast<OMPTargetParallelDirective>(
E));
9549 case OMPD_target_teams:
9551 CGM, ParentName, cast<OMPTargetTeamsDirective>(
E));
9553 case OMPD_target_teams_distribute:
9555 CGM, ParentName, cast<OMPTargetTeamsDistributeDirective>(
E));
9557 case OMPD_target_teams_distribute_simd:
9559 CGM, ParentName, cast<OMPTargetTeamsDistributeSimdDirective>(
E));
9561 case OMPD_target_parallel_for:
9563 CGM, ParentName, cast<OMPTargetParallelForDirective>(
E));
9565 case OMPD_target_parallel_for_simd:
9567 CGM, ParentName, cast<OMPTargetParallelForSimdDirective>(
E));
9569 case OMPD_target_simd:
9571 CGM, ParentName, cast<OMPTargetSimdDirective>(
E));
9573 case OMPD_target_teams_distribute_parallel_for:
9576 cast<OMPTargetTeamsDistributeParallelForDirective>(
E));
9578 case OMPD_target_teams_distribute_parallel_for_simd:
9582 cast<OMPTargetTeamsDistributeParallelForSimdDirective>(
E));
9584 case OMPD_target_teams_loop:
9586 CGM, ParentName, cast<OMPTargetTeamsGenericLoopDirective>(
E));
9588 case OMPD_target_parallel_loop:
9590 CGM, ParentName, cast<OMPTargetParallelGenericLoopDirective>(
E));
9594 case OMPD_parallel_for:
9595 case OMPD_parallel_master:
9596 case OMPD_parallel_sections:
9598 case OMPD_parallel_for_simd:
9600 case OMPD_cancellation_point:
9602 case OMPD_threadprivate:
9613 case OMPD_taskyield:
9616 case OMPD_taskgroup:
9622 case OMPD_target_data:
9623 case OMPD_target_exit_data:
9624 case OMPD_target_enter_data:
9625 case OMPD_distribute:
9626 case OMPD_distribute_simd:
9627 case OMPD_distribute_parallel_for:
9628 case OMPD_distribute_parallel_for_simd:
9629 case OMPD_teams_distribute:
9630 case OMPD_teams_distribute_simd:
9631 case OMPD_teams_distribute_parallel_for:
9632 case OMPD_teams_distribute_parallel_for_simd:
9633 case OMPD_target_update:
9634 case OMPD_declare_simd:
9635 case OMPD_declare_variant:
9636 case OMPD_begin_declare_variant:
9637 case OMPD_end_declare_variant:
9638 case OMPD_declare_target:
9639 case OMPD_end_declare_target:
9640 case OMPD_declare_reduction:
9641 case OMPD_declare_mapper:
9643 case OMPD_taskloop_simd:
9644 case OMPD_master_taskloop:
9645 case OMPD_master_taskloop_simd:
9646 case OMPD_parallel_master_taskloop:
9647 case OMPD_parallel_master_taskloop_simd:
9649 case OMPD_metadirective:
9652 llvm_unreachable(
"Unknown target directive for OpenMP device codegen.");
9657 if (
const auto *
E = dyn_cast<OMPExecutableDirective>(S)) {
9658 if (!
E->hasAssociatedStmt() || !
E->getAssociatedStmt())
9666 if (
const auto *L = dyn_cast<LambdaExpr>(S))
9670 for (
const Stmt *II : S->children())
9675 std::optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
9676 OMPDeclareTargetDeclAttr::getDeviceType(VD);
9680 if (!IsDevice && DevTy == OMPDeclareTargetDeclAttr::DT_NoHost)
9683 if (IsDevice && DevTy == OMPDeclareTargetDeclAttr::DT_Host)
9692 if (
const auto *FD = dyn_cast<FunctionDecl>(GD.
getDecl()))
9701 if (
const auto *FD = dyn_cast<FunctionDecl>(VD)) {
9710 return !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD) &&
9728 StringRef ParentName =
9733 StringRef ParentName =
9740 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
9741 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(
9743 if (!Res || *Res == OMPDeclareTargetDeclAttr::MT_Link ||
9744 ((*Res == OMPDeclareTargetDeclAttr::MT_To ||
9745 *Res == OMPDeclareTargetDeclAttr::MT_Enter) &&
9754 llvm::Constant *Addr) {
9759 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
9760 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
9764 if (Res && *Res != OMPDeclareTargetDeclAttr::MT_Link &&
9779 auto LinkageForVariable = [&VD,
this]() {
9783 std::vector<llvm::GlobalVariable *> GeneratedRefs;
9796 for (
auto *ref : GeneratedRefs)
9801 if (isa<FunctionDecl>(GD.
getDecl()) ||
9802 isa<OMPDeclareReductionDecl>(GD.
getDecl()))
9810 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
9811 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
9814 if ((*Res == OMPDeclareTargetDeclAttr::MT_To ||
9815 *Res == OMPDeclareTargetDeclAttr::MT_Enter) &&
9819 assert((*Res == OMPDeclareTargetDeclAttr::MT_Link ||
9820 ((*Res == OMPDeclareTargetDeclAttr::MT_To ||
9821 *Res == OMPDeclareTargetDeclAttr::MT_Enter) &&
9823 "Expected link clause or to clause with unified memory.");
9832 " Expected target-based directive.");
9836 for (
const OMPClause *Clause :
D->clauselists()) {
9837 if (Clause->getClauseKind() == OMPC_unified_shared_memory) {
9839 OMPBuilder.Config.setHasRequiresUnifiedSharedMemory(
true);
9840 }
else if (
const auto *AC =
9841 dyn_cast<OMPAtomicDefaultMemOrderClause>(Clause)) {
9842 switch (AC->getAtomicDefaultMemOrderKind()) {
9843 case OMPC_ATOMIC_DEFAULT_MEM_ORDER_acq_rel:
9846 case OMPC_ATOMIC_DEFAULT_MEM_ORDER_seq_cst:
9849 case OMPC_ATOMIC_DEFAULT_MEM_ORDER_relaxed:
9865 if (!VD || !VD->
hasAttr<OMPAllocateDeclAttr>())
9867 const auto *A = VD->
getAttr<OMPAllocateDeclAttr>();
9868 switch(A->getAllocatorType()) {
9869 case OMPAllocateDeclAttr::OMPNullMemAlloc:
9870 case OMPAllocateDeclAttr::OMPDefaultMemAlloc:
9872 case OMPAllocateDeclAttr::OMPLargeCapMemAlloc:
9873 case OMPAllocateDeclAttr::OMPCGroupMemAlloc:
9874 case OMPAllocateDeclAttr::OMPHighBWMemAlloc:
9875 case OMPAllocateDeclAttr::OMPLowLatMemAlloc:
9876 case OMPAllocateDeclAttr::OMPThreadMemAlloc:
9877 case OMPAllocateDeclAttr::OMPConstMemAlloc:
9878 case OMPAllocateDeclAttr::OMPPTeamMemAlloc:
9881 case OMPAllocateDeclAttr::OMPUserDefinedMemAlloc:
9882 llvm_unreachable(
"Expected predefined allocator for the variables with the "
9910 const auto *
D = cast<FunctionDecl>(GD.
getDecl());
9913 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(
D)) {
9915 if (
auto *F = dyn_cast_or_null<llvm::Function>(
9917 return !F->isDeclaration();
9929 llvm::Function *OutlinedFn,
9938 llvm::Value *Args[] = {
9940 CGF.
Builder.getInt32(CapturedVars.size()),
9943 RealArgs.append(std::begin(Args), std::end(Args));
9944 RealArgs.append(CapturedVars.begin(), CapturedVars.end());
9946 llvm::FunctionCallee RTLFn =
OMPBuilder.getOrCreateRuntimeFunction(
9952 const Expr *NumTeams,
9953 const Expr *ThreadLimit,
9960 llvm::Value *NumTeamsVal =
9966 llvm::Value *ThreadLimitVal =
9973 llvm::Value *PushNumTeamsArgs[] = {RTLoc,
getThreadID(CGF,
Loc), NumTeamsVal,
9981 const Expr *ThreadLimit,
9984 llvm::Value *ThreadLimitVal =
10009 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
10011 llvm::Value *IfCondVal =
nullptr;
10016 llvm::Value *DeviceID =
nullptr;
10021 DeviceID = CGF.
Builder.getInt64(OMP_DEVICEID_UNDEF);
10025 MappableExprsHandler::MapCombinedInfoTy CombinedInfo;
10026 auto GenMapInfoCB =
10027 [&](InsertPointTy CodeGenIP) -> llvm::OpenMPIRBuilder::MapInfosTy & {
10028 CGF.
Builder.restoreIP(CodeGenIP);
10030 MappableExprsHandler MEHandler(
D, CGF);
10031 MEHandler.generateAllInfo(CombinedInfo,
OMPBuilder);
10033 auto FillInfoMap = [&](MappableExprsHandler::MappingExprInfo &MapExpr) {
10037 llvm::codegenoptions::NoDebugInfo) {
10038 CombinedInfo.Names.resize(CombinedInfo.Exprs.size());
10039 llvm::transform(CombinedInfo.Exprs, CombinedInfo.Names.begin(),
10043 return CombinedInfo;
10045 using BodyGenTy = llvm::OpenMPIRBuilder::BodyGenTy;
10046 auto BodyCB = [&](InsertPointTy CodeGenIP, BodyGenTy BodyGenType) {
10047 CGF.
Builder.restoreIP(CodeGenIP);
10048 switch (BodyGenType) {
10049 case BodyGenTy::Priv:
10053 case BodyGenTy::DupNoPriv:
10059 case BodyGenTy::NoPriv:
10066 return InsertPointTy(CGF.
Builder.GetInsertBlock(),
10067 CGF.
Builder.GetInsertPoint());
10070 auto DeviceAddrCB = [&](
unsigned int I, llvm::Value *NewDecl) {
10071 if (
const ValueDecl *DevVD = CombinedInfo.DevicePtrDecls[I]) {
10076 auto CustomMapperCB = [&](
unsigned int I) {
10077 llvm::Value *MFunc =
nullptr;
10078 if (CombinedInfo.Mappers[I]) {
10079 Info.HasMapper =
true;
10081 cast<OMPDeclareMapperDecl>(CombinedInfo.Mappers[I]));
10091 InsertPointTy CodeGenIP(CGF.
Builder.GetInsertBlock(),
10092 CGF.
Builder.GetInsertPoint());
10093 llvm::OpenMPIRBuilder::LocationDescription OmpLoc(CodeGenIP);
10094 llvm::OpenMPIRBuilder::InsertPointOrErrorTy AfterIP =
10096 OmpLoc, AllocaIP, CodeGenIP, DeviceID, IfCondVal, Info, GenMapInfoCB,
10097 nullptr, BodyCB, DeviceAddrCB, CustomMapperCB, RTLoc);
10098 assert(AfterIP &&
"unexpected error creating target data");
10099 CGF.
Builder.restoreIP(*AfterIP);
10108 assert((isa<OMPTargetEnterDataDirective>(
D) ||
10109 isa<OMPTargetExitDataDirective>(
D) ||
10110 isa<OMPTargetUpdateDirective>(
D)) &&
10111 "Expecting either target enter, exit data, or update directives.");
10114 llvm::Value *MapTypesArray =
nullptr;
10115 llvm::Value *MapNamesArray =
nullptr;
10117 auto &&ThenGen = [
this, &
D,
Device, &InputInfo, &MapTypesArray,
10120 llvm::Value *DeviceID =
nullptr;
10125 DeviceID = CGF.
Builder.getInt64(OMP_DEVICEID_UNDEF);
10129 llvm::Constant *PointerNum =
10136 {RTLoc, DeviceID, PointerNum,
10145 RuntimeFunction RTLFn;
10146 switch (
D.getDirectiveKind()) {
10147 case OMPD_target_enter_data:
10148 RTLFn = HasNowait ? OMPRTL___tgt_target_data_begin_nowait_mapper
10149 : OMPRTL___tgt_target_data_begin_mapper;
10151 case OMPD_target_exit_data:
10152 RTLFn = HasNowait ? OMPRTL___tgt_target_data_end_nowait_mapper
10153 : OMPRTL___tgt_target_data_end_mapper;
10155 case OMPD_target_update:
10156 RTLFn = HasNowait ? OMPRTL___tgt_target_data_update_nowait_mapper
10157 : OMPRTL___tgt_target_data_update_mapper;
10159 case OMPD_parallel:
10161 case OMPD_parallel_for:
10162 case OMPD_parallel_master:
10163 case OMPD_parallel_sections:
10164 case OMPD_for_simd:
10165 case OMPD_parallel_for_simd:
10167 case OMPD_cancellation_point:
10169 case OMPD_threadprivate:
10170 case OMPD_allocate:
10175 case OMPD_sections:
10179 case OMPD_critical:
10180 case OMPD_taskyield:
10182 case OMPD_taskwait:
10183 case OMPD_taskgroup:
10189 case OMPD_target_data:
10190 case OMPD_distribute:
10191 case OMPD_distribute_simd:
10192 case OMPD_distribute_parallel_for:
10193 case OMPD_distribute_parallel_for_simd:
10194 case OMPD_teams_distribute:
10195 case OMPD_teams_distribute_simd:
10196 case OMPD_teams_distribute_parallel_for:
10197 case OMPD_teams_distribute_parallel_for_simd:
10198 case OMPD_declare_simd:
10199 case OMPD_declare_variant:
10200 case OMPD_begin_declare_variant:
10201 case OMPD_end_declare_variant:
10202 case OMPD_declare_target:
10203 case OMPD_end_declare_target:
10204 case OMPD_declare_reduction:
10205 case OMPD_declare_mapper:
10206 case OMPD_taskloop:
10207 case OMPD_taskloop_simd:
10208 case OMPD_master_taskloop:
10209 case OMPD_master_taskloop_simd:
10210 case OMPD_parallel_master_taskloop:
10211 case OMPD_parallel_master_taskloop_simd:
10213 case OMPD_target_simd:
10214 case OMPD_target_teams_distribute:
10215 case OMPD_target_teams_distribute_simd:
10216 case OMPD_target_teams_distribute_parallel_for:
10217 case OMPD_target_teams_distribute_parallel_for_simd:
10218 case OMPD_target_teams:
10219 case OMPD_target_parallel:
10220 case OMPD_target_parallel_for:
10221 case OMPD_target_parallel_for_simd:
10222 case OMPD_requires:
10223 case OMPD_metadirective:
10226 llvm_unreachable(
"Unexpected standalone target data directive.");
10230 OffloadingArgs.push_back(llvm::Constant::getNullValue(CGF.
Int32Ty));
10231 OffloadingArgs.push_back(llvm::Constant::getNullValue(CGF.
VoidPtrTy));
10232 OffloadingArgs.push_back(llvm::Constant::getNullValue(CGF.
Int32Ty));
10233 OffloadingArgs.push_back(llvm::Constant::getNullValue(CGF.
VoidPtrTy));
10240 auto &&TargetThenGen = [
this, &ThenGen, &
D, &InputInfo, &MapTypesArray,
10244 MappableExprsHandler::MapCombinedInfoTy CombinedInfo;
10246 MappableExprsHandler MEHandler(
D, CGF);
10263 MapTypesArray = Info.RTArgs.MapTypesArray;
10264 MapNamesArray = Info.RTArgs.MapNamesArray;
10265 if (RequiresOuterTask)
10291struct ParamAttrTy {
10293 llvm::APSInt StrideOrArg;
10294 llvm::APSInt Alignment;
10295 bool HasVarStride =
false;
10328 unsigned Offset = 0;
10329 if (
const auto *MD = dyn_cast<CXXMethodDecl>(FD)) {
10330 if (ParamAttrs[Offset].Kind ==
Vector)
10331 CDT =
C.getPointerType(
C.getRecordType(MD->
getParent()));
10336 if (ParamAttrs[I + Offset].Kind ==
Vector) {
10348 return C.getTypeSize(CDT);
10356 llvm::raw_svector_ostream Out(Buffer);
10357 for (
const auto &ParamAttr : ParamAttrs) {
10358 switch (ParamAttr.Kind) {
10378 if (ParamAttr.HasVarStride)
10379 Out <<
"s" << ParamAttr.StrideOrArg;
10380 else if (ParamAttr.Kind == Linear || ParamAttr.Kind == LinearRef ||
10381 ParamAttr.Kind == LinearUVal || ParamAttr.Kind == LinearVal) {
10384 if (ParamAttr.StrideOrArg < 0)
10385 Out <<
'n' << -ParamAttr.StrideOrArg;
10386 else if (ParamAttr.StrideOrArg != 1)
10387 Out << ParamAttr.StrideOrArg;
10390 if (!!ParamAttr.Alignment)
10391 Out <<
'a' << ParamAttr.Alignment;
10394 return std::string(Out.str());
10399 const llvm::APSInt &VLENVal,
10401 OMPDeclareSimdDeclAttr::BranchStateTy State) {
10404 unsigned VecRegSize;
10406 ISADataTy ISAData[] = {
10422 case OMPDeclareSimdDeclAttr::BS_Undefined:
10423 Masked.push_back(
'N');
10424 Masked.push_back(
'M');
10426 case OMPDeclareSimdDeclAttr::BS_Notinbranch:
10427 Masked.push_back(
'N');
10429 case OMPDeclareSimdDeclAttr::BS_Inbranch:
10430 Masked.push_back(
'M');
10433 for (
char Mask : Masked) {
10434 for (
const ISADataTy &
Data : ISAData) {
10436 llvm::raw_svector_ostream Out(Buffer);
10437 Out <<
"_ZGV" <<
Data.ISA << Mask;
10440 assert(NumElts &&
"Non-zero simdlen/cdtsize expected");
10441 Out << llvm::APSInt::getUnsigned(
Data.VecRegSize / NumElts);
10446 Out <<
'_' << Fn->getName();
10447 Fn->addFnAttr(Out.str());
10465 if (Kind == ParamKindTy::Uniform)
10468 if (Kind == ParamKindTy::LinearUVal || Kind == ParamKindTy::LinearRef)
10471 if ((Kind == ParamKindTy::Linear || Kind == ParamKindTy::LinearVal) &&
10481 unsigned Size =
C.getTypeSize(QT);
10484 if (Size != 8 && Size != 16 && Size != 32 && Size != 64 && Size != 128)
10508 return C.getTypeSize(PTy);
10511 return C.getTypeSize(QT);
10513 return C.getTypeSize(
C.getUIntPtrType());
10519static std::tuple<unsigned, unsigned, bool>
10525 bool OutputBecomesInput =
false;
10529 Sizes.push_back(
getAArch64LS(RetType, ParamKindTy::Vector,
C));
10531 OutputBecomesInput =
true;
10538 assert(!Sizes.empty() &&
"Unable to determine NDS and WDS.");
10541 assert(llvm::all_of(Sizes,
10542 [](
unsigned Size) {
10543 return Size == 8 || Size == 16 || Size == 32 ||
10544 Size == 64 || Size == 128;
10548 return std::make_tuple(*std::min_element(std::begin(Sizes), std::end(Sizes)),
10549 *std::max_element(std::begin(Sizes), std::end(Sizes)),
10550 OutputBecomesInput);
10556template <
typename T>
10558 char ISA, StringRef ParSeq,
10559 StringRef MangledName,
bool OutputBecomesInput,
10560 llvm::Function *Fn) {
10562 llvm::raw_svector_ostream Out(Buffer);
10563 Out << Prefix << ISA << LMask << VLEN;
10564 if (OutputBecomesInput)
10566 Out << ParSeq <<
"_" << MangledName;
10567 Fn->addFnAttr(Out.str());
10573 StringRef Prefix,
char ISA,
10574 StringRef ParSeq, StringRef MangledName,
10575 bool OutputBecomesInput,
10576 llvm::Function *Fn) {
10580 OutputBecomesInput, Fn);
10582 OutputBecomesInput, Fn);
10586 OutputBecomesInput, Fn);
10588 OutputBecomesInput, Fn);
10592 OutputBecomesInput, Fn);
10594 OutputBecomesInput, Fn);
10599 OutputBecomesInput, Fn);
10602 llvm_unreachable(
"Scalar type is too wide.");
10610 OMPDeclareSimdDeclAttr::BranchStateTy State, StringRef MangledName,
10611 char ISA,
unsigned VecRegSize, llvm::Function *Fn,
SourceLocation SLoc) {
10615 const unsigned NDS = std::get<0>(
Data);
10616 const unsigned WDS = std::get<1>(
Data);
10617 const bool OutputBecomesInput = std::get<2>(
Data);
10621 if (UserVLEN == 1) {
10624 "The clause simdlen(1) has no effect when targeting aarch64.");
10631 if (ISA ==
'n' && UserVLEN && !llvm::isPowerOf2_32(UserVLEN)) {
10634 "power of 2 when targeting Advanced SIMD.");
10641 if (ISA ==
's' && UserVLEN != 0) {
10642 if ((UserVLEN * WDS > 2048) || (UserVLEN * WDS % 128 != 0)) {
10645 "lanes in the architectural constraints "
10646 "for SVE (min is 128-bit, max is "
10647 "2048-bit, by steps of 128-bit)");
10655 StringRef Prefix =
"_ZGV";
10661 OutputBecomesInput, Fn);
10663 assert(ISA ==
'n' &&
"Expected ISA either 's' or 'n'.");
10667 case OMPDeclareSimdDeclAttr::BS_Undefined:
10669 OutputBecomesInput, Fn);
10671 OutputBecomesInput, Fn);
10673 case OMPDeclareSimdDeclAttr::BS_Notinbranch:
10675 OutputBecomesInput, Fn);
10677 case OMPDeclareSimdDeclAttr::BS_Inbranch:
10679 OutputBecomesInput, Fn);
10689 OutputBecomesInput, Fn);
10691 assert(ISA ==
'n' &&
"Expected ISA either 's' or 'n'.");
10696 case OMPDeclareSimdDeclAttr::BS_Undefined:
10698 OutputBecomesInput, Fn);
10700 OutputBecomesInput, Fn);
10702 case OMPDeclareSimdDeclAttr::BS_Notinbranch:
10704 OutputBecomesInput, Fn);
10706 case OMPDeclareSimdDeclAttr::BS_Inbranch:
10708 OutputBecomesInput, Fn);
10716 llvm::Function *Fn) {
10721 llvm::DenseMap<const Decl *, unsigned> ParamPositions;
10722 if (isa<CXXMethodDecl>(FD))
10723 ParamPositions.try_emplace(FD, 0);
10724 unsigned ParamPos = ParamPositions.size();
10726 ParamPositions.try_emplace(
P->getCanonicalDecl(), ParamPos);
10732 for (
const Expr *
E :
Attr->uniforms()) {
10735 if (isa<CXXThisExpr>(
E)) {
10736 Pos = ParamPositions[FD];
10738 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(
E)->getDecl())
10739 ->getCanonicalDecl();
10740 auto It = ParamPositions.find(PVD);
10741 assert(It != ParamPositions.end() &&
"Function parameter not found");
10744 ParamAttrs[Pos].Kind = Uniform;
10747 auto *NI =
Attr->alignments_begin();
10748 for (
const Expr *
E :
Attr->aligneds()) {
10752 if (isa<CXXThisExpr>(
E)) {
10753 Pos = ParamPositions[FD];
10756 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(
E)->getDecl())
10757 ->getCanonicalDecl();
10758 auto It = ParamPositions.find(PVD);
10759 assert(It != ParamPositions.end() &&
"Function parameter not found");
10761 ParmTy = PVD->getType();
10763 ParamAttrs[Pos].Alignment =
10765 ? (*NI)->EvaluateKnownConstInt(
C)
10766 : llvm::APSInt::getUnsigned(
10767 C.toCharUnitsFromBits(
C.getOpenMPDefaultSimdAlign(ParmTy))
10772 auto *SI =
Attr->steps_begin();
10773 auto *MI =
Attr->modifiers_begin();
10774 for (
const Expr *
E :
Attr->linears()) {
10777 bool IsReferenceType =
false;
10780 unsigned PtrRescalingFactor = 1;
10781 if (isa<CXXThisExpr>(
E)) {
10782 Pos = ParamPositions[FD];
10783 auto *
P = cast<PointerType>(
E->
getType());
10788 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(
E)->getDecl())
10789 ->getCanonicalDecl();
10790 auto It = ParamPositions.find(PVD);
10791 assert(It != ParamPositions.end() &&
"Function parameter not found");
10793 if (
auto *
P = dyn_cast<PointerType>(PVD->getType()))
10797 else if (PVD->getType()->isReferenceType()) {
10798 IsReferenceType =
true;
10799 PtrRescalingFactor =
10805 ParamAttrTy &ParamAttr = ParamAttrs[Pos];
10806 if (*MI == OMPC_LINEAR_ref)
10807 ParamAttr.Kind = LinearRef;
10808 else if (*MI == OMPC_LINEAR_uval)
10809 ParamAttr.Kind = LinearUVal;
10810 else if (IsReferenceType)
10811 ParamAttr.Kind = LinearVal;
10813 ParamAttr.Kind = Linear;
10815 ParamAttr.StrideOrArg = llvm::APSInt::getUnsigned(1);
10819 if (
const auto *DRE =
10820 cast<DeclRefExpr>((*SI)->IgnoreParenImpCasts())) {
10821 if (
const auto *StridePVD =
10822 dyn_cast<ParmVarDecl>(DRE->getDecl())) {
10823 ParamAttr.HasVarStride =
true;
10824 auto It = ParamPositions.find(StridePVD->getCanonicalDecl());
10825 assert(It != ParamPositions.end() &&
10826 "Function parameter not found");
10827 ParamAttr.StrideOrArg = llvm::APSInt::getUnsigned(It->second);
10831 ParamAttr.StrideOrArg =
Result.Val.getInt();
10837 if (!ParamAttr.HasVarStride &&
10838 (ParamAttr.Kind == Linear || ParamAttr.Kind == LinearRef))
10839 ParamAttr.StrideOrArg = ParamAttr.StrideOrArg * PtrRescalingFactor;
10843 llvm::APSInt VLENVal;
10845 const Expr *VLENExpr =
Attr->getSimdlen();
10850 OMPDeclareSimdDeclAttr::BranchStateTy State =
Attr->getBranchState();
10853 }
else if (
CGM.
getTriple().getArch() == llvm::Triple::aarch64) {
10854 unsigned VLEN = VLENVal.getExtValue();
10855 StringRef MangledName = Fn->getName();
10858 MangledName,
's', 128, Fn, ExprLoc);
10861 MangledName,
'n', 128, Fn, ExprLoc);
10872 static const int DoacrossFinArgs = 2;
10875 llvm::FunctionCallee RTLFn;
10876 llvm::Value *Args[DoacrossFinArgs];
10879 DoacrossCleanupTy(llvm::FunctionCallee RTLFn,
10882 assert(CallArgs.size() == DoacrossFinArgs);
10883 std::copy(CallArgs.begin(), CallArgs.end(), std::begin(Args));
10900 QualType Int64Ty =
C.getIntTypeForBitwidth(64,
true);
10908 RD =
C.buildImplicitRecord(
"kmp_dim");
10918 llvm::APInt Size(32, NumIterations.size());
10924 enum { LowerFD = 0, UpperFD, StrideFD };
10926 for (
unsigned I = 0,
E = NumIterations.size(); I <
E; ++I) {
10931 DimsLVal, *std::next(RD->
field_begin(), UpperFD));
10933 CGF.
EmitScalarExpr(NumIterations[I]), NumIterations[I]->getType(),
10934 Int64Ty, NumIterations[I]->getExprLoc());
10938 DimsLVal, *std::next(RD->
field_begin(), StrideFD));
10945 llvm::Value *Args[] = {
10948 llvm::ConstantInt::getSigned(
CGM.
Int32Ty, NumIterations.size()),
10953 llvm::FunctionCallee RTLFn =
OMPBuilder.getOrCreateRuntimeFunction(
10956 llvm::Value *FiniArgs[DoacrossCleanupTy::DoacrossFinArgs] = {
10958 llvm::FunctionCallee FiniRTLFn =
OMPBuilder.getOrCreateRuntimeFunction(
10964template <
typename T>
10966 const T *
C, llvm::Value *ULoc,
10967 llvm::Value *ThreadID) {
10970 llvm::APInt Size(32,
C->getNumLoops());
10974 for (
unsigned I = 0,
E =
C->getNumLoops(); I <
E; ++I) {
10975 const Expr *CounterVal =
C->getLoopData(I);
10976 assert(CounterVal);
10983 llvm::Value *Args[] = {
10986 llvm::FunctionCallee RTLFn;
10988 OMPDoacrossKind<T> ODK;
10989 if (ODK.isSource(
C)) {
10991 OMPRTL___kmpc_doacross_post);
10993 assert(ODK.isSink(
C) &&
"Expect sink modifier.");
10995 OMPRTL___kmpc_doacross_wait);
11002 return EmitDoacrossOrdered<OMPDependClause>(
11009 return EmitDoacrossOrdered<OMPDoacrossClause>(
11015 llvm::FunctionCallee Callee,
11017 assert(
Loc.
isValid() &&
"Outlined function call location must be valid.");
11020 if (
auto *Fn = dyn_cast<llvm::Function>(Callee.getCallee())) {
11021 if (Fn->doesNotThrow()) {
11036 if (
const auto *FD = dyn_cast<FunctionDecl>(
D))
11037 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(FD))
11043 const VarDecl *TargetParam)
const {
11050 const Expr *Allocator) {
11051 llvm::Value *AllocVal;
11058 Allocator->getExprLoc());
11061 AllocVal = llvm::Constant::getNullValue(
11071 if (!AllocateAlignment)
11074 return llvm::ConstantInt::get(
CGM.
SizeTy, AllocateAlignment->getQuantity());
11087 auto I = UntiedData.find(VD);
11088 if (I != UntiedData.end()) {
11089 UntiedAddr = I->second.first;
11090 UntiedRealAddr = I->second.second;
11094 if (CVD->
hasAttr<OMPAllocateDeclAttr>()) {
11103 Size = CGF.
Builder.CreateNUWAdd(
11112 const auto *AA = CVD->
getAttr<OMPAllocateDeclAttr>();
11113 const Expr *Allocator = AA->getAllocator();
11117 Args.push_back(ThreadID);
11119 Args.push_back(Alignment);
11120 Args.push_back(Size);
11121 Args.push_back(AllocVal);
11122 llvm::omp::RuntimeFunction FnID =
11123 Alignment ? OMPRTL___kmpc_aligned_alloc : OMPRTL___kmpc_alloc;
11127 llvm::FunctionCallee FiniRTLFn =
OMPBuilder.getOrCreateRuntimeFunction(
11137 llvm::FunctionCallee RTLFn;
11140 const Expr *AllocExpr;
11143 OMPAllocateCleanupTy(llvm::FunctionCallee RTLFn,
11145 const Expr *AllocExpr)
11146 : RTLFn(RTLFn), LocEncoding(LocEncoding), Addr(Addr),
11147 AllocExpr(AllocExpr) {}
11151 llvm::Value *Args[3];
11157 Args[2] = AllocVal;
11165 CGF.
EHStack.pushCleanup<OMPAllocateCleanupTy>(
11167 VDAddr, Allocator);
11168 if (UntiedRealAddr.
isValid())
11171 Region->emitUntiedSwitch(CGF);
11188 assert(CGM.
getLangOpts().OpenMP &&
"Not in OpenMP mode.");
11194 for (
const Stmt *Ref :
C->private_refs()) {
11195 const auto *SimpleRefExpr = cast<Expr>(Ref)->IgnoreParenImpCasts();
11197 if (
const auto *DRE = dyn_cast<DeclRefExpr>(SimpleRefExpr)) {
11198 VD = DRE->getDecl();
11200 const auto *ME = cast<MemberExpr>(SimpleRefExpr);
11201 assert((ME->isImplicitCXXThis() ||
11202 isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts())) &&
11203 "Expected member of current class.");
11204 VD = ME->getMemberDecl();
11220 std::pair<Address, Address>> &LocalVars)
11221 :
CGM(CGF.
CGM), NeedToPush(!LocalVars.empty()) {
11238 return llvm::any_of(
11243void CGOpenMPRuntime::LastprivateConditionalRAII::tryToDisableInnerAnalysis(
11247 llvm::DenseSet<CanonicalDeclPtr<const Decl>> NeedToCheckForLPCs;
11253 const CapturedStmt *CS = S.getCapturedStmt(CaptureRegions.front());
11261 for (
const Expr *Ref :
C->varlist()) {
11262 if (!Ref->getType()->isScalarType())
11264 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
11267 NeedToCheckForLPCs.insert(DRE->getDecl());
11271 for (
const Expr *Ref :
C->varlist()) {
11272 if (!Ref->getType()->isScalarType())
11274 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
11277 NeedToCheckForLPCs.insert(DRE->getDecl());
11281 for (
const Expr *Ref :
C->varlist()) {
11282 if (!Ref->getType()->isScalarType())
11284 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
11287 NeedToCheckForLPCs.insert(DRE->getDecl());
11291 for (
const Expr *Ref :
C->varlist()) {
11292 if (!Ref->getType()->isScalarType())
11294 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
11297 NeedToCheckForLPCs.insert(DRE->getDecl());
11301 for (
const Expr *Ref :
C->varlist()) {
11302 if (!Ref->getType()->isScalarType())
11304 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
11307 NeedToCheckForLPCs.insert(DRE->getDecl());
11310 for (
const Decl *VD : NeedToCheckForLPCs) {
11311 for (
const LastprivateConditionalData &
Data :
11313 if (
Data.DeclToUniqueName.count(VD) > 0) {
11314 if (!
Data.Disabled)
11315 NeedToAddForLPCsAsDisabled.insert(VD);
11322CGOpenMPRuntime::LastprivateConditionalRAII::LastprivateConditionalRAII(
11325 Action((
CGM.getLangOpts().OpenMP >= 50 &&
11328 return C->getKind() ==
11329 OMPC_LASTPRIVATE_conditional;
11331 ? ActionToDo::PushAsLastprivateConditional
11332 : ActionToDo::DoNotPush) {
11334 if (
CGM.
getLangOpts().OpenMP < 50 || Action == ActionToDo::DoNotPush)
11336 assert(Action == ActionToDo::PushAsLastprivateConditional &&
11337 "Expected a push action.");
11341 if (
C->getKind() != OMPC_LASTPRIVATE_conditional)
11344 for (
const Expr *Ref :
C->varlist()) {
11345 Data.DeclToUniqueName.insert(std::make_pair(
11346 cast<DeclRefExpr>(Ref->IgnoreParenImpCasts())->getDecl(),
11350 Data.IVLVal = IVLVal;
11354CGOpenMPRuntime::LastprivateConditionalRAII::LastprivateConditionalRAII(
11356 :
CGM(CGF.
CGM), Action(ActionToDo::DoNotPush) {
11357 assert(CGM.
getLangOpts().OpenMP &&
"Not in OpenMP mode.");
11360 llvm::DenseSet<CanonicalDeclPtr<const Decl>> NeedToAddForLPCsAsDisabled;
11361 tryToDisableInnerAnalysis(S, NeedToAddForLPCsAsDisabled);
11362 if (!NeedToAddForLPCsAsDisabled.empty()) {
11363 Action = ActionToDo::DisableLastprivateConditional;
11364 LastprivateConditionalData &
Data =
11366 for (
const Decl *VD : NeedToAddForLPCsAsDisabled)
11369 Data.Disabled =
true;
11382 if (Action == ActionToDo::DisableLastprivateConditional) {
11384 "Expected list of disabled private vars.");
11387 if (Action == ActionToDo::PushAsLastprivateConditional) {
11390 "Expected list of lastprivate conditional vars.");
11403 auto VI = I->getSecond().find(VD);
11404 if (VI == I->getSecond().end()) {
11405 RecordDecl *RD =
C.buildImplicitRecord(
"lasprivate.conditional");
11410 NewType =
C.getRecordType(RD);
11413 I->getSecond().try_emplace(VD, NewType, VDField, FiredField, BaseLVal);
11415 NewType = std::get<0>(VI->getSecond());
11416 VDField = std::get<1>(VI->getSecond());
11417 FiredField = std::get<2>(VI->getSecond());
11418 BaseLVal = std::get<3>(VI->getSecond());
11430class LastprivateConditionalRefChecker final
11433 const Expr *FoundE =
nullptr;
11434 const Decl *FoundD =
nullptr;
11435 StringRef UniqueDeclName;
11437 llvm::Function *FoundFn =
nullptr;
11443 llvm::reverse(LPM)) {
11444 auto It =
D.DeclToUniqueName.find(
E->getDecl());
11445 if (It ==
D.DeclToUniqueName.end())
11450 FoundD =
E->getDecl()->getCanonicalDecl();
11451 UniqueDeclName = It->second;
11456 return FoundE ==
E;
11459 if (!CodeGenFunction::IsWrappedCXXThis(
E->getBase()))
11462 llvm::reverse(LPM)) {
11463 auto It =
D.DeclToUniqueName.find(
E->getMemberDecl());
11464 if (It ==
D.DeclToUniqueName.end())
11469 FoundD =
E->getMemberDecl()->getCanonicalDecl();
11470 UniqueDeclName = It->second;
11475 return FoundE ==
E;
11477 bool VisitStmt(
const Stmt *S) {
11478 for (
const Stmt *Child : S->children()) {
11481 if (
const auto *
E = dyn_cast<Expr>(Child))
11489 explicit LastprivateConditionalRefChecker(
11492 std::tuple<const Expr *, const Decl *, StringRef, LValue, llvm::Function *>
11493 getFoundData()
const {
11494 return std::make_tuple(FoundE, FoundD, UniqueDeclName, IVLVal, FoundFn);
11501 StringRef UniqueDeclName,
11507 llvm::Constant *LastIV =
OMPBuilder.getOrCreateInternalVariable(
11508 LLIVTy,
getName({UniqueDeclName,
"iv"}));
11509 cast<llvm::GlobalVariable>(LastIV)->setAlignment(
11516 llvm::GlobalVariable *
Last =
OMPBuilder.getOrCreateInternalVariable(
11518 cast<llvm::GlobalVariable>(
Last)->setAlignment(
11532 auto &&CodeGen = [&LastIVLVal, &IVLVal, IVVal, &LVal, &LastLVal,
11538 llvm::Value *CmpRes;
11540 CmpRes = CGF.
Builder.CreateICmpSLE(LastIVVal, IVVal);
11543 "Loop iteration variable must be integer.");
11544 CmpRes = CGF.
Builder.CreateICmpULE(LastIVVal, IVVal);
11548 CGF.
Builder.CreateCondBr(CmpRes, ThenBB, ExitBB);
11569 "Aggregates are not supported in lastprivate conditional.");
11592 if (!Checker.Visit(LHS))
11594 const Expr *FoundE;
11595 const Decl *FoundD;
11596 StringRef UniqueDeclName;
11598 llvm::Function *FoundFn;
11599 std::tie(FoundE, FoundD, UniqueDeclName, IVLVal, FoundFn) =
11600 Checker.getFoundData();
11601 if (FoundFn != CGF.
CurFn) {
11606 "Lastprivate conditional is not found in outer region.");
11607 QualType StructTy = std::get<0>(It->getSecond());
11608 const FieldDecl* FiredDecl = std::get<2>(It->getSecond());
11619 FiredLVal, llvm::AtomicOrdering::Unordered,
11637 auto It = llvm::find_if(
11639 if (It ==
Range.end() || It->Fn != CGF.
CurFn)
11643 "Lastprivates must be registered already.");
11646 const CapturedStmt *CS =
D.getCapturedStmt(CaptureRegions.back());
11647 for (
const auto &Pair : It->DeclToUniqueName) {
11648 const auto *VD = cast<VarDecl>(Pair.first->getCanonicalDecl());
11651 auto I = LPCI->getSecond().find(Pair.first);
11652 assert(I != LPCI->getSecond().end() &&
11653 "Lastprivate must be rehistered already.");
11655 LValue BaseLVal = std::get<3>(I->getSecond());
11659 llvm::Value *Cmp = CGF.
Builder.CreateIsNotNull(Res);
11663 CGF.
Builder.CreateCondBr(Cmp, ThenBB, DoneBB);
11688 "Unknown lastprivate conditional variable.");
11689 StringRef UniqueName = It->second;
11690 llvm::GlobalVariable *GV =
CGM.
getModule().getNamedGlobal(UniqueName);
11704 llvm_unreachable(
"Not supported in SIMD-only mode");
11711 llvm_unreachable(
"Not supported in SIMD-only mode");
11718 bool Tied,
unsigned &NumberOfParts) {
11719 llvm_unreachable(
"Not supported in SIMD-only mode");
11724 llvm::Function *OutlinedFn,
11726 const Expr *IfCond,
11727 llvm::Value *NumThreads) {
11728 llvm_unreachable(
"Not supported in SIMD-only mode");
11734 const Expr *Hint) {
11735 llvm_unreachable(
"Not supported in SIMD-only mode");
11741 llvm_unreachable(
"Not supported in SIMD-only mode");
11747 const Expr *Filter) {
11748 llvm_unreachable(
"Not supported in SIMD-only mode");
11753 llvm_unreachable(
"Not supported in SIMD-only mode");
11759 llvm_unreachable(
"Not supported in SIMD-only mode");
11767 llvm_unreachable(
"Not supported in SIMD-only mode");
11774 llvm_unreachable(
"Not supported in SIMD-only mode");
11781 bool ForceSimpleCall) {
11782 llvm_unreachable(
"Not supported in SIMD-only mode");
11789 llvm_unreachable(
"Not supported in SIMD-only mode");
11794 llvm_unreachable(
"Not supported in SIMD-only mode");
11800 llvm_unreachable(
"Not supported in SIMD-only mode");
11806 llvm_unreachable(
"Not supported in SIMD-only mode");
11813 llvm_unreachable(
"Not supported in SIMD-only mode");
11819 llvm_unreachable(
"Not supported in SIMD-only mode");
11824 unsigned IVSize,
bool IVSigned,
11827 llvm_unreachable(
"Not supported in SIMD-only mode");
11831 llvm::Value *NumThreads,
11833 llvm_unreachable(
"Not supported in SIMD-only mode");
11837 ProcBindKind ProcBind,
11839 llvm_unreachable(
"Not supported in SIMD-only mode");
11846 llvm_unreachable(
"Not supported in SIMD-only mode");
11852 llvm_unreachable(
"Not supported in SIMD-only mode");
11857 llvm_unreachable(
"Not supported in SIMD-only mode");
11863 llvm::AtomicOrdering AO) {
11864 llvm_unreachable(
"Not supported in SIMD-only mode");
11869 llvm::Function *TaskFunction,
11871 const Expr *IfCond,
11873 llvm_unreachable(
"Not supported in SIMD-only mode");
11880 llvm_unreachable(
"Not supported in SIMD-only mode");
11887 assert(Options.SimpleReduction &&
"Only simple reduction is expected.");
11889 ReductionOps, Options);
11895 llvm_unreachable(
"Not supported in SIMD-only mode");
11900 bool IsWorksharingReduction) {
11901 llvm_unreachable(
"Not supported in SIMD-only mode");
11908 llvm_unreachable(
"Not supported in SIMD-only mode");
11913 llvm::Value *ReductionsPtr,
11915 llvm_unreachable(
"Not supported in SIMD-only mode");
11921 llvm_unreachable(
"Not supported in SIMD-only mode");
11927 llvm_unreachable(
"Not supported in SIMD-only mode");
11933 llvm_unreachable(
"Not supported in SIMD-only mode");
11938 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
11940 llvm_unreachable(
"Not supported in SIMD-only mode");
11945 llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID,
const Expr *IfCond,
11946 llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier>
Device,
11950 llvm_unreachable(
"Not supported in SIMD-only mode");
11954 llvm_unreachable(
"Not supported in SIMD-only mode");
11958 llvm_unreachable(
"Not supported in SIMD-only mode");
11968 llvm::Function *OutlinedFn,
11970 llvm_unreachable(
"Not supported in SIMD-only mode");
11974 const Expr *NumTeams,
11975 const Expr *ThreadLimit,
11977 llvm_unreachable(
"Not supported in SIMD-only mode");
11984 llvm_unreachable(
"Not supported in SIMD-only mode");
11990 llvm_unreachable(
"Not supported in SIMD-only mode");
11996 llvm_unreachable(
"Not supported in SIMD-only mode");
12001 llvm_unreachable(
"Not supported in SIMD-only mode");
12006 llvm_unreachable(
"Not supported in SIMD-only mode");
12011 const VarDecl *NativeParam)
const {
12012 llvm_unreachable(
"Not supported in SIMD-only mode");
12018 const VarDecl *TargetParam)
const {
12019 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 std::string generateUniqueName(CodeGenModule &CGM, StringRef Prefix, const Expr *Ref)
Generates unique name for artificial threadprivate variables.
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 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::@1718::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,...
CanQualType getSizeType() const
Return the unique type for "size_t" (C99 7.17), defined in <stddef.h>.
CharUnits getDeclAlign(const Decl *D, bool ForAlignof=false) const
Return a conservative estimate of the alignment of the specified decl D.
const ArrayType * getAsArrayType(QualType T) const
Type Query functions.
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
const VariableArrayType * getAsVariableArrayType(QualType T) const
const TargetInfo & getTargetInfo() const
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::FunctionType * Kmpc_MicroTy
The type for a microtask which gets passed to __kmpc_fork_call().
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 emitTargetDataStandAloneCall(CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, const Expr *Device)
Emit the data mapping/movement code associated with the directive D that should be of the form 'targe...
virtual void emitNumThreadsClause(CodeGenFunction &CGF, llvm::Value *NumThreads, SourceLocation Loc)
Emits call to void __kmpc_push_num_threads(ident_t *loc, kmp_int32 global_tid, kmp_int32 num_threads)...
QualType SavedKmpTaskloopTQTy
Saved kmp_task_t for taskloop-based directive.
virtual void emitSingleRegion(CodeGenFunction &CGF, const RegionCodeGenTy &SingleOpGen, SourceLocation Loc, ArrayRef< const Expr * > CopyprivateVars, ArrayRef< const Expr * > DestExprs, ArrayRef< const Expr * > SrcExprs, ArrayRef< const Expr * > AssignmentOps)
Emits a single region.
virtual bool emitTargetGlobal(GlobalDecl GD)
Emit the global GD if it is meaningful for the target.
void setLocThreadIdInsertPt(CodeGenFunction &CGF, bool AtCurrentPoint=false)
std::string getOutlinedHelperName(StringRef Name) const
Get the function name of an outlined region.
bool HasEmittedDeclareTargetRegion
Flag for keeping track of weather a device routine has been emitted.
llvm::Constant * getOrCreateThreadPrivateCache(const VarDecl *VD)
If the specified mangled name is not in the module, create and return threadprivate cache object.
virtual Address getTaskReductionItem(CodeGenFunction &CGF, SourceLocation Loc, llvm::Value *ReductionsPtr, LValue SharedLVal)
Get the address of void * type of the privatue copy of the reduction item specified by the SharedLVal...
virtual void emitForDispatchDeinit(CodeGenFunction &CGF, SourceLocation Loc)
This is used for non static scheduled types and when the ordered clause is present on the loop constr...
void emitCall(CodeGenFunction &CGF, SourceLocation Loc, llvm::FunctionCallee Callee, ArrayRef< llvm::Value * > Args={}) const
Emits Callee function call with arguments Args with location Loc.
virtual void getDefaultScheduleAndChunk(CodeGenFunction &CGF, const OMPLoopDirective &S, OpenMPScheduleClauseKind &ScheduleKind, const Expr *&ChunkExpr) const
Choose default schedule type and chunk value for the schedule clause.
virtual std::pair< llvm::Function *, llvm::Function * > getUserDefinedReduction(const OMPDeclareReductionDecl *D)
Get combiner/initializer for the specified user-defined reduction, if any.
virtual bool isGPU() const
Returns true if the current target is a GPU.
static const Stmt * getSingleCompoundChild(ASTContext &Ctx, const Stmt *Body)
Checks if the Body is the CompoundStmt and returns its child statement iff there is only one that is ...
virtual void emitDeclareTargetFunction(const FunctionDecl *FD, llvm::GlobalValue *GV)
Emit code for handling declare target functions in the runtime.
llvm::Type * getKmpc_MicroPointerTy()
Returns pointer to kmpc_micro type.
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.
void computeMinAndMaxThreadsAndTeams(const OMPExecutableDirective &D, CodeGenFunction &CGF, int32_t &MinThreadsVal, int32_t &MaxThreadsVal, int32_t &MinTeamsVal, int32_t &MaxTeamsVal)
Helper to determine the min/max number of threads/teams for D.
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.
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.
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
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...
bool isNontemporalDecl(const ValueDecl *VD) const
Checks if the VD variable is marked as nontemporal declaration in current context.
virtual llvm::Function * emitParallelOutlinedFunction(CodeGenFunction &CGF, const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen)
Emits outlined function for the specified OpenMP parallel directive D.
const Expr * getNumThreadsExprForTargetDirective(CodeGenFunction &CGF, const OMPExecutableDirective &D, int32_t &UpperBound, bool UpperBoundOnly, llvm::Value **CondExpr=nullptr, const Expr **ThreadLimitExpr=nullptr)
Check for a number of threads upper bound constant value (stored in UpperBound), or expression (retur...
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.
virtual void emitParallelCall(CodeGenFunction &CGF, SourceLocation Loc, llvm::Function *OutlinedFn, ArrayRef< llvm::Value * > CapturedVars, const Expr *IfCond, llvm::Value *NumThreads)
Emits code for parallel or serial call of the OutlinedFn with variables captured in a record which ad...
void emitKmpRoutineEntryT(QualType KmpInt32Ty)
Build type kmp_routine_entry_t (if not built yet).
virtual bool isStaticChunked(OpenMPScheduleClauseKind ScheduleKind, bool Chunked) const
Check if the specified ScheduleKind is static chunked.
virtual void emitTargetCall(CodeGenFunction &CGF, const OMPExecutableDirective &D, llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID, const Expr *IfCond, llvm::PointerIntPair< const Expr *, 2, OpenMPDeviceClauseModifier > Device, llvm::function_ref< llvm::Value *(CodeGenFunction &CGF, const OMPLoopDirective &D)> SizeEmitter)
Emit the target offloading code associated with D.
virtual bool hasAllocateAttributeForGlobalVar(const VarDecl *VD, LangAS &AS)
Checks if the variable has associated OMPAllocateDeclAttr attribute with the predefined allocator and...
llvm::AtomicOrdering RequiresAtomicOrdering
Atomic ordering from the omp requires directive.
virtual void emitReduction(CodeGenFunction &CGF, SourceLocation Loc, ArrayRef< const Expr * > Privates, ArrayRef< const Expr * > LHSExprs, ArrayRef< const Expr * > RHSExprs, ArrayRef< const Expr * > ReductionOps, ReductionOptionsTy Options)
Emit a code for reduction clause.
std::pair< llvm::Value *, Address > emitDependClause(CodeGenFunction &CGF, ArrayRef< OMPTaskDataTy::DependData > Dependencies, SourceLocation Loc)
Emits list of dependecies based on the provided data (array of dependence/expression pairs).
llvm::StringMap< llvm::WeakTrackingVH > EmittedNonTargetVariables
List of the global variables with their addresses that should not be emitted for the target.
virtual bool isDynamic(OpenMPScheduleClauseKind ScheduleKind) const
Check if the specified ScheduleKind is dynamic.
Address emitLastprivateConditionalInit(CodeGenFunction &CGF, const VarDecl *VD)
Create specialized alloca to handle lastprivate conditionals.
virtual void emitOrderedRegion(CodeGenFunction &CGF, const RegionCodeGenTy &OrderedOpGen, SourceLocation Loc, bool IsThreads)
Emit an ordered region.
virtual Address getAddressOfLocalVariable(CodeGenFunction &CGF, const VarDecl *VD)
Gets the OpenMP-specific address of the local variable.
virtual void emitTaskReductionFini(CodeGenFunction &CGF, SourceLocation Loc, bool IsWorksharingReduction)
Emits the following code for reduction clause with task modifier:
virtual void emitMaskedRegion(CodeGenFunction &CGF, const RegionCodeGenTy &MaskedOpGen, SourceLocation Loc, const Expr *Filter=nullptr)
Emits a masked region.
QualType KmpDependInfoTy
Type typedef struct kmp_depend_info { kmp_intptr_t base_addr; size_t len; struct { bool in:1; bool ou...
llvm::Function * emitReductionFunction(StringRef ReducerName, SourceLocation Loc, llvm::Type *ArgsElemType, ArrayRef< const Expr * > Privates, ArrayRef< const Expr * > LHSExprs, ArrayRef< const Expr * > RHSExprs, ArrayRef< const Expr * > ReductionOps)
Emits reduction function.
virtual void emitForDispatchInit(CodeGenFunction &CGF, SourceLocation Loc, const OpenMPScheduleTy &ScheduleKind, unsigned IVSize, bool IVSigned, bool Ordered, const DispatchRTInput &DispatchValues)
Call the appropriate runtime routine to initialize it before start of loop.
Address getTaskReductionItem(CodeGenFunction &CGF, SourceLocation Loc, llvm::Value *ReductionsPtr, LValue SharedLVal) override
Get the address of void * type of the privatue copy of the reduction item specified by the SharedLVal...
void emitCriticalRegion(CodeGenFunction &CGF, StringRef CriticalName, const RegionCodeGenTy &CriticalOpGen, SourceLocation Loc, const Expr *Hint=nullptr) override
Emits a critical region.
void emitDistributeStaticInit(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDistScheduleClauseKind SchedKind, const StaticRTInput &Values) override
void emitForStaticInit(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind DKind, const OpenMPScheduleTy &ScheduleKind, const StaticRTInput &Values) override
Call the appropriate runtime routine to initialize it before start of loop.
bool emitTargetGlobalVariable(GlobalDecl GD) override
Emit the global variable if it is a valid device global variable.
llvm::Value * emitForNext(CodeGenFunction &CGF, SourceLocation Loc, unsigned IVSize, bool IVSigned, Address IL, Address LB, Address UB, Address ST) override
Call __kmpc_dispatch_next( ident_t *loc, kmp_int32 tid, kmp_int32 *p_lastiter, kmp_int[32|64] *p_lowe...
llvm::Function * emitThreadPrivateVarDefinition(const VarDecl *VD, Address VDAddr, SourceLocation Loc, bool PerformInit, CodeGenFunction *CGF=nullptr) override
Emit a code for initialization of threadprivate variable.
void emitTargetDataStandAloneCall(CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, const Expr *Device) override
Emit the data mapping/movement code associated with the directive D that should be of the form 'targe...
llvm::Function * emitTeamsOutlinedFunction(CodeGenFunction &CGF, const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) override
Emits outlined function for the specified OpenMP teams directive D.
void 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 emitParallelCall(CodeGenFunction &CGF, SourceLocation Loc, llvm::Function *OutlinedFn, ArrayRef< llvm::Value * > CapturedVars, const Expr *IfCond, llvm::Value *NumThreads) override
Emits code for parallel or serial call of the OutlinedFn with variables captured in a record which ad...
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 emitNumThreadsClause(CodeGenFunction &CGF, llvm::Value *NumThreads, SourceLocation Loc) override
Emits call to void __kmpc_push_num_threads(ident_t *loc, kmp_int32 global_tid, kmp_int32 num_threads)...
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.
virtual void EmitBody(CodeGenFunction &CGF, const Stmt *S)
Emit the captured statement body.
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...
void FinishFunction(SourceLocation EndLoc=SourceLocation())
FinishFunction - Complete IR generation of the current function.
void EmitNullInitialization(Address DestPtr, QualType Ty)
EmitNullInitialization - Generate code to set a value of the given type to null, If the type contains...
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...
static TypeEvaluationKind getEvaluationKind(QualType T)
getEvaluationKind - Return the TypeEvaluationKind of QualType T.
void EmitBranchOnBoolExpr(const Expr *Cond, llvm::BasicBlock *TrueBlock, llvm::BasicBlock *FalseBlock, uint64_t TrueCount, Stmt::Likelihood LH=Stmt::LH_None, const Expr *ConditionalOp=nullptr)
EmitBranchOnBoolExpr - Emit a branch on a boolean condition (e.g.
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...
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.
void EmitStoreThroughLValue(RValue Src, LValue Dst, bool isInit=false)
EmitStoreThroughLValue - Store the specified rvalue into the specified lvalue, where both are guarant...
static void EmitOMPTargetTeamsDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsDirective &S)
Emit device code for the target teams directive.
FieldDecl * LambdaThisCaptureField
CGCapturedStmtInfo * CapturedStmtInfo
static void EmitOMPTargetTeamsDistributeDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsDistributeDirective &S)
Emit device code for the target teams distribute directive.
Address EmitLoadOfPointer(Address Ptr, const PointerType *PtrTy, LValueBaseInfo *BaseInfo=nullptr, TBAAAccessInfo *TBAAInfo=nullptr)
Load a pointer with type PtrTy stored at address Ptr.
RawAddress CreateDefaultAlignTempAlloca(llvm::Type *Ty, const Twine &Name="tmp")
CreateDefaultAlignedTempAlloca - This creates an alloca with the default ABI alignment of the given L...
static void EmitOMPTargetParallelForSimdDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetParallelForSimdDirective &S)
Emit device code for the target parallel for simd directive.
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...
VlaSizePair getVLASize(const VariableArrayType *vla)
Returns an LLVM value that corresponds to the size, in non-variably-sized elements,...
JumpDest getOMPCancelDestination(OpenMPDirectiveKind Kind)
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 EmitOMPTargetDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetDirective &S)
Emit device code for the target directive.
void EmitVariablyModifiedType(QualType Ty)
EmitVLASize - Capture all the sizes for the VLA expressions in the given variably-modified type and s...
llvm::BasicBlock * createBasicBlock(const Twine &name="", llvm::Function *parent=nullptr, llvm::BasicBlock *before=nullptr)
createBasicBlock - Create an LLVM basic block.
const LangOptions & getLangOpts() const
static void EmitOMPTargetSimdDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetSimdDirective &S)
Emit device code for the target simd directive.
LValue EmitLValueForFieldInitialization(LValue Base, const FieldDecl *Field)
EmitLValueForFieldInitialization - Like EmitLValueForField, except that if the Field is a reference,...
void EmitBlock(llvm::BasicBlock *BB, bool IsFinished=false)
EmitBlock - Emit the given block.
const CodeGen::CGBlockInfo * BlockInfo
Address EmitLoadOfReference(LValue RefLVal, LValueBaseInfo *PointeeBaseInfo=nullptr, TBAAAccessInfo *PointeeTBAAInfo=nullptr)
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...
RValue EmitLoadOfLValue(LValue V, SourceLocation Loc)
EmitLoadOfLValue - Given an expression that represents a value lvalue, this method emits the address ...
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...
void EmitIgnoredExpr(const Expr *E)
EmitIgnoredExpr - Emit an expression in a context which ignores the result.
llvm::Type * ConvertTypeForMem(QualType T)
const Decl * CurCodeDecl
CurCodeDecl - This is the inner-most code context, which includes blocks.
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.
void GenerateOpenMPCapturedVars(const CapturedStmt &S, SmallVectorImpl< llvm::Value * > &CapturedVars)
JumpDest ReturnBlock
ReturnBlock - Unified return block.
static void EmitOMPTargetTeamsGenericLoopDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsGenericLoopDirective &S)
Emit device code for the target teams loop directive.
LValue EmitLValueForField(LValue Base, const FieldDecl *Field)
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...
Destroyer * getDestroyer(QualType::DestructionKind destructionKind)
static void EmitOMPTargetTeamsDistributeParallelForDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsDistributeParallelForDirective &S)
llvm::Value * getTypeSize(QualType Ty)
Returns calculated size of the specified type.
void emitDestroy(Address addr, QualType type, Destroyer *destroyer, bool useEHCleanupForArray)
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...
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.
ComplexPairTy EmitLoadOfComplex(LValue src, SourceLocation loc)
EmitLoadOfComplex - Load a complex number from the specified l-value.
bool HaveInsertPoint() const
HaveInsertPoint - True if an insertion point is defined.
bool isTrivialInitializer(const Expr *Init)
Determine whether the given initializer is trivial in the sense that it requires no code to be genera...
void EmitBranch(llvm::BasicBlock *Block)
EmitBranch - Emit a branch to the specified basic block from the current insert block,...
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.
void EmitAggregateCopy(LValue Dest, LValue Src, QualType EltTy, AggValueSlot::Overlap_t MayOverlap, bool isVolatile=false)
EmitAggregateCopy - Emit an aggregate copy.
LValue MakeNaturalAlignRawAddrLValue(llvm::Value *V, QualType T)
void EmitOMPTargetTaskBasedDirective(const OMPExecutableDirective &S, const RegionCodeGenTy &BodyGen, OMPTargetDataInfo &InputInfo)
static void EmitOMPTargetParallelForDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetParallelForDirective &S)
Emit device code for the target parallel for directive.
void EmitVarDecl(const VarDecl &D)
EmitVarDecl - Emit a local variable declaration.
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...
const Decl * CurFuncDecl
CurFuncDecl - Holds the Decl for the current outermost non-closure context.
LValue EmitLoadOfPointerLValue(Address Ptr, const PointerType *PtrTy)
static void EmitOMPTargetTeamsDistributeSimdDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsDistributeSimdDirective &S)
Emit device code for the target teams distribute simd directive.
void EmitBranchThroughCleanup(JumpDest Dest)
EmitBranchThroughCleanup - Emit a branch from the current insert block through the normal cleanup han...
AutoVarEmission EmitAutoVarAlloca(const VarDecl &var)
void pushDestroy(QualType::DestructionKind dtorKind, Address addr, QualType type)
bool ConstantFoldsToSimpleInteger(const Expr *Cond, bool &Result, bool AllowLabels=false)
ConstantFoldsToSimpleInteger - If the specified expression does not fold to a constant,...
void EmitAutoVarCleanups(const AutoVarEmission &emission)
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="")
CodeGenTypes & getTypes() const
LValue EmitArraySectionExpr(const ArraySectionExpr *E, bool IsLowerBound=true)
static void EmitOMPTargetTeamsDistributeParallelForSimdDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsDistributeParallelForSimdDirective &S)
Emit device code for the target teams distribute parallel for simd directive.
LValue EmitStringLiteralLValue(const StringLiteral *E)
llvm::Value * EvaluateExprAsBool(const Expr *E)
EvaluateExprAsBool - Perform the usual unary conversions on the specified expression and compare the ...
Address LoadCXXThisAddress()
LValue EmitOMPSharedLValue(const Expr *E)
Emits the lvalue for the expression with possibly captured variable.
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...
llvm::Function * GenerateOpenMPCapturedStmtFunction(const CapturedStmt &S, SourceLocation Loc)
LValue MakeAddrLValue(Address Addr, QualType T, AlignmentSource Source=AlignmentSource::Type)
void EmitStoreOfComplex(ComplexPairTy V, LValue dest, bool isInit)
EmitStoreOfComplex - Store a complex number into the specified l-value.
static void EmitOMPTargetParallelGenericLoopDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetParallelGenericLoopDirective &S)
Emit device code for the target parallel loop directive.
LValue EmitLoadOfReferenceLValue(LValue RefLVal)
Address GetAddrOfLocalVar(const VarDecl *VD)
GetAddrOfLocalVar - Return the address of a local variable.
void EmitAtomicStore(RValue rvalue, LValue lvalue, bool isInit)
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...
std::pair< llvm::Value *, llvm::Value * > ComplexPairTy
Address ReturnValue
ReturnValue - The temporary alloca to hold the return value.
static void EmitOMPTargetParallelDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetParallelDirective &S)
llvm::Value * EmitScalarExpr(const Expr *E, bool IgnoreResultAssign=false)
EmitScalarExpr - Emit the computation of the specified expression of LLVM scalar type,...
void incrementProfileCounter(const Stmt *S, llvm::Value *StepV=nullptr)
Increment the profiler's counter for the given statement by StepV.
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...
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 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.
@ 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...
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 isIntegerConstantExpr(const ASTContext &Ctx, SourceLocation *Loc=nullptr) const
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...
std::optional< llvm::APSInt > getIntegerConstantExpr(const ASTContext &Ctx, SourceLocation *Loc=nullptr) const
isIntegerConstantExpr - Return the value if this expression is a valid integer constant expression.
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.
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.
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 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 '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
RecordDecl * getDecl() 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
A trivial tuple used to represent a source range.
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.
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
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,...
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
QualType getCanonicalTypeInternal() const
const RecordType * getAsStructureType() 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
TagDecl * getAsTagDecl() const
Retrieves the TagDecl that this type refers to, either because the type is a TagType or because it is...
RecordDecl * getAsRecordDecl() const
Retrieves the RecordDecl this type refers to.
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.
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.
@ 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.
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.
@ 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.